diff options
Diffstat (limited to 'source/blender/draw')
236 files changed, 73805 insertions, 0 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt new file mode 100644 index 00000000000..96dd9356109 --- /dev/null +++ b/source/blender/draw/CMakeLists.txt @@ -0,0 +1,303 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2016, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Blender Institute +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + intern + modes + + ../blenfont + ../blenkernel + ../blenlib + ../blentranslation + ../bmesh + ../depsgraph + ../editors/include + ../editors/space_view3d + ../gpu + ../imbuf + ../makesdna + ../makesrna + ../render/extern/include + ../render/intern/include + ../windowmanager + + ../../../intern/glew-mx + ../../../intern/guardedalloc +) + +set(INC_SYS + ${GLEW_INCLUDE_PATH} +) + +set(SRC + intern/draw_armature.c + intern/draw_cache.c + intern/draw_cache_impl_curve.c + intern/draw_cache_impl_displist.c + intern/draw_cache_impl_lattice.c + intern/draw_cache_impl_mesh.c + intern/draw_cache_impl_metaball.c + intern/draw_cache_impl_particles.c + intern/draw_common.c + intern/draw_debug.c + intern/draw_hair.c + intern/draw_instance_data.c + intern/draw_manager.c + intern/draw_manager_data.c + intern/draw_manager_exec.c + intern/draw_manager_shader.c + intern/draw_manager_text.c + intern/draw_manager_texture.c + intern/draw_manager_profiling.c + intern/draw_view.c + modes/edit_armature_mode.c + modes/edit_curve_mode.c + modes/edit_lattice_mode.c + modes/edit_mesh_mode.c + modes/edit_mesh_mode_text.c + modes/edit_metaball_mode.c + modes/edit_surface_mode.c + modes/edit_text_mode.c + modes/object_mode.c + modes/overlay_mode.c + modes/paint_texture_mode.c + modes/paint_vertex_mode.c + modes/paint_weight_mode.c + modes/particle_mode.c + modes/pose_mode.c + modes/sculpt_mode.c + engines/basic/basic_engine.c + engines/clay/clay_engine.c + engines/eevee/eevee_bloom.c + engines/eevee/eevee_data.c + engines/eevee/eevee_depth_of_field.c + engines/eevee/eevee_effects.c + engines/eevee/eevee_engine.c + engines/eevee/eevee_lightprobes.c + engines/eevee/eevee_lights.c + engines/eevee/eevee_lookdev.c + engines/eevee/eevee_materials.c + engines/eevee/eevee_mist.c + engines/eevee/eevee_motion_blur.c + engines/eevee/eevee_occlusion.c + engines/eevee/eevee_render.c + engines/eevee/eevee_screen_raytrace.c + engines/eevee/eevee_subsurface.c + engines/eevee/eevee_temporal_sampling.c + engines/eevee/eevee_volumes.c + engines/workbench/workbench_data.c + engines/workbench/workbench_engine.c + engines/workbench/workbench_deferred.c + engines/workbench/workbench_forward.c + engines/workbench/workbench_materials.c + engines/workbench/workbench_studiolight.c + engines/workbench/solid_mode.c + engines/workbench/transparent_mode.c + engines/external/external_engine.c + + DRW_engine.h + intern/DRW_render.h + intern/draw_cache.h + intern/draw_cache_impl.h + intern/draw_common.h + intern/draw_debug.h + intern/draw_hair_private.h + intern/draw_instance_data.h + intern/draw_manager.h + intern/draw_manager_text.h + intern/draw_manager_profiling.h + intern/draw_view.h + modes/draw_mode_engines.h + modes/edit_mesh_mode_intern.h + engines/basic/basic_engine.h + engines/clay/clay_engine.h + engines/eevee/eevee_engine.h + engines/eevee/eevee_lut.h + engines/eevee/eevee_private.h + engines/external/external_engine.h +) + +if(WITH_CLAY_ENGINE) + add_definitions(-DWITH_CLAY_ENGINE) +endif() + +data_to_c_simple(engines/clay/shaders/clay_frag.glsl SRC) +data_to_c_simple(engines/clay/shaders/clay_fxaa.glsl SRC) +data_to_c_simple(engines/clay/shaders/clay_copy.glsl SRC) +data_to_c_simple(engines/clay/shaders/clay_prepass_frag.glsl SRC) +data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC) +data_to_c_simple(engines/clay/shaders/clay_particle_vert.glsl SRC) +data_to_c_simple(engines/clay/shaders/clay_particle_strand_frag.glsl SRC) +data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC) +data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC) + +data_to_c_simple(engines/eevee/shaders/ambient_occlusion_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/background_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/concentric_samples_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/common_uniforms_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lamps_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_geom.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_cube_display_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_cube_display_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_grid_display_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_grid_display_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_grid_fill_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_planar_display_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_planar_display_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lit_surface_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lit_surface_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_bloom_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_dof_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_dof_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_downsample_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_downsample_cube_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_gtao_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_velocity_resolve_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_minmaxz_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_mist_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_ssr_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_subsurface_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_temporal_aa.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/prepass_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/prepass_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/shadow_store_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/shadow_copy_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/btdf_lut_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/irradiance_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/raytrace_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/update_noise_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/volumetric_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/volumetric_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/volumetric_geom.glsl SRC) +data_to_c_simple(engines/eevee/shaders/volumetric_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/volumetric_resolve_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/volumetric_scatter_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/volumetric_integration_frag.glsl SRC) + +data_to_c_simple(engines/workbench/shaders/workbench_background_lib.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_common_lib.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_data_lib.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_forward_composite_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_forward_depth_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_object_outline_lib.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_prepass_vert.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_prepass_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_shadow_vert.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_shadow_geom.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_shadow_caps_geom.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_shadow_debug_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_world_light_lib.glsl SRC) + +data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC) +data_to_c_simple(modes/shaders/common_hair_lib.glsl SRC) +data_to_c_simple(modes/shaders/common_hair_refine_vert.glsl SRC) +data_to_c_simple(modes/shaders/common_view_lib.glsl SRC) +data_to_c_simple(modes/shaders/common_fxaa_lib.glsl SRC) +data_to_c_simple(modes/shaders/common_fullscreen_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_axes_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_sphere_solid_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_sphere_solid_frag.glsl SRC) +data_to_c_simple(modes/shaders/armature_sphere_outline_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_envelope_solid_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_envelope_solid_frag.glsl SRC) +data_to_c_simple(modes/shaders/armature_envelope_outline_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_envelope_distance_frag.glsl SRC) +data_to_c_simple(modes/shaders/armature_shape_solid_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_shape_solid_frag.glsl SRC) +data_to_c_simple(modes/shaders/armature_shape_outline_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_shape_outline_geom.glsl SRC) +data_to_c_simple(modes/shaders/armature_stick_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_stick_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_tri.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_edge.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_loosevert_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_curve_overlay_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_curve_overlay_handle_geom.glsl SRC) +data_to_c_simple(modes/shaders/edit_curve_overlay_loosevert_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_lattice_overlay_frag.glsl SRC) +data_to_c_simple(modes/shaders/edit_lattice_overlay_loosevert_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_normals_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_normals_geom.glsl SRC) +data_to_c_simple(modes/shaders/overlay_face_orientation_frag.glsl SRC) +data_to_c_simple(modes/shaders/overlay_face_orientation_vert.glsl SRC) +data_to_c_simple(modes/shaders/object_empty_image_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC) +data_to_c_simple(modes/shaders/object_outline_resolve_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_outline_expand_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_outline_detect_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_outline_prepass_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_grid_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_grid_vert.glsl SRC) +data_to_c_simple(modes/shaders/object_lightprobe_grid_vert.glsl SRC) +data_to_c_simple(modes/shaders/object_mball_handles_vert.glsl SRC) +data_to_c_simple(modes/shaders/object_particle_prim_vert.glsl SRC) +data_to_c_simple(modes/shaders/object_particle_dot_vert.glsl SRC) +data_to_c_simple(modes/shaders/object_particle_dot_frag.glsl SRC) +data_to_c_simple(modes/shaders/paint_texture_frag.glsl SRC) +data_to_c_simple(modes/shaders/paint_texture_vert.glsl SRC) +data_to_c_simple(modes/shaders/paint_vertex_frag.glsl SRC) +data_to_c_simple(modes/shaders/paint_vertex_vert.glsl SRC) +data_to_c_simple(modes/shaders/paint_wire_frag.glsl SRC) +data_to_c_simple(modes/shaders/paint_wire_vert.glsl SRC) +data_to_c_simple(modes/shaders/paint_vert_frag.glsl SRC) +data_to_c_simple(modes/shaders/particle_strand_frag.glsl SRC) +data_to_c_simple(modes/shaders/particle_strand_vert.glsl SRC) + +list(APPEND INC +) + +blender_add_lib(bf_draw "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h new file mode 100644 index 00000000000..524a94e5886 --- /dev/null +++ b/source/blender/draw/DRW_engine.h @@ -0,0 +1,138 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file DRW_engine.h + * \ingroup draw + */ + +#ifndef __DRW_ENGINE_H__ +#define __DRW_ENGINE_H__ + +#include "BLI_sys_types.h" /* for bool */ + +struct ARegion; +struct CollectionEngineSettings; +struct Depsgraph; +struct DRWPass; +struct DRWInstanceDataList; +struct Main; +struct Material; +struct Scene; +struct DrawEngineType; +struct ID; +struct IDProperty; +struct bContext; +struct Object; +struct ViewLayer; +struct ViewContext; +struct ViewportEngineData; +struct View3D; +struct rcti; +struct GPUMaterial; +struct GPUOffScreen; +struct GPUViewport; +struct RenderEngine; +struct RenderEngineType; +struct WorkSpace; + +#include "DNA_object_enums.h" + +/* Buffer and textures used by the viewport by default */ +typedef struct DefaultFramebufferList { + struct GPUFrameBuffer *default_fb; + struct GPUFrameBuffer *color_only_fb; + struct GPUFrameBuffer *depth_only_fb; + struct GPUFrameBuffer *multisample_fb; +} DefaultFramebufferList; + +typedef struct DefaultTextureList { + struct GPUTexture *color; + struct GPUTexture *depth; + struct GPUTexture *multisample_color; + struct GPUTexture *multisample_depth; +} DefaultTextureList; + +void DRW_engines_register(void); +void DRW_engines_free(void); + +bool DRW_engine_render_support(struct DrawEngineType *draw_engine_type); +void DRW_engine_register(struct DrawEngineType *draw_engine_type); +void DRW_engine_viewport_data_size_get( + const void *engine_type, + int *r_fbl_len, int *r_txl_len, int *r_psl_len, int *r_stl_len); + +typedef struct DRWUpdateContext { + struct Main *bmain; + struct Depsgraph *depsgraph; + struct Scene *scene; + struct ViewLayer *view_layer; + struct ARegion *ar; + struct View3D *v3d; + struct RenderEngineType *engine_type; +} DRWUpdateContext; +void DRW_notify_view_update(const DRWUpdateContext *update_ctx); + + +typedef enum eDRWSelectStage { DRW_SELECT_PASS_PRE = 1, DRW_SELECT_PASS_POST, } eDRWSelectStage; +typedef bool (*DRW_SelectPassFn)( + eDRWSelectStage stage, void *user_data); + +void DRW_draw_view(const struct bContext *C); + +void DRW_draw_render_loop_ex( + struct Depsgraph *depsgraph, + struct RenderEngineType *engine_type, + struct ARegion *ar, struct View3D *v3d, + struct GPUViewport *viewport, + const struct bContext *evil_C); +void DRW_draw_render_loop( + struct Depsgraph *depsgraph, + struct ARegion *ar, struct View3D *v3d, + struct GPUViewport *viewport); +void DRW_draw_render_loop_offscreen( + struct Depsgraph *depsgraph, + struct RenderEngineType *engine_type, + struct ARegion *ar, struct View3D *v3d, + const bool draw_background, + struct GPUOffScreen *ofs, + struct GPUViewport *viewport); +void DRW_draw_select_loop( + struct Depsgraph *depsgraph, + struct ARegion *ar, struct View3D *v3d, + bool use_obedit_skip, bool use_nearest, const struct rcti *rect, + DRW_SelectPassFn select_pass_fn, void *select_pass_user_data); +void DRW_draw_depth_loop( + struct Depsgraph *depsgraph, + struct ARegion *ar, struct View3D *v3d); + +/* This is here because GPUViewport needs it */ +void DRW_pass_free(struct DRWPass *pass); +struct DRWInstanceDataList *DRW_instance_data_list_create(void); +void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist); + +void DRW_opengl_context_create(void); +void DRW_opengl_context_destroy(void); +void DRW_opengl_context_enable(void); +void DRW_opengl_context_disable(void); + +void DRW_deferred_shader_remove(struct GPUMaterial *mat); + +#endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c new file mode 100644 index 00000000000..c86574f7557 --- /dev/null +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -0,0 +1,255 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file basic_engine.c + * \ingroup draw_engine + * + * Simple engine for drawing color and/or depth. + * When we only need simple flat shaders. + */ + +#include "DRW_render.h" + +#include "BKE_icons.h" +#include "BKE_idprop.h" +#include "BKE_main.h" +#include "BKE_particle.h" + +#include "DNA_particle_types.h" + +#include "GPU_shader.h" + +#include "basic_engine.h" +/* Shaders */ + +#define BASIC_ENGINE "BLENDER_BASIC" + +/* we may want this later? */ +#define USE_DEPTH + +/* *********** LISTS *********** */ + +/* GPUViewport.storage + * Is freed everytime the viewport engine changes */ +typedef struct BASIC_StorageList { + struct BASIC_PrivateData *g_data; +} BASIC_StorageList; + +typedef struct BASIC_PassList { +#ifdef USE_DEPTH + struct DRWPass *depth_pass; + struct DRWPass *depth_pass_cull; +#endif + struct DRWPass *color_pass; +} BASIC_PassList; + +typedef struct BASIC_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + BASIC_PassList *psl; + BASIC_StorageList *stl; +} BASIC_Data; + +/* *********** STATIC *********** */ + +static struct { +#ifdef USE_DEPTH + /* Depth Pre Pass */ + struct GPUShader *depth_sh; +#endif + /* Shading Pass */ + struct GPUShader *color_sh; +} e_data = {NULL}; /* Engine data */ + +typedef struct BASIC_PrivateData { +#ifdef USE_DEPTH + DRWShadingGroup *depth_shgrp; + DRWShadingGroup *depth_shgrp_cull; + DRWShadingGroup *depth_shgrp_hair; +#endif + DRWShadingGroup *color_shgrp; +} BASIC_PrivateData; /* Transient data */ + +/* Functions */ + +static void basic_engine_init(void *UNUSED(vedata)) +{ +#ifdef USE_DEPTH + /* Depth prepass */ + if (!e_data.depth_sh) { + e_data.depth_sh = DRW_shader_create_3D_depth_only(); + } +#endif + + /* Shading pass */ + if (!e_data.color_sh) { + e_data.color_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } +} + +static void basic_cache_init(void *vedata) +{ + BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl; + BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + +#ifdef USE_DEPTH + /* Depth Pass */ + { + psl->depth_pass = DRW_pass_create( + "Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass); + + psl->depth_pass_cull = DRW_pass_create( + "Depth Pass Cull", + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK); + stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull); + } +#endif + + /* Color Pass */ + { + psl->color_pass = DRW_pass_create("Color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); + stl->g_data->color_shgrp = DRW_shgroup_create(e_data.color_sh, psl->color_pass); + } +} + +static void basic_cache_populate(void *vedata, Object *ob) +{ + BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl; + + if (!DRW_object_is_renderable(ob)) { + return; + } + + const DRWContextState *draw_ctx = DRW_context_state_get(); + if (ob == draw_ctx->object_edit) { + return; + } + + for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { + if (!psys_check_enabled(ob, psys, false)) { + continue; + } + if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + return; + } + ParticleSettings *part = psys->part; + const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + if (draw_as == PART_DRAW_PATH) { + struct Gwn_Batch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL); + DRW_shgroup_call_add(stl->g_data->depth_shgrp, hairs, NULL); + } + } + + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + bool do_cull = false; /* TODO (we probably wan't to take this from the viewport?) */ +#ifdef USE_DEPTH + /* Depth Prepass */ + DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat); +#endif + /* Shading */ + DRW_shgroup_call_add(stl->g_data->color_shgrp, geom, ob->obmat); + } +} + +static void basic_cache_finish(void *vedata) +{ + BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl; + + UNUSED_VARS(stl); +} + +static void basic_draw_scene(void *vedata) +{ + + BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl; + const bool is_select = DRW_state_is_select(); + + bool use_color = true; + bool use_depth = true; + bool use_depth_cull = true; + + if (is_select) { + /* Needed for depth-picking, + * for other selection types there are no need for extra passes either. */ + use_color = false; + use_depth_cull = false; + } + +#ifdef USE_DEPTH + /* Pass 1 : Depth pre-pass */ + if (use_depth) { + DRW_draw_pass(psl->depth_pass); + } + + if (use_depth_cull) { + DRW_draw_pass(psl->depth_pass_cull); + } +#endif + + /* Pass 3 : Shading */ + if (use_color) { + DRW_draw_pass(psl->color_pass); + } +} + +static void basic_engine_free(void) +{ + /* all shaders are builtin */ +} + +static const DrawEngineDataSize basic_data_size = DRW_VIEWPORT_DATA_SIZE(BASIC_Data); + +DrawEngineType draw_engine_basic_type = { + NULL, NULL, + N_("Basic"), + &basic_data_size, + &basic_engine_init, + &basic_engine_free, + &basic_cache_init, + &basic_cache_populate, + &basic_cache_finish, + NULL, + &basic_draw_scene, + NULL, + NULL, + NULL, +}; + +/* Note: currently unused, we may want to register so we can see this when debugging the view. */ + +RenderEngineType DRW_engine_viewport_basic_type = { + NULL, NULL, + BASIC_ENGINE, N_("Basic"), RE_INTERNAL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &draw_engine_basic_type, + {NULL, NULL, NULL} +}; + + +#undef BASIC_ENGINE diff --git a/source/blender/draw/engines/basic/basic_engine.h b/source/blender/draw/engines/basic/basic_engine.h new file mode 100644 index 00000000000..0adf99835a2 --- /dev/null +++ b/source/blender/draw/engines/basic/basic_engine.h @@ -0,0 +1,32 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file basic_engine.h + * \ingroup draw_engine + */ + +#ifndef __BASIC_ENGINE_H__ +#define __BASIC_ENGINE_H__ + +extern DrawEngineType draw_engine_basic_type; +extern RenderEngineType DRW_engine_viewport_basic_type; + +#endif /* __BASIC_ENGINE_H__ */ diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c new file mode 100644 index 00000000000..d08fee6039f --- /dev/null +++ b/source/blender/draw/engines/clay/clay_engine.c @@ -0,0 +1,985 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +#include "BLI_utildefines.h" +#include "BLI_string_utils.h" +#include "BLI_rand.h" + +#include "DNA_particle_types.h" +#include "DNA_view3d_types.h" + +#include "BKE_icons.h" +#include "BKE_idprop.h" +#include "BKE_main.h" +#include "BKE_particle.h" + +#include "GPU_shader.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "UI_resources.h" +#include "UI_interface_icons.h" + +#include "DRW_render.h" + +#include "DEG_depsgraph_query.h" + +#include "clay_engine.h" + +#ifdef WITH_CLAY_ENGINE +#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */ + +/* Shaders */ + +#define CLAY_ENGINE "BLENDER_CLAY" + +#define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */ + +#define SHADER_DEFINES_NO_AO \ + "#define MAX_MATERIAL " STRINGIFY(MAX_CLAY_MAT) "\n" \ + "#define USE_ROTATION\n" \ + "#define USE_HSV\n" + +#define SHADER_DEFINES \ + SHADER_DEFINES_NO_AO \ + "#define USE_AO\n" + +extern char datatoc_clay_frag_glsl[]; +extern char datatoc_clay_prepass_frag_glsl[]; +extern char datatoc_clay_copy_glsl[]; +extern char datatoc_clay_vert_glsl[]; +extern char datatoc_clay_fxaa_glsl[]; +extern char datatoc_clay_particle_vert_glsl[]; +extern char datatoc_clay_particle_strand_frag_glsl[]; +extern char datatoc_ssao_alchemy_glsl[]; +extern char datatoc_common_fxaa_lib_glsl[]; + +/* *********** LISTS *********** */ + +/** + * UBOs data needs to be 16 byte aligned (size of vec4) + * + * Reminder: float, int, bool are 4 bytes + * + * \note struct is expected to be initialized with all pad-bits zero'd + * so we can use 'memcmp' to check for duplicates. Possibly hash data later. + */ +typedef struct CLAY_UBO_Material { + float ssao_params_var[4]; + /* - 16 -*/ + float matcap_hsv[3]; + float matcap_id; /* even float encoding have enough precision */ + /* - 16 -*/ + float matcap_rot[2]; + float pad[2]; /* ensure 16 bytes alignement */ +} CLAY_UBO_Material; /* 48 bytes */ +BLI_STATIC_ASSERT_ALIGN(CLAY_UBO_Material, 16) + +typedef struct CLAY_HAIR_UBO_Material { + float hair_randomness; + float matcap_id; + float matcap_rot[2]; + float matcap_hsv[3]; + float pad; +} CLAY_HAIR_UBO_Material; /* 32 bytes */ +BLI_STATIC_ASSERT_ALIGN(CLAY_HAIR_UBO_Material, 16) + +typedef struct CLAY_UBO_Storage { + CLAY_UBO_Material materials[MAX_CLAY_MAT]; +} CLAY_UBO_Storage; + +typedef struct CLAY_HAIR_UBO_Storage { + CLAY_HAIR_UBO_Material materials[MAX_CLAY_MAT]; +} CLAY_HAIR_UBO_Storage; + +/* GPUViewport.storage + * Is freed everytime the viewport engine changes */ +typedef struct CLAY_Storage { + /* Materials Parameter UBO */ + CLAY_UBO_Storage mat_storage; + CLAY_HAIR_UBO_Storage hair_mat_storage; + int ubo_current_id; + int hair_ubo_current_id; + DRWShadingGroup *shgrps[MAX_CLAY_MAT]; + DRWShadingGroup *shgrps_flat[MAX_CLAY_MAT]; + DRWShadingGroup *shgrps_pre[MAX_CLAY_MAT]; + DRWShadingGroup *shgrps_pre_flat[MAX_CLAY_MAT]; + DRWShadingGroup *hair_shgrps[MAX_CLAY_MAT]; +} CLAY_Storage; + +typedef struct CLAY_StorageList { + struct CLAY_Storage *storage; + struct CLAY_PrivateData *g_data; +} CLAY_StorageList; + +typedef struct CLAY_FramebufferList { + struct GPUFrameBuffer *antialias_fb; + struct GPUFrameBuffer *prepass_fb; +} CLAY_FramebufferList; + +typedef struct CLAY_PassList { + struct DRWPass *clay_ps; + struct DRWPass *clay_cull_ps; + struct DRWPass *clay_flat_ps; + struct DRWPass *clay_flat_cull_ps; + struct DRWPass *clay_pre_ps; + struct DRWPass *clay_pre_cull_ps; + struct DRWPass *clay_flat_pre_ps; + struct DRWPass *clay_flat_pre_cull_ps; + struct DRWPass *clay_deferred_ps; + struct DRWPass *fxaa_ps; + struct DRWPass *copy_ps; + struct DRWPass *hair_pass; +} CLAY_PassList; + + +typedef struct CLAY_Data { + void *engine_type; + CLAY_FramebufferList *fbl; + DRWViewportEmptyList *txl; + CLAY_PassList *psl; + CLAY_StorageList *stl; +} CLAY_Data; + +typedef struct CLAY_ViewLayerData { + struct GPUTexture *jitter_tx; + struct GPUUniformBuffer *mat_ubo; + struct GPUUniformBuffer *matcaps_ubo; + struct GPUUniformBuffer *hair_mat_ubo; + struct GPUUniformBuffer *sampling_ubo; + int cached_sample_num; +} CLAY_ViewLayerData; + +/* *********** STATIC *********** */ + +static struct { + /* Shading Pass */ + struct GPUShader *clay_sh; + struct GPUShader *clay_flat_sh; + struct GPUShader *clay_prepass_flat_sh; + struct GPUShader *clay_prepass_sh; + struct GPUShader *clay_deferred_shading_sh; + struct GPUShader *fxaa_sh; + struct GPUShader *copy_sh; + struct GPUShader *hair_sh; + /* Matcap textures */ + struct GPUTexture *matcap_array; + float matcap_colors[24][4]; + /* Just a serie of int from 0 to MAX_CLAY_MAT-1 */ + int ubo_mat_idxs[MAX_CLAY_MAT]; + /* To avoid useless texture and ubo binds. */ + bool first_shgrp; +} e_data = {NULL}; /* Engine data */ + +typedef struct CLAY_PrivateData { + DRWShadingGroup *depth_shgrp; + DRWShadingGroup *depth_shgrp_select; + DRWShadingGroup *depth_shgrp_active; + DRWShadingGroup *depth_shgrp_cull; + DRWShadingGroup *depth_shgrp_cull_select; + DRWShadingGroup *depth_shgrp_cull_active; + /* Deferred shading */ + struct GPUTexture *depth_tx; /* ref only, not alloced */ + struct GPUTexture *normal_tx; /* ref only, not alloced */ + struct GPUTexture *id_tx; /* ref only, not alloced */ + struct GPUTexture *color_copy; /* ref only, not alloced */ + bool enable_deferred_path; + /* Ssao */ + float winmat[4][4]; + float viewvecs[3][4]; + float ssao_params[4]; +} CLAY_PrivateData; /* Transient data */ + +/* Functions */ + +static void clay_view_layer_data_free(void *storage) +{ + CLAY_ViewLayerData *sldata = (CLAY_ViewLayerData *)storage; + + DRW_UBO_FREE_SAFE(sldata->mat_ubo); + DRW_UBO_FREE_SAFE(sldata->matcaps_ubo); + DRW_UBO_FREE_SAFE(sldata->hair_mat_ubo); + DRW_UBO_FREE_SAFE(sldata->sampling_ubo); + DRW_TEXTURE_FREE_SAFE(sldata->jitter_tx); +} + +static CLAY_ViewLayerData *CLAY_view_layer_data_get(void) +{ + CLAY_ViewLayerData **sldata = (CLAY_ViewLayerData **)DRW_view_layer_engine_data_ensure( + &draw_engine_clay_type, &clay_view_layer_data_free); + + if (*sldata == NULL) { + *sldata = MEM_callocN(sizeof(**sldata), "CLAY_ViewLayerData"); + } + + return *sldata; +} + +static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer) +{ + int image_size = prv->w[0] * prv->h[0]; + float *new_rect = &final_rect[image_size * 4 * layer]; + + IMB_buffer_float_from_byte(new_rect, (unsigned char *)prv->rect[0], IB_PROFILE_SRGB, IB_PROFILE_SRGB, + false, prv->w[0], prv->h[0], prv->w[0], prv->w[0]); + + /* Find overall color */ + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + e_data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0]; + e_data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1]; + e_data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2]; + } + } + + e_data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */ + e_data.matcap_colors[layer][1] /= 16.0f * 2.0f; + e_data.matcap_colors[layer][2] /= 16.0f * 2.0f; +} + +static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr) +{ + struct GPUTexture *tex; + int w = prv[0]->w[0]; + int h = prv[0]->h[0]; + float *final_rect = MEM_callocN(sizeof(float) * 4 * w * h * nbr, "Clay Matcap array rect"); + + for (int i = 0; i < nbr; ++i) { + add_icon_to_rect(prv[i], final_rect, i); + BKE_previewimg_free(&prv[i]); + } + + tex = DRW_texture_create_2D_array(w, h, nbr, GPU_RGBA8, DRW_TEX_FILTER, final_rect); + MEM_freeN(final_rect); + + return tex; +} + +static int matcap_to_index(int matcap) +{ + return matcap - 1; +} + +/* Using Hammersley distribution */ +static float *create_disk_samples(int num_samples) +{ + /* vec4 to ensure memory alignment. */ + float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * num_samples, "concentric_tex"); + const float num_samples_inv = 1.0f / num_samples; + + for (int i = 0; i < num_samples; i++) { + float r = (i + 0.5f) * num_samples_inv; + double dphi; + BLI_hammersley_1D(i, &dphi); + + float phi = (float)dphi * 2.0f * M_PI; + texels[i][0] = cosf(phi); + texels[i][1] = sinf(phi); + /* This deliberatly distribute more samples + * at the center of the disk (and thus the shadow). */ + texels[i][2] = r; + } + + return (float *)texels; +} + +static struct GPUTexture *create_jitter_texture(int num_samples) +{ + float jitter[64 * 64][3]; + const float num_samples_inv = 1.0f / num_samples; + + for (int i = 0; i < 64 * 64; i++) { + float phi = blue_noise[i][0] * 2.0f * M_PI; + /* This rotate the sample per pixels */ + jitter[i][0] = cosf(phi); + jitter[i][1] = sinf(phi); + /* This offset the sample along it's direction axis (reduce banding) */ + float bn = blue_noise[i][1] - 0.5f; + CLAMP(bn, -0.499f, 0.499f); /* fix fireflies */ + jitter[i][2] = bn * num_samples_inv; + } + + UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx, ltc_disk_integral); + + return DRW_texture_create_2D(64, 64, GPU_RGB16F, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]); +} + +static void clay_engine_init(void *vedata) +{ + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; + CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl; + CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + /* Create Texture Array */ + if (!e_data.matcap_array) { + PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */ + const int num_matcap = ARRAY_SIZE(prv); + + /* TODO only load used matcaps */ + for (int i = 0; i < num_matcap; ++i) { + prv[i] = UI_icon_to_preview((int)ICON_MATCAP_01 + i); + } + + e_data.matcap_array = load_matcaps(prv, num_matcap); + } + + /* Shading pass */ + if (!e_data.clay_sh) { + char *matcap_with_ao = BLI_string_joinN( + datatoc_clay_frag_glsl, + datatoc_ssao_alchemy_glsl); + + e_data.clay_sh = DRW_shader_create( + datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl, + SHADER_DEFINES_NO_AO); + e_data.clay_flat_sh = DRW_shader_create( + datatoc_clay_vert_glsl, NULL, datatoc_clay_frag_glsl, + SHADER_DEFINES_NO_AO + "#define USE_FLAT_NORMAL\n"); + + e_data.clay_prepass_sh = DRW_shader_create( + datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl, + SHADER_DEFINES); + e_data.clay_prepass_flat_sh = DRW_shader_create( + datatoc_clay_vert_glsl, NULL, datatoc_clay_prepass_frag_glsl, + SHADER_DEFINES + "#define USE_FLAT_NORMAL\n"); + + e_data.clay_deferred_shading_sh = DRW_shader_create_fullscreen( + matcap_with_ao, + SHADER_DEFINES + "#define DEFERRED_SHADING\n"); + + MEM_freeN(matcap_with_ao); + + char *fxaa_str = BLI_string_joinN( + datatoc_common_fxaa_lib_glsl, + datatoc_clay_fxaa_glsl); + + e_data.fxaa_sh = DRW_shader_create_fullscreen(fxaa_str, NULL); + + MEM_freeN(fxaa_str); + + e_data.copy_sh = DRW_shader_create_fullscreen(datatoc_clay_copy_glsl, NULL); + } + + if (!stl->storage) { + stl->storage = MEM_callocN(sizeof(CLAY_Storage), "CLAY_Storage"); + } + + if (!stl->g_data) { + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), "CLAY_PrivateStorage"); + } + + CLAY_PrivateData *g_data = stl->g_data; + + if (!sldata->mat_ubo) { + sldata->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL); + } + + if (!sldata->hair_mat_ubo) { + sldata->hair_mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_HAIR_UBO_Storage), NULL); + } + + if (!sldata->matcaps_ubo) { + sldata->matcaps_ubo = DRW_uniformbuffer_create(sizeof(e_data.matcap_colors), e_data.matcap_colors); + } + + if (e_data.ubo_mat_idxs[1] == 0) { + /* Just int to have pointers to them */ + for (int i = 0; i < MAX_CLAY_MAT; ++i) { + e_data.ubo_mat_idxs[i] = i; + } + } + + /* FBO setup */ + { + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + g_data->normal_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RG8, &draw_engine_clay_type); + g_data->id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R16UI, &draw_engine_clay_type); + + GPU_framebuffer_ensure_config(&fbl->prepass_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(g_data->normal_tx), + GPU_ATTACHMENT_TEXTURE(g_data->id_tx) + }); + + /* For FXAA */ + /* TODO(fclem): OPTI: we could merge normal_tx and id_tx into a GPU_RGBA8 + * and reuse it for the fxaa target. */ + g_data->color_copy = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_clay_type); + + GPU_framebuffer_ensure_config(&fbl->antialias_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(g_data->color_copy) + }); + } + + /* SSAO setup */ + { + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + const int ssao_samples = scene_eval->display.matcap_ssao_samples; + + float invproj[4][4]; + float dfdyfacs[2]; + const bool is_persp = DRW_viewport_is_persp_get(); + /* view vectors for the corners of the view frustum. + * Can be used to recreate the world space position easily */ + float viewvecs[3][4] = { + {-1.0f, -1.0f, -1.0f, 1.0f}, + {1.0f, -1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f, 1.0f} + }; + int i; + const float *size = DRW_viewport_size_get(); + + DRW_state_dfdy_factors_get(dfdyfacs); + + g_data->ssao_params[0] = ssao_samples; + g_data->ssao_params[1] = size[0] / 64.0; + g_data->ssao_params[2] = size[1] / 64.0; + g_data->ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */ + + /* invert the view matrix */ + DRW_viewport_matrix_get(g_data->winmat, DRW_MAT_WIN); + invert_m4_m4(invproj, g_data->winmat); + + /* convert the view vectors to view space */ + for (i = 0; i < 3; i++) { + mul_m4_v4(invproj, viewvecs[i]); + /* normalized trick see: + * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]); + if (is_persp) + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); + viewvecs[i][3] = 1.0; + + copy_v4_v4(g_data->viewvecs[i], viewvecs[i]); + } + + /* we need to store the differences */ + g_data->viewvecs[1][0] -= g_data->viewvecs[0][0]; + g_data->viewvecs[1][1] = g_data->viewvecs[2][1] - g_data->viewvecs[0][1]; + + /* calculate a depth offset as well */ + if (!is_persp) { + float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f}; + mul_m4_v4(invproj, vec_far); + mul_v3_fl(vec_far, 1.0f / vec_far[3]); + g_data->viewvecs[1][2] = vec_far[2] - g_data->viewvecs[0][2]; + } + + /* AO Samples Tex */ + if (sldata->sampling_ubo && (sldata->cached_sample_num != ssao_samples)) { + DRW_UBO_FREE_SAFE(sldata->sampling_ubo); + DRW_TEXTURE_FREE_SAFE(sldata->jitter_tx); + } + + if (sldata->sampling_ubo == NULL) { + float *samples = create_disk_samples(ssao_samples); + sldata->jitter_tx = create_jitter_texture(ssao_samples); + sldata->sampling_ubo = DRW_uniformbuffer_create(sizeof(float[4]) * ssao_samples, samples); + sldata->cached_sample_num = ssao_samples; + MEM_freeN(samples); + } + } +} + +static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, GPUShader *sh, int id) +{ + CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1); + if (e_data.first_shgrp) { + DRW_shgroup_uniform_texture_persistent(grp, "matcaps", e_data.matcap_array); + DRW_shgroup_uniform_block_persistent(grp, "material_block", sldata->mat_ubo); + DRW_shgroup_uniform_block_persistent(grp, "matcaps_block", sldata->matcaps_ubo); + } + return grp; +} + +static DRWShadingGroup *CLAY_shgroup_deferred_prepass_create(DRWPass *pass, GPUShader *sh, int id) +{ + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1); + + return grp; +} + +static DRWShadingGroup *CLAY_shgroup_deferred_shading_create(DRWPass *pass, CLAY_PrivateData *g_data) +{ + CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_deferred_shading_sh, pass); + DRW_shgroup_uniform_texture_ref(grp, "depthtex", &g_data->depth_tx); + DRW_shgroup_uniform_texture_ref(grp, "normaltex", &g_data->normal_tx); + DRW_shgroup_uniform_texture_ref(grp, "idtex", &g_data->id_tx); + DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array); + DRW_shgroup_uniform_texture(grp, "ssao_jitter", sldata->jitter_tx); + DRW_shgroup_uniform_block(grp, "samples_block", sldata->sampling_ubo); + DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo); + DRW_shgroup_uniform_block(grp, "matcaps_block", sldata->matcaps_ubo); + /* TODO put in ubo */ + DRW_shgroup_uniform_mat4(grp, "WinMatrix", g_data->winmat); + DRW_shgroup_uniform_vec2(grp, "invscreenres", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)g_data->viewvecs, 3); + DRW_shgroup_uniform_vec4(grp, "ssao_params", g_data->ssao_params, 1); + return grp; +} + +static DRWShadingGroup *CLAY_hair_shgroup_create(DRWPass *pass, int id) +{ + CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); + + if (!e_data.hair_sh) { + e_data.hair_sh = DRW_shader_create( + datatoc_clay_particle_vert_glsl, NULL, datatoc_clay_particle_strand_frag_glsl, + "#define MAX_MATERIAL " STRINGIFY(MAX_CLAY_MAT) "\n" ); + } + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.hair_sh, pass); + DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array); + DRW_shgroup_uniform_block(grp, "material_block", sldata->mat_ubo); + DRW_shgroup_uniform_int(grp, "mat_id", &e_data.ubo_mat_idxs[id], 1); + + return grp; +} + +static int search_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test) +{ + /* For now just use a linear search and test all parameters */ + /* TODO make a hash table */ + for (int i = 0; i < storage->ubo_current_id; ++i) { + CLAY_UBO_Material *ubo = &storage->mat_storage.materials[i]; + if (memcmp(ubo, mat_ubo_test, sizeof(*mat_ubo_test)) == 0) { + return i; + } + } + + return -1; +} + +static int search_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test) +{ + /* For now just use a linear search and test all parameters */ + /* TODO make a hash table */ + for (int i = 0; i < storage->hair_ubo_current_id; ++i) { + CLAY_HAIR_UBO_Material *ubo = &storage->hair_mat_storage.materials[i]; + if (memcmp(ubo, hair_mat_ubo_test, sizeof(*hair_mat_ubo_test)) == 0) { + return i; + } + } + + return -1; +} + +static int push_mat_to_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test) +{ + int id = storage->ubo_current_id++; + id = min_ii(MAX_CLAY_MAT, id); + storage->mat_storage.materials[id] = *mat_ubo_test; + return id; +} + +static int push_hair_mat_to_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test) +{ + int id = storage->hair_ubo_current_id++; + id = min_ii(MAX_CLAY_MAT, id); + storage->hair_mat_storage.materials[id] = *hair_mat_ubo_test; + return id; +} + +static int mat_in_ubo(CLAY_Storage *storage, const CLAY_UBO_Material *mat_ubo_test) +{ + /* Search material in UBO */ + int id = search_mat_to_ubo(storage, mat_ubo_test); + + /* if not found create it */ + if (id == -1) { + id = push_mat_to_ubo(storage, mat_ubo_test); + } + + return id; +} + +static int hair_mat_in_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *hair_mat_ubo_test) +{ + /* Search material in UBO */ + int id = search_hair_mat_to_ubo(storage, hair_mat_ubo_test); + + /* if not found create it */ + if (id == -1) { + id = push_hair_mat_to_ubo(storage, hair_mat_ubo_test); + } + + return id; +} + +static void ubo_mat_from_object(CLAY_Storage *storage, Object *UNUSED(ob), bool *r_needs_ao, int *r_id) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + const int matcap_icon = scene_eval->display.matcap_icon; + const float matcap_rot = scene_eval->display.matcap_rotation; + const float matcap_hue = scene_eval->display.matcap_hue; + const float matcap_sat = scene_eval->display.matcap_saturation; + const float matcap_val = scene_eval->display.matcap_value; + const float ssao_distance = scene_eval->display.matcap_ssao_distance; + const float ssao_factor_cavity = scene_eval->display.matcap_ssao_factor_cavity; + const float ssao_factor_edge = scene_eval->display.matcap_ssao_factor_edge; + const float ssao_attenuation = scene_eval->display.matcap_ssao_attenuation; + + CLAY_UBO_Material r_ubo = {{0.0f}}; + + if (((ssao_factor_cavity > 0.0) || (ssao_factor_edge > 0.0)) && + (ssao_distance > 0.0)) + { + *r_needs_ao = true; + + r_ubo.ssao_params_var[0] = ssao_distance; + r_ubo.ssao_params_var[1] = ssao_factor_cavity; + r_ubo.ssao_params_var[2] = ssao_factor_edge; + r_ubo.ssao_params_var[3] = ssao_attenuation; + } + else { + *r_needs_ao = false; + } + + r_ubo.matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f); + r_ubo.matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f); + + r_ubo.matcap_hsv[0] = matcap_hue + 0.5f; + r_ubo.matcap_hsv[1] = matcap_sat * 2.0f; + r_ubo.matcap_hsv[2] = matcap_val * 2.0f; + + r_ubo.matcap_id = matcap_to_index(matcap_icon); + + *r_id = mat_in_ubo(storage, &r_ubo); +} + +static void hair_ubo_mat_from_object(Object *UNUSED(ob), CLAY_HAIR_UBO_Material *r_ubo) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + const int matcap_icon = scene_eval->display.matcap_icon; + const float matcap_rot = scene_eval->display.matcap_rotation; + const float matcap_hue = scene_eval->display.matcap_hue; + const float matcap_sat = scene_eval->display.matcap_saturation; + const float matcap_val = scene_eval->display.matcap_value; + const float hair_randomness = scene_eval->display.matcap_hair_brightness_randomness; + + memset(r_ubo, 0x0, sizeof(*r_ubo)); + + r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f); + r_ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f); + r_ubo->matcap_hsv[0] = matcap_hue + 0.5f; + r_ubo->matcap_hsv[1] = matcap_sat * 2.0f; + r_ubo->matcap_hsv[2] = matcap_val * 2.0f; + r_ubo->hair_randomness = hair_randomness; + r_ubo->matcap_id = matcap_to_index(matcap_icon); +} + +static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, bool use_flat, bool cull) +{ + bool prepass; int id; + CLAY_PassList *psl = vedata->psl; + CLAY_Storage *storage = vedata->stl->storage; + DRWShadingGroup **shgrps; + DRWPass *pass; GPUShader *sh; + + ubo_mat_from_object(storage, ob, &prepass, &id); + + if (prepass) { + if (use_flat) { + shgrps = storage->shgrps_pre_flat; + pass = (cull) ? psl->clay_flat_pre_cull_ps : psl->clay_flat_pre_ps; + sh = e_data.clay_prepass_flat_sh; + } + else { + shgrps = storage->shgrps_pre; + pass = (cull) ? psl->clay_pre_cull_ps : psl->clay_pre_ps; + sh = e_data.clay_prepass_sh; + } + + if (shgrps[id] == NULL) { + shgrps[id] = CLAY_shgroup_deferred_prepass_create(pass, sh, id); + } + + vedata->stl->g_data->enable_deferred_path = true; + } + else { + if (use_flat) { + shgrps = storage->shgrps_flat; + pass = (cull) ? psl->clay_flat_cull_ps : psl->clay_flat_ps; + sh = e_data.clay_flat_sh; + } + else { + shgrps = storage->shgrps; + pass = (cull) ? psl->clay_cull_ps : psl->clay_ps; + sh = e_data.clay_sh; + } + + if (shgrps[id] == NULL) { + shgrps[id] = CLAY_shgroup_create(pass, sh, id); + e_data.first_shgrp = false; + } + } + + return shgrps[id]; +} + +static DRWShadingGroup *CLAY_hair_shgrp_get( + CLAY_Data *UNUSED(vedata), Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl) +{ + DRWShadingGroup **hair_shgrps = stl->storage->hair_shgrps; + + CLAY_HAIR_UBO_Material hair_mat_ubo_test; + hair_ubo_mat_from_object(ob, &hair_mat_ubo_test); + + int hair_id = hair_mat_in_ubo(stl->storage, &hair_mat_ubo_test); + + if (hair_shgrps[hair_id] == NULL) { + hair_shgrps[hair_id] = CLAY_hair_shgroup_create(psl->hair_pass, hair_id); + } + + return hair_shgrps[hair_id]; +} + +static void clay_cache_init(void *vedata) +{ + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; + + /* Disable AO unless a material needs it. */ + stl->g_data->enable_deferred_path = false; + + /* Reset UBO datas, shgrp pointers and material id counters. */ + memset(stl->storage, 0, sizeof(*stl->storage)); + e_data.first_shgrp = true; + + /* Solid Passes */ + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + psl->clay_ps = DRW_pass_create("Clay", state); + psl->clay_cull_ps = DRW_pass_create("Clay Culled", state | DRW_STATE_CULL_BACK); + psl->clay_flat_ps = DRW_pass_create("Clay Flat", state); + psl->clay_flat_cull_ps = DRW_pass_create("Clay Flat Culled", state | DRW_STATE_CULL_BACK); + + DRWState prepass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + DRWState prepass_cull_state = prepass_state | DRW_STATE_CULL_BACK; + psl->clay_pre_ps = DRW_pass_create("Clay Deferred Pre", prepass_state); + psl->clay_pre_cull_ps = DRW_pass_create("Clay Deferred Pre Culled", prepass_cull_state); + psl->clay_flat_pre_ps = DRW_pass_create("Clay Deferred Flat Pre", prepass_state); + psl->clay_flat_pre_cull_ps = DRW_pass_create("Clay Deferred Flat Pre Culled", prepass_cull_state); + + psl->clay_deferred_ps = DRW_pass_create("Clay Deferred Shading", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = CLAY_shgroup_deferred_shading_create(psl->clay_deferred_ps, stl->g_data); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + /* Hair Pass */ + { + psl->hair_pass = DRW_pass_create( + "Hair Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + } + + { + psl->fxaa_ps = DRW_pass_create("Fxaa", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.fxaa_sh, psl->fxaa_ps); + DRW_shgroup_uniform_texture_ref(grp, "colortex", &dtxl->color); + DRW_shgroup_uniform_vec2(grp, "invscreenres", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + + psl->copy_ps = DRW_pass_create("Copy", DRW_STATE_WRITE_COLOR); + grp = DRW_shgroup_create(e_data.copy_sh, psl->copy_ps); + DRW_shgroup_uniform_texture_ref(grp, "colortex", &stl->g_data->color_copy); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } +} + +static void clay_cache_populate_particles(void *vedata, Object *ob) +{ + CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (ob == draw_ctx->object_edit) { + return; + } + + for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { + if (!psys_check_enabled(ob, psys, false)) { + continue; + } + if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + return; + } + ParticleSettings *part = psys->part; + const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + if (draw_as == PART_DRAW_PATH) { + struct Gwn_Batch *geom = DRW_cache_particles_get_hair(ob, psys, NULL); + DRWShadingGroup *hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl); + DRW_shgroup_call_add(hair_shgrp, geom, NULL); + } + } +} + +static void clay_cache_populate(void *vedata, Object *ob) +{ + DRWShadingGroup *clay_shgrp; + + if (!DRW_object_is_renderable(ob)) + return; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool is_active = (ob == draw_ctx->obact); + if (is_active) { + if (DRW_object_is_mode_shade(ob) == true) { + return; + } + } + + /* Handle particles first in case the emitter itself shouldn't be rendered. */ + if (ob->type == OB_MESH) { + clay_cache_populate_particles(vedata, ob); + } + + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING)); + const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; + const bool use_flat = is_sculpt_mode && DRW_object_is_flat_normal(ob); + + clay_shgrp = CLAY_object_shgrp_get(vedata, ob, use_flat, do_cull); + + if (is_sculpt_mode) { + DRW_shgroup_call_sculpt_add(clay_shgrp, ob, ob->obmat); + } + else { + DRW_shgroup_call_object_add(clay_shgrp, geom, ob); + } + } +} + +static void clay_cache_finish(void *vedata) +{ + CLAY_ViewLayerData *sldata = CLAY_view_layer_data_get(); + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; + + DRW_uniformbuffer_update(sldata->mat_ubo, &stl->storage->mat_storage); + DRW_uniformbuffer_update(sldata->hair_mat_ubo, &stl->storage->hair_mat_storage); +} + +static void clay_draw_scene(void *vedata) +{ + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; + CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; + CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + stl->g_data->depth_tx = dtxl->depth; + + /* Passes are ordered to have less _potential_ overdraw */ + DRW_draw_pass(psl->clay_cull_ps); + DRW_draw_pass(psl->clay_flat_cull_ps); + DRW_draw_pass(psl->clay_ps); + DRW_draw_pass(psl->clay_flat_ps); + DRW_draw_pass(psl->hair_pass); + + if (stl->g_data->enable_deferred_path) { + GPU_framebuffer_bind(fbl->prepass_fb); + /* We need to clear the id texture unfortunately. */ + const float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->prepass_fb, clear_col); + + DRW_draw_pass(psl->clay_pre_cull_ps); + DRW_draw_pass(psl->clay_flat_pre_cull_ps); + DRW_draw_pass(psl->clay_pre_ps); + DRW_draw_pass(psl->clay_flat_pre_ps); + + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_draw_pass(psl->clay_deferred_ps); + } + + if (true) { /* Always on for now. We might want a parameter for this. */ + GPU_framebuffer_bind(fbl->antialias_fb); + DRW_draw_pass(psl->fxaa_ps); + + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_draw_pass(psl->copy_ps); + } +} + +static void clay_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.clay_sh); + DRW_SHADER_FREE_SAFE(e_data.clay_flat_sh); + DRW_SHADER_FREE_SAFE(e_data.clay_prepass_flat_sh); + DRW_SHADER_FREE_SAFE(e_data.clay_prepass_sh); + DRW_SHADER_FREE_SAFE(e_data.clay_deferred_shading_sh); + DRW_SHADER_FREE_SAFE(e_data.fxaa_sh); + DRW_SHADER_FREE_SAFE(e_data.copy_sh); + DRW_SHADER_FREE_SAFE(e_data.hair_sh); + DRW_TEXTURE_FREE_SAFE(e_data.matcap_array); +} + +static const DrawEngineDataSize clay_data_size = DRW_VIEWPORT_DATA_SIZE(CLAY_Data); + +DrawEngineType draw_engine_clay_type = { + NULL, NULL, + N_("Clay"), + &clay_data_size, + &clay_engine_init, + &clay_engine_free, + &clay_cache_init, + &clay_cache_populate, + &clay_cache_finish, + NULL, + &clay_draw_scene, + NULL, + NULL, + NULL, +}; + +RenderEngineType DRW_engine_viewport_clay_type = { + NULL, NULL, + CLAY_ENGINE, N_("Clay"), RE_INTERNAL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &draw_engine_clay_type, + {NULL, NULL, NULL} +}; + + +#undef CLAY_ENGINE + +#endif /* WITH_CLAY_ENGINE */ diff --git a/source/blender/draw/engines/clay/clay_engine.h b/source/blender/draw/engines/clay/clay_engine.h new file mode 100644 index 00000000000..b7c9d00c9ae --- /dev/null +++ b/source/blender/draw/engines/clay/clay_engine.h @@ -0,0 +1,36 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file clay_engine.h + * \ingroup draw_engine + */ + +#ifndef __CLAY_ENGINE_H__ +#define __CLAY_ENGINE_H__ + +extern DrawEngineType draw_engine_clay_type; +extern RenderEngineType DRW_engine_viewport_clay_type; + +struct IDProperty; + +struct IDProperty *CLAY_render_settings_create(void); + +#endif /* __CLAY_ENGINE_H__ */ diff --git a/source/blender/draw/engines/clay/shaders/clay_copy.glsl b/source/blender/draw/engines/clay/shaders/clay_copy.glsl new file mode 100644 index 00000000000..ec462978e67 --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/clay_copy.glsl @@ -0,0 +1,10 @@ + +in vec4 uvcoordsvar; +out vec4 fragColor; + +uniform sampler2D colortex; + +void main() +{ + fragColor = texture(colortex, uvcoordsvar.st); +} diff --git a/source/blender/draw/engines/clay/shaders/clay_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_frag.glsl new file mode 100644 index 00000000000..1939e4b735d --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/clay_frag.glsl @@ -0,0 +1,252 @@ +uniform vec2 invscreenres; +uniform mat4 WinMatrix; + +/* Matcap */ +uniform sampler2DArray matcaps; + +/* Screen Space Occlusion */ +/* store the view space vectors for the corners of the view frustum here. + * It helps to quickly reconstruct view space vectors by using uv coordinates, + * see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ +uniform vec4 viewvecs[3]; +uniform vec4 ssao_params; + +uniform sampler2D ssao_jitter; + +/* Material Parameters packed in an UBO */ +struct Material { + vec4 ssao_params_var; + vec4 matcap_hsv_id; + vec4 matcap_rot; /* vec4 to ensure 16 bytes alignement (don't trust compiler) */ +}; + +layout(std140) uniform samples_block { + vec4 ssao_samples[500]; +}; + +layout(std140) uniform matcaps_block { + vec4 matcaps_color[24]; +}; + +layout(std140) uniform material_block { + Material matcaps_param[MAX_MATERIAL]; +}; + +#ifdef DEFERRED_SHADING +uniform sampler2D depthtex; +uniform sampler2D normaltex; +uniform isampler2D idtex; +int mat_id; /* global */ +#else +uniform int mat_id; +#endif + +/* Aliases */ +#define ssao_samples_num ssao_params.x +#define jitter_tilling ssao_params.yz +#define dfdy_sign ssao_params.w + +#define matcap_hsv matcaps_param[mat_id].matcap_hsv_id.xyz +#define matcap_index matcaps_param[mat_id].matcap_hsv_id.w +#define matcap_rotation matcaps_param[mat_id].matcap_rot.xy + +#ifndef DEFERRED_SHADING +# ifdef USE_FLAT_NORMAL +flat in vec3 normal; +# else +in vec3 normal; +# endif +#endif + +out vec4 fragColor; + +/* TODO Move this to SSAO modules */ +/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer + * we change the factors from the article to fit the OpennGL model. */ +vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth) +{ + if (WinMatrix[3][3] == 0.0) { + /* Perspective */ + float d = 2.0 * depth - 1.0; + + float zview = -WinMatrix[3][2] / (d + WinMatrix[2][2]); + + return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz); + } + else { + /* Orthographic */ + vec3 offset = vec3(uvcoords, depth); + + return viewvecs[0].xyz + offset * viewvecs[1].xyz; + } +} + +#ifdef USE_HSV +void rgb_to_hsv(vec3 rgb, out vec3 outcol) +{ + float cmax, cmin, h, s, v, cdelta; + vec3 c; + + cmax = max(rgb[0], max(rgb[1], rgb[2])); + cmin = min(rgb[0], min(rgb[1], rgb[2])); + cdelta = cmax - cmin; + + v = cmax; + if (cmax != 0.0) + s = cdelta / cmax; + else { + s = 0.0; + h = 0.0; + } + + if (s == 0.0) { + h = 0.0; + } + else { + c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta; + + if (rgb.x == cmax) h = c[2] - c[1]; + else if (rgb.y == cmax) h = 2.0 + c[0] - c[2]; + else h = 4.0 + c[1] - c[0]; + + h /= 6.0; + + if (h < 0.0) + h += 1.0; + } + + outcol = vec3(h, s, v); +} + +void hsv_to_rgb(vec3 hsv, out vec3 outcol) +{ + float i, f, p, q, t, h, s, v; + vec3 rgb; + + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; + + if (s == 0.0) { + rgb = vec3(v, v, v); + } + else { + if (h == 1.0) + h = 0.0; + + h *= 6.0; + i = floor(h); + f = h - i; + rgb = vec3(f, f, f); + p = v * (1.0 - s); + q = v * (1.0 - (s * f)); + t = v * (1.0 - (s * (1.0 - f))); + + if (i == 0.0) rgb = vec3(v, t, p); + else if (i == 1.0) rgb = vec3(q, v, p); + else if (i == 2.0) rgb = vec3(p, v, t); + else if (i == 3.0) rgb = vec3(p, q, v); + else if (i == 4.0) rgb = vec3(t, p, v); + else rgb = vec3(v, p, q); + } + + outcol = rgb; +} + +void hue_sat(float hue, float sat, float value, inout vec3 col) +{ + vec3 hsv; + + rgb_to_hsv(col, hsv); + + hsv.x += hue; + hsv.x -= floor(hsv.x); + hsv.y *= sat; + hsv.y = clamp(hsv.y, 0.0, 1.0); + hsv.z *= value; + hsv.z = clamp(hsv.z, 0.0, 1.0); + + hsv_to_rgb(hsv, col); +} +#endif + +#ifdef USE_AO +/* Prototype */ +void ssao_factors( + in float depth, in vec3 normal, in vec3 position, in vec2 screenco, + out float cavities, out float edges); +#endif + +/* From http://aras-p.info/texts/CompactNormalStorage.html + * Using Method #4: Spheremap Transform */ +vec3 normal_decode(vec2 enc) +{ + vec2 fenc = enc * 4.0 - 2.0; + float f = dot(fenc, fenc); + float g = sqrt(1.0 - f / 4.0); + vec3 n; + n.xy = fenc*g; + n.z = 1 - f / 2; + return n; +} + +vec3 shade(vec3 N, vec3 position, float depth, vec2 screenco) +{ +#ifdef USE_ROTATION + /* Rotate texture coordinates */ + vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x); + vec2 texco = abs(vec2(dot(N.xy, matcap_rotation), dot(N.xy, rotY)) * .49 + 0.5); +#else + vec2 texco = abs(N.xy * .49 + 0.5); +#endif + vec3 col = texture(matcaps, vec3(texco, matcap_index)).rgb; + +#ifdef USE_AO + float cavity = 0.0, edges = 0.0; + ssao_factors(depth, N, position, screenco, cavity, edges); + + col *= mix(vec3(1.0), matcaps_color[int(matcap_index)].rgb, cavity); +#endif + +#ifdef USE_HSV + hue_sat(matcap_hsv.x, matcap_hsv.y, matcap_hsv.z, col); +#endif + +#ifdef USE_AO + /* Apply highlights after hue shift */ + col *= edges + 1.0; +#endif + + return col; +} + +void main() +{ + vec2 screenco = vec2(gl_FragCoord.xy) * invscreenres; + +#ifdef DEFERRED_SHADING + ivec2 texel = ivec2(gl_FragCoord.xy); + mat_id = texelFetch(idtex, texel, 0).r; + + /* early out (manual stencil test) */ + if (mat_id == 0) + discard; + + float depth = texelFetch(depthtex, texel, 0).r; + vec3 N = normal_decode(texelFetch(normaltex, texel, 0).rg); + /* see the prepass for explanations. */ + if (mat_id < 0) { + N = -N; + } + mat_id = abs(mat_id) - 1; +#else + float depth = gl_FragCoord.z; + vec3 N = normal; +#endif + + vec3 position = get_view_space_from_depth(screenco, depth); + + vec3 col = shade(N, position, depth, screenco); + + fragColor = vec4(col, 1.0); +} diff --git a/source/blender/draw/engines/clay/shaders/clay_fxaa.glsl b/source/blender/draw/engines/clay/shaders/clay_fxaa.glsl new file mode 100644 index 00000000000..924e51421aa --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/clay_fxaa.glsl @@ -0,0 +1,18 @@ + +in vec4 uvcoordsvar; +out vec4 fragColor; + +uniform vec2 invscreenres; +uniform sampler2D colortex; + +void main() +{ + fragColor = vec4(FxaaPixelShader( + uvcoordsvar.st, + colortex, + invscreenres, + 1.0, + 0.166, + 0.0833 + ).rgb, 1.0); +} diff --git a/source/blender/draw/engines/clay/shaders/clay_particle_strand_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_particle_strand_frag.glsl new file mode 100644 index 00000000000..980a1e4690d --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/clay_particle_strand_frag.glsl @@ -0,0 +1,144 @@ + +/* Material Parameters packed in an UBO */ +struct Material { + vec4 one; + vec4 two; +}; + +layout(std140) uniform material_block { + Material shader_param[MAX_MATERIAL]; +}; + +uniform mat4 ProjectionMatrix; +uniform sampler2DArray matcaps; +uniform int mat_id; + +#define randomness shader_param[mat_id].one.x +#define matcap_index shader_param[mat_id].one.y +#define matcap_rotation shader_param[mat_id].one.zw +#define matcap_hsv shader_param[mat_id].two.xyz + +in vec3 tangent; +in vec3 viewPosition; +flat in float colRand; +out vec4 fragColor; + +vec3 rotate(vec3 norm, vec3 ortho, float ang) +{ + return norm * cos(ang) + ortho * sin(ang); +} + +void rgb_to_hsv(vec3 rgb, out vec3 outcol) +{ + float cmax, cmin, h, s, v, cdelta; + vec3 c; + + cmax = max(rgb[0], max(rgb[1], rgb[2])); + cmin = min(rgb[0], min(rgb[1], rgb[2])); + cdelta = cmax - cmin; + + v = cmax; + if (cmax != 0.0) + s = cdelta / cmax; + else { + s = 0.0; + h = 0.0; + } + + if (s == 0.0) { + h = 0.0; + } + else { + c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta; + + if (rgb.x == cmax) h = c[2] - c[1]; + else if (rgb.y == cmax) h = 2.0 + c[0] - c[2]; + else h = 4.0 + c[1] - c[0]; + + h /= 6.0; + + if (h < 0.0) + h += 1.0; + } + + outcol = vec3(h, s, v); +} + +void hsv_to_rgb(vec3 hsv, out vec3 outcol) +{ + float i, f, p, q, t, h, s, v; + vec3 rgb; + + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; + + if (s == 0.0) { + rgb = vec3(v, v, v); + } + else { + if (h == 1.0) + h = 0.0; + + h *= 6.0; + i = floor(h); + f = h - i; + rgb = vec3(f, f, f); + p = v * (1.0 - s); + q = v * (1.0 - (s * f)); + t = v * (1.0 - (s * (1.0 - f))); + + if (i == 0.0) rgb = vec3(v, t, p); + else if (i == 1.0) rgb = vec3(q, v, p); + else if (i == 2.0) rgb = vec3(p, v, t); + else if (i == 3.0) rgb = vec3(p, q, v); + else if (i == 4.0) rgb = vec3(t, p, v); + else rgb = vec3(v, p, q); + } + + outcol = rgb; +} + +void hue_sat(float hue, float sat, float value, inout vec3 col) +{ + vec3 hsv; + + rgb_to_hsv(col, hsv); + + hsv.x += hue; + hsv.x -= floor(hsv.x); + hsv.y *= sat; + hsv.y = clamp(hsv.y, 0.0, 1.0); + hsv.z *= value; + hsv.z = clamp(hsv.z, 0.0, 1.0); + + hsv_to_rgb(hsv, col); +} + +void main() +{ + vec3 viewvec = (ProjectionMatrix[3][3] == 0.0) ? normalize(viewPosition) : vec3(0.0, 0.0, -1.0); + vec3 ortho = normalize(cross(viewvec, tangent)); + vec3 norm = normalize(cross(ortho, tangent)); + + vec3 col = vec3(0); + + vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x); + + for (int i = 0; i < 9; i++) { + vec3 rotNorm = rotate(norm, ortho, -0.5 + (i * 0.125)); + vec3 ray = reflect(viewvec, rotNorm); + vec2 texco = abs(vec2(dot(ray.xy, matcap_rotation), dot(ray.xy, rotY)) * .49 + 0.5); + + col += texture(matcaps, vec3(texco, matcap_index)).rgb / 9.0; + } + + hue_sat(matcap_hsv.x, matcap_hsv.y, matcap_hsv.z, col); + + float maxChan = max(max(col.r, col.g), col.b); + + col += (colRand * maxChan * randomness * 1.5) - (maxChan * randomness * 0.75); + + fragColor.rgb = col; + fragColor.a = 1.0; +} diff --git a/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl new file mode 100644 index 00000000000..d4c35d14182 --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl @@ -0,0 +1,34 @@ + +uniform mat4 ModelViewProjectionMatrix; +uniform mat3 NormalMatrix; +uniform mat4 ModelViewMatrix; + +in vec3 pos; +in vec3 nor; +in int ind; +out vec3 tangent; +out vec3 viewPosition; +flat out float colRand; + +float rand(int s) +{ + int seed = s * 1023423; + + seed = (seed ^ 61) ^ (seed >> 16); + seed *= 9; + seed = seed ^ (seed >> 4); + seed *= 0x27d4eb2d; + seed = seed ^ (seed >> 15); + + float value = float(seed); + value *= 1.0 / 42596.0; + return fract(value); +} + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + tangent = normalize(NormalMatrix * nor); + viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz; + colRand = rand(ind); +} diff --git a/source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl new file mode 100644 index 00000000000..f30322bc9fe --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/clay_prepass_frag.glsl @@ -0,0 +1,44 @@ +uniform int mat_id; + +#ifdef USE_FLAT_NORMAL +flat in vec3 normal; +#else +in vec3 normal; +#endif + +layout(location = 0) out vec2 outNormals; +layout(location = 1) out int outIndex; + +/* From http://aras-p.info/texts/CompactNormalStorage.html + * Using Method #4: Spheremap Transform */ +vec2 normal_encode(vec3 n) +{ + float p = sqrt(n.z * 8.0 + 8.0); + return n.xy / p + 0.5; +} + +/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ +#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0)) +const vec4 dither_mat[4] = vec4[4]( + vec4( P(0.0), P(8.0), P(2.0), P(10.0)), + vec4(P(12.0), P(4.0), P(14.0), P(6.0)), + vec4( P(3.0), P(11.0), P(1.0), P(9.0)), + vec4(P(15.0), P(7.0), P(13.0), P(5.0)) +); + +void main() { + outIndex = (mat_id + 1); /* 0 is clear color */ + /** + * To fix the normal buffer precision issue for backfaces, + * we invert normals and use the sign of the index buffer + * to tag them, and re-invert in deferred pass. + **/ + vec3 N = (gl_FrontFacing) ? normal : -normal; + outIndex = (gl_FrontFacing) ? outIndex : -outIndex; + + outNormals = normal_encode(N); + + /* Dither the output to fight low quality. */ + ivec2 tx = ivec2(gl_FragCoord.xy) % 4; + outNormals += dither_mat[tx.x][tx.y]; +} diff --git a/source/blender/draw/engines/clay/shaders/clay_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_vert.glsl new file mode 100644 index 00000000000..8f8866b3839 --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/clay_vert.glsl @@ -0,0 +1,17 @@ +uniform mat4 ModelViewProjectionMatrix; +uniform mat3 NormalMatrix; + +in vec3 pos; +in vec3 nor; + +#ifdef USE_FLAT_NORMAL +flat out vec3 normal; +#else +out vec3 normal; +#endif + +void main() +{ + normal = normalize(NormalMatrix * nor); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); +} diff --git a/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl new file mode 100644 index 00000000000..94e2d6f3c7b --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl @@ -0,0 +1,82 @@ +#define ssao_distance matcaps_param[mat_id].ssao_params_var.x +#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y +#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z +#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w + +/* from The Alchemy screen-space ambient obscurance algorithm + * http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */ + +void ssao_factors( + in float depth, in vec3 normal, in vec3 position, in vec2 screenco, + out float cavities, out float edges) +{ + cavities = edges = 0.0; + /* early out if there is no need for SSAO */ + if (ssao_factor_cavity == 0.0 && ssao_factor_edge == 0.0) + return; + + /* take the normalized ray direction here */ + vec3 noise = texture(ssao_jitter, screenco.xy * jitter_tilling).rgb; + + /* find the offset in screen space by multiplying a point + * in camera space at the depth of the point by the projection matrix. */ + vec2 offset; + float homcoord = WinMatrix[2][3] * position.z + WinMatrix[3][3]; + offset.x = WinMatrix[0][0] * ssao_distance / homcoord; + offset.y = WinMatrix[1][1] * ssao_distance / homcoord; + /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */ + offset *= 0.5; + + int num_samples = int(ssao_samples_num); + + /* Note. Putting noise usage here to put some ALU after texture fetch. */ + vec2 rotX = noise.rg; + vec2 rotY = vec2(-rotX.y, rotX.x); + + for (int x = 0; x < num_samples && x < 500; x++) { + /* ssao_samples[x].xy is sample direction (normalized). + * ssao_samples[x].z is sample distance from disk center. */ + + /* Rotate with random direction to get jittered result. */ + vec2 dir_jittered = vec2(dot(ssao_samples[x].xy, rotX), dot(ssao_samples[x].xy, rotY)); + dir_jittered.xy *= ssao_samples[x].z + noise.b; + + vec2 uvcoords = screenco.xy + dir_jittered * offset; + + if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0) + continue; + + float depth_new = texture(depthtex, uvcoords).r; + + /* Handle Background case */ + bool is_background = (depth_new == 1.0); + + /* This trick provide good edge effect even if no neighboor is found. */ + vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new); + + if (is_background) + pos_new.z -= ssao_distance; + + vec3 dir = pos_new - position; + float len = length(dir); + float f_cavities = dot(dir, normal); + float f_edge = -f_cavities; + float f_bias = 0.05 * len + 0.0001; + + float attenuation = 1.0 / (len * (1.0 + len * len * ssao_attenuation)); + + /* use minor bias here to avoid self shadowing */ + if (f_cavities > -f_bias) + cavities += f_cavities * attenuation; + + if (f_edge > f_bias) + edges += f_edge * attenuation; + } + + cavities /= ssao_samples_num; + edges /= ssao_samples_num; + + /* don't let cavity wash out the surface appearance */ + cavities = clamp(cavities * ssao_factor_cavity, 0.0, 1.0); + edges = edges * ssao_factor_edge; +} diff --git a/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl new file mode 100644 index 00000000000..9c203a4246c --- /dev/null +++ b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl @@ -0,0 +1,122 @@ +#define ssao_distance matcaps_param[mat_id].ssao_params_var.x +#define ssao_factor_cavity matcaps_param[mat_id].ssao_params_var.y +#define ssao_factor_edge matcaps_param[mat_id].ssao_params_var.z +#define ssao_attenuation matcaps_param[mat_id].ssao_params_var.w + +/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */ + +#define COSINE_WEIGHTING + +float integrate_arc(in float h1, in float h2, in float gamma, in float n_proj_len) +{ + float a = 0.0; +#ifdef COSINE_WEIGHTING + float cos_gamma = cos(gamma); + float sin_gamma_2 = 2.0 * sin(gamma); + a += -cos(2.0 * h1 - gamma) + cos_gamma + h1 * sin_gamma_2; + a += -cos(2.0 * h2 - gamma) + cos_gamma + h2 * sin_gamma_2; + a *= 0.25; /* 1/4 */ + a *= n_proj_len; +#else + /* Uniform weighting (slide 59) */ + a += 1 - cos(h1); + a += 1 - cos(h2); +#endif + return a; +} + +float get_max_horizon(in vec2 co, in vec3 x, in vec3 omega_o, in float h) +{ + if (co.x > 1.0 || co.x < 0.0 || co.y > 1.0 || co.y < 0.0) + return h; + + float depth = texture(depthtex, co).r; + + /* Background case */ + if (depth == 1.0) + return h; + + vec3 s = get_view_space_from_depth(co, depth); /* s View coordinate */ + vec3 omega_s = s - x; + float len = length(omega_s); + + if (len < ssao_distance) { + omega_s /= len; + h = max(h, dot(omega_s, omega_o)); + } + return h; +} + +void ssao_factors( + in float depth, in vec3 normal, in vec3 position, in vec2 screenco, + out float cavities, out float edges) +{ + /* Renaming */ + vec3 omega_o = -normalize(position); /* viewvec */ + vec2 x_ = screenco; /* x^ Screen coordinate */ + vec3 x = position; /* x view space coordinate */ + +#ifdef SPATIAL_DENOISE + float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3)); + float noise_offset = (1.0 / 4.0) * float(int(gl_FragCoord.y - gl_FragCoord.x) & 0x3); +#else + float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3)); + float noise_offset = (0.5 / 16.0) + (1.0 / 16.0) * float(((int(gl_FragCoord.x - gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3)); +#endif + + const float phi_step = 16.0; + const float theta_step = 16.0; + const float m_pi = 3.14159265358979323846; + vec2 pixel_ratio = vec2(screenres.y / screenres.x, 1.0); + vec2 pixel_size = vec2(1.0) / screenres.xy; + float min_stride = length(pixel_size); + float homcco = WinMatrix[2][3] * position.z + WinMatrix[3][3]; + float n = max(min_stride * theta_step, ssao_distance / homcco); /* Search distance */ + + /* Integral over PI */ + float A = 0.0; + for (float i = 0.0; i < phi_step; i++) { + float phi = m_pi * ((noise_dir + i) / phi_step); + + vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */ + + /* Search maximum horizon angles Theta1 and Theta2 */ + float theta1 = -1.0, theta2 = -1.0; /* init at cos(pi) */ + for (float j = 0.0; j < theta_step; j++) { + vec2 s_ = t_phi * pixel_ratio * n * ((j + noise_offset)/ theta_step); /* s^ Screen coordinate */ + vec2 co; + + co = x_ + s_; + theta1 = get_max_horizon(co, x, omega_o, theta1); + + co = x_ - s_; + theta2 = get_max_horizon(co, x, omega_o, theta2); + } + + /* (Slide 54) */ + theta1 = -acos(theta1); + theta2 = acos(theta2); + + /* Projecting Normal to Plane P defined by t_phi and omega_o */ + vec3 h = normalize(cross(vec3(t_phi, 0.0), omega_o)); /* Normal vector to Integration plane */ + vec3 t = cross(h, omega_o); /* Normal vector to plane */ + vec3 n_proj = normal - h * dot(normal, h); + float n_proj_len = length(n_proj); + vec3 n_proj_norm = normalize(n_proj); + + /* Clamping thetas (slide 58) */ + float gamma = sign(dot(n_proj_norm, t)) * acos(dot(normal, omega_o)); /* Angle between view vec and normal */ + theta1 = gamma + max(theta1 - gamma, -m_pi * 0.5); + theta2 = gamma + min(theta2 - gamma, m_pi * 0.5); + + /* Solving inner integral */ + A += integrate_arc(theta1, theta2, gamma, n_proj_len); + } + + A /= phi_step; + + cavities = 1.0 - A; + edges = 0.0; +} diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c new file mode 100644 index 00000000000..8be9c637fbc --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_bloom.c @@ -0,0 +1,336 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_bloom.c + * \ingroup draw_engine + * + * Eevee's bloom shader. + */ + +#include "DRW_render.h" + +#include "BLI_dynstr.h" + +#include "BKE_global.h" /* for G.debug_value */ + +#include "GPU_extensions.h" +#include "GPU_texture.h" + +#include "DEG_depsgraph_query.h" + +#include "eevee_private.h" + +static struct { + /* Bloom */ + struct GPUShader *bloom_blit_sh[2]; + struct GPUShader *bloom_downsample_sh[2]; + struct GPUShader *bloom_upsample_sh[2]; + struct GPUShader *bloom_resolve_sh[2]; +} e_data = {{NULL}}; /* Engine data */ + +extern char datatoc_effect_bloom_frag_glsl[]; + +static void eevee_create_shader_bloom(void) +{ + e_data.bloom_blit_sh[0] = DRW_shader_create_fullscreen( + datatoc_effect_bloom_frag_glsl, + "#define STEP_BLIT\n"); + e_data.bloom_blit_sh[1] = DRW_shader_create_fullscreen( + datatoc_effect_bloom_frag_glsl, + "#define STEP_BLIT\n" + "#define HIGH_QUALITY\n"); + + e_data.bloom_downsample_sh[0] = DRW_shader_create_fullscreen( + datatoc_effect_bloom_frag_glsl, + "#define STEP_DOWNSAMPLE\n"); + e_data.bloom_downsample_sh[1] = DRW_shader_create_fullscreen( + datatoc_effect_bloom_frag_glsl, + "#define STEP_DOWNSAMPLE\n" + "#define HIGH_QUALITY\n"); + + e_data.bloom_upsample_sh[0] = DRW_shader_create_fullscreen( + datatoc_effect_bloom_frag_glsl, + "#define STEP_UPSAMPLE\n"); + e_data.bloom_upsample_sh[1] = DRW_shader_create_fullscreen( + datatoc_effect_bloom_frag_glsl, + "#define STEP_UPSAMPLE\n" + "#define HIGH_QUALITY\n"); + + e_data.bloom_resolve_sh[0] = DRW_shader_create_fullscreen( + datatoc_effect_bloom_frag_glsl, + "#define STEP_RESOLVE\n"); + e_data.bloom_resolve_sh[1] = DRW_shader_create_fullscreen( + datatoc_effect_bloom_frag_glsl, + "#define STEP_RESOLVE\n" + "#define HIGH_QUALITY\n"); +} + +int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_EffectsInfo *effects = stl->effects; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + if (scene_eval->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) { + const float *viewport_size = DRW_viewport_size_get(); + + /* Shaders */ + if (!e_data.bloom_blit_sh[0]) { + eevee_create_shader_bloom(); + } + + /* Bloom */ + int blitsize[2], texsize[2]; + + /* Blit Buffer */ + effects->source_texel_size[0] = 1.0f / viewport_size[0]; + effects->source_texel_size[1] = 1.0f / viewport_size[1]; + + blitsize[0] = (int)viewport_size[0]; + blitsize[1] = (int)viewport_size[1]; + + effects->blit_texel_size[0] = 1.0f / (float)blitsize[0]; + effects->blit_texel_size[1] = 1.0f / (float)blitsize[1]; + + effects->bloom_blit = DRW_texture_pool_query_2D(blitsize[0], blitsize[1], GPU_R11F_G11F_B10F, + &draw_engine_eevee_type); + + GPU_framebuffer_ensure_config(&fbl->bloom_blit_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->bloom_blit) + }); + + /* Parameters */ + const float threshold = scene_eval->eevee.bloom_threshold; + const float knee = scene_eval->eevee.bloom_knee; + const float intensity = scene_eval->eevee.bloom_intensity; + const float *color = scene_eval->eevee.bloom_color; + const float radius = scene_eval->eevee.bloom_radius; + effects->bloom_clamp = scene_eval->eevee.bloom_clamp; + + /* determine the iteration count */ + const float minDim = (float)MIN2(blitsize[0], blitsize[1]); + const float maxIter = (radius - 8.0f) + log(minDim) / log(2); + const int maxIterInt = effects->bloom_iteration_ct = (int)maxIter; + + CLAMP(effects->bloom_iteration_ct, 1, MAX_BLOOM_STEP); + + effects->bloom_sample_scale = 0.5f + maxIter - (float)maxIterInt; + effects->bloom_curve_threshold[0] = threshold - knee; + effects->bloom_curve_threshold[1] = knee * 2.0f; + effects->bloom_curve_threshold[2] = 0.25f / max_ff(1e-5f, knee); + effects->bloom_curve_threshold[3] = threshold; + + mul_v3_v3fl(effects->bloom_color, color, intensity); + + /* Downsample buffers */ + copy_v2_v2_int(texsize, blitsize); + for (int i = 0; i < effects->bloom_iteration_ct; ++i) { + texsize[0] /= 2; texsize[1] /= 2; + + texsize[0] = MAX2(texsize[0], 2); + texsize[1] = MAX2(texsize[1], 2); + + effects->downsamp_texel_size[i][0] = 1.0f / (float)texsize[0]; + effects->downsamp_texel_size[i][1] = 1.0f / (float)texsize[1]; + + effects->bloom_downsample[i] = DRW_texture_pool_query_2D(texsize[0], texsize[1], GPU_R11F_G11F_B10F, + &draw_engine_eevee_type); + GPU_framebuffer_ensure_config(&fbl->bloom_down_fb[i], { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->bloom_downsample[i]) + }); + } + + /* Upsample buffers */ + copy_v2_v2_int(texsize, blitsize); + for (int i = 0; i < effects->bloom_iteration_ct - 1; ++i) { + texsize[0] /= 2; texsize[1] /= 2; + + texsize[0] = MAX2(texsize[0], 2); + texsize[1] = MAX2(texsize[1], 2); + + effects->bloom_upsample[i] = DRW_texture_pool_query_2D(texsize[0], texsize[1], GPU_R11F_G11F_B10F, + &draw_engine_eevee_type); + GPU_framebuffer_ensure_config(&fbl->bloom_accum_fb[i], { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->bloom_upsample[i]) + }); + } + + return EFFECT_BLOOM | EFFECT_POST_BUFFER; + } + + /* Cleanup to release memory */ + GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_blit_fb); + + for (int i = 0; i < MAX_BLOOM_STEP - 1; ++i) { + GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_down_fb[i]); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->bloom_accum_fb[i]); + } + + return 0; +} + +static DRWShadingGroup *eevee_create_bloom_pass( + const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample) +{ + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + + *pass = DRW_pass_create(name, DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, *pass); + DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_uniform_texture_ref(grp, "sourceBuffer", &effects->unf_source_buffer); + DRW_shgroup_uniform_vec2(grp, "sourceBufferTexelSize", effects->unf_source_texel_size, 1); + if (upsample) { + DRW_shgroup_uniform_texture_ref(grp, "baseBuffer", &effects->unf_base_buffer); + DRW_shgroup_uniform_float(grp, "sampleScale", &effects->bloom_sample_scale, 1); + } + + return grp; +} + +void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & EFFECT_BLOOM) != 0) { + /** Bloom algorithm + * + * Overview : + * - Downsample the color buffer doing a small blur during each step. + * - Accumulate bloom color using previously downsampled color buffers + * and do an upsample blur for each new accumulated layer. + * - Finally add accumulation buffer onto the source color buffer. + * + * [1/1] is original copy resolution (can be half or quater res for performance) + * + * [DOWNSAMPLE CHAIN] [UPSAMPLE CHAIN] + * + * Source Color ── [Blit] ──> Bright Color Extract [1/1] Final Color + * | Λ + * [Downsample First] Source Color ─> + [Resolve] + * v | + * Color Downsampled [1/2] ────────────> + Accumulation Buffer [1/2] + * | Λ + * ─── ─── + * Repeat Repeat + * ─── ─── + * v | + * Color Downsampled [1/N-1] ──────────> + Accumulation Buffer [1/N-1] + * | Λ + * [Downsample] [Upsample] + * v | + * Color Downsampled [1/N] ─────────────────────────┘ + **/ + DRWShadingGroup *grp; + const bool use_highres = true; + const bool use_antiflicker = true; + eevee_create_bloom_pass("Bloom Downsample First", effects, e_data.bloom_downsample_sh[use_antiflicker], &psl->bloom_downsample_first, false); + eevee_create_bloom_pass("Bloom Downsample", effects, e_data.bloom_downsample_sh[0], &psl->bloom_downsample, false); + eevee_create_bloom_pass("Bloom Upsample", effects, e_data.bloom_upsample_sh[use_highres], &psl->bloom_upsample, true); + + grp = eevee_create_bloom_pass("Bloom Blit", effects, e_data.bloom_blit_sh[use_antiflicker], &psl->bloom_blit, false); + DRW_shgroup_uniform_vec4(grp, "curveThreshold", effects->bloom_curve_threshold, 1); + DRW_shgroup_uniform_float(grp, "clampIntensity", &effects->bloom_clamp, 1); + + grp = eevee_create_bloom_pass("Bloom Resolve", effects, e_data.bloom_resolve_sh[use_highres], &psl->bloom_resolve, true); + DRW_shgroup_uniform_vec3(grp, "bloomColor", effects->bloom_color, 1); + } +} + +void EEVEE_bloom_draw(EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + /* Bloom */ + if ((effects->enabled_effects & EFFECT_BLOOM) != 0) { + struct GPUTexture *last; + + /* Extract bright pixels */ + copy_v2_v2(effects->unf_source_texel_size, effects->source_texel_size); + effects->unf_source_buffer = effects->source_buffer; + + GPU_framebuffer_bind(fbl->bloom_blit_fb); + DRW_draw_pass(psl->bloom_blit); + + /* Downsample */ + copy_v2_v2(effects->unf_source_texel_size, effects->blit_texel_size); + effects->unf_source_buffer = effects->bloom_blit; + + GPU_framebuffer_bind(fbl->bloom_down_fb[0]); + DRW_draw_pass(psl->bloom_downsample_first); + + last = effects->bloom_downsample[0]; + + for (int i = 1; i < effects->bloom_iteration_ct; ++i) { + copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i - 1]); + effects->unf_source_buffer = last; + + GPU_framebuffer_bind(fbl->bloom_down_fb[i]); + DRW_draw_pass(psl->bloom_downsample); + + /* Used in next loop */ + last = effects->bloom_downsample[i]; + } + + /* Upsample and accumulate */ + for (int i = effects->bloom_iteration_ct - 2; i >= 0; --i) { + copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i]); + effects->unf_source_buffer = effects->bloom_downsample[i]; + effects->unf_base_buffer = last; + + GPU_framebuffer_bind(fbl->bloom_accum_fb[i]); + DRW_draw_pass(psl->bloom_upsample); + + last = effects->bloom_upsample[i]; + } + + /* Resolve */ + copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[0]); + effects->unf_source_buffer = last; + effects->unf_base_buffer = effects->source_buffer; + + GPU_framebuffer_bind(effects->target_buffer); + DRW_draw_pass(psl->bloom_resolve); + SWAP_BUFFERS(); + } +} + +void EEVEE_bloom_free(void) +{ + for (int i = 0; i < 2; ++i) { + DRW_SHADER_FREE_SAFE(e_data.bloom_blit_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.bloom_downsample_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.bloom_upsample_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.bloom_resolve_sh[i]); + } +} diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c new file mode 100644 index 00000000000..e9883cc3054 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -0,0 +1,183 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_data.c + * \ingroup draw_engine + * + * All specific data handler for Objects, Lights, ViewLayers, ... + */ + +#include "DRW_render.h" + +#include "eevee_private.h" + +static void eevee_view_layer_data_free(void *storage) +{ + EEVEE_ViewLayerData *sldata = (EEVEE_ViewLayerData *)storage; + + /* Lights */ + MEM_SAFE_FREE(sldata->lamps); + DRW_UBO_FREE_SAFE(sldata->light_ubo); + DRW_UBO_FREE_SAFE(sldata->shadow_ubo); + DRW_UBO_FREE_SAFE(sldata->shadow_render_ubo); + GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_target_fb); + GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cube_store_fb); + GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cascade_target_fb); + GPU_FRAMEBUFFER_FREE_SAFE(sldata->shadow_cascade_store_fb); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_pool); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_pool); + MEM_SAFE_FREE(sldata->shcasters_buffers[0].shadow_casters); + MEM_SAFE_FREE(sldata->shcasters_buffers[0].flags); + MEM_SAFE_FREE(sldata->shcasters_buffers[1].shadow_casters); + MEM_SAFE_FREE(sldata->shcasters_buffers[1].flags); + + /* Probes */ + MEM_SAFE_FREE(sldata->probes); + DRW_UBO_FREE_SAFE(sldata->probe_ubo); + DRW_UBO_FREE_SAFE(sldata->grid_ubo); + DRW_UBO_FREE_SAFE(sldata->planar_ubo); + DRW_UBO_FREE_SAFE(sldata->common_ubo); + DRW_UBO_FREE_SAFE(sldata->clip_ubo); + GPU_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb); + for (int i = 0; i < 6; ++i) { + GPU_FRAMEBUFFER_FREE_SAFE(sldata->probe_face_fb[i]); + } + DRW_TEXTURE_FREE_SAFE(sldata->probe_rt); + DRW_TEXTURE_FREE_SAFE(sldata->probe_depth_rt); + DRW_TEXTURE_FREE_SAFE(sldata->probe_pool); + DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool); + DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt); +} + +EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void) +{ + return (EEVEE_ViewLayerData *)DRW_view_layer_engine_data_get( + &draw_engine_eevee_type); +} + +EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void) +{ + EEVEE_ViewLayerData **sldata = (EEVEE_ViewLayerData **)DRW_view_layer_engine_data_ensure( + &draw_engine_eevee_type, &eevee_view_layer_data_free); + + if (*sldata == NULL) { + *sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData"); + } + + return *sldata; +} + +/* Object data. */ + +static void eevee_object_data_init(ObjectEngineData *engine_data) +{ + EEVEE_ObjectEngineData *eevee_data = (EEVEE_ObjectEngineData *)engine_data; + eevee_data->shadow_caster_id = -1; +} + +EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob) +{ + if (ELEM(ob->type, OB_LIGHTPROBE, OB_LAMP)) { + return NULL; + } + return (EEVEE_ObjectEngineData *)DRW_object_engine_data_get( + ob, &draw_engine_eevee_type); +} + +EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob) +{ + BLI_assert(!ELEM(ob->type, OB_LIGHTPROBE, OB_LAMP)); + return (EEVEE_ObjectEngineData *)DRW_object_engine_data_ensure( + ob, + &draw_engine_eevee_type, + sizeof(EEVEE_ObjectEngineData), + eevee_object_data_init, + NULL); +} + +/* Light probe data. */ + +static void eevee_lightprobe_data_init(ObjectEngineData *engine_data) +{ + EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)engine_data; + ped->need_full_update = true; + ped->need_update = true; +} + +static void eevee_lightprobe_data_free(ObjectEngineData *engine_data) +{ + EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)engine_data; + + BLI_freelistN(&ped->captured_object_list); +} + +EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob) +{ + if (ob->type != OB_LIGHTPROBE) { + return NULL; + } + return (EEVEE_LightProbeEngineData *)DRW_object_engine_data_get( + ob, &draw_engine_eevee_type); +} + +EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob) +{ + BLI_assert(ob->type == OB_LIGHTPROBE); + return (EEVEE_LightProbeEngineData *)DRW_object_engine_data_ensure( + ob, + &draw_engine_eevee_type, + sizeof(EEVEE_LightProbeEngineData), + eevee_lightprobe_data_init, + eevee_lightprobe_data_free); +} + +/* Lamp data. */ + +static void eevee_lamp_data_init(ObjectEngineData *engine_data) +{ + EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)engine_data; + led->need_update = true; + led->prev_cube_shadow_id = -1; +} + +EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob) +{ + if (ob->type != OB_LAMP) { + return NULL; + } + return (EEVEE_LampEngineData *)DRW_object_engine_data_get( + ob, &draw_engine_eevee_type); +} + +EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob) +{ + BLI_assert(ob->type == OB_LAMP); + return (EEVEE_LampEngineData *)DRW_object_engine_data_ensure( + ob, + &draw_engine_eevee_type, + sizeof(EEVEE_LampEngineData), + eevee_lamp_data_init, + NULL); +} diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c new file mode 100644 index 00000000000..60c6175f4fa --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -0,0 +1,264 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_depth_of_field.c + * \ingroup draw_engine + * + * Depth of field post process effect. + */ + +#include "DRW_render.h" + +#include "BLI_dynstr.h" +#include "BLI_rand.h" + +#include "DNA_anim_types.h" +#include "DNA_camera_types.h" +#include "DNA_object_force_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BKE_global.h" /* for G.debug_value */ +#include "BKE_camera.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_animsys.h" +#include "BKE_screen.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "eevee_private.h" +#include "GPU_extensions.h" +#include "GPU_framebuffer.h" +#include "GPU_texture.h" + +#include "ED_screen.h" + +static struct { + /* Depth Of Field */ + struct GPUShader *dof_downsample_sh; + struct GPUShader *dof_scatter_sh; + struct GPUShader *dof_resolve_sh; +} e_data = {NULL}; /* Engine data */ + +extern char datatoc_effect_dof_vert_glsl[]; +extern char datatoc_effect_dof_frag_glsl[]; + +static void eevee_create_shader_depth_of_field(void) +{ + e_data.dof_downsample_sh = DRW_shader_create_fullscreen( + datatoc_effect_dof_frag_glsl, "#define STEP_DOWNSAMPLE\n"); + e_data.dof_scatter_sh = DRW_shader_create( + datatoc_effect_dof_vert_glsl, NULL, + datatoc_effect_dof_frag_glsl, "#define STEP_SCATTER\n"); + e_data.dof_resolve_sh = DRW_shader_create_fullscreen( + datatoc_effect_dof_frag_glsl, "#define STEP_RESOLVE\n"); +} + +int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_EffectsInfo *effects = stl->effects; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + if (scene_eval->eevee.flag & SCE_EEVEE_DOF_ENABLED) { + RegionView3D *rv3d = draw_ctx->rv3d; + + if (!e_data.dof_downsample_sh) { + eevee_create_shader_depth_of_field(); + } + + if (camera) { + const float *viewport_size = DRW_viewport_size_get(); + Camera *cam = (Camera *)camera->data; + + /* Retreive Near and Far distance */ + effects->dof_near_far[0] = -cam->clipsta; + effects->dof_near_far[1] = -cam->clipend; + + int buffer_size[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2}; + + effects->dof_down_near = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], GPU_R11F_G11F_B10F, + &draw_engine_eevee_type); + effects->dof_down_far = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], GPU_R11F_G11F_B10F, + &draw_engine_eevee_type); + effects->dof_coc = DRW_texture_pool_query_2D(buffer_size[0], buffer_size[1], GPU_RG16F, + &draw_engine_eevee_type); + + GPU_framebuffer_ensure_config(&fbl->dof_down_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->dof_down_near), + GPU_ATTACHMENT_TEXTURE(effects->dof_down_far), + GPU_ATTACHMENT_TEXTURE(effects->dof_coc) + }); + + /* Go full 32bits for rendering and reduce the color artifacts. */ + GPUTextureFormat fb_format = DRW_state_is_image_render() ? GPU_RGBA32F : GPU_RGBA16F; + + effects->dof_blur = DRW_texture_pool_query_2D(buffer_size[0] * 2, buffer_size[1], fb_format, + &draw_engine_eevee_type); + GPU_framebuffer_ensure_config(&fbl->dof_scatter_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->dof_blur), + }); + + /* Parameters */ + /* TODO UI Options */ + float fstop = cam->gpu_dof.fstop; + float blades = cam->gpu_dof.num_blades; + float rotation = cam->gpu_dof.rotation; + float ratio = 1.0f / cam->gpu_dof.ratio; + float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); + float focus_dist = BKE_camera_object_dof_distance(camera); + float focal_len = cam->lens; + + /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm + * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though + * because the shader reads coordinates in world space, which is in blender units. + * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */ + float scale = (scene_eval->unit.system) ? scene_eval->unit.scale_length : 1.0f; + float scale_camera = 0.001f / scale; + /* we want radius here for the aperture number */ + float aperture = 0.5f * scale_camera * focal_len / fstop; + float focal_len_scaled = scale_camera * focal_len; + float sensor_scaled = scale_camera * sensor; + + if (rv3d != NULL) { + sensor_scaled *= rv3d->viewcamtexcofac[0]; + } + + effects->dof_params[0] = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled)); + effects->dof_params[1] = -focus_dist; + effects->dof_params[2] = viewport_size[0] / sensor_scaled; + effects->dof_bokeh[0] = rotation; + effects->dof_bokeh[1] = ratio; + effects->dof_bokeh[2] = scene_eval->eevee.bokeh_max_size; + + /* Precompute values to save instructions in fragment shader. */ + effects->dof_bokeh_sides[0] = blades; + effects->dof_bokeh_sides[1] = 2.0f * M_PI / blades; + effects->dof_bokeh_sides[2] = blades / (2.0f * M_PI); + effects->dof_bokeh_sides[3] = cosf(M_PI / blades); + + return EFFECT_DOF | EFFECT_POST_BUFFER; + } + } + + /* Cleanup to release memory */ + GPU_FRAMEBUFFER_FREE_SAFE(fbl->dof_down_fb); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->dof_scatter_fb); + + return 0; +} + +void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + if ((effects->enabled_effects & EFFECT_DOF) != 0) { + /** Depth of Field algorithm + * + * Overview : + * - Downsample the color buffer into 2 buffers weighted with + * CoC values. Also output CoC into a texture. + * - Shoot quads for every pixel and expand it depending on the CoC. + * Do one pass for near Dof and one pass for far Dof. + * - Finally composite the 2 blurred buffers with the original render. + **/ + DRWShadingGroup *grp; + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + + psl->dof_down = DRW_pass_create("DoF Downsample", DRW_STATE_WRITE_COLOR); + + grp = DRW_shgroup_create(e_data.dof_downsample_sh, psl->dof_down); + DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1); + DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->dof_scatter = DRW_pass_create("DoF Scatter", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL); + + /* This create an empty batch of N triangles to be positioned + * by the vertex shader 0.4ms against 6ms with instancing */ + const float *viewport_size = DRW_viewport_size_get(); + const int sprite_ct = ((int)viewport_size[0] / 2) * ((int)viewport_size[1] / 2); /* brackets matters */ + grp = DRW_shgroup_empty_tri_batch_create(e_data.dof_scatter_sh, psl->dof_scatter, sprite_ct); + + DRW_shgroup_uniform_texture_ref(grp, "nearBuffer", &effects->dof_down_near); + DRW_shgroup_uniform_texture_ref(grp, "farBuffer", &effects->dof_down_far); + DRW_shgroup_uniform_texture_ref(grp, "cocBuffer", &effects->dof_coc); + DRW_shgroup_uniform_vec4(grp, "bokehParams", effects->dof_bokeh, 2); + + psl->dof_resolve = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR); + + grp = DRW_shgroup_create(e_data.dof_resolve_sh, psl->dof_resolve); + DRW_shgroup_uniform_texture_ref(grp, "scatterBuffer", &effects->dof_blur); + DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1); + DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1); + DRW_shgroup_call_add(grp, quad, NULL); + } +} + +void EEVEE_depth_of_field_draw(EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + /* Depth Of Field */ + if ((effects->enabled_effects & EFFECT_DOF) != 0) { + float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Downsample */ + GPU_framebuffer_bind(fbl->dof_down_fb); + DRW_draw_pass(psl->dof_down); + + /* Scatter */ + GPU_framebuffer_bind(fbl->dof_scatter_fb); + GPU_framebuffer_clear_color(fbl->dof_scatter_fb, clear_col); + DRW_draw_pass(psl->dof_scatter); + + /* Resolve */ + GPU_framebuffer_bind(effects->target_buffer); + DRW_draw_pass(psl->dof_resolve); + SWAP_BUFFERS(); + } +} + +void EEVEE_depth_of_field_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.dof_downsample_sh); + DRW_SHADER_FREE_SAFE(e_data.dof_scatter_sh); + DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh); +} diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c new file mode 100644 index 00000000000..d7a978066d5 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -0,0 +1,561 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_effects.c + * \ingroup draw_engine + * + * Gather all screen space effects technique such as Bloom, Motion Blur, DoF, SSAO, SSR, ... + */ + +#include "DRW_render.h" + +#include "BKE_global.h" /* for G.debug_value */ + +#include "BLI_string_utils.h" + +#include "eevee_private.h" +#include "GPU_texture.h" +#include "GPU_extensions.h" + +static struct { + /* Downsample Depth */ + struct GPUShader *minz_downlevel_sh; + struct GPUShader *maxz_downlevel_sh; + struct GPUShader *minz_downdepth_sh; + struct GPUShader *maxz_downdepth_sh; + struct GPUShader *minz_downdepth_layer_sh; + struct GPUShader *maxz_downdepth_layer_sh; + struct GPUShader *minz_copydepth_sh; + struct GPUShader *maxz_copydepth_sh; + + /* Simple Downsample */ + struct GPUShader *downsample_sh; + struct GPUShader *downsample_cube_sh; + + /* Velocity Resolve */ + struct GPUShader *velocity_resolve_sh; + + /* Theses are just references, not actually allocated */ + struct GPUTexture *depth_src; + struct GPUTexture *color_src; + + int depth_src_layer; + float cube_texel_size; +} e_data = {NULL}; /* Engine data */ + +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_effect_velocity_resolve_frag_glsl[]; +extern char datatoc_effect_minmaxz_frag_glsl[]; +extern char datatoc_effect_downsample_frag_glsl[]; +extern char datatoc_effect_downsample_cube_frag_glsl[]; +extern char datatoc_lightprobe_vert_glsl[]; +extern char datatoc_lightprobe_geom_glsl[]; + +static void eevee_create_shader_downsample(void) +{ + char *frag_str = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_common_view_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_effect_velocity_resolve_frag_glsl); + + e_data.velocity_resolve_sh = DRW_shader_create_fullscreen(frag_str, NULL); + + MEM_freeN(frag_str); + + e_data.downsample_sh = DRW_shader_create_fullscreen(datatoc_effect_downsample_frag_glsl, NULL); + e_data.downsample_cube_sh = DRW_shader_create( + datatoc_lightprobe_vert_glsl, + datatoc_lightprobe_geom_glsl, + datatoc_effect_downsample_cube_frag_glsl, NULL); + + e_data.minz_downlevel_sh = DRW_shader_create_fullscreen( + datatoc_effect_minmaxz_frag_glsl, + "#define MIN_PASS\n"); + e_data.maxz_downlevel_sh = DRW_shader_create_fullscreen( + datatoc_effect_minmaxz_frag_glsl, + "#define MAX_PASS\n"); + e_data.minz_downdepth_sh = DRW_shader_create_fullscreen( + datatoc_effect_minmaxz_frag_glsl, + "#define MIN_PASS\n"); + e_data.maxz_downdepth_sh = DRW_shader_create_fullscreen( + datatoc_effect_minmaxz_frag_glsl, + "#define MAX_PASS\n"); + e_data.minz_downdepth_layer_sh = DRW_shader_create_fullscreen( + datatoc_effect_minmaxz_frag_glsl, + "#define MIN_PASS\n" + "#define LAYERED\n"); + e_data.maxz_downdepth_layer_sh = DRW_shader_create_fullscreen( + datatoc_effect_minmaxz_frag_glsl, + "#define MAX_PASS\n" + "#define LAYERED\n"); + e_data.minz_copydepth_sh = DRW_shader_create_fullscreen( + datatoc_effect_minmaxz_frag_glsl, + "#define MIN_PASS\n" + "#define COPY_DEPTH\n"); + e_data.maxz_copydepth_sh = DRW_shader_create_fullscreen( + datatoc_effect_minmaxz_frag_glsl, + "#define MAX_PASS\n" + "#define COPY_DEPTH\n"); +} + +void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + + const float *viewport_size = DRW_viewport_size_get(); + int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + /* Shaders */ + if (!e_data.downsample_sh) { + eevee_create_shader_downsample(); + } + + if (!stl->effects) { + stl->effects = MEM_callocN(sizeof(EEVEE_EffectsInfo), "EEVEE_EffectsInfo"); + } + + effects = stl->effects; + + effects->enabled_effects = 0; + effects->enabled_effects |= (G.debug_value == 9) ? EFFECT_VELOCITY_BUFFER : 0; + effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata, camera); + effects->enabled_effects |= EEVEE_bloom_init(sldata, vedata); + effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata, camera); + effects->enabled_effects |= EEVEE_temporal_sampling_init(sldata, vedata); + effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata); + effects->enabled_effects |= EEVEE_subsurface_init(sldata, vedata); + effects->enabled_effects |= EEVEE_screen_raytrace_init(sldata, vedata); + effects->enabled_effects |= EEVEE_volumes_init(sldata, vedata); + + /* Force normal buffer creation. */ + if (DRW_state_is_image_render() && + (view_layer->passflag & SCE_PASS_NORMAL) != 0) + { + effects->enabled_effects |= EFFECT_NORMAL_BUFFER; + } + + /** + * Ping Pong buffer + */ + if ((effects->enabled_effects & EFFECT_POST_BUFFER) != 0) { + DRW_texture_ensure_fullscreen_2D(&txl->color_post, GPU_RGBA16F, DRW_TEX_FILTER | DRW_TEX_MIPMAP); + + GPU_framebuffer_ensure_config(&fbl->effect_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(txl->color_post), + }); + + GPU_framebuffer_ensure_config(&fbl->effect_color_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->color_post), + }); + } + else { + /* Cleanup to release memory */ + DRW_TEXTURE_FREE_SAFE(txl->color_post); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->effect_fb); + } + + /** + * MinMax Pyramid + */ + int size[2]; + size[0] = max_ii(size_fs[0] / 2, 1); + size[1] = max_ii(size_fs[1] / 2, 1); + + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { + /* Intel gpu seems to have problem rendering to only depth format */ + DRW_texture_ensure_2D(&txl->maxzbuffer, size[0], size[1], GPU_R32F, DRW_TEX_MIPMAP); + } + else { + DRW_texture_ensure_2D(&txl->maxzbuffer, size[0], size[1], GPU_DEPTH_COMPONENT24, DRW_TEX_MIPMAP); + } + + if (fbl->downsample_fb == NULL) { + fbl->downsample_fb = GPU_framebuffer_create(); + } + + /** + * Compute Mipmap texel alignement. + */ + for (int i = 0; i < 10; ++i) { + float mip_size[2] = {viewport_size[0], viewport_size[1]}; + for (int j = 0; j < i; ++j) { + mip_size[0] = floorf(fmaxf(1.0f, mip_size[0] / 2.0f)); + mip_size[1] = floorf(fmaxf(1.0f, mip_size[1] / 2.0f)); + } + common_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, floorf(log2f(floorf(viewport_size[0] / mip_size[0]))))); + common_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, floorf(log2f(floorf(viewport_size[1] / mip_size[1]))))); + } + + + /** + * Normal buffer for deferred passes. + */ + if ((effects->enabled_effects & EFFECT_NORMAL_BUFFER) != 0) { + effects->ssr_normal_input = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], GPU_RG16, + &draw_engine_eevee_type); + + GPU_framebuffer_texture_attach(fbl->main_fb, effects->ssr_normal_input, 1, 0); + } + else { + effects->ssr_normal_input = NULL; + } + + /** + * Motion vector buffer for correct TAA / motion blur. + */ + if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { + effects->velocity_tx = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], GPU_RG16, + &draw_engine_eevee_type); + + /* TODO output objects velocity during the mainpass. */ + // GPU_framebuffer_texture_attach(fbl->main_fb, effects->velocity_tx, 1, 0); + + GPU_framebuffer_ensure_config(&fbl->velocity_resolve_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->velocity_tx) + }); + } + else { + effects->velocity_tx = NULL; + } + + /** + * Setup depth double buffer. + */ + if ((effects->enabled_effects & EFFECT_DEPTH_DOUBLE_BUFFER) != 0) { + DRW_texture_ensure_fullscreen_2D(&txl->depth_double_buffer, GPU_DEPTH24_STENCIL8, 0); + + GPU_framebuffer_ensure_config(&fbl->double_buffer_depth_fb, { + GPU_ATTACHMENT_TEXTURE(txl->depth_double_buffer) + }); + } + else { + /* Cleanup to release memory */ + DRW_TEXTURE_FREE_SAFE(txl->depth_double_buffer); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_depth_fb); + } + + /** + * Setup double buffer so we can access last frame as it was before post processes. + */ + if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) { + DRW_texture_ensure_fullscreen_2D(&txl->color_double_buffer, GPU_RGBA16F, DRW_TEX_FILTER | DRW_TEX_MIPMAP); + + GPU_framebuffer_ensure_config(&fbl->double_buffer_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(txl->color_double_buffer) + }); + + GPU_framebuffer_ensure_config(&fbl->double_buffer_color_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->color_double_buffer) + }); + } + else { + /* Cleanup to release memory */ + DRW_TEXTURE_FREE_SAFE(txl->color_double_buffer); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_fb); + } +} + +void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + int downsample_write = DRW_STATE_WRITE_DEPTH; + + /* Intel gpu seems to have problem rendering to only depth format. + * Use color texture instead. */ + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { + downsample_write = DRW_STATE_WRITE_COLOR; + } + + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + + { + psl->color_downsample_ps = DRW_pass_create( + "Downsample", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps); + DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src); + DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1); + DRW_shgroup_call_add(grp, quad, NULL); + } + + { + static int zero = 0; + static uint six = 6; + psl->color_downsample_cube_ps = DRW_pass_create( + "Downsample Cube", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps); + DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src); + DRW_shgroup_uniform_float(grp, "texelSize", &e_data.cube_texel_size, 1); + DRW_shgroup_uniform_int(grp, "Layer", &zero, 1); + DRW_shgroup_call_instances_add(grp, quad, NULL, &six); + } + + { + /* Perform min/max downsample */ + DRWShadingGroup *grp; + + psl->maxz_downlevel_ps = DRW_pass_create( + "HiZ Max Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS); + grp = DRW_shgroup_create(e_data.maxz_downlevel_sh, psl->maxz_downlevel_ps); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &txl->maxzbuffer); + DRW_shgroup_call_add(grp, quad, NULL); + + /* Copy depth buffer to halfres top level of HiZ */ + + psl->maxz_downdepth_ps = DRW_pass_create( + "HiZ Max Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); + grp = DRW_shgroup_create(e_data.maxz_downdepth_sh, psl->maxz_downdepth_ps); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->maxz_downdepth_layer_ps = DRW_pass_create( + "HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); + grp = DRW_shgroup_create(e_data.maxz_downdepth_layer_sh, psl->maxz_downdepth_layer_ps); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); + DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->maxz_copydepth_ps = DRW_pass_create( + "HiZ Max Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS); + grp = DRW_shgroup_create(e_data.maxz_copydepth_sh, psl->maxz_copydepth_ps); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); + DRW_shgroup_call_add(grp, quad, NULL); + } + + if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { + /* This pass compute camera motions to the non moving objects. */ + psl->velocity_resolve = DRW_pass_create( + "Velocity Resolve", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.velocity_resolve_sh, psl->velocity_resolve); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv); + DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat); + DRW_shgroup_call_add(grp, quad, NULL); + } +} + +#if 0 /* Not required for now */ +static void min_downsample_cb(void *vedata, int UNUSED(level)) +{ + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + DRW_draw_pass(psl->minz_downlevel_ps); +} +#endif + +static void max_downsample_cb(void *vedata, int UNUSED(level)) +{ + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + DRW_draw_pass(psl->maxz_downlevel_ps); +} + +static void simple_downsample_cb(void *vedata, int UNUSED(level)) +{ + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + DRW_draw_pass(psl->color_downsample_ps); +} + +static void simple_downsample_cube_cb(void *vedata, int level) +{ + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + e_data.cube_texel_size = (float)(1 << level) / (float)GPU_texture_width(e_data.color_src); + DRW_draw_pass(psl->color_downsample_cube_ps); +} + +void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int layer) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + + e_data.depth_src = depth_src; + e_data.depth_src_layer = layer; + +#if 0 /* Not required for now */ + DRW_stats_group_start("Min buffer"); + /* Copy depth buffer to min texture top level */ + GPU_framebuffer_texture_attach(fbl->downsample_fb, stl->g_data->minzbuffer, 0, 0); + GPU_framebuffer_bind(fbl->downsample_fb); + if (layer >= 0) { + DRW_draw_pass(psl->minz_downdepth_layer_ps); + } + else { + DRW_draw_pass(psl->minz_downdepth_ps); + } + GPU_framebuffer_texture_detach(stl->g_data->minzbuffer); + + /* Create lower levels */ + GPU_framebuffer_recursive_downsample(fbl->downsample_fb, stl->g_data->minzbuffer, 8, &min_downsample_cb, vedata); + DRW_stats_group_end(); +#endif + + DRW_stats_group_start("Max buffer"); + /* Copy depth buffer to max texture top level */ + GPU_framebuffer_texture_attach(fbl->downsample_fb, txl->maxzbuffer, 0, 0); + GPU_framebuffer_bind(fbl->downsample_fb); + if (layer >= 0) { + DRW_draw_pass(psl->maxz_downdepth_layer_ps); + } + else { + DRW_draw_pass(psl->maxz_downdepth_ps); + } + + /* Create lower levels */ + GPU_framebuffer_recursive_downsample(fbl->downsample_fb, 8, &max_downsample_cb, vedata); + GPU_framebuffer_texture_detach(fbl->downsample_fb, txl->maxzbuffer); + DRW_stats_group_end(); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); +} + +/** + * Simple downsampling algorithm. Reconstruct mip chain up to mip level. + **/ +void EEVEE_downsample_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + e_data.color_src = texture_src; + + /* Create lower levels */ + DRW_stats_group_start("Downsample buffer"); + GPU_framebuffer_texture_attach(fbl->downsample_fb, texture_src, 0, 0); + GPU_framebuffer_recursive_downsample(fbl->downsample_fb, level, &simple_downsample_cb, vedata); + GPU_framebuffer_texture_detach(fbl->downsample_fb, texture_src); + DRW_stats_group_end(); +} + +/** + * Simple downsampling algorithm for cubemap. Reconstruct mip chain up to mip level. + **/ +void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + e_data.color_src = texture_src; + + /* Create lower levels */ + DRW_stats_group_start("Downsample Cube buffer"); + GPU_framebuffer_texture_attach(fbl->downsample_fb, texture_src, 0, 0); + GPU_framebuffer_recursive_downsample(fbl->downsample_fb, level, &simple_downsample_cube_cb, vedata); + GPU_framebuffer_texture_detach(fbl->downsample_fb, texture_src); + DRW_stats_group_end(); +} + +void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + /* First resolve the velocity. */ + if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { + DRW_viewport_matrix_get(effects->velocity_curr_persinv, DRW_MAT_PERSINV); + + GPU_framebuffer_bind(fbl->velocity_resolve_fb); + DRW_draw_pass(psl->velocity_resolve); + } + DRW_viewport_matrix_get(effects->velocity_past_persmat, DRW_MAT_PERS); + + /* only once per frame after the first post process */ + effects->swap_double_buffer = ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0); + + /* Init pointers */ + effects->source_buffer = txl->color; /* latest updated texture */ + effects->target_buffer = fbl->effect_color_fb; /* next target to render to */ + + /* Temporal Anti-Aliasing MUST come first */ + EEVEE_temporal_sampling_draw(vedata); + + /* Post process stack (order matters) */ + EEVEE_motion_blur_draw(vedata); + EEVEE_depth_of_field_draw(vedata); + EEVEE_bloom_draw(vedata); + + /* Save the final texture and framebuffer for final transformation or read. */ + effects->final_tx = effects->source_buffer; + effects->final_fb = (effects->target_buffer != fbl->main_color_fb) ? fbl->main_fb : fbl->effect_fb; + if ((effects->enabled_effects & EFFECT_TAA) && + (effects->enabled_effects & (EFFECT_BLOOM | EFFECT_DOF | EFFECT_MOTION_BLUR)) == 0) + { + if (!effects->swap_double_buffer) { + effects->final_fb = fbl->double_buffer_fb; + } + else { + effects->final_fb = fbl->main_fb; + } + } + + /* If no post processes is enabled, buffers are still not swapped, do it now. */ + SWAP_DOUBLE_BUFFERS(); + + if (!stl->g_data->valid_double_buffer && + ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) && + (DRW_state_is_image_render() == false)) + { + /* If history buffer is not valid request another frame. + * This fix black reflections on area resize. */ + DRW_viewport_request_redraw(); + } + + /* Record pers matrix for the next frame. */ + DRW_viewport_matrix_get(stl->effects->prev_persmat, DRW_MAT_PERS); + + /* Update double buffer status if render mode. */ + if (DRW_state_is_image_render()) { + stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL); + } +} + +void EEVEE_effects_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh); + + DRW_SHADER_FREE_SAFE(e_data.downsample_sh); + DRW_SHADER_FREE_SAFE(e_data.downsample_cube_sh); + + DRW_SHADER_FREE_SAFE(e_data.minz_downlevel_sh); + DRW_SHADER_FREE_SAFE(e_data.maxz_downlevel_sh); + DRW_SHADER_FREE_SAFE(e_data.minz_downdepth_sh); + DRW_SHADER_FREE_SAFE(e_data.maxz_downdepth_sh); + DRW_SHADER_FREE_SAFE(e_data.minz_downdepth_layer_sh); + DRW_SHADER_FREE_SAFE(e_data.maxz_downdepth_layer_sh); + DRW_SHADER_FREE_SAFE(e_data.minz_copydepth_sh); + DRW_SHADER_FREE_SAFE(e_data.maxz_copydepth_sh); +} diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c new file mode 100644 index 00000000000..9147a332764 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -0,0 +1,463 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_engine.c + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "BLI_dynstr.h" +#include "BLI_rand.h" + +#include "BKE_object.h" +#include "BKE_global.h" /* for G.debug_value */ +#include "BKE_screen.h" + +#include "DNA_world_types.h" + +#include "ED_screen.h" + +#include "GPU_material.h" +#include "GPU_glew.h" + +#include "eevee_engine.h" +#include "eevee_private.h" + +#define EEVEE_ENGINE "BLENDER_EEVEE" + +extern GlobalsUboStorage ts; + +/* *********** FUNCTIONS *********** */ + +static void eevee_engine_init(void *ved) +{ + EEVEE_Data *vedata = (EEVEE_Data *)ved; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + RegionView3D *rv3d = draw_ctx->rv3d; + Object *camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); + } + stl->g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f; + stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL); + + /* Main Buffer */ + DRW_texture_ensure_fullscreen_2D(&txl->color, GPU_RGBA16F, DRW_TEX_FILTER | DRW_TEX_MIPMAP); + + GPU_framebuffer_ensure_config(&fbl->main_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(txl->color), + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE + }); + + GPU_framebuffer_ensure_config(&fbl->main_color_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->color) + }); + + if (sldata->common_ubo == NULL) { + sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data); + } + if (sldata->clip_ubo == NULL) { + sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data); + } + + /* EEVEE_effects_init needs to go first for TAA */ + EEVEE_effects_init(sldata, vedata, camera); + EEVEE_materials_init(sldata, stl, fbl); + EEVEE_lights_init(sldata); + EEVEE_lightprobes_init(sldata, vedata); + + if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) { + /* XXX otherwise it would break the other engines. */ + DRW_viewport_matrix_override_unset_all(); + } +} + +static void eevee_cache_init(void *vedata) +{ + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + + EEVEE_bloom_cache_init(sldata, vedata); + EEVEE_depth_of_field_cache_init(sldata, vedata); + EEVEE_effects_cache_init(sldata, vedata); + EEVEE_lightprobes_cache_init(sldata, vedata); + EEVEE_lights_cache_init(sldata, vedata); + EEVEE_materials_cache_init(sldata, vedata); + EEVEE_motion_blur_cache_init(sldata, vedata); + EEVEE_occlusion_cache_init(sldata, vedata); + EEVEE_screen_raytrace_cache_init(sldata, vedata); + EEVEE_subsurface_cache_init(sldata, vedata); + EEVEE_temporal_sampling_cache_init(sldata, vedata); + EEVEE_volumes_cache_init(sldata, vedata); +} + +static void eevee_cache_populate(void *vedata, Object *ob) +{ + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool is_active = (ob == draw_ctx->obact); + if (is_active) { + if (DRW_object_is_mode_shade(ob) == true) { + return; + } + } + + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + bool cast_shadow; + + EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); + + if (cast_shadow) { + EEVEE_lights_cache_shcaster_object_add(sldata, ob); + } + } + else if (!USE_SCENE_LIGHT(draw_ctx->v3d)) { + /* do not add any scene light sources to the cache */ + } + else if (ob->type == OB_LIGHTPROBE) { + if ((ob->base_flag & BASE_FROMDUPLI) != 0) { + /* TODO: Special case for dupli objects because we cannot save the object pointer. */ + } + else { + EEVEE_lightprobes_cache_add(sldata, ob); + } + } + else if (ob->type == OB_LAMP) { + EEVEE_lights_cache_add(sldata, ob); + } +} + +static void eevee_cache_finish(void *vedata) +{ + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + + EEVEE_materials_cache_finish(vedata); + EEVEE_lights_cache_finish(sldata); + EEVEE_lightprobes_cache_finish(sldata, vedata); +} + +/* As renders in an HDR offscreen buffer, we need draw everything once + * during the background pass. This way the other drawing callback between + * the background and the scene pass are visible. + * Note: we could break it up in two passes using some depth test + * to reduce the fillrate */ +static void eevee_draw_background(void *vedata) +{ + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + + /* Default framebuffer and texture */ + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + /* Refresh Hair */ + DRW_draw_pass(psl->hair_tf_pass); + + /* Sort transparents before the loop. */ + DRW_pass_sort_shgroup_z(psl->transparent_pass); + + /* Number of iteration: needed for all temporal effect (SSR, volumetrics) + * when using opengl render. */ + int loop_ct = (DRW_state_is_image_render() && + (stl->effects->enabled_effects & (EFFECT_VOLUMETRIC | EFFECT_SSR)) != 0) ? 4 : 1; + + while (loop_ct--) { + float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float clear_depth = 1.0f; + uint clear_stencil = 0xFF; + uint primes[3] = {2, 3, 7}; + double offset[3] = {0.0, 0.0, 0.0}; + double r[3]; + + bool taa_use_reprojection = (stl->effects->enabled_effects & EFFECT_TAA_REPROJECT) != 0; + + if (DRW_state_is_image_render() || + taa_use_reprojection || + ((stl->effects->enabled_effects & EFFECT_TAA) != 0)) + { + int samp = taa_use_reprojection + ? stl->effects->taa_reproject_sample + 1 + : stl->effects->taa_current_sample; + BLI_halton_3D(primes, offset, samp, r); + EEVEE_update_noise(psl, fbl, r); + EEVEE_volumes_set_jitter(sldata, samp - 1); + EEVEE_materials_init(sldata, stl, fbl); + } + /* Copy previous persmat to UBO data */ + copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat); + + if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) && + (stl->effects->taa_current_sample > 1) && + !DRW_state_is_image_render() && + !taa_use_reprojection) + { + DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV); + } + + /* Refresh Probes */ + DRW_stats_group_start("Probes Refresh"); + EEVEE_lightprobes_refresh(sldata, vedata); + /* Probes refresh can have reset the current sample. */ + if (stl->effects->taa_current_sample == 1) { + DRW_viewport_matrix_override_unset_all(); + } + EEVEE_lightprobes_refresh_planar(sldata, vedata); + DRW_stats_group_end(); + + /* Update common buffer after probe rendering. */ + DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data); + + /* Refresh shadows */ + DRW_stats_group_start("Shadows"); + EEVEE_draw_shadows(sldata, psl); + DRW_stats_group_end(); + + GPU_framebuffer_bind(fbl->main_fb); + GPUFrameBufferBits clear_bits = GPU_DEPTH_BIT; + clear_bits |= (DRW_state_draw_background()) ? 0 : GPU_COLOR_BIT; + clear_bits |= ((stl->effects->enabled_effects & EFFECT_SSS) != 0) ? GPU_STENCIL_BIT : 0; + GPU_framebuffer_clear(fbl->main_fb, clear_bits, clear_col, clear_depth, clear_stencil); + + /* Depth prepass */ + DRW_stats_group_start("Prepass"); + DRW_draw_pass(psl->depth_pass); + DRW_draw_pass(psl->depth_pass_cull); + DRW_stats_group_end(); + + /* Create minmax texture */ + DRW_stats_group_start("Main MinMax buffer"); + EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1); + DRW_stats_group_end(); + + EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1); + EEVEE_volumes_compute(sldata, vedata); + + /* Shading pass */ + DRW_stats_group_start("Shading"); + if (DRW_state_draw_background()) { + DRW_draw_pass(psl->background_pass); + } + EEVEE_draw_default_passes(psl); + DRW_draw_pass(psl->material_pass); + EEVEE_subsurface_data_render(sldata, vedata); + DRW_stats_group_end(); + + /* Effects pre-transparency */ + EEVEE_subsurface_compute(sldata, vedata); + EEVEE_reflection_compute(sldata, vedata); + EEVEE_occlusion_draw_debug(sldata, vedata); + DRW_draw_pass(psl->probe_display); + EEVEE_refraction_compute(sldata, vedata); + + /* Opaque refraction */ + DRW_stats_group_start("Opaque Refraction"); + DRW_draw_pass(psl->refract_depth_pass); + DRW_draw_pass(psl->refract_depth_pass_cull); + DRW_draw_pass(psl->refract_pass); + DRW_stats_group_end(); + + /* Volumetrics Resolve Opaque */ + EEVEE_volumes_resolve(sldata, vedata); + + /* Transparent */ + DRW_draw_pass(psl->transparent_pass); + + /* Post Process */ + DRW_stats_group_start("Post FX"); + EEVEE_draw_effects(sldata, vedata); + DRW_stats_group_end(); + + if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) { + DRW_viewport_matrix_override_unset_all(); + } + } + + /* LookDev */ + EEVEE_lookdev_draw_background(vedata); + /* END */ + + + /* Tonemapping and transfer result to default framebuffer. */ + GPU_framebuffer_bind(dfbl->default_fb); + DRW_transform_to_display(stl->effects->final_tx); + + /* Debug : Ouput buffer to view. */ + switch (G.debug_value) { + case 1: + if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer); + break; + case 2: + if (effects->ssr_pdf_output) DRW_transform_to_display(effects->ssr_pdf_output); + break; + case 3: + if (effects->ssr_normal_input) DRW_transform_to_display(effects->ssr_normal_input); + break; + case 4: + if (effects->ssr_specrough_input) DRW_transform_to_display(effects->ssr_specrough_input); + break; + case 5: + if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer); + break; + case 6: + if (effects->gtao_horizons_debug) DRW_transform_to_display(effects->gtao_horizons_debug); + break; + case 7: + if (effects->gtao_horizons) DRW_transform_to_display(effects->gtao_horizons); + break; + case 8: + if (effects->sss_data) DRW_transform_to_display(effects->sss_data); + break; + case 9: + if (effects->velocity_tx) DRW_transform_to_display(effects->velocity_tx); + break; + default: + break; + } + + EEVEE_volumes_free_smoke_textures(); + + stl->g_data->view_updated = false; +} + +static void eevee_view_update(void *vedata) +{ + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + if (stl->g_data) { + stl->g_data->view_updated = true; + } +} + +static void eevee_id_object_update(void *UNUSED(vedata), Object *object) +{ + /* This is a bit mask of components which update is to be ignored. */ + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object); + if (ped != NULL && ped->engine_data.recalc != 0) { + ped->need_full_update = true; + ped->engine_data.recalc = 0; + } + EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object); + if (led != NULL && led->engine_data.recalc != 0) { + led->need_update = true; + led->engine_data.recalc = 0; + } + EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object); + if (oedata != NULL && oedata->engine_data.recalc != 0) { + oedata->need_update = true; + oedata->engine_data.recalc = 0; + } +} + +static void eevee_id_update(void *vedata, ID *id) +{ + /* Handle updates based on ID type. */ + switch (GS(id->name)) { + case ID_OB: + eevee_id_object_update(vedata, (Object *)id); + break; + default: + /* pass */ + break; + } +} + +static void eevee_render_to_image(void *vedata, RenderEngine *engine, struct RenderLayer *render_layer, const rcti *rect) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + EEVEE_render_init(vedata, engine, draw_ctx->depsgraph); + + DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, EEVEE_render_cache); + + /* Actually do the rendering. */ + EEVEE_render_draw(vedata, engine, render_layer, rect); +} + +static void eevee_engine_free(void) +{ + EEVEE_bloom_free(); + EEVEE_depth_of_field_free(); + EEVEE_effects_free(); + EEVEE_lightprobes_free(); + EEVEE_lights_free(); + EEVEE_materials_free(); + EEVEE_mist_free(); + EEVEE_motion_blur_free(); + EEVEE_occlusion_free(); + EEVEE_screen_raytrace_free(); + EEVEE_subsurface_free(); + EEVEE_temporal_sampling_free(); + EEVEE_volumes_free(); +} + +static const DrawEngineDataSize eevee_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data); + +DrawEngineType draw_engine_eevee_type = { + NULL, NULL, + N_("Eevee"), + &eevee_data_size, + &eevee_engine_init, + &eevee_engine_free, + &eevee_cache_init, + &eevee_cache_populate, + &eevee_cache_finish, + &eevee_draw_background, + NULL, /* Everything is drawn in the background pass (see comment on function) */ + &eevee_view_update, + &eevee_id_update, + &eevee_render_to_image, +}; + +RenderEngineType DRW_engine_viewport_eevee_type = { + NULL, NULL, + EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_SHADING_NODES | RE_USE_PREVIEW, + NULL, &DRW_render_to_image, NULL, NULL, NULL, NULL, + &EEVEE_render_update_passes, + &draw_engine_eevee_type, + {NULL, NULL, NULL} +}; + + +#undef EEVEE_ENGINE diff --git a/source/blender/draw/engines/eevee/eevee_engine.h b/source/blender/draw/engines/eevee/eevee_engine.h new file mode 100644 index 00000000000..b7de3a055b9 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_engine.h @@ -0,0 +1,31 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_engine.h + * \ingroup DNA + */ + +#ifndef __EEVEE_ENGINE_H__ +#define __EEVEE_ENGINE_H__ + +extern RenderEngineType DRW_engine_viewport_eevee_type; + +#endif /* __EEVEE_ENGINE_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c new file mode 100644 index 00000000000..a45d69794f3 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -0,0 +1,1856 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_lightprobes.c + * \ingroup DNA + */ + +#include "DRW_render.h" + +#include "BLI_utildefines.h" +#include "BLI_string_utils.h" +#include "BLI_rand.h" + +#include "DNA_world_types.h" +#include "DNA_texture_types.h" +#include "DNA_image_types.h" +#include "DNA_lightprobe_types.h" +#include "DNA_view3d_types.h" + +#include "BKE_collection.h" +#include "BKE_object.h" +#include "MEM_guardedalloc.h" + +#include "GPU_material.h" +#include "GPU_texture.h" +#include "GPU_glew.h" + +#include "DEG_depsgraph_query.h" + +#include "eevee_engine.h" +#include "eevee_private.h" + +#include "ED_screen.h" + +/* Rounded to nearest PowerOfTwo */ +#if defined(IRRADIANCE_SH_L2) +#define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */ +#define IRRADIANCE_SAMPLE_SIZE_Y 4 /* 3 in reality */ +#elif defined(IRRADIANCE_CUBEMAP) +#define IRRADIANCE_SAMPLE_SIZE_X 8 +#define IRRADIANCE_SAMPLE_SIZE_Y 8 +#elif defined(IRRADIANCE_HL2) +#define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */ +#define IRRADIANCE_SAMPLE_SIZE_Y 2 +#endif + +#define IRRADIANCE_MAX_POOL_LAYER 256 /* OpenGL 3.3 core requirement, can be extended but it's already very big */ +#define IRRADIANCE_MAX_POOL_SIZE 1024 +#define MAX_IRRADIANCE_SAMPLES \ + (IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_X) * \ + (IRRADIANCE_MAX_POOL_SIZE / IRRADIANCE_SAMPLE_SIZE_Y) +#define HAMMERSLEY_SIZE 1024 + +static struct { + struct GPUShader *probe_default_sh; + struct GPUShader *probe_default_studiolight_sh; + struct GPUShader *probe_filter_glossy_sh; + struct GPUShader *probe_filter_diffuse_sh; + struct GPUShader *probe_filter_visibility_sh; + struct GPUShader *probe_grid_fill_sh; + struct GPUShader *probe_grid_display_sh; + struct GPUShader *probe_planar_display_sh; + struct GPUShader *probe_planar_downsample_sh; + struct GPUShader *probe_cube_display_sh; + + struct GPUTexture *hammersley; + struct GPUTexture *planar_pool_placeholder; + struct GPUTexture *depth_placeholder; + struct GPUTexture *depth_array_placeholder; + struct GPUTexture *cube_face_minmaxz; + + struct Gwn_VertFormat *format_probe_display_cube; + struct Gwn_VertFormat *format_probe_display_planar; +} e_data = {NULL}; /* Engine data */ + +extern char datatoc_background_vert_glsl[]; +extern char datatoc_default_world_frag_glsl[]; +extern char datatoc_lightprobe_filter_glossy_frag_glsl[]; +extern char datatoc_lightprobe_filter_diffuse_frag_glsl[]; +extern char datatoc_lightprobe_filter_visibility_frag_glsl[]; +extern char datatoc_lightprobe_geom_glsl[]; +extern char datatoc_lightprobe_vert_glsl[]; +extern char datatoc_lightprobe_planar_display_frag_glsl[]; +extern char datatoc_lightprobe_planar_display_vert_glsl[]; +extern char datatoc_lightprobe_planar_downsample_frag_glsl[]; +extern char datatoc_lightprobe_planar_downsample_geom_glsl[]; +extern char datatoc_lightprobe_planar_downsample_vert_glsl[]; +extern char datatoc_lightprobe_cube_display_frag_glsl[]; +extern char datatoc_lightprobe_cube_display_vert_glsl[]; +extern char datatoc_lightprobe_grid_display_frag_glsl[]; +extern char datatoc_lightprobe_grid_display_vert_glsl[]; +extern char datatoc_lightprobe_grid_fill_frag_glsl[]; +extern char datatoc_irradiance_lib_glsl[]; +extern char datatoc_lightprobe_lib_glsl[]; +extern char datatoc_octahedron_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_bsdf_sampling_lib_glsl[]; + +extern GlobalsUboStorage ts; + +/* *********** FUNCTIONS *********** */ + +static void irradiance_pool_size_get(int visibility_size, int total_samples, int r_size[3]) +{ + /* Compute how many irradiance samples we can store per visibility sample. */ + int irr_per_vis = (visibility_size / IRRADIANCE_SAMPLE_SIZE_X) * + (visibility_size / IRRADIANCE_SAMPLE_SIZE_Y); + + /* The irradiance itself take one layer, hence the +1 */ + int layer_ct = MIN2(irr_per_vis + 1, IRRADIANCE_MAX_POOL_LAYER); + + int texel_ct = (int)ceilf((float)total_samples / (float)(layer_ct - 1)); + r_size[0] = visibility_size * max_ii(1, min_ii(texel_ct, (IRRADIANCE_MAX_POOL_SIZE / visibility_size))); + r_size[1] = visibility_size * max_ii(1, (texel_ct / (IRRADIANCE_MAX_POOL_SIZE / visibility_size))); + r_size[2] = layer_ct; +} + +static struct GPUTexture *create_hammersley_sample_texture(int samples) +{ + struct GPUTexture *tex; + float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * samples, "hammersley_tex"); + int i; + + for (i = 0; i < samples; i++) { + double dphi; + BLI_hammersley_1D(i, &dphi); + float phi = (float)dphi * 2.0f * M_PI; + texels[i][0] = cosf(phi); + texels[i][1] = sinf(phi); + } + + tex = DRW_texture_create_1D(samples, GPU_RG16F, DRW_TEX_WRAP, (float *)texels); + MEM_freeN(texels); + return tex; +} + +static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref) +{ + /* XXX TODO OPTIMISATION : This is a complete waist of texture memory. + * Instead of allocating each planar probe for each viewport, + * only alloc them once using the biggest viewport resolution. */ + EEVEE_TextureList *txl = vedata->txl; + + const float *viewport_size = DRW_viewport_size_get(); + + /* TODO get screen percentage from layer setting */ + // const DRWContextState *draw_ctx = DRW_context_state_get(); + // ViewLayer *view_layer = draw_ctx->view_layer; + float screen_percentage = 1.0f; + + int width = (int)(viewport_size[0] * screen_percentage); + int height = (int)(viewport_size[1] * screen_percentage); + + /* We need an Array texture so allocate it ourself */ + if (!txl->planar_pool) { + if (num_planar_ref > 0) { + txl->planar_pool = DRW_texture_create_2D_array(width, height, max_ff(1, num_planar_ref), + GPU_R11F_G11F_B10F, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL); + txl->planar_depth = DRW_texture_create_2D_array(width, height, max_ff(1, num_planar_ref), + GPU_DEPTH_COMPONENT24, 0, NULL); + } + else if (num_planar_ref == 0) { + /* Makes Opengl Happy : Create a placeholder texture that will never be sampled but still bound to shader. */ + txl->planar_pool = DRW_texture_create_2D_array(1, 1, 1, GPU_RGBA8, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL); + txl->planar_depth = DRW_texture_create_2D_array(1, 1, 1, GPU_DEPTH_COMPONENT24, 0, NULL); + } + } +} + +static void lightprobe_shaders_init(void) +{ + const char *filter_defines = "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n" +#if defined(IRRADIANCE_SH_L2) + "#define IRRADIANCE_SH_L2\n" +#elif defined(IRRADIANCE_CUBEMAP) + "#define IRRADIANCE_CUBEMAP\n" +#elif defined(IRRADIANCE_HL2) + "#define IRRADIANCE_HL2\n" +#endif + "#define NOISE_SIZE 64\n"; + + char *shader_str = NULL; + char *vert_str = NULL; + + shader_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_lightprobe_filter_glossy_frag_glsl); + + e_data.probe_filter_glossy_sh = DRW_shader_create( + datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, shader_str, filter_defines); + + e_data.probe_default_sh = DRW_shader_create( + datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL); + + e_data.probe_default_studiolight_sh = DRW_shader_create( + datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, "#define LOOKDEV\n"); + + MEM_freeN(shader_str); + + shader_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_lightprobe_filter_diffuse_frag_glsl); + + e_data.probe_filter_diffuse_sh = DRW_shader_create_fullscreen(shader_str, filter_defines); + + MEM_freeN(shader_str); + + shader_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_lightprobe_filter_visibility_frag_glsl); + + e_data.probe_filter_visibility_sh = DRW_shader_create_fullscreen(shader_str, filter_defines); + + MEM_freeN(shader_str); + + shader_str = BLI_string_joinN( + datatoc_octahedron_lib_glsl, + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_lightprobe_grid_display_frag_glsl); + + vert_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_lightprobe_grid_display_vert_glsl); + + e_data.probe_grid_display_sh = DRW_shader_create(vert_str, NULL, shader_str, filter_defines); + + MEM_freeN(vert_str); + MEM_freeN(shader_str); + + e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen( + datatoc_lightprobe_grid_fill_frag_glsl, filter_defines); + + shader_str = BLI_string_joinN( + datatoc_octahedron_lib_glsl, + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_lightprobe_cube_display_frag_glsl); + + vert_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_lightprobe_cube_display_vert_glsl); + + e_data.probe_cube_display_sh = DRW_shader_create(vert_str, NULL, shader_str, NULL); + + MEM_freeN(vert_str); + MEM_freeN(shader_str); + + vert_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_lightprobe_planar_display_vert_glsl); + + shader_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_lightprobe_planar_display_frag_glsl); + + e_data.probe_planar_display_sh = DRW_shader_create(vert_str, NULL, shader_str, NULL); + + MEM_freeN(vert_str); + MEM_freeN(shader_str); + + e_data.probe_planar_downsample_sh = DRW_shader_create( + datatoc_lightprobe_planar_downsample_vert_glsl, + datatoc_lightprobe_planar_downsample_geom_glsl, + datatoc_lightprobe_planar_downsample_frag_glsl, + NULL); + + e_data.hammersley = create_hammersley_sample_texture(HAMMERSLEY_SIZE); +} + +void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(vedata)) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + bool update_all = false; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + /* Shaders */ + if (!e_data.probe_filter_glossy_sh) { + lightprobe_shaders_init(); + } + + if (!sldata->probes) { + sldata->probes = MEM_callocN(sizeof(EEVEE_LightProbesInfo), "EEVEE_LightProbesInfo"); + sldata->probes->grid_initialized = false; + sldata->probe_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightProbe) * MAX_PROBE, NULL); + sldata->grid_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightGrid) * MAX_GRID, NULL); + sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL); + } + + /* Only start doing probes if all materials have finished compiling. */ + sldata->probes->all_materials_updated = true; + + common_data->spec_toggle = true; + common_data->ssr_toggle = true; + common_data->sss_toggle = true; + + int prop_bounce_num = scene_eval->eevee.gi_diffuse_bounces; + if (sldata->probes->num_bounce != prop_bounce_num) { + sldata->probes->num_bounce = prop_bounce_num; + update_all = true; + } + + int prop_cubemap_res = scene_eval->eevee.gi_cubemap_resolution; + if (sldata->probes->cubemap_res != prop_cubemap_res) { + sldata->probes->cubemap_res = prop_cubemap_res; + update_all = true; + + sldata->probes->target_size = prop_cubemap_res >> 1; + + DRW_TEXTURE_FREE_SAFE(sldata->probe_depth_rt); + DRW_TEXTURE_FREE_SAFE(sldata->probe_rt); + DRW_TEXTURE_FREE_SAFE(sldata->probe_pool); + } + + const int visibility_res = scene_eval->eevee.gi_visibility_resolution; + if (common_data->prb_irradiance_vis_size != visibility_res) { + common_data->prb_irradiance_vis_size = visibility_res; + update_all = true; + } + + if (update_all) { + sldata->probes->update_world |= PROBE_UPDATE_ALL; + sldata->probes->updated_bounce = 0; + sldata->probes->grid_initialized = false; + } + + /* Setup Render Target Cubemap */ + if (!sldata->probe_rt) { + sldata->probe_depth_rt = DRW_texture_create_cube(sldata->probes->target_size, GPU_DEPTH_COMPONENT24, 0, NULL); + sldata->probe_rt = DRW_texture_create_cube(sldata->probes->target_size, GPU_RGBA16F, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL); + } + + for (int i = 0; i < 6; ++i) { + GPU_framebuffer_ensure_config(&sldata->probe_face_fb[i], { + GPU_ATTACHMENT_TEXTURE_CUBEFACE(sldata->probe_depth_rt, i), + GPU_ATTACHMENT_TEXTURE_CUBEFACE(sldata->probe_rt, i) + }); + } + + /* Placeholder planar pool: used when rendering planar reflections (avoid dependency loop). */ + if (!e_data.planar_pool_placeholder) { + e_data.planar_pool_placeholder = DRW_texture_create_2D_array(1, 1, 1, GPU_RGBA8, DRW_TEX_FILTER, NULL); + } + + if (!e_data.depth_placeholder) { + e_data.depth_placeholder = DRW_texture_create_2D(1, 1, GPU_DEPTH_COMPONENT24, 0, NULL); + } + if (!e_data.depth_array_placeholder) { + e_data.depth_array_placeholder = DRW_texture_create_2D_array(1, 1, 1, GPU_DEPTH_COMPONENT24, 0, NULL); + } +} + +void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_LightProbesInfo *pinfo = sldata->probes; + + /* Make sure no aditionnal visibility check runs by default. */ + pinfo->vis_data.collection = NULL; + + pinfo->do_cube_update = false; + pinfo->num_cube = 1; /* at least one for the world */ + pinfo->num_grid = 1; + pinfo->num_planar = 0; + pinfo->total_irradiance_samples = 1; + memset(pinfo->probes_cube_ref, 0, sizeof(pinfo->probes_cube_ref)); + memset(pinfo->probes_grid_ref, 0, sizeof(pinfo->probes_grid_ref)); + memset(pinfo->probes_planar_ref, 0, sizeof(pinfo->probes_planar_ref)); + + { + psl->probe_background = DRW_pass_create("World Probe Background Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); + + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + DRWShadingGroup *grp = NULL; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + World *wo = scene->world; + + float *col = ts.colorBackground; + + /* LookDev */ + EEVEE_lookdev_cache_init(vedata, &grp, e_data.probe_default_studiolight_sh, psl->probe_background, wo, pinfo); + /* END */ + if (!grp && wo) { + col = &wo->horr; + bool wo_sh_compiled = true; + + if (wo->use_nodes && wo->nodetree) { + static float error_col[3] = {1.0f, 0.0f, 1.0f}; + static float compile_col[3] = {0.5f, 0.5f, 0.5f}; + struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo); + + GPUMaterialStatus status = GPU_material_status(gpumat); + + switch (status) { + case GPU_MAT_SUCCESS: + grp = DRW_shgroup_material_create(gpumat, psl->probe_background); + DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + DRW_shgroup_call_add(grp, geom, NULL); + wo_sh_compiled = true; + break; + case GPU_MAT_QUEUED: + pinfo->all_materials_updated = false; + wo_sh_compiled = false; + /* TODO Bypass probe compilation. */ + col = compile_col; + break; + case GPU_MAT_FAILED: + default: + wo_sh_compiled = true; + col = error_col; + break; + } + } + + if (wo->update_flag != 0 || pinfo->prev_world != wo || pinfo->prev_wo_sh_compiled != wo_sh_compiled) { + pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->studiolight_index = 0; + pinfo->prev_wo_sh_compiled = wo_sh_compiled; + pinfo->prev_world = wo; + } + wo->update_flag = 0; + } + else if (pinfo->prev_world) { + pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->studiolight_index = 0; + pinfo->prev_wo_sh_compiled = false; + pinfo->prev_world = NULL; + } + + /* Fallback if shader fails or if not using nodetree. */ + if (grp == NULL) { + grp = DRW_shgroup_create(e_data.probe_default_sh, psl->probe_background); + DRW_shgroup_uniform_vec3(grp, "color", col, 1); + DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + DRW_shgroup_call_add(grp, geom, NULL); + } + } + + { + psl->probe_glossy_compute = DRW_pass_create("LightProbe Glossy Compute", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_glossy_sh, psl->probe_glossy_compute); + DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1); + DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1); + DRW_shgroup_uniform_float(grp, "roughnessSquared", &pinfo->roughness, 1); + DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1); + DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1); + DRW_shgroup_uniform_float(grp, "texelSize", &pinfo->texel_size, 1); + DRW_shgroup_uniform_float(grp, "paddingSize", &pinfo->padding_size, 1); + DRW_shgroup_uniform_int(grp, "Layer", &pinfo->layer, 1); + DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); + // DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter); + DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { + psl->probe_diffuse_compute = DRW_pass_create("LightProbe Diffuse Compute", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_diffuse_sh, psl->probe_diffuse_compute); +#ifdef IRRADIANCE_SH_L2 + DRW_shgroup_uniform_int(grp, "probeSize", &pinfo->shres, 1); +#else + DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1); + DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1); + DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1); + DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); +#endif + DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1); + DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt); + + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + DRW_shgroup_call_add(grp, geom, NULL); + } + + { + psl->probe_visibility_compute = DRW_pass_create("LightProbe Visibility Compute", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_visibility_sh, psl->probe_visibility_compute); + DRW_shgroup_uniform_int(grp, "outputSize", &pinfo->shres, 1); + DRW_shgroup_uniform_float(grp, "visibilityRange", &pinfo->visibility_range, 1); + DRW_shgroup_uniform_float(grp, "visibilityBlur", &pinfo->visibility_blur, 1); + DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1); + DRW_shgroup_uniform_float(grp, "storedTexelSize", &pinfo->texel_size, 1); + DRW_shgroup_uniform_float(grp, "nearClip", &pinfo->near_clip, 1); + DRW_shgroup_uniform_float(grp, "farClip", &pinfo->far_clip, 1); + DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); + DRW_shgroup_uniform_texture(grp, "probeDepth", sldata->probe_depth_rt); + + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + DRW_shgroup_call_add(grp, geom, NULL); + } + + { + psl->probe_grid_fill = DRW_pass_create("LightProbe Grid Floodfill", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_grid_fill_sh, psl->probe_grid_fill); + DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &sldata->irradiance_pool); + + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + DRW_shgroup_call_add(grp, geom, NULL); + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; + psl->probe_display = DRW_pass_create("LightProbe Display", state); + + DRW_shgroup_instance_format(e_data.format_probe_display_cube, { + {"probe_id", DRW_ATTRIB_INT, 1}, + {"probe_location", DRW_ATTRIB_FLOAT, 3}, + {"sphere_size", DRW_ATTRIB_FLOAT, 1}, + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + e_data.probe_cube_display_sh, + psl->probe_display, + DRW_cache_sphere_get(), + e_data.format_probe_display_cube); + stl->g_data->cube_display_shgrp = grp; + DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &sldata->probe_pool); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + + DRW_shgroup_instance_format(e_data.format_probe_display_planar, { + {"probe_id", DRW_ATTRIB_INT, 1}, + {"probe_mat", DRW_ATTRIB_FLOAT, 16}, + }); + + grp = DRW_shgroup_instance_create( + e_data.probe_planar_display_sh, + psl->probe_display, + DRW_cache_quad_get(), + e_data.format_probe_display_planar); + stl->g_data->planar_display_shgrp = grp; + DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool); + } + + { + psl->probe_planar_downsample_ps = DRW_pass_create("LightProbe Planar Downsample", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_planar_downsample_sh, psl->probe_planar_downsample_ps); + DRW_shgroup_uniform_texture_ref(grp, "source", &txl->planar_pool); + DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1); + DRW_shgroup_call_instances_add(grp, DRW_cache_fullscreen_quad_get(), NULL, (uint *)&pinfo->num_planar); + } +} + +bool EEVEE_lightprobes_obj_visibility_cb(bool vis_in, void *user_data) +{ + EEVEE_ObjectEngineData *oed = (EEVEE_ObjectEngineData *)user_data; + + /* test disabled if group is NULL */ + if (oed->test_data->collection == NULL) + return vis_in; + + if (oed->test_data->cached == false) + oed->ob_vis_dirty = true; + + /* early out, don't need to compute ob_vis yet. */ + if (vis_in == false) + return vis_in; + + if (oed->ob_vis_dirty) { + oed->ob_vis_dirty = false; + oed->ob_vis = BKE_collection_has_object_recursive(oed->test_data->collection, oed->ob); + oed->ob_vis = (oed->test_data->invert) ? !oed->ob_vis : oed->ob_vis; + } + + return vis_in && oed->ob_vis; +} + +void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) +{ + EEVEE_LightProbesInfo *pinfo = sldata->probes; + LightProbe *probe = (LightProbe *)ob->data; + + if ((probe->type == LIGHTPROBE_TYPE_CUBE && pinfo->num_cube >= MAX_PROBE) || + (probe->type == LIGHTPROBE_TYPE_GRID && pinfo->num_grid >= MAX_PROBE) || + (probe->type == LIGHTPROBE_TYPE_PLANAR && pinfo->num_grid >= MAX_PLANAR)) + { + printf("Too much probes in the scene !!!\n"); + return; + } + + if (probe->type == LIGHTPROBE_TYPE_PLANAR) { + /* See if this planar probe is inside the view frustum. If not, no need to update it. */ + /* NOTE: this could be bypassed if we want feedback loop mirrors for rendering. */ + BoundBox bbox; float tmp[4][4]; + const float min[3] = {-1.0f, -1.0f, -1.0f}; + const float max[3] = { 1.0f, 1.0f, 1.0f}; + BKE_boundbox_init_from_minmax(&bbox, min, max); + + copy_m4_m4(tmp, ob->obmat); + normalize_v3(tmp[2]); + mul_v3_fl(tmp[2], probe->distinf); + + for (int v = 0; v < 8; ++v) { + mul_m4_v3(tmp, bbox.vec[v]); + } + if (!DRW_culling_box_test(&bbox)) { + return; /* Culled */ + } + } + + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + + ped->num_cell = probe->grid_resolution_x * probe->grid_resolution_y * probe->grid_resolution_z; + + if ((probe->type == LIGHTPROBE_TYPE_GRID) && + ((pinfo->total_irradiance_samples + ped->num_cell) >= MAX_IRRADIANCE_SAMPLES)) + { + printf("Too much grid samples !!!\n"); + return; + } + + if (ped->need_full_update) { + ped->need_full_update = false; + + ped->need_update = true; + ped->probe_id = 0; + if (probe->type == LIGHTPROBE_TYPE_GRID) { + ped->updated_cells = 0; + ped->updated_lvl = 0; + pinfo->updated_bounce = 0; + pinfo->grid_initialized = false; + } + } + + if (pinfo->update_world) { + ped->need_update = true; + ped->updated_cells = 0; + ped->updated_lvl = 0; + ped->probe_id = 0; + } + + pinfo->do_cube_update |= ped->need_update; + + switch (probe->type) { + case LIGHTPROBE_TYPE_CUBE: + pinfo->probes_cube_ref[pinfo->num_cube] = ob; + pinfo->num_cube++; + break; + case LIGHTPROBE_TYPE_PLANAR: + pinfo->probes_planar_ref[pinfo->num_planar] = ob; + pinfo->num_planar++; + break; + case LIGHTPROBE_TYPE_GRID: + pinfo->probes_grid_ref[pinfo->num_grid] = ob; + pinfo->num_grid++; + pinfo->total_irradiance_samples += ped->num_cell; + break; + } +} + +/* TODO find a nice name to push it to math_matrix.c */ +static void scale_m4_v3(float R[4][4], float v[3]) +{ + for (int i = 0; i < 4; ++i) + mul_v3_v3(R[i], v); +} + +static void EEVEE_planar_reflections_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl) +{ + EEVEE_LightProbesInfo *pinfo = sldata->probes; + Object *ob; + + for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) { + LightProbe *probe = (LightProbe *)ob->data; + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + + ped->probe_id = i; + + /* Debug Display */ + if (DRW_state_draw_support() && + (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) + { + DRW_shgroup_call_dynamic_add(stl->g_data->planar_display_shgrp, &ped->probe_id, ob->obmat); + } + } +} + +static void EEVEE_planar_reflections_updates(EEVEE_ViewLayerData *sldata) +{ + EEVEE_LightProbesInfo *pinfo = sldata->probes; + Object *ob; + float mtx[4][4], normat[4][4], imat[4][4], rangemat[4][4]; + + float viewmat[4][4]; + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + + zero_m4(rangemat); + rangemat[0][0] = rangemat[1][1] = rangemat[2][2] = 0.5f; + rangemat[3][0] = rangemat[3][1] = rangemat[3][2] = 0.5f; + rangemat[3][3] = 1.0f; + + /* PLANAR REFLECTION */ + for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) { + LightProbe *probe = (LightProbe *)ob->data; + EEVEE_PlanarReflection *eplanar = &pinfo->planar_data[i]; + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + /* Computing mtx : matrix that mirror position around object's XY plane. */ + normalize_m4_m4(normat, ob->obmat); /* object > world */ + invert_m4_m4(imat, normat); /* world > object */ + float reflect[3] = {1.0f, 1.0f, -1.0f}; /* XY reflection plane */ + scale_m4_v3(imat, reflect); /* world > object > mirrored obj */ + mul_m4_m4m4(mtx, normat, imat); /* world > object > mirrored obj > world */ + /* Reflect Camera Matrix. */ + mul_m4_m4m4(ped->mats.mat[DRW_MAT_VIEW], viewmat, mtx); + /* TODO FOV margin */ + /* Temporal sampling jitter should be already applied to the DRW_MAT_WIN. */ + DRW_viewport_matrix_get(ped->mats.mat[DRW_MAT_WIN], DRW_MAT_WIN); + /* Apply Projection Matrix. */ + mul_m4_m4m4(ped->mats.mat[DRW_MAT_PERS], ped->mats.mat[DRW_MAT_WIN], ped->mats.mat[DRW_MAT_VIEW]); + /* This is the matrix used to reconstruct texture coordinates. + * We use the original view matrix because it does not create + * visual artifacts if receiver is not perfectly aligned with + * the planar reflection probe. */ + mul_m4_m4m4(eplanar->reflectionmat, ped->mats.mat[DRW_MAT_WIN], viewmat); /* TODO FOV margin */ + /* Convert from [-1, 1] to [0, 1] (NDC to Texture coord). */ + mul_m4_m4m4(eplanar->reflectionmat, rangemat, eplanar->reflectionmat); + + /* Compute clip plane equation / normal. */ + float refpoint[3]; + copy_v3_v3(eplanar->plane_equation, ob->obmat[2]); + normalize_v3(eplanar->plane_equation); /* plane normal */ + eplanar->plane_equation[3] = -dot_v3v3(eplanar->plane_equation, ob->obmat[3]); + + /* Compute offset plane equation (fix missing texels near reflection plane). */ + copy_v3_v3(ped->planer_eq_offset, eplanar->plane_equation); + mul_v3_v3fl(refpoint, eplanar->plane_equation, -probe->clipsta); + add_v3_v3(refpoint, ob->obmat[3]); + ped->planer_eq_offset[3] = -dot_v3v3(eplanar->plane_equation, refpoint); + + /* Compute XY clip planes. */ + normalize_v3_v3(eplanar->clip_vec_x, ob->obmat[0]); + normalize_v3_v3(eplanar->clip_vec_y, ob->obmat[1]); + + float vec[3] = {0.0f, 0.0f, 0.0f}; + vec[0] = 1.0f; vec[1] = 0.0f; vec[2] = 0.0f; + mul_m4_v3(ob->obmat, vec); /* Point on the edge */ + eplanar->clip_edge_x_pos = dot_v3v3(eplanar->clip_vec_x, vec); + + vec[0] = 0.0f; vec[1] = 1.0f; vec[2] = 0.0f; + mul_m4_v3(ob->obmat, vec); /* Point on the edge */ + eplanar->clip_edge_y_pos = dot_v3v3(eplanar->clip_vec_y, vec); + + vec[0] = -1.0f; vec[1] = 0.0f; vec[2] = 0.0f; + mul_m4_v3(ob->obmat, vec); /* Point on the edge */ + eplanar->clip_edge_x_neg = dot_v3v3(eplanar->clip_vec_x, vec); + + vec[0] = 0.0f; vec[1] = -1.0f; vec[2] = 0.0f; + mul_m4_v3(ob->obmat, vec); /* Point on the edge */ + eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec); + + /* Facing factors */ + float max_angle = max_ff(1e-2f, probe->falloff) * M_PI * 0.5f; + float min_angle = 0.0f; + eplanar->facing_scale = 1.0f / max_ff(1e-8f, cosf(min_angle) - cosf(max_angle)); + eplanar->facing_bias = -min_ff(1.0f - 1e-8f, cosf(max_angle)) * eplanar->facing_scale; + + /* Distance factors */ + float max_dist = probe->distinf; + float min_dist = min_ff(1.0f - 1e-8f, 1.0f - probe->falloff) * probe->distinf; + eplanar->attenuation_scale = -1.0f / max_ff(1e-8f, max_dist - min_dist); + eplanar->attenuation_bias = max_dist * -eplanar->attenuation_scale; + } +} + +static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, EEVEE_StorageList *stl) +{ + EEVEE_LightProbesInfo *pinfo = sldata->probes; + Object *ob; + + /* CUBE REFLECTION */ + for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) { + LightProbe *probe = (LightProbe *)ob->data; + EEVEE_LightProbe *eprobe = &pinfo->probe_data[i]; + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + + /* Update transforms */ + copy_v3_v3(eprobe->position, ob->obmat[3]); + + /* Attenuation */ + eprobe->attenuation_type = probe->attenuation_type; + eprobe->attenuation_fac = 1.0f / max_ff(1e-8f, probe->falloff); + + unit_m4(eprobe->attenuationmat); + scale_m4_fl(eprobe->attenuationmat, probe->distinf); + mul_m4_m4m4(eprobe->attenuationmat, ob->obmat, eprobe->attenuationmat); + invert_m4(eprobe->attenuationmat); + + /* Parallax */ + float dist; + if ((probe->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) { + eprobe->parallax_type = probe->parallax_type; + dist = probe->distpar; + } + else { + eprobe->parallax_type = probe->attenuation_type; + dist = probe->distinf; + } + + unit_m4(eprobe->parallaxmat); + scale_m4_fl(eprobe->parallaxmat, dist); + mul_m4_m4m4(eprobe->parallaxmat, ob->obmat, eprobe->parallaxmat); + invert_m4(eprobe->parallaxmat); + + /* Debug Display */ + if (DRW_state_draw_support() && + (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) + { + ped->probe_size = probe->data_draw_size * 0.1f; + DRW_shgroup_call_dynamic_add( + stl->g_data->cube_display_shgrp, &ped->probe_id, ob->obmat[3], &ped->probe_size); + } + } + + /* IRRADIANCE GRID */ + int offset = 1; /* to account for the world probe */ + for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); i++) { + LightProbe *probe = (LightProbe *)ob->data; + EEVEE_LightGrid *egrid = &pinfo->grid_data[i]; + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + + /* If one grid has move we need to recompute all the lighting. */ + if (!pinfo->grid_initialized) { + ped->updated_cells = 0; + ped->updated_lvl = 0; + ped->need_update = true; + } + + /* Add one for level 0 */ + ped->max_lvl = 1.0f + floorf(log2f((float)MAX3(probe->grid_resolution_x, + probe->grid_resolution_y, + probe->grid_resolution_z))); + + egrid->offset = offset; + float fac = 1.0f / max_ff(1e-8f, probe->falloff); + egrid->attenuation_scale = fac / max_ff(1e-8f, probe->distinf); + egrid->attenuation_bias = fac; + + /* Set offset for the next grid */ + offset += ped->num_cell; + + /* Update transforms */ + float cell_dim[3], half_cell_dim[3]; + cell_dim[0] = 2.0f / (float)(probe->grid_resolution_x); + cell_dim[1] = 2.0f / (float)(probe->grid_resolution_y); + cell_dim[2] = 2.0f / (float)(probe->grid_resolution_z); + + mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f); + + /* Matrix converting world space to cell ranges. */ + invert_m4_m4(egrid->mat, ob->obmat); + + /* First cell. */ + copy_v3_fl(egrid->corner, -1.0f); + add_v3_v3(egrid->corner, half_cell_dim); + mul_m4_v3(ob->obmat, egrid->corner); + + /* Opposite neighbor cell. */ + copy_v3_fl3(egrid->increment_x, cell_dim[0], 0.0f, 0.0f); + add_v3_v3(egrid->increment_x, half_cell_dim); + add_v3_fl(egrid->increment_x, -1.0f); + mul_m4_v3(ob->obmat, egrid->increment_x); + sub_v3_v3(egrid->increment_x, egrid->corner); + + copy_v3_fl3(egrid->increment_y, 0.0f, cell_dim[1], 0.0f); + add_v3_v3(egrid->increment_y, half_cell_dim); + add_v3_fl(egrid->increment_y, -1.0f); + mul_m4_v3(ob->obmat, egrid->increment_y); + sub_v3_v3(egrid->increment_y, egrid->corner); + + copy_v3_fl3(egrid->increment_z, 0.0f, 0.0f, cell_dim[2]); + add_v3_v3(egrid->increment_z, half_cell_dim); + add_v3_fl(egrid->increment_z, -1.0f); + mul_m4_v3(ob->obmat, egrid->increment_z); + sub_v3_v3(egrid->increment_z, egrid->corner); + + copy_v3_v3_int(egrid->resolution, &probe->grid_resolution_x); + + /* Visibility bias */ + egrid->visibility_bias = 0.05f * probe->vis_bias; + egrid->visibility_bleed = probe->vis_bleedbias; + egrid->visibility_range = ( + sqrtf(max_fff(len_squared_v3(egrid->increment_x), + len_squared_v3(egrid->increment_y), + len_squared_v3(egrid->increment_z))) + 1.0f); + + /* Debug Display */ + if (DRW_state_draw_support() && + (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_grid_display_sh, psl->probe_display); + DRW_shgroup_uniform_int(grp, "offset", &egrid->offset, 1); + DRW_shgroup_uniform_ivec3(grp, "grid_resolution", egrid->resolution, 1); + DRW_shgroup_uniform_vec3(grp, "corner", egrid->corner, 1); + DRW_shgroup_uniform_vec3(grp, "increment_x", egrid->increment_x, 1); + DRW_shgroup_uniform_vec3(grp, "increment_y", egrid->increment_y, 1); + DRW_shgroup_uniform_vec3(grp, "increment_z", egrid->increment_z, 1); + DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &sldata->irradiance_pool); + DRW_shgroup_uniform_float(grp, "sphere_size", &probe->data_draw_size, 1); + DRW_shgroup_call_instances_add(grp, DRW_cache_sphere_get(), NULL, (uint *)&ped->num_cell); + } + } +} + +void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_LightProbesInfo *pinfo = sldata->probes; + Object *ob; + + /* Setup enough layers. */ + /* Free textures if number mismatch. */ + if (pinfo->num_cube != pinfo->cache_num_cube) { + DRW_TEXTURE_FREE_SAFE(sldata->probe_pool); + pinfo->cache_num_cube = pinfo->num_cube; + } + + if (pinfo->num_planar != pinfo->cache_num_planar) { + DRW_TEXTURE_FREE_SAFE(vedata->txl->planar_pool); + DRW_TEXTURE_FREE_SAFE(vedata->txl->planar_depth); + pinfo->cache_num_planar = pinfo->num_planar; + } + + int irr_size[3]; + irradiance_pool_size_get(common_data->prb_irradiance_vis_size, pinfo->total_irradiance_samples, irr_size); + + if ((irr_size[0] != pinfo->cache_irradiance_size[0]) || + (irr_size[1] != pinfo->cache_irradiance_size[1]) || + (irr_size[2] != pinfo->cache_irradiance_size[2])) + { + DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool); + DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt); + copy_v3_v3_int(pinfo->cache_irradiance_size, irr_size); + } + + /* XXX this should be run each frame as it ensure planar_depth is set */ + planar_pool_ensure_alloc(vedata, pinfo->num_planar); + + if (!sldata->probe_pool) { + sldata->probe_pool = DRW_texture_create_2D_array(pinfo->cubemap_res, pinfo->cubemap_res, max_ff(1, pinfo->num_cube), + GPU_R11F_G11F_B10F, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL); + if (sldata->probe_filter_fb) { + GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0); + } + /* Tag probes to refresh */ + pinfo->update_world |= PROBE_UPDATE_CUBE; + } + + if ((pinfo->update_world & PROBE_UPDATE_CUBE) != 0) { + common_data->prb_num_render_cube = 0; + for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) { + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + ped->need_update = true; + ped->ready_to_shade = false; + ped->probe_id = 0; + } + } + +#ifdef IRRADIANCE_SH_L2 + /* we need a signed format for Spherical Harmonics */ + int irradiance_format = GPU_RGBA16F; +#else + int irradiance_format = GPU_RGBA8; +#endif + + if (!sldata->irradiance_pool || !sldata->irradiance_rt) { + if (!sldata->irradiance_pool) { + sldata->irradiance_pool = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2], + irradiance_format, DRW_TEX_FILTER, NULL); + } + if (!sldata->irradiance_rt) { + sldata->irradiance_rt = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2], + irradiance_format, DRW_TEX_FILTER, NULL); + } + /* Tag probes to refresh */ + pinfo->update_world |= PROBE_UPDATE_GRID; + pinfo->grid_initialized = false; + } + + if ((pinfo->update_world & PROBE_UPDATE_GRID) != 0) { + common_data->prb_num_render_grid = 0; + pinfo->updated_bounce = 0; + for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_PROBE); i++) { + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + ped->need_update = true; + ped->updated_cells = 0; + } + } + + if (common_data->prb_num_render_grid > pinfo->num_grid) { + /* This can happen when deleting a probe. */ + common_data->prb_num_render_grid = pinfo->num_grid; + } + + EEVEE_planar_reflections_cache_finish(sldata, vedata->stl); + + EEVEE_lightprobes_updates(sldata, vedata->psl, vedata->stl); + + DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data); + DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data); +} + +static void downsample_planar(void *vedata, int level) +{ + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + + const float *size = DRW_viewport_size_get(); + copy_v2_v2(stl->g_data->planar_texel_size, size); + for (int i = 0; i < level - 1; ++i) { + stl->g_data->planar_texel_size[0] /= 2.0f; + stl->g_data->planar_texel_size[1] /= 2.0f; + min_ff(floorf(stl->g_data->planar_texel_size[0]), 1.0f); + min_ff(floorf(stl->g_data->planar_texel_size[1]), 1.0f); + } + invert_v2(stl->g_data->planar_texel_size); + + DRW_draw_pass(psl->probe_planar_downsample_ps); +} + +/* Glossy filter probe_rt to probe_pool at index probe_idx */ +static void glossy_filter_probe( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int probe_idx, float intensity) +{ + EEVEE_LightProbesInfo *pinfo = sldata->probes; + + pinfo->intensity_fac = intensity; + + /* Max lod used from the render target probe */ + pinfo->lod_rt_max = floorf(log2f(pinfo->target_size)) - 2.0f; + + /* Start fresh */ + GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_NONE + }); + + /* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */ + /* Bind next framebuffer to be able to gen. mips for probe_rt. */ + EEVEE_downsample_cube_buffer(vedata, sldata->probe_rt, (int)(pinfo->lod_rt_max)); + + /* 3 - Render to probe array to the specified layer, do prefiltering. */ + float mipsize = pinfo->cubemap_res; + const int maxlevel = (int)floorf(log2f(pinfo->cubemap_res)); + const int min_lod_level = 3; + for (int i = 0; i < maxlevel - min_lod_level; i++) { + float bias = (i == 0) ? -1.0f : 1.0f; + pinfo->texel_size = 1.0f / mipsize; + pinfo->padding_size = powf(2.0f, (float)(maxlevel - min_lod_level - 1 - i)); + /* XXX : WHY THE HECK DO WE NEED THIS ??? */ + /* padding is incorrect without this! float precision issue? */ + if (pinfo->padding_size > 32) { + pinfo->padding_size += 5; + } + if (pinfo->padding_size > 16) { + pinfo->padding_size += 4; + } + else if (pinfo->padding_size > 8) { + pinfo->padding_size += 2; + } + else if (pinfo->padding_size > 4) { + pinfo->padding_size += 1; + } + pinfo->layer = probe_idx; + pinfo->roughness = (float)i / ((float)maxlevel - 4.0f); + pinfo->roughness *= pinfo->roughness; /* Disney Roughness */ + pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */ + CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */ + +#if 1 /* Variable Sample count (fast) */ + switch (i) { + case 0: pinfo->samples_ct = 1.0f; break; + case 1: pinfo->samples_ct = 16.0f; break; + case 2: pinfo->samples_ct = 32.0f; break; + case 3: pinfo->samples_ct = 64.0f; break; + default: pinfo->samples_ct = 128.0f; break; + } +#else /* Constant Sample count (slow) */ + pinfo->samples_ct = 1024.0f; +#endif + + pinfo->invsamples_ct = 1.0f / pinfo->samples_ct; + pinfo->lodfactor = bias + 0.5f * log((float)(pinfo->target_size * pinfo->target_size) * pinfo->invsamples_ct) / log(2); + + GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE_MIP(sldata->probe_pool, i) + }); + GPU_framebuffer_bind(sldata->probe_filter_fb); + GPU_framebuffer_viewport_set(sldata->probe_filter_fb, 0, 0, mipsize, mipsize); + DRW_draw_pass(psl->probe_glossy_compute); + + mipsize /= 2; + CLAMP_MIN(mipsize, 1); + } + /* For shading, save max level of the octahedron map */ + sldata->common_data.prb_lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f; +} + +/* Diffuse filter probe_rt to irradiance_pool at index probe_idx */ +static void diffuse_filter_probe( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int offset, + float clipsta, float clipend, float vis_range, float vis_blur, float intensity) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_LightProbesInfo *pinfo = sldata->probes; + + pinfo->intensity_fac = intensity; + + int pool_size[3]; + irradiance_pool_size_get(common_data->prb_irradiance_vis_size, pinfo->total_irradiance_samples, pool_size); + + /* find cell position on the virtual 3D texture */ + /* NOTE : Keep in sync with load_irradiance_cell() */ +#if defined(IRRADIANCE_SH_L2) + int size[2] = {3, 3}; +#elif defined(IRRADIANCE_CUBEMAP) + int size[2] = {8, 8}; + pinfo->samples_ct = 1024.0f; +#elif defined(IRRADIANCE_HL2) + int size[2] = {3, 2}; + pinfo->samples_ct = 1024.0f; +#endif + + int cell_per_row = pool_size[0] / size[0]; + int x = size[0] * (offset % cell_per_row); + int y = size[1] * (offset / cell_per_row); + +#ifndef IRRADIANCE_SH_L2 + /* Tweaking parameters to balance perf. vs precision */ + const float bias = 0.0f; + pinfo->invsamples_ct = 1.0f / pinfo->samples_ct; + pinfo->lodfactor = bias + 0.5f * log((float)(pinfo->target_size * pinfo->target_size) * pinfo->invsamples_ct) / log(2); + pinfo->lod_rt_max = floorf(log2f(pinfo->target_size)) - 2.0f; +#else + pinfo->shres = 32; /* Less texture fetches & reduce branches */ + pinfo->lod_rt_max = 2.0f; /* Improve cache reuse */ +#endif + + /* Start fresh */ + GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_NONE + }); + + /* 4 - Compute spherical harmonics */ + EEVEE_downsample_cube_buffer(vedata, sldata->probe_rt, (int)(pinfo->lod_rt_max)); + + GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE_LAYER(sldata->irradiance_rt, 0) + }); + GPU_framebuffer_bind(sldata->probe_filter_fb); + GPU_framebuffer_viewport_set(sldata->probe_filter_fb, x, y, size[0], size[1]); + DRW_draw_pass(psl->probe_diffuse_compute); + + /* World irradiance have no visibility */ + if (offset > 0) { + /* Compute visibility */ + pinfo->samples_ct = 512.0f; /* TODO refine */ + pinfo->invsamples_ct = 1.0f / pinfo->samples_ct; + pinfo->shres = common_data->prb_irradiance_vis_size; + pinfo->visibility_range = vis_range; + pinfo->visibility_blur = vis_blur; + pinfo->near_clip = -clipsta; + pinfo->far_clip = -clipend; + pinfo->texel_size = 1.0f / (float)common_data->prb_irradiance_vis_size; + + int cell_per_col = pool_size[1] / common_data->prb_irradiance_vis_size; + cell_per_row = pool_size[0] / common_data->prb_irradiance_vis_size; + x = common_data->prb_irradiance_vis_size * (offset % cell_per_row); + y = common_data->prb_irradiance_vis_size * ((offset / cell_per_row) % cell_per_col); + int layer = 1 + ((offset / cell_per_row) / cell_per_col); + const int vis_size = common_data->prb_irradiance_vis_size; + + GPU_framebuffer_ensure_config(&sldata->probe_filter_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE_LAYER(sldata->irradiance_rt, layer) + }); + GPU_framebuffer_bind(sldata->probe_filter_fb); + GPU_framebuffer_viewport_set(sldata->probe_filter_fb, x, y, vis_size, vis_size); + DRW_draw_pass(psl->probe_visibility_compute); + } +} + +/* Render the scene to the probe_rt texture. */ +static void render_scene_to_probe( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, + const float pos[3], float clipsta, float clipend) +{ + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_LightProbesInfo *pinfo = sldata->probes; + + DRWMatrixState matstate; + float (*viewmat)[4] = matstate.mat[DRW_MAT_VIEW]; + float (*viewinv)[4] = matstate.mat[DRW_MAT_VIEWINV]; + float (*persmat)[4] = matstate.mat[DRW_MAT_PERS]; + float (*persinv)[4] = matstate.mat[DRW_MAT_PERSINV]; + float (*winmat)[4] = matstate.mat[DRW_MAT_WIN]; + float (*wininv)[4] = matstate.mat[DRW_MAT_WININV]; + + float posmat[4][4]; + unit_m4(posmat); + + /* Move to capture position */ + negate_v3_v3(posmat[3], pos); + + /* 1 - Render to each cubeface individually. + * We do this instead of using geometry shader because a) it's faster, + * b) it's easier than fixing the nodetree shaders (for view dependant effects). */ + pinfo->layer = 0; + perspective_m4(winmat, -clipsta, clipsta, -clipsta, clipsta, clipsta, clipend); + + /* Avoid using the texture attached to framebuffer when rendering. */ + /* XXX */ + GPUTexture *tmp_planar_pool = txl->planar_pool; + GPUTexture *tmp_maxz = txl->maxzbuffer; + txl->planar_pool = e_data.planar_pool_placeholder; + txl->maxzbuffer = e_data.depth_placeholder; + + DRW_stats_group_start("Cubemap Render"); + + /* Update common uniforms */ + DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data); + + for (int i = 0; i < 6; ++i) { + /* Recompute only on 1st drawloop. */ + pinfo->vis_data.cached = (i != 0); + + DRW_stats_group_start("Cubemap Face"); + + /* Setup custom matrices */ + mul_m4_m4m4(viewmat, cubefacemat[i], posmat); + mul_m4_m4m4(persmat, winmat, viewmat); + invert_m4_m4(persinv, persmat); + invert_m4_m4(viewinv, viewmat); + invert_m4_m4(wininv, winmat); + + DRW_viewport_matrix_override_set_all(&matstate); + + /* Be sure that cascaded shadow maps are updated. */ + EEVEE_draw_shadows(sldata, psl); + + GPU_framebuffer_bind(sldata->probe_face_fb[i]); + GPU_framebuffer_clear_depth(sldata->probe_face_fb[i], 1.0); + + /* Depth prepass */ + DRW_draw_pass(psl->depth_pass); + DRW_draw_pass(psl->depth_pass_cull); + + DRW_draw_pass(psl->probe_background); + + // EEVEE_create_minmax_buffer(vedata, sldata->probe_depth_rt); + + /* Rebind Target FB */ + GPU_framebuffer_bind(sldata->probe_face_fb[i]); + + /* Shading pass */ + EEVEE_draw_default_passes(psl); + DRW_draw_pass(psl->material_pass); + DRW_draw_pass(psl->sss_pass); /* Only output standard pass */ + + DRW_stats_group_end(); + } + + DRW_stats_group_end(); + + /* Make sure no aditionnal visibility check runs after this. */ + pinfo->vis_data.collection = NULL; + + /* Restore */ + txl->planar_pool = tmp_planar_pool; + txl->maxzbuffer = tmp_maxz; +} + +static void render_scene_to_planar( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, int layer, + EEVEE_LightProbeEngineData *ped) +{ + EEVEE_LightProbesInfo *pinfo = sldata->probes; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + + float (*viewmat)[4] = ped->mats.mat[DRW_MAT_VIEW]; + float (*viewinv)[4] = ped->mats.mat[DRW_MAT_VIEWINV]; + float (*persmat)[4] = ped->mats.mat[DRW_MAT_PERS]; + float (*persinv)[4] = ped->mats.mat[DRW_MAT_PERSINV]; + float (*winmat)[4] = ped->mats.mat[DRW_MAT_WIN]; + float (*wininv)[4] = ped->mats.mat[DRW_MAT_WININV]; + + invert_m4_m4(viewinv, viewmat); + invert_m4_m4(persinv, persmat); + invert_m4_m4(wininv, winmat); + + DRW_stats_group_start("Planar Reflection"); + + DRW_viewport_matrix_override_set_all(&ped->mats); + + /* Don't reuse previous visibility. */ + pinfo->vis_data.cached = false; + + /* Be sure that cascaded shadow maps are updated. */ + EEVEE_draw_shadows(sldata, psl); + + /* Since we are rendering with an inverted view matrix, we need + * to invert the facing for backface culling to be the same. */ + DRW_state_invert_facing(); + /* Set clipping plan */ + copy_v4_v4(sldata->clip_data.clip_planes[0], ped->planer_eq_offset); + DRW_uniformbuffer_update(sldata->clip_ubo, &sldata->clip_data); + DRW_state_clip_planes_count_set(1); + + GPU_framebuffer_ensure_config(&fbl->planarref_fb, { + GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_depth, layer), + GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_pool, layer) + }); + + GPU_framebuffer_bind(fbl->planarref_fb); + GPU_framebuffer_clear_depth(fbl->planarref_fb, 1.0); + + /* Avoid using the texture attached to framebuffer when rendering. */ + /* XXX */ + GPUTexture *tmp_planar_pool = txl->planar_pool; + GPUTexture *tmp_planar_depth = txl->planar_depth; + txl->planar_pool = e_data.planar_pool_placeholder; + txl->planar_depth = e_data.depth_array_placeholder; + + /* Slight modification: we handle refraction as normal + * shading and don't do SSRefraction. */ + + /* Depth prepass */ + DRW_draw_pass(psl->depth_pass_clip); + DRW_draw_pass(psl->depth_pass_clip_cull); + DRW_draw_pass(psl->refract_depth_pass); + DRW_draw_pass(psl->refract_depth_pass_cull); + + /* Background */ + DRW_draw_pass(psl->probe_background); + + EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer); + + /* Compute GTAO Horizons */ + EEVEE_occlusion_compute(sldata, vedata, tmp_planar_depth, layer); + + /* Rebind Planar FB */ + GPU_framebuffer_bind(fbl->planarref_fb); + + /* Shading pass */ + EEVEE_draw_default_passes(psl); + DRW_draw_pass(psl->material_pass); + DRW_draw_pass(psl->sss_pass); /* Only output standard pass */ + DRW_draw_pass(psl->refract_pass); + + /* Transparent */ + if (DRW_state_is_image_render()) { + /* Do the reordering only for offline because it can be costly. */ + DRW_pass_sort_shgroup_z(psl->transparent_pass); + } + DRW_draw_pass(psl->transparent_pass); + + DRW_state_invert_facing(); + DRW_state_clip_planes_reset(); + + DRW_stats_group_end(); + + /* Make sure no aditionnal visibility check runs after this. */ + pinfo->vis_data.collection = NULL; + + /* Restore */ + txl->planar_pool = tmp_planar_pool; + txl->planar_depth = tmp_planar_depth; +} + +static void render_world_to_probe(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) +{ + EEVEE_LightProbesInfo *pinfo = sldata->probes; + DRWMatrixState matstate; + float (*viewmat)[4] = matstate.mat[DRW_MAT_VIEW]; + float (*viewinv)[4] = matstate.mat[DRW_MAT_VIEWINV]; + float (*persmat)[4] = matstate.mat[DRW_MAT_PERS]; + float (*persinv)[4] = matstate.mat[DRW_MAT_PERSINV]; + float (*winmat)[4] = matstate.mat[DRW_MAT_WIN]; + float (*wininv)[4] = matstate.mat[DRW_MAT_WININV]; + + /* For world probe, we don't need to clear since we render the background directly. */ + pinfo->layer = 0; + + perspective_m4(winmat, -0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 1.0f); + invert_m4_m4(wininv, winmat); + + for (int i = 0; i < 6; ++i) { + /* Setup custom matrices */ + copy_m4_m4(viewmat, cubefacemat[i]); + mul_m4_m4m4(persmat, winmat, viewmat); + invert_m4_m4(persinv, persmat); + invert_m4_m4(viewinv, viewmat); + DRW_viewport_matrix_override_set_all(&matstate); + + GPU_framebuffer_bind(sldata->probe_face_fb[i]); + GPU_framebuffer_clear_depth(sldata->probe_face_fb[i], 1.0f); + DRW_draw_pass(psl->probe_background); + } +} + +static void lightprobe_cell_grid_location_get(EEVEE_LightGrid *egrid, int cell_idx, float r_local_cell[3]) +{ + /* Keep in sync with lightprobe_grid_display_vert */ + r_local_cell[2] = (float)(cell_idx % egrid->resolution[2]); + r_local_cell[1] = (float)((cell_idx / egrid->resolution[2]) % egrid->resolution[1]); + r_local_cell[0] = (float)(cell_idx / (egrid->resolution[2] * egrid->resolution[1])); +} + +static void lightprobe_cell_world_location_get(EEVEE_LightGrid *egrid, float local_cell[3], float r_pos[3]) +{ + float tmp[3]; + + copy_v3_v3(r_pos, egrid->corner); + mul_v3_v3fl(tmp, egrid->increment_x, local_cell[0]); + add_v3_v3(r_pos, tmp); + mul_v3_v3fl(tmp, egrid->increment_y, local_cell[1]); + add_v3_v3(r_pos, tmp); + mul_v3_v3fl(tmp, egrid->increment_z, local_cell[2]); + add_v3_v3(r_pos, tmp); +} + +static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_LightProbesInfo *pinfo = sldata->probes; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + DRWMatrixState saved_mats; + + /* We need to save the Matrices before overidding them */ + DRW_viewport_matrix_get_all(&saved_mats); + + render_world_to_probe(sldata, psl); + if (pinfo->update_world & PROBE_UPDATE_CUBE) { + glossy_filter_probe(sldata, vedata, psl, 0, 1.0); + common_data->prb_num_render_cube = 1; + } + if (pinfo->update_world & PROBE_UPDATE_GRID) { + diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0, 1.0); + + SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); + + GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0); + GPU_framebuffer_bind(sldata->probe_filter_fb); + DRW_draw_pass(psl->probe_grid_fill); + + common_data->prb_num_render_grid = 1; + /* Reset volume history. */ + stl->effects->volume_current_sample = -1; + common_data->vol_history_alpha = 0.0f; + } + pinfo->update_world = 0; + DRW_viewport_request_redraw(); + /* Do not let this frame accumulate. */ + stl->effects->taa_current_sample = 1; + + DRW_viewport_matrix_override_set_all(&saved_mats); +} + +static void lightprobes_refresh_initialize_grid(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_LightProbesInfo *pinfo = sldata->probes; + EEVEE_PassList *psl = vedata->psl; + if (pinfo->grid_initialized) { + /* Grid is already initialized, nothing to do. */ + return; + } + /* Flood fill with world irradiance. */ + GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0); + GPU_framebuffer_bind(sldata->probe_filter_fb); + DRW_draw_pass(psl->probe_grid_fill); + + SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); + + GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0); + GPU_framebuffer_bind(sldata->probe_filter_fb); + DRW_draw_pass(psl->probe_grid_fill); + + SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); + + pinfo->grid_initialized = true; +} + +void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + Object *ob; + EEVEE_LightProbesInfo *pinfo = sldata->probes; + DRWMatrixState saved_mats; + + if (pinfo->num_planar == 0) { + /* Disable SSR if we cannot read previous frame */ + common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer; + common_data->prb_num_planar = 0; + return; + } + + EEVEE_planar_reflections_updates(sldata); + DRW_uniformbuffer_update(sldata->planar_ubo, &sldata->probes->planar_data); + + /* We need to save the Matrices before overidding them */ + DRW_viewport_matrix_get_all(&saved_mats); + + /* Temporary Remove all planar reflections (avoid lag effect). */ + common_data->prb_num_planar = 0; + /* Turn off ssr to avoid black specular */ + common_data->ssr_toggle = false; + common_data->sss_toggle = false; + + DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data); + + for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) { + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + LightProbe *prb = (LightProbe *)ob->data; + pinfo->vis_data.collection = prb->visibility_grp; + pinfo->vis_data.invert = prb->flag & LIGHTPROBE_FLAG_INVERT_GROUP; + render_scene_to_planar(sldata, vedata, i, ped); + } + + /* Restore */ + common_data->prb_num_planar = pinfo->num_planar; + common_data->ssr_toggle = true; + common_data->sss_toggle = true; + + /* Prefilter for SSR */ + if ((vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) { + const int max_lod = 9; + DRW_stats_group_start("Planar Probe Downsample"); + + GPU_framebuffer_ensure_config(&fbl->planar_downsample_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->planar_pool) + }); + GPU_framebuffer_recursive_downsample(fbl->planar_downsample_fb, max_lod, &downsample_planar, vedata); + /* For shading, save max level of the planar map */ + common_data->prb_lod_planar_max = (float)(max_lod); + DRW_stats_group_end(); + } + + DRW_viewport_matrix_override_set_all(&saved_mats); + + if (DRW_state_is_image_render()) { + /* Sort transparents because planar reflections could have re-sorted them. */ + DRW_pass_sort_shgroup_z(vedata->psl->transparent_pass); + } + + /* Disable SSR if we cannot read previous frame */ + common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer; +} + +static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_LightProbesInfo *pinfo = sldata->probes; + Object *ob; + for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) { + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + if (!ped->need_update) { + continue; + } + LightProbe *prb = (LightProbe *)ob->data; + pinfo->vis_data.collection = prb->visibility_grp; + pinfo->vis_data.invert = prb->flag & LIGHTPROBE_FLAG_INVERT_GROUP; + render_scene_to_probe(sldata, vedata, ob->obmat[3], prb->clipsta, prb->clipend); + glossy_filter_probe(sldata, vedata, psl, i, prb->intensity); + ped->need_update = false; + ped->probe_id = i; + if (!ped->ready_to_shade) { + common_data->prb_num_render_cube++; + ped->ready_to_shade = true; + } +#if 0 + printf("Update Cubemap %d\n", i); +#endif + DRW_viewport_request_redraw(); + /* Do not let this frame accumulate. */ + stl->effects->taa_current_sample = 1; + /* Only do one probe per frame */ + return; + } + + pinfo->do_cube_update = false; +} + +static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_LightProbesInfo *pinfo = sldata->probes; + Object *ob; + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + + if (draw_ctx->evil_C != NULL) { + /* Only compute probes if not navigating or in playback */ + struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C); + if (((rv3d->rflag & RV3D_NAVIGATING) != 0) || ED_screen_animation_no_scrub(wm) != NULL) { + return; + } + } + /* We need to save the Matrices before overidding them */ + DRWMatrixState saved_mats; + DRW_viewport_matrix_get_all(&saved_mats); + /* Make sure grid is initialized. */ + lightprobes_refresh_initialize_grid(sldata, vedata); + /* Reflection probes depend on diffuse lighting thus on irradiance grid, + * so update them first. */ + while (pinfo->updated_bounce < pinfo->num_bounce) { + common_data->prb_num_render_grid = pinfo->num_grid; + /* TODO(sergey): This logic can be split into smaller functions. */ + for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); i++) { + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + if (!ped->need_update) { + continue; + } + EEVEE_LightGrid *egrid = &pinfo->grid_data[i]; + LightProbe *prb = (LightProbe *)ob->data; + /* Find the next cell corresponding to the current level. */ + bool valid_cell = false; + int cell_id = ped->updated_cells; + float pos[3], grid_loc[3]; + /* Other levels */ + int current_stride = 1 << max_ii(0, ped->max_lvl - ped->updated_lvl); + int prev_stride = current_stride << 1; + bool do_rendering = true; + while (!valid_cell) { + cell_id = ped->updated_cells; + lightprobe_cell_grid_location_get(egrid, cell_id, grid_loc); + if (ped->updated_lvl == 0 && cell_id == 0) { + valid_cell = true; + ped->updated_cells = ped->num_cell; + continue; + } + else if (((((int)grid_loc[0] % current_stride) == 0) && + (((int)grid_loc[1] % current_stride) == 0) && + (((int)grid_loc[2] % current_stride) == 0)) && + !((((int)grid_loc[0] % prev_stride) == 0) && + (((int)grid_loc[1] % prev_stride) == 0) && + (((int)grid_loc[2] % prev_stride) == 0))) + { + valid_cell = true; + } + ped->updated_cells++; + if (ped->updated_cells > ped->num_cell) { + do_rendering = false; + break; + } + } + if (do_rendering) { + lightprobe_cell_world_location_get(egrid, grid_loc, pos); + SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); + /* Temporary Remove all probes. */ + int tmp_num_render_grid = common_data->prb_num_render_grid; + int tmp_num_render_cube = common_data->prb_num_render_cube; + int tmp_num_planar = common_data->prb_num_planar; + float tmp_level_bias = egrid->level_bias; + common_data->prb_num_render_cube = 0; + common_data->prb_num_planar = 0; + /* Use light from previous bounce when capturing radiance. */ + if (pinfo->updated_bounce == 0) { + /* But not on first bounce. */ + common_data->prb_num_render_grid = 0; + } + else { + /* Remove bias */ + egrid->level_bias = (float)(1 << 0); + DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data); + } + pinfo->vis_data.collection = prb->visibility_grp; + pinfo->vis_data.invert = prb->flag & LIGHTPROBE_FLAG_INVERT_GROUP; + render_scene_to_probe(sldata, vedata, pos, prb->clipsta, prb->clipend); + diffuse_filter_probe(sldata, vedata, psl, egrid->offset + cell_id, + prb->clipsta, prb->clipend, egrid->visibility_range, prb->vis_blur, + prb->intensity); + /* To see what is going on. */ + SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); + /* Restore */ + common_data->prb_num_render_cube = tmp_num_render_cube; + pinfo->num_planar = tmp_num_planar; + if (pinfo->updated_bounce == 0) { + common_data->prb_num_render_grid = tmp_num_render_grid; + } + else { + egrid->level_bias = tmp_level_bias; + DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data); + } +#if 0 + printf("Updated Grid %d : cell %d / %d, bounce %d / %d\n", + i, cell_id + 1, ped->num_cell, pinfo->updated_bounce + 1, pinfo->num_bounce); +#endif + } + if (ped->updated_cells >= ped->num_cell) { + ped->updated_lvl++; + ped->updated_cells = 0; + if (ped->updated_lvl > ped->max_lvl) { + ped->need_update = false; + } + egrid->level_bias = (float)(1 << max_ii(0, ped->max_lvl - ped->updated_lvl + 1)); + DRW_uniformbuffer_update(sldata->grid_ubo, &sldata->probes->grid_data); + } + /* Only do one probe per frame */ + DRW_viewport_request_redraw(); + /* Do not let this frame accumulate. */ + stl->effects->taa_current_sample = 1; + /* Reset volume history. */ + stl->effects->volume_current_sample = -1; + common_data->vol_history_alpha = 0.0f; + /* Restore matrices */ + DRW_viewport_matrix_override_set_all(&saved_mats); + return; + } + + pinfo->updated_bounce++; + common_data->prb_num_render_grid = pinfo->num_grid; + + if (pinfo->updated_bounce < pinfo->num_bounce) { + /* Retag all grids to update for next bounce */ + for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); i++) { + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); + ped->need_update = true; + ped->updated_cells = 0; + ped->updated_lvl = 0; + } + /* Reset the next buffer so we can see the progress. */ + /* irradiance_rt is already the next rt because of the previous SWAP */ + GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0); + GPU_framebuffer_bind(sldata->probe_filter_fb); + DRW_draw_pass(psl->probe_grid_fill); + + GPU_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0); + /* Swap AFTER */ + SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); + } + } + /* Refresh cube probe when needed. */ + lightprobes_refresh_cube(sldata, vedata); + /* Restore matrices */ + DRW_viewport_matrix_override_set_all(&saved_mats); +} + +bool EEVEE_lightprobes_all_probes_ready(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(vedata)) +{ + EEVEE_LightProbesInfo *pinfo = sldata->probes; + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + + return ((pinfo->do_cube_update == false) && + (pinfo->updated_bounce == pinfo->num_bounce) && + (common_data->prb_num_render_cube == pinfo->num_cube)); +} + +void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_LightProbesInfo *pinfo = sldata->probes; + + /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */ + common_data->spec_toggle = false; + common_data->ssr_toggle = false; + common_data->sss_toggle = false; + + /* Disable AO until we find a way to hide really bad discontinuities between cubefaces. */ + float tmp_ao_dist = common_data->ao_dist; + float tmp_ao_settings = common_data->ao_settings; + common_data->ao_settings = 0.0f; + common_data->ao_dist = 0.0f; + + /* Render world in priority */ + if (pinfo->update_world) { + lightprobes_refresh_world(sldata, vedata); + } + else if (EEVEE_lightprobes_all_probes_ready(sldata, vedata) == false && pinfo->all_materials_updated) { + lightprobes_refresh_all_no_world(sldata, vedata); + } + + /* Restore */ + common_data->spec_toggle = true; + common_data->ssr_toggle = true; + common_data->sss_toggle = true; + common_data->ao_dist = tmp_ao_dist; + common_data->ao_settings = tmp_ao_settings; +} + +void EEVEE_lightprobes_free(void) +{ + MEM_SAFE_FREE(e_data.format_probe_display_cube); + MEM_SAFE_FREE(e_data.format_probe_display_planar); + DRW_SHADER_FREE_SAFE(e_data.probe_default_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_default_studiolight_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_filter_visibility_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_grid_fill_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_grid_display_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_planar_display_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_planar_downsample_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_cube_display_sh); + DRW_TEXTURE_FREE_SAFE(e_data.hammersley); + DRW_TEXTURE_FREE_SAFE(e_data.planar_pool_placeholder); + DRW_TEXTURE_FREE_SAFE(e_data.depth_placeholder); + DRW_TEXTURE_FREE_SAFE(e_data.depth_array_placeholder); +} diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c new file mode 100644 index 00000000000..dd69e19e7c1 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -0,0 +1,1248 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_lights.c + * \ingroup DNA + */ + +#include "DRW_render.h" + +#include "BLI_dynstr.h" +#include "BLI_rect.h" + +#include "BKE_object.h" + +#include "DEG_depsgraph_query.h" + +#include "eevee_engine.h" +#include "eevee_private.h" + +#define SHADOW_CASTER_ALLOC_CHUNK 16 + +static struct { + struct GPUShader *shadow_sh; + struct GPUShader *shadow_store_cube_sh[SHADOW_METHOD_MAX]; + struct GPUShader *shadow_store_cascade_sh[SHADOW_METHOD_MAX]; + struct GPUShader *shadow_copy_cube_sh[SHADOW_METHOD_MAX]; + struct GPUShader *shadow_copy_cascade_sh[SHADOW_METHOD_MAX]; +} e_data = {NULL}; /* Engine data */ + +extern char datatoc_shadow_vert_glsl[]; +extern char datatoc_shadow_frag_glsl[]; +extern char datatoc_shadow_store_frag_glsl[]; +extern char datatoc_shadow_copy_frag_glsl[]; +extern char datatoc_concentric_samples_lib_glsl[]; + +/* Prototype */ +static void eevee_light_setup(Object *ob, EEVEE_Light *evli); + +/* *********** LIGHT BITS *********** */ +static void lightbits_set_single(EEVEE_LightBits *bitf, uint idx, bool val) +{ + if (val) { + bitf->fields[idx / 8] |= (1 << (idx % 8)); + } + else { + bitf->fields[idx / 8] &= ~(1 << (idx % 8)); + } +} + +static void lightbits_set_all(EEVEE_LightBits *bitf, bool val) +{ + memset(bitf, (val) ? 0xFF : 0x00, sizeof(EEVEE_LightBits)); +} + +static void lightbits_or(EEVEE_LightBits *r, const EEVEE_LightBits *v) +{ + for (int i = 0; i < MAX_LIGHTBITS_FIELDS; ++i) { + r->fields[i] |= v->fields[i]; + } +} + +static bool lightbits_get(const EEVEE_LightBits *r, uint idx) +{ + return r->fields[idx / 8] & (1 << (idx % 8)); +} + +static void lightbits_convert( + EEVEE_LightBits *r, const EEVEE_LightBits *bitf, const int *light_bit_conv_table, uint table_length) +{ + for (int i = 0; i < table_length; ++i) { + if (lightbits_get(bitf, i) != 0) { + if (light_bit_conv_table[i] >= 0) { + r->fields[i / 8] |= (1 << (i % 8)); + } + } + } +} + +/* *********** FUNCTIONS *********** */ + +void EEVEE_lights_init(EEVEE_ViewLayerData *sldata) +{ + const uint shadow_ubo_size = sizeof(EEVEE_Shadow) * MAX_SHADOW + + sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE + + sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + if (!e_data.shadow_sh) { + e_data.shadow_sh = DRW_shader_create( + datatoc_shadow_vert_glsl, NULL, datatoc_shadow_frag_glsl, NULL); + } + + if (!sldata->lamps) { + sldata->lamps = MEM_callocN(sizeof(EEVEE_LampsInfo), "EEVEE_LampsInfo"); + sldata->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL); + sldata->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL); + sldata->shadow_render_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_ShadowRender), NULL); + + for (int i = 0; i < 2; ++i) { + sldata->shcasters_buffers[i].shadow_casters = MEM_callocN(sizeof(EEVEE_ShadowCaster) * SHADOW_CASTER_ALLOC_CHUNK, "EEVEE_ShadowCaster buf"); + sldata->shcasters_buffers[i].flags = MEM_callocN(sizeof(sldata->shcasters_buffers[0].flags) * SHADOW_CASTER_ALLOC_CHUNK, "EEVEE_shcast_buffer flags buf"); + sldata->shcasters_buffers[i].alloc_count = SHADOW_CASTER_ALLOC_CHUNK; + sldata->shcasters_buffers[i].count = 0; + } + + sldata->lamps->shcaster_frontbuffer = &sldata->shcasters_buffers[0]; + sldata->lamps->shcaster_backbuffer = &sldata->shcasters_buffers[1]; + } + + /* Flip buffers */ + SWAP(EEVEE_ShadowCasterBuffer *, sldata->lamps->shcaster_frontbuffer, sldata->lamps->shcaster_backbuffer); + + const int sh_method = scene_eval->eevee.shadow_method; + int sh_cube_size = scene_eval->eevee.shadow_cube_size; + int sh_cascade_size = scene_eval->eevee.shadow_cascade_size; + const bool sh_high_bitdepth = (scene_eval->eevee.flag & SCE_EEVEE_SHADOW_HIGH_BITDEPTH) != 0; + + EEVEE_LampsInfo *linfo = sldata->lamps; + if ((linfo->shadow_cube_size != sh_cube_size) || + (linfo->shadow_method != sh_method) || + (linfo->shadow_high_bitdepth != sh_high_bitdepth)) + { + BLI_assert((sh_cube_size > 0) && (sh_cube_size <= 4096)); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_pool); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur); + + /* Compute adequate size for the octahedral map. */ + linfo->shadow_cube_store_size = (int)ceil(sqrt((sh_cube_size * sh_cube_size) * 6.0f)); + + CLAMP(linfo->shadow_cube_store_size, 1, 4096); + CLAMP(sh_cube_size, 1, 4096); + + linfo->shadow_render_data.cube_texel_size = 1.0f / sh_cube_size; + } + + if ((linfo->shadow_cascade_size != sh_cascade_size) || + (linfo->shadow_method != sh_method) || + (linfo->shadow_high_bitdepth != sh_high_bitdepth)) + { + BLI_assert((sh_cascade_size > 0) && (sh_cascade_size <= 4096)); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_pool); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target); + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur); + + CLAMP(sh_cascade_size, 1, 4096); + } + + linfo->shadow_high_bitdepth = sh_high_bitdepth; + linfo->shadow_method = sh_method; + linfo->shadow_cube_size = sh_cube_size; + linfo->shadow_cascade_size = sh_cascade_size; + + /* only compile the ones needed. reduce startup time. */ + if ((sh_method == SHADOW_ESM) && !e_data.shadow_store_cube_sh[SHADOW_ESM]) { + DynStr *ds_frag = BLI_dynstr_new(); + BLI_dynstr_append(ds_frag, datatoc_concentric_samples_lib_glsl); + BLI_dynstr_append(ds_frag, datatoc_shadow_store_frag_glsl); + char *store_shadow_shader_str = BLI_dynstr_get_cstring(ds_frag); + BLI_dynstr_free(ds_frag); + + e_data.shadow_store_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen( + store_shadow_shader_str, + "#define ESM\n"); + e_data.shadow_store_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen( + store_shadow_shader_str, + "#define ESM\n" + "#define CSM\n"); + MEM_freeN(store_shadow_shader_str); + + e_data.shadow_copy_cube_sh[SHADOW_ESM] = DRW_shader_create_fullscreen( + datatoc_shadow_copy_frag_glsl, + "#define ESM\n" + "#define COPY\n"); + e_data.shadow_copy_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen( + datatoc_shadow_copy_frag_glsl, + "#define ESM\n" + "#define COPY\n" + "#define CSM\n"); + } + else if ((sh_method == SHADOW_VSM) && !e_data.shadow_store_cube_sh[SHADOW_VSM]) { + DynStr *ds_frag = BLI_dynstr_new(); + BLI_dynstr_append(ds_frag, datatoc_concentric_samples_lib_glsl); + BLI_dynstr_append(ds_frag, datatoc_shadow_store_frag_glsl); + char *store_shadow_shader_str = BLI_dynstr_get_cstring(ds_frag); + BLI_dynstr_free(ds_frag); + + e_data.shadow_store_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen( + store_shadow_shader_str, + "#define VSM\n"); + e_data.shadow_store_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen( + store_shadow_shader_str, + "#define VSM\n" + "#define CSM\n"); + MEM_freeN(store_shadow_shader_str); + + e_data.shadow_copy_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen( + datatoc_shadow_copy_frag_glsl, + "#define VSM\n" + "#define COPY\n"); + e_data.shadow_copy_cascade_sh[SHADOW_VSM] = DRW_shader_create_fullscreen( + datatoc_shadow_copy_frag_glsl, + "#define VSM\n" + "#define COPY\n" + "#define CSM\n"); + } +} + +void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_LampsInfo *linfo = sldata->lamps; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PassList *psl = vedata->psl; + + linfo->shcaster_frontbuffer->count = 0; + linfo->num_light = 0; + linfo->num_cube_layer = 0; + linfo->num_cascade_layer = 0; + linfo->gpu_cube_ct = linfo->gpu_cascade_ct = linfo->gpu_shadow_ct = 0; + linfo->cpu_cube_ct = linfo->cpu_cascade_ct = 0; + memset(linfo->light_ref, 0, sizeof(linfo->light_ref)); + memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_ref)); + memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref)); + memset(linfo->new_shadow_id, -1, sizeof(linfo->new_shadow_id)); + + /* Shadow Casters: Reset flags. */ + memset(linfo->shcaster_backbuffer->flags, (char)SHADOW_CASTER_PRUNED, linfo->shcaster_backbuffer->alloc_count); + memset(linfo->shcaster_frontbuffer->flags, 0x00, linfo->shcaster_frontbuffer->alloc_count); + + { + psl->shadow_cube_store_pass = DRW_pass_create("Shadow Storage Pass", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create( + e_data.shadow_store_cube_sh[linfo->shadow_method], psl->shadow_cube_store_pass); + DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cube_blur); + DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); + DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { + psl->shadow_cascade_store_pass = DRW_pass_create("Shadow Cascade Storage Pass", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create( + e_data.shadow_store_cascade_sh[linfo->shadow_method], psl->shadow_cascade_store_pass); + DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cascade_blur); + DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); + DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1); + DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { + psl->shadow_cube_copy_pass = DRW_pass_create("Shadow Copy Pass", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create( + e_data.shadow_copy_cube_sh[linfo->shadow_method], psl->shadow_cube_copy_pass); + DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cube_target); + DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); + DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); + DRW_shgroup_uniform_int(grp, "faceId", &linfo->current_shadow_face, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { + psl->shadow_cascade_copy_pass = DRW_pass_create("Shadow Cascade Copy Pass", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create( + e_data.shadow_copy_cascade_sh[linfo->shadow_method], psl->shadow_cascade_copy_pass); + DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cascade_target); + DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); + DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); + DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + psl->shadow_pass = DRW_pass_create("Shadow Pass", state); + + stl->g_data->shadow_shgrp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass); + } +} + +void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) +{ + EEVEE_LampsInfo *linfo = sldata->lamps; + + /* Step 1 find all lamps in the scene and setup them */ + if (linfo->num_light >= MAX_LIGHT) { + printf("Too many lamps in the scene !!!\n"); + } + else { + Lamp *la = (Lamp *)ob->data; + EEVEE_Light *evli = linfo->light_data + linfo->num_light; + eevee_light_setup(ob, evli); + + /* We do not support shadowmaps for dupli lamps. */ + if ((ob->base_flag & BASE_FROMDUPLI) != 0) { + linfo->num_light++; + return; + } + + EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); + + /* Save previous shadow id. */ + int prev_cube_sh_id = led->prev_cube_shadow_id; + + /* Default light without shadows */ + led->data.ld.shadow_id = -1; + led->prev_cube_shadow_id = -1; + + if (la->mode & LA_SHADOW) { + if (la->type == LA_SUN) { + int sh_nbr = 1; /* TODO : MSM */ + int cascade_nbr = la->cascade_count; + + if ((linfo->gpu_cascade_ct + sh_nbr) <= MAX_SHADOW_CASCADE) { + /* Save Light object. */ + linfo->shadow_cascade_ref[linfo->cpu_cascade_ct] = ob; + + /* Store indices. */ + EEVEE_ShadowCascadeData *data = &led->data.scad; + data->shadow_id = linfo->gpu_shadow_ct; + data->cascade_id = linfo->gpu_cascade_ct; + data->layer_id = linfo->num_cascade_layer; + + /* Increment indices. */ + linfo->gpu_shadow_ct += 1; + linfo->gpu_cascade_ct += sh_nbr; + linfo->num_cascade_layer += sh_nbr * cascade_nbr; + + linfo->cpu_cascade_ct += 1; + } + } + else if (la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA) { + int sh_nbr = 1; /* TODO : MSM */ + + if ((linfo->gpu_cube_ct + sh_nbr) <= MAX_SHADOW_CUBE) { + /* Save Light object. */ + linfo->shadow_cube_ref[linfo->cpu_cube_ct] = ob; + + /* For light update tracking. */ + if ((prev_cube_sh_id >= 0) && + (prev_cube_sh_id < linfo->shcaster_backbuffer->count)) + { + linfo->new_shadow_id[prev_cube_sh_id] = linfo->cpu_cube_ct; + } + led->prev_cube_shadow_id = linfo->cpu_cube_ct; + + /* Saving lamp bounds for later. */ + BLI_assert(linfo->cpu_cube_ct >= 0 && linfo->cpu_cube_ct < MAX_LIGHT); + copy_v3_v3(linfo->shadow_bounds[linfo->cpu_cube_ct].center, ob->obmat[3]); + linfo->shadow_bounds[linfo->cpu_cube_ct].radius = la->clipend; + + EEVEE_ShadowCubeData *data = &led->data.scd; + /* Store indices. */ + data->shadow_id = linfo->gpu_shadow_ct; + data->cube_id = linfo->gpu_cube_ct; + data->layer_id = linfo->num_cube_layer; + + /* Increment indices. */ + linfo->gpu_shadow_ct += 1; + linfo->gpu_cube_ct += sh_nbr; + linfo->num_cube_layer += sh_nbr; + + linfo->cpu_cube_ct += 1; + } + } + } + + led->data.ld.light_id = linfo->num_light; + linfo->light_ref[linfo->num_light] = ob; + linfo->num_light++; + } +} + +/* Add a shadow caster to the shadowpasses */ +void EEVEE_lights_cache_shcaster_add( + EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_StorageList *stl, struct Gwn_Batch *geom, Object *ob) +{ + DRW_shgroup_call_object_add( + stl->g_data->shadow_shgrp, + geom, ob); +} + +void EEVEE_lights_cache_shcaster_material_add( + EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_PassList *psl, struct GPUMaterial *gpumat, + struct Gwn_Batch *geom, struct Object *ob, float *alpha_threshold) +{ + /* TODO / PERF : reuse the same shading group for objects with the same material */ + DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass); + + if (grp == NULL) return; + + if (alpha_threshold != NULL) + DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1); + + DRW_shgroup_call_object_add(grp, geom, ob); +} + +/* Make that object update shadow casting lamps inside its influence bounding box. */ +void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, Object *ob) +{ + if ((ob->base_flag & BASE_FROMDUPLI) != 0) { + /* TODO: Special case for dupli objects because we cannot save the object pointer. */ + return; + } + + EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob); + EEVEE_LampsInfo *linfo = sldata->lamps; + EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer; + EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer; + int past_id = oedata->shadow_caster_id; + + /* Update flags in backbuffer. */ + if (past_id > -1 && past_id < backbuffer->count) { + backbuffer->flags[past_id] &= ~SHADOW_CASTER_PRUNED; + + if (oedata->need_update) { + backbuffer->flags[past_id] |= SHADOW_CASTER_UPDATED; + } + } + + /* Update id. */ + oedata->shadow_caster_id = frontbuffer->count++; + + /* Make sure shadow_casters is big enough. */ + if (oedata->shadow_caster_id >= frontbuffer->alloc_count) { + frontbuffer->alloc_count += SHADOW_CASTER_ALLOC_CHUNK; + frontbuffer->shadow_casters = MEM_reallocN(frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count); + frontbuffer->flags = MEM_reallocN(frontbuffer->flags, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count); + } + + EEVEE_ShadowCaster *shcaster = frontbuffer->shadow_casters + oedata->shadow_caster_id; + + if (oedata->need_update) { + frontbuffer->flags[oedata->shadow_caster_id] = SHADOW_CASTER_UPDATED; + } + + /* Update World AABB in frontbuffer. */ + BoundBox *bb = BKE_object_boundbox_get(ob); + float min[3], max[3]; + INIT_MINMAX(min, max); + for (int i = 0; i < 8; ++i) { + float vec[3]; + copy_v3_v3(vec, bb->vec[i]); + mul_m4_v3(ob->obmat, vec); + minmax_v3v3_v3(min, max, vec); + } + + EEVEE_BoundBox *aabb = &shcaster->bbox; + add_v3_v3v3(aabb->center, min, max); + mul_v3_fl(aabb->center, 0.5f); + sub_v3_v3v3(aabb->halfdim, aabb->center, max); + + aabb->halfdim[0] = fabsf(aabb->halfdim[0]); + aabb->halfdim[1] = fabsf(aabb->halfdim[1]); + aabb->halfdim[2] = fabsf(aabb->halfdim[2]); + + oedata->need_update = false; +} + +void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata) +{ + EEVEE_LampsInfo *linfo = sldata->lamps; + GPUTextureFormat shadow_pool_format = GPU_R32F; + + sldata->common_data.la_num_light = linfo->num_light; + + /* Setup enough layers. */ + /* Free textures if number mismatch. */ + if (linfo->num_cube_layer != linfo->cache_num_cube_layer) { + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_pool); + linfo->cache_num_cube_layer = linfo->num_cube_layer; + linfo->update_flag |= LIGHT_UPDATE_SHADOW_CUBE; + } + + if (linfo->num_cascade_layer != linfo->cache_num_cascade_layer) { + DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_pool); + linfo->cache_num_cascade_layer = linfo->num_cascade_layer; + } + + switch (linfo->shadow_method) { + case SHADOW_ESM: shadow_pool_format = ((linfo->shadow_high_bitdepth) ? GPU_R32F : GPU_R16F); break; + case SHADOW_VSM: shadow_pool_format = ((linfo->shadow_high_bitdepth) ? GPU_RG32F : GPU_RG16F); break; + default: + BLI_assert(!"Incorrect Shadow Method"); + break; + } + + /* Cubemaps */ + if (!sldata->shadow_cube_target) { + sldata->shadow_cube_target = DRW_texture_create_cube( + linfo->shadow_cube_size, GPU_DEPTH_COMPONENT24, 0, NULL); + sldata->shadow_cube_blur = DRW_texture_create_cube( + linfo->shadow_cube_size, shadow_pool_format, DRW_TEX_FILTER, NULL); + } + if (!sldata->shadow_cube_pool) { + sldata->shadow_cube_pool = DRW_texture_create_2D_array( + linfo->shadow_cube_store_size, linfo->shadow_cube_store_size, max_ii(1, linfo->num_cube_layer), + shadow_pool_format, DRW_TEX_FILTER, NULL); + } + GPU_framebuffer_ensure_config(&sldata->shadow_cube_target_fb, { + GPU_ATTACHMENT_TEXTURE(sldata->shadow_cube_target) + }); + GPU_framebuffer_ensure_config(&sldata->shadow_cube_store_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(sldata->shadow_cube_pool) + }); + + /* CSM */ + if (!sldata->shadow_cascade_target) { + sldata->shadow_cascade_target = DRW_texture_create_2D_array( + linfo->shadow_cascade_size, linfo->shadow_cascade_size, MAX_CASCADE_NUM, GPU_DEPTH_COMPONENT24, 0, NULL); + sldata->shadow_cascade_blur = DRW_texture_create_2D_array( + linfo->shadow_cascade_size, linfo->shadow_cascade_size, MAX_CASCADE_NUM, shadow_pool_format, DRW_TEX_FILTER, NULL); + } + if (!sldata->shadow_cascade_pool) { + sldata->shadow_cascade_pool = DRW_texture_create_2D_array( + linfo->shadow_cascade_size, linfo->shadow_cascade_size, max_ii(1, linfo->num_cascade_layer), + shadow_pool_format, DRW_TEX_FILTER, NULL); + } + GPU_framebuffer_ensure_config(&sldata->shadow_cascade_target_fb, { + GPU_ATTACHMENT_TEXTURE(sldata->shadow_cascade_target) + }); + GPU_framebuffer_ensure_config(&sldata->shadow_cascade_store_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(sldata->shadow_cascade_pool) + }); + + /* Update Lamps UBOs. */ + EEVEE_lights_update(sldata); +} + +/* Update buffer with lamp data */ +static void eevee_light_setup(Object *ob, EEVEE_Light *evli) +{ + Lamp *la = (Lamp *)ob->data; + float mat[4][4], scale[3], power; + + /* Position */ + copy_v3_v3(evli->position, ob->obmat[3]); + + /* Color */ + copy_v3_v3(evli->color, &la->r); + + evli->spec = la->spec_fac; + + /* Influence Radius */ + evli->dist = la->dist; + + /* Vectors */ + normalize_m4_m4_ex(mat, ob->obmat, scale); + copy_v3_v3(evli->forwardvec, mat[2]); + normalize_v3(evli->forwardvec); + negate_v3(evli->forwardvec); + + copy_v3_v3(evli->rightvec, mat[0]); + normalize_v3(evli->rightvec); + + copy_v3_v3(evli->upvec, mat[1]); + normalize_v3(evli->upvec); + + /* Spot size & blend */ + if (la->type == LA_SPOT) { + evli->sizex = scale[0] / scale[2]; + evli->sizey = scale[1] / scale[2]; + evli->spotsize = cosf(la->spotsize * 0.5f); + evli->spotblend = (1.0f - evli->spotsize) * la->spotblend; + evli->radius = max_ff(0.001f, la->area_size); + } + else if (la->type == LA_AREA) { + evli->sizex = max_ff(0.0001f, la->area_size * scale[0] * 0.5f); + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { + evli->sizey = max_ff(0.0001f, la->area_sizey * scale[1] * 0.5f); + } + else { + evli->sizey = max_ff(0.0001f, la->area_size * scale[1] * 0.5f); + } + } + else { + evli->radius = max_ff(0.001f, la->area_size); + } + + /* Lamp Type */ + evli->lamptype = (float)la->type; + + /* Make illumination power constant */ + if (la->type == LA_AREA) { + power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */ + 80.0f; /* XXX : Empirical, Fit cycles power */ + if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { + evli->lamptype = LAMPTYPE_AREA_ELLIPSE; + /* Scale power to account for the lower area of the ellipse compared to the surrouding rectangle. */ + power *= 4.0f / M_PI; + } + } + else if (la->type == LA_SPOT || la->type == LA_LOCAL) { + power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(4*r²*Pi²) */ + M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */ + + /* for point lights (a.k.a radius == 0.0) */ + // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */ + } + else { + power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(r²*Pi) */ + 12.5f; /* XXX : Empirical, Fit cycles power */ + } + mul_v3_fl(evli->color, power * la->energy); + + /* No shadow by default */ + evli->shadowid = -1.0f; +} + +static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led) +{ + EEVEE_ShadowCubeData *sh_data = &led->data.scd; + EEVEE_Light *evli = linfo->light_data + sh_data->light_id; + EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id; + EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + sh_data->cube_id; + Lamp *la = (Lamp *)ob->data; + + int sh_nbr = 1; /* TODO: MSM */ + + for (int i = 0; i < sh_nbr; ++i) { + /* TODO : choose MSM sample point here. */ + copy_v3_v3(cube_data->position, ob->obmat[3]); + } + + ubo_data->bias = 0.05f * la->bias; + ubo_data->near = la->clipsta; + ubo_data->far = la->clipend; + ubo_data->exp = (linfo->shadow_method == SHADOW_VSM) ? la->bleedbias : la->bleedexp; + + evli->shadowid = (float)(sh_data->shadow_id); + ubo_data->shadow_start = (float)(sh_data->layer_id); + ubo_data->data_start = (float)(sh_data->cube_id); + ubo_data->multi_shadow_count = (float)(sh_nbr); + ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */ + + ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f; + ubo_data->contact_bias = 0.05f * la->contact_bias; + ubo_data->contact_spread = la->contact_spread; + ubo_data->contact_thickness = la->contact_thickness; +} + +#define LERP(t, a, b) ((a) + (t) * ((b) - (a))) + +static double round_to_digits(double value, int digits) +{ + double factor = pow(10.0, digits - ceil(log10(fabs(value)))); + return round(value * factor) / factor; +} + +static void frustum_min_bounding_sphere(const float corners[8][3], float r_center[3], float *r_radius) +{ +#if 0 /* Simple solution but waste too much space. */ + float minvec[3], maxvec[3]; + + /* compute the bounding box */ + INIT_MINMAX(minvec, maxvec); + for (int i = 0; i < 8; ++i) { + minmax_v3v3_v3(minvec, maxvec, corners[i]); + } + + /* compute the bounding sphere of this box */ + r_radius = len_v3v3(minvec, maxvec) * 0.5f; + add_v3_v3v3(r_center, minvec, maxvec); + mul_v3_fl(r_center, 0.5f); +#else + /* Find averaged center. */ + zero_v3(r_center); + for (int i = 0; i < 8; ++i) { + add_v3_v3(r_center, corners[i]); + } + mul_v3_fl(r_center, 1.0f / 8.0f); + + /* Search the largest distance from the sphere center. */ + *r_radius = 0.0f; + for (int i = 0; i < 8; ++i) { + float rad = len_squared_v3v3(corners[i], r_center); + if (rad > *r_radius) { + *r_radius = rad; + } + } + + /* TODO try to reduce the radius further by moving the center. + * Remember we need a __stable__ solution! */ + + /* Try to reduce float imprecision leading to shimmering. */ + *r_radius = (float)round_to_digits(sqrtf(*r_radius), 3); +#endif +} + +static void eevee_shadow_cascade_setup( + Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led, + DRWMatrixState *saved_mats, float view_near, float view_far) +{ + Lamp *la = (Lamp *)ob->data; + + /* Camera Matrices */ + float (*persinv)[4] = saved_mats->mat[DRW_MAT_PERSINV]; + float (*vp_projmat)[4] = saved_mats->mat[DRW_MAT_WIN]; + bool is_persp = DRW_viewport_is_persp_get(); + + /* Lamps Matrices */ + int sh_nbr = 1; /* TODO : MSM */ + int cascade_nbr = la->cascade_count; + + EEVEE_ShadowCascadeData *sh_data = &led->data.scad; + EEVEE_Light *evli = linfo->light_data + sh_data->light_id; + EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id; + EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id; + + /* obmat = Object Space > World Space */ + /* viewmat = World Space > View Space */ + float (*viewmat)[4] = sh_data->viewmat; +#if 0 /* done at culling time */ + normalize_m4_m4(viewmat, ob->obmat); +#endif + invert_m4(viewmat); + invert_m4_m4(sh_data->viewinv, viewmat); + + /* The technique consists into splitting + * the view frustum into several sub-frustum + * that are individually receiving one shadow map */ + + float csm_start, csm_end; + + if (is_persp) { + csm_start = view_near; + csm_end = max_ff(view_far, -la->cascade_max_dist); + /* Avoid artifacts */ + csm_end = min_ff(view_near, csm_end); + } + else { + csm_start = -view_far; + csm_end = view_far; + } + + /* init near/far */ + for (int c = 0; c < MAX_CASCADE_NUM; ++c) { + cascade_data->split_start[c] = csm_end; + cascade_data->split_end[c] = csm_end; + } + + /* Compute split planes */ + float splits_start_ndc[MAX_CASCADE_NUM]; + float splits_end_ndc[MAX_CASCADE_NUM]; + + { + /* Nearest plane */ + float p[4] = {1.0f, 1.0f, csm_start, 1.0f}; + /* TODO: we don't need full m4 multiply here */ + mul_m4_v4(vp_projmat, p); + splits_start_ndc[0] = p[2]; + if (is_persp) { + splits_start_ndc[0] /= p[3]; + } + } + + { + /* Farthest plane */ + float p[4] = {1.0f, 1.0f, csm_end, 1.0f}; + /* TODO: we don't need full m4 multiply here */ + mul_m4_v4(vp_projmat, p); + splits_end_ndc[cascade_nbr - 1] = p[2]; + if (is_persp) { + splits_end_ndc[cascade_nbr - 1] /= p[3]; + } + } + + cascade_data->split_start[0] = csm_start; + cascade_data->split_end[cascade_nbr - 1] = csm_end; + + for (int c = 1; c < cascade_nbr; ++c) { + /* View Space */ + float linear_split = LERP(((float)(c) / (float)cascade_nbr), csm_start, csm_end); + float exp_split = csm_start * powf(csm_end / csm_start, (float)(c) / (float)cascade_nbr); + + if (is_persp) { + cascade_data->split_start[c] = LERP(la->cascade_exponent, linear_split, exp_split); + } + else { + cascade_data->split_start[c] = linear_split; + } + cascade_data->split_end[c - 1] = cascade_data->split_start[c]; + + /* Add some overlap for smooth transition */ + cascade_data->split_start[c] = LERP(la->cascade_fade, cascade_data->split_end[c - 1], + (c > 1) ? cascade_data->split_end[c - 2] : cascade_data->split_start[0]); + + /* NDC Space */ + { + float p[4] = {1.0f, 1.0f, cascade_data->split_start[c], 1.0f}; + /* TODO: we don't need full m4 multiply here */ + mul_m4_v4(vp_projmat, p); + splits_start_ndc[c] = p[2]; + + if (is_persp) { + splits_start_ndc[c] /= p[3]; + } + } + + { + float p[4] = {1.0f, 1.0f, cascade_data->split_end[c - 1], 1.0f}; + /* TODO: we don't need full m4 multiply here */ + mul_m4_v4(vp_projmat, p); + splits_end_ndc[c - 1] = p[2]; + + if (is_persp) { + splits_end_ndc[c - 1] /= p[3]; + } + } + } + + /* Set last cascade split fade distance into the first split_start. */ + float prev_split = (cascade_nbr > 1) ? cascade_data->split_end[cascade_nbr - 2] : cascade_data->split_start[0]; + cascade_data->split_start[0] = LERP(la->cascade_fade, cascade_data->split_end[cascade_nbr - 1], prev_split); + + /* For each cascade */ + for (int c = 0; c < cascade_nbr; ++c) { + float (*projmat)[4] = sh_data->projmat[c]; + /* Given 8 frustum corners */ + float corners[8][3] = { + /* Near Cap */ + {-1.0f, -1.0f, splits_start_ndc[c]}, + { 1.0f, -1.0f, splits_start_ndc[c]}, + {-1.0f, 1.0f, splits_start_ndc[c]}, + { 1.0f, 1.0f, splits_start_ndc[c]}, + /* Far Cap */ + {-1.0f, -1.0f, splits_end_ndc[c]}, + { 1.0f, -1.0f, splits_end_ndc[c]}, + {-1.0f, 1.0f, splits_end_ndc[c]}, + { 1.0f, 1.0f, splits_end_ndc[c]} + }; + + /* Transform them into world space */ + for (int i = 0; i < 8; ++i) { + mul_project_m4_v3(persinv, corners[i]); + } + + float center[3]; + frustum_min_bounding_sphere(corners, center, &(sh_data->radius[c])); + + /* Project into lightspace */ + mul_mat3_m4_v3(viewmat, center); + + /* Snap projection center to nearest texel to cancel shimmering. */ + float shadow_origin[2], shadow_texco[2]; + /* Light to texture space. */ + mul_v2_v2fl(shadow_origin, center, linfo->shadow_cascade_size / (2.0f * sh_data->radius[c])); + + /* Find the nearest texel. */ + shadow_texco[0] = roundf(shadow_origin[0]); + shadow_texco[1] = roundf(shadow_origin[1]); + + /* Compute offset. */ + sub_v2_v2(shadow_texco, shadow_origin); + mul_v2_fl(shadow_texco, (2.0f * sh_data->radius[c]) / linfo->shadow_cascade_size); /* Texture to light space. */ + + /* Apply offset. */ + add_v2_v2(center, shadow_texco); + + /* Expand the projection to cover frustum range */ + rctf rect_cascade; + BLI_rctf_init_pt_radius(&rect_cascade, center, sh_data->radius[c]); + orthographic_m4(projmat, + rect_cascade.xmin, rect_cascade.xmax, + rect_cascade.ymin, rect_cascade.ymax, + la->clipsta, la->clipend); + + mul_m4_m4m4(sh_data->viewprojmat[c], projmat, viewmat); + mul_m4_m4m4(cascade_data->shadowmat[c], texcomat, sh_data->viewprojmat[c]); + } + + ubo_data->bias = 0.05f * la->bias; + ubo_data->near = la->clipsta; + ubo_data->far = la->clipend; + ubo_data->exp = (linfo->shadow_method == SHADOW_VSM) ? la->bleedbias : la->bleedexp; + + evli->shadowid = (float)(sh_data->shadow_id); + ubo_data->shadow_start = (float)(sh_data->layer_id); + ubo_data->data_start = (float)(sh_data->cascade_id); + ubo_data->multi_shadow_count = (float)(sh_nbr); + ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */ + + ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f; + ubo_data->contact_bias = 0.05f * la->contact_bias; + ubo_data->contact_spread = la->contact_spread; + ubo_data->contact_thickness = la->contact_thickness; +} + +/* Used for checking if object is inside the shadow volume. */ +static bool sphere_bbox_intersect(const EEVEE_BoundSphere *bs, const EEVEE_BoundBox *bb) +{ + /* We are testing using a rougher AABB vs AABB test instead of full AABB vs Sphere. */ + /* TODO test speed with AABB vs Sphere. */ + bool x = fabsf(bb->center[0] - bs->center[0]) <= (bb->halfdim[0] + bs->radius); + bool y = fabsf(bb->center[1] - bs->center[1]) <= (bb->halfdim[1] + bs->radius); + bool z = fabsf(bb->center[2] - bs->center[2]) <= (bb->halfdim[2] + bs->radius); + + return x && y && z; +} + +void EEVEE_lights_update(EEVEE_ViewLayerData *sldata) +{ + EEVEE_LampsInfo *linfo = sldata->lamps; + Object *ob; + int i; + char *flag; + EEVEE_ShadowCaster *shcaster; + EEVEE_BoundSphere *bsphere; + EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer; + EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer; + + EEVEE_LightBits update_bits = {{0}}; + if ((linfo->update_flag & LIGHT_UPDATE_SHADOW_CUBE) != 0) { + /* Update all lights. */ + lightbits_set_all(&update_bits, true); + } + else { + /* Search for deleted shadow casters and if shcaster WAS in shadow radius. */ + /* No need to run this if we already update all lamps. */ + EEVEE_LightBits past_bits = {{0}}; + EEVEE_LightBits curr_bits = {{0}}; + shcaster = backbuffer->shadow_casters; + flag = backbuffer->flags; + for (i = 0; i < backbuffer->count; ++i, ++flag, ++shcaster) { + /* If the shadowcaster has been deleted or updated. */ + if (*flag != 0) { + /* Add the lamps that were intersecting with its BBox. */ + lightbits_or(&past_bits, &shcaster->bits); + } + } + /* Convert old bits to new bits and add result to final update bits. */ + /* NOTE: This might be overkill since all lights are tagged to refresh if + * the light count changes. */ + lightbits_convert(&curr_bits, &past_bits, linfo->new_shadow_id, MAX_LIGHT); + lightbits_or(&update_bits, &curr_bits); + } + + /* Search for updates in current shadow casters. */ + shcaster = frontbuffer->shadow_casters; + flag = frontbuffer->flags; + for (i = 0; i < frontbuffer->count; i++, flag++, shcaster++) { + /* Run intersection checks to fill the bitfields. */ + bsphere = linfo->shadow_bounds; + for (int j = 0; j < linfo->cpu_cube_ct; j++, bsphere++) { + bool iter = sphere_bbox_intersect(bsphere, &shcaster->bbox); + lightbits_set_single(&shcaster->bits, j, iter); + } + /* Only add to final bits if objects has been updated. */ + if (*flag != 0) { + lightbits_or(&update_bits, &shcaster->bits); + } + } + + /* Setup shadow cube in UBO and tag for update if necessary. */ + for (i = 0; (i < MAX_SHADOW_CUBE) && (ob = linfo->shadow_cube_ref[i]); i++) { + EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); + + eevee_shadow_cube_setup(ob, linfo, led); + if (lightbits_get(&update_bits, i) != 0) { + led->need_update = true; + } + } + + /* Resize shcasters buffers if too big. */ + if (frontbuffer->alloc_count - frontbuffer->count > SHADOW_CASTER_ALLOC_CHUNK) { + frontbuffer->alloc_count = (frontbuffer->count / SHADOW_CASTER_ALLOC_CHUNK) * SHADOW_CASTER_ALLOC_CHUNK; + frontbuffer->alloc_count += (frontbuffer->count % SHADOW_CASTER_ALLOC_CHUNK != 0) ? SHADOW_CASTER_ALLOC_CHUNK : 0; + frontbuffer->shadow_casters = MEM_reallocN(frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count); + frontbuffer->flags = MEM_reallocN(frontbuffer->flags, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count); + } +} + +/* this refresh lamps shadow buffers */ +void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) +{ + EEVEE_LampsInfo *linfo = sldata->lamps; + Object *ob; + int i; + + DRWMatrixState saved_mats; + + /* Precompute all shadow/view test before rendering and trashing the culling cache. */ + bool cube_visible[MAX_SHADOW_CUBE]; + for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) { + Lamp *la = (Lamp *)ob->data; + BoundSphere bsphere = { + .center = {ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2]}, + .radius = la->dist + }; + cube_visible[i] = DRW_culling_sphere_test(&bsphere); + } + bool cascade_visible[MAX_SHADOW_CASCADE]; + for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) { + EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob); + EEVEE_ShadowCascadeData *sh_data = &led->data.scad; + float plane[4]; + normalize_m4_m4(sh_data->viewmat, ob->obmat); + plane_from_point_normal_v3(plane, sh_data->viewmat[3], sh_data->viewmat[2]); + /* TODO: check against near/far instead of "local Z = 0" plane. + * Or even the cascades AABB. */ + cascade_visible[i] = DRW_culling_plane_test(plane); + } + + /* We need to save the Matrices before overidding them */ + DRW_viewport_matrix_get_all(&saved_mats); + + /* Cube Shadow Maps */ + DRW_stats_group_start("Cube Shadow Maps"); + /* Render each shadow to one layer of the array */ + for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) { + EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); + Lamp *la = (Lamp *)ob->data; + + if (!led->need_update || !cube_visible[i]) { + continue; + } + + DRWMatrixState render_mats; + float (*winmat)[4] = render_mats.mat[DRW_MAT_WIN]; + float (*viewmat)[4] = render_mats.mat[DRW_MAT_VIEW]; + float (*persmat)[4] = render_mats.mat[DRW_MAT_PERS]; + + EEVEE_ShadowRender *srd = &linfo->shadow_render_data; + EEVEE_ShadowCubeData *evscd = &led->data.scd; + + perspective_m4(winmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend); + + srd->clip_near = la->clipsta; + srd->clip_far = la->clipend; + copy_v3_v3(srd->position, ob->obmat[3]); + + srd->stored_texel_size = 1.0 / (float)linfo->shadow_cube_store_size; + + DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd); + + /* Render shadow cube */ + /* Render 6 faces separatly: seems to be faster for the general case. + * The only time it's more beneficial is when the CPU culling overhead + * outweight the instancing overhead. which is rarelly the case. */ + for (int j = 0; j < 6; j++) { + /* TODO optimize */ + float tmp[4][4]; + unit_m4(tmp); + negate_v3_v3(tmp[3], srd->position); + mul_m4_m4m4(viewmat, cubefacemat[j], tmp); + mul_m4_m4m4(persmat, winmat, viewmat); + invert_m4_m4(render_mats.mat[DRW_MAT_WININV], winmat); + invert_m4_m4(render_mats.mat[DRW_MAT_VIEWINV], viewmat); + invert_m4_m4(render_mats.mat[DRW_MAT_PERSINV], persmat); + + DRW_viewport_matrix_override_set_all(&render_mats); + + GPU_framebuffer_texture_cubeface_attach(sldata->shadow_cube_target_fb, + sldata->shadow_cube_target, 0, j, 0); + GPU_framebuffer_bind(sldata->shadow_cube_target_fb); + GPU_framebuffer_clear_depth(sldata->shadow_cube_target_fb, 1.0f); + DRW_draw_pass(psl->shadow_pass); + } + + /* 0.001f is arbitrary, but it should be relatively small so that filter size is not too big. */ + float filter_texture_size = la->soft * 0.001f; + float filter_pixel_size = ceil(filter_texture_size / srd->cube_texel_size); + linfo->filter_size = srd->cube_texel_size * ((filter_pixel_size > 1.0f) ? 1.5f : 0.0f); + + /* TODO: OPTI: Filter all faces in one/two draw call */ + /* TODO: OPTI: Don't do this intermediate step if no filter is needed. */ + for (linfo->current_shadow_face = 0; + linfo->current_shadow_face < 6; + linfo->current_shadow_face++) + { + /* Copy using a small 3x3 box filter */ + GPU_framebuffer_texture_cubeface_attach(sldata->shadow_cube_store_fb, sldata->shadow_cube_blur, 0, + linfo->current_shadow_face, 0); + GPU_framebuffer_bind(sldata->shadow_cube_store_fb); + DRW_draw_pass(psl->shadow_cube_copy_pass); + } + + /* Push it to shadowmap array */ + + /* Adjust constants if concentric samples change. */ + const float max_filter_size = 7.5f; + const float magic = 4.5f; /* Dunno why but that works. */ + const int max_sample = 256; + + if (filter_pixel_size > 2.0f) { + linfo->filter_size = srd->cube_texel_size * max_filter_size * magic; + filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f); + /* Compute number of concentric samples. Depends directly on filter size. */ + float pix_size_sqr = filter_pixel_size * filter_pixel_size; + srd->shadow_samples_ct = min_ii(max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr)); + } + else { + linfo->filter_size = 0.0f; + srd->shadow_samples_ct = 4; + } + srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct; + DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd); + + GPU_framebuffer_texture_layer_attach(sldata->shadow_cube_store_fb, sldata->shadow_cube_pool, 0, evscd->layer_id, 0); + GPU_framebuffer_bind(sldata->shadow_cube_store_fb); + DRW_draw_pass(psl->shadow_cube_store_pass); + + led->need_update = false; + } + linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE; + DRW_stats_group_end(); + + DRW_viewport_matrix_override_set_all(&saved_mats); + float near = DRW_viewport_near_distance_get(); + float far = DRW_viewport_far_distance_get(); + + /* Cascaded Shadow Maps */ + DRW_stats_group_start("Cascaded Shadow Maps"); + for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) { + if (!cascade_visible[i]) { + continue; + } + + EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); + Lamp *la = (Lamp *)ob->data; + + EEVEE_ShadowCascadeData *evscd = &led->data.scad; + EEVEE_ShadowRender *srd = &linfo->shadow_render_data; + + DRWMatrixState render_mats; + float (*winmat)[4] = render_mats.mat[DRW_MAT_WIN]; + float (*viewmat)[4] = render_mats.mat[DRW_MAT_VIEW]; + float (*persmat)[4] = render_mats.mat[DRW_MAT_PERS]; + + eevee_shadow_cascade_setup(ob, linfo, led, &saved_mats, near, far); + + srd->clip_near = la->clipsta; + srd->clip_far = la->clipend; + srd->stored_texel_size = 1.0 / (float)linfo->shadow_cascade_size; + + DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data); + + copy_m4_m4(viewmat, evscd->viewmat); + invert_m4_m4(render_mats.mat[DRW_MAT_VIEWINV], viewmat); + + /* Render shadow cascades */ + /* Render cascade separatly: seems to be faster for the general case. + * The only time it's more beneficial is when the CPU culling overhead + * outweight the instancing overhead. which is rarelly the case. */ + for (int j = 0; j < la->cascade_count; j++) { + copy_m4_m4(winmat, evscd->projmat[j]); + copy_m4_m4(persmat, evscd->viewprojmat[j]); + invert_m4_m4(render_mats.mat[DRW_MAT_WININV], winmat); + invert_m4_m4(render_mats.mat[DRW_MAT_PERSINV], persmat); + + DRW_viewport_matrix_override_set_all(&render_mats); + + GPU_framebuffer_texture_layer_attach(sldata->shadow_cascade_target_fb, + sldata->shadow_cascade_target, 0, j, 0); + GPU_framebuffer_bind(sldata->shadow_cascade_target_fb); + GPU_framebuffer_clear_depth(sldata->shadow_cascade_target_fb, 1.0f); + DRW_draw_pass(psl->shadow_pass); + } + + /* TODO: OPTI: Filter all cascade in one/two draw call */ + for (linfo->current_shadow_cascade = 0; + linfo->current_shadow_cascade < la->cascade_count; + ++linfo->current_shadow_cascade) + { + /* 0.01f factor to convert to percentage */ + float filter_texture_size = la->soft * 0.01f / evscd->radius[linfo->current_shadow_cascade]; + float filter_pixel_size = ceil(linfo->shadow_cascade_size * filter_texture_size); + + /* Copy using a small 3x3 box filter */ + /* NOTE: We always do it in the case of CSM because of artifacts in the farthest cascade. */ + linfo->filter_size = srd->stored_texel_size; + GPU_framebuffer_texture_layer_attach( + sldata->shadow_cascade_store_fb, sldata->shadow_cascade_blur, 0, linfo->current_shadow_cascade, 0); + GPU_framebuffer_bind(sldata->shadow_cascade_store_fb); + DRW_draw_pass(psl->shadow_cascade_copy_pass); + + /* Push it to shadowmap array and blur more */ + + /* Adjust constants if concentric samples change. */ + const float max_filter_size = 7.5f; + const float magic = 3.2f; /* Arbitrary: less banding */ + const int max_sample = 256; + + if (filter_pixel_size > 2.0f) { + linfo->filter_size = srd->stored_texel_size * max_filter_size * magic; + filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f); + /* Compute number of concentric samples. Depends directly on filter size. */ + float pix_size_sqr = filter_pixel_size * filter_pixel_size; + srd->shadow_samples_ct = min_ii(max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr)); + } + else { + linfo->filter_size = 0.0f; + srd->shadow_samples_ct = 4; + } + srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct; + DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data); + + int layer = evscd->layer_id + linfo->current_shadow_cascade; + GPU_framebuffer_texture_layer_attach(sldata->shadow_cascade_store_fb, sldata->shadow_cascade_pool, 0, layer, 0); + GPU_framebuffer_bind(sldata->shadow_cascade_store_fb); + DRW_draw_pass(psl->shadow_cascade_store_pass); + } + } + + DRW_stats_group_end(); + + DRW_viewport_matrix_override_set_all(&saved_mats); + + DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data); + DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */ +} + +void EEVEE_lights_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.shadow_sh); + for (int i = 0; i < SHADOW_METHOD_MAX; ++i) { + DRW_SHADER_FREE_SAFE(e_data.shadow_store_cube_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.shadow_store_cascade_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cube_sh[i]); + DRW_SHADER_FREE_SAFE(e_data.shadow_copy_cascade_sh[i]); + } +} diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c new file mode 100644 index 00000000000..0e0bea53927 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -0,0 +1,151 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_lookdev.c + * \ingroup draw_engine + */ +#include "DRW_render.h" + +#include "BKE_camera.h" +#include "BKE_studiolight.h" + +#include "DNA_screen_types.h" +#include "DNA_world_types.h" + +#include "eevee_private.h" + +void EEVEE_lookdev_cache_init( + EEVEE_Data *vedata, DRWShadingGroup **grp, GPUShader *shader, DRWPass *pass, + World *world, EEVEE_LightProbesInfo *pinfo) +{ + EEVEE_StorageList *stl = vedata->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + if (LOOK_DEV_MODE_ENABLED(v3d)) { + StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, STUDIOLIGHT_ORIENTATION_WORLD); + if ((sl->flag & STUDIOLIGHT_ORIENTATION_WORLD)) { + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + GPUTexture *tex; + + *grp = DRW_shgroup_create(shader, pass); + axis_angle_to_mat3_single(stl->g_data->studiolight_matrix, 'Z', v3d->shading.studiolight_rot_z); + DRW_shgroup_uniform_mat3(*grp, "StudioLightMatrix", stl->g_data->studiolight_matrix); + + DRW_shgroup_uniform_vec3(*grp, "color", &world->horr, 1); + DRW_shgroup_uniform_float(*grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + DRW_shgroup_call_add(*grp, geom, NULL); + if (!pinfo) { + /* Do not fadeout when doing probe rendering, only when drawing the background */ + DRW_shgroup_uniform_float(*grp, "studioLightBackground", &v3d->shading.studiolight_background, 1); + + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_GPUTEXTURE); + tex = sl->equirectangular_irradiance_gputexture; + } + else { + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE); + tex = sl->equirectangular_radiance_gputexture; + } + DRW_shgroup_uniform_texture(*grp, "image", tex); + + /* Do we need to recalc the lightprobes? */ + if (pinfo && + ((pinfo->studiolight_index != sl->index) || + (pinfo->studiolight_rot_z != v3d->shading.studiolight_rot_z))) + { + pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->studiolight_index = sl->index; + pinfo->studiolight_rot_z = v3d->shading.studiolight_rot_z; + pinfo->prev_wo_sh_compiled = false; + pinfo->prev_world = NULL; + } + } + } +} + +void EEVEE_lookdev_draw_background(EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (psl->lookdev_pass && LOOK_DEV_OVERLAY_ENABLED(draw_ctx->v3d)) { + DRW_stats_group_start("Look Dev"); + CameraParams params; + BKE_camera_params_init(¶ms); + View3D *v3d = draw_ctx->v3d; + RegionView3D *rv3d = draw_ctx->rv3d; + ARegion *ar = draw_ctx->ar; + + BKE_camera_params_from_view3d(¶ms, draw_ctx->depsgraph, v3d, rv3d); + params.is_ortho = true; + params.ortho_scale = 4.0f; + params.zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; + params.offsetx = 0.0f; + params.offsety = 0.0f; + params.shiftx = 0.0f; + params.shifty = 0.0f; + params.clipsta = 0.001f; + params.clipend = 20.0f; + BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, 1.0f, 1.0f); + BKE_camera_params_compute_matrix(¶ms); + + const float *viewport_size = DRW_viewport_size_get(); + int viewport_inset_x = viewport_size[0] / 4; + int viewport_inset_y = viewport_size[1] / 4; + + EEVEE_CommonUniformBuffer *common = &sldata->common_data; + common->la_num_light = 0; + common->prb_num_planar = 0; + common->prb_num_render_cube = 1; + common->prb_num_render_grid = 1; + common->ao_dist = 0.0f; + common->ao_factor = 0.0f; + common->ao_settings = 0.0f; + DRW_uniformbuffer_update(sldata->common_ubo, common); + + /* override matrices */ + float winmat[4][4]; + float winmat_inv[4][4]; + copy_m4_m4(winmat, params.winmat); + invert_m4_m4(winmat_inv, winmat); + DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(winmat_inv, DRW_MAT_WININV); + float viewmat[4][4]; + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + float persmat[4][4]; + float persmat_inv[4][4]; + mul_m4_m4m4(persmat, winmat, viewmat); + invert_m4_m4(persmat_inv, persmat); + DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(persmat_inv, DRW_MAT_PERSINV); + + GPUFrameBuffer *fb = effects->final_fb; + GPU_framebuffer_bind(fb); + GPU_framebuffer_viewport_set(fb, viewport_size[0] - viewport_inset_x, 0, viewport_inset_x, viewport_inset_y); + DRW_draw_pass(psl->lookdev_pass); + + DRW_viewport_matrix_override_unset_all(); + DRW_stats_group_end(); + } +} diff --git a/source/blender/draw/engines/eevee/eevee_lut.h b/source/blender/draw/engines/eevee/eevee_lut.h new file mode 100644 index 00000000000..da765b3e53a --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_lut.h @@ -0,0 +1,16926 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Clement Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file eevee_lut.h + * \ingroup gpu + */ + +#ifndef __EEVEE_LUT_H__ +#define __EEVEE_LUT_H__ + +static float ltc_mat_ggx[64 * 64 * 4] = { + 0.000200, -0.000000, 1.000000, -0.000000, 0.000504, -0.000000, 1.000000, -0.000000, 0.002016, + -0.000000, 1.000000, -0.000000, 0.004535, -0.000000, 1.000000, -0.000000, 0.008063, -0.000000, + 1.000000, -0.000000, 0.012598, -0.000000, 1.000000, -0.000000, 0.018141, -0.000000, 1.000000, + -0.000000, 0.024692, -0.000000, 1.000000, -0.000000, 0.032252, -0.000000, 1.000000, -0.000000, + 0.040821, -0.000000, 1.000000, -0.000000, 0.050400, -0.000000, 1.000000, -0.000000, 0.060989, + -0.000000, 1.000000, -0.000000, 0.072591, -0.000000, 1.000000, -0.000000, 0.085206, -0.000000, + 1.000000, -0.000000, 0.098836, -0.000000, 1.000000, -0.000000, 0.113483, -0.000000, 1.000000, + -0.000000, 0.129147, -0.000000, 1.000000, -0.000000, 0.145828, -0.000000, 1.000000, -0.000000, + 0.163499, -0.000000, 1.000000, -0.000000, 0.181972, -0.000000, 1.000000, -0.000000, 0.199498, + -0.000000, 1.000000, -0.000000, 0.220031, -0.000000, 1.000000, -0.000000, 0.241588, -0.000000, + 1.000000, -0.000000, 0.264120, -0.000000, 1.000000, -0.000000, 0.287521, -0.000000, 1.000000, + -0.000000, 0.311478, -0.000000, 1.000000, -0.000000, 0.335127, -0.000000, 1.000000, -0.000000, + 0.359811, -0.000000, 1.000000, -0.000000, 0.386446, -0.000000, 1.000000, -0.000000, 0.413161, + -0.000000, 1.000000, -0.000000, 0.439142, -0.000000, 1.000000, -0.000000, 0.467039, -0.000000, + 1.000000, -0.000000, 0.495170, -0.000000, 1.000000, -0.000000, 0.522324, -0.000000, 1.000000, + -0.000000, 0.551482, -0.000000, 1.000000, -0.000000, 0.579621, -0.000000, 1.000000, -0.000000, + 0.608255, -0.000000, 1.000000, -0.000000, 0.636515, -0.000000, 1.000000, -0.000000, 0.664835, + -0.000000, 1.000000, -0.000000, 0.692549, -0.000000, 1.000000, -0.000000, 0.720375, -0.000000, + 1.000000, -0.000000, 0.747238, -0.000000, 1.000000, -0.000000, 0.773956, -0.000000, 1.000000, + -0.000000, 0.799879, -0.000000, 1.000000, -0.000000, 0.824889, -0.000000, 1.000000, -0.000000, + 0.849357, -0.000000, 1.000000, -0.000000, 0.873016, -0.000000, 1.000000, -0.000000, 0.895670, + -0.000000, 1.000000, -0.000000, 0.917194, -0.000000, 1.000000, -0.000000, 0.937978, -0.000000, + 1.000000, -0.000000, 0.957872, -0.000000, 1.000000, -0.000000, 0.976736, -0.000000, 1.000000, + -0.000000, 0.994433, -0.000000, 1.000000, -0.000000, 1.011206, -0.000000, 1.000000, -0.000000, + 1.026820, -0.000000, 1.000000, -0.000000, 1.041720, -0.000000, 1.000000, -0.000000, 1.055657, + -0.000000, 1.000000, -0.000000, 1.068642, -0.000000, 1.000000, -0.000000, 1.080646, -0.000000, + 1.000000, -0.000000, 1.091637, -0.000000, 1.000000, -0.000000, 1.101837, -0.000000, 1.000000, + -0.000000, 1.111292, -0.000000, 1.000000, -0.000000, 1.120025, -0.000000, 1.000000, -0.000000, + 1.127918, -0.000000, 1.000000, -0.000000, 0.000200, -0.000005, 1.000623, 0.024938, 0.000504, + -0.000013, 1.000643, 0.024938, 0.002016, -0.000050, 1.000618, 0.024938, 0.004535, -0.000113, + 1.000621, 0.024938, 0.008063, -0.000201, 1.000746, 0.024938, 0.012596, -0.000314, 1.000463, + 0.024937, 0.018140, -0.000452, 1.000511, 0.024939, 0.024693, -0.000616, 1.000541, 0.024938, + 0.032253, -0.000804, 1.000684, 0.024938, 0.040815, -0.001018, 1.000524, 0.024940, 0.050399, + -0.001257, 1.000582, 0.024937, 0.060989, -0.001521, 1.000655, 0.024937, 0.072591, -0.001810, + 1.000608, 0.024938, 0.085204, -0.002125, 1.000622, 0.024939, 0.098835, -0.002465, 1.000632, + 0.024937, 0.113483, -0.002830, 1.000640, 0.024939, 0.129143, -0.003220, 1.000568, 0.024938, + 0.145830, -0.003633, 1.000635, 0.024938, 0.163497, -0.004062, 1.000626, 0.024938, 0.181956, + -0.004424, 1.000612, 0.024924, 0.199791, -0.004593, 1.000627, 0.024890, 0.220029, -0.005480, + 1.000594, 0.024935, 0.241586, -0.006010, 1.000616, 0.024933, 0.264115, -0.006550, 1.000607, + 0.024927, 0.287514, -0.007072, 1.000595, 0.024909, 0.311455, -0.007472, 1.000616, 0.024872, + 0.335083, -0.007491, 1.000589, 0.024755, 0.359805, -0.008810, 1.000601, 0.024877, 0.386438, + -0.009282, 1.000640, 0.024824, 0.413131, -0.009534, 1.000599, 0.024708, 0.439249, -0.009701, + 1.000497, 0.024573, 0.466997, -0.010878, 1.000467, 0.024652, 0.495138, -0.010959, 1.000539, + 0.024455, 0.522654, -0.011386, 1.000518, 0.024318, 0.551415, -0.012022, 1.000533, 0.024216, + 0.579610, -0.011805, 1.000495, 0.023867, 0.608185, -0.012773, 1.000474, 0.023834, 0.636492, + -0.012377, 1.000488, 0.023327, 0.664826, -0.013172, 1.000576, 0.023205, 0.692674, -0.012847, + 1.000505, 0.022708, 0.720341, -0.013141, 1.000424, 0.022349, 0.747373, -0.013227, 1.000449, + 0.021871, 0.773980, -0.012739, 1.000478, 0.021171, 0.799839, -0.012999, 1.000396, 0.020606, + 0.825113, -0.012727, 1.000425, 0.020006, 0.849579, -0.012170, 1.000469, 0.019089, 0.873046, + -0.011855, 1.000411, 0.018291, 0.895777, -0.011711, 1.000426, 0.017534, 0.917518, -0.011107, + 1.000373, 0.016542, 0.938264, -0.010439, 1.000322, 0.015512, 0.958032, -0.009807, 1.000324, + 0.014491, 0.976838, -0.009268, 1.000341, 0.013468, 0.994631, -0.008662, 1.000318, 0.012376, + 1.011434, -0.007923, 1.000289, 0.011187, 1.027169, -0.007132, 1.000216, 0.010078, 1.041929, + -0.006332, 1.000096, 0.008924, 1.055767, -0.005554, 1.000156, 0.007770, 1.068595, -0.004811, + 1.000084, 0.006611, 1.080612, -0.003950, 1.000047, 0.005485, 1.091785, -0.003174, 1.000109, + 0.004352, 1.101998, -0.002363, 1.000029, 0.003180, 1.111423, -0.001552, 0.999985, 0.002091, + 1.120007, -0.000786, 0.999947, 0.000991, 1.127918, 0.000004, 1.000000, -0.000004, 0.000200, + -0.000010, 1.002495, 0.049907, 0.000504, -0.000025, 1.002476, 0.049908, 0.002016, -0.000101, + 1.002500, 0.049908, 0.004535, -0.000226, 1.002487, 0.049908, 0.008062, -0.000402, 1.002364, + 0.049908, 0.012598, -0.000629, 1.002412, 0.049908, 0.018140, -0.000905, 1.002379, 0.049908, + 0.024691, -0.001232, 1.002490, 0.049907, 0.032251, -0.001610, 1.002398, 0.049908, 0.040821, + -0.002037, 1.002392, 0.049908, 0.050398, -0.002515, 1.002431, 0.049907, 0.060989, -0.003044, + 1.002475, 0.049908, 0.072592, -0.003623, 1.002546, 0.049907, 0.085204, -0.004252, 1.002467, + 0.049907, 0.098832, -0.004932, 1.002450, 0.049908, 0.113481, -0.005663, 1.002482, 0.049907, + 0.129145, -0.006443, 1.002443, 0.049907, 0.145825, -0.007271, 1.002495, 0.049906, 0.163491, + -0.008128, 1.002475, 0.049903, 0.181911, -0.008826, 1.002459, 0.049879, 0.200065, -0.009285, + 1.002443, 0.049824, 0.220025, -0.010966, 1.002450, 0.049897, 0.241581, -0.012025, 1.002463, + 0.049893, 0.264099, -0.013105, 1.002395, 0.049881, 0.287493, -0.014145, 1.002390, 0.049855, + 0.311399, -0.014925, 1.002414, 0.049769, 0.335096, -0.015239, 1.002363, 0.049591, 0.359815, + -0.017559, 1.002415, 0.049777, 0.386365, -0.018554, 1.002354, 0.049675, 0.413017, -0.019043, + 1.002297, 0.049444, 0.439519, -0.019815, 1.002284, 0.049253, 0.466938, -0.021741, 1.002307, + 0.049327, 0.494999, -0.021887, 1.002181, 0.048922, 0.522922, -0.022844, 1.002107, 0.048677, + 0.551270, -0.024014, 1.002101, 0.048478, 0.579771, -0.024156, 1.002060, 0.047904, 0.608156, + -0.025317, 1.002077, 0.047594, 0.636662, -0.025321, 1.001975, 0.046876, 0.664846, -0.026018, + 1.001992, 0.046354, 0.692877, -0.026041, 1.001846, 0.045504, 0.720316, -0.026252, 1.001846, + 0.044655, 0.747658, -0.026159, 1.001931, 0.043670, 0.774252, -0.026086, 1.001845, 0.042515, + 0.800179, -0.025653, 1.001794, 0.041211, 0.825525, -0.025170, 1.001787, 0.039823, 0.850013, + -0.024788, 1.001806, 0.038409, 0.873593, -0.023992, 1.001688, 0.036767, 0.896343, -0.022985, + 1.001666, 0.034900, 0.918062, -0.022005, 1.001548, 0.033010, 0.938928, -0.021110, 1.001503, + 0.031143, 0.958667, -0.019893, 1.001341, 0.029059, 0.977457, -0.018546, 1.001194, 0.026888, + 0.995243, -0.017152, 1.001095, 0.024713, 1.012023, -0.015750, 1.001100, 0.022496, 1.027614, + -0.014289, 1.000851, 0.020153, 1.042389, -0.012688, 1.000724, 0.017839, 1.056161, -0.011118, + 1.000572, 0.015529, 1.068968, -0.009540, 1.000407, 0.013240, 1.080866, -0.007963, 1.000258, + 0.010940, 1.091944, -0.006416, 1.000254, 0.008716, 1.102104, -0.004771, 1.000175, 0.006434, + 1.111571, -0.003056, 1.000148, 0.004169, 1.120084, -0.001458, 1.000050, 0.002033, 1.127981, + 0.000021, 0.999987, -0.000027, 0.000200, -0.000015, 1.005620, 0.074940, 0.000504, -0.000038, + 1.005650, 0.074939, 0.002016, -0.000151, 1.005613, 0.074939, 0.004535, -0.000340, 1.005618, + 0.074939, 0.008062, -0.000604, 1.005614, 0.074939, 0.012597, -0.000944, 1.005616, 0.074940, + 0.018141, -0.001359, 1.005558, 0.074939, 0.024695, -0.001851, 1.005495, 0.074940, 0.032253, + -0.002417, 1.005616, 0.074939, 0.040822, -0.003059, 1.005591, 0.074940, 0.050399, -0.003777, + 1.005596, 0.074940, 0.060989, -0.004570, 1.005599, 0.074939, 0.072591, -0.005440, 1.005616, + 0.074940, 0.085203, -0.006385, 1.005616, 0.074939, 0.098833, -0.007406, 1.005595, 0.074938, + 0.113481, -0.008502, 1.005605, 0.074938, 0.129147, -0.009674, 1.005605, 0.074937, 0.145817, + -0.010916, 1.005513, 0.074937, 0.163485, -0.012199, 1.005579, 0.074928, 0.181824, -0.013172, + 1.005552, 0.074885, 0.200274, -0.014100, 1.005524, 0.074825, 0.220017, -0.016464, 1.005529, + 0.074928, 0.241568, -0.018052, 1.005490, 0.074914, 0.264084, -0.019671, 1.005457, 0.074898, + 0.287450, -0.021217, 1.005431, 0.074860, 0.311281, -0.022341, 1.005395, 0.074717, 0.335228, + -0.023296, 1.005320, 0.074526, 0.360047, -0.025965, 1.005302, 0.074649, 0.386273, -0.027808, + 1.005285, 0.074575, 0.412855, -0.028504, 1.005167, 0.074237, 0.439705, -0.030007, 1.005129, + 0.074013, 0.466975, -0.032263, 1.005082, 0.073967, 0.494874, -0.032931, 1.004960, 0.073475, + 0.523066, -0.034348, 1.004834, 0.073084, 0.551198, -0.035739, 1.004806, 0.072657, 0.579889, + -0.036575, 1.004687, 0.072029, 0.608282, -0.037434, 1.004605, 0.071309, 0.636812, -0.038323, + 1.004589, 0.070507, 0.665010, -0.038676, 1.004403, 0.069424, 0.693063, -0.039237, 1.004340, + 0.068370, 0.720750, -0.039332, 1.004224, 0.066988, 0.747911, -0.039179, 1.004117, 0.065447, + 0.774576, -0.039110, 1.004035, 0.063838, 0.800737, -0.038542, 1.004027, 0.061923, 0.825966, + -0.037966, 1.003825, 0.059859, 0.850534, -0.036943, 1.003786, 0.057529, 0.874289, -0.035853, + 1.003560, 0.055081, 0.897152, -0.034730, 1.003549, 0.052476, 0.919029, -0.033242, 1.003454, + 0.049647, 0.939851, -0.031508, 1.003215, 0.046670, 0.959599, -0.029695, 1.002916, 0.043588, + 0.978293, -0.027845, 1.002720, 0.040401, 0.996085, -0.025775, 1.002445, 0.037060, 1.012768, + -0.023607, 1.002133, 0.033726, 1.028404, -0.021374, 1.001822, 0.030217, 1.043150, -0.019108, + 1.001602, 0.026820, 1.056760, -0.016823, 1.001274, 0.023372, 1.069471, -0.014378, 1.000964, + 0.019891, 1.081283, -0.011884, 1.000684, 0.016405, 1.092238, -0.009398, 1.000514, 0.012950, + 1.102384, -0.007030, 1.000319, 0.009579, 1.111737, -0.004751, 1.000225, 0.006384, 1.120274, + -0.002404, 1.000046, 0.003192, 1.128182, 0.000031, 1.000020, 0.000033, 0.000200, -0.000020, + 1.010006, 0.100065, 0.000504, -0.000050, 1.009927, 0.100065, 0.002016, -0.000202, 1.010026, + 0.100064, 0.004535, -0.000454, 1.010018, 0.100065, 0.008062, -0.000807, 1.009891, 0.100064, + 0.012599, -0.001261, 1.010175, 0.100064, 0.018141, -0.001815, 1.010067, 0.100065, 0.024692, + -0.002471, 1.010014, 0.100066, 0.032251, -0.003227, 1.009950, 0.100065, 0.040818, -0.004084, + 1.009963, 0.100067, 0.050401, -0.005043, 1.010032, 0.100064, 0.060988, -0.006102, 1.009979, + 0.100064, 0.072588, -0.007263, 1.009984, 0.100063, 0.085205, -0.008525, 1.010023, 0.100063, + 0.098832, -0.009888, 1.009960, 0.100062, 0.113479, -0.011352, 1.009974, 0.100063, 0.129142, + -0.012916, 1.009945, 0.100062, 0.145817, -0.014573, 1.009924, 0.100058, 0.163468, -0.016276, + 1.009912, 0.100050, 0.181674, -0.017411, 1.009859, 0.099975, 0.200435, -0.019002, 1.009842, + 0.099932, 0.220005, -0.021978, 1.009820, 0.100043, 0.241550, -0.024096, 1.009778, 0.100031, + 0.264058, -0.026250, 1.009765, 0.100002, 0.287399, -0.028286, 1.009724, 0.099939, 0.311134, + -0.029698, 1.009596, 0.099748, 0.335350, -0.031442, 1.009508, 0.099582, 0.360295, -0.034401, + 1.009475, 0.099613, 0.386112, -0.037030, 1.009329, 0.099558, 0.412733, -0.038163, 1.009250, + 0.099137, 0.439833, -0.040250, 1.009125, 0.098866, 0.467099, -0.042583, 1.009011, 0.098626, + 0.494828, -0.044299, 1.008803, 0.098149, 0.523217, -0.045876, 1.008712, 0.097600, 0.551338, + -0.047440, 1.008509, 0.096929, 0.579917, -0.048995, 1.008371, 0.096178, 0.608454, -0.049901, + 1.008212, 0.095145, 0.636785, -0.051224, 1.007963, 0.094151, 0.665220, -0.051675, 1.007741, + 0.092728, 0.693194, -0.052278, 1.007616, 0.091195, 0.721008, -0.052406, 1.007327, 0.089384, + 0.748196, -0.052529, 1.007219, 0.087461, 0.774975, -0.051950, 1.006851, 0.085133, 0.801129, + -0.051456, 1.006732, 0.082628, 0.826668, -0.050569, 1.006612, 0.079817, 0.851291, -0.049328, + 1.006374, 0.076710, 0.875056, -0.047988, 1.006183, 0.073481, 0.897872, -0.046149, 1.005742, + 0.069943, 0.919803, -0.044144, 1.005514, 0.066151, 0.940701, -0.042095, 1.005153, 0.062247, + 0.960580, -0.039730, 1.004843, 0.058158, 0.979427, -0.037104, 1.004535, 0.053850, 0.997157, + -0.034369, 1.004023, 0.049403, 1.013777, -0.031555, 1.003622, 0.044944, 1.029452, -0.028571, + 1.003212, 0.040414, 1.044029, -0.025416, 1.002698, 0.035723, 1.057586, -0.022217, 1.002202, + 0.031072, 1.070148, -0.019037, 1.001703, 0.026429, 1.081875, -0.015936, 1.001322, 0.021896, + 1.092789, -0.012734, 1.001053, 0.017288, 1.102704, -0.009454, 1.000604, 0.012841, 1.112011, + -0.006199, 1.000387, 0.008446, 1.120590, -0.003010, 1.000166, 0.004122, 1.128283, 0.000027, + 0.999956, -0.000038, 0.000200, -0.000025, 1.015664, 0.125315, 0.000504, -0.000063, 1.015664, + 0.125316, 0.002016, -0.000253, 1.015727, 0.125315, 0.004535, -0.000568, 1.015695, 0.125314, + 0.008063, -0.001010, 1.015823, 0.125316, 0.012599, -0.001579, 1.015867, 0.125315, 0.018141, + -0.002273, 1.015758, 0.125316, 0.024691, -0.003094, 1.015662, 0.125316, 0.032252, -0.004042, + 1.015674, 0.125316, 0.040820, -0.005115, 1.015678, 0.125316, 0.050400, -0.006316, 1.015684, + 0.125315, 0.060989, -0.007642, 1.015685, 0.125315, 0.072590, -0.009096, 1.015703, 0.125314, + 0.085203, -0.010676, 1.015654, 0.125314, 0.098833, -0.012383, 1.015670, 0.125315, 0.113477, + -0.014215, 1.015635, 0.125312, 0.129138, -0.016173, 1.015599, 0.125311, 0.145815, -0.018246, + 1.015610, 0.125306, 0.163450, -0.020360, 1.015564, 0.125294, 0.181595, -0.021807, 1.015460, + 0.125204, 0.200563, -0.023971, 1.015440, 0.125165, 0.220186, -0.027280, 1.015412, 0.125250, + 0.241528, -0.030164, 1.015342, 0.125267, 0.264020, -0.032847, 1.015269, 0.125233, 0.287311, + -0.035345, 1.015232, 0.125138, 0.310993, -0.037108, 1.015063, 0.124903, 0.335467, -0.039653, + 1.014970, 0.124749, 0.360497, -0.042914, 1.014819, 0.124702, 0.385986, -0.046142, 1.014685, + 0.124623, 0.412703, -0.048050, 1.014543, 0.124193, 0.439929, -0.050527, 1.014315, 0.123833, + 0.467163, -0.052880, 1.014087, 0.123375, 0.494824, -0.055672, 1.013898, 0.122982, 0.523222, + -0.057388, 1.013647, 0.122166, 0.551557, -0.059328, 1.013403, 0.121343, 0.579884, -0.061315, + 1.013059, 0.120430, 0.608619, -0.062531, 1.012745, 0.119140, 0.637014, -0.063778, 1.012425, + 0.117721, 0.665425, -0.064734, 1.012067, 0.116069, 0.693580, -0.065315, 1.011712, 0.114146, + 0.721194, -0.065535, 1.011200, 0.111846, 0.748586, -0.065501, 1.010896, 0.109309, 0.775437, + -0.065091, 1.010576, 0.106504, 0.801554, -0.064332, 1.010136, 0.103308, 0.827079, -0.063078, + 1.009629, 0.099695, 0.851693, -0.061728, 1.009233, 0.095946, 0.875586, -0.059853, 1.008726, + 0.091802, 0.898589, -0.057727, 1.008412, 0.087339, 0.920421, -0.055377, 1.007767, 0.082687, + 0.941533, -0.052571, 1.007529, 0.077716, 0.961426, -0.049544, 1.006929, 0.072574, 0.980287, + -0.046400, 1.006393, 0.067217, 0.998080, -0.042966, 1.005872, 0.061757, 1.014940, -0.039321, + 1.005346, 0.056072, 1.030455, -0.035585, 1.004609, 0.050410, 1.045078, -0.031823, 1.004151, + 0.044622, 1.058555, -0.027947, 1.003421, 0.038893, 1.071009, -0.023891, 1.002704, 0.032977, + 1.082594, -0.019822, 1.002023, 0.027290, 1.093265, -0.015765, 1.001403, 0.021543, 1.103132, + -0.011790, 1.000944, 0.016072, 1.112348, -0.007784, 1.000550, 0.010511, 1.120845, -0.003849, + 1.000224, 0.005174, 1.128573, 0.000057, 0.999975, -0.000039, 0.000200, -0.000030, 1.022609, + 0.150725, 0.000504, -0.000076, 1.022728, 0.150725, 0.002016, -0.000304, 1.022728, 0.150725, + 0.004535, -0.000684, 1.022733, 0.150725, 0.008062, -0.001215, 1.022715, 0.150725, 0.012598, + -0.001899, 1.022720, 0.150725, 0.018141, -0.002734, 1.022659, 0.150725, 0.024694, -0.003722, + 1.022801, 0.150724, 0.032254, -0.004861, 1.022779, 0.150726, 0.040815, -0.006152, 1.022693, + 0.150724, 0.050400, -0.007596, 1.022716, 0.150725, 0.060990, -0.009192, 1.022733, 0.150725, + 0.072587, -0.010939, 1.022630, 0.150723, 0.085203, -0.012839, 1.022676, 0.150725, 0.098828, + -0.014891, 1.022659, 0.150725, 0.113473, -0.017095, 1.022589, 0.150720, 0.129137, -0.019449, + 1.022572, 0.150716, 0.145803, -0.021938, 1.022508, 0.150712, 0.163417, -0.024443, 1.022471, + 0.150691, 0.181580, -0.026329, 1.022406, 0.150600, 0.200667, -0.028997, 1.022336, 0.150553, + 0.220429, -0.032584, 1.022296, 0.150610, 0.241497, -0.036260, 1.022202, 0.150658, 0.263975, + -0.039465, 1.022119, 0.150619, 0.287210, -0.042385, 1.021988, 0.150490, 0.310935, -0.044758, + 1.021771, 0.150241, 0.335556, -0.047922, 1.021658, 0.150076, 0.360667, -0.051493, 1.021437, + 0.149931, 0.386028, -0.054931, 1.021228, 0.149754, 0.412665, -0.058007, 1.021023, 0.149400, + 0.439951, -0.060813, 1.020723, 0.148913, 0.467262, -0.063461, 1.020332, 0.148319, 0.494972, + -0.066738, 1.020097, 0.147798, 0.523153, -0.068976, 1.019630, 0.146903, 0.551700, -0.071268, + 1.019245, 0.145863, 0.580046, -0.073439, 1.018797, 0.144695, 0.608649, -0.075193, 1.018201, + 0.143237, 0.637239, -0.076536, 1.017746, 0.141463, 0.665388, -0.077771, 1.017111, 0.139462, + 0.693755, -0.078344, 1.016609, 0.137082, 0.721345, -0.078817, 1.015863, 0.134403, 0.748879, + -0.078512, 1.015390, 0.131252, 0.775560, -0.078128, 1.014652, 0.127866, 0.801897, -0.077094, + 1.013877, 0.123928, 0.827193, -0.075863, 1.013021, 0.119733, 0.851990, -0.073973, 1.012395, + 0.115055, 0.875823, -0.071765, 1.011595, 0.110098, 0.898655, -0.069241, 1.010862, 0.104722, + 0.920915, -0.066232, 1.010185, 0.098991, 0.941969, -0.062980, 1.009588, 0.093044, 0.961882, + -0.059507, 1.008777, 0.086925, 0.980952, -0.055606, 1.008252, 0.080520, 0.998955, -0.051503, + 1.007633, 0.073890, 1.015756, -0.047292, 1.006908, 0.067302, 1.031571, -0.042804, 1.006338, + 0.060412, 1.046095, -0.038132, 1.005512, 0.053497, 1.059542, -0.033380, 1.004592, 0.046569, + 1.072006, -0.028613, 1.003731, 0.039679, 1.083348, -0.023811, 1.002871, 0.032772, 1.093969, + -0.018930, 1.002068, 0.025894, 1.103697, -0.014098, 1.001284, 0.019178, 1.112813, -0.009339, + 1.000820, 0.012652, 1.121193, -0.004661, 1.000324, 0.006226, 1.128930, 0.000052, 0.999988, + -0.000008, 0.000200, -0.000035, 1.030857, 0.176327, 0.000504, -0.000089, 1.031137, 0.176326, + 0.002016, -0.000355, 1.031049, 0.176325, 0.004535, -0.000800, 1.031105, 0.176326, 0.008062, + -0.001422, 1.030973, 0.176326, 0.012598, -0.002221, 1.031168, 0.176326, 0.018141, -0.003199, + 1.031093, 0.176326, 0.024695, -0.004354, 1.031297, 0.176326, 0.032253, -0.005687, 1.031091, + 0.176327, 0.040821, -0.007197, 1.031012, 0.176326, 0.050399, -0.008886, 1.031068, 0.176325, + 0.060987, -0.010752, 1.030967, 0.176323, 0.072588, -0.012797, 1.031028, 0.176324, 0.085200, + -0.015019, 1.030985, 0.176322, 0.098829, -0.017419, 1.030983, 0.176320, 0.113474, -0.019997, + 1.030953, 0.176317, 0.129133, -0.022748, 1.030891, 0.176312, 0.145800, -0.025655, 1.030825, + 0.176306, 0.163372, -0.028510, 1.030781, 0.176279, 0.181578, -0.030914, 1.030683, 0.176187, + 0.200761, -0.034076, 1.030574, 0.176139, 0.220645, -0.037985, 1.030476, 0.176160, 0.241473, + -0.042391, 1.030384, 0.176238, 0.263922, -0.046105, 1.030241, 0.176175, 0.287074, -0.049390, + 1.030049, 0.176013, 0.310915, -0.052511, 1.029839, 0.175776, 0.335604, -0.056236, 1.029608, + 0.175578, 0.360775, -0.060118, 1.029355, 0.175359, 0.386196, -0.063907, 1.029052, 0.175083, + 0.412599, -0.067997, 1.028766, 0.174791, 0.439916, -0.071088, 1.028326, 0.174174, 0.467444, + -0.074247, 1.027890, 0.173487, 0.495132, -0.077728, 1.027374, 0.172774, 0.523117, -0.080822, + 1.026763, 0.171824, 0.551783, -0.083228, 1.026205, 0.170554, 0.580234, -0.085682, 1.025614, + 0.169090, 0.608568, -0.087860, 1.024668, 0.167468, 0.637357, -0.089346, 1.023939, 0.165283, + 0.665507, -0.090704, 1.022946, 0.162966, 0.693704, -0.091388, 1.022010, 0.160131, 0.721396, + -0.091783, 1.021085, 0.156957, 0.748676, -0.091688, 1.019894, 0.153292, 0.775370, -0.090992, + 1.018608, 0.149158, 0.801547, -0.089881, 1.017646, 0.144551, 0.827013, -0.088267, 1.016355, + 0.139614, 0.851708, -0.086132, 1.015446, 0.134026, 0.875652, -0.083707, 1.014321, 0.128101, + 0.898703, -0.080619, 1.013454, 0.121841, 0.920904, -0.077280, 1.012634, 0.115379, 0.942077, + -0.073484, 1.011770, 0.108355, 0.962245, -0.069252, 1.010894, 0.101153, 0.981385, -0.064807, + 1.010114, 0.093666, 0.999379, -0.060080, 1.009294, 0.086007, 1.016494, -0.055007, 1.008591, + 0.078194, 1.032357, -0.049760, 1.007821, 0.070328, 1.047061, -0.044468, 1.006871, 0.062358, + 1.060675, -0.038960, 1.006062, 0.054279, 1.073032, -0.033343, 1.004911, 0.046158, 1.084293, + -0.027699, 1.003791, 0.038111, 1.094724, -0.022130, 1.002744, 0.030239, 1.104302, -0.016508, + 1.001815, 0.022397, 1.113290, -0.010846, 1.001083, 0.014747, 1.121649, -0.005294, 1.000490, + 0.007234, 1.129230, 0.000071, 0.999975, -0.000053, 0.000200, -0.000040, 1.040431, 0.202155, + 0.000504, -0.000102, 1.040912, 0.202154, 0.002016, -0.000407, 1.041328, 0.202152, 0.004535, + -0.000917, 1.040877, 0.202154, 0.008063, -0.001630, 1.040867, 0.202153, 0.012598, -0.002547, + 1.040870, 0.202153, 0.018140, -0.003667, 1.040808, 0.202153, 0.024692, -0.004991, 1.040861, + 0.202153, 0.032252, -0.006519, 1.040861, 0.202153, 0.040822, -0.008252, 1.040864, 0.202153, + 0.050397, -0.010187, 1.040717, 0.202151, 0.060988, -0.012327, 1.040791, 0.202152, 0.072582, + -0.014669, 1.040640, 0.202149, 0.085198, -0.017217, 1.040716, 0.202147, 0.098827, -0.019968, + 1.040748, 0.202141, 0.113467, -0.022921, 1.040632, 0.202142, 0.129129, -0.026074, 1.040606, + 0.202137, 0.145793, -0.029399, 1.040566, 0.202127, 0.163294, -0.032524, 1.040459, 0.202078, + 0.181589, -0.035552, 1.040315, 0.201996, 0.200844, -0.039208, 1.040221, 0.201948, 0.220835, + -0.043489, 1.040047, 0.201945, 0.241471, -0.048523, 1.039921, 0.202031, 0.263854, -0.052764, + 1.039756, 0.201957, 0.286935, -0.056387, 1.039497, 0.201743, 0.310902, -0.060338, 1.039252, + 0.201531, 0.335642, -0.064594, 1.038954, 0.201286, 0.360859, -0.068772, 1.038582, 0.200983, + 0.386419, -0.073086, 1.038160, 0.200651, 0.412588, -0.077887, 1.037724, 0.200343, 0.439836, + -0.081391, 1.037182, 0.199618, 0.467538, -0.085121, 1.036602, 0.198839, 0.495286, -0.088718, + 1.035893, 0.197895, 0.523231, -0.092514, 1.035121, 0.196887, 0.551730, -0.095238, 1.034127, + 0.195390, 0.580302, -0.097949, 1.033131, 0.193668, 0.608559, -0.100418, 1.031962, 0.191773, + 0.637224, -0.102129, 1.030838, 0.189319, 0.665597, -0.103578, 1.029511, 0.186529, 0.693535, + -0.104652, 1.028263, 0.183303, 0.721325, -0.104766, 1.026611, 0.179497, 0.748384, -0.104717, + 1.025128, 0.175283, 0.775058, -0.103846, 1.023385, 0.170493, 0.801387, -0.102728, 1.022236, + 0.165187, 0.826412, -0.100679, 1.019908, 0.159362, 0.851314, -0.098451, 1.018839, 0.153059, + 0.875100, -0.095363, 1.017306, 0.146284, 0.898280, -0.092008, 1.016151, 0.138975, 0.920450, + -0.088095, 1.014880, 0.131361, 0.941727, -0.083690, 1.013556, 0.123417, 0.962308, -0.079077, + 1.012998, 0.115201, 0.981364, -0.073894, 1.011841, 0.106711, 0.999798, -0.068435, 1.011021, + 0.098063, 1.016983, -0.062830, 1.010194, 0.089183, 1.033039, -0.056914, 1.009292, 0.080190, + 1.047994, -0.050721, 1.008474, 0.071010, 1.061580, -0.044454, 1.007386, 0.061867, 1.074023, + -0.038145, 1.006135, 0.052711, 1.085470, -0.031679, 1.004890, 0.043595, 1.095673, -0.025157, + 1.003627, 0.034506, 1.105000, -0.018702, 1.002331, 0.025468, 1.113795, -0.012458, 1.001278, + 0.016834, 1.122012, -0.006169, 1.000548, 0.008265, 1.129683, 0.000078, 0.999988, -0.000072, + 0.000200, -0.000046, 1.052496, 0.228243, 0.000504, -0.000115, 1.052079, 0.228243, 0.002016, + -0.000460, 1.052079, 0.228241, 0.004535, -0.001035, 1.052091, 0.228242, 0.008062, -0.001840, + 1.051962, 0.228242, 0.012598, -0.002875, 1.052087, 0.228242, 0.018141, -0.004140, 1.052088, + 0.228242, 0.024692, -0.005636, 1.052096, 0.228239, 0.032251, -0.007361, 1.052029, 0.228243, + 0.040820, -0.009316, 1.052038, 0.228241, 0.050399, -0.011501, 1.052042, 0.228239, 0.060990, + -0.013917, 1.052046, 0.228238, 0.072586, -0.016562, 1.051990, 0.228236, 0.085198, -0.019437, + 1.051946, 0.228234, 0.098824, -0.022542, 1.051879, 0.228229, 0.113467, -0.025875, 1.051841, + 0.228227, 0.129121, -0.029430, 1.051724, 0.228219, 0.145780, -0.033170, 1.051672, 0.228205, + 0.163222, -0.036567, 1.051556, 0.228143, 0.181604, -0.040245, 1.051382, 0.228069, 0.200913, + -0.044395, 1.051230, 0.228010, 0.221005, -0.049088, 1.051062, 0.227988, 0.241667, -0.054506, + 1.050881, 0.228044, 0.263777, -0.059437, 1.050643, 0.227986, 0.286841, -0.063590, 1.050312, + 0.227755, 0.310879, -0.068224, 1.050009, 0.227525, 0.335650, -0.072986, 1.049597, 0.227253, + 0.360869, -0.077435, 1.049121, 0.226845, 0.386609, -0.082385, 1.048587, 0.226466, 0.412742, + -0.087570, 1.047987, 0.226059, 0.439789, -0.091929, 1.047308, 0.225331, 0.467558, -0.096038, + 1.046423, 0.224409, 0.495406, -0.099938, 1.045481, 0.223288, 0.523417, -0.104050, 1.044512, + 0.222066, 0.551755, -0.107503, 1.043408, 0.220487, 0.580468, -0.110234, 1.042016, 0.218451, + 0.608904, -0.112993, 1.040535, 0.216200, 0.637230, -0.115173, 1.038934, 0.213458, 0.665566, + -0.116433, 1.036961, 0.210158, 0.693413, -0.117589, 1.035130, 0.206457, 0.721025, -0.117885, + 1.033080, 0.202197, 0.748054, -0.117606, 1.030752, 0.197296, 0.774631, -0.116771, 1.028608, + 0.191813, 0.800677, -0.115194, 1.026350, 0.185691, 0.826062, -0.113138, 1.024472, 0.179053, + 0.850590, -0.110359, 1.022174, 0.171839, 0.874550, -0.107072, 1.020381, 0.164067, 0.897567, + -0.103268, 1.018777, 0.155959, 0.919609, -0.098794, 1.016886, 0.147320, 0.941177, -0.094067, + 1.015880, 0.138365, 0.961752, -0.088670, 1.014616, 0.129051, 0.981518, -0.082965, 1.013807, + 0.119515, 0.999880, -0.076971, 1.012793, 0.109897, 1.017370, -0.070518, 1.011894, 0.099872, + 1.033661, -0.063830, 1.010943, 0.089883, 1.048672, -0.057040, 1.009802, 0.079691, 1.062479, + -0.049917, 1.008670, 0.069458, 1.075052, -0.042735, 1.007429, 0.059191, 1.086371, -0.035513, + 1.005991, 0.048894, 1.096623, -0.028359, 1.004468, 0.038770, 1.105871, -0.021111, 1.002927, + 0.028745, 1.114481, -0.013908, 1.001728, 0.018884, 1.122610, -0.006843, 1.000740, 0.009264, + 1.130165, 0.000062, 0.999983, -0.000006, 0.000200, -0.000051, 1.064931, 0.254630, 0.000504, + -0.000128, 1.064668, 0.254630, 0.002016, -0.000513, 1.064794, 0.254630, 0.004535, -0.001155, + 1.064851, 0.254630, 0.008063, -0.002053, 1.064966, 0.254630, 0.012598, -0.003208, 1.064840, + 0.254630, 0.018140, -0.004619, 1.064602, 0.254631, 0.024695, -0.006288, 1.064965, 0.254632, + 0.032251, -0.008211, 1.064795, 0.254630, 0.040821, -0.010393, 1.064802, 0.254628, 0.050398, + -0.012830, 1.064758, 0.254627, 0.060987, -0.015525, 1.064731, 0.254625, 0.072584, -0.018474, + 1.064615, 0.254621, 0.085199, -0.021682, 1.064672, 0.254619, 0.098826, -0.025144, 1.064630, + 0.254613, 0.113465, -0.028860, 1.064515, 0.254606, 0.129119, -0.032823, 1.064416, 0.254598, + 0.145767, -0.036969, 1.064347, 0.254579, 0.163190, -0.040754, 1.064132, 0.254506, 0.181622, + -0.044989, 1.063951, 0.254437, 0.200981, -0.049642, 1.063745, 0.254370, 0.221145, -0.054776, + 1.063547, 0.254324, 0.241896, -0.060538, 1.063289, 0.254346, 0.263684, -0.066113, 1.063013, + 0.254296, 0.286796, -0.070925, 1.062625, 0.254059, 0.310867, -0.076187, 1.062216, 0.253817, + 0.335644, -0.081406, 1.061703, 0.253481, 0.360917, -0.086336, 1.061066, 0.253005, 0.386786, + -0.091790, 1.060454, 0.252558, 0.412921, -0.097230, 1.059568, 0.252008, 0.439722, -0.102574, + 1.058706, 0.251323, 0.467559, -0.106972, 1.057682, 0.250239, 0.495605, -0.111329, 1.056612, + 0.248944, 0.523589, -0.115561, 1.055101, 0.247471, 0.551787, -0.119732, 1.053745, 0.245777, + 0.580426, -0.122711, 1.051829, 0.243448, 0.608778, -0.125436, 1.049642, 0.240769, 0.637069, + -0.127993, 1.047749, 0.237739, 0.665251, -0.129448, 1.045244, 0.233928, 0.692977, -0.130408, + 1.042279, 0.229640, 0.720346, -0.130931, 1.039693, 0.224829, 0.747365, -0.130392, 1.036675, + 0.219144, 0.773734, -0.129540, 1.033719, 0.212965, 0.799578, -0.127689, 1.030774, 0.206047, + 0.825002, -0.125456, 1.028551, 0.198576, 0.849564, -0.122291, 1.025800, 0.190471, 0.873412, + -0.118720, 1.023657, 0.181739, 0.896628, -0.114323, 1.021381, 0.172586, 0.918952, -0.109587, + 1.019674, 0.162914, 0.940602, -0.104093, 1.018126, 0.153039, 0.960917, -0.098187, 1.016339, + 0.142774, 0.980911, -0.091963, 1.015440, 0.132316, 0.999686, -0.085159, 1.014377, 0.121453, + 1.017538, -0.078139, 1.013498, 0.110527, 1.033918, -0.070797, 1.012332, 0.099437, 1.049390, + -0.063129, 1.011368, 0.088157, 1.063402, -0.055354, 1.010111, 0.076951, 1.076096, -0.047522, + 1.008774, 0.065616, 1.087562, -0.039447, 1.007202, 0.054310, 1.097591, -0.031359, 1.005346, + 0.042948, 1.106782, -0.023393, 1.003710, 0.031799, 1.115234, -0.015461, 1.002116, 0.020943, + 1.123166, -0.007589, 1.000858, 0.010288, 1.130796, 0.000104, 1.000032, -0.000024, 0.000200, + -0.000056, 1.078780, 0.281356, 0.000504, -0.000142, 1.079271, 0.281355, 0.002015, -0.000567, + 1.078635, 0.281355, 0.004535, -0.001276, 1.079164, 0.281356, 0.008064, -0.002269, 1.079300, + 0.281355, 0.012598, -0.003544, 1.079149, 0.281355, 0.018143, -0.005104, 1.079329, 0.281355, + 0.024691, -0.006947, 1.079073, 0.281353, 0.032254, -0.009074, 1.079253, 0.281354, 0.040822, + -0.011484, 1.079176, 0.281353, 0.050399, -0.014177, 1.079057, 0.281349, 0.060987, -0.017153, + 1.079007, 0.281347, 0.072586, -0.020412, 1.078998, 0.281343, 0.085203, -0.023956, 1.078962, + 0.281336, 0.098823, -0.027778, 1.078839, 0.281332, 0.113464, -0.031882, 1.078783, 0.281325, + 0.129114, -0.036255, 1.078633, 0.281315, 0.145748, -0.040790, 1.078545, 0.281287, 0.163179, + -0.045024, 1.078311, 0.281208, 0.181649, -0.049791, 1.078135, 0.281137, 0.201042, -0.054953, + 1.077845, 0.281063, 0.221267, -0.060551, 1.077576, 0.281006, 0.242114, -0.066663, 1.077257, + 0.280978, 0.263568, -0.072771, 1.076897, 0.280925, 0.286744, -0.078349, 1.076405, 0.280689, + 0.310840, -0.084201, 1.075898, 0.280418, 0.335612, -0.089846, 1.075287, 0.280020, 0.360975, + -0.095394, 1.074482, 0.279513, 0.386932, -0.101290, 1.073617, 0.278961, 0.413171, -0.107042, + 1.072719, 0.278283, 0.439886, -0.113083, 1.071698, 0.277547, 0.467535, -0.118010, 1.070213, + 0.276311, 0.495701, -0.122793, 1.068857, 0.274867, 0.523772, -0.127278, 1.067037, 0.273153, + 0.551849, -0.131671, 1.064923, 0.271176, 0.580338, -0.135293, 1.062749, 0.268626, 0.608771, + -0.138065, 1.059944, 0.265569, 0.636756, -0.140565, 1.056851, 0.262054, 0.664574, -0.142434, + 1.053461, 0.257807, 0.692151, -0.143237, 1.049910, 0.252930, 0.719376, -0.143717, 1.046426, + 0.247414, 0.745852, -0.143117, 1.042377, 0.241001, 0.772300, -0.141975, 1.038789, 0.233797, + 0.798050, -0.140114, 1.035290, 0.226218, 0.823370, -0.137379, 1.032374, 0.217785, 0.847735, + -0.134119, 1.028853, 0.208748, 0.871897, -0.129985, 1.026395, 0.198877, 0.894950, -0.125324, + 1.023787, 0.188803, 0.917909, -0.120007, 1.022073, 0.178493, 0.939567, -0.114099, 1.020098, + 0.167466, 0.960534, -0.107748, 1.018851, 0.156223, 0.980423, -0.100748, 1.017362, 0.144716, + 0.999334, -0.093494, 1.015961, 0.133028, 1.017561, -0.085728, 1.015059, 0.120953, 1.034225, + -0.077627, 1.013888, 0.108943, 1.049937, -0.069375, 1.012898, 0.096678, 1.064265, -0.060807, + 1.011635, 0.084350, 1.077188, -0.052052, 1.010095, 0.071964, 1.088637, -0.043304, 1.008399, + 0.059531, 1.098766, -0.034458, 1.006397, 0.047134, 1.107697, -0.025637, 1.004354, 0.034887, + 1.116055, -0.016932, 1.002611, 0.022948, 1.123819, -0.008437, 1.001023, 0.011386, 1.131333, + 0.000087, 0.999952, -0.000097, 0.000200, -0.000062, 1.095622, 0.308458, 0.000504, -0.000155, + 1.094863, 0.308458, 0.002016, -0.000622, 1.095169, 0.308458, 0.004535, -0.001399, 1.095156, + 0.308458, 0.008063, -0.002487, 1.095413, 0.308455, 0.012598, -0.003886, 1.095147, 0.308458, + 0.018141, -0.005596, 1.095150, 0.308457, 0.024692, -0.007616, 1.095140, 0.308457, 0.032252, + -0.009947, 1.095098, 0.308456, 0.040822, -0.012589, 1.095096, 0.308453, 0.050399, -0.015541, + 1.095070, 0.308451, 0.060985, -0.018803, 1.094922, 0.308448, 0.072583, -0.022375, 1.094902, + 0.308444, 0.085197, -0.026258, 1.094882, 0.308438, 0.098822, -0.030448, 1.094775, 0.308429, + 0.113460, -0.034944, 1.094641, 0.308419, 0.129112, -0.039731, 1.094530, 0.308403, 0.145711, + -0.044610, 1.094332, 0.308365, 0.163178, -0.049362, 1.094149, 0.308285, 0.181679, -0.054666, + 1.093876, 0.308210, 0.201109, -0.060336, 1.093603, 0.308132, 0.221388, -0.066414, 1.093250, + 0.308047, 0.242315, -0.072881, 1.092835, 0.307985, 0.263651, -0.079453, 1.092391, 0.307902, + 0.286720, -0.085882, 1.091866, 0.307688, 0.310817, -0.092274, 1.091225, 0.307379, 0.335562, + -0.098306, 1.090346, 0.306906, 0.361043, -0.104572, 1.089423, 0.306374, 0.387051, -0.110843, + 1.088437, 0.305710, 0.413405, -0.117062, 1.087228, 0.304906, 0.440122, -0.123501, 1.085879, + 0.304017, 0.467522, -0.129245, 1.084197, 0.302783, 0.495721, -0.134285, 1.082284, 0.301104, + 0.523925, -0.139143, 1.080109, 0.299142, 0.551814, -0.143638, 1.077043, 0.296825, 0.579878, + -0.147774, 1.074071, 0.294071, 0.608316, -0.150724, 1.070621, 0.290519, 0.636059, -0.153168, + 1.066390, 0.286424, 0.663481, -0.155139, 1.062069, 0.281559, 0.690753, -0.155944, 1.057211, + 0.276024, 0.717767, -0.156176, 1.052682, 0.269622, 0.743937, -0.155783, 1.047747, 0.262532, + 0.770214, -0.154245, 1.043510, 0.254609, 0.795542, -0.152192, 1.039121, 0.246007, 0.821099, + -0.149256, 1.035962, 0.236663, 0.845452, -0.145605, 1.032320, 0.226751, 0.869780, -0.141186, + 1.029390, 0.216165, 0.893141, -0.136137, 1.026485, 0.204937, 0.916034, -0.130332, 1.024389, + 0.193624, 0.938089, -0.124040, 1.022270, 0.181756, 0.959488, -0.117011, 1.020457, 0.169339, + 0.979594, -0.109617, 1.018871, 0.156875, 0.998912, -0.101562, 1.017533, 0.144288, 1.017100, + -0.093164, 1.016445, 0.131370, 1.034413, -0.084488, 1.015453, 0.118322, 1.050347, -0.075377, + 1.014259, 0.104963, 1.064958, -0.066108, 1.013057, 0.091722, 1.078045, -0.056702, 1.011491, + 0.078231, 1.089749, -0.047106, 1.009662, 0.064797, 1.099831, -0.037467, 1.007417, 0.051315, + 1.108789, -0.027990, 1.005144, 0.038064, 1.116865, -0.018464, 1.002925, 0.025008, 1.124609, + -0.009068, 1.001221, 0.012250, 1.132040, 0.000093, 0.999984, -0.000071, 0.000200, -0.000067, + 1.112554, 0.335981, 0.000504, -0.000169, 1.112660, 0.335981, 0.002016, -0.000677, 1.112827, + 0.335981, 0.004533, -0.001523, 1.112147, 0.335982, 0.008063, -0.002709, 1.112882, 0.335979, + 0.012598, -0.004233, 1.112891, 0.335980, 0.018141, -0.006095, 1.112882, 0.335980, 0.024693, + -0.008296, 1.112877, 0.335978, 0.032252, -0.010834, 1.112860, 0.335976, 0.040824, -0.013713, + 1.112965, 0.335974, 0.050398, -0.016927, 1.112753, 0.335971, 0.060991, -0.020482, 1.112826, + 0.335970, 0.072587, -0.024371, 1.112676, 0.335962, 0.085199, -0.028597, 1.112593, 0.335955, + 0.098822, -0.033159, 1.112453, 0.335943, 0.113461, -0.038052, 1.112329, 0.335930, 0.129108, + -0.043255, 1.112144, 0.335910, 0.145665, -0.048412, 1.111905, 0.335857, 0.163185, -0.053786, + 1.111668, 0.335781, 0.181710, -0.059608, 1.111345, 0.335696, 0.201166, -0.065794, 1.110979, + 0.335606, 0.221489, -0.072361, 1.110553, 0.335505, 0.242471, -0.079184, 1.110112, 0.335396, + 0.263900, -0.086213, 1.109584, 0.335271, 0.286688, -0.093491, 1.108927, 0.335089, 0.310773, + -0.100406, 1.108091, 0.334737, 0.335573, -0.106987, 1.107169, 0.334208, 0.361117, -0.113844, + 1.106097, 0.333600, 0.387175, -0.120463, 1.104826, 0.332828, 0.413665, -0.127245, 1.103415, + 0.331929, 0.440386, -0.133927, 1.101632, 0.330851, 0.467527, -0.140496, 1.099563, 0.329538, + 0.495630, -0.145874, 1.096956, 0.327618, 0.523864, -0.150997, 1.094201, 0.325390, 0.551705, + -0.155713, 1.090342, 0.322688, 0.579383, -0.159993, 1.086010, 0.319483, 0.607301, -0.163238, + 1.081226, 0.315522, 0.634873, -0.165667, 1.076065, 0.310840, 0.662028, -0.167606, 1.070466, + 0.305377, 0.688755, -0.168626, 1.064601, 0.299056, 0.715612, -0.168578, 1.059269, 0.291963, + 0.741604, -0.167961, 1.053648, 0.284018, 0.767757, -0.166439, 1.048928, 0.275474, 0.793264, + -0.164023, 1.044343, 0.266056, 0.818165, -0.160965, 1.039909, 0.255750, 0.843255, -0.156896, + 1.036180, 0.244843, 0.867249, -0.152262, 1.032303, 0.233464, 0.890994, -0.146655, 1.029365, + 0.221128, 0.913829, -0.140574, 1.026607, 0.208554, 0.936508, -0.133640, 1.024512, 0.195772, + 0.957720, -0.126220, 1.022421, 0.182420, 0.978940, -0.118164, 1.021293, 0.168852, 0.998285, + -0.109558, 1.019444, 0.155261, 1.016764, -0.100562, 1.017825, 0.141395, 1.034387, -0.091064, + 1.016996, 0.127311, 1.050916, -0.081468, 1.015945, 0.113089, 1.065652, -0.071463, 1.014547, + 0.098879, 1.079155, -0.061240, 1.013066, 0.084468, 1.090822, -0.050980, 1.010788, 0.069940, + 1.101100, -0.040549, 1.008563, 0.055475, 1.109824, -0.030101, 1.005950, 0.041033, 1.117828, + -0.019884, 1.003453, 0.027022, 1.125443, -0.009900, 1.001484, 0.013306, 1.132869, 0.000094, + 1.000004, -0.000046, 0.000200, -0.000073, 1.132849, 0.363970, 0.000504, -0.000183, 1.132155, + 0.363969, 0.002016, -0.000734, 1.132516, 0.363969, 0.004535, -0.001651, 1.132256, 0.363969, + 0.008062, -0.002934, 1.132318, 0.363966, 0.012597, -0.004585, 1.132386, 0.363968, 0.018141, + -0.006602, 1.132457, 0.363967, 0.024693, -0.008987, 1.132511, 0.363967, 0.032252, -0.011737, + 1.132488, 0.363965, 0.040819, -0.014853, 1.132241, 0.363959, 0.050398, -0.018336, 1.132372, + 0.363958, 0.060988, -0.022185, 1.132373, 0.363954, 0.072582, -0.026396, 1.132137, 0.363943, + 0.085195, -0.030973, 1.132071, 0.363935, 0.098822, -0.035913, 1.131978, 0.363922, 0.113461, + -0.041209, 1.131801, 0.363905, 0.129116, -0.046833, 1.131535, 0.363867, 0.145640, -0.052346, + 1.131290, 0.363814, 0.163199, -0.058275, 1.131046, 0.363734, 0.181742, -0.064623, 1.130671, + 0.363642, 0.201227, -0.071336, 1.130224, 0.363539, 0.221587, -0.078396, 1.129758, 0.363419, + 0.242625, -0.085545, 1.129213, 0.363256, 0.264183, -0.093110, 1.128549, 0.363097, 0.286668, + -0.101206, 1.127767, 0.362939, 0.310745, -0.108586, 1.126796, 0.362516, 0.335602, -0.115827, + 1.125686, 0.361953, 0.361202, -0.123212, 1.124451, 0.361275, 0.387298, -0.130294, 1.122861, + 0.360376, 0.413918, -0.137553, 1.121154, 0.359362, 0.440680, -0.144577, 1.118825, 0.358069, + 0.467667, -0.151558, 1.116002, 0.356581, 0.495449, -0.157621, 1.112778, 0.354531, 0.523514, + -0.162844, 1.108842, 0.351915, 0.551250, -0.167744, 1.104075, 0.348797, 0.578629, -0.172132, + 1.098733, 0.345222, 0.605757, -0.175733, 1.092224, 0.340665, 0.633392, -0.178109, 1.086201, + 0.335286, 0.660783, -0.180009, 1.080110, 0.329286, 0.687219, -0.181105, 1.073419, 0.322319, + 0.713873, -0.181046, 1.067410, 0.314616, 0.740094, -0.180219, 1.061414, 0.306014, 0.765233, + -0.178559, 1.055287, 0.296704, 0.790885, -0.175806, 1.049727, 0.286394, 0.815464, -0.172354, + 1.044519, 0.275189, 0.840259, -0.168048, 1.040375, 0.263441, 0.864285, -0.162904, 1.036010, + 0.250918, 0.888806, -0.157194, 1.033525, 0.237611, 0.911682, -0.150486, 1.029490, 0.223809, + 0.934481, -0.143212, 1.026778, 0.209705, 0.956337, -0.135233, 1.024632, 0.195281, 0.977380, + -0.126650, 1.022737, 0.180878, 0.997427, -0.117552, 1.021110, 0.166112, 1.016666, -0.107814, + 1.019869, 0.151231, 1.034337, -0.097814, 1.018543, 0.136375, 1.051082, -0.087330, 1.017476, + 0.121187, 1.066326, -0.076614, 1.016083, 0.106043, 1.079897, -0.065793, 1.014227, 0.090566, + 1.092136, -0.054654, 1.012334, 0.074988, 1.102315, -0.043516, 1.009627, 0.059577, 1.111105, + -0.032509, 1.006808, 0.044202, 1.118861, -0.021381, 1.003917, 0.028995, 1.126363, -0.010489, + 1.001670, 0.014269, 1.133598, 0.000083, 0.999989, -0.000035, 0.000200, -0.000079, 1.155026, + 0.392470, 0.000504, -0.000198, 1.154184, 0.392469, 0.002016, -0.000791, 1.153990, 0.392469, + 0.004535, -0.001780, 1.154045, 0.392469, 0.008063, -0.003164, 1.154007, 0.392466, 0.012598, + -0.004944, 1.154022, 0.392469, 0.018141, -0.007119, 1.154015, 0.392468, 0.024692, -0.009690, + 1.154017, 0.392466, 0.032254, -0.012656, 1.154069, 0.392465, 0.040826, -0.016018, 1.153980, + 0.392459, 0.050399, -0.019771, 1.153911, 0.392456, 0.060987, -0.023919, 1.153860, 0.392447, + 0.072588, -0.028461, 1.153777, 0.392442, 0.085197, -0.033393, 1.153582, 0.392428, 0.098822, + -0.038716, 1.153434, 0.392412, 0.113462, -0.044422, 1.153271, 0.392390, 0.129101, -0.050455, + 1.153019, 0.392359, 0.145642, -0.056392, 1.152721, 0.392283, 0.163223, -0.062859, 1.152404, + 0.392201, 0.181779, -0.069721, 1.151941, 0.392099, 0.201289, -0.076968, 1.151422, 0.391978, + 0.221678, -0.084518, 1.150861, 0.391833, 0.242752, -0.092017, 1.150156, 0.391618, 0.264474, + -0.100184, 1.149402, 0.391421, 0.286768, -0.108921, 1.148545, 0.391249, 0.310719, -0.116815, + 1.147388, 0.390773, 0.335638, -0.124785, 1.146042, 0.390168, 0.361240, -0.132630, 1.144529, + 0.389394, 0.387443, -0.140298, 1.142602, 0.388391, 0.414067, -0.147913, 1.140361, 0.387199, + 0.440904, -0.155362, 1.137612, 0.385742, 0.467771, -0.162574, 1.133659, 0.383926, 0.494907, + -0.169312, 1.129246, 0.381715, 0.522801, -0.174778, 1.124228, 0.378678, 0.550751, -0.179824, + 1.118697, 0.375158, 0.578018, -0.184284, 1.112019, 0.370851, 0.605291, -0.188215, 1.105151, + 0.365928, 0.632269, -0.190760, 1.097677, 0.360114, 0.659432, -0.192457, 1.090816, 0.353498, + 0.685839, -0.193458, 1.083286, 0.346094, 0.711876, -0.193502, 1.076245, 0.337754, 0.738184, + -0.192371, 1.069684, 0.328412, 0.763723, -0.190531, 1.063249, 0.318164, 0.789192, -0.187726, + 1.057265, 0.306900, 0.813744, -0.183783, 1.051177, 0.295021, 0.838408, -0.179328, 1.045902, + 0.282144, 0.862116, -0.173573, 1.040853, 0.268438, 0.885636, -0.167350, 1.036515, 0.254108, + 0.909342, -0.160229, 1.033269, 0.239082, 0.931962, -0.152529, 1.029627, 0.224024, 0.954671, + -0.144080, 1.027507, 0.208393, 0.975707, -0.135023, 1.024657, 0.192630, 0.996644, -0.125258, + 1.022998, 0.176741, 1.015817, -0.115089, 1.021234, 0.160926, 1.034301, -0.104317, 1.020025, + 0.145042, 1.051131, -0.093218, 1.018739, 0.129052, 1.066836, -0.081828, 1.017419, 0.112905, + 1.081027, -0.070132, 1.015714, 0.096578, 1.093225, -0.058382, 1.013465, 0.080077, 1.103691, + -0.046527, 1.010853, 0.063580, 1.112431, -0.034624, 1.007702, 0.047118, 1.120035, -0.022913, + 1.004551, 0.031018, 1.127336, -0.011284, 1.001924, 0.015283, 1.134510, 0.000170, 0.999937, + -0.000058, 0.000200, -0.000084, 1.177044, 0.421534, 0.000504, -0.000212, 1.177312, 0.421533, + 0.002016, -0.000850, 1.177730, 0.421533, 0.004535, -0.001912, 1.177722, 0.421533, 0.008063, + -0.003399, 1.177844, 0.421529, 0.012598, -0.005310, 1.177768, 0.421533, 0.018141, -0.007646, + 1.177730, 0.421531, 0.024692, -0.010407, 1.177663, 0.421530, 0.032252, -0.013592, 1.177681, + 0.421527, 0.040821, -0.017201, 1.177562, 0.421524, 0.050401, -0.021234, 1.177445, 0.421516, + 0.060988, -0.025688, 1.177461, 0.421509, 0.072590, -0.030565, 1.177364, 0.421498, 0.085200, + -0.035860, 1.177205, 0.421482, 0.098823, -0.041572, 1.177011, 0.421462, 0.113465, -0.047694, + 1.176794, 0.421436, 0.129094, -0.054122, 1.176504, 0.421396, 0.145652, -0.060530, 1.176203, + 0.421311, 0.163245, -0.067517, 1.175805, 0.421218, 0.181825, -0.074919, 1.175271, 0.421108, + 0.201360, -0.082700, 1.174717, 0.420974, 0.221773, -0.090727, 1.174021, 0.420795, 0.242908, + -0.098719, 1.173173, 0.420536, 0.264742, -0.107417, 1.172285, 0.420296, 0.287091, -0.116601, + 1.171326, 0.420065, 0.310723, -0.125265, 1.169907, 0.419582, 0.335685, -0.133876, 1.168352, + 0.418912, 0.361285, -0.142140, 1.166322, 0.418006, 0.387562, -0.150436, 1.164136, 0.416899, + 0.414175, -0.158388, 1.161162, 0.415513, 0.441021, -0.166258, 1.157608, 0.413836, 0.467698, + -0.173720, 1.152519, 0.411702, 0.494730, -0.180843, 1.147020, 0.409102, 0.522524, -0.186906, + 1.141256, 0.405789, 0.550055, -0.192004, 1.134114, 0.401759, 0.577512, -0.196588, 1.127086, + 0.397153, 0.604348, -0.200420, 1.119029, 0.391767, 0.630970, -0.203320, 1.110308, 0.385573, + 0.658023, -0.204883, 1.102643, 0.378245, 0.684422, -0.205716, 1.094573, 0.370191, 0.710405, + -0.205767, 1.086405, 0.361231, 0.736417, -0.204513, 1.078712, 0.351106, 0.761836, -0.202281, + 1.071619, 0.340096, 0.787140, -0.199395, 1.064873, 0.328139, 0.812197, -0.195185, 1.058313, + 0.315044, 0.836342, -0.190191, 1.052085, 0.300933, 0.860311, -0.184343, 1.046705, 0.286411, + 0.883597, -0.177415, 1.041072, 0.270897, 0.906852, -0.170003, 1.036797, 0.254825, 0.929991, + -0.161592, 1.033264, 0.238176, 0.952478, -0.152792, 1.030250, 0.221581, 0.974216, -0.143032, + 1.027331, 0.204378, 0.995372, -0.132922, 1.025135, 0.187470, 1.015330, -0.122009, 1.023250, + 0.170538, 1.034070, -0.110740, 1.022021, 0.153777, 1.051295, -0.099016, 1.020271, 0.136916, + 1.067460, -0.086920, 1.018948, 0.119880, 1.082022, -0.074729, 1.017336, 0.102565, 1.094378, + -0.062036, 1.014820, 0.084994, 1.104998, -0.049413, 1.011999, 0.067650, 1.113773, -0.036812, + 1.008711, 0.050148, 1.121263, -0.024274, 1.005141, 0.032976, 1.128420, -0.012038, 1.002196, + 0.016239, 1.135496, 0.000106, 1.000042, -0.000062, 0.000200, -0.000090, 1.203048, 0.451217, + 0.000504, -0.000227, 1.203226, 0.451215, 0.002016, -0.000909, 1.203450, 0.451215, 0.004535, + -0.002046, 1.203569, 0.451215, 0.008062, -0.003638, 1.203609, 0.451209, 0.012598, -0.005684, + 1.203580, 0.451214, 0.018141, -0.008185, 1.203515, 0.451212, 0.024694, -0.011141, 1.203618, + 0.451211, 0.032253, -0.014549, 1.203609, 0.451207, 0.040815, -0.018409, 1.203302, 0.451203, + 0.050401, -0.022727, 1.203454, 0.451195, 0.060990, -0.027495, 1.203480, 0.451188, 0.072591, + -0.032713, 1.203220, 0.451172, 0.085203, -0.038378, 1.203058, 0.451154, 0.098829, -0.044489, + 1.202838, 0.451130, 0.113466, -0.051031, 1.202530, 0.451098, 0.129084, -0.057808, 1.202270, + 0.451041, 0.145669, -0.064769, 1.201904, 0.450956, 0.163278, -0.072278, 1.201411, 0.450853, + 0.181880, -0.080224, 1.200825, 0.450721, 0.201436, -0.088537, 1.200164, 0.450566, 0.221865, + -0.097009, 1.199335, 0.450351, 0.243083, -0.105591, 1.198383, 0.450062, 0.265033, -0.114818, + 1.197380, 0.449769, 0.287456, -0.124372, 1.196137, 0.449438, 0.310758, -0.133892, 1.194554, + 0.448974, 0.335721, -0.143052, 1.192649, 0.448216, 0.361348, -0.151868, 1.190233, 0.447202, + 0.387573, -0.160644, 1.187211, 0.445926, 0.414159, -0.169028, 1.183452, 0.444313, 0.440950, + -0.177169, 1.178562, 0.442315, 0.467998, -0.185090, 1.173540, 0.439960, 0.494566, -0.192396, + 1.166344, 0.436989, 0.521730, -0.198915, 1.159283, 0.433439, 0.549405, -0.204240, 1.151503, + 0.428984, 0.576755, -0.208861, 1.143004, 0.423839, 0.603635, -0.212734, 1.134099, 0.418012, + 0.629979, -0.215712, 1.124555, 0.411445, 0.656597, -0.217385, 1.115293, 0.403628, 0.683317, + -0.218093, 1.106460, 0.394639, 0.708990, -0.217835, 1.097389, 0.385012, 0.734898, -0.216774, + 1.088940, 0.373999, 0.760342, -0.214120, 1.080385, 0.362128, 0.785517, -0.210821, 1.072959, + 0.349184, 0.809933, -0.206443, 1.065450, 0.335080, 0.834339, -0.200942, 1.058701, 0.320257, + 0.858793, -0.194938, 1.052711, 0.304133, 0.882300, -0.187615, 1.047044, 0.287771, 0.905560, + -0.179626, 1.042083, 0.270571, 0.927916, -0.170753, 1.037077, 0.252741, 0.950415, -0.161270, + 1.033200, 0.234656, 0.972920, -0.151239, 1.030418, 0.216652, 0.993893, -0.140358, 1.027479, + 0.198252, 1.014204, -0.128963, 1.024897, 0.180113, 1.033878, -0.117128, 1.023648, 0.162282, + 1.051754, -0.104678, 1.022230, 0.144366, 1.067924, -0.092000, 1.020453, 0.126455, 1.082643, + -0.078837, 1.018518, 0.108194, 1.095503, -0.065669, 1.016199, 0.089966, 1.106290, -0.052345, + 1.013113, 0.071530, 1.115219, -0.039024, 1.009636, 0.053158, 1.122587, -0.025789, 1.005801, + 0.034959, 1.129461, -0.012622, 1.002442, 0.017222, 1.136468, 0.000152, 0.999964, -0.000065, + 0.000200, -0.000096, 1.231156, 0.481574, 0.000504, -0.000243, 1.232187, 0.481572, 0.002016, + -0.000971, 1.231948, 0.481572, 0.004535, -0.002184, 1.231919, 0.481572, 0.008061, -0.003882, + 1.231453, 0.481566, 0.012597, -0.006066, 1.231800, 0.481572, 0.018142, -0.008736, 1.231756, + 0.481569, 0.024693, -0.011889, 1.232062, 0.481570, 0.032254, -0.015528, 1.231915, 0.481563, + 0.040822, -0.019650, 1.231863, 0.481559, 0.050402, -0.024255, 1.231737, 0.481550, 0.060992, + -0.029342, 1.231678, 0.481537, 0.072592, -0.034908, 1.231537, 0.481521, 0.085207, -0.040953, + 1.231336, 0.481499, 0.098834, -0.047469, 1.231071, 0.481469, 0.113474, -0.054441, 1.230757, + 0.481431, 0.129077, -0.061556, 1.230424, 0.481359, 0.145691, -0.069091, 1.230022, 0.481269, + 0.163321, -0.077151, 1.229461, 0.481156, 0.181936, -0.085636, 1.228718, 0.481011, 0.201516, + -0.094484, 1.228023, 0.480830, 0.221963, -0.103362, 1.227057, 0.480562, 0.243264, -0.112628, + 1.225997, 0.480247, 0.265291, -0.122366, 1.224744, 0.479891, 0.287824, -0.132256, 1.223255, + 0.479461, 0.310927, -0.142614, 1.221348, 0.478978, 0.335749, -0.152326, 1.218953, 0.478132, + 0.361361, -0.161747, 1.215806, 0.476971, 0.387480, -0.170879, 1.211853, 0.475477, 0.414231, + -0.179865, 1.207783, 0.473686, 0.441065, -0.188331, 1.202051, 0.471415, 0.467923, -0.196454, + 1.195463, 0.468647, 0.494526, -0.204048, 1.187542, 0.465459, 0.521318, -0.211020, 1.179235, + 0.461650, 0.548654, -0.216520, 1.170110, 0.456868, 0.575778, -0.221098, 1.160163, 0.451227, + 0.602610, -0.224923, 1.149751, 0.444866, 0.628891, -0.227895, 1.139169, 0.437577, 0.655635, + -0.230020, 1.129736, 0.429369, 0.682115, -0.230419, 1.119516, 0.419673, 0.707514, -0.229789, + 1.108277, 0.409143, 0.733169, -0.228520, 1.099159, 0.397296, 0.758342, -0.225793, 1.089839, + 0.384578, 0.783477, -0.222049, 1.081428, 0.370323, 0.808497, -0.217562, 1.073742, 0.355253, + 0.832790, -0.211697, 1.065850, 0.339282, 0.856677, -0.204989, 1.058834, 0.322181, 0.880662, + -0.197653, 1.053291, 0.304610, 0.903474, -0.188858, 1.046822, 0.286042, 0.926313, -0.179746, + 1.041663, 0.267224, 0.948458, -0.169542, 1.036532, 0.247978, 0.970873, -0.159005, 1.033008, + 0.228535, 0.992958, -0.147658, 1.029844, 0.208819, 1.013413, -0.135771, 1.026930, 0.189486, + 1.033483, -0.123256, 1.025545, 0.170422, 1.051872, -0.110401, 1.023935, 0.152075, 1.068396, + -0.096860, 1.022092, 0.133169, 1.083731, -0.083259, 1.020221, 0.114022, 1.096849, -0.069266, + 1.017663, 0.094772, 1.107864, -0.055203, 1.014524, 0.075432, 1.116600, -0.041097, 1.010514, + 0.055980, 1.123871, -0.027083, 1.006313, 0.036839, 1.130718, -0.013510, 1.002778, 0.018156, + 1.137649, 0.000154, 1.000033, -0.000028, 0.000200, -0.000103, 1.264025, 0.512670, 0.000504, + -0.000258, 1.262437, 0.512667, 0.002016, -0.001033, 1.262691, 0.512668, 0.004535, -0.002325, + 1.262834, 0.512667, 0.008063, -0.004133, 1.262783, 0.512659, 0.012598, -0.006458, 1.262803, + 0.512666, 0.018141, -0.009299, 1.262720, 0.512665, 0.024683, -0.012652, 1.262061, 0.512655, + 0.032257, -0.016532, 1.262858, 0.512656, 0.040826, -0.020919, 1.262709, 0.512649, 0.050403, + -0.025820, 1.262685, 0.512639, 0.060993, -0.031233, 1.262544, 0.512625, 0.072597, -0.037157, + 1.262435, 0.512607, 0.085211, -0.043587, 1.262209, 0.512581, 0.098842, -0.050520, 1.261907, + 0.512544, 0.113484, -0.057926, 1.261575, 0.512500, 0.129097, -0.065460, 1.261293, 0.512420, + 0.145727, -0.073543, 1.260736, 0.512316, 0.163375, -0.082134, 1.260117, 0.512190, 0.182011, + -0.091173, 1.259299, 0.512024, 0.201598, -0.100540, 1.258381, 0.511810, 0.222084, -0.109931, + 1.257293, 0.511505, 0.243446, -0.119838, 1.256050, 0.511151, 0.265574, -0.130090, 1.254607, + 0.510724, 0.288230, -0.140421, 1.252808, 0.510191, 0.311336, -0.151343, 1.250489, 0.509627, + 0.335719, -0.161689, 1.247279, 0.508688, 0.361314, -0.171748, 1.243467, 0.507393, 0.387541, + -0.181399, 1.239145, 0.505758, 0.414204, -0.190768, 1.233760, 0.503676, 0.441092, -0.199659, + 1.227433, 0.501129, 0.467789, -0.207934, 1.219247, 0.498078, 0.494454, -0.215747, 1.210441, + 0.494630, 0.520950, -0.222869, 1.200559, 0.490467, 0.547802, -0.228881, 1.189872, 0.485444, + 0.575563, -0.233760, 1.180081, 0.479268, 0.602426, -0.237566, 1.168544, 0.472272, 0.628772, + -0.240447, 1.156546, 0.464390, 0.654963, -0.242427, 1.145123, 0.455345, 0.681384, -0.242980, + 1.134322, 0.444885, 0.707173, -0.242150, 1.122665, 0.433338, 0.732477, -0.240435, 1.111733, + 0.420647, 0.757567, -0.237806, 1.101271, 0.406799, 0.782341, -0.233503, 1.091341, 0.391761, + 0.806690, -0.228346, 1.082042, 0.375576, 0.830804, -0.222386, 1.073504, 0.358545, 0.854940, + -0.215141, 1.065880, 0.340431, 0.878709, -0.207207, 1.058850, 0.321690, 0.901928, -0.198273, + 1.052588, 0.301930, 0.924845, -0.188476, 1.046521, 0.281513, 0.946932, -0.177996, 1.040966, + 0.261234, 0.969256, -0.166644, 1.036670, 0.240356, 0.991323, -0.154968, 1.032694, 0.219748, + 1.013013, -0.142425, 1.030061, 0.199103, 1.032845, -0.129456, 1.027254, 0.178936, 1.051887, + -0.115763, 1.025497, 0.159243, 1.069179, -0.101851, 1.023807, 0.139560, 1.084499, -0.087357, + 1.021441, 0.119607, 1.097921, -0.072796, 1.018780, 0.099501, 1.109281, -0.058037, 1.015566, + 0.079211, 1.118194, -0.043226, 1.011494, 0.058873, 1.125351, -0.028633, 1.007089, 0.038736, + 1.132002, -0.013996, 1.003014, 0.019063, 1.138951, 0.000132, 1.000036, -0.000007, 0.000200, + -0.000109, 1.296791, 0.544571, 0.000504, -0.000274, 1.296055, 0.544568, 0.002016, -0.001098, + 1.297239, 0.544568, 0.004535, -0.002470, 1.296600, 0.544568, 0.008062, -0.004390, 1.296368, + 0.544559, 0.012597, -0.006860, 1.296454, 0.544566, 0.018141, -0.009878, 1.296522, 0.544565, + 0.024693, -0.013444, 1.296536, 0.544560, 0.032256, -0.017559, 1.296638, 0.544557, 0.040824, + -0.022218, 1.296491, 0.544547, 0.050408, -0.027426, 1.296552, 0.544532, 0.060997, -0.033173, + 1.296283, 0.544518, 0.072600, -0.039463, 1.296113, 0.544496, 0.085220, -0.046292, 1.295894, + 0.544466, 0.098851, -0.053648, 1.295545, 0.544422, 0.113496, -0.061487, 1.295201, 0.544371, + 0.129112, -0.069467, 1.294754, 0.544273, 0.145765, -0.078092, 1.294209, 0.544160, 0.163431, + -0.087231, 1.293534, 0.544017, 0.182088, -0.096837, 1.292580, 0.543828, 0.201698, -0.106713, + 1.291586, 0.543585, 0.222231, -0.116699, 1.290325, 0.543238, 0.243653, -0.127208, 1.288888, + 0.542836, 0.265855, -0.137949, 1.287131, 0.542329, 0.288623, -0.148847, 1.284936, 0.541700, + 0.311830, -0.160204, 1.282109, 0.540997, 0.335728, -0.171324, 1.278036, 0.540045, 0.361403, + -0.181915, 1.273912, 0.538603, 0.387647, -0.192124, 1.268881, 0.536741, 0.414217, -0.201807, + 1.262363, 0.534432, 0.441090, -0.211093, 1.254755, 0.531623, 0.467823, -0.219678, 1.245456, + 0.528314, 0.494361, -0.227581, 1.234953, 0.524391, 0.521264, -0.235087, 1.224839, 0.519902, + 0.547881, -0.241508, 1.213175, 0.514574, 0.574965, -0.246315, 1.200505, 0.507837, 0.601847, + -0.250061, 1.187901, 0.500286, 0.628207, -0.252822, 1.174601, 0.491502, 0.654445, -0.254691, + 1.161944, 0.481726, 0.680175, -0.255318, 1.149305, 0.470727, 0.706168, -0.254257, 1.136708, + 0.458045, 0.731458, -0.252100, 1.124047, 0.444438, 0.756378, -0.249115, 1.112942, 0.429611, + 0.781311, -0.244899, 1.101800, 0.413501, 0.805755, -0.239225, 1.091662, 0.395889, 0.829867, + -0.232830, 1.082291, 0.377860, 0.853067, -0.225193, 1.072820, 0.358704, 0.877084, -0.216648, + 1.065415, 0.338413, 0.900123, -0.207390, 1.058403, 0.317596, 0.923370, -0.197095, 1.051412, + 0.296301, 0.946021, -0.186084, 1.045877, 0.274498, 0.967669, -0.174262, 1.040316, 0.252565, + 0.989761, -0.161814, 1.035489, 0.230312, 1.012163, -0.149076, 1.032540, 0.208746, 1.032547, + -0.135299, 1.029598, 0.187180, 1.052032, -0.121277, 1.027355, 0.166482, 1.069907, -0.106582, + 1.025622, 0.145939, 1.085563, -0.091589, 1.023244, 0.125362, 1.099447, -0.076263, 1.020661, + 0.104087, 1.110848, -0.060825, 1.017035, 0.083036, 1.119923, -0.045319, 1.012675, 0.061719, + 1.126805, -0.029852, 1.007668, 0.040583, 1.133282, -0.014846, 1.003335, 0.019969, 1.140128, + 0.000149, 1.000024, -0.000037, 0.000200, -0.000116, 1.334863, 0.577350, 0.000504, -0.000291, + 1.333350, 0.577348, 0.002015, -0.001164, 1.332853, 0.577347, 0.004535, -0.002618, 1.333295, + 0.577347, 0.008062, -0.004655, 1.333189, 0.577336, 0.012598, -0.007273, 1.333309, 0.577345, + 0.018141, -0.010472, 1.333274, 0.577342, 0.024694, -0.014253, 1.333231, 0.577339, 0.032254, + -0.018614, 1.333265, 0.577332, 0.040827, -0.023556, 1.333261, 0.577321, 0.050400, -0.029069, + 1.332893, 0.577309, 0.061000, -0.035166, 1.332998, 0.577288, 0.072608, -0.041833, 1.332901, + 0.577263, 0.085227, -0.049067, 1.332603, 0.577226, 0.098864, -0.056860, 1.332264, 0.577177, + 0.113507, -0.065114, 1.331825, 0.577109, 0.129146, -0.073610, 1.331311, 0.577005, 0.145808, + -0.082766, 1.330639, 0.576872, 0.163494, -0.092458, 1.329878, 0.576709, 0.182176, -0.102639, + 1.328889, 0.576501, 0.201804, -0.112983, 1.327710, 0.576207, 0.222394, -0.123650, 1.326256, + 0.575823, 0.243881, -0.134780, 1.324593, 0.575363, 0.266122, -0.145931, 1.322426, 0.574751, + 0.289043, -0.157500, 1.319837, 0.574033, 0.312330, -0.169208, 1.316301, 0.573181, 0.336120, + -0.181125, 1.312251, 0.572188, 0.361506, -0.192232, 1.307003, 0.570631, 0.387757, -0.202981, + 1.301068, 0.568558, 0.414365, -0.213160, 1.293695, 0.566027, 0.440986, -0.222617, 1.283958, + 0.562942, 0.467943, -0.231583, 1.274057, 0.559219, 0.494821, -0.239881, 1.262864, 0.554913, + 0.521486, -0.247336, 1.250633, 0.549953, 0.547884, -0.253921, 1.237448, 0.544251, 0.574582, + -0.259099, 1.223164, 0.537120, 0.601342, -0.262695, 1.208784, 0.528650, 0.627861, -0.265337, + 1.194424, 0.518978, 0.653745, -0.266872, 1.179361, 0.508525, 0.679348, -0.267403, 1.165010, + 0.496705, 0.705068, -0.266429, 1.151693, 0.482926, 0.730312, -0.263829, 1.137584, 0.468519, + 0.755576, -0.260491, 1.125328, 0.452213, 0.780371, -0.256166, 1.113759, 0.435127, 0.804632, + -0.250079, 1.101656, 0.416833, 0.828983, -0.243181, 1.091235, 0.397009, 0.852585, -0.235383, + 1.081475, 0.376647, 0.875237, -0.226031, 1.071806, 0.355506, 0.899152, -0.216343, 1.064453, + 0.333133, 0.922121, -0.205772, 1.057161, 0.311073, 0.944523, -0.193980, 1.050447, 0.287781, + 0.967313, -0.181920, 1.044531, 0.264350, 0.989042, -0.168822, 1.039312, 0.241128, 1.010881, + -0.155350, 1.035298, 0.218138, 1.032368, -0.141231, 1.032073, 0.195579, 1.052254, -0.126521, + 1.029395, 0.173399, 1.070207, -0.111243, 1.026938, 0.151866, 1.086528, -0.095617, 1.024957, + 0.130711, 1.100670, -0.079687, 1.021924, 0.108865, 1.112461, -0.063593, 1.018281, 0.086760, + 1.121588, -0.047313, 1.013747, 0.064575, 1.128522, -0.031385, 1.008433, 0.042499, 1.134759, + -0.015356, 1.003569, 0.020840, 1.141448, 0.000114, 0.999978, -0.000056, 0.000200, -0.000122, + 1.372763, 0.611086, 0.000503, -0.000308, 1.371456, 0.611084, 0.002016, -0.001232, 1.373440, + 0.611084, 0.004535, -0.002771, 1.373387, 0.611083, 0.008061, -0.004926, 1.372916, 0.611083, + 0.012601, -0.007700, 1.373956, 0.611084, 0.018142, -0.011084, 1.373419, 0.611078, 0.024695, + -0.015087, 1.373492, 0.611074, 0.032255, -0.019701, 1.373360, 0.611066, 0.040827, -0.024930, + 1.373327, 0.611055, 0.050408, -0.030769, 1.373222, 0.611037, 0.061004, -0.037217, 1.373079, + 0.611014, 0.072613, -0.044270, 1.372895, 0.610982, 0.085238, -0.051923, 1.372624, 0.610941, + 0.098878, -0.060161, 1.372252, 0.610883, 0.113522, -0.068785, 1.371785, 0.610798, 0.129176, + -0.077863, 1.371103, 0.610683, 0.145876, -0.087593, 1.370541, 0.610537, 0.163570, -0.097847, + 1.369496, 0.610349, 0.182283, -0.108592, 1.368477, 0.610109, 0.201930, -0.119420, 1.366980, + 0.609763, 0.222570, -0.130789, 1.365375, 0.609343, 0.244123, -0.142514, 1.363456, 0.608815, + 0.266437, -0.154232, 1.360916, 0.608114, 0.289467, -0.166370, 1.357909, 0.607291, 0.312861, + -0.178505, 1.353588, 0.606272, 0.336736, -0.190980, 1.349211, 0.605153, 0.361740, -0.202859, + 1.343319, 0.603548, 0.387878, -0.213997, 1.335908, 0.601268, 0.414357, -0.224584, 1.326676, + 0.598499, 0.441442, -0.234664, 1.317331, 0.595066, 0.468409, -0.243875, 1.305818, 0.590996, + 0.494999, -0.252121, 1.291863, 0.586293, 0.521730, -0.259714, 1.278212, 0.580840, 0.547894, + -0.266242, 1.262656, 0.574494, 0.573865, -0.271578, 1.246364, 0.567007, 0.601124, -0.275503, + 1.231274, 0.557771, 0.627606, -0.277954, 1.215252, 0.547255, 0.654004, -0.279404, 1.199977, + 0.535766, 0.679554, -0.279632, 1.183995, 0.522792, 0.704280, -0.278457, 1.167428, 0.508488, + 0.729830, -0.275706, 1.152760, 0.492425, 0.754376, -0.271640, 1.137942, 0.475285, 0.779209, + -0.266911, 1.125222, 0.456679, 0.803562, -0.260838, 1.112179, 0.437267, 0.827985, -0.253353, + 1.101439, 0.416227, 0.851737, -0.245027, 1.089890, 0.394728, 0.874850, -0.235719, 1.080018, + 0.372244, 0.897680, -0.225051, 1.070807, 0.348846, 0.921351, -0.214051, 1.063180, 0.324961, + 0.943818, -0.202039, 1.056148, 0.300836, 0.966368, -0.189134, 1.049277, 0.276333, 0.987426, + -0.175613, 1.042176, 0.251862, 1.010162, -0.161473, 1.038567, 0.227217, 1.031224, -0.146866, + 1.034102, 0.203582, 1.052317, -0.131644, 1.031600, 0.180629, 1.070879, -0.115909, 1.028913, + 0.158165, 1.087407, -0.099638, 1.026193, 0.135905, 1.102159, -0.083091, 1.023567, 0.113394, + 1.114006, -0.066178, 1.019567, 0.090325, 1.123374, -0.049430, 1.014856, 0.067302, 1.130310, + -0.032557, 1.009141, 0.044264, 1.136334, -0.016157, 1.003984, 0.021807, 1.142961, 0.000172, + 0.999951, -0.000077, 0.000200, -0.000129, 1.416584, 0.645866, 0.000504, -0.000326, 1.417762, + 0.645865, 0.002016, -0.001302, 1.417825, 0.645866, 0.004535, -0.002929, 1.417142, 0.645865, + 0.008062, -0.005207, 1.416968, 0.645864, 0.012598, -0.008136, 1.417109, 0.645862, 0.018141, + -0.011715, 1.417001, 0.645859, 0.024690, -0.015941, 1.416878, 0.645853, 0.032257, -0.020823, + 1.417134, 0.645843, 0.040827, -0.026347, 1.416983, 0.645829, 0.050411, -0.032518, 1.416949, + 0.645808, 0.061007, -0.039330, 1.416694, 0.645781, 0.072621, -0.046783, 1.416599, 0.645746, + 0.085249, -0.054865, 1.416241, 0.645695, 0.098897, -0.063563, 1.415832, 0.645630, 0.113546, + -0.072607, 1.415264, 0.645529, 0.129220, -0.082257, 1.414482, 0.645396, 0.145888, -0.092515, + 1.413626, 0.645268, 0.163659, -0.103393, 1.412710, 0.645018, 0.182385, -0.114684, 1.411418, + 0.644739, 0.202078, -0.126098, 1.409822, 0.644348, 0.222772, -0.138145, 1.407948, 0.643872, + 0.244370, -0.150405, 1.405678, 0.643255, 0.266787, -0.162798, 1.402763, 0.642463, 0.289844, + -0.175434, 1.398863, 0.641504, 0.313540, -0.188158, 1.394695, 0.640346, 0.337489, -0.201014, + 1.389376, 0.639042, 0.362008, -0.213719, 1.382439, 0.637412, 0.387990, -0.225248, 1.373281, + 0.634930, 0.414728, -0.236348, 1.363729, 0.631861, 0.441635, -0.246701, 1.352304, 0.628155, + 0.468588, -0.256167, 1.339162, 0.623625, 0.495337, -0.264662, 1.323811, 0.618458, 0.521886, + -0.272207, 1.307630, 0.612373, 0.548355, -0.278890, 1.291265, 0.605263, 0.574535, -0.284442, + 1.273752, 0.597048, 0.600870, -0.288389, 1.256171, 0.587401, 0.627715, -0.290816, 1.238447, + 0.576001, 0.653830, -0.291886, 1.221036, 0.563198, 0.679175, -0.291629, 1.202283, 0.549249, + 0.704539, -0.290489, 1.185866, 0.533881, 0.729126, -0.287529, 1.168822, 0.516966, 0.754297, + -0.283184, 1.152934, 0.498501, 0.778678, -0.277732, 1.137821, 0.478728, 0.802473, -0.271203, + 1.123387, 0.457814, 0.826596, -0.263494, 1.110573, 0.435865, 0.850835, -0.254572, 1.099099, + 0.412597, 0.874203, -0.244815, 1.088403, 0.388995, 0.897271, -0.233993, 1.078085, 0.364487, + 0.919667, -0.221934, 1.068543, 0.339344, 0.943001, -0.209714, 1.061081, 0.313770, 0.965688, + -0.196367, 1.054023, 0.287928, 0.987598, -0.182263, 1.047247, 0.262157, 1.009280, -0.167775, + 1.041376, 0.236855, 1.031762, -0.152530, 1.037647, 0.211847, 1.051965, -0.136809, 1.033396, + 0.187546, 1.071699, -0.120418, 1.031021, 0.164186, 1.088881, -0.103618, 1.028403, 0.141184, + 1.103482, -0.086271, 1.024987, 0.117665, 1.115646, -0.068973, 1.020884, 0.093896, 1.125258, + -0.051285, 1.015966, 0.069978, 1.132045, -0.033998, 1.009990, 0.046126, 1.138004, -0.016696, + 1.004270, 0.022635, 1.144463, 0.000089, 0.999987, -0.000016, 0.000200, -0.000136, 1.463614, + 0.681786, 0.000504, -0.000344, 1.465345, 0.681785, 0.002015, -0.001374, 1.464172, 0.681783, + 0.004535, -0.003092, 1.464846, 0.681784, 0.008062, -0.005496, 1.464783, 0.681784, 0.012598, + -0.008588, 1.464883, 0.681781, 0.018141, -0.012366, 1.464740, 0.681777, 0.024692, -0.016829, + 1.464665, 0.681770, 0.032258, -0.021980, 1.464720, 0.681760, 0.040829, -0.027811, 1.464625, + 0.681742, 0.050415, -0.034324, 1.464571, 0.681720, 0.061013, -0.041513, 1.464346, 0.681688, + 0.072628, -0.049375, 1.464131, 0.681644, 0.085264, -0.057903, 1.463847, 0.681588, 0.098918, + -0.067067, 1.463369, 0.681509, 0.113568, -0.076570, 1.462549, 0.681389, 0.129265, -0.086782, + 1.461703, 0.681239, 0.145997, -0.097637, 1.460840, 0.681047, 0.163751, -0.109101, 1.459737, + 0.680806, 0.182505, -0.120922, 1.458231, 0.680480, 0.202241, -0.133007, 1.456393, 0.680042, + 0.222987, -0.145693, 1.454258, 0.679503, 0.244638, -0.158488, 1.451543, 0.678792, 0.267132, + -0.171585, 1.448115, 0.677907, 0.290365, -0.184746, 1.443992, 0.676796, 0.314178, -0.198101, + 1.439271, 0.675498, 0.338289, -0.211370, 1.432830, 0.673922, 0.362543, -0.224489, 1.424163, + 0.672151, 0.388470, -0.236914, 1.415160, 0.669601, 0.415105, -0.248342, 1.403811, 0.666255, + 0.441925, -0.258957, 1.390149, 0.662166, 0.468668, -0.268556, 1.374104, 0.657229, 0.495720, + -0.277359, 1.358102, 0.651347, 0.522574, -0.285078, 1.340754, 0.644598, 0.548981, -0.291718, + 1.322033, 0.636820, 0.574946, -0.297087, 1.302148, 0.627812, 0.600744, -0.301079, 1.282130, + 0.617485, 0.627565, -0.303566, 1.263339, 0.605047, 0.653598, -0.304330, 1.242712, 0.591167, + 0.679239, -0.303820, 1.223212, 0.576025, 0.704043, -0.302064, 1.203763, 0.559649, 0.728796, + -0.299095, 1.185434, 0.541271, 0.753581, -0.294392, 1.167630, 0.521800, 0.778577, -0.288603, + 1.151930, 0.500628, 0.802550, -0.281604, 1.136072, 0.478434, 0.825803, -0.273472, 1.121673, + 0.455384, 0.849768, -0.264011, 1.108491, 0.430811, 0.873250, -0.253653, 1.096550, 0.405524, + 0.896725, -0.242642, 1.085905, 0.380038, 0.919158, -0.230191, 1.075091, 0.353482, 0.942236, + -0.217145, 1.066848, 0.326605, 0.965031, -0.203555, 1.059310, 0.299842, 0.987048, -0.188777, + 1.051749, 0.272859, 1.008718, -0.173613, 1.044999, 0.246040, 1.031097, -0.157972, 1.040066, + 0.219826, 1.052493, -0.141589, 1.035951, 0.194278, 1.071773, -0.124814, 1.032520, 0.169830, + 1.089646, -0.107321, 1.029803, 0.146135, 1.104932, -0.089726, 1.026612, 0.122127, 1.117687, + -0.071433, 1.022391, 0.097461, 1.127188, -0.053395, 1.017113, 0.072556, 1.134010, -0.035151, + 1.010934, 0.047749, 1.139746, -0.017427, 1.004633, 0.023530, 1.146205, 0.000151, 1.000020, + -0.000106, 0.000200, -0.000144, 1.517643, 0.718949, 0.000504, -0.000362, 1.516387, 0.718947, + 0.002016, -0.001449, 1.516742, 0.718946, 0.004536, -0.003261, 1.517196, 0.718946, 0.008063, + -0.005796, 1.516806, 0.718945, 0.012598, -0.009057, 1.516986, 0.718943, 0.018140, -0.013039, + 1.516603, 0.718937, 0.024694, -0.017747, 1.516739, 0.718929, 0.032260, -0.023178, 1.516994, + 0.718917, 0.040831, -0.029325, 1.516649, 0.718896, 0.050419, -0.036192, 1.516594, 0.718870, + 0.061019, -0.043770, 1.516327, 0.718833, 0.072638, -0.052056, 1.516054, 0.718782, 0.085274, + -0.061039, 1.515628, 0.718714, 0.098938, -0.070676, 1.515199, 0.718623, 0.113607, -0.080679, + 1.514222, 0.718483, 0.129329, -0.091485, 1.513354, 0.718316, 0.146077, -0.102931, 1.512301, + 0.718096, 0.163856, -0.114986, 1.510977, 0.717818, 0.182640, -0.127305, 1.509225, 0.717432, + 0.202432, -0.140147, 1.507152, 0.716939, 0.223229, -0.153468, 1.504780, 0.716331, 0.244943, + -0.166875, 1.501612, 0.715527, 0.267559, -0.180658, 1.497898, 0.714523, 0.290926, -0.194405, + 1.493208, 0.713266, 0.314863, -0.208302, 1.487388, 0.711758, 0.339053, -0.222020, 1.479677, + 0.709982, 0.363627, -0.235683, 1.470950, 0.707958, 0.388887, -0.248723, 1.459907, 0.705346, + 0.415474, -0.260563, 1.446579, 0.701644, 0.442065, -0.271352, 1.429962, 0.697134, 0.469418, + -0.281541, 1.414343, 0.691665, 0.496419, -0.290429, 1.395681, 0.685227, 0.523071, -0.298032, + 1.375347, 0.677815, 0.549641, -0.304679, 1.354816, 0.669063, 0.575489, -0.309902, 1.332505, + 0.659071, 0.601108, -0.313771, 1.309752, 0.647799, 0.627199, -0.316225, 1.288381, 0.634856, + 0.653243, -0.316679, 1.265785, 0.619627, 0.678960, -0.315816, 1.244333, 0.603244, 0.704055, + -0.313776, 1.223315, 0.585191, 0.728713, -0.310417, 1.203142, 0.565969, 0.753301, -0.305786, + 1.184323, 0.545347, 0.777890, -0.299262, 1.166070, 0.522753, 0.802354, -0.291830, 1.149599, + 0.499017, 0.826005, -0.283281, 1.133655, 0.474335, 0.848920, -0.273512, 1.118132, 0.449019, + 0.872765, -0.262525, 1.105606, 0.422329, 0.895950, -0.250769, 1.093539, 0.395057, 0.918816, + -0.238257, 1.082388, 0.367709, 0.941089, -0.224381, 1.072484, 0.339350, 0.964514, -0.210289, + 1.064054, 0.311239, 0.987128, -0.195488, 1.056645, 0.283272, 1.009064, -0.179491, 1.049549, + 0.255163, 1.030163, -0.163172, 1.042741, 0.227757, 1.052502, -0.146457, 1.038270, 0.200970, + 1.072971, -0.129054, 1.035014, 0.175767, 1.091223, -0.111285, 1.032231, 0.151118, 1.106518, + -0.092617, 1.028211, 0.126196, 1.119235, -0.074168, 1.023686, 0.100828, 1.129311, -0.055212, + 1.018311, 0.075240, 1.135983, -0.036571, 1.011485, 0.049558, 1.141648, -0.017954, 1.004952, + 0.024273, 1.147938, 0.000125, 1.000009, -0.000048, 0.000199, -0.000151, 1.566887, 0.757466, + 0.000504, -0.000382, 1.574111, 0.757466, 0.002016, -0.001527, 1.573735, 0.757466, 0.004535, + -0.003435, 1.573737, 0.757466, 0.008062, -0.006107, 1.573782, 0.757464, 0.012599, -0.009542, + 1.573796, 0.757460, 0.018142, -0.013739, 1.573710, 0.757455, 0.024694, -0.018697, 1.573562, + 0.757446, 0.032259, -0.024418, 1.573667, 0.757429, 0.040834, -0.030895, 1.573555, 0.757407, + 0.050422, -0.038127, 1.573383, 0.757376, 0.061025, -0.046108, 1.573086, 0.757332, 0.072650, + -0.054835, 1.572833, 0.757274, 0.085296, -0.064294, 1.572395, 0.757195, 0.098962, -0.074376, + 1.571729, 0.757087, 0.113649, -0.084955, 1.570571, 0.756925, 0.129389, -0.096334, 1.569582, + 0.756729, 0.146167, -0.108406, 1.568444, 0.756481, 0.163973, -0.121056, 1.566905, 0.756158, + 0.182798, -0.133970, 1.564939, 0.755715, 0.202650, -0.147522, 1.562666, 0.755167, 0.223502, + -0.161466, 1.559877, 0.754465, 0.245269, -0.175539, 1.556008, 0.753552, 0.268010, -0.189957, + 1.552013, 0.752420, 0.291474, -0.204361, 1.546509, 0.751008, 0.315527, -0.218714, 1.539575, + 0.749266, 0.339954, -0.233029, 1.530968, 0.747232, 0.364649, -0.247149, 1.520994, 0.744906, + 0.389520, -0.260672, 1.507748, 0.742123, 0.415717, -0.272873, 1.491777, 0.738187, 0.442862, + -0.284317, 1.475658, 0.733189, 0.469939, -0.294552, 1.456572, 0.727165, 0.496916, -0.303517, + 1.435237, 0.720043, 0.523480, -0.311061, 1.412192, 0.711640, 0.550092, -0.317596, 1.389033, + 0.702174, 0.576384, -0.322921, 1.365086, 0.691225, 0.602280, -0.326806, 1.341317, 0.678841, + 0.627676, -0.329057, 1.316518, 0.664815, 0.653458, -0.329372, 1.291877, 0.648548, 0.679227, + -0.328067, 1.268126, 0.630676, 0.704476, -0.325585, 1.244424, 0.611585, 0.729232, -0.321775, + 1.223010, 0.590803, 0.753405, -0.316713, 1.201297, 0.568653, 0.777274, -0.309858, 1.181071, + 0.544763, 0.801882, -0.301866, 1.162826, 0.519747, 0.826030, -0.292861, 1.145704, 0.493531, + 0.849359, -0.282794, 1.129629, 0.466900, 0.871837, -0.271197, 1.114155, 0.439230, 0.895896, + -0.258954, 1.102334, 0.410570, 0.918951, -0.245878, 1.090163, 0.381314, 0.941148, -0.231897, + 1.078738, 0.352268, 0.963464, -0.216743, 1.068862, 0.322688, 0.986628, -0.201486, 1.061077, + 0.293523, 1.009289, -0.185521, 1.053561, 0.264125, 1.030659, -0.168429, 1.046627, 0.235706, + 1.052382, -0.151210, 1.040953, 0.208022, 1.073476, -0.133289, 1.036534, 0.181245, 1.092237, + -0.114768, 1.033580, 0.155661, 1.108200, -0.095917, 1.029997, 0.130223, 1.121435, -0.076492, + 1.025374, 0.104098, 1.131382, -0.057204, 1.019485, 0.077776, 1.137994, -0.037747, 1.012188, + 0.051250, 1.143441, -0.018673, 1.005309, 0.025245, 1.149714, 0.000216, 1.000004, -0.000120, + 0.000200, -0.000159, 1.633988, 0.797469, 0.000504, -0.000402, 1.636076, 0.797469, 0.002016, + -0.001607, 1.635679, 0.797467, 0.004535, -0.003617, 1.636040, 0.797468, 0.008063, -0.006430, + 1.636159, 0.797467, 0.012599, -0.010046, 1.636128, 0.797462, 0.018141, -0.014464, 1.635730, + 0.797457, 0.024696, -0.019685, 1.635836, 0.797445, 0.032259, -0.025705, 1.635719, 0.797426, + 0.040835, -0.032523, 1.635610, 0.797401, 0.050425, -0.040135, 1.635460, 0.797363, 0.061033, + -0.048536, 1.635182, 0.797313, 0.072661, -0.057718, 1.634817, 0.797243, 0.085315, -0.067666, + 1.634314, 0.797150, 0.098985, -0.078179, 1.633350, 0.797016, 0.113699, -0.089383, 1.632253, + 0.796839, 0.129456, -0.101364, 1.631025, 0.796623, 0.146275, -0.114081, 1.629867, 0.796331, + 0.164108, -0.127318, 1.628043, 0.795956, 0.182983, -0.140901, 1.625813, 0.795458, 0.202891, + -0.155174, 1.623149, 0.794834, 0.223787, -0.169654, 1.619686, 0.794015, 0.245678, -0.184540, + 1.615694, 0.793013, 0.268495, -0.199543, 1.610812, 0.791727, 0.292093, -0.214639, 1.604629, + 0.790107, 0.316184, -0.229499, 1.596061, 0.788154, 0.340986, -0.244407, 1.587195, 0.785797, + 0.365808, -0.258907, 1.575031, 0.783093, 0.390528, -0.272746, 1.559448, 0.779970, 0.416510, + -0.285845, 1.543294, 0.775852, 0.443443, -0.297404, 1.523476, 0.770323, 0.470442, -0.307757, + 1.501515, 0.763721, 0.497499, -0.316846, 1.477841, 0.755889, 0.524316, -0.324561, 1.452427, + 0.746662, 0.551212, -0.331060, 1.427421, 0.736004, 0.577323, -0.335956, 1.400369, 0.723810, + 0.602976, -0.339501, 1.373093, 0.710184, 0.628357, -0.341577, 1.345853, 0.695017, 0.653642, + -0.342031, 1.319040, 0.677972, 0.679440, -0.340342, 1.292490, 0.658877, 0.704744, -0.337356, + 1.267182, 0.638085, 0.729692, -0.333042, 1.243280, 0.615615, 0.753920, -0.327504, 1.219751, + 0.592054, 0.777695, -0.320537, 1.197796, 0.566967, 0.801426, -0.311880, 1.176872, 0.540643, + 0.825649, -0.302211, 1.158160, 0.512906, 0.849282, -0.291665, 1.141257, 0.484587, 0.872341, + -0.280050, 1.125469, 0.455556, 0.895110, -0.266978, 1.110222, 0.425652, 0.918841, -0.253326, + 1.097419, 0.395015, 0.941209, -0.238899, 1.086101, 0.364948, 0.963142, -0.223523, 1.075023, + 0.334151, 0.985996, -0.207346, 1.065628, 0.303708, 1.008718, -0.190889, 1.057256, 0.273008, + 1.030554, -0.173517, 1.049720, 0.243221, 1.053085, -0.155645, 1.043837, 0.214426, 1.074267, + -0.137472, 1.039312, 0.187036, 1.093591, -0.118385, 1.035457, 0.160512, 1.109850, -0.098883, + 1.031630, 0.134384, 1.123516, -0.079050, 1.026762, 0.107424, 1.133578, -0.058977, 1.020640, + 0.080317, 1.140289, -0.039013, 1.013096, 0.052944, 1.145610, -0.019228, 1.005694, 0.025989, + 1.151704, 0.000105, 0.999981, -0.000019, 0.000200, -0.000168, 1.704841, 0.839096, 0.000504, + -0.000423, 1.704242, 0.839097, 0.002016, -0.001691, 1.703821, 0.839091, 0.004534, -0.003805, + 1.703804, 0.839094, 0.008063, -0.006765, 1.704224, 0.839092, 0.012598, -0.010570, 1.704013, + 0.839087, 0.018142, -0.015219, 1.703889, 0.839079, 0.024697, -0.020712, 1.704023, 0.839066, + 0.032261, -0.027046, 1.703836, 0.839045, 0.040837, -0.034218, 1.703608, 0.839014, 0.050429, + -0.042224, 1.703414, 0.838972, 0.061041, -0.051061, 1.703148, 0.838912, 0.072676, -0.060717, + 1.702744, 0.838831, 0.085340, -0.071175, 1.702223, 0.838724, 0.099023, -0.082182, 1.700984, + 0.838567, 0.113759, -0.094007, 1.699764, 0.838367, 0.129546, -0.106621, 1.698462, 0.838112, + 0.146382, -0.119956, 1.696938, 0.837782, 0.164260, -0.133760, 1.694868, 0.837346, 0.183188, + -0.148108, 1.692262, 0.836780, 0.203158, -0.163075, 1.689251, 0.836073, 0.224147, -0.178255, + 1.685408, 0.835148, 0.246147, -0.193900, 1.680946, 0.833992, 0.269072, -0.209553, 1.675277, + 0.832546, 0.292718, -0.225226, 1.667626, 0.830727, 0.317159, -0.240836, 1.658952, 0.828510, + 0.341979, -0.256103, 1.647624, 0.825843, 0.366844, -0.270887, 1.633014, 0.822760, 0.392043, + -0.285324, 1.617191, 0.819159, 0.417356, -0.298817, 1.597501, 0.814788, 0.444093, -0.310711, + 1.575184, 0.808751, 0.471379, -0.321410, 1.551590, 0.801294, 0.498267, -0.330421, 1.524134, + 0.792711, 0.525401, -0.338331, 1.496672, 0.782480, 0.551846, -0.344430, 1.467062, 0.770659, + 0.578009, -0.349047, 1.436943, 0.757348, 0.604054, -0.352490, 1.407611, 0.742541, 0.629387, + -0.354158, 1.377441, 0.726071, 0.654435, -0.354422, 1.347651, 0.707524, 0.679845, -0.352663, + 1.318769, 0.687067, 0.704892, -0.348994, 1.290600, 0.664637, 0.729763, -0.344105, 1.263997, + 0.640663, 0.754345, -0.338129, 1.239273, 0.615484, 0.778629, -0.330905, 1.215858, 0.589210, + 0.801939, -0.322113, 1.192318, 0.561550, 0.825723, -0.311673, 1.171380, 0.532175, 0.849387, + -0.300410, 1.152991, 0.502055, 0.872792, -0.288328, 1.136139, 0.471308, 0.895083, -0.275087, + 1.119534, 0.440427, 0.918335, -0.260700, 1.105542, 0.409260, 0.941577, -0.245717, 1.093070, + 0.377142, 0.963992, -0.230079, 1.081207, 0.345289, 0.986510, -0.213523, 1.071488, 0.313508, + 1.008806, -0.196157, 1.062011, 0.281962, 1.030724, -0.178467, 1.053240, 0.251177, 1.053782, + -0.160291, 1.047057, 0.220986, 1.075451, -0.141308, 1.041842, 0.192256, 1.094947, -0.121975, + 1.037704, 0.165023, 1.111783, -0.101744, 1.033300, 0.138228, 1.125525, -0.081476, 1.028234, + 0.110679, 1.135873, -0.060770, 1.021695, 0.082672, 1.142478, -0.040207, 1.013838, 0.054506, + 1.147889, -0.019908, 1.006166, 0.026938, 1.153852, 0.000204, 0.999983, -0.000123, 0.000199, + -0.000176, 1.771601, 0.882501, 0.000504, -0.000445, 1.779195, 0.882504, 0.002016, -0.001779, + 1.779635, 0.882498, 0.004536, -0.004003, 1.779586, 0.882499, 0.008062, -0.007115, 1.778613, + 0.882496, 0.012598, -0.011116, 1.778678, 0.882492, 0.018142, -0.016005, 1.778531, 0.882481, + 0.024696, -0.021782, 1.778556, 0.882466, 0.032262, -0.028444, 1.778507, 0.882442, 0.040842, + -0.035987, 1.778385, 0.882408, 0.050436, -0.044404, 1.778034, 0.882364, 0.061053, -0.053695, + 1.777761, 0.882287, 0.072692, -0.063842, 1.777256, 0.882190, 0.085364, -0.074821, 1.776518, + 0.882067, 0.099064, -0.086368, 1.775080, 0.881884, 0.113828, -0.098805, 1.773836, 0.881657, + 0.129649, -0.112090, 1.772370, 0.881361, 0.146518, -0.126067, 1.770594, 0.880982, 0.164440, + -0.140493, 1.768089, 0.880484, 0.183437, -0.155646, 1.765301, 0.879843, 0.203468, -0.171266, + 1.761698, 0.879035, 0.224562, -0.187231, 1.757518, 0.877982, 0.246665, -0.203540, 1.752318, + 0.876667, 0.269652, -0.219916, 1.745356, 0.875028, 0.293531, -0.236255, 1.737186, 0.872977, + 0.318048, -0.252410, 1.726709, 0.870448, 0.342963, -0.268192, 1.713109, 0.867400, 0.368336, + -0.283587, 1.698087, 0.863882, 0.393512, -0.298186, 1.678638, 0.859724, 0.418602, -0.311882, + 1.655604, 0.854835, 0.445080, -0.324500, 1.632250, 0.848353, 0.472289, -0.335295, 1.605069, + 0.840218, 0.499128, -0.344256, 1.573846, 0.830556, 0.525834, -0.351716, 1.541120, 0.819269, + 0.553177, -0.358241, 1.511385, 0.806222, 0.579480, -0.362640, 1.477866, 0.791647, 0.605205, + -0.365513, 1.444218, 0.775398, 0.630617, -0.366822, 1.410954, 0.757144, 0.655730, -0.366785, + 1.379010, 0.737323, 0.680529, -0.364904, 1.347280, 0.715601, 0.705800, -0.360990, 1.316416, + 0.691547, 0.730550, -0.355397, 1.286344, 0.666141, 0.754970, -0.348664, 1.258954, 0.638929, + 0.779042, -0.340774, 1.232965, 0.611015, 0.802839, -0.331767, 1.209775, 0.581877, 0.825793, + -0.321054, 1.185813, 0.551509, 0.849512, -0.309016, 1.165080, 0.519698, 0.873120, -0.296369, + 1.147091, 0.487506, 0.895942, -0.282704, 1.129658, 0.455320, 0.917996, -0.268007, 1.113463, + 0.422605, 0.941281, -0.252329, 1.100040, 0.389347, 0.964584, -0.236203, 1.087973, 0.356430, + 0.986371, -0.219209, 1.075983, 0.323089, 1.009522, -0.201588, 1.066940, 0.290806, 1.031976, + -0.183296, 1.057999, 0.258682, 1.053461, -0.164509, 1.049542, 0.227722, 1.076121, -0.145165, + 1.043718, 0.197439, 1.096597, -0.125199, 1.039607, 0.169578, 1.113908, -0.104921, 1.035528, + 0.142222, 1.127939, -0.083623, 1.029807, 0.113802, 1.138391, -0.062589, 1.023312, 0.085164, + 1.145110, -0.041376, 1.014806, 0.056186, 1.150141, -0.020433, 1.006501, 0.027654, 1.156069, + 0.000097, 0.999949, -0.000046, 0.000200, -0.000185, 1.858268, 0.927857, 0.000504, -0.000468, + 1.861583, 0.927859, 0.002016, -0.001870, 1.860659, 0.927855, 0.004535, -0.004208, 1.860963, + 0.927867, 0.008063, -0.007480, 1.860766, 0.927855, 0.012594, -0.011683, 1.859996, 0.927851, + 0.018142, -0.016828, 1.860739, 0.927839, 0.024698, -0.022901, 1.860763, 0.927818, 0.032263, + -0.029903, 1.860501, 0.927791, 0.040846, -0.037834, 1.860431, 0.927751, 0.050440, -0.046680, + 1.859827, 0.927690, 0.061066, -0.056446, 1.859624, 0.927610, 0.072713, -0.067109, 1.859039, + 0.927505, 0.085393, -0.078613, 1.858144, 0.927357, 0.099120, -0.090747, 1.856618, 0.927145, + 0.113910, -0.103850, 1.855221, 0.926884, 0.129755, -0.117777, 1.853470, 0.926546, 0.146669, + -0.132441, 1.851413, 0.926104, 0.164648, -0.147565, 1.848498, 0.925530, 0.183708, -0.163470, + 1.845281, 0.924802, 0.203832, -0.179763, 1.841273, 0.923871, 0.225029, -0.196564, 1.836481, + 0.922691, 0.247221, -0.213537, 1.830273, 0.921198, 0.270343, -0.230662, 1.822374, 0.919320, + 0.294399, -0.247740, 1.812975, 0.917008, 0.319040, -0.264448, 1.800693, 0.914141, 0.344269, + -0.280831, 1.785923, 0.910707, 0.369625, -0.296478, 1.767203, 0.906585, 0.394925, -0.311287, + 1.744434, 0.901918, 0.420583, -0.325578, 1.720938, 0.896240, 0.446200, -0.338384, 1.693005, + 0.889335, 0.472969, -0.349187, 1.660901, 0.880394, 0.500490, -0.358687, 1.628806, 0.869705, + 0.527312, -0.366042, 1.593001, 0.857145, 0.554207, -0.372045, 1.557046, 0.842943, 0.580620, + -0.376134, 1.520192, 0.826837, 0.606480, -0.378636, 1.482947, 0.808891, 0.631815, -0.379414, + 1.445954, 0.789119, 0.657021, -0.378972, 1.410833, 0.767564, 0.681686, -0.376728, 1.376575, + 0.744338, 0.706498, -0.372844, 1.342935, 0.718799, 0.731258, -0.366649, 1.311052, 0.691756, + 0.755937, -0.359354, 1.280478, 0.662683, 0.779259, -0.350487, 1.250585, 0.632892, 0.803295, + -0.340941, 1.225722, 0.602160, 0.826570, -0.330174, 1.201003, 0.570520, 0.849954, -0.317854, + 1.178488, 0.537651, 0.873696, -0.304426, 1.158302, 0.503799, 0.896695, -0.290120, 1.139886, + 0.469645, 0.919149, -0.275106, 1.122884, 0.435625, 0.942121, -0.259282, 1.107691, 0.401228, + 0.964627, -0.242123, 1.093661, 0.367086, 0.986614, -0.224575, 1.081580, 0.332885, 1.009623, + -0.206837, 1.071375, 0.299209, 1.033126, -0.188092, 1.062241, 0.266187, 1.054954, -0.168637, + 1.052912, 0.233733, 1.077660, -0.149166, 1.047047, 0.203192, 1.097983, -0.128587, 1.041607, + 0.173918, 1.115586, -0.107339, 1.036850, 0.145531, 1.130170, -0.086203, 1.031427, 0.116890, + 1.141018, -0.064171, 1.024395, 0.087388, 1.147681, -0.042530, 1.015719, 0.057733, 1.152560, + -0.021011, 1.006883, 0.028413, 1.158406, 0.000158, 0.999897, -0.000106, 0.000200, -0.000195, + 1.950982, 0.975366, 0.000504, -0.000491, 1.950207, 0.975365, 0.002015, -0.001966, 1.950675, + 0.975362, 0.004535, -0.004423, 1.951281, 0.975370, 0.008062, -0.007863, 1.951045, 0.975362, + 0.012597, -0.012285, 1.951199, 0.975356, 0.018145, -0.017692, 1.951528, 0.975340, 0.024699, + -0.024074, 1.951194, 0.975321, 0.032266, -0.031434, 1.950865, 0.975288, 0.040853, -0.039771, + 1.951038, 0.975244, 0.050452, -0.049067, 1.950336, 0.975173, 0.061077, -0.059324, 1.949805, + 0.975078, 0.072736, -0.070526, 1.949133, 0.974951, 0.085431, -0.082528, 1.947947, 0.974777, + 0.099182, -0.095345, 1.946337, 0.974540, 0.113999, -0.109118, 1.944725, 0.974241, 0.129888, + -0.123741, 1.942857, 0.973852, 0.146842, -0.139071, 1.940251, 0.973342, 0.164890, -0.154986, + 1.937086, 0.972684, 0.184025, -0.171661, 1.933404, 0.971856, 0.204245, -0.188672, 1.928770, + 0.970785, 0.225528, -0.206252, 1.923041, 0.969448, 0.247841, -0.223972, 1.915788, 0.967742, + 0.271157, -0.241827, 1.907008, 0.965607, 0.295297, -0.259562, 1.895854, 0.963007, 0.320121, + -0.276909, 1.881289, 0.959722, 0.345566, -0.293883, 1.864528, 0.955831, 0.371012, -0.309816, + 1.842062, 0.951127, 0.396834, -0.325157, 1.818068, 0.945725, 0.422277, -0.339357, 1.788874, + 0.939318, 0.447928, -0.352387, 1.758283, 0.931470, 0.474315, -0.363680, 1.723668, 0.921900, + 0.501560, -0.372963, 1.686081, 0.909996, 0.528391, -0.380159, 1.645816, 0.896244, 0.554754, + -0.385545, 1.603709, 0.880326, 0.581888, -0.389778, 1.565475, 0.862716, 0.607791, -0.391839, + 1.524196, 0.843146, 0.633511, -0.392331, 1.483921, 0.821554, 0.658621, -0.391193, 1.445013, + 0.798336, 0.683160, -0.388424, 1.406963, 0.773299, 0.707429, -0.384104, 1.370996, 0.746668, + 0.732212, -0.377945, 1.335879, 0.717502, 0.756871, -0.369856, 1.302489, 0.686954, 0.781065, + -0.360707, 1.271815, 0.655372, 0.804167, -0.350091, 1.242416, 0.622683, 0.827948, -0.338941, + 1.217208, 0.589185, 0.850901, -0.326427, 1.192354, 0.555005, 0.873589, -0.312199, 1.169639, + 0.519594, 0.897085, -0.297374, 1.150181, 0.484105, 0.920459, -0.281932, 1.132858, 0.448661, + 0.942637, -0.265625, 1.115401, 0.413051, 0.965341, -0.248332, 1.101078, 0.377329, 0.987530, + -0.229983, 1.087377, 0.342349, 1.010739, -0.211647, 1.076582, 0.307824, 1.033449, -0.192725, + 1.065900, 0.273368, 1.055618, -0.172726, 1.056958, 0.240238, 1.079345, -0.152640, 1.049620, + 0.208322, 1.100058, -0.131931, 1.044084, 0.178242, 1.118547, -0.110351, 1.039387, 0.149493, + 1.132748, -0.088128, 1.033049, 0.119673, 1.143419, -0.066069, 1.025521, 0.089728, 1.150316, + -0.043513, 1.016378, 0.059253, 1.155208, -0.021593, 1.007506, 0.029140, 1.160871, 0.000111, + 0.999916, -0.000035, 0.000201, -0.000206, 2.061000, 1.025243, 0.000504, -0.000516, 2.049647, + 1.025237, 0.002015, -0.002066, 2.050169, 1.025237, 0.004535, -0.004650, 2.051254, 1.025255, + 0.008063, -0.008266, 2.051302, 1.025236, 0.012600, -0.012915, 2.051508, 1.025226, 0.018144, + -0.018594, 2.050981, 1.025215, 0.024700, -0.025304, 2.050841, 1.025190, 0.032267, -0.033038, + 2.050537, 1.025152, 0.040852, -0.041795, 2.050660, 1.025090, 0.050460, -0.051570, 2.049921, + 1.025017, 0.061094, -0.062347, 2.049350, 1.024908, 0.072762, -0.074111, 2.048517, 1.024760, + 0.085475, -0.086661, 2.047009, 1.024555, 0.099249, -0.100160, 2.045261, 1.024278, 0.114106, + -0.114628, 2.043508, 1.023941, 0.130032, -0.130002, 2.041321, 1.023488, 0.147050, -0.145985, + 2.038299, 1.022905, 0.165164, -0.162762, 2.034658, 1.022151, 0.184380, -0.180172, 2.030312, + 1.021200, 0.204704, -0.198022, 2.024944, 1.019966, 0.226129, -0.216359, 2.018546, 1.018424, + 0.248582, -0.234923, 2.010153, 1.016519, 0.272011, -0.253474, 1.999659, 1.014072, 0.296259, + -0.271820, 1.986076, 1.011071, 0.321423, -0.289959, 1.970618, 1.007389, 0.346897, -0.307283, + 1.949667, 1.002955, 0.372750, -0.323817, 1.925287, 0.997633, 0.398603, -0.339241, 1.896006, + 0.991354, 0.424351, -0.353633, 1.863658, 0.983937, 0.449887, -0.366660, 1.827430, 0.975254, + 0.475715, -0.378213, 1.789521, 0.964753, 0.502204, -0.387133, 1.745632, 0.951594, 0.530179, + -0.394976, 1.705347, 0.936344, 0.556732, -0.400134, 1.658928, 0.918907, 0.583123, -0.403439, + 1.613077, 0.899504, 0.609477, -0.405285, 1.567884, 0.878172, 0.634927, -0.405055, 1.523507, + 0.854396, 0.660357, -0.403494, 1.481712, 0.829259, 0.684851, -0.400104, 1.439000, 0.802359, + 0.709654, -0.395536, 1.400956, 0.773534, 0.733472, -0.388996, 1.362156, 0.743230, 0.757502, + -0.380263, 1.325113, 0.711090, 0.782249, -0.370594, 1.292913, 0.677166, 0.806017, -0.359509, + 1.262088, 0.642527, 0.828687, -0.347126, 1.232059, 0.607589, 0.852372, -0.334474, 1.207160, + 0.571938, 0.874266, -0.320074, 1.181978, 0.535518, 0.898168, -0.304719, 1.161156, 0.498375, + 0.920456, -0.288246, 1.140667, 0.461179, 0.942832, -0.271311, 1.122780, 0.424533, 0.966458, + -0.254154, 1.108743, 0.387784, 0.988907, -0.235659, 1.093872, 0.351689, 1.011557, -0.216322, + 1.081959, 0.315743, 1.035099, -0.197007, 1.070885, 0.280402, 1.056354, -0.176878, 1.059968, + 0.246472, 1.079854, -0.156058, 1.051815, 0.212818, 1.101494, -0.134772, 1.045757, 0.182143, + 1.120587, -0.113071, 1.041169, 0.152867, 1.135399, -0.090411, 1.034844, 0.122796, 1.146612, + -0.067477, 1.026974, 0.091888, 1.153168, -0.044849, 1.017303, 0.060779, 1.157912, -0.021998, + 1.007735, 0.029919, 1.163607, 0.000121, 0.999959, 0.000003, 0.000200, -0.000216, 2.163956, + 1.077737, 0.000504, -0.000543, 2.161128, 1.077732, 0.002016, -0.002173, 2.162732, 1.077729, + 0.004535, -0.004887, 2.161402, 1.077749, 0.008066, -0.008692, 2.163252, 1.077732, 0.012599, + -0.013576, 2.161300, 1.077727, 0.018145, -0.019546, 2.161151, 1.077702, 0.024702, -0.026599, + 2.161223, 1.077675, 0.032272, -0.034729, 2.160949, 1.077632, 0.040862, -0.043936, 2.160967, + 1.077575, 0.050470, -0.054203, 2.160035, 1.077473, 0.061113, -0.065528, 2.159490, 1.077348, + 0.072794, -0.077882, 2.158517, 1.077178, 0.085528, -0.091030, 2.156605, 1.076937, 0.099337, + -0.105251, 2.154828, 1.076631, 0.114228, -0.120456, 2.152812, 1.076229, 0.130202, -0.136573, + 2.150298, 1.075713, 0.147284, -0.153306, 2.146752, 1.075031, 0.165480, -0.170931, 2.142744, + 1.074173, 0.184793, -0.189083, 2.137475, 1.073063, 0.205224, -0.207840, 2.131320, 1.071683, + 0.226743, -0.226939, 2.123154, 1.069914, 0.249401, -0.246344, 2.114086, 1.067718, 0.272955, + -0.265640, 2.101599, 1.064924, 0.297494, -0.284846, 2.086612, 1.061512, 0.322731, -0.303452, + 2.067356, 1.057359, 0.348451, -0.321330, 2.043711, 1.052294, 0.374451, -0.338201, 2.015033, + 1.046153, 0.400454, -0.353816, 1.981139, 1.039003, 0.426434, -0.368216, 1.944128, 1.030498, + 0.452088, -0.381251, 1.903094, 1.020454, 0.477901, -0.392833, 1.860402, 1.008793, 0.504173, + -0.402408, 1.814402, 0.994791, 0.531520, -0.409545, 1.766273, 0.977733, 0.558049, -0.414351, + 1.714119, 0.958625, 0.584778, -0.417437, 1.664612, 0.937189, 0.610808, -0.418519, 1.613793, + 0.913543, 0.636915, -0.418094, 1.565942, 0.888137, 0.662204, -0.415742, 1.518783, 0.860728, + 0.686848, -0.411746, 1.473306, 0.831793, 0.710992, -0.406153, 1.430153, 0.800862, 0.735382, + -0.399519, 1.389824, 0.768768, 0.759079, -0.390927, 1.350744, 0.734825, 0.782912, -0.380111, + 1.313559, 0.699450, 0.806746, -0.368383, 1.280028, 0.663191, 0.830269, -0.355606, 1.249814, + 0.625927, 0.853305, -0.341988, 1.221138, 0.588644, 0.876326, -0.327545, 1.195837, 0.550849, + 0.898322, -0.311779, 1.171844, 0.512694, 0.921811, -0.294944, 1.150671, 0.474225, 0.944563, + -0.277333, 1.132224, 0.435772, 0.967089, -0.259340, 1.115422, 0.398001, 0.989754, -0.240836, + 1.100405, 0.360802, 1.012470, -0.221293, 1.086533, 0.323566, 1.036426, -0.201191, 1.075496, + 0.287387, 1.058709, -0.180590, 1.064233, 0.252184, 1.081593, -0.159810, 1.055296, 0.218441, + 1.103146, -0.137772, 1.047978, 0.186223, 1.122814, -0.115347, 1.042693, 0.156019, 1.137790, + -0.092582, 1.036049, 0.125579, 1.149184, -0.069152, 1.027944, 0.093986, 1.156062, -0.045661, + 1.018039, 0.062122, 1.160733, -0.022719, 1.008072, 0.030650, 1.166487, 0.000231, 1.000063, + -0.000120, 0.000201, -0.000228, 2.308308, 1.133128, 0.000504, -0.000571, 2.283756, 1.133123, + 0.002016, -0.002284, 2.283756, 1.133123, 0.004535, -0.005138, 2.283310, 1.133144, 0.008048, + -0.009119, 2.266192, 1.133138, 0.012600, -0.014274, 2.284377, 1.133110, 0.018147, -0.020553, + 2.284204, 1.133093, 0.024702, -0.027964, 2.283517, 1.133060, 0.032272, -0.036510, 2.282997, + 1.133007, 0.040866, -0.046188, 2.282986, 1.132930, 0.050481, -0.056979, 2.282260, 1.132824, + 0.061133, -0.068881, 2.281533, 1.132678, 0.072830, -0.081850, 2.280504, 1.132481, 0.085592, + -0.095657, 2.278304, 1.132202, 0.099431, -0.110594, 2.276269, 1.131845, 0.114360, -0.126590, + 2.273890, 1.131383, 0.130388, -0.143454, 2.270761, 1.130784, 0.147547, -0.161029, 2.266794, + 1.130003, 0.165836, -0.179523, 2.262332, 1.129016, 0.185269, -0.198527, 2.256326, 1.127738, + 0.205822, -0.218138, 2.249031, 1.126156, 0.227527, -0.238141, 2.239993, 1.124132, 0.250325, + -0.258302, 2.228878, 1.121594, 0.274070, -0.278329, 2.214204, 1.118449, 0.298793, -0.298310, + 2.196654, 1.114528, 0.324131, -0.317462, 2.173394, 1.109783, 0.350101, -0.335853, 2.146395, + 1.103901, 0.376293, -0.353064, 2.112341, 1.096954, 0.402547, -0.368950, 2.073700, 1.088642, + 0.428791, -0.383462, 2.031152, 1.078946, 0.454976, -0.396635, 1.986661, 1.067536, 0.480566, + -0.407873, 1.937038, 1.054403, 0.506154, -0.417303, 1.885155, 1.038894, 0.532862, -0.424194, + 1.830369, 1.020535, 0.560354, -0.429344, 1.776976, 0.999295, 0.587114, -0.431949, 1.721214, + 0.975990, 0.613345, -0.432547, 1.665739, 0.950239, 0.639335, -0.431338, 1.612200, 0.922467, + 0.664996, -0.428473, 1.561035, 0.892593, 0.688947, -0.423355, 1.508240, 0.861325, 0.713403, + -0.417235, 1.461776, 0.828289, 0.737649, -0.409848, 1.418888, 0.793863, 0.761275, -0.400901, + 1.376807, 0.758074, 0.784778, -0.390174, 1.337204, 0.721974, 0.808762, -0.377683, 1.301527, + 0.682718, 0.831993, -0.364037, 1.267144, 0.644001, 0.854696, -0.349494, 1.236023, 0.605478, + 0.877933, -0.334499, 1.209284, 0.565588, 0.900180, -0.318435, 1.183967, 0.526138, 0.923039, + -0.301669, 1.161513, 0.486524, 0.945895, -0.283298, 1.140838, 0.446747, 0.968069, -0.264438, + 1.122475, 0.408041, 0.991179, -0.245463, 1.106968, 0.369477, 1.012926, -0.225680, 1.091435, + 0.331626, 1.036995, -0.205401, 1.079561, 0.294288, 1.060909, -0.184310, 1.068215, 0.257696, + 1.083531, -0.162846, 1.058133, 0.223343, 1.105644, -0.141040, 1.050851, 0.190541, 1.125691, + -0.117965, 1.045001, 0.159310, 1.141297, -0.094377, 1.038028, 0.128238, 1.152672, -0.070831, + 1.029694, 0.096282, 1.159333, -0.046853, 1.019136, 0.063720, 1.163819, -0.022991, 1.008518, + 0.031234, 1.169564, 0.000125, 1.000069, -0.000024, 0.000202, -0.000241, 2.458341, 1.191742, + 0.000504, -0.000600, 2.418738, 1.191740, 0.002015, -0.002401, 2.418821, 1.191730, 0.004535, + -0.005405, 2.421986, 1.191756, 0.008071, -0.009618, 2.424988, 1.191753, 0.012600, -0.015012, + 2.420242, 1.191727, 0.018145, -0.021612, 2.419937, 1.191703, 0.024704, -0.029410, 2.419746, + 1.191662, 0.032278, -0.038398, 2.419409, 1.191604, 0.040874, -0.048574, 2.418995, 1.191515, + 0.050496, -0.059920, 2.418190, 1.191389, 0.061160, -0.072432, 2.417487, 1.191221, 0.072871, + -0.086009, 2.415853, 1.190984, 0.085664, -0.100559, 2.413669, 1.190664, 0.099543, -0.116283, + 2.411423, 1.190256, 0.114520, -0.133071, 2.408711, 1.189719, 0.130616, -0.150670, 2.404900, + 1.189019, 0.147856, -0.169197, 2.400512, 1.188125, 0.166235, -0.188545, 2.394939, 1.186972, + 0.185804, -0.208480, 2.388232, 1.185515, 0.206488, -0.228883, 2.379190, 1.183673, 0.228383, + -0.249897, 2.369208, 1.181382, 0.251305, -0.270851, 2.355459, 1.178478, 0.275349, -0.291780, + 2.339142, 1.174857, 0.300106, -0.312257, 2.316655, 1.170411, 0.325849, -0.332225, 2.291540, + 1.164883, 0.351782, -0.350862, 2.257242, 1.158196, 0.378248, -0.368431, 2.218671, 1.150173, + 0.404674, -0.384428, 2.173680, 1.140703, 0.431385, -0.399230, 2.127083, 1.129555, 0.457407, + -0.411875, 2.073236, 1.116436, 0.483275, -0.423013, 2.018223, 1.101373, 0.509278, -0.432624, + 1.962674, 1.084257, 0.534751, -0.439261, 1.900814, 1.064592, 0.561895, -0.443801, 1.839558, + 1.040881, 0.588677, -0.445872, 1.777763, 1.015208, 0.614900, -0.445896, 1.716550, 0.987252, + 0.641051, -0.444148, 1.657984, 0.957271, 0.666409, -0.440299, 1.600832, 0.924841, 0.691872, + -0.435318, 1.548237, 0.891185, 0.716638, -0.428631, 1.497572, 0.855929, 0.739864, -0.419872, + 1.447043, 0.819676, 0.763707, -0.410456, 1.403648, 0.781455, 0.786744, -0.399390, 1.360844, + 0.742965, 0.809585, -0.386381, 1.320529, 0.703260, 0.834164, -0.372622, 1.286467, 0.662385, + 0.856713, -0.357177, 1.252306, 0.621379, 0.879820, -0.341458, 1.223070, 0.580238, 0.902721, + -0.325024, 1.197115, 0.539028, 0.924650, -0.307543, 1.172314, 0.498592, 0.947613, -0.289557, + 1.151171, 0.457980, 0.969590, -0.269799, 1.129986, 0.417696, 0.992961, -0.250111, 1.113321, + 0.377529, 1.014582, -0.229761, 1.097149, 0.339096, 1.038069, -0.209375, 1.083913, 0.301119, + 1.061661, -0.188038, 1.071241, 0.263506, 1.085069, -0.165874, 1.060508, 0.227921, 1.107744, + -0.143437, 1.052930, 0.194062, 1.127982, -0.120574, 1.046396, 0.162506, 1.144541, -0.096569, + 1.039880, 0.130788, 1.155876, -0.072039, 1.030946, 0.098057, 1.162719, -0.047888, 1.020124, + 0.064956, 1.167089, -0.023740, 1.008953, 0.031966, 1.172775, 0.000277, 1.000067, -0.000111, + 0.000200, -0.000251, 2.573709, 1.253951, 0.000504, -0.000632, 2.572401, 1.253940, 0.002015, + -0.002527, 2.571267, 1.253927, 0.004535, -0.005687, 2.572481, 1.253948, 0.008062, -0.010108, + 2.571851, 1.253941, 0.012588, -0.015780, 2.568431, 1.253934, 0.018139, -0.022731, 2.569765, + 1.253893, 0.024709, -0.030948, 2.572115, 1.253853, 0.032283, -0.040401, 2.571456, 1.253785, + 0.040883, -0.051105, 2.571041, 1.253683, 0.050514, -0.063041, 2.570153, 1.253538, 0.061188, + -0.076195, 2.569085, 1.253336, 0.072926, -0.090402, 2.567184, 1.253065, 0.085746, -0.105745, + 2.564731, 1.252697, 0.099661, -0.122296, 2.561995, 1.252218, 0.114699, -0.139912, 2.559019, + 1.251590, 0.130882, -0.158362, 2.555017, 1.250766, 0.148202, -0.177856, 2.549419, 1.249744, + 0.166706, -0.198049, 2.542908, 1.248423, 0.186404, -0.219014, 2.535205, 1.246741, 0.207272, + -0.240376, 2.524893, 1.244596, 0.229345, -0.262230, 2.512804, 1.241917, 0.252494, -0.284134, + 2.496923, 1.238610, 0.276690, -0.305828, 2.476583, 1.234474, 0.301798, -0.327107, 2.451548, + 1.229292, 0.327423, -0.347300, 2.418630, 1.222997, 0.353848, -0.366699, 2.381002, 1.215366, + 0.380342, -0.384421, 2.334413, 1.206199, 0.407390, -0.400855, 2.285660, 1.195374, 0.433913, + -0.415241, 2.228604, 1.182290, 0.460837, -0.428275, 2.171532, 1.167385, 0.486381, -0.438573, + 2.105639, 1.150401, 0.511959, -0.447348, 2.040835, 1.130990, 0.537586, -0.454152, 1.974797, + 1.109302, 0.564035, -0.458684, 1.907895, 1.084131, 0.590690, -0.460058, 1.839482, 1.055803, + 0.617250, -0.459662, 1.772332, 1.025103, 0.643406, -0.457260, 1.707313, 0.992502, 0.668794, + -0.452666, 1.644722, 0.957657, 0.693930, -0.446641, 1.586832, 0.921340, 0.718708, -0.439121, + 1.531197, 0.883841, 0.743469, -0.430429, 1.480765, 0.844931, 0.766080, -0.419622, 1.430338, + 0.804786, 0.789801, -0.408368, 1.386295, 0.764206, 0.812718, -0.395392, 1.343758, 0.722565, + 0.835453, -0.380699, 1.304655, 0.680585, 0.858801, -0.364834, 1.269287, 0.637235, 0.881537, + -0.348092, 1.237493, 0.594579, 0.904656, -0.331087, 1.208862, 0.552313, 0.926357, -0.312966, + 1.182365, 0.510080, 0.949001, -0.294684, 1.159452, 0.468677, 0.971598, -0.275361, 1.138706, + 0.426723, 0.994905, -0.254947, 1.120552, 0.385875, 1.017981, -0.234109, 1.104215, 0.345751, + 1.040840, -0.213040, 1.089276, 0.306762, 1.063893, -0.191616, 1.075845, 0.269066, 1.086907, + -0.169272, 1.063788, 0.232171, 1.109937, -0.146076, 1.054977, 0.197826, 1.130808, -0.122544, + 1.048572, 0.165272, 1.146831, -0.098492, 1.040742, 0.133280, 1.158955, -0.073710, 1.031818, + 0.100262, 1.166161, -0.048610, 1.020747, 0.066165, 1.170491, -0.024209, 1.009380, 0.032741, + 1.176111, 0.000010, 1.000042, 0.000056, 0.000202, -0.000267, 2.786357, 1.320169, 0.000504, + -0.000665, 2.741889, 1.320168, 0.002015, -0.002660, 2.740000, 1.320143, 0.004536, -0.005987, + 2.744276, 1.320161, 0.008063, -0.010644, 2.743432, 1.320162, 0.012600, -0.016628, 2.741741, + 1.320148, 0.018144, -0.023937, 2.741314, 1.320127, 0.024708, -0.032577, 2.741916, 1.320061, + 0.032290, -0.042536, 2.742132, 1.319976, 0.040894, -0.053799, 2.741199, 1.319861, 0.050533, + -0.066361, 2.740258, 1.319691, 0.061223, -0.080202, 2.739045, 1.319458, 0.072985, -0.095109, + 2.736519, 1.319138, 0.085841, -0.111296, 2.733903, 1.318715, 0.099808, -0.128685, 2.730944, + 1.318156, 0.114903, -0.147202, 2.727293, 1.317424, 0.131164, -0.166575, 2.722169, 1.316485, + 0.148599, -0.187019, 2.716148, 1.315274, 0.167245, -0.208240, 2.708701, 1.313733, 0.187078, + -0.230151, 2.698998, 1.311792, 0.208153, -0.252538, 2.687341, 1.309343, 0.230418, -0.275295, + 2.672621, 1.306247, 0.253802, -0.298066, 2.653619, 1.302374, 0.278261, -0.320673, 2.629943, + 1.297573, 0.303527, -0.342528, 2.599228, 1.291625, 0.329571, -0.363531, 2.562226, 1.284374, + 0.355939, -0.382963, 2.515491, 1.275478, 0.382987, -0.401306, 2.464858, 1.264866, 0.409917, + -0.417455, 2.404877, 1.252184, 0.437015, -0.432067, 2.341408, 1.237415, 0.463474, -0.444204, + 2.271837, 1.220687, 0.489835, -0.454631, 2.200593, 1.200973, 0.516054, -0.463338, 2.129733, + 1.179346, 0.541397, -0.469425, 2.055635, 1.155039, 0.566798, -0.473526, 1.980812, 1.127866, + 0.593114, -0.474632, 1.904723, 1.097304, 0.619945, -0.473597, 1.832456, 1.063603, 0.646325, + -0.470656, 1.761501, 1.027971, 0.672320, -0.465675, 1.694248, 0.990692, 0.697163, -0.458527, + 1.629227, 0.951582, 0.721472, -0.449904, 1.568132, 0.911197, 0.745855, -0.440140, 1.512084, + 0.869745, 0.770089, -0.429338, 1.460694, 0.827648, 0.792546, -0.416701, 1.410739, 0.784728, + 0.815161, -0.403151, 1.365438, 0.741884, 0.837994, -0.388714, 1.324811, 0.697800, 0.861220, + -0.372573, 1.287723, 0.653341, 0.883737, -0.355024, 1.252491, 0.609455, 0.906784, -0.337092, + 1.221844, 0.565275, 0.928493, -0.318370, 1.192881, 0.521558, 0.951495, -0.299605, 1.169131, + 0.478149, 0.973586, -0.280067, 1.146316, 0.436325, 0.996400, -0.259823, 1.127860, 0.394409, + 1.019780, -0.238313, 1.110521, 0.353045, 1.042775, -0.216506, 1.093915, 0.312803, 1.066822, + -0.194695, 1.080326, 0.274100, 1.089869, -0.172290, 1.067722, 0.236657, 1.113606, -0.149264, + 1.058471, 0.201603, 1.134229, -0.124814, 1.050701, 0.168398, 1.150922, -0.100070, 1.043051, + 0.135616, 1.163224, -0.075155, 1.033742, 0.102144, 1.169965, -0.049933, 1.021818, 0.067532, + 1.174200, -0.024461, 1.009916, 0.033215, 1.179766, 0.000188, 1.000045, -0.000014, 0.000202, + -0.000281, 2.964186, 1.390880, 0.000505, -0.000702, 2.945157, 1.390903, 0.002015, -0.002802, + 2.931184, 1.390863, 0.004535, -0.006307, 2.935673, 1.390900, 0.008063, -0.011213, 2.934274, + 1.390890, 0.012598, -0.017516, 2.932216, 1.390876, 0.018147, -0.025221, 2.933324, 1.390832, + 0.024711, -0.034322, 2.933945, 1.390769, 0.032295, -0.044810, 2.933496, 1.390674, 0.040904, + -0.056673, 2.932487, 1.390538, 0.050555, -0.069906, 2.931571, 1.390342, 0.061259, -0.084468, + 2.929914, 1.390064, 0.073053, -0.100152, 2.927039, 1.389695, 0.085948, -0.117202, 2.924241, + 1.389201, 0.099968, -0.135531, 2.920760, 1.388548, 0.115135, -0.154906, 2.915998, 1.387692, + 0.131496, -0.175352, 2.910285, 1.386611, 0.149049, -0.196783, 2.903174, 1.385190, 0.167848, + -0.219066, 2.894584, 1.383407, 0.187879, -0.241983, 2.883171, 1.381148, 0.209143, -0.265398, + 2.869102, 1.378261, 0.231689, -0.289254, 2.852238, 1.374690, 0.255223, -0.312776, 2.828264, + 1.370166, 0.279952, -0.336260, 2.800175, 1.364591, 0.305572, -0.358865, 2.764282, 1.357758, + 0.331650, -0.380223, 2.717845, 1.349413, 0.358491, -0.400252, 2.665326, 1.339084, 0.385445, + -0.418422, 2.602293, 1.326773, 0.412947, -0.434993, 2.536973, 1.312141, 0.439681, -0.448757, + 2.459463, 1.295205, 0.467272, -0.461427, 2.386250, 1.275573, 0.493568, -0.471102, 2.303225, + 1.253400, 0.519743, -0.478930, 2.221945, 1.228890, 0.544882, -0.484098, 2.136425, 1.201730, + 0.570690, -0.488125, 2.057093, 1.172022, 0.595905, -0.489185, 1.975334, 1.139312, 0.622747, + -0.487535, 1.895055, 1.103038, 0.648695, -0.483482, 1.815995, 1.064364, 0.675159, -0.478096, + 1.744272, 1.024098, 0.700714, -0.470492, 1.675257, 0.982186, 0.725641, -0.461398, 1.609135, + 0.939137, 0.748552, -0.449825, 1.545091, 0.894791, 0.772808, -0.438185, 1.489394, 0.850373, + 0.795928, -0.425073, 1.437026, 0.805287, 0.818900, -0.411028, 1.389654, 0.760003, 0.841633, + -0.396047, 1.345873, 0.714914, 0.863213, -0.379637, 1.305185, 0.669271, 0.886662, -0.362227, + 1.269147, 0.622935, 0.908504, -0.343068, 1.234714, 0.577757, 0.931425, -0.323982, 1.204997, + 0.532922, 0.953835, -0.304347, 1.178871, 0.488154, 0.975813, -0.284219, 1.155019, 0.444885, + 0.997662, -0.263544, 1.133941, 0.402224, 1.021167, -0.242611, 1.116100, 0.360530, 1.044038, + -0.220065, 1.098348, 0.318968, 1.068837, -0.197580, 1.084605, 0.279107, 1.092548, -0.174779, + 1.071217, 0.241111, 1.116157, -0.151596, 1.060486, 0.204913, 1.137486, -0.127478, 1.052751, + 0.171410, 1.154694, -0.101915, 1.044807, 0.137999, 1.166867, -0.076246, 1.034824, 0.103807, + 1.173715, -0.050661, 1.022501, 0.068802, 1.178236, -0.025355, 1.010324, 0.034155, 1.183545, + 0.000205, 1.000059, -0.000110, 0.000201, -0.000294, 3.161080, 1.466721, 0.000505, -0.000740, + 3.155526, 1.466737, 0.002016, -0.002957, 3.152852, 1.466688, 0.004537, -0.006655, 3.150654, + 1.466667, 0.008066, -0.011828, 3.153109, 1.466694, 0.012604, -0.018479, 3.152143, 1.466721, + 0.018150, -0.026598, 3.151025, 1.466636, 0.024714, -0.036191, 3.150300, 1.466562, 0.032301, + -0.047249, 3.149861, 1.466450, 0.040924, -0.059766, 3.149548, 1.466289, 0.050579, -0.073703, + 3.147516, 1.466055, 0.061306, -0.089022, 3.145680, 1.465738, 0.073135, -0.105563, 3.142428, + 1.465301, 0.086075, -0.123544, 3.139113, 1.464715, 0.100153, -0.142853, 3.135064, 1.463956, + 0.115411, -0.163183, 3.129509, 1.462962, 0.131876, -0.184760, 3.122959, 1.461670, 0.149570, + -0.207172, 3.114153, 1.460045, 0.168523, -0.230578, 3.103626, 1.457945, 0.188784, -0.254658, + 3.090818, 1.455279, 0.210264, -0.279114, 3.073352, 1.451998, 0.233030, -0.303930, 3.052592, + 1.447780, 0.256959, -0.328517, 3.025187, 1.442568, 0.281901, -0.352755, 2.990341, 1.436026, + 0.307728, -0.375894, 2.946820, 1.427979, 0.334197, -0.397924, 2.892845, 1.418249, 0.360966, + -0.417914, 2.827937, 1.406370, 0.388478, -0.436526, 2.758006, 1.392134, 0.415567, -0.452366, + 2.674696, 1.375244, 0.443518, -0.466917, 2.595136, 1.355660, 0.470631, -0.478417, 2.504173, + 1.333123, 0.497419, -0.487825, 2.413227, 1.308181, 0.523961, -0.495064, 2.321239, 1.280227, + 0.549708, -0.499844, 2.228911, 1.249894, 0.575296, -0.502844, 2.138834, 1.217130, 0.600168, + -0.503368, 2.049030, 1.181412, 0.625874, -0.501622, 1.962267, 1.142648, 0.652164, -0.496936, + 1.876900, 1.101268, 0.678029, -0.490319, 1.796344, 1.057782, 0.703248, -0.481575, 1.718925, + 1.012884, 0.728520, -0.471822, 1.648358, 0.966487, 0.752577, -0.460134, 1.581989, 0.919880, + 0.776163, -0.447164, 1.520109, 0.873087, 0.800016, -0.433601, 1.465081, 0.825803, 0.822176, + -0.418388, 1.412564, 0.778249, 0.844873, -0.402704, 1.366184, 0.730849, 0.865955, -0.385633, + 1.321865, 0.684037, 0.888173, -0.368255, 1.283464, 0.637192, 0.910994, -0.349332, 1.249215, + 0.590131, 0.934270, -0.329612, 1.218366, 0.543213, 0.956653, -0.309228, 1.189808, 0.497752, + 0.978476, -0.288310, 1.163674, 0.452837, 1.000755, -0.267243, 1.141389, 0.409481, 1.023827, + -0.246015, 1.122012, 0.367354, 1.045572, -0.223777, 1.103303, 0.325171, 1.070445, -0.200837, + 1.088010, 0.284442, 1.094268, -0.177211, 1.073650, 0.245138, 1.118639, -0.153531, 1.063051, + 0.208289, 1.139786, -0.129074, 1.053921, 0.173607, 1.157848, -0.104051, 1.045968, 0.140467, + 1.170697, -0.077694, 1.035782, 0.105594, 1.177874, -0.051393, 1.023483, 0.069898, 1.182242, + -0.025392, 1.010620, 0.034532, 1.187612, -0.000032, 1.000062, -0.000035, 0.000202, -0.000313, + 3.450327, 1.548291, 0.000504, -0.000780, 3.396162, 1.548289, 0.002015, -0.003120, 3.395621, + 1.548260, 0.004533, -0.007019, 3.394299, 1.548217, 0.008066, -0.012486, 3.398803, 1.548274, + 0.012600, -0.019500, 3.396363, 1.548245, 0.018151, -0.028076, 3.396805, 1.548192, 0.024722, + -0.038209, 3.396384, 1.548109, 0.032306, -0.049868, 3.395158, 1.547979, 0.040936, -0.063077, + 3.394303, 1.547785, 0.050610, -0.077791, 3.392979, 1.547513, 0.061360, -0.093869, 3.389910, + 1.547134, 0.073227, -0.111380, 3.386669, 1.546619, 0.086217, -0.130371, 3.382974, 1.545938, + 0.100364, -0.150684, 3.378046, 1.545039, 0.115733, -0.172116, 3.371719, 1.543880, 0.132309, + -0.194809, 3.363764, 1.542380, 0.150174, -0.218431, 3.353699, 1.540462, 0.169340, -0.242954, + 3.341397, 1.538002, 0.189788, -0.268175, 3.324957, 1.534894, 0.211581, -0.293776, 3.304776, + 1.530954, 0.234561, -0.319619, 3.278192, 1.526033, 0.258776, -0.345089, 3.244910, 1.519926, + 0.284059, -0.370176, 3.203338, 1.512296, 0.310312, -0.394171, 3.152477, 1.502956, 0.336748, + -0.416137, 3.083616, 1.491463, 0.364029, -0.436752, 3.010481, 1.477493, 0.391575, -0.455102, + 2.925454, 1.460933, 0.419409, -0.471378, 2.834380, 1.441554, 0.446811, -0.484714, 2.733329, + 1.418861, 0.474489, -0.496021, 2.633630, 1.393405, 0.501751, -0.504991, 2.530935, 1.364633, + 0.528488, -0.511392, 2.426653, 1.333234, 0.554428, -0.515395, 2.323633, 1.299138, 0.580434, + -0.517761, 2.224964, 1.262462, 0.605474, -0.517598, 2.127228, 1.223784, 0.629888, -0.514946, + 2.030545, 1.182321, 0.655579, -0.510177, 1.939070, 1.138515, 0.681940, -0.503097, 1.852355, + 1.091502, 0.707228, -0.493537, 1.768084, 1.043464, 0.731894, -0.482372, 1.690840, 0.994242, + 0.756741, -0.470312, 1.619277, 0.944749, 0.780160, -0.456412, 1.553430, 0.894816, 0.803384, + -0.441492, 1.493357, 0.845202, 0.826347, -0.425944, 1.437830, 0.795954, 0.849145, -0.409532, + 1.388578, 0.746915, 0.870617, -0.391988, 1.341527, 0.698025, 0.892943, -0.374229, 1.302188, + 0.649579, 0.913828, -0.355148, 1.262877, 0.601833, 0.936830, -0.335238, 1.230136, 0.554521, + 0.958687, -0.313939, 1.199596, 0.507208, 0.982008, -0.292741, 1.173619, 0.461357, 1.003691, + -0.270940, 1.149015, 0.416031, 1.027223, -0.249102, 1.128689, 0.372457, 1.050048, -0.226899, + 1.109444, 0.330281, 1.074105, -0.204329, 1.092943, 0.288987, 1.098971, -0.180560, 1.078591, + 0.249075, 1.123324, -0.155987, 1.066885, 0.211519, 1.145445, -0.130929, 1.057617, 0.176506, + 1.162856, -0.105269, 1.048453, 0.142345, 1.175360, -0.079267, 1.037439, 0.107452, 1.182514, + -0.052547, 1.024393, 0.071252, 1.186575, -0.025744, 1.011093, 0.035019, 1.192050, 0.000318, + 1.000013, -0.000152, 0.000204, -0.000334, 3.909175, 1.636412, 0.000504, -0.000825, 3.678647, + 1.636410, 0.002015, -0.003298, 3.678315, 1.636387, 0.004533, -0.007417, 3.674126, 1.636310, + 0.008062, -0.013190, 3.676771, 1.636376, 0.012603, -0.020613, 3.678135, 1.636369, 0.018153, + -0.029675, 3.677315, 1.636299, 0.024723, -0.040378, 3.676872, 1.636196, 0.032318, -0.052708, + 3.675750, 1.636038, 0.040955, -0.066660, 3.674803, 1.635810, 0.050645, -0.082203, 3.672735, + 1.635494, 0.061429, -0.099150, 3.669047, 1.635048, 0.073333, -0.117679, 3.665401, 1.634437, + 0.086388, -0.137725, 3.661315, 1.633634, 0.100620, -0.159081, 3.654992, 1.632571, 0.116087, + -0.181721, 3.647341, 1.631202, 0.132820, -0.205611, 3.637877, 1.629432, 0.150867, -0.230542, + 3.626333, 1.627161, 0.170234, -0.256239, 3.610671, 1.624266, 0.190981, -0.282751, 3.591685, + 1.620589, 0.213013, -0.309430, 3.565864, 1.615999, 0.236387, -0.336427, 3.534826, 1.610216, + 0.260943, -0.362931, 3.493984, 1.603047, 0.286497, -0.388644, 3.442075, 1.593920, 0.312769, + -0.412912, 3.375973, 1.582961, 0.339832, -0.435635, 3.299355, 1.569343, 0.367214, -0.456181, + 3.208994, 1.553137, 0.394935, -0.474325, 3.108910, 1.533791, 0.422935, -0.490318, 3.001767, + 1.511093, 0.451166, -0.503827, 2.891735, 1.485145, 0.478695, -0.514185, 2.773430, 1.455617, + 0.506313, -0.522502, 2.657639, 1.422946, 0.533427, -0.528119, 2.541132, 1.387843, 0.559942, + -0.531430, 2.426950, 1.349542, 0.585150, -0.531978, 2.312437, 1.309303, 0.610500, -0.531054, + 2.205966, 1.266280, 0.635380, -0.528058, 2.101993, 1.221709, 0.659852, -0.522751, 2.002950, + 1.175062, 0.685151, -0.515026, 1.908647, 1.125078, 0.710920, -0.505020, 1.819389, 1.074296, + 0.736066, -0.493268, 1.735806, 1.022420, 0.760503, -0.480032, 1.658607, 0.970230, 0.785091, + -0.465986, 1.589424, 0.917077, 0.807523, -0.449721, 1.522533, 0.864888, 0.830974, -0.433461, + 1.465416, 0.813006, 0.852659, -0.415808, 1.409076, 0.761689, 0.874841, -0.397855, 1.360758, + 0.711258, 0.896322, -0.379041, 1.316829, 0.661721, 0.918134, -0.360048, 1.278574, 0.612263, + 0.939356, -0.340108, 1.242200, 0.564369, 0.961025, -0.318877, 1.210305, 0.516506, 0.984371, + -0.297130, 1.183689, 0.469342, 1.006905, -0.274661, 1.157466, 0.423080, 1.029941, -0.252234, + 1.135066, 0.378315, 1.052751, -0.229268, 1.114518, 0.335169, 1.077981, -0.206662, 1.097760, + 0.293336, 1.102542, -0.183331, 1.082051, 0.252984, 1.126539, -0.158797, 1.068935, 0.214990, + 1.149023, -0.133014, 1.058996, 0.178903, 1.167550, -0.106641, 1.050245, 0.144559, 1.179994, + -0.079952, 1.038648, 0.108667, 1.187104, -0.053316, 1.025284, 0.072209, 1.191406, -0.026826, + 1.011453, 0.035833, 1.196748, 0.000226, 1.000034, -0.000061, 0.000200, -0.000346, 3.996419, + 1.732034, 0.000504, -0.000873, 4.000138, 1.732038, 0.002016, -0.003492, 4.002078, 1.732012, + 0.004538, -0.007859, 4.005626, 1.731962, 0.008064, -0.013963, 3.998500, 1.731999, 0.012590, + -0.021794, 3.995024, 1.732004, 0.018154, -0.031406, 3.999233, 1.731901, 0.024727, -0.042733, + 3.998497, 1.731774, 0.032327, -0.055781, 3.997064, 1.731599, 0.040974, -0.070543, 3.995856, + 1.731325, 0.050685, -0.086984, 3.993839, 1.730945, 0.061506, -0.104897, 3.989519, 1.730417, + 0.073458, -0.124506, 3.985313, 1.729697, 0.086573, -0.145706, 3.979984, 1.728747, 0.100909, + -0.168211, 3.972562, 1.727491, 0.116509, -0.192198, 3.963836, 1.725854, 0.133404, -0.217280, + 3.951919, 1.723749, 0.151659, -0.243556, 3.937734, 1.721093, 0.171288, -0.270611, 3.919021, + 1.717640, 0.192301, -0.298389, 3.895171, 1.713272, 0.214683, -0.326338, 3.864171, 1.707825, + 0.238392, -0.354394, 3.824682, 1.700956, 0.263151, -0.381636, 3.771168, 1.692392, 0.289155, + -0.408266, 3.709961, 1.681769, 0.315832, -0.433070, 3.630302, 1.668539, 0.342942, -0.455741, + 3.534719, 1.652513, 0.370892, -0.476655, 3.431531, 1.633428, 0.398985, -0.494692, 3.314933, + 1.610694, 0.427206, -0.510313, 3.189741, 1.584240, 0.455266, -0.522760, 3.058325, 1.554195, + 0.483472, -0.532872, 2.927213, 1.520805, 0.511192, -0.540229, 2.794112, 1.484026, 0.538706, + -0.545105, 2.663786, 1.443796, 0.565422, -0.547251, 2.534841, 1.401429, 0.591270, -0.547115, + 2.408437, 1.356231, 0.616787, -0.545113, 2.291284, 1.308887, 0.641380, -0.540853, 2.177478, + 1.260447, 0.665344, -0.534561, 2.069265, 1.210634, 0.690147, -0.527115, 1.969776, 1.158569, + 0.714578, -0.516171, 1.870847, 1.104593, 0.740349, -0.504048, 1.782674, 1.049578, 0.764563, + -0.489683, 1.698614, 0.994458, 0.788710, -0.474541, 1.624447, 0.938612, 0.812154, -0.458099, + 1.554453, 0.883694, 0.834566, -0.440345, 1.490045, 0.830220, 0.857486, -0.422491, 1.432889, + 0.776499, 0.879224, -0.403588, 1.380669, 0.724257, 0.899971, -0.383819, 1.333124, 0.673311, + 0.922111, -0.364250, 1.292648, 0.622999, 0.942842, -0.343873, 1.253933, 0.573304, 0.964398, + -0.323206, 1.221027, 0.525090, 0.986860, -0.301711, 1.191806, 0.477580, 1.009760, -0.278695, + 1.165162, 0.430624, 1.033347, -0.255591, 1.141715, 0.384482, 1.055937, -0.232039, 1.119739, + 0.340532, 1.081178, -0.208664, 1.102117, 0.297311, 1.105696, -0.184935, 1.085062, 0.256227, + 1.129575, -0.160673, 1.070918, 0.217709, 1.152135, -0.135414, 1.060642, 0.181471, 1.171221, + -0.108462, 1.051041, 0.146380, 1.184412, -0.081008, 1.039694, 0.110120, 1.191820, -0.053710, + 1.025903, 0.073052, 1.196195, -0.026625, 1.011816, 0.036129, 1.201677, -0.000175, 0.999945, + 0.000098, 0.000196, -0.000360, 4.100786, 1.836290, 0.000504, -0.000925, 4.370184, 1.836295, + 0.002018, -0.003706, 4.385247, 1.836243, 0.004534, -0.008324, 4.370146, 1.836210, 0.008064, + -0.014805, 4.372335, 1.836256, 0.012597, -0.023116, 4.359918, 1.836259, 0.018158, -0.033299, + 4.371503, 1.836123, 0.024732, -0.045301, 4.370533, 1.835988, 0.032344, -0.059143, 4.369649, + 1.835768, 0.040999, -0.074779, 4.367861, 1.835454, 0.050739, -0.092178, 4.364322, 1.834974, + 0.061594, -0.111161, 4.359221, 1.834355, 0.073604, -0.131958, 4.354620, 1.833499, 0.086796, + -0.154393, 4.347915, 1.832355, 0.101246, -0.178201, 4.339152, 1.830880, 0.116990, -0.203531, + 4.328327, 1.828936, 0.134086, -0.230043, 4.314240, 1.826442, 0.152589, -0.257718, 4.296795, + 1.823230, 0.172514, -0.286176, 4.273985, 1.819124, 0.193853, -0.315295, 4.244136, 1.813909, + 0.216582, -0.344507, 4.205152, 1.807410, 0.240668, -0.373646, 4.154781, 1.799084, 0.265904, + -0.401897, 4.091563, 1.788905, 0.292226, -0.429136, 4.013199, 1.776206, 0.319045, -0.454057, + 3.912886, 1.760500, 0.346721, -0.477219, 3.800927, 1.741586, 0.374849, -0.497883, 3.675652, + 1.718818, 0.403078, -0.515504, 3.536892, 1.692138, 0.431597, -0.530621, 3.391351, 1.661434, + 0.460246, -0.542852, 3.242817, 1.626989, 0.488899, -0.552238, 3.093685, 1.588582, 0.517215, + -0.559045, 2.944163, 1.546300, 0.544480, -0.562351, 2.794189, 1.501299, 0.571542, -0.563394, + 2.650239, 1.453758, 0.598167, -0.562590, 2.513757, 1.403321, 0.624104, -0.559636, 2.384203, + 1.352431, 0.648789, -0.554148, 2.259149, 1.298758, 0.672715, -0.546779, 2.140250, 1.244943, + 0.696258, -0.537896, 2.030401, 1.189971, 0.720048, -0.527401, 1.928311, 1.134526, 0.744078, + -0.514142, 1.830175, 1.076504, 0.768895, -0.499352, 1.740731, 1.018032, 0.792551, -0.482982, + 1.658911, 0.960250, 0.817007, -0.466406, 1.586579, 0.903029, 0.839035, -0.447616, 1.516969, + 0.846484, 0.862742, -0.429261, 1.458675, 0.791420, 0.884307, -0.409479, 1.402989, 0.737125, + 0.905641, -0.389303, 1.352817, 0.683912, 0.926185, -0.368344, 1.306684, 0.632690, 0.947229, + -0.347366, 1.267395, 0.581739, 0.969502, -0.326720, 1.233192, 0.532305, 0.990758, -0.304973, + 1.201017, 0.484166, 1.012749, -0.282816, 1.173018, 0.437385, 1.035533, -0.259084, 1.147184, + 0.390755, 1.059915, -0.235239, 1.125388, 0.345399, 1.084348, -0.211044, 1.105859, 0.301356, + 1.109544, -0.186698, 1.088888, 0.259708, 1.133770, -0.161900, 1.073848, 0.220324, 1.157553, + -0.136604, 1.063190, 0.183857, 1.176461, -0.110428, 1.053110, 0.148521, 1.190137, -0.082898, + 1.041484, 0.112124, 1.197215, -0.054554, 1.026844, 0.074160, 1.201654, -0.026744, 1.012264, + 0.036527, 1.207085, 0.000399, 1.000034, -0.000201, 0.000191, -0.000373, 4.194318, 1.950551, + 0.000504, -0.000983, 4.804350, 1.950552, 0.002015, -0.003931, 4.802820, 1.950518, 0.004536, + -0.008847, 4.805254, 1.950472, 0.008064, -0.015725, 4.804152, 1.950517, 0.012693, -0.024740, + 4.826828, 1.949914, 0.018159, -0.035365, 4.803103, 1.950349, 0.024740, -0.048122, 4.803220, + 1.950183, 0.032361, -0.062822, 4.801522, 1.949917, 0.041034, -0.079430, 4.799593, 1.949538, + 0.050815, -0.097841, 4.797179, 1.948972, 0.061702, -0.118026, 4.789557, 1.948246, 0.073766, + -0.140112, 4.783293, 1.947204, 0.087066, -0.163819, 4.775698, 1.945855, 0.101637, -0.189122, + 4.764612, 1.944052, 0.117558, -0.215884, 4.751486, 1.941710, 0.134884, -0.243968, 4.734791, + 1.938727, 0.153637, -0.273170, 4.712078, 1.934891, 0.173890, -0.303146, 4.683575, 1.929976, + 0.195643, -0.333704, 4.646766, 1.923740, 0.218767, -0.364170, 4.596814, 1.915888, 0.243337, + -0.394530, 4.535509, 1.905970, 0.268860, -0.423512, 4.452006, 1.893623, 0.295173, -0.450609, + 4.345682, 1.878286, 0.322784, -0.476488, 4.231632, 1.859391, 0.350616, -0.499420, 4.093553, + 1.836912, 0.379127, -0.519862, 3.944127, 1.809625, 0.407860, -0.537373, 3.782223, 1.778529, + 0.436717, -0.551802, 3.615563, 1.742684, 0.465345, -0.562951, 3.440672, 1.702289, 0.494158, + -0.571334, 3.268070, 1.658666, 0.522896, -0.577227, 3.100668, 1.611027, 0.551379, -0.580514, + 2.937615, 1.559742, 0.578992, -0.580610, 2.778703, 1.507257, 0.605095, -0.577729, 2.621626, + 1.451941, 0.630653, -0.573000, 2.476506, 1.395218, 0.656175, -0.566944, 2.341592, 1.337862, + 0.681036, -0.558988, 2.216478, 1.279275, 0.704713, -0.549211, 2.096972, 1.220526, 0.726894, + -0.537190, 1.983311, 1.161709, 0.749865, -0.524167, 1.881100, 1.102095, 0.773553, -0.508991, + 1.785637, 1.042039, 0.797102, -0.491658, 1.697234, 0.981588, 0.821187, -0.474093, 1.620250, + 0.921265, 0.843848, -0.454980, 1.547071, 0.862757, 0.866662, -0.435421, 1.482008, 0.804700, + 0.888696, -0.414990, 1.424116, 0.749432, 0.910945, -0.394472, 1.372658, 0.694767, 0.932300, + -0.373239, 1.325157, 0.641106, 0.952850, -0.351347, 1.282217, 0.589689, 0.974718, -0.329809, + 1.244897, 0.539322, 0.996445, -0.307902, 1.212306, 0.490083, 1.017580, -0.285392, 1.181402, + 0.442702, 1.040342, -0.262782, 1.155996, 0.395911, 1.064399, -0.238995, 1.131708, 0.350206, + 1.089464, -0.214297, 1.111215, 0.305175, 1.115565, -0.189293, 1.093094, 0.262686, 1.140640, + -0.163843, 1.077994, 0.223078, 1.163824, -0.137789, 1.066014, 0.185651, 1.182577, -0.111087, + 1.055615, 0.150045, 1.195775, -0.083945, 1.042940, 0.113457, 1.203175, -0.056145, 1.028015, + 0.075453, 1.207282, -0.027685, 1.012552, 0.037217, 1.213019, 0.000362, 0.999938, -0.000293, + 0.000187, -0.000388, 4.316009, 2.076500, 0.000504, -0.001048, 5.317799, 2.076499, 0.002014, + -0.004182, 5.306557, 2.076523, 0.004539, -0.009425, 5.317505, 2.076453, 0.008063, -0.016737, + 5.312143, 2.076410, 0.012614, -0.026171, 5.316434, 2.076389, 0.018158, -0.037641, 5.307836, + 2.076265, 0.024767, -0.051266, 5.315297, 2.076044, 0.032372, -0.066859, 5.307433, 2.075743, + 0.041066, -0.084538, 5.304809, 2.075270, 0.050871, -0.104062, 5.299277, 2.074622, 0.061821, + -0.125613, 5.293419, 2.073708, 0.073970, -0.149085, 5.286629, 2.072457, 0.087375, -0.174214, + 5.275937, 2.070804, 0.102105, -0.201136, 5.263267, 2.068647, 0.118223, -0.229505, 5.246309, + 2.065846, 0.135814, -0.259217, 5.225496, 2.062189, 0.154887, -0.289990, 5.196580, 2.057566, + 0.175510, -0.321618, 5.160716, 2.051593, 0.197636, -0.353632, 5.112202, 2.043949, 0.221168, + -0.385303, 5.046981, 2.034445, 0.246099, -0.416511, 4.965386, 2.022368, 0.272070, -0.446377, + 4.860735, 2.007160, 0.299090, -0.474279, 4.735140, 1.988598, 0.326702, -0.499809, 4.584962, + 1.965865, 0.355017, -0.522790, 4.420447, 1.938705, 0.383856, -0.542755, 4.241942, 1.906370, + 0.413059, -0.559903, 4.053302, 1.869455, 0.441882, -0.573174, 3.852753, 1.827946, 0.471516, + -0.584151, 3.660377, 1.781652, 0.500872, -0.591843, 3.466027, 1.730885, 0.529677, -0.596253, + 3.272812, 1.676821, 0.557683, -0.597604, 3.084286, 1.620064, 0.585652, -0.596591, 2.906111, + 1.560909, 0.612819, -0.593138, 2.738258, 1.500318, 0.639848, -0.588245, 2.584172, 1.438127, + 0.664758, -0.580140, 2.430697, 1.375746, 0.688754, -0.570189, 2.290701, 1.312727, 0.712848, + -0.559420, 2.162679, 1.250063, 0.735111, -0.546570, 2.042186, 1.187840, 0.757521, -0.532944, + 1.933435, 1.125513, 0.780056, -0.517981, 1.833524, 1.063827, 0.802513, -0.500724, 1.739053, + 1.002154, 0.825462, -0.481625, 1.652381, 0.939811, 0.848973, -0.462327, 1.577560, 0.878279, + 0.871521, -0.441928, 1.509291, 0.819200, 0.892325, -0.420297, 1.443799, 0.761607, 0.914935, + -0.399072, 1.389647, 0.705351, 0.936429, -0.377232, 1.339903, 0.650213, 0.957614, -0.355091, + 1.295467, 0.597773, 0.979578, -0.332767, 1.256692, 0.545914, 1.000860, -0.310147, 1.221666, + 0.495661, 1.022550, -0.287395, 1.190775, 0.448026, 1.045005, -0.264582, 1.162641, 0.400490, + 1.068703, -0.241464, 1.138358, 0.354088, 1.093098, -0.217504, 1.115973, 0.309812, 1.119230, + -0.192140, 1.096284, 0.266297, 1.144608, -0.165975, 1.080042, 0.225831, 1.168599, -0.139174, + 1.067749, 0.187761, 1.187970, -0.111910, 1.056635, 0.151322, 1.201240, -0.083978, 1.043566, + 0.114337, 1.208895, -0.056089, 1.028366, 0.076083, 1.213344, -0.028369, 1.013074, 0.037735, + 1.219220, -0.000534, 0.999968, 0.000076, 0.000182, -0.000404, 4.433519, 2.216201, 0.000504, + -0.001117, 5.911693, 2.216198, 0.002017, -0.004469, 5.919142, 2.216190, 0.004536, -0.010051, + 5.913172, 2.216130, 0.008065, -0.017867, 5.911791, 2.216145, 0.012467, -0.027603, 5.785357, + 2.216447, 0.018156, -0.040159, 5.901121, 2.215958, 0.024758, -0.054670, 5.908781, 2.215654, + 0.032395, -0.071352, 5.906098, 2.215283, 0.041108, -0.090201, 5.902558, 2.214715, 0.050955, + -0.111004, 5.895707, 2.213905, 0.061968, -0.134002, 5.888736, 2.212807, 0.074206, -0.159038, + 5.880633, 2.211303, 0.087742, -0.185801, 5.867001, 2.209297, 0.102652, -0.214368, 5.851446, + 2.206657, 0.119006, -0.244573, 5.830722, 2.203232, 0.136883, -0.276067, 5.802688, 2.198778, + 0.156335, -0.308660, 5.767185, 2.193091, 0.177396, -0.341940, 5.719726, 2.185858, 0.200070, + -0.375591, 5.658792, 2.176584, 0.224067, -0.408564, 5.573508, 2.164759, 0.249420, -0.440668, + 5.465696, 2.149777, 0.275879, -0.471138, 5.332207, 2.131225, 0.303307, -0.499204, 5.173339, + 2.108794, 0.331189, -0.524547, 4.985102, 2.080585, 0.359932, -0.547256, 4.785788, 2.047792, + 0.389063, -0.566479, 4.569344, 2.009518, 0.418725, -0.583031, 4.349557, 1.965601, 0.448181, + -0.595809, 4.121278, 1.916911, 0.477703, -0.605102, 3.892291, 1.863530, 0.507999, -0.612462, + 3.676557, 1.806286, 0.536889, -0.615451, 3.456241, 1.745841, 0.565778, -0.616029, 3.249464, + 1.681137, 0.593863, -0.613644, 3.050273, 1.615238, 0.620770, -0.608268, 2.859599, 1.548003, + 0.647171, -0.601116, 2.683287, 1.480447, 0.673458, -0.592840, 2.524036, 1.412084, 0.698064, + -0.581973, 2.371046, 1.345130, 0.721011, -0.568963, 2.229104, 1.278440, 0.744293, -0.555642, + 2.103213, 1.212448, 0.766314, -0.540934, 1.985370, 1.146287, 0.788164, -0.525271, 1.878842, + 1.082600, 0.809019, -0.507986, 1.779821, 1.019978, 0.830947, -0.489717, 1.691630, 0.956931, + 0.853732, -0.469345, 1.607513, 0.894207, 0.874904, -0.447618, 1.531176, 0.833436, 0.897289, + -0.426124, 1.467302, 0.773611, 0.919226, -0.404025, 1.408321, 0.716016, 0.940860, -0.381454, + 1.356209, 0.659515, 0.962764, -0.358901, 1.310082, 0.604629, 0.984322, -0.335983, 1.268485, + 0.552335, 1.005343, -0.312533, 1.230662, 0.501591, 1.028153, -0.289452, 1.199168, 0.452032, + 1.049283, -0.265754, 1.168575, 0.404347, 1.073687, -0.242571, 1.143533, 0.357445, 1.097546, + -0.218681, 1.119859, 0.312534, 1.123340, -0.194465, 1.099634, 0.269437, 1.148166, -0.168797, + 1.081968, 0.228586, 1.172518, -0.141552, 1.068789, 0.189866, 1.192930, -0.113325, 1.057548, + 0.152772, 1.206816, -0.084800, 1.044145, 0.115390, 1.215045, -0.056019, 1.028938, 0.076493, + 1.220048, -0.027733, 1.013338, 0.037767, 1.225852, 0.000050, 0.999927, -0.000160, 0.000178, + -0.000422, 4.587902, 2.372253, 0.000504, -0.001195, 6.624675, 2.372248, 0.002016, -0.004782, + 6.626884, 2.372187, 0.004531, -0.010746, 6.607379, 2.372318, 0.008081, -0.019161, 6.640102, + 2.372084, 0.012637, -0.029945, 6.653708, 2.372128, 0.018167, -0.042999, 6.623837, 2.371902, + 0.024769, -0.058516, 6.624484, 2.371595, 0.032421, -0.076370, 6.620877, 2.371120, 0.041164, + -0.096474, 6.615235, 2.370428, 0.051057, -0.118786, 6.607844, 2.369440, 0.062136, -0.143390, + 6.599216, 2.368075, 0.074490, -0.170034, 6.588018, 2.366218, 0.088179, -0.198717, 6.572526, + 2.363747, 0.103307, -0.229147, 6.551868, 2.360517, 0.119964, -0.261253, 6.526089, 2.356304, + 0.138173, -0.294703, 6.489593, 2.350797, 0.158072, -0.329261, 6.443573, 2.343783, 0.179592, + -0.364298, 6.379764, 2.334673, 0.202709, -0.399375, 6.295845, 2.323125, 0.227335, -0.433616, + 6.184929, 2.308547, 0.253230, -0.466794, 6.045905, 2.289980, 0.280100, -0.497509, 5.871803, + 2.266964, 0.308146, -0.525956, 5.672422, 2.239074, 0.336544, -0.551101, 5.443256, 2.204809, + 0.365223, -0.572471, 5.188034, 2.164827, 0.395484, -0.592088, 4.943783, 2.119489, 0.424416, + -0.606026, 4.666400, 2.067262, 0.455641, -0.619671, 4.418961, 2.009937, 0.485298, -0.627583, + 4.152737, 1.948900, 0.514774, -0.632072, 3.893344, 1.882692, 0.544172, -0.634033, 3.645332, + 1.814073, 0.573283, -0.633239, 3.414651, 1.742717, 0.602155, -0.630008, 3.195712, 1.669703, + 0.630520, -0.624550, 2.994536, 1.596021, 0.657121, -0.615749, 2.799373, 1.522572, 0.682071, + -0.604738, 2.616102, 1.448978, 0.707605, -0.593301, 2.456112, 1.376250, 0.731492, -0.579628, + 2.303517, 1.305297, 0.754139, -0.564473, 2.165340, 1.235548, 0.776505, -0.548787, 2.041646, + 1.167051, 0.796833, -0.531415, 1.923334, 1.100534, 0.817565, -0.513778, 1.818176, 1.035144, + 0.837981, -0.495167, 1.723830, 0.971583, 0.858513, -0.475690, 1.638448, 0.908841, 0.879892, + -0.454099, 1.559420, 0.846701, 0.902258, -0.432038, 1.491471, 0.785332, 0.924114, -0.409316, + 1.428878, 0.726409, 0.944230, -0.385618, 1.370785, 0.668588, 0.967001, -0.362604, 1.323529, + 0.612943, 0.988579, -0.339117, 1.279679, 0.559038, 1.010210, -0.315355, 1.240104, 0.506867, + 1.032084, -0.291408, 1.205261, 0.456934, 1.054671, -0.267387, 1.175197, 0.407792, 1.078314, + -0.243346, 1.148153, 0.360992, 1.102443, -0.219205, 1.123799, 0.315577, 1.128524, -0.194996, + 1.102624, 0.271742, 1.153989, -0.169897, 1.085134, 0.230702, 1.179420, -0.143960, 1.071699, + 0.192146, 1.200098, -0.116173, 1.060179, 0.155164, 1.214837, -0.086655, 1.046290, 0.117071, + 1.222749, -0.056956, 1.030040, 0.077450, 1.227273, -0.027883, 1.013650, 0.038092, 1.233293, + 0.000831, 1.000043, -0.000462, 0.000173, -0.000442, 4.741539, 2.547922, 0.000504, -0.001284, + 7.491127, 2.547919, 0.002014, -0.005132, 7.484889, 2.547844, 0.004523, -0.011521, 7.439875, + 2.547587, 0.008059, -0.020524, 7.483694, 2.547725, 0.012586, -0.032029, 7.470912, 2.547685, + 0.018081, -0.045948, 7.422534, 2.547686, 0.024783, -0.062844, 7.487581, 2.547107, 0.032451, + -0.082011, 7.483603, 2.546522, 0.041233, -0.103540, 7.475124, 2.545684, 0.051181, -0.127537, + 7.467521, 2.544438, 0.062347, -0.153921, 7.456266, 2.542744, 0.074829, -0.182427, 7.440422, + 2.540459, 0.088703, -0.213134, 7.420694, 2.537380, 0.104080, -0.245750, 7.394875, 2.533347, + 0.121050, -0.279941, 7.358515, 2.528069, 0.139697, -0.315591, 7.313001, 2.521237, 0.160036, + -0.351980, 7.246342, 2.512378, 0.182147, -0.388993, 7.163688, 2.500993, 0.205799, -0.425570, + 7.048339, 2.486450, 0.231091, -0.461093, 6.902586, 2.468174, 0.257405, -0.494668, 6.712721, + 2.444774, 0.284956, -0.525889, 6.491261, 2.415538, 0.313180, -0.553693, 6.232833, 2.380610, + 0.342327, -0.578724, 5.953834, 2.338525, 0.371689, -0.599706, 5.649698, 2.290256, 0.401919, + -0.617615, 5.347900, 2.235157, 0.432204, -0.631632, 5.036417, 2.173932, 0.463151, -0.643082, + 4.735976, 2.107298, 0.493388, -0.649970, 4.432044, 2.036121, 0.524128, -0.654188, 4.145472, + 1.961595, 0.553930, -0.654671, 3.866877, 1.883602, 0.583856, -0.653051, 3.607848, 1.804521, + 0.611762, -0.646994, 3.356237, 1.724047, 0.639117, -0.638860, 3.122531, 1.643016, 0.666279, + -0.629093, 2.913178, 1.563932, 0.692936, -0.617862, 2.722675, 1.484614, 0.716498, -0.603279, + 2.536926, 1.406734, 0.742273, -0.589878, 2.381054, 1.331469, 0.764031, -0.572744, 2.228312, + 1.256796, 0.786601, -0.555933, 2.095451, 1.185290, 0.807776, -0.537992, 1.972866, 1.115940, + 0.828400, -0.519596, 1.863394, 1.048371, 0.847412, -0.499847, 1.760630, 0.982934, 0.866850, + -0.479920, 1.670998, 0.919972, 0.886340, -0.459434, 1.587962, 0.858100, 0.906933, -0.437767, + 1.515505, 0.796714, 0.927490, -0.414068, 1.448243, 0.736162, 0.950217, -0.390910, 1.390505, + 0.677613, 0.971545, -0.366964, 1.337865, 0.620477, 0.992901, -0.342603, 1.291104, 0.565807, + 1.015460, -0.318596, 1.251138, 0.513086, 1.037859, -0.294242, 1.214291, 0.461573, 1.060535, + -0.269601, 1.182517, 0.411838, 1.086885, -0.245608, 1.155300, 0.363221, 1.111237, -0.220589, + 1.129715, 0.317174, 1.138718, -0.196008, 1.108103, 0.273213, 1.164223, -0.170408, 1.089640, + 0.231968, 1.187256, -0.144205, 1.074145, 0.192987, 1.207851, -0.116945, 1.061615, 0.156118, + 1.222217, -0.088852, 1.047599, 0.118674, 1.230315, -0.059381, 1.030869, 0.078993, 1.235052, + -0.029145, 1.014126, 0.038924, 1.241359, 0.000479, 1.000114, -0.000211, 0.000169, -0.000465, + 4.953966, 2.747437, 0.000504, -0.001384, 8.544530, 2.747430, 0.002015, -0.005537, 8.545147, + 2.747339, 0.004542, -0.012477, 8.557734, 2.747125, 0.008064, -0.022143, 8.530193, 2.747341, + 0.012543, -0.034411, 8.465151, 2.747411, 0.018178, -0.049792, 8.543328, 2.746874, 0.024810, + -0.067784, 8.547247, 2.746396, 0.032489, -0.088416, 8.537436, 2.745730, 0.041313, -0.111580, + 8.526655, 2.744596, 0.051332, -0.137462, 8.517438, 2.743082, 0.062603, -0.165860, 8.502803, + 2.740950, 0.075240, -0.196548, 8.481507, 2.738057, 0.089341, -0.229440, 8.454287, 2.734174, + 0.105021, -0.264395, 8.420289, 2.729086, 0.122399, -0.301020, 8.373503, 2.722420, 0.141526, + -0.338997, 8.309059, 2.713686, 0.162451, -0.377589, 8.221539, 2.702492, 0.185098, -0.416349, + 8.100116, 2.687893, 0.209406, -0.454284, 7.941704, 2.669386, 0.235098, -0.490450, 7.733318, + 2.645590, 0.262100, -0.524592, 7.486120, 2.615709, 0.290103, -0.555558, 7.193498, 2.579231, + 0.319135, -0.583516, 6.874796, 2.534957, 0.348286, -0.606714, 6.516118, 2.483017, 0.378840, + -0.627850, 6.163912, 2.424214, 0.409608, -0.644715, 5.801404, 2.357563, 0.440553, -0.657657, + 5.435955, 2.285835, 0.470599, -0.665621, 5.063481, 2.207940, 0.503172, -0.673767, 4.743532, + 2.126440, 0.533884, -0.676009, 4.413409, 2.040694, 0.563808, -0.674536, 4.092169, 1.953979, + 0.591849, -0.668913, 3.787057, 1.865897, 0.621474, -0.663159, 3.520578, 1.777762, 0.650500, + -0.655018, 3.275065, 1.689902, 0.678011, -0.643949, 3.043141, 1.603528, 0.703490, -0.630030, + 2.827104, 1.519484, 0.728250, -0.614910, 2.632620, 1.436677, 0.752165, -0.598649, 2.455570, + 1.355753, 0.775894, -0.581771, 2.295932, 1.278884, 0.797650, -0.563193, 2.152291, 1.202767, + 0.818505, -0.543750, 2.022099, 1.130338, 0.838596, -0.524017, 1.903562, 1.060263, 0.858396, + -0.504064, 1.797204, 0.993077, 0.877088, -0.483418, 1.701208, 0.928606, 0.896606, -0.462786, + 1.617736, 0.866039, 0.914342, -0.440943, 1.539227, 0.804293, 0.933550, -0.419129, 1.470383, + 0.745206, 0.955237, -0.396100, 1.409100, 0.685832, 0.976700, -0.371743, 1.354930, 0.627953, + 0.997681, -0.346882, 1.305249, 0.572127, 1.020784, -0.322391, 1.262603, 0.517941, 1.043840, + -0.297564, 1.225115, 0.466188, 1.067224, -0.272639, 1.190817, 0.415499, 1.092358, -0.247664, + 1.161265, 0.366782, 1.117573, -0.222260, 1.133935, 0.319377, 1.145730, -0.196933, 1.111750, + 0.275293, 1.170822, -0.170577, 1.091981, 0.233306, 1.194559, -0.143878, 1.075810, 0.193950, + 1.214819, -0.116347, 1.062438, 0.156724, 1.229830, -0.088233, 1.048092, 0.118984, 1.238185, + -0.059408, 1.031325, 0.079385, 1.243527, -0.030703, 1.014698, 0.039893, 1.249724, -0.001520, + 0.999819, 0.000760, 0.000164, -0.000489, 5.157359, 2.976300, 0.000505, -0.001502, 9.891415, + 2.976286, 0.002016, -0.006000, 9.857730, 2.976197, 0.004543, -0.013519, 9.870651, 2.975832, + 0.008064, -0.023985, 9.855780, 2.976170, 0.012611, -0.037471, 9.850209, 2.975941, 0.018162, + -0.053866, 9.827134, 2.974968, 0.024820, -0.073390, 9.849955, 2.975010, 0.032545, -0.095758, + 9.842021, 2.974073, 0.041418, -0.120834, 9.829989, 2.972700, 0.051511, -0.148861, 9.817421, + 2.970736, 0.062920, -0.179456, 9.797347, 2.968033, 0.075744, -0.212674, 9.771533, 2.964371, + 0.090131, -0.248193, 9.735924, 2.959437, 0.106187, -0.285748, 9.687707, 2.952881, 0.124035, + -0.325017, 9.622684, 2.944273, 0.143733, -0.365463, 9.531452, 2.933093, 0.165262, -0.406157, + 9.401732, 2.918484, 0.188622, -0.446833, 9.232451, 2.899529, 0.213693, -0.486209, 9.013432, + 2.875137, 0.239987, -0.522925, 8.725671, 2.844166, 0.267796, -0.557452, 8.400028, 2.805649, + 0.296547, -0.588266, 8.023041, 2.758720, 0.325838, -0.614837, 7.606773, 2.702676, 0.355479, + -0.636760, 7.160680, 2.638483, 0.386984, -0.657230, 6.736765, 2.566849, 0.418853, -0.673592, + 6.313742, 2.488091, 0.450302, -0.684966, 5.884479, 2.402458, 0.481149, -0.691591, 5.455771, + 2.311816, 0.512177, -0.695337, 5.055698, 2.217330, 0.543437, -0.696370, 4.681506, 2.121285, + 0.574309, -0.694186, 4.334716, 2.024160, 0.604787, -0.689158, 4.008524, 1.927738, 0.633483, + -0.680580, 3.703505, 1.830456, 0.660766, -0.669088, 3.418386, 1.734934, 0.688471, -0.656673, + 3.168101, 1.642316, 0.715729, -0.642820, 2.941735, 1.550744, 0.740435, -0.626155, 2.730570, + 1.463345, 0.764114, -0.608299, 2.537561, 1.378151, 0.787028, -0.589519, 2.364323, 1.297630, + 0.807985, -0.569257, 2.207970, 1.217830, 0.830663, -0.550055, 2.076646, 1.142746, 0.850416, + -0.528812, 1.948085, 1.070757, 0.869609, -0.507478, 1.834684, 1.001282, 0.888324, -0.486131, + 1.734879, 0.934987, 0.907482, -0.464910, 1.645974, 0.871203, 0.924829, -0.442742, 1.563550, + 0.809260, 0.942958, -0.420777, 1.491264, 0.750037, 0.961999, -0.398842, 1.428069, 0.691715, + 0.981043, -0.375967, 1.369668, 0.635669, 1.002371, -0.351469, 1.318588, 0.578689, 1.025343, + -0.326601, 1.273628, 0.524424, 1.048511, -0.301395, 1.234572, 0.471403, 1.072242, -0.275835, + 1.198354, 0.419950, 1.096758, -0.250200, 1.166392, 0.370733, 1.122781, -0.224474, 1.138991, + 0.322864, 1.150871, -0.198592, 1.114313, 0.277723, 1.177319, -0.171805, 1.093534, 0.234950, + 1.201765, -0.144291, 1.077462, 0.195376, 1.222629, -0.115949, 1.063288, 0.157315, 1.237334, + -0.087140, 1.048366, 0.118843, 1.246153, -0.058094, 1.031224, 0.079207, 1.252570, -0.029194, + 1.014695, 0.039376, 1.259060, -0.000418, 0.999881, 0.000307, 0.000159, -0.000515, 5.393984, + 3.241865, 0.000505, -0.001636, 11.548038, 3.241848, 0.002016, -0.006534, 11.506640, 3.241718, + 0.004537, -0.014706, 11.513460, 3.241196, 0.008068, -0.026134, 11.510533, 3.241693, 0.012573, + -0.040676, 11.428978, 3.241030, 0.018212, -0.058794, 11.510745, 3.240924, 0.024847, -0.079926, + 11.497339, 3.240201, 0.032603, -0.104160, 11.484607, 3.238994, 0.041543, -0.131552, 11.470801, + 3.237182, 0.051738, -0.162012, 11.453219, 3.234635, 0.063313, -0.195260, 11.427244, 3.231153, + 0.076381, -0.231205, 11.388534, 3.226361, 0.091096, -0.269678, 11.340406, 3.219943, 0.107600, + -0.310170, 11.270127, 3.211448, 0.126017, -0.352435, 11.178583, 3.200168, 0.146411, -0.395551, + 11.046559, 3.185328, 0.168663, -0.438627, 10.858624, 3.165972, 0.192730, -0.480660, 10.606379, + 3.140735, 0.218497, -0.520987, 10.288093, 3.108388, 0.245752, -0.558483, 9.907480, 3.067586, + 0.273993, -0.592090, 9.453246, 3.016931, 0.303495, -0.622416, 8.966138, 2.956444, 0.333717, + -0.648303, 8.443776, 2.885116, 0.363928, -0.668640, 7.894122, 2.805963, 0.396240, -0.687748, + 7.385728, 2.718338, 0.427161, -0.699903, 6.838511, 2.622346, 0.460175, -0.711210, 6.356371, + 2.522476, 0.492593, -0.717734, 5.878312, 2.417984, 0.524449, -0.719956, 5.423285, 2.310941, + 0.556010, -0.719127, 4.997909, 2.201885, 0.587032, -0.715077, 4.600426, 2.093330, 0.617030, + -0.707574, 4.235885, 1.986585, 0.644684, -0.695781, 3.881712, 1.881279, 0.674483, -0.685313, + 3.590960, 1.777918, 0.700290, -0.669619, 3.303138, 1.678004, 0.727892, -0.654728, 3.057771, + 1.581162, 0.751694, -0.635727, 2.826642, 1.487769, 0.776271, -0.617343, 2.622178, 1.399628, + 0.799502, -0.597683, 2.441265, 1.313195, 0.821768, -0.577090, 2.276954, 1.232316, 0.841960, + -0.555165, 2.125744, 1.153914, 0.861582, -0.532983, 1.991236, 1.079598, 0.881460, -0.510933, + 1.874027, 1.008883, 0.899952, -0.488321, 1.766812, 0.940802, 0.918954, -0.466405, 1.673436, + 0.875653, 0.936130, -0.443623, 1.586986, 0.813130, 0.954799, -0.421532, 1.513558, 0.752241, + 0.972435, -0.398897, 1.445787, 0.694711, 0.990147, -0.376302, 1.384382, 0.638770, 1.009189, + -0.353623, 1.331934, 0.583826, 1.029687, -0.330635, 1.284478, 0.530476, 1.052604, -0.305698, + 1.243632, 0.477187, 1.076524, -0.279917, 1.204997, 0.425349, 1.101701, -0.253951, 1.171750, + 0.375165, 1.127264, -0.227541, 1.142519, 0.326869, 1.156397, -0.201265, 1.116817, 0.280912, + 1.183020, -0.173943, 1.095289, 0.237447, 1.208448, -0.145860, 1.078296, 0.196694, 1.230417, + -0.116901, 1.064416, 0.158409, 1.248617, -0.087507, 1.050504, 0.119483, 1.257310, -0.057353, + 1.032796, 0.079092, 1.263076, -0.027785, 1.015128, 0.038883, 1.269870, 0.001331, 0.999935, + -0.000557, 0.000154, -0.000549, 5.705205, 3.554136, 0.000506, -0.001797, 13.703335, 3.554133, + 0.002014, -0.007156, 13.614074, 3.553937, 0.004544, -0.016145, 13.657344, 3.553096, 0.008070, + -0.028652, 13.627997, 3.553894, 0.012584, -0.044617, 13.606235, 3.554000, 0.018180, -0.064288, + 13.581339, 3.549637, 0.024887, -0.087627, 13.608851, 3.552006, 0.032690, -0.114134, 13.599099, + 3.550341, 0.041705, -0.144154, 13.579829, 3.547982, 0.052035, -0.177400, 13.552845, 3.544641, + 0.063810, -0.213813, 13.515619, 3.539941, 0.077171, -0.252978, 13.460460, 3.533696, 0.092329, + -0.294852, 13.393559, 3.524977, 0.109390, -0.338688, 13.292376, 3.513655, 0.128455, -0.384018, + 13.147332, 3.498484, 0.149661, -0.429960, 12.945774, 3.478323, 0.172694, -0.475024, 12.658979, + 3.451862, 0.197650, -0.518614, 12.289564, 3.417602, 0.224156, -0.559298, 11.828307, 3.372913, + 0.252008, -0.596110, 11.285162, 3.317454, 0.281165, -0.629292, 10.684922, 3.251171, 0.311434, + -0.658379, 10.052939, 3.172222, 0.342741, -0.683455, 9.405296, 3.082825, 0.373543, -0.701674, + 8.716078, 2.983976, 0.407008, -0.719664, 8.108425, 2.876244, 0.438623, -0.729882, 7.461252, + 2.763279, 0.471872, -0.738696, 6.880182, 2.645590, 0.504700, -0.743136, 6.324308, 2.524680, + 0.537118, -0.743676, 5.808302, 2.402723, 0.569412, -0.741181, 5.332306, 2.281437, 0.598202, + -0.732348, 4.857402, 2.161401, 0.629640, -0.724832, 4.465554, 2.043872, 0.659239, -0.713435, + 4.093661, 1.930129, 0.686547, -0.698539, 3.752593, 1.817654, 0.715529, -0.684471, 3.457593, + 1.712567, 0.739456, -0.664983, 3.171220, 1.610687, 0.764892, -0.646322, 2.929674, 1.512031, + 0.789301, -0.626393, 2.710719, 1.419033, 0.809881, -0.603498, 2.506139, 1.330115, 0.833385, + -0.582934, 2.336089, 1.245859, 0.854254, -0.560419, 2.178470, 1.165042, 0.873964, -0.537294, + 2.040087, 1.086633, 0.893433, -0.514264, 1.911969, 1.015028, 0.911756, -0.490657, 1.799840, + 0.944938, 0.930894, -0.467601, 1.703188, 0.878743, 0.948078, -0.444043, 1.612092, 0.815356, + 0.966162, -0.421155, 1.534444, 0.753883, 0.984166, -0.398238, 1.462397, 0.695534, 1.002184, + -0.375278, 1.400793, 0.638806, 1.019669, -0.352159, 1.344172, 0.584549, 1.039571, -0.329651, + 1.295227, 0.531660, 1.059989, -0.306804, 1.251281, 0.480529, 1.081116, -0.283345, 1.211504, + 0.430071, 1.105742, -0.258568, 1.176400, 0.380277, 1.133080, -0.232146, 1.144519, 0.331076, + 1.161888, -0.205244, 1.118059, 0.284040, 1.192408, -0.177932, 1.097561, 0.239958, 1.221043, + -0.149532, 1.082021, 0.198751, 1.244141, -0.120046, 1.067634, 0.160114, 1.259465, -0.089542, + 1.051626, 0.121101, 1.268124, -0.058593, 1.033296, 0.079898, 1.274330, -0.028011, 1.015382, + 0.039038, 1.281590, 0.002330, 1.000087, -0.001259, 0.000149, -0.000587, 6.059834, 3.927143, + 0.000507, -0.001992, 16.560400, 3.927149, 0.002014, -0.007910, 16.406326, 3.926821, 0.004549, + -0.017856, 16.545532, 3.927027, 0.008064, -0.031632, 16.375853, 3.925487, 0.012450, -0.048749, + 15.928564, 3.928272, 0.018030, -0.070371, 16.072989, 3.917862, 0.024964, -0.096897, 16.458925, + 3.924489, 0.032807, -0.126073, 16.377851, 3.921896, 0.041917, -0.159205, 16.351561, 3.918860, + 0.052416, -0.195762, 16.307037, 3.914339, 0.064464, -0.235784, 16.255514, 3.907954, 0.078225, + -0.278812, 16.176226, 3.899254, 0.093900, -0.324457, 16.066530, 3.887455, 0.111657, -0.372174, + 15.913818, 3.871777, 0.131478, -0.420530, 15.669197, 3.850776, 0.153574, -0.469330, 15.355453, + 3.822348, 0.177505, -0.516029, 14.908978, 3.785168, 0.203383, -0.560585, 14.352687, 3.736602, + 0.230569, -0.600607, 13.666022, 3.675046, 0.259188, -0.636296, 12.900244, 3.599811, 0.289272, + -0.668312, 12.111226, 3.510550, 0.320490, -0.695986, 11.292102, 3.408535, 0.353031, -0.719848, + 10.493485, 3.295667, 0.385228, -0.737073, 9.661955, 3.171998, 0.419219, -0.752419, 8.909942, + 3.042428, 0.452096, -0.761179, 8.155107, 2.907108, 0.484909, -0.766166, 7.450609, 2.769858, + 0.518306, -0.768596, 6.811866, 2.631935, 0.550067, -0.765683, 6.205275, 2.492870, 0.582562, + -0.761197, 5.663215, 2.358645, 0.614450, -0.753834, 5.165358, 2.227377, 0.644563, -0.742860, + 4.712554, 2.097547, 0.673658, -0.729294, 4.306101, 1.974920, 0.702857, -0.714839, 3.943352, + 1.857613, 0.729350, -0.696774, 3.609432, 1.743601, 0.754958, -0.677394, 3.308389, 1.636607, + 0.779575, -0.657018, 3.043803, 1.533841, 0.800491, -0.633342, 2.793592, 1.437092, 0.825030, + -0.612471, 2.590307, 1.344272, 0.847535, -0.589882, 2.406477, 1.256436, 0.865979, -0.564850, + 2.231999, 1.173938, 0.886254, -0.541357, 2.083556, 1.094722, 0.905566, -0.517353, 1.950928, + 1.021107, 0.924607, -0.493320, 1.835979, 0.948941, 0.943365, -0.469366, 1.731417, 0.881060, + 0.960405, -0.444745, 1.635838, 0.816479, 0.977893, -0.420493, 1.552981, 0.754604, 0.996573, + -0.397150, 1.481595, 0.694917, 1.014000, -0.373483, 1.414070, 0.638445, 1.031807, -0.349985, + 1.356031, 0.584035, 1.051877, -0.327062, 1.305041, 0.530010, 1.071701, -0.304134, 1.258836, + 0.479439, 1.093109, -0.280962, 1.217297, 0.429763, 1.116681, -0.258121, 1.182063, 0.381050, + 1.143886, -0.235365, 1.150039, 0.333395, 1.175163, -0.211621, 1.125074, 0.287477, 1.203675, + -0.184061, 1.102339, 0.243301, 1.230477, -0.154815, 1.083927, 0.201826, 1.253134, -0.124513, + 1.067989, 0.162271, 1.270092, -0.093383, 1.052032, 0.122855, 1.279576, -0.061770, 1.033685, + 0.081639, 1.286472, -0.030317, 1.015583, 0.040411, 1.294476, 0.000964, 1.000206, -0.000454, + 0.000144, -0.000630, 6.467978, 4.381146, 0.000504, -0.002208, 20.193617, 4.381151, 0.002017, + -0.008834, 20.206446, 4.380687, 0.004536, -0.019864, 20.183254, 4.380550, 0.008174, -0.035759, + 20.564249, 4.381247, 0.012608, -0.055034, 20.111612, 4.382390, 0.018198, -0.079119, 20.106096, + 4.379815, 0.025057, -0.108067, 20.215635, 4.376874, 0.032962, -0.140630, 20.153549, 4.374143, + 0.042199, -0.177350, 20.084061, 4.369558, 0.052928, -0.218094, 20.026609, 4.363287, 0.065327, + -0.262407, 19.940054, 4.354386, 0.079568, -0.309833, 19.806814, 4.342127, 0.095961, -0.360074, + 19.641878, 4.325533, 0.114516, -0.411747, 19.370914, 4.302950, 0.135349, -0.463726, 18.983900, + 4.271991, 0.158293, -0.514211, 18.433926, 4.230856, 0.183348, -0.562511, 17.733471, 4.176250, + 0.209959, -0.606310, 16.864214, 4.105895, 0.238736, -0.646958, 15.935207, 4.020104, 0.268543, + -0.681574, 14.890014, 3.916094, 0.299996, -0.712458, 13.846786, 3.798239, 0.331930, -0.737130, + 12.758296, 3.664191, 0.365222, -0.758156, 11.732940, 3.521867, 0.399061, -0.774364, 10.741743, + 3.369831, 0.433480, -0.786412, 9.812527, 3.212079, 0.467002, -0.792373, 8.915130, 3.053715, + 0.500754, -0.795410, 8.094276, 2.894526, 0.534023, -0.794617, 7.342067, 2.735959, 0.566988, + -0.790689, 6.664186, 2.581160, 0.599960, -0.784433, 6.052983, 2.432318, 0.630599, -0.773378, + 5.486277, 2.287630, 0.660807, -0.760334, 4.982516, 2.150183, 0.690103, -0.745430, 4.531104, + 2.017266, 0.717315, -0.727511, 4.120734, 1.891699, 0.743819, -0.708376, 3.759599, 1.772680, + 0.770147, -0.688632, 3.441912, 1.660620, 0.793510, -0.665931, 3.152600, 1.553166, 0.816535, + -0.643045, 2.898883, 1.452080, 0.839163, -0.619917, 2.674488, 1.355544, 0.859066, -0.594923, + 2.469262, 1.267232, 0.879489, -0.570343, 2.292209, 1.181702, 0.898525, -0.544975, 2.131086, + 1.102089, 0.918359, -0.520585, 1.994526, 1.024744, 0.937502, -0.496044, 1.873079, 0.951712, + 0.955573, -0.471010, 1.761232, 0.883374, 0.972957, -0.445712, 1.661604, 0.818008, 0.991248, + -0.421201, 1.577169, 0.754446, 1.008997, -0.396444, 1.499653, 0.694518, 1.028127, -0.372362, + 1.432030, 0.637259, 1.045710, -0.347895, 1.369870, 0.581515, 1.065977, -0.324409, 1.317341, + 0.527713, 1.087469, -0.301181, 1.270447, 0.476281, 1.109943, -0.277866, 1.228398, 0.426403, + 1.134440, -0.254849, 1.190986, 0.377822, 1.160986, -0.231754, 1.157681, 0.330740, 1.188458, + -0.207973, 1.128665, 0.286014, 1.214405, -0.183424, 1.103711, 0.243600, 1.239504, -0.157972, + 1.084253, 0.203686, 1.262961, -0.130607, 1.068258, 0.165214, 1.280340, -0.099652, 1.051919, + 0.126067, 1.292129, -0.067363, 1.034016, 0.084791, 1.299876, -0.035026, 1.015775, 0.042786, + 1.308328, -0.002944, 0.999963, 0.001385, 0.000138, -0.000681, 6.943771, 4.946556, 0.000503, + -0.002486, 25.346689, 4.946532, 0.002016, -0.009973, 25.494320, 4.946311, 0.004539, -0.022440, + 25.484949, 4.945823, 0.008069, -0.039836, 25.420902, 4.945311, 0.012628, -0.062172, 25.394403, + 4.945041, 0.018294, -0.089609, 25.440279, 4.943295, 0.025079, -0.121584, 25.399988, 4.939368, + 0.033142, -0.158595, 25.356537, 4.936200, 0.042596, -0.199971, 25.295067, 4.929842, 0.053628, + -0.245624, 25.196465, 4.920586, 0.066496, -0.295240, 25.055311, 4.907700, 0.081434, -0.348006, + 24.846170, 4.889647, 0.098640, -0.403167, 24.527803, 4.864680, 0.118231, -0.459106, 24.051735, + 4.830574, 0.140139, -0.513907, 23.352467, 4.783530, 0.164198, -0.565953, 22.418245, 4.720530, + 0.190502, -0.614858, 21.324049, 4.638075, 0.218530, -0.658304, 20.038671, 4.535464, 0.248094, + -0.696133, 18.639786, 4.411646, 0.279435, -0.729388, 17.234526, 4.268872, 0.312002, -0.757534, + 15.830426, 4.109603, 0.346173, -0.781866, 14.495901, 3.938782, 0.379435, -0.797579, 13.136444, + 3.756138, 0.414945, -0.812334, 11.946491, 3.571258, 0.449991, -0.821119, 10.811908, 3.384217, + 0.484636, -0.825066, 9.763482, 3.198076, 0.518675, -0.824728, 8.796811, 3.015808, 0.552559, + -0.821710, 7.932528, 2.836886, 0.587272, -0.817478, 7.185156, 2.664995, 0.616960, -0.804441, + 6.445302, 2.502223, 0.648054, -0.792063, 5.818812, 2.345851, 0.678575, -0.777793, 5.264731, + 2.197150, 0.707287, -0.760476, 4.766033, 2.056042, 0.735851, -0.742541, 4.335871, 1.922805, + 0.760594, -0.720503, 3.928021, 1.798585, 0.784534, -0.697719, 3.579153, 1.680605, 0.811029, + -0.677036, 3.285307, 1.568942, 0.831809, -0.651479, 3.001423, 1.465496, 0.854364, -0.627376, + 2.760672, 1.367849, 0.872639, -0.600496, 2.540697, 1.275644, 0.894296, -0.576297, 2.355273, + 1.188638, 0.913123, -0.550377, 2.188563, 1.105652, 0.932025, -0.524640, 2.040739, 1.028614, + 0.949876, -0.498402, 1.910315, 0.954421, 0.968933, -0.473220, 1.795750, 0.884061, 0.985366, + -0.447086, 1.690336, 0.817765, 1.004940, -0.422394, 1.599626, 0.753295, 1.022217, -0.396726, + 1.519055, 0.693380, 1.041490, -0.371854, 1.448745, 0.635747, 1.059920, -0.346769, 1.384292, + 0.579508, 1.080408, -0.322343, 1.328798, 0.525045, 1.101632, -0.297979, 1.279898, 0.473773, + 1.124812, -0.274059, 1.234005, 0.422949, 1.148503, -0.249954, 1.195373, 0.374609, 1.174554, + -0.225988, 1.160362, 0.327350, 1.202931, -0.201932, 1.131307, 0.283494, 1.229335, -0.176886, + 1.105885, 0.241092, 1.254254, -0.151225, 1.085802, 0.201514, 1.275743, -0.124282, 1.068524, + 0.162866, 1.292929, -0.097122, 1.051493, 0.124991, 1.305805, -0.068939, 1.033890, 0.085521, + 1.314991, -0.040082, 1.015927, 0.045247, 1.324033, -0.009923, 0.999893, 0.004738, 0.000131, + -0.000745, 7.562414, 5.671075, 0.000473, -0.002681, 27.216688, 5.670949, 0.002021, -0.011462, + 32.962402, 5.670177, 0.004540, -0.025728, 33.183949, 5.670197, 0.008087, -0.045746, 33.185688, + 5.667313, 0.012673, -0.071427, 33.170441, 5.668396, 0.018358, -0.102673, 33.145138, 5.665252, + 0.025299, -0.139780, 33.303326, 5.653404, 0.033469, -0.181718, 33.107243, 5.652829, 0.043139, + -0.228698, 32.859524, 5.645676, 0.054622, -0.280648, 32.694893, 5.631547, 0.068115, -0.336524, + 32.422569, 5.611561, 0.083957, -0.395671, 32.035511, 5.583449, 0.102259, -0.456164, 31.415047, + 5.543651, 0.123021, -0.515765, 30.470440, 5.488278, 0.146127, -0.572309, 29.186451, 5.413118, + 0.171749, -0.625710, 27.653852, 5.312369, 0.199549, -0.673853, 25.902435, 5.185774, 0.229188, + -0.715905, 23.978609, 5.030582, 0.260421, -0.751533, 21.999035, 4.853484, 0.293421, -0.782309, + 20.087366, 4.656137, 0.327077, -0.806332, 18.186535, 4.443975, 0.361892, -0.825818, 16.418409, + 4.223844, 0.397146, -0.840019, 14.774344, 3.998959, 0.434169, -0.852434, 13.321097, 3.775443, + 0.469288, -0.856632, 11.929448, 3.552818, 0.504319, -0.857130, 10.675201, 3.338825, 0.540067, + -0.855903, 9.591900, 3.130547, 0.575404, -0.851565, 8.607655, 2.932930, 0.606782, -0.839818, + 7.690560, 2.743876, 0.638660, -0.827508, 6.900781, 2.565115, 0.670577, -0.814154, 6.216821, + 2.395215, 0.696718, -0.793162, 5.551886, 2.238233, 0.725990, -0.775291, 5.015406, 2.090264, + 0.754140, -0.755758, 4.546843, 1.950834, 0.775992, -0.729824, 4.094254, 1.820582, 0.802990, + -0.708909, 3.732984, 1.699191, 0.828291, -0.686483, 3.413194, 1.583805, 0.847406, -0.659162, + 3.103861, 1.478093, 0.864951, -0.631051, 2.832976, 1.378496, 0.887154, -0.606590, 2.616645, + 1.282127, 0.906337, -0.580124, 2.413988, 1.194643, 0.927184, -0.554835, 2.244380, 1.110354, + 0.943810, -0.527583, 2.081964, 1.031996, 0.963630, -0.502243, 1.948979, 0.956718, 0.979691, + -0.475006, 1.822701, 0.886957, 0.997690, -0.448815, 1.715714, 0.819006, 1.016460, -0.423044, + 1.621868, 0.754892, 1.035485, -0.397637, 1.539537, 0.693707, 1.053165, -0.371775, 1.462285, + 0.634867, 1.072394, -0.346372, 1.396193, 0.578574, 1.093397, -0.321291, 1.338344, 0.524341, + 1.115194, -0.296102, 1.287594, 0.472059, 1.137943, -0.271023, 1.240495, 0.421674, 1.164163, + -0.246367, 1.201224, 0.371963, 1.191457, -0.221414, 1.164472, 0.325040, 1.220253, -0.196228, + 1.134325, 0.280343, 1.245456, -0.169991, 1.108214, 0.238098, 1.270647, -0.143314, 1.087277, + 0.197886, 1.292124, -0.115881, 1.069397, 0.159560, 1.309091, -0.087816, 1.051426, 0.120547, + 1.321130, -0.059301, 1.032904, 0.080834, 1.332484, -0.030912, 1.015767, 0.040933, 1.342834, + -0.002172, 0.999591, 0.001185, 0.000125, -0.000830, 8.392562, 6.634228, 0.000443, -0.002936, + 29.687805, 6.634032, 0.002016, -0.013374, 45.025234, 6.633008, 0.004540, -0.030089, 45.020294, + 6.633056, 0.008092, -0.053499, 45.066029, 6.626466, 0.012710, -0.083610, 44.810101, 6.630330, + 0.018485, -0.120260, 45.216747, 6.614516, 0.025134, -0.161031, 44.674168, 6.600349, 0.033897, + -0.212161, 44.819195, 6.610186, 0.043978, -0.266661, 44.450245, 6.593605, 0.056094, -0.326582, + 44.134544, 6.570142, 0.070528, -0.390342, 43.591648, 6.536712, 0.087498, -0.456162, 42.708160, + 6.488329, 0.107138, -0.521609, 41.365093, 6.420198, 0.129461, -0.584225, 39.525822, 6.323702, + 0.154245, -0.641931, 37.186111, 6.193606, 0.181228, -0.692829, 34.478470, 6.026897, 0.210711, + -0.738440, 31.680904, 5.825769, 0.242181, -0.777397, 28.828054, 5.595428, 0.275337, -0.809980, + 26.042755, 5.342321, 0.309698, -0.835990, 23.376804, 5.073076, 0.345702, -0.858077, 20.965754, + 4.794572, 0.382135, -0.874122, 18.710079, 4.516676, 0.419871, -0.887133, 16.713011, 4.241767, + 0.455609, -0.891199, 14.819674, 3.972124, 0.492617, -0.894082, 13.187921, 3.717271, 0.528186, + -0.891270, 11.708584, 3.471719, 0.563462, -0.885719, 10.422834, 3.237760, 0.596013, -0.874241, + 9.237741, 3.019060, 0.629455, -0.862814, 8.248549, 2.813572, 0.661110, -0.848126, 7.358398, + 2.621046, 0.690314, -0.829798, 6.569392, 2.441627, 0.720589, -0.812314, 5.905934, 2.274629, + 0.745631, -0.788704, 5.276800, 2.119423, 0.771488, -0.766133, 4.752773, 1.974380, 0.798704, + -0.744726, 4.306095, 1.839482, 0.820172, -0.718062, 3.889792, 1.713244, 0.844368, -0.693972, + 3.545456, 1.594809, 0.863128, -0.665748, 3.212762, 1.487512, 0.880094, -0.637003, 2.926572, + 1.386724, 0.904252, -0.613728, 2.704260, 1.288131, 0.920506, -0.585217, 2.483164, 1.199845, + 0.940919, -0.559603, 2.300348, 1.114958, 0.957044, -0.531597, 2.130516, 1.034754, 0.972648, + -0.503583, 1.979313, 0.960912, 0.994318, -0.478813, 1.859664, 0.889786, 1.008754, -0.450943, + 1.742705, 0.820833, 1.028667, -0.425516, 1.645220, 0.756332, 1.046145, -0.398977, 1.557184, + 0.693921, 1.067212, -0.373657, 1.480814, 0.635955, 1.084111, -0.346657, 1.408762, 0.578832, + 1.106749, -0.321392, 1.350468, 0.523561, 1.128440, -0.295773, 1.294865, 0.471146, 1.151073, + -0.270028, 1.246118, 0.420298, 1.178601, -0.244816, 1.204226, 0.370575, 1.206845, -0.219027, + 1.166896, 0.323716, 1.235963, -0.192622, 1.135756, 0.278058, 1.263030, -0.165331, 1.109240, + 0.235743, 1.288937, -0.137489, 1.088379, 0.195390, 1.310681, -0.108685, 1.068987, 0.156439, + 1.334352, -0.079710, 1.054273, 0.117096, 1.344847, -0.049947, 1.034598, 0.076554, 1.354943, + -0.020272, 1.016079, 0.035585, 1.365515, 0.009170, 0.999969, -0.004771, 0.000117, -0.000935, + 9.424866, 7.979243, 0.000410, -0.003275, 33.013195, 7.979422, 0.002009, -0.016024, 64.370331, + 7.977156, 0.004541, -0.036176, 64.655952, 7.976128, 0.008109, -0.064384, 64.864494, 7.964988, + 0.012694, -0.099984, 64.487198, 7.971348, 0.018554, -0.143991, 64.637970, 7.923116, 0.025303, + -0.192040, 61.930538, 7.953975, 0.035297, -0.259442, 66.274422, 7.921861, 0.045226, -0.318370, + 63.334690, 7.909609, 0.058370, -0.388821, 62.686401, 7.864696, 0.074083, -0.461667, 61.332054, + 7.801843, 0.092537, -0.533744, 59.125607, 7.708949, 0.113781, -0.601905, 55.997845, 7.575799, + 0.137786, -0.664409, 52.177567, 7.393524, 0.164770, -0.721193, 48.019485, 7.161756, 0.193894, + -0.768842, 43.460278, 6.882018, 0.225586, -0.810332, 39.086590, 6.564607, 0.259311, -0.845096, + 34.896049, 6.221983, 0.294517, -0.872849, 30.952213, 5.865831, 0.331163, -0.895159, 27.375792, + 5.507064, 0.368964, -0.912860, 24.213310, 5.149763, 0.407255, -0.925338, 21.364958, 4.806172, + 0.444704, -0.930956, 18.791691, 4.472272, 0.482041, -0.932576, 16.521160, 4.160864, 0.519572, + -0.931547, 14.589918, 3.865206, 0.556236, -0.926554, 12.887797, 3.590445, 0.590431, -0.915839, + 11.352402, 3.332747, 0.622723, -0.901266, 10.002660, 3.093264, 0.657029, -0.888747, 8.905210, + 2.873842, 0.686164, -0.868666, 7.876704, 2.666740, 0.719168, -0.853152, 7.051816, 2.479017, + 0.742294, -0.826169, 6.226034, 2.306498, 0.770320, -0.804936, 5.590831, 2.141328, 0.792337, + -0.777772, 4.984083, 1.994663, 0.819050, -0.755478, 4.507655, 1.853950, 0.837684, -0.726072, + 4.049884, 1.725590, 0.861324, -0.701424, 3.678201, 1.606303, 0.880741, -0.673615, 3.337163, + 1.495452, 0.903335, -0.648506, 3.055720, 1.391162, 0.920311, -0.619640, 2.792068, 1.294734, + 0.935769, -0.590245, 2.554566, 1.204518, 0.956592, -0.564944, 2.366468, 1.118630, 0.972424, + -0.536842, 2.187863, 1.038323, 0.986269, -0.508020, 2.023480, 0.963803, 1.006122, -0.482411, + 1.895137, 0.890986, 1.022504, -0.455110, 1.775886, 0.820936, 1.037905, -0.427450, 1.665951, + 0.758556, 1.059281, -0.402198, 1.577363, 0.696126, 1.076613, -0.375156, 1.493391, 0.636676, + 1.097828, -0.349577, 1.421129, 0.579947, 1.116671, -0.322955, 1.355205, 0.525140, 1.140514, + -0.297406, 1.299979, 0.471460, 1.166473, -0.271786, 1.249847, 0.420473, 1.192591, -0.245461, + 1.204625, 0.371118, 1.223349, -0.219412, 1.166686, 0.322600, 1.254833, -0.192660, 1.134121, + 0.277572, 1.285808, -0.165167, 1.108617, 0.234417, 1.322015, -0.137236, 1.093841, 0.194640, + 1.342172, -0.106871, 1.074616, 0.155001, 1.357238, -0.075759, 1.053550, 0.114648, 1.367725, + -0.044279, 1.033851, 0.073254, 1.379461, -0.013001, 1.015713, 0.031895, 1.391625, 0.018075, + 1.000203, -0.009397, 0.000109, -0.001093, 10.986820, 9.992467, 0.000378, -0.003779, 37.989063, + 9.992861, 0.002028, -0.020252, 101.850441, 9.988345, 0.004557, -0.045429, 101.106750, 9.983879, + 0.008115, -0.080453, 100.646606, 9.953411, 0.012864, -0.125836, 101.366592, 9.943727, 0.018734, + -0.179350, 100.786118, 9.908408, 0.026314, -0.243680, 99.779343, 9.821631, 0.035500, -0.313552, + 98.608231, 9.782450, 0.047562, -0.394644, 97.689568, 9.845875, 0.062065, -0.476697, 95.177795, + 9.755218, 0.079552, -0.557933, 91.095581, 9.615121, 0.099905, -0.632818, 85.110382, 9.408299, + 0.123231, -0.699926, 77.948921, 9.120996, 0.149980, -0.760671, 70.491119, 8.764173, 0.179550, + -0.812251, 62.821407, 8.341752, 0.211839, -0.855909, 55.512890, 7.876337, 0.246434, -0.892023, + 48.744549, 7.386268, 0.282317, -0.919200, 42.462059, 6.886009, 0.319580, -0.940333, 36.901031, + 6.400318, 0.360135, -0.962176, 32.353752, 5.937503, 0.397805, -0.969755, 27.996445, 5.489783, + 0.437077, -0.976494, 24.359192, 5.072855, 0.474388, -0.975265, 21.124300, 4.684682, 0.513695, + -0.975335, 18.476677, 4.326597, 0.551542, -0.970264, 16.167391, 3.999049, 0.587525, -0.960365, + 14.143442, 3.696317, 0.621251, -0.945944, 12.374341, 3.414176, 0.654738, -0.930709, 10.877112, + 3.160455, 0.685794, -0.911702, 9.580887, 2.921461, 0.717135, -0.892948, 8.481939, 2.707478, + 0.740798, -0.865086, 7.435941, 2.510382, 0.770920, -0.845137, 6.650625, 2.329648, 0.792303, + -0.815956, 5.879976, 2.163206, 0.818363, -0.792225, 5.274404, 2.008042, 0.837362, -0.762396, + 4.700960, 1.867576, 0.862266, -0.738465, 4.254798, 1.735819, 0.880069, -0.708890, 3.828697, + 1.614690, 0.896021, -0.678588, 3.451655, 1.503477, 0.920156, -0.654832, 3.168722, 1.395800, + 0.934948, -0.624740, 2.879533, 1.299955, 0.949686, -0.595203, 2.628258, 1.208597, 0.970989, + -0.570041, 2.433689, 1.122310, 0.985606, -0.541116, 2.241461, 1.042168, 1.000819, -0.512835, + 2.075567, 0.966543, 1.012209, -0.483024, 1.919932, 0.895758, 1.035320, -0.459125, 1.807884, + 0.825668, 1.052077, -0.432333, 1.695689, 0.760812, 1.070459, -0.406131, 1.595491, 0.699897, + 1.088704, -0.379721, 1.508512, 0.640575, 1.103817, -0.352104, 1.428159, 0.583765, 1.131711, + -0.328122, 1.366565, 0.528240, 1.156448, -0.302568, 1.306843, 0.473988, 1.181821, -0.276487, + 1.252861, 0.422189, 1.211347, -0.250540, 1.205265, 0.372005, 1.243636, -0.224264, 1.165943, + 0.324184, 1.283038, -0.198289, 1.137772, 0.278419, 1.316722, -0.170179, 1.115057, 0.235425, + 1.342715, -0.140095, 1.092994, 0.195084, 1.363288, -0.108794, 1.071875, 0.155439, 1.380656, + -0.076774, 1.052475, 0.114636, 1.394826, -0.044509, 1.032525, 0.072890, 1.408830, -0.011968, + 1.015459, 0.031101, 1.422370, 0.020555, 0.999808, -0.011002, 0.000100, -0.001334, 13.377127, + 13.342275, 0.000342, -0.004563, 45.758434, 13.342710, 0.002026, -0.027004, 179.672058, + 13.331846, 0.004559, -0.060563, 179.294235, 13.314877, 0.008232, -0.108154, 181.242035, + 13.222856, 0.013031, -0.167590, 179.684509, 13.153860, 0.019526, -0.242041, 181.004608, + 12.986094, 0.026364, -0.309289, 159.606293, 13.247752, 0.037670, -0.409755, 179.468521, + 12.368877, 0.051804, -0.512051, 167.955582, 12.981333, 0.068214, -0.601994, 156.278793, + 12.704532, 0.088295, -0.686849, 143.096878, 12.316531, 0.111478, -0.758670, 127.423111, + 11.793048, 0.138336, -0.821348, 111.763031, 11.157992, 0.168447, -0.873616, 96.887924, + 10.447472, 0.201411, -0.916322, 83.225327, 9.696606, 0.237443, -0.953090, 71.403137, 8.949244, + 0.274234, -0.977751, 60.739277, 8.225874, 0.314566, -1.003135, 52.115578, 7.547433, 0.353932, + -1.016312, 44.341869, 6.910326, 0.393858, -1.024848, 37.827263, 6.324401, 0.433805, -1.028950, + 32.380932, 5.790555, 0.475812, -1.034084, 27.955982, 5.312826, 0.513254, -1.026743, 23.977417, + 4.866118, 0.549965, -1.016740, 20.628025, 4.468437, 0.590300, -1.012030, 18.036856, 4.105483, + 0.626420, -0.998919, 15.669224, 3.780593, 0.658897, -0.979874, 13.603898, 3.482054, 0.687252, + -0.955238, 11.788331, 3.211213, 0.718941, -0.935663, 10.355552, 2.962083, 0.749877, -0.915206, + 9.131123, 2.741382, 0.772094, -0.884837, 7.973935, 2.536501, 0.799495, -0.861214, 7.086230, + 2.347282, 0.820136, -0.830976, 6.240769, 2.179332, 0.846715, -0.807408, 5.604792, 2.018005, + 0.865176, -0.776657, 4.975034, 1.877021, 0.881100, -0.744657, 4.442767, 1.743528, 0.907637, + -0.722088, 4.035177, 1.621563, 0.922239, -0.690432, 3.633160, 1.506158, 0.936558, -0.659650, + 3.281798, 1.403606, 0.950047, -0.629105, 2.974179, 1.304276, 0.961959, -0.598277, 2.704483, + 1.213888, 0.987410, -0.576085, 2.510453, 1.125569, 0.999996, -0.546494, 2.304016, 1.045567, + 1.014127, -0.518186, 2.127867, 0.970718, 1.036275, -0.494009, 1.985804, 0.897557, 1.049695, + -0.465659, 1.845074, 0.830584, 1.064617, -0.438159, 1.725130, 0.766083, 1.077131, -0.409813, + 1.613818, 0.705101, 1.101054, -0.385632, 1.528694, 0.644828, 1.122361, -0.360045, 1.447086, + 0.587878, 1.147359, -0.335186, 1.377588, 0.532130, 1.169881, -0.309040, 1.313673, 0.478843, + 1.200554, -0.284590, 1.257256, 0.426855, 1.232047, -0.259332, 1.208431, 0.376125, 1.275402, + -0.235215, 1.174692, 0.326614, 1.306595, -0.207508, 1.141042, 0.281524, 1.334304, -0.178290, + 1.111778, 0.238694, 1.364678, -0.148530, 1.090976, 0.198549, 1.387168, -0.117114, 1.069308, + 0.158529, 1.408657, -0.084977, 1.050625, 0.118042, 1.426214, -0.052052, 1.031444, 0.076541, + 1.444257, -0.018653, 1.014298, 0.034061, 1.460618, 0.015206, 0.999413, -0.008132, 0.000100, + -0.002003, 20.052612, 20.032721, 0.000297, -0.005947, 59.540512, 20.033842, 0.002022, + -0.040439, 404.848511, 20.032743, 0.004588, -0.090999, 403.741241, 19.910591, 0.008769, + -0.169802, 441.471558, 19.572552, 0.013708, -0.253629, 411.667816, 19.145721, 0.020331, + -0.349396, 371.322571, 18.591049, 0.030259, -0.468121, 385.816498, 18.331083, 0.045190, + -0.611444, 391.924133, 15.807686, 0.058476, -0.676875, 319.638641, 16.947781, 0.079894, + -0.781421, 278.804260, 17.512903, 0.103871, -0.855116, 235.999786, 16.290295, 0.131756, + -0.915747, 197.168076, 14.956566, 0.163487, -0.966333, 163.452347, 13.608010, 0.198693, + -1.008386, 135.632706, 12.299661, 0.236157, -1.039862, 111.919281, 11.088790, 0.274579, + -1.059988, 92.136581, 9.983883, 0.317164, -1.084069, 77.063034, 9.008505, 0.357624, -1.092124, + 63.963051, 8.127298, 0.399009, -1.097560, 53.483341, 7.347628, 0.441182, -1.100981, 45.052429, + 6.658191, 0.481606, -1.097318, 37.932640, 6.047333, 0.524253, -1.096570, 32.395638, 5.505878, + 0.564351, -1.088739, 27.679380, 5.018494, 0.600843, -1.073396, 23.611519, 4.580770, 0.635527, + -1.055024, 20.207081, 4.194785, 0.672045, -1.039775, 17.469036, 3.847436, 0.698372, -1.009545, + 14.928226, 3.532546, 0.729336, -0.987168, 12.953170, 3.248834, 0.761147, -0.966299, 11.346271, + 2.994166, 0.782270, -0.932841, 9.813129, 2.762244, 0.811832, -0.910431, 8.672224, 2.549933, + 0.832053, -0.878369, 7.578633, 2.363132, 0.849383, -0.844673, 6.648379, 2.189266, 0.866020, + -0.811703, 5.850784, 2.031716, 0.893083, -0.789181, 5.273372, 1.884480, 0.909212, -0.757541, + 4.700618, 1.750298, 0.923169, -0.725157, 4.196640, 1.627590, 0.937112, -0.693769, 3.764841, + 1.514906, 0.961901, -0.670828, 3.444598, 1.406839, 0.975245, -0.640240, 3.120745, 1.307873, + 0.989696, -0.611032, 2.840732, 1.216417, 1.002057, -0.581144, 2.591596, 1.132553, 1.014022, + -0.551620, 2.373820, 1.051695, 1.025307, -0.522268, 2.177992, 0.977500, 1.052190, -0.500826, + 2.042511, 0.904301, 1.064408, -0.472355, 1.891934, 0.837557, 1.077876, -0.444815, 1.761054, + 0.773004, 1.088939, -0.416531, 1.638939, 0.713958, 1.118551, -0.395057, 1.555724, 0.652485, + 1.134469, -0.368289, 1.465490, 0.596330, 1.162778, -0.345095, 1.390977, 0.539703, 1.185298, + -0.319527, 1.321225, 0.486250, 1.208419, -0.293590, 1.259318, 0.434178, 1.261013, -0.273471, + 1.219767, 0.382032, 1.297811, -0.248226, 1.176422, 0.334190, 1.326591, -0.220354, 1.139881, + 0.289075, 1.357918, -0.191937, 1.111418, 0.246259, 1.387590, -0.162282, 1.086511, 0.205129, + 1.415797, -0.131515, 1.067072, 0.165601, 1.440194, -0.099555, 1.047799, 0.125462, 1.465600, + -0.066957, 1.030406, 0.084082, 1.487714, -0.033496, 1.013889, 0.041981, 1.509947, 0.000663, + 0.998773, -0.000485, 0.000100, -0.004009, 40.102047, 40.087105, 0.000228, -0.009141, 91.431366, + 40.074432, 0.001522, -0.060544, 605.651733, 39.918827, 0.004919, -0.188871, 1712.982300, + 38.873421, 0.009053, -0.320325, 1583.453125, 39.715633, 0.015375, -0.471415, 1486.033691, + 39.162876, 0.029306, -0.735111, 1751.701050, 28.083200, 0.043450, -0.859759, 1392.475220, + 24.599945, 0.079075, -1.220033, 1629.972656, 18.507019, 0.090130, -1.091255, 940.347351, + 17.961655, 0.098008, -0.945965, 425.901093, 24.478010, 0.138246, -1.084105, 416.823944, + 20.003433, 0.174489, -1.133148, 302.730042, 18.550846, 0.207969, -1.138483, 242.853577, + 15.923334, 0.249132, -1.168197, 191.649445, 13.940813, 0.291391, -1.187038, 152.910309, + 12.263267, 0.332856, -1.192793, 121.905075, 10.822873, 0.377473, -1.202846, 99.145561, + 9.618412, 0.422601, -1.208871, 81.343315, 8.591735, 0.465276, -1.204545, 66.742569, 7.692911, + 0.504710, -1.190839, 54.787876, 6.915612, 0.544909, -1.178827, 45.507313, 6.242786, 0.582125, + -1.160590, 37.819912, 5.651690, 0.620694, -1.145481, 31.926588, 5.123660, 0.659127, -1.130178, + 27.147310, 4.669475, 0.684358, -1.093728, 22.650702, 4.258717, 0.719453, -1.074591, 19.454103, + 3.901225, 0.751695, -1.051678, 16.735672, 3.576870, 0.775082, -1.017716, 14.281039, 3.287471, + 0.796233, -0.982759, 12.261332, 3.023708, 0.827404, -0.961227, 10.767912, 2.787740, 0.848149, + -0.928433, 9.371350, 2.570737, 0.864891, -0.892838, 8.142364, 2.379204, 0.880979, -0.858193, + 7.118954, 2.204470, 0.910434, -0.837281, 6.389041, 2.041554, 0.925396, -0.803638, 5.643217, + 1.893353, 0.942463, -0.772925, 5.031223, 1.757331, 0.955217, -0.739720, 4.486978, 1.633572, + 0.968570, -0.708048, 4.014621, 1.520414, 0.981672, -0.677109, 3.617768, 1.412506, 0.992829, + -0.645712, 3.258773, 1.317079, 1.021270, -0.625746, 3.006640, 1.222611, 1.031247, -0.594628, + 2.733073, 1.137911, 1.043581, -0.565540, 2.498495, 1.058439, 1.055930, -0.536962, 2.289843, + 0.984428, 1.066727, -0.508076, 2.108603, 0.912794, 1.081225, -0.481297, 1.951454, 0.845536, + 1.088198, -0.451563, 1.801891, 0.782718, 1.123316, -0.433247, 1.704316, 0.721664, 1.133206, + -0.404812, 1.586153, 0.662761, 1.152889, -0.379901, 1.490958, 0.606866, 1.188158, -0.359421, + 1.415730, 0.550666, 1.217064, -0.336049, 1.344172, 0.496748, 1.257727, -0.314816, 1.283196, + 0.443538, 1.286647, -0.289530, 1.225903, 0.394018, 1.308729, -0.262053, 1.173928, 0.346255, + 1.351453, -0.237704, 1.139992, 0.300393, 1.380284, -0.209733, 1.105997, 0.256661, 1.414621, + -0.181613, 1.082109, 0.215429, 1.453045, -0.152797, 1.063853, 0.177098, 1.481066, -0.121803, + 1.043185, 0.137203, 1.514113, -0.090250, 1.027072, 0.096998, 1.547317, -0.057603, 1.012551, + 0.055328, 1.577983, -0.023799, 0.999267, 0.013094, 0.000108, -0.124970, 1249.704346, + 1249.703491, 0.000140, -0.119585, 1195.855469, 1195.854370, 0.003995, -0.927433, 9274.246094, + 232.443573, 0.012013, -1.131580, 11315.999023, 98.211105, 0.023892, -1.216018, 12162.739258, + 67.214500, 0.047506, -1.517865, 15186.294922, 42.410069, 0.082523, -1.812564, 18145.718750, + 24.421545, 0.112452, -1.805072, 11112.966797, 18.450365, 0.164460, -2.016784, 8086.032715, + 14.043465, 0.195870, -1.898199, 4245.658203, 13.178202, 0.197797, -1.556158, 1315.561768, + 30.760096, 0.219540, -1.433455, 802.380371, 25.037956, 0.268696, -1.483235, 579.715515, + 20.975695, 0.265968, -1.261051, 386.583649, 12.017023, 0.325369, -1.343349, 316.795959, + 12.612406, 0.387968, -1.411606, 232.491623, 13.296940, 0.435543, -1.411236, 181.515228, + 11.646996, 0.482729, -1.405722, 143.425354, 10.265131, 0.531742, -1.402782, 114.920082, + 9.114828, 0.559383, -1.346165, 88.589005, 8.089214, 0.607851, -1.342407, 73.056610, 7.249064, + 0.656928, -1.338238, 60.826897, 6.531094, 0.681212, -1.285692, 48.727219, 5.868711, 0.729238, + -1.279951, 41.256016, 5.324553, 0.751172, -1.230045, 33.728260, 4.816513, 0.773107, -1.184288, + 27.913816, 4.377203, 0.815726, -1.171653, 24.065962, 3.999965, 0.837886, -1.130636, 20.254860, + 3.658493, 0.857674, -1.089071, 17.138168, 3.347930, 0.876120, -1.048303, 14.572968, 3.072666, + 0.893935, -1.009040, 12.496377, 2.825165, 0.927998, -0.989064, 11.040731, 2.605520, 0.928445, + -0.935017, 9.365102, 2.401481, 0.945279, -0.899993, 8.177711, 2.222282, 0.959378, -0.863854, + 7.155303, 2.059342, 0.971761, -0.827684, 6.284632, 1.909314, 0.987812, -0.795878, 5.583837, + 1.771094, 1.001958, -0.763540, 4.962345, 1.645968, 1.014357, -0.730897, 4.435898, 1.527438, + 1.025946, -0.698675, 3.973241, 1.421337, 1.036435, -0.666662, 3.568025, 1.323677, 1.046807, + -0.635466, 3.218647, 1.232678, 1.052974, -0.602660, 2.902273, 1.147675, 1.086089, -0.585364, + 2.694939, 1.068352, 1.094660, -0.554784, 2.454491, 0.993445, 1.117131, -0.531500, 2.270746, + 0.923758, 1.114009, -0.496581, 2.063934, 0.858381, 1.137328, -0.473914, 1.917990, 0.794980, + 1.158671, -0.450127, 1.786523, 0.735697, 1.177878, -0.425306, 1.662454, 0.677498, 1.207510, + -0.403797, 1.559058, 0.621762, 1.244496, -0.383812, 1.466801, 0.566190, 1.240412, -0.351080, + 1.366853, 0.514288, 1.321257, -0.341200, 1.309808, 0.464621, 1.336512, -0.312710, 1.241822, + 0.413228, 1.365047, -0.286935, 1.186612, 0.366092, 1.418984, -0.265184, 1.152120, 0.321528, + 1.388864, -0.227750, 1.089937, 0.271827, 1.464383, -0.207168, 1.077271, 0.232838, 1.473125, + -0.175770, 1.041835, 0.193289, 1.542908, -0.150424, 1.036794, 0.156153, 1.563005, -0.118748, + 1.013029, 0.114866, 1.637048, -0.089604, 1.013493, 0.076804, 1.670777, -0.056398, 0.999208, + 0.032691, +}; +static float ltc_mag_ggx[64 * 64] = { + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 0.999995, 0.999990, 0.999971, 0.999937, 0.999853, 0.999670, + 0.999138, 0.996746, 0.979578, 0.979309, 0.978836, 0.977972, 0.976223, 0.972205, 0.962466, + 0.953919, 0.949829, 0.942492, 0.929870, 0.921319, 0.911112, 0.896015, 0.885105, 0.869971, + 0.855017, 0.838328, 0.821241, 0.802352, 0.783873, 0.763309, 0.743058, 0.721929, 0.699755, + 0.677721, 0.655456, 0.632681, 0.609629, 0.586831, 0.564287, 0.541772, 0.519428, 0.497353, + 0.475624, 0.454606, 0.434099, 0.414085, 0.394605, 0.375698, 0.357386, 0.339871, 0.323085, + 0.306905, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 0.999999, 0.999999, 0.999998, 0.999995, 0.999990, 0.999980, 0.999959, 0.999923, 0.999842, + 0.999660, 0.999119, 0.996613, 0.981824, 0.979298, 0.978826, 0.977957, 0.976184, 0.972091, + 0.962188, 0.953875, 0.949746, 0.942335, 0.930166, 0.921211, 0.910927, 0.896979, 0.884940, + 0.869864, 0.854835, 0.838200, 0.821049, 0.802552, 0.783659, 0.763512, 0.742927, 0.721715, + 0.699938, 0.677775, 0.655246, 0.632555, 0.609805, 0.586996, 0.564225, 0.541606, 0.519346, + 0.497419, 0.475863, 0.454738, 0.434099, 0.414003, 0.394547, 0.375747, 0.357564, 0.340012, + 0.323099, 0.306861, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 0.999999, 0.999998, 0.999995, 0.999991, 0.999979, 0.999959, 0.999917, + 0.999839, 0.999648, 0.999074, 0.996168, 0.983770, 0.979279, 0.978800, 0.977905, 0.976058, + 0.971727, 0.962120, 0.953901, 0.949485, 0.941859, 0.930911, 0.920853, 0.910394, 0.897600, + 0.884427, 0.870101, 0.854522, 0.838325, 0.820754, 0.802707, 0.783223, 0.763605, 0.742872, + 0.721565, 0.699935, 0.677726, 0.655242, 0.632580, 0.609766, 0.586946, 0.564275, 0.541759, + 0.519467, 0.497478, 0.475886, 0.454794, 0.434233, 0.414207, 0.394751, 0.375892, 0.357683, + 0.340146, 0.323287, 0.307095, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 0.999999, 0.999999, 0.999998, 0.999996, 0.999992, 0.999987, 0.999975, 0.999953, + 0.999913, 0.999830, 0.999630, 0.998993, 0.995279, 0.985142, 0.979252, 0.978754, 0.977821, + 0.975838, 0.971088, 0.962563, 0.954785, 0.949048, 0.941052, 0.931420, 0.920812, 0.909750, + 0.897867, 0.883856, 0.870091, 0.854353, 0.838166, 0.820661, 0.802465, 0.783308, 0.763346, + 0.742734, 0.721608, 0.699747, 0.677626, 0.655245, 0.632547, 0.609793, 0.587044, 0.564340, + 0.541779, 0.519529, 0.497633, 0.476114, 0.455030, 0.434430, 0.414406, 0.394974, 0.376154, + 0.357979, 0.340443, 0.323572, 0.307379, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 0.999998, 0.999998, 0.999996, 0.999991, 0.999984, 0.999970, + 0.999946, 0.999905, 0.999815, 0.999599, 0.998856, 0.993704, 0.986135, 0.979212, 0.978690, + 0.977691, 0.975504, 0.970133, 0.962951, 0.955649, 0.948405, 0.940418, 0.931660, 0.920881, + 0.909376, 0.897785, 0.883844, 0.869756, 0.854326, 0.837732, 0.820617, 0.802053, 0.783195, + 0.763119, 0.742610, 0.721344, 0.699709, 0.677624, 0.655114, 0.632523, 0.609812, 0.587052, + 0.564417, 0.541966, 0.519751, 0.497824, 0.476309, 0.455271, 0.434735, 0.414736, 0.395317, + 0.376524, 0.358364, 0.340852, 0.323988, 0.307786, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 0.999999, 0.999999, 0.999997, 0.999996, 0.999994, 0.999989, 0.999980, + 0.999965, 0.999940, 0.999895, 0.999796, 0.999559, 0.998638, 0.992774, 0.986878, 0.980297, + 0.978602, 0.977514, 0.975026, 0.969169, 0.963214, 0.956267, 0.947689, 0.940054, 0.931637, + 0.920678, 0.908990, 0.897349, 0.883905, 0.869139, 0.854177, 0.837476, 0.820295, 0.801977, + 0.782798, 0.762978, 0.742418, 0.721193, 0.699560, 0.677402, 0.655108, 0.632543, 0.609804, + 0.587158, 0.564557, 0.542096, 0.519908, 0.498088, 0.476632, 0.455623, 0.435104, 0.415161, + 0.395783, 0.377005, 0.358843, 0.341345, 0.324529, 0.308355, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 0.999999, 0.999999, 0.999998, 0.999997, 0.999992, 0.999991, 0.999985, + 0.999977, 0.999959, 0.999935, 0.999878, 0.999773, 0.999505, 0.998284, 0.992353, 0.987457, + 0.981665, 0.978492, 0.977277, 0.974360, 0.968716, 0.963373, 0.956629, 0.947397, 0.939657, + 0.931339, 0.920588, 0.908975, 0.896712, 0.883763, 0.868890, 0.853731, 0.837333, 0.819702, + 0.801738, 0.782454, 0.762712, 0.742024, 0.721037, 0.699325, 0.677359, 0.655030, 0.632439, + 0.609869, 0.587221, 0.564663, 0.542328, 0.520220, 0.498400, 0.476997, 0.456053, 0.435593, + 0.415658, 0.396300, 0.377577, 0.359473, 0.342004, 0.325170, 0.308997, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999998, 0.999996, 0.999993, 0.999988, + 0.999981, 0.999971, 0.999951, 0.999921, 0.999863, 0.999748, 0.999433, 0.997681, 0.992120, + 0.987920, 0.982864, 0.978353, 0.976961, 0.973451, 0.968396, 0.963400, 0.956680, 0.947529, + 0.939151, 0.930747, 0.920511, 0.908867, 0.896142, 0.883335, 0.868764, 0.853025, 0.837015, + 0.819452, 0.801249, 0.782176, 0.762345, 0.741843, 0.720721, 0.699135, 0.677194, 0.654889, + 0.632487, 0.609902, 0.587328, 0.564891, 0.542567, 0.520501, 0.498793, 0.477442, 0.456528, + 0.436131, 0.416273, 0.396980, 0.378276, 0.360176, 0.342738, 0.325950, 0.309803, 1.000000, + 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999999, 0.999997, 0.999995, 0.999991, + 0.999985, 0.999978, 0.999963, 0.999942, 0.999907, 0.999844, 0.999715, 0.999332, 0.996612, + 0.991974, 0.988297, 0.983843, 0.978349, 0.976540, 0.972351, 0.968109, 0.963280, 0.956464, + 0.947779, 0.938754, 0.929952, 0.920253, 0.908530, 0.895785, 0.882679, 0.868456, 0.852669, + 0.836406, 0.819138, 0.800708, 0.781803, 0.761855, 0.741534, 0.720405, 0.698959, 0.676964, + 0.654827, 0.632411, 0.609922, 0.587477, 0.565051, 0.542829, 0.520889, 0.499225, 0.477951, + 0.457148, 0.436792, 0.416963, 0.397723, 0.379068, 0.361025, 0.343608, 0.326842, 0.310718, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999995, 0.999994, + 0.999990, 0.999983, 0.999971, 0.999954, 0.999932, 0.999892, 0.999820, 0.999675, 0.999190, + 0.995492, 0.991911, 0.988610, 0.984662, 0.979221, 0.975975, 0.971671, 0.967788, 0.963002, + 0.955938, 0.947965, 0.938692, 0.929309, 0.919781, 0.908268, 0.895518, 0.882022, 0.867884, + 0.852346, 0.835746, 0.818607, 0.800261, 0.781335, 0.761539, 0.741063, 0.720116, 0.698617, + 0.676815, 0.654700, 0.632389, 0.610037, 0.587591, 0.565328, 0.543205, 0.521293, 0.499745, + 0.478562, 0.457776, 0.437515, 0.417776, 0.398586, 0.379963, 0.361984, 0.344616, 0.327857, + 0.311751, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999997, 0.999996, + 0.999992, 0.999986, 0.999977, 0.999965, 0.999947, 0.999916, 0.999873, 0.999794, 0.999628, + 0.998966, 0.994914, 0.991849, 0.988873, 0.985288, 0.980170, 0.975207, 0.971156, 0.967476, + 0.962538, 0.955601, 0.947978, 0.938542, 0.928618, 0.919056, 0.907890, 0.895098, 0.881352, + 0.867263, 0.851806, 0.835168, 0.818003, 0.799785, 0.780633, 0.761080, 0.740618, 0.719795, + 0.698332, 0.676629, 0.654544, 0.632411, 0.610042, 0.587805, 0.565593, 0.543549, 0.521793, + 0.500309, 0.479195, 0.458546, 0.438353, 0.418669, 0.399557, 0.381012, 0.363049, 0.345710, + 0.329006, 0.312948, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999997, + 0.999993, 0.999990, 0.999984, 0.999972, 0.999960, 0.999939, 0.999906, 0.999853, 0.999765, + 0.999567, 0.998603, 0.994519, 0.991794, 0.989089, 0.985781, 0.980956, 0.974161, 0.970688, + 0.967064, 0.961890, 0.955292, 0.947848, 0.938359, 0.928226, 0.918214, 0.907361, 0.894702, + 0.880834, 0.866500, 0.851209, 0.834627, 0.817211, 0.799250, 0.780131, 0.760512, 0.740218, + 0.719264, 0.698063, 0.676325, 0.654450, 0.632316, 0.610170, 0.587988, 0.565891, 0.544013, + 0.522305, 0.500958, 0.479971, 0.459376, 0.439271, 0.419699, 0.400620, 0.382126, 0.364246, + 0.346967, 0.330273, 0.314236, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, + 0.999996, 0.999994, 0.999988, 0.999979, 0.999967, 0.999952, 0.999924, 0.999888, 0.999833, + 0.999733, 0.999490, 0.997946, 0.994192, 0.991812, 0.989274, 0.986224, 0.981547, 0.974000, + 0.970269, 0.966545, 0.961031, 0.954921, 0.947416, 0.938226, 0.928003, 0.917390, 0.906553, + 0.894191, 0.880329, 0.865540, 0.850476, 0.834058, 0.816467, 0.798509, 0.779561, 0.759828, + 0.739738, 0.718878, 0.697718, 0.676138, 0.654342, 0.632317, 0.610292, 0.588207, 0.566289, + 0.544443, 0.522927, 0.501674, 0.480765, 0.460314, 0.440304, 0.420782, 0.401824, 0.383410, + 0.365538, 0.348312, 0.331692, 0.315688, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, + 0.999998, 0.999996, 0.999993, 0.999985, 0.999976, 0.999961, 0.999943, 0.999913, 0.999872, + 0.999807, 0.999691, 0.999390, 0.996859, 0.994003, 0.991808, 0.989423, 0.986523, 0.981783, + 0.974511, 0.969791, 0.965933, 0.960377, 0.954434, 0.946803, 0.938026, 0.927620, 0.916545, + 0.905639, 0.893489, 0.879820, 0.864852, 0.849513, 0.833311, 0.815878, 0.797621, 0.778938, + 0.759253, 0.739142, 0.718479, 0.697274, 0.675902, 0.654135, 0.632357, 0.610364, 0.588497, + 0.566631, 0.545012, 0.523579, 0.502429, 0.481680, 0.461304, 0.441425, 0.422039, 0.403135, + 0.384779, 0.366976, 0.349796, 0.333231, 0.317277, 1.000000, 1.000000, 1.000000, 1.000000, + 0.999999, 0.999998, 0.999996, 0.999991, 0.999983, 0.999974, 0.999956, 0.999932, 0.999901, + 0.999852, 0.999780, 0.999646, 0.999248, 0.996193, 0.993784, 0.991782, 0.989539, 0.986694, + 0.981765, 0.975135, 0.969309, 0.965128, 0.959788, 0.953831, 0.946255, 0.937664, 0.927351, + 0.916044, 0.904715, 0.892528, 0.879111, 0.864256, 0.848452, 0.832434, 0.815129, 0.796806, + 0.778118, 0.758668, 0.738466, 0.718024, 0.696958, 0.675642, 0.654067, 0.632325, 0.610546, + 0.588786, 0.567123, 0.545617, 0.524312, 0.503348, 0.482637, 0.462418, 0.442657, 0.423338, + 0.404564, 0.386277, 0.368545, 0.351448, 0.334906, 0.318961, 1.000000, 1.000000, 1.000000, + 0.999999, 0.999999, 0.999998, 0.999994, 0.999989, 0.999979, 0.999968, 0.999949, 0.999921, + 0.999886, 0.999833, 0.999747, 0.999596, 0.999029, 0.995749, 0.993677, 0.991724, 0.989620, + 0.986723, 0.981515, 0.975767, 0.969056, 0.964124, 0.959142, 0.953036, 0.945650, 0.937022, + 0.926971, 0.915515, 0.903584, 0.891603, 0.878212, 0.863472, 0.847652, 0.831398, 0.814299, + 0.796105, 0.777231, 0.757977, 0.737895, 0.717415, 0.696595, 0.675317, 0.653980, 0.632343, + 0.610735, 0.589076, 0.567620, 0.546251, 0.525165, 0.504255, 0.483759, 0.463666, 0.443987, + 0.424783, 0.406042, 0.387891, 0.370293, 0.353221, 0.336715, 0.320806, 1.000000, 1.000000, + 1.000000, 0.999999, 0.999998, 0.999998, 0.999993, 0.999987, 0.999977, 0.999964, 0.999943, + 0.999911, 0.999867, 0.999807, 0.999714, 0.999531, 0.998645, 0.995399, 0.993512, 0.991717, + 0.989661, 0.986652, 0.981559, 0.976183, 0.969411, 0.963317, 0.958457, 0.952091, 0.944951, + 0.936307, 0.926454, 0.915043, 0.902668, 0.890462, 0.877245, 0.862672, 0.846823, 0.830201, + 0.813293, 0.795306, 0.776393, 0.757199, 0.737324, 0.716808, 0.696187, 0.675094, 0.653814, + 0.632453, 0.610885, 0.589483, 0.568099, 0.546975, 0.525953, 0.505268, 0.484936, 0.464988, + 0.445458, 0.426314, 0.407750, 0.389670, 0.372098, 0.355105, 0.338682, 0.322825, 1.000000, + 1.000000, 1.000000, 1.000000, 0.999999, 0.999996, 0.999992, 0.999983, 0.999976, 0.999959, + 0.999933, 0.999898, 0.999849, 0.999780, 0.999676, 0.999454, 0.997884, 0.995166, 0.993394, + 0.991723, 0.989654, 0.986389, 0.981632, 0.976607, 0.969701, 0.962555, 0.957605, 0.951232, + 0.944099, 0.935556, 0.925699, 0.914492, 0.902027, 0.889116, 0.876093, 0.861649, 0.845956, + 0.829238, 0.812220, 0.794420, 0.775657, 0.756265, 0.736673, 0.716372, 0.695669, 0.674886, + 0.653728, 0.632568, 0.611217, 0.589929, 0.568783, 0.547752, 0.526931, 0.506425, 0.486238, + 0.466425, 0.446945, 0.428026, 0.409536, 0.391551, 0.374087, 0.357155, 0.340787, 0.324974, + 1.000000, 1.000000, 1.000000, 1.000000, 0.999998, 0.999996, 0.999990, 0.999984, 0.999970, + 0.999952, 0.999925, 0.999886, 0.999831, 0.999757, 0.999633, 0.999356, 0.997017, 0.994868, + 0.993337, 0.991710, 0.989580, 0.985848, 0.981640, 0.976711, 0.969755, 0.962166, 0.956609, + 0.950365, 0.943026, 0.934693, 0.924880, 0.913729, 0.901350, 0.887966, 0.874726, 0.860474, + 0.844905, 0.828269, 0.810905, 0.793364, 0.774812, 0.755478, 0.735886, 0.715847, 0.695231, + 0.674537, 0.653667, 0.632527, 0.611475, 0.590363, 0.569462, 0.548571, 0.527976, 0.507634, + 0.487632, 0.467901, 0.448680, 0.429833, 0.411467, 0.393568, 0.376197, 0.359374, 0.343034, + 0.327273, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999993, 0.999989, 0.999980, + 0.999965, 0.999945, 0.999913, 0.999869, 0.999810, 0.999723, 0.999583, 0.999213, 0.996540, + 0.994740, 0.993244, 0.991671, 0.989411, 0.985533, 0.981616, 0.976847, 0.969968, 0.962315, + 0.955468, 0.949420, 0.942016, 0.933617, 0.923949, 0.912899, 0.900495, 0.887022, 0.873283, + 0.859153, 0.843830, 0.827325, 0.809888, 0.792172, 0.773832, 0.754686, 0.735035, 0.715297, + 0.694955, 0.674242, 0.653660, 0.632752, 0.611804, 0.590993, 0.570154, 0.549539, 0.529087, + 0.508974, 0.489030, 0.469599, 0.450466, 0.431761, 0.413508, 0.395761, 0.378480, 0.361679, + 0.345465, 0.329752, 1.000000, 1.000000, 1.000000, 1.000000, 0.999997, 0.999994, 0.999987, + 0.999978, 0.999961, 0.999936, 0.999903, 0.999855, 0.999786, 0.999689, 0.999527, 0.998988, + 0.996137, 0.994527, 0.993108, 0.991599, 0.989084, 0.985308, 0.981527, 0.976677, 0.970079, + 0.962535, 0.954490, 0.948271, 0.940942, 0.932422, 0.922836, 0.911896, 0.899632, 0.886118, + 0.871864, 0.857719, 0.842536, 0.826163, 0.808849, 0.790860, 0.772802, 0.753860, 0.734335, + 0.714582, 0.694543, 0.674071, 0.653544, 0.632922, 0.612153, 0.591573, 0.570951, 0.550520, + 0.530352, 0.510311, 0.490707, 0.471359, 0.452396, 0.433837, 0.415736, 0.398052, 0.380874, + 0.364232, 0.348023, 0.332368, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999994, + 0.999988, 0.999976, 0.999957, 0.999928, 0.999891, 0.999837, 0.999759, 0.999650, 0.999463, + 0.998551, 0.995879, 0.994366, 0.992964, 0.991479, 0.988521, 0.985101, 0.981482, 0.976168, + 0.970242, 0.962585, 0.953950, 0.946973, 0.939686, 0.931248, 0.921614, 0.910765, 0.898617, + 0.885183, 0.870772, 0.856138, 0.841120, 0.824962, 0.807732, 0.789813, 0.771638, 0.753008, + 0.733686, 0.713927, 0.694082, 0.673967, 0.653549, 0.633135, 0.612702, 0.592200, 0.571904, + 0.551679, 0.531678, 0.511898, 0.492437, 0.473239, 0.454451, 0.436067, 0.418054, 0.400542, + 0.383486, 0.366848, 0.350781, 0.335182, 1.000000, 1.000000, 1.000000, 0.999999, 0.999997, + 0.999993, 0.999985, 0.999972, 0.999951, 0.999919, 0.999877, 0.999817, 0.999733, 0.999608, + 0.999380, 0.997685, 0.995603, 0.994264, 0.992911, 0.991287, 0.987923, 0.984871, 0.981239, + 0.975933, 0.970149, 0.962511, 0.953824, 0.945699, 0.938285, 0.929907, 0.920343, 0.909537, + 0.897435, 0.884056, 0.869626, 0.854490, 0.839459, 0.823511, 0.806511, 0.788752, 0.770440, + 0.751995, 0.732962, 0.713424, 0.693525, 0.673798, 0.653622, 0.633301, 0.613224, 0.592938, + 0.572833, 0.552904, 0.533030, 0.513556, 0.494215, 0.475279, 0.456673, 0.438411, 0.420583, + 0.403178, 0.386178, 0.369728, 0.353688, 0.338147, 1.000000, 1.000000, 1.000000, 0.999999, + 0.999997, 0.999991, 0.999984, 0.999967, 0.999944, 0.999912, 0.999863, 0.999796, 0.999703, + 0.999563, 0.999279, 0.997104, 0.995394, 0.994111, 0.992825, 0.990979, 0.987529, 0.984661, + 0.980774, 0.975758, 0.969866, 0.962465, 0.953678, 0.944489, 0.936886, 0.928356, 0.918820, + 0.908073, 0.896092, 0.882833, 0.868463, 0.853212, 0.837744, 0.822048, 0.805333, 0.787643, + 0.769414, 0.750830, 0.732178, 0.712972, 0.693227, 0.673569, 0.653744, 0.633739, 0.613735, + 0.593822, 0.573916, 0.554158, 0.534652, 0.515248, 0.496233, 0.477436, 0.459009, 0.440929, + 0.423259, 0.405951, 0.389136, 0.372690, 0.356789, 0.341329, 1.000000, 1.000000, 1.000000, + 0.999999, 0.999996, 0.999991, 0.999981, 0.999966, 0.999939, 0.999903, 0.999847, 0.999771, + 0.999666, 0.999510, 0.999131, 0.996690, 0.995147, 0.993882, 0.992696, 0.990474, 0.987227, + 0.984334, 0.980153, 0.975438, 0.969406, 0.962238, 0.953598, 0.943868, 0.935356, 0.926721, + 0.917122, 0.906430, 0.894550, 0.881354, 0.867131, 0.851954, 0.835972, 0.820331, 0.803911, + 0.786452, 0.768420, 0.749821, 0.731298, 0.712393, 0.692979, 0.673418, 0.653859, 0.634232, + 0.614327, 0.594732, 0.575131, 0.555584, 0.536346, 0.517175, 0.498323, 0.479744, 0.461485, + 0.443645, 0.426061, 0.408969, 0.392155, 0.375921, 0.360060, 0.344677, 1.000000, 1.000000, + 1.000000, 0.999999, 0.999997, 0.999991, 0.999979, 0.999960, 0.999931, 0.999891, 0.999832, + 0.999748, 0.999629, 0.999449, 0.998880, 0.996305, 0.995024, 0.993812, 0.992508, 0.989721, + 0.986936, 0.983936, 0.979629, 0.974979, 0.968928, 0.961970, 0.953291, 0.943458, 0.933644, + 0.925007, 0.915388, 0.904755, 0.892932, 0.879831, 0.865794, 0.850672, 0.834591, 0.818398, + 0.802304, 0.785151, 0.767450, 0.748987, 0.730325, 0.711758, 0.692761, 0.673417, 0.653908, + 0.634686, 0.615168, 0.595707, 0.576393, 0.557198, 0.538018, 0.519253, 0.500555, 0.482220, + 0.464197, 0.446414, 0.429106, 0.412035, 0.395508, 0.379284, 0.363538, 0.348220, 1.000000, + 1.000000, 1.000000, 0.999999, 0.999995, 0.999989, 0.999977, 0.999955, 0.999924, 0.999879, + 0.999813, 0.999722, 0.999590, 0.999381, 0.998335, 0.996088, 0.994814, 0.993709, 0.992220, + 0.989209, 0.986575, 0.983383, 0.979084, 0.974272, 0.968359, 0.961275, 0.953025, 0.943098, + 0.932434, 0.923101, 0.913477, 0.902861, 0.891059, 0.878072, 0.864118, 0.849188, 0.833281, + 0.816808, 0.800596, 0.783745, 0.766331, 0.748123, 0.729686, 0.711078, 0.692527, 0.673491, + 0.654296, 0.635113, 0.616048, 0.596847, 0.577720, 0.558879, 0.540028, 0.521371, 0.502996, + 0.484858, 0.466997, 0.449477, 0.432217, 0.415426, 0.398924, 0.382890, 0.367206, 0.351955, + 1.000000, 1.000000, 1.000000, 0.999998, 0.999996, 0.999988, 0.999974, 0.999953, 0.999918, + 0.999865, 0.999791, 0.999690, 0.999542, 0.999293, 0.997535, 0.995790, 0.994609, 0.993557, + 0.991766, 0.988767, 0.986255, 0.982544, 0.978541, 0.973528, 0.967700, 0.960596, 0.952299, + 0.942684, 0.931653, 0.921211, 0.911489, 0.900818, 0.889018, 0.876245, 0.862406, 0.847517, + 0.831852, 0.815367, 0.798719, 0.782224, 0.765167, 0.747304, 0.729133, 0.710485, 0.692196, + 0.673589, 0.654770, 0.635717, 0.616986, 0.598119, 0.579298, 0.560560, 0.542163, 0.523669, + 0.505564, 0.487642, 0.469991, 0.452658, 0.435620, 0.418937, 0.402612, 0.386633, 0.371091, + 0.355949, 1.000000, 1.000000, 0.999999, 0.999998, 0.999995, 0.999986, 0.999973, 0.999948, + 0.999909, 0.999852, 0.999769, 0.999656, 0.999490, 0.999186, 0.997059, 0.995624, 0.994510, + 0.993327, 0.991020, 0.988379, 0.985771, 0.981971, 0.978051, 0.972892, 0.967020, 0.959965, + 0.951625, 0.941902, 0.930951, 0.919370, 0.909285, 0.898562, 0.886809, 0.874251, 0.860597, + 0.845808, 0.830365, 0.813972, 0.797260, 0.780597, 0.763854, 0.746401, 0.728519, 0.710203, + 0.691882, 0.673687, 0.655275, 0.636621, 0.617909, 0.599473, 0.581032, 0.562560, 0.544295, + 0.526228, 0.508293, 0.490652, 0.473242, 0.456004, 0.439212, 0.422663, 0.406476, 0.390647, + 0.375204, 0.360129, 1.000000, 1.000000, 1.000000, 0.999999, 0.999994, 0.999984, 0.999969, + 0.999940, 0.999898, 0.999837, 0.999746, 0.999617, 0.999438, 0.999016, 0.996703, 0.995302, + 0.994356, 0.992993, 0.990390, 0.988072, 0.985152, 0.981447, 0.977273, 0.972234, 0.966113, + 0.959033, 0.950869, 0.941217, 0.930175, 0.918279, 0.906941, 0.896201, 0.884509, 0.871920, + 0.858420, 0.843906, 0.828730, 0.812524, 0.795978, 0.778979, 0.762450, 0.745459, 0.727966, + 0.710046, 0.691808, 0.673739, 0.655756, 0.637574, 0.619153, 0.600887, 0.582796, 0.564748, + 0.546636, 0.528904, 0.511252, 0.493791, 0.476563, 0.459695, 0.442942, 0.426632, 0.410558, + 0.394895, 0.379517, 0.364560, 1.000000, 1.000000, 1.000000, 0.999998, 0.999994, 0.999984, + 0.999966, 0.999934, 0.999887, 0.999819, 0.999720, 0.999578, 0.999367, 0.998696, 0.996353, + 0.995201, 0.994115, 0.992665, 0.989948, 0.987633, 0.984331, 0.980827, 0.976390, 0.971327, + 0.965201, 0.957977, 0.949712, 0.940128, 0.929187, 0.917237, 0.904645, 0.893711, 0.882112, + 0.869516, 0.856236, 0.841929, 0.826924, 0.810991, 0.794686, 0.777761, 0.760980, 0.744384, + 0.727314, 0.709877, 0.691988, 0.674098, 0.656243, 0.638603, 0.620606, 0.602574, 0.584694, + 0.567018, 0.549311, 0.531673, 0.514403, 0.497148, 0.480177, 0.463439, 0.446998, 0.430743, + 0.414943, 0.399304, 0.384121, 0.369251, 1.000000, 1.000000, 1.000000, 0.999997, 0.999992, + 0.999981, 0.999962, 0.999927, 0.999874, 0.999798, 0.999691, 0.999533, 0.999291, 0.997909, + 0.996117, 0.995029, 0.993880, 0.992142, 0.989576, 0.987185, 0.983587, 0.980055, 0.975487, + 0.970172, 0.963998, 0.956738, 0.948637, 0.939083, 0.928169, 0.916144, 0.903147, 0.890916, + 0.879389, 0.866895, 0.853826, 0.839729, 0.824957, 0.809472, 0.793341, 0.776743, 0.759808, + 0.743277, 0.726643, 0.709685, 0.692249, 0.674639, 0.657008, 0.639576, 0.622114, 0.604471, + 0.586851, 0.569340, 0.552135, 0.534806, 0.517599, 0.500765, 0.484035, 0.467440, 0.451212, + 0.435240, 0.419399, 0.404083, 0.388944, 0.374182, 1.000000, 1.000000, 1.000000, 0.999998, + 0.999993, 0.999979, 0.999958, 0.999919, 0.999861, 0.999774, 0.999656, 0.999482, 0.999195, + 0.997307, 0.995837, 0.994722, 0.993707, 0.991391, 0.989169, 0.986461, 0.982904, 0.979062, + 0.974536, 0.969035, 0.962653, 0.955486, 0.947243, 0.937747, 0.926861, 0.914936, 0.901835, + 0.888472, 0.876571, 0.864223, 0.851252, 0.837374, 0.822985, 0.807788, 0.791927, 0.775702, + 0.758928, 0.742347, 0.725914, 0.709495, 0.692569, 0.675363, 0.658085, 0.640639, 0.623698, + 0.606505, 0.589267, 0.572008, 0.554939, 0.538132, 0.521211, 0.504487, 0.488048, 0.471807, + 0.455651, 0.439858, 0.424332, 0.408983, 0.394071, 0.379402, 1.000000, 1.000000, 1.000000, + 0.999997, 0.999992, 0.999978, 0.999954, 0.999913, 0.999844, 0.999753, 0.999618, 0.999424, + 0.999067, 0.996875, 0.995659, 0.994603, 0.993420, 0.990874, 0.988713, 0.985585, 0.982193, + 0.978145, 0.973416, 0.967801, 0.961483, 0.954069, 0.945704, 0.936138, 0.925374, 0.913395, + 0.900339, 0.886675, 0.873512, 0.861326, 0.848513, 0.834956, 0.820820, 0.805943, 0.790574, + 0.774677, 0.758279, 0.741807, 0.725271, 0.709231, 0.692874, 0.676189, 0.659352, 0.642296, + 0.625250, 0.608700, 0.591823, 0.575012, 0.558143, 0.541491, 0.525075, 0.508558, 0.492277, + 0.476270, 0.460459, 0.444740, 0.429400, 0.414309, 0.399421, 0.384907, 1.000000, 1.000000, + 1.000000, 0.999997, 0.999990, 0.999977, 0.999947, 0.999902, 0.999832, 0.999730, 0.999577, + 0.999359, 0.998845, 0.996554, 0.995328, 0.994442, 0.992919, 0.990393, 0.988170, 0.984855, + 0.981312, 0.977149, 0.972137, 0.966207, 0.959967, 0.952454, 0.943873, 0.934434, 0.923813, + 0.911942, 0.898928, 0.885120, 0.871043, 0.858248, 0.845666, 0.832346, 0.818482, 0.804029, + 0.788982, 0.773571, 0.757700, 0.741484, 0.725186, 0.708915, 0.693244, 0.677028, 0.660656, + 0.644079, 0.627377, 0.610804, 0.594542, 0.578112, 0.561650, 0.545163, 0.528962, 0.512926, + 0.496893, 0.481007, 0.465397, 0.450042, 0.434740, 0.419831, 0.405156, 0.390692, 1.000000, + 1.000000, 0.999999, 0.999997, 0.999989, 0.999973, 0.999942, 0.999891, 0.999813, 0.999698, + 0.999532, 0.999285, 0.998286, 0.996295, 0.995215, 0.994182, 0.992032, 0.989855, 0.987415, + 0.984047, 0.980050, 0.976017, 0.970845, 0.964767, 0.958269, 0.950600, 0.942033, 0.932501, + 0.921807, 0.910017, 0.897149, 0.883414, 0.869182, 0.855055, 0.842687, 0.829548, 0.816162, + 0.802072, 0.787436, 0.772533, 0.757043, 0.741263, 0.725330, 0.709262, 0.693497, 0.678038, + 0.662128, 0.646068, 0.629824, 0.613437, 0.597334, 0.581401, 0.565372, 0.549288, 0.533182, + 0.517405, 0.501765, 0.486143, 0.470675, 0.455465, 0.440532, 0.425630, 0.411113, 0.396887, + 1.000000, 1.000000, 0.999999, 0.999996, 0.999989, 0.999970, 0.999934, 0.999879, 0.999793, + 0.999665, 0.999481, 0.999192, 0.997506, 0.995926, 0.995009, 0.993736, 0.991298, 0.989326, + 0.986371, 0.983199, 0.979032, 0.974596, 0.969364, 0.963198, 0.956385, 0.948509, 0.939993, + 0.930421, 0.919590, 0.908140, 0.895349, 0.881699, 0.867456, 0.852784, 0.839500, 0.826629, + 0.813602, 0.799983, 0.785873, 0.771340, 0.756480, 0.741190, 0.725687, 0.709997, 0.694192, + 0.678975, 0.663673, 0.648135, 0.632442, 0.616477, 0.600565, 0.584772, 0.569202, 0.553595, + 0.537881, 0.522193, 0.506784, 0.491554, 0.476349, 0.461278, 0.446419, 0.431913, 0.417443, + 0.403271, 1.000000, 1.000000, 0.999999, 0.999995, 0.999986, 0.999966, 0.999927, 0.999867, + 0.999772, 0.999629, 0.999423, 0.999075, 0.997024, 0.995773, 0.994651, 0.993353, 0.990822, + 0.988569, 0.985596, 0.982182, 0.977871, 0.973140, 0.967584, 0.961408, 0.954294, 0.946398, + 0.937603, 0.927937, 0.917305, 0.905833, 0.893138, 0.879770, 0.865720, 0.851023, 0.836801, + 0.823784, 0.810909, 0.797886, 0.784177, 0.770243, 0.755925, 0.741144, 0.726214, 0.710971, + 0.695563, 0.680212, 0.665304, 0.650297, 0.635168, 0.619796, 0.604217, 0.588692, 0.573254, + 0.557998, 0.542839, 0.527470, 0.512162, 0.497115, 0.482296, 0.467477, 0.452812, 0.438310, + 0.424184, 0.410163, 1.000000, 1.000000, 0.999999, 0.999996, 0.999984, 0.999962, 0.999920, + 0.999852, 0.999745, 0.999586, 0.999354, 0.998894, 0.996686, 0.995485, 0.994493, 0.992573, + 0.990323, 0.987772, 0.984692, 0.980887, 0.976446, 0.971625, 0.965717, 0.959421, 0.951975, + 0.944086, 0.935066, 0.925403, 0.914814, 0.903208, 0.890958, 0.877817, 0.863828, 0.849289, + 0.834872, 0.820889, 0.808183, 0.795660, 0.782556, 0.769066, 0.755386, 0.741229, 0.726726, + 0.712170, 0.697209, 0.682170, 0.667203, 0.652689, 0.637938, 0.623262, 0.608190, 0.593002, + 0.577817, 0.562737, 0.547836, 0.533036, 0.518052, 0.503135, 0.488422, 0.473986, 0.459552, + 0.445282, 0.431149, 0.417407, 1.000000, 1.000000, 0.999999, 0.999994, 0.999983, 0.999957, + 0.999914, 0.999835, 0.999718, 0.999538, 0.999275, 0.998454, 0.996341, 0.995246, 0.994222, + 0.991844, 0.989829, 0.986688, 0.983562, 0.979638, 0.974932, 0.969827, 0.963621, 0.957146, + 0.949365, 0.941398, 0.932245, 0.922556, 0.911949, 0.900627, 0.888440, 0.875544, 0.862005, + 0.847810, 0.833372, 0.819134, 0.805508, 0.793339, 0.780916, 0.767837, 0.754858, 0.741307, + 0.727496, 0.713386, 0.699131, 0.684542, 0.669878, 0.655261, 0.641035, 0.626685, 0.612377, + 0.597625, 0.582805, 0.568030, 0.553204, 0.538684, 0.524269, 0.509662, 0.495119, 0.480735, + 0.466634, 0.452593, 0.438748, 0.424915, 1.000000, 1.000000, 0.999998, 0.999994, 0.999982, + 0.999956, 0.999901, 0.999818, 0.999683, 0.999487, 0.999185, 0.997584, 0.996004, 0.995050, + 0.993715, 0.991212, 0.989057, 0.985879, 0.982243, 0.978206, 0.973119, 0.967919, 0.961343, + 0.954603, 0.946712, 0.938378, 0.929266, 0.919443, 0.908911, 0.897725, 0.885589, 0.873254, + 0.859889, 0.846123, 0.832094, 0.817898, 0.803866, 0.791061, 0.779235, 0.766885, 0.754292, + 0.741565, 0.728331, 0.714861, 0.701179, 0.687166, 0.673012, 0.658716, 0.644442, 0.630472, + 0.616519, 0.602514, 0.588172, 0.573689, 0.559281, 0.544768, 0.530543, 0.516485, 0.502303, + 0.488100, 0.474095, 0.460245, 0.446598, 0.433169, 1.000000, 1.000000, 0.999997, 0.999993, + 0.999980, 0.999947, 0.999891, 0.999794, 0.999647, 0.999425, 0.999062, 0.997049, 0.995778, + 0.994652, 0.992778, 0.990482, 0.988004, 0.984893, 0.980881, 0.976605, 0.971199, 0.965610, + 0.958925, 0.951746, 0.943791, 0.935200, 0.926018, 0.916028, 0.905724, 0.894528, 0.882914, + 0.870740, 0.857802, 0.844552, 0.830857, 0.816921, 0.803102, 0.789625, 0.777480, 0.765891, + 0.753908, 0.741795, 0.729390, 0.716440, 0.703411, 0.690068, 0.676438, 0.662586, 0.648697, + 0.634732, 0.620997, 0.607451, 0.593765, 0.579748, 0.565661, 0.551594, 0.537396, 0.523433, + 0.509708, 0.495972, 0.482082, 0.468427, 0.454890, 0.441623, 1.000000, 1.000000, 0.999999, + 0.999991, 0.999977, 0.999940, 0.999875, 0.999769, 0.999605, 0.999352, 0.998882, 0.996665, + 0.995459, 0.994380, 0.992014, 0.989912, 0.986796, 0.983537, 0.979326, 0.974792, 0.969140, + 0.963160, 0.956222, 0.948807, 0.940518, 0.931755, 0.922452, 0.912319, 0.902227, 0.891142, + 0.879838, 0.868047, 0.855745, 0.842718, 0.829827, 0.816398, 0.802786, 0.789396, 0.776581, + 0.764901, 0.753710, 0.742102, 0.730448, 0.718337, 0.705768, 0.693172, 0.680153, 0.666882, + 0.653401, 0.639837, 0.626152, 0.612676, 0.599435, 0.586109, 0.572473, 0.558715, 0.544964, + 0.531112, 0.517416, 0.503992, 0.490653, 0.477162, 0.463832, 0.450645, 1.000000, 1.000000, + 0.999999, 0.999992, 0.999973, 0.999933, 0.999861, 0.999741, 0.999554, 0.999267, 0.998411, + 0.996303, 0.995191, 0.993945, 0.991406, 0.989019, 0.985720, 0.982057, 0.977501, 0.972605, + 0.966697, 0.960340, 0.953031, 0.945347, 0.936866, 0.927917, 0.918562, 0.908598, 0.898486, + 0.887794, 0.876545, 0.865379, 0.853428, 0.841167, 0.828649, 0.815967, 0.802957, 0.789865, + 0.777077, 0.764695, 0.753544, 0.742694, 0.731571, 0.720304, 0.708490, 0.696351, 0.684134, + 0.671470, 0.658541, 0.645376, 0.632209, 0.618776, 0.605511, 0.592527, 0.579546, 0.566310, + 0.552860, 0.539492, 0.526005, 0.512564, 0.499340, 0.486360, 0.473357, 0.460306, 1.000000, + 1.000000, 0.999998, 0.999991, 0.999970, 0.999926, 0.999842, 0.999710, 0.999498, 0.999164, + 0.997464, 0.995870, 0.994917, 0.992911, 0.990682, 0.987816, 0.984410, 0.980551, 0.975693, + 0.970263, 0.963946, 0.957248, 0.949765, 0.941571, 0.932941, 0.923873, 0.914332, 0.904560, + 0.894394, 0.884127, 0.873294, 0.862503, 0.851335, 0.839566, 0.827776, 0.815708, 0.803370, + 0.790821, 0.778386, 0.766121, 0.754193, 0.743420, 0.732975, 0.722326, 0.711376, 0.699992, + 0.688180, 0.676354, 0.664004, 0.651449, 0.638600, 0.625776, 0.612660, 0.599603, 0.586719, + 0.574078, 0.561273, 0.548129, 0.535155, 0.522015, 0.508851, 0.495837, 0.483190, 0.470624, + 1.000000, 1.000000, 0.999998, 0.999988, 0.999965, 0.999916, 0.999823, 0.999669, 0.999425, + 0.999025, 0.996874, 0.995670, 0.994415, 0.991991, 0.989766, 0.986646, 0.982812, 0.978356, + 0.973317, 0.967612, 0.960820, 0.953603, 0.945969, 0.937323, 0.928661, 0.919507, 0.909833, + 0.900245, 0.890390, 0.880252, 0.870000, 0.859518, 0.849163, 0.838101, 0.826960, 0.815688, + 0.804126, 0.792234, 0.780356, 0.768474, 0.756678, 0.745159, 0.734601, 0.724624, 0.714339, + 0.703751, 0.692766, 0.681267, 0.669799, 0.657871, 0.645577, 0.633102, 0.620560, 0.607737, + 0.594890, 0.582143, 0.569779, 0.557360, 0.544651, 0.531942, 0.519228, 0.506467, 0.493710, + 0.481143, 1.000000, 1.000000, 0.999998, 0.999988, 0.999961, 0.999902, 0.999798, 0.999622, + 0.999341, 0.998801, 0.996397, 0.995225, 0.993927, 0.991338, 0.988500, 0.985327, 0.981195, + 0.976383, 0.970726, 0.964471, 0.957386, 0.949813, 0.941694, 0.932681, 0.923974, 0.914755, + 0.905026, 0.895649, 0.886178, 0.876277, 0.866629, 0.856890, 0.846934, 0.836887, 0.826373, + 0.815885, 0.805169, 0.794133, 0.782812, 0.771547, 0.760175, 0.748896, 0.737687, 0.727152, + 0.717601, 0.707670, 0.697425, 0.686788, 0.675664, 0.664513, 0.652962, 0.640965, 0.628851, + 0.616551, 0.604168, 0.591559, 0.579009, 0.566648, 0.554597, 0.542382, 0.529999, 0.517655, + 0.505254, 0.492894, 1.000000, 1.000000, 0.999997, 0.999986, 0.999956, 0.999889, 0.999766, + 0.999562, 0.999240, 0.997952, 0.996094, 0.994979, 0.992773, 0.990536, 0.987214, 0.983322, + 0.978938, 0.973714, 0.967681, 0.960981, 0.953144, 0.945475, 0.936909, 0.927734, 0.918826, + 0.909590, 0.900085, 0.890867, 0.881801, 0.872565, 0.863236, 0.854239, 0.845060, 0.835686, + 0.826251, 0.816284, 0.806586, 0.796419, 0.785914, 0.775210, 0.764461, 0.753599, 0.742805, + 0.731872, 0.721370, 0.711898, 0.702337, 0.692383, 0.682137, 0.671365, 0.660479, 0.649314, + 0.637685, 0.625899, 0.613898, 0.601865, 0.589582, 0.577285, 0.565013, 0.553106, 0.541280, + 0.529367, 0.517320, 0.505411, 1.000000, 1.000000, 0.999997, 0.999983, 0.999948, 0.999869, + 0.999732, 0.999499, 0.999111, 0.997167, 0.995720, 0.994349, 0.991727, 0.989197, 0.985883, + 0.981483, 0.976618, 0.970597, 0.964122, 0.956994, 0.948639, 0.940500, 0.931606, 0.922385, + 0.913291, 0.904205, 0.894938, 0.885890, 0.877334, 0.868754, 0.860053, 0.851683, 0.843447, + 0.834889, 0.826304, 0.817441, 0.808285, 0.799141, 0.789570, 0.779600, 0.769510, 0.759155, + 0.748882, 0.738346, 0.727629, 0.717273, 0.707467, 0.698283, 0.688609, 0.678748, 0.668371, + 0.657739, 0.646951, 0.635765, 0.624254, 0.612647, 0.600900, 0.589061, 0.576998, 0.564991, + 0.553102, 0.541517, 0.530027, 0.518495, 1.000000, 1.000000, 0.999997, 0.999983, 0.999939, + 0.999851, 0.999684, 0.999412, 0.998925, 0.996597, 0.995207, 0.993603, 0.990903, 0.987594, + 0.983814, 0.979016, 0.973647, 0.967048, 0.960109, 0.952123, 0.943560, 0.934900, 0.925747, + 0.916566, 0.907305, 0.898441, 0.889629, 0.881042, 0.872874, 0.865064, 0.857225, 0.849446, + 0.842063, 0.834561, 0.826814, 0.818875, 0.810748, 0.802316, 0.793699, 0.784704, 0.775198, + 0.765643, 0.755735, 0.745873, 0.735526, 0.725229, 0.714892, 0.704807, 0.695502, 0.686241, + 0.676633, 0.666688, 0.656384, 0.645871, 0.635174, 0.624113, 0.612788, 0.601426, 0.589925, + 0.578399, 0.566612, 0.554931, 0.543383, 0.532065, 1.000000, 1.000000, 0.999996, 0.999977, + 0.999928, 0.999824, 0.999633, 0.999306, 0.998429, 0.996133, 0.994890, 0.992316, 0.989752, + 0.986095, 0.981564, 0.976234, 0.970081, 0.962779, 0.955232, 0.946702, 0.937716, 0.928604, + 0.919281, 0.910167, 0.901046, 0.892446, 0.884183, 0.876253, 0.868619, 0.861545, 0.854673, + 0.847885, 0.841074, 0.834610, 0.827984, 0.820945, 0.813648, 0.806232, 0.798444, 0.790232, + 0.781853, 0.772897, 0.763648, 0.754227, 0.744542, 0.734689, 0.724526, 0.714204, 0.704152, + 0.694222, 0.685143, 0.675860, 0.666319, 0.656415, 0.646273, 0.635902, 0.625399, 0.614563, + 0.603490, 0.592413, 0.581217, 0.570000, 0.558608, 0.547242, 1.000000, 0.999999, 0.999995, + 0.999972, 0.999915, 0.999790, 0.999562, 0.999168, 0.997237, 0.995672, 0.994074, 0.991220, + 0.987792, 0.983822, 0.978599, 0.972804, 0.965718, 0.958053, 0.949460, 0.940503, 0.931011, + 0.921608, 0.912409, 0.903378, 0.894606, 0.886369, 0.878756, 0.871573, 0.864862, 0.858421, + 0.852541, 0.846802, 0.841027, 0.835206, 0.829628, 0.823730, 0.817415, 0.810655, 0.803873, + 0.796659, 0.788887, 0.780940, 0.772537, 0.763507, 0.754487, 0.745163, 0.735572, 0.725687, + 0.715611, 0.705398, 0.695418, 0.685592, 0.676518, 0.667304, 0.657875, 0.648182, 0.638235, + 0.628062, 0.617813, 0.607283, 0.596552, 0.585770, 0.575033, 0.564153, 1.000000, 1.000000, + 0.999995, 0.999970, 0.999898, 0.999748, 0.999472, 0.998969, 0.996528, 0.995102, 0.992701, + 0.989963, 0.985981, 0.981194, 0.975183, 0.968501, 0.960502, 0.952012, 0.942861, 0.933376, + 0.923506, 0.914042, 0.904921, 0.896282, 0.887987, 0.880341, 0.873536, 0.867293, 0.861556, + 0.856148, 0.850987, 0.846352, 0.841684, 0.836880, 0.832036, 0.827091, 0.821900, 0.816206, + 0.810042, 0.803629, 0.796918, 0.789653, 0.781915, 0.774014, 0.765530, 0.756526, 0.747669, + 0.738342, 0.728770, 0.718942, 0.708942, 0.698855, 0.688933, 0.679131, 0.669855, 0.660811, + 0.651549, 0.642127, 0.632454, 0.622651, 0.612709, 0.602606, 0.592344, 0.581877, 1.000000, + 0.999999, 0.999993, 0.999963, 0.999874, 0.999691, 0.999350, 0.998431, 0.995873, 0.994456, + 0.991327, 0.987798, 0.983232, 0.977500, 0.970828, 0.962815, 0.954228, 0.944752, 0.935126, + 0.925179, 0.915102, 0.905763, 0.897087, 0.888933, 0.881452, 0.874687, 0.868716, 0.863585, + 0.858931, 0.854662, 0.850569, 0.846719, 0.843151, 0.839426, 0.835588, 0.831443, 0.827004, + 0.822395, 0.817254, 0.811630, 0.805464, 0.799124, 0.792382, 0.785091, 0.777315, 0.769360, + 0.760908, 0.751957, 0.743128, 0.733917, 0.724340, 0.714713, 0.704721, 0.694835, 0.684862, + 0.675099, 0.665570, 0.656644, 0.647651, 0.638581, 0.629337, 0.619926, 0.610358, 0.600707, + 1.000000, 1.000000, 0.999990, 0.999953, 0.999843, 0.999613, 0.999186, 0.997025, 0.995317, + 0.992850, 0.989760, 0.985270, 0.979807, 0.973049, 0.965228, 0.956248, 0.946394, 0.936324, + 0.926124, 0.915808, 0.905942, 0.897060, 0.889001, 0.881755, 0.875351, 0.869688, 0.864736, + 0.860745, 0.857305, 0.854190, 0.851261, 0.848484, 0.845642, 0.842948, 0.840060, 0.836901, + 0.833379, 0.829393, 0.825103, 0.820431, 0.815288, 0.809575, 0.803326, 0.796949, 0.790174, + 0.782873, 0.775048, 0.767139, 0.758772, 0.750019, 0.741120, 0.732127, 0.722743, 0.713225, + 0.703637, 0.693768, 0.684016, 0.674277, 0.664703, 0.655328, 0.646550, 0.637812, 0.629036, + 0.620129, 1.000000, 1.000000, 0.999988, 0.999933, 0.999800, 0.999508, 0.998917, 0.996236, + 0.994617, 0.991176, 0.987089, 0.981880, 0.974966, 0.967156, 0.957914, 0.947585, 0.936937, + 0.926318, 0.915662, 0.905567, 0.896223, 0.888166, 0.881117, 0.875079, 0.869981, 0.865675, + 0.862091, 0.859183, 0.856981, 0.855065, 0.853273, 0.851572, 0.849782, 0.847768, 0.845668, + 0.843345, 0.840703, 0.837646, 0.834094, 0.830030, 0.825631, 0.820873, 0.815619, 0.809856, + 0.803578, 0.797096, 0.790359, 0.783152, 0.775507, 0.767504, 0.759411, 0.750982, 0.742208, + 0.733383, 0.724445, 0.715190, 0.705827, 0.696440, 0.686773, 0.677242, 0.667735, 0.658471, + 0.649236, 0.640305, 1.000000, 0.999999, 0.999984, 0.999918, 0.999737, 0.999350, 0.997576, + 0.995476, 0.992614, 0.988817, 0.983601, 0.976880, 0.968694, 0.959092, 0.948297, 0.936831, + 0.925592, 0.914494, 0.904159, 0.894643, 0.886417, 0.879620, 0.874023, 0.869533, 0.865967, + 0.863238, 0.861113, 0.859527, 0.858367, 0.857594, 0.856882, 0.856172, 0.855316, 0.854197, + 0.852818, 0.851062, 0.849046, 0.846747, 0.844043, 0.840842, 0.837164, 0.832985, 0.828344, + 0.823544, 0.818276, 0.812543, 0.806374, 0.799838, 0.793170, 0.786246, 0.778956, 0.771297, + 0.763278, 0.755252, 0.746984, 0.738445, 0.729688, 0.721045, 0.712189, 0.703099, 0.694045, + 0.684930, 0.675601, 0.666480, 1.000000, 0.999999, 0.999978, 0.999888, 0.999639, 0.999093, + 0.996310, 0.994405, 0.990527, 0.985186, 0.978518, 0.969748, 0.959597, 0.948104, 0.935724, + 0.923704, 0.912023, 0.901356, 0.891850, 0.883847, 0.877280, 0.872289, 0.868583, 0.865913, + 0.864098, 0.862993, 0.862356, 0.862125, 0.862107, 0.862168, 0.862359, 0.862490, 0.862430, + 0.862063, 0.861431, 0.860386, 0.858950, 0.857090, 0.854848, 0.852381, 0.849503, 0.846167, + 0.842399, 0.838194, 0.833566, 0.828579, 0.823464, 0.817951, 0.812079, 0.805873, 0.799320, + 0.792533, 0.785715, 0.778636, 0.771260, 0.763618, 0.755719, 0.747815, 0.739825, 0.731602, + 0.723212, 0.714845, 0.706465, 0.697933, 1.000000, 0.999998, 0.999969, 0.999836, 0.999475, + 0.997943, 0.995219, 0.991760, 0.986663, 0.979592, 0.970218, 0.959155, 0.946575, 0.933047, + 0.920022, 0.907749, 0.896801, 0.887506, 0.880077, 0.874322, 0.870126, 0.867481, 0.865949, + 0.865293, 0.865287, 0.865746, 0.866502, 0.867439, 0.868442, 0.869382, 0.870161, 0.870782, + 0.871303, 0.871511, 0.871427, 0.870978, 0.870136, 0.868892, 0.867248, 0.865209, 0.862775, + 0.859944, 0.857004, 0.853671, 0.849984, 0.845927, 0.841518, 0.836774, 0.831750, 0.826407, + 0.821001, 0.815333, 0.809412, 0.803238, 0.796802, 0.790204, 0.783457, 0.776713, 0.769749, + 0.762596, 0.755239, 0.747690, 0.740127, 0.732595, 1.000000, 0.999997, 0.999950, 0.999744, + 0.999162, 0.996124, 0.992844, 0.987757, 0.980062, 0.969642, 0.957087, 0.942735, 0.927747, + 0.913622, 0.900889, 0.890115, 0.881584, 0.875288, 0.870926, 0.868307, 0.867033, 0.866972, + 0.867692, 0.868950, 0.870549, 0.872320, 0.874144, 0.875947, 0.877674, 0.879192, 0.880478, + 0.881539, 0.882307, 0.882739, 0.882902, 0.882847, 0.882461, 0.881725, 0.880636, 0.879197, + 0.877422, 0.875296, 0.872849, 0.870076, 0.866988, 0.863637, 0.860159, 0.856475, 0.852525, + 0.848328, 0.843883, 0.839198, 0.834322, 0.829221, 0.823907, 0.818461, 0.812972, 0.807316, + 0.801474, 0.795459, 0.789276, 0.783025, 0.776615, 0.770223, 0.999999, 0.999994, 0.999909, + 0.999536, 0.997195, 0.994123, 0.988168, 0.979344, 0.967003, 0.951763, 0.934724, 0.917948, + 0.902918, 0.890432, 0.880902, 0.874401, 0.870394, 0.868503, 0.868209, 0.869062, 0.870725, + 0.873006, 0.875558, 0.878230, 0.880893, 0.883445, 0.885832, 0.888059, 0.890058, 0.891782, + 0.893247, 0.894460, 0.895397, 0.896023, 0.896380, 0.896433, 0.896198, 0.895673, 0.894865, + 0.893908, 0.892700, 0.891224, 0.889501, 0.887539, 0.885336, 0.882903, 0.880244, 0.877373, + 0.874296, 0.871019, 0.867549, 0.863933, 0.860153, 0.856355, 0.852395, 0.848277, 0.844006, + 0.839587, 0.835045, 0.830378, 0.825579, 0.820649, 0.815592, 0.810432, 0.999998, 0.999988, + 0.999795, 0.998892, 0.994635, 0.987290, 0.975397, 0.958508, 0.938352, 0.917733, 0.899800, + 0.885878, 0.876516, 0.871200, 0.869099, 0.869317, 0.871112, 0.873870, 0.877160, 0.880682, + 0.884228, 0.887737, 0.891076, 0.894161, 0.896981, 0.899543, 0.901847, 0.903882, 0.905672, + 0.907188, 0.908451, 0.909480, 0.910289, 0.910878, 0.911259, 0.911430, 0.911396, 0.911154, + 0.910712, 0.910081, 0.909266, 0.908264, 0.907094, 0.905752, 0.904244, 0.902577, 0.900799, + 0.898931, 0.896923, 0.894782, 0.892513, 0.890117, 0.887600, 0.884968, 0.882222, 0.879369, + 0.876408, 0.873345, 0.870183, 0.866926, 0.863575, 0.860160, 0.856672, 0.853098, 0.999991, + 0.999947, 0.999158, 0.992842, 0.980107, 0.957230, 0.928231, 0.901539, 0.882688, 0.872588, + 0.869394, 0.870671, 0.874458, 0.879378, 0.884639, 0.889770, 0.894601, 0.898972, 0.902930, + 0.906456, 0.909568, 0.912329, 0.914750, 0.916893, 0.918774, 0.920429, 0.921868, 0.923110, + 0.924185, 0.925089, 0.925842, 0.926457, 0.926934, 0.927285, 0.927522, 0.927639, 0.927650, + 0.927553, 0.927356, 0.927061, 0.926671, 0.926187, 0.925617, 0.924962, 0.924224, 0.923409, + 0.922519, 0.921555, 0.920521, 0.919419, 0.918252, 0.917021, 0.915729, 0.914377, 0.912967, + 0.911503, 0.909984, 0.908414, 0.906791, 0.905122, 0.903401, 0.901637, 0.899826, 0.897972, + 0.987461, 0.940121, 0.871507, 0.898572, 0.916705, 0.926425, 0.931922, 0.935265, 0.937431, + 0.938899, 0.939950, 0.940717, 0.941301, 0.941754, 0.942111, 0.942397, 0.942631, 0.942823, + 0.942983, 0.943117, 0.943231, 0.943329, 0.943412, 0.943484, 0.943545, 0.943599, 0.943644, + 0.943682, 0.943716, 0.943744, 0.943766, 0.943785, 0.943799, 0.943808, 0.943815, 0.943818, + 0.943818, 0.943814, 0.943807, 0.943797, 0.943784, 0.943769, 0.943751, 0.943730, 0.943707, + 0.943681, 0.943652, 0.943623, 0.943589, 0.943554, 0.943518, 0.943479, 0.943438, 0.943396, + 0.943351, 0.943305, 0.943257, 0.943207, 0.943156, 0.943104, 0.943049, 0.942993, 0.942936, + 0.942877, +}; + +static float bsdf_split_sum_ggx[64 * 64 * 2] = { + 1.000000f, 0.000000f, 1.000000f, 0.000000f, 1.000000f, 0.000000f, 1.000000f, 0.000000f, + 1.000000f, 0.000000f, 1.000000f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f, + 0.999512f, 0.000000f, 0.999023f, 0.000001f, 0.999023f, 0.000001f, 0.998535f, 0.000001f, + 0.998047f, 0.000001f, 0.997559f, 0.000002f, 0.997070f, 0.000003f, 0.996094f, 0.000004f, + 0.994629f, 0.000004f, 0.993652f, 0.000006f, 0.991699f, 0.000007f, 0.989746f, 0.000008f, + 0.987305f, 0.000010f, 0.984375f, 0.000012f, 0.980957f, 0.000013f, 0.977539f, 0.000016f, + 0.973145f, 0.000018f, 0.967773f, 0.000020f, 0.961914f, 0.000023f, 0.955566f, 0.000025f, + 0.947754f, 0.000028f, 0.939941f, 0.000031f, 0.930664f, 0.000033f, 0.920410f, 0.000036f, + 0.909180f, 0.000039f, 0.896973f, 0.000042f, 0.884277f, 0.000044f, 0.870117f, 0.000047f, + 0.854980f, 0.000049f, 0.838867f, 0.000051f, 0.821777f, 0.000053f, 0.803711f, 0.000055f, + 0.785156f, 0.000057f, 0.765625f, 0.000058f, 0.745605f, 0.000059f, 0.724609f, 0.000060f, + 0.703613f, 0.000061f, 0.681641f, 0.000061f, 0.659668f, 0.000061f, 0.637695f, 0.000061f, + 0.615234f, 0.000061f, 0.592773f, 0.000060f, 0.570801f, 0.000060f, 0.548340f, 0.000059f, + 0.526855f, 0.000058f, 0.504883f, 0.000057f, 0.483887f, 0.000055f, 0.462891f, 0.000054f, + 0.442627f, 0.000053f, 0.422607f, 0.000051f, 0.403320f, 0.000050f, 0.384766f, 0.000048f, + 0.366455f, 0.000046f, 0.348877f, 0.000045f, 0.332031f, 0.000043f, 0.315918f, 0.000041f, + 0.999512f, 0.000000f, 0.999512f, 0.000000f, 1.000000f, 0.000000f, 1.000000f, 0.000000f, + 0.999512f, 0.000000f, 1.000000f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f, + 0.999512f, 0.000000f, 0.999023f, 0.000001f, 0.999023f, 0.000001f, 0.998535f, 0.000002f, + 0.998047f, 0.000003f, 0.997559f, 0.000004f, 0.997070f, 0.000005f, 0.996094f, 0.000006f, + 0.994629f, 0.000008f, 0.993164f, 0.000010f, 0.991699f, 0.000012f, 0.989746f, 0.000015f, + 0.987305f, 0.000018f, 0.984375f, 0.000020f, 0.980957f, 0.000024f, 0.977051f, 0.000027f, + 0.972168f, 0.000031f, 0.967285f, 0.000035f, 0.961426f, 0.000039f, 0.954590f, 0.000043f, + 0.947266f, 0.000048f, 0.938965f, 0.000052f, 0.929199f, 0.000057f, 0.919434f, 0.000061f, + 0.908203f, 0.000065f, 0.895996f, 0.000069f, 0.882812f, 0.000073f, 0.868652f, 0.000077f, + 0.853027f, 0.000080f, 0.837402f, 0.000083f, 0.820312f, 0.000086f, 0.802246f, 0.000088f, + 0.783691f, 0.000090f, 0.764160f, 0.000092f, 0.744141f, 0.000093f, 0.723633f, 0.000093f, + 0.702637f, 0.000094f, 0.681152f, 0.000094f, 0.659180f, 0.000093f, 0.637207f, 0.000093f, + 0.615234f, 0.000091f, 0.593262f, 0.000090f, 0.571289f, 0.000088f, 0.549316f, 0.000087f, + 0.527344f, 0.000085f, 0.505859f, 0.000082f, 0.485107f, 0.000080f, 0.464355f, 0.000078f, + 0.444336f, 0.000075f, 0.424561f, 0.000072f, 0.405273f, 0.000070f, 0.386719f, 0.000067f, + 0.368652f, 0.000065f, 0.351318f, 0.000062f, 0.334473f, 0.000059f, 0.318115f, 0.000057f, + 0.999512f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f, 1.000000f, 0.000000f, + 0.999512f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000001f, 0.999512f, 0.000001f, + 0.999512f, 0.000001f, 0.999512f, 0.000003f, 0.999023f, 0.000002f, 0.998535f, 0.000004f, + 0.998047f, 0.000005f, 0.997559f, 0.000007f, 0.997070f, 0.000009f, 0.996094f, 0.000011f, + 0.994629f, 0.000013f, 0.993164f, 0.000017f, 0.991211f, 0.000020f, 0.989258f, 0.000024f, + 0.986816f, 0.000028f, 0.983887f, 0.000033f, 0.980469f, 0.000038f, 0.976562f, 0.000043f, + 0.971680f, 0.000049f, 0.966797f, 0.000055f, 0.960449f, 0.000062f, 0.953613f, 0.000068f, + 0.946289f, 0.000075f, 0.937500f, 0.000081f, 0.928223f, 0.000088f, 0.917969f, 0.000094f, + 0.906738f, 0.000100f, 0.894531f, 0.000106f, 0.880859f, 0.000111f, 0.866699f, 0.000116f, + 0.851562f, 0.000120f, 0.835449f, 0.000124f, 0.818359f, 0.000127f, 0.800781f, 0.000130f, + 0.782227f, 0.000132f, 0.762695f, 0.000134f, 0.742676f, 0.000134f, 0.722656f, 0.000135f, + 0.701660f, 0.000134f, 0.680176f, 0.000133f, 0.658691f, 0.000132f, 0.636719f, 0.000130f, + 0.615234f, 0.000128f, 0.593262f, 0.000125f, 0.571289f, 0.000123f, 0.549805f, 0.000119f, + 0.528320f, 0.000116f, 0.507324f, 0.000112f, 0.486328f, 0.000109f, 0.466064f, 0.000105f, + 0.446045f, 0.000101f, 0.426514f, 0.000097f, 0.407471f, 0.000093f, 0.388916f, 0.000089f, + 0.370850f, 0.000085f, 0.353516f, 0.000082f, 0.336914f, 0.000078f, 0.320557f, 0.000074f, + 1.000000f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f, 0.999512f, 0.000000f, + 1.000000f, 0.000000f, 1.000000f, 0.000001f, 0.999512f, 0.000001f, 0.999512f, 0.000002f, + 0.999512f, 0.000002f, 0.999023f, 0.000003f, 0.999023f, 0.000005f, 0.998535f, 0.000006f, + 0.998535f, 0.000008f, 0.997559f, 0.000011f, 0.997070f, 0.000014f, 0.996094f, 0.000017f, + 0.994629f, 0.000020f, 0.993164f, 0.000026f, 0.991211f, 0.000030f, 0.989258f, 0.000036f, + 0.986816f, 0.000043f, 0.983398f, 0.000050f, 0.979980f, 0.000058f, 0.976074f, 0.000066f, + 0.971191f, 0.000074f, 0.965820f, 0.000082f, 0.959961f, 0.000093f, 0.952637f, 0.000101f, + 0.945312f, 0.000111f, 0.936523f, 0.000120f, 0.927246f, 0.000129f, 0.916504f, 0.000137f, + 0.905273f, 0.000145f, 0.892578f, 0.000153f, 0.879395f, 0.000160f, 0.865234f, 0.000166f, + 0.850098f, 0.000171f, 0.833984f, 0.000176f, 0.816895f, 0.000179f, 0.799316f, 0.000182f, + 0.780762f, 0.000184f, 0.761230f, 0.000185f, 0.741699f, 0.000185f, 0.721191f, 0.000184f, + 0.700684f, 0.000183f, 0.679688f, 0.000181f, 0.658203f, 0.000178f, 0.636719f, 0.000175f, + 0.615234f, 0.000171f, 0.593262f, 0.000167f, 0.571777f, 0.000162f, 0.550293f, 0.000158f, + 0.529297f, 0.000152f, 0.508301f, 0.000147f, 0.487793f, 0.000142f, 0.467529f, 0.000136f, + 0.447754f, 0.000131f, 0.428223f, 0.000125f, 0.409424f, 0.000120f, 0.391113f, 0.000115f, + 0.373291f, 0.000109f, 0.355957f, 0.000104f, 0.339355f, 0.000099f, 0.323242f, 0.000094f, + 0.999512f, 0.000002f, 0.999512f, 0.000002f, 1.000000f, 0.000002f, 0.999512f, 0.000002f, + 1.000000f, 0.000002f, 0.999512f, 0.000002f, 0.999512f, 0.000002f, 0.999512f, 0.000003f, + 0.999512f, 0.000004f, 0.999512f, 0.000005f, 0.999023f, 0.000007f, 0.998535f, 0.000010f, + 0.998047f, 0.000012f, 0.997559f, 0.000017f, 0.996582f, 0.000020f, 0.995605f, 0.000025f, + 0.994629f, 0.000032f, 0.993164f, 0.000038f, 0.991211f, 0.000047f, 0.988770f, 0.000055f, + 0.986328f, 0.000063f, 0.983398f, 0.000074f, 0.979492f, 0.000085f, 0.975586f, 0.000095f, + 0.970703f, 0.000108f, 0.965332f, 0.000121f, 0.958984f, 0.000132f, 0.952148f, 0.000145f, + 0.944336f, 0.000157f, 0.935547f, 0.000170f, 0.925781f, 0.000181f, 0.915039f, 0.000192f, + 0.903809f, 0.000203f, 0.891113f, 0.000212f, 0.877930f, 0.000220f, 0.863281f, 0.000227f, + 0.848145f, 0.000234f, 0.832031f, 0.000239f, 0.814941f, 0.000242f, 0.797363f, 0.000245f, + 0.778809f, 0.000247f, 0.759766f, 0.000247f, 0.740234f, 0.000246f, 0.720215f, 0.000244f, + 0.699707f, 0.000241f, 0.678711f, 0.000237f, 0.657715f, 0.000233f, 0.636230f, 0.000228f, + 0.614746f, 0.000222f, 0.593750f, 0.000216f, 0.572266f, 0.000209f, 0.551270f, 0.000202f, + 0.530273f, 0.000195f, 0.509277f, 0.000187f, 0.489014f, 0.000180f, 0.468994f, 0.000172f, + 0.449463f, 0.000165f, 0.430176f, 0.000157f, 0.411377f, 0.000150f, 0.393311f, 0.000143f, + 0.375488f, 0.000136f, 0.358398f, 0.000129f, 0.341797f, 0.000123f, 0.325684f, 0.000116f, + 0.999512f, 0.000005f, 0.999512f, 0.000005f, 0.999512f, 0.000005f, 0.999512f, 0.000005f, + 0.999512f, 0.000005f, 0.999512f, 0.000005f, 0.999512f, 0.000006f, 0.999512f, 0.000007f, + 0.999512f, 0.000008f, 0.999512f, 0.000011f, 0.999023f, 0.000013f, 0.998535f, 0.000015f, + 0.998047f, 0.000019f, 0.997559f, 0.000026f, 0.996582f, 0.000033f, 0.995605f, 0.000040f, + 0.994141f, 0.000047f, 0.993164f, 0.000058f, 0.991211f, 0.000069f, 0.988770f, 0.000080f, + 0.985840f, 0.000093f, 0.982910f, 0.000106f, 0.979004f, 0.000121f, 0.975098f, 0.000137f, + 0.970215f, 0.000153f, 0.964355f, 0.000169f, 0.958008f, 0.000186f, 0.951172f, 0.000201f, + 0.943359f, 0.000218f, 0.934082f, 0.000233f, 0.924316f, 0.000248f, 0.914062f, 0.000262f, + 0.902344f, 0.000275f, 0.889648f, 0.000286f, 0.875977f, 0.000295f, 0.861816f, 0.000304f, + 0.846680f, 0.000311f, 0.830566f, 0.000316f, 0.813477f, 0.000319f, 0.795898f, 0.000321f, + 0.777344f, 0.000322f, 0.758301f, 0.000320f, 0.739258f, 0.000318f, 0.719238f, 0.000314f, + 0.698730f, 0.000309f, 0.678223f, 0.000303f, 0.657227f, 0.000296f, 0.636230f, 0.000288f, + 0.614746f, 0.000280f, 0.593750f, 0.000271f, 0.572754f, 0.000262f, 0.551758f, 0.000252f, + 0.531250f, 0.000243f, 0.510742f, 0.000233f, 0.490479f, 0.000223f, 0.470703f, 0.000213f, + 0.451172f, 0.000203f, 0.432129f, 0.000194f, 0.413574f, 0.000184f, 0.395508f, 0.000175f, + 0.377930f, 0.000166f, 0.360840f, 0.000157f, 0.344238f, 0.000149f, 0.328125f, 0.000141f, + 0.999512f, 0.000011f, 0.999512f, 0.000011f, 0.999512f, 0.000011f, 0.999512f, 0.000011f, + 0.999512f, 0.000011f, 0.999512f, 0.000012f, 0.999512f, 0.000014f, 0.999512f, 0.000015f, + 0.999512f, 0.000017f, 0.999023f, 0.000020f, 0.998535f, 0.000022f, 0.998535f, 0.000028f, + 0.998047f, 0.000034f, 0.997559f, 0.000042f, 0.996582f, 0.000050f, 0.995605f, 0.000060f, + 0.994141f, 0.000072f, 0.992676f, 0.000084f, 0.990723f, 0.000099f, 0.988281f, 0.000115f, + 0.985840f, 0.000133f, 0.982422f, 0.000150f, 0.978516f, 0.000171f, 0.974609f, 0.000191f, + 0.969238f, 0.000211f, 0.963867f, 0.000232f, 0.957520f, 0.000253f, 0.950195f, 0.000274f, + 0.941895f, 0.000294f, 0.933105f, 0.000314f, 0.922852f, 0.000332f, 0.912109f, 0.000348f, + 0.900879f, 0.000363f, 0.888184f, 0.000377f, 0.874512f, 0.000387f, 0.859863f, 0.000397f, + 0.844727f, 0.000404f, 0.828613f, 0.000408f, 0.811523f, 0.000411f, 0.793945f, 0.000412f, + 0.775879f, 0.000411f, 0.756836f, 0.000407f, 0.737793f, 0.000403f, 0.717773f, 0.000396f, + 0.697754f, 0.000389f, 0.677246f, 0.000380f, 0.656738f, 0.000370f, 0.635742f, 0.000359f, + 0.614746f, 0.000347f, 0.594238f, 0.000335f, 0.573242f, 0.000323f, 0.552734f, 0.000310f, + 0.532227f, 0.000297f, 0.511719f, 0.000284f, 0.491943f, 0.000272f, 0.472412f, 0.000259f, + 0.453125f, 0.000246f, 0.434082f, 0.000234f, 0.415771f, 0.000222f, 0.397705f, 0.000211f, + 0.380127f, 0.000199f, 0.363281f, 0.000189f, 0.346680f, 0.000178f, 0.330811f, 0.000168f, + 0.999512f, 0.000022f, 0.999512f, 0.000022f, 0.999512f, 0.000022f, 0.999512f, 0.000022f, + 0.999512f, 0.000023f, 0.999512f, 0.000025f, 0.999512f, 0.000024f, 0.999512f, 0.000028f, + 0.999023f, 0.000030f, 0.999023f, 0.000035f, 0.999023f, 0.000040f, 0.998535f, 0.000046f, + 0.998047f, 0.000056f, 0.997559f, 0.000063f, 0.996094f, 0.000077f, 0.995605f, 0.000089f, + 0.994141f, 0.000106f, 0.992188f, 0.000123f, 0.990234f, 0.000143f, 0.987793f, 0.000163f, + 0.985352f, 0.000185f, 0.981934f, 0.000211f, 0.978027f, 0.000236f, 0.973633f, 0.000261f, + 0.968750f, 0.000288f, 0.962891f, 0.000314f, 0.956055f, 0.000341f, 0.949219f, 0.000366f, + 0.940918f, 0.000391f, 0.931641f, 0.000414f, 0.921875f, 0.000436f, 0.910645f, 0.000455f, + 0.898926f, 0.000471f, 0.886230f, 0.000487f, 0.872559f, 0.000499f, 0.858398f, 0.000509f, + 0.842773f, 0.000515f, 0.826660f, 0.000518f, 0.810059f, 0.000520f, 0.792480f, 0.000519f, + 0.774414f, 0.000515f, 0.755371f, 0.000509f, 0.736328f, 0.000501f, 0.716797f, 0.000492f, + 0.696777f, 0.000480f, 0.676758f, 0.000468f, 0.656250f, 0.000454f, 0.635742f, 0.000439f, + 0.615234f, 0.000424f, 0.594238f, 0.000408f, 0.573730f, 0.000392f, 0.553223f, 0.000375f, + 0.533203f, 0.000359f, 0.513184f, 0.000342f, 0.493408f, 0.000326f, 0.474121f, 0.000310f, + 0.455078f, 0.000294f, 0.436279f, 0.000279f, 0.417969f, 0.000264f, 0.400146f, 0.000250f, + 0.382812f, 0.000237f, 0.365723f, 0.000223f, 0.349365f, 0.000211f, 0.333496f, 0.000199f, + 0.999512f, 0.000041f, 0.999512f, 0.000041f, 0.999512f, 0.000041f, 0.999512f, 0.000042f, + 0.999512f, 0.000042f, 0.999512f, 0.000044f, 0.999512f, 0.000046f, 0.999512f, 0.000049f, + 0.999512f, 0.000054f, 0.999512f, 0.000059f, 0.999023f, 0.000065f, 0.998535f, 0.000076f, + 0.998047f, 0.000087f, 0.997070f, 0.000098f, 0.996582f, 0.000117f, 0.995117f, 0.000135f, + 0.993652f, 0.000152f, 0.992188f, 0.000176f, 0.989746f, 0.000201f, 0.987793f, 0.000228f, + 0.984863f, 0.000256f, 0.981445f, 0.000286f, 0.977539f, 0.000318f, 0.973145f, 0.000352f, + 0.967773f, 0.000384f, 0.961914f, 0.000417f, 0.955566f, 0.000451f, 0.947754f, 0.000481f, + 0.939453f, 0.000510f, 0.930176f, 0.000537f, 0.919922f, 0.000563f, 0.909180f, 0.000585f, + 0.897461f, 0.000604f, 0.884766f, 0.000620f, 0.871094f, 0.000632f, 0.856445f, 0.000641f, + 0.841309f, 0.000647f, 0.825195f, 0.000648f, 0.808105f, 0.000648f, 0.790527f, 0.000643f, + 0.772949f, 0.000637f, 0.754395f, 0.000627f, 0.735352f, 0.000615f, 0.715820f, 0.000601f, + 0.695801f, 0.000585f, 0.675781f, 0.000568f, 0.655762f, 0.000550f, 0.635742f, 0.000530f, + 0.615234f, 0.000510f, 0.594727f, 0.000490f, 0.574707f, 0.000469f, 0.554199f, 0.000448f, + 0.534180f, 0.000428f, 0.514648f, 0.000407f, 0.495117f, 0.000387f, 0.475830f, 0.000367f, + 0.456787f, 0.000348f, 0.438232f, 0.000329f, 0.420166f, 0.000311f, 0.402344f, 0.000294f, + 0.385254f, 0.000277f, 0.368408f, 0.000262f, 0.352051f, 0.000246f, 0.336182f, 0.000232f, + 0.999512f, 0.000072f, 0.999512f, 0.000072f, 0.999512f, 0.000072f, 0.999512f, 0.000072f, + 0.999512f, 0.000073f, 0.999512f, 0.000076f, 0.999512f, 0.000078f, 0.999512f, 0.000082f, + 0.999023f, 0.000086f, 0.999023f, 0.000095f, 0.998535f, 0.000102f, 0.998047f, 0.000116f, + 0.998047f, 0.000131f, 0.997070f, 0.000147f, 0.996094f, 0.000167f, 0.995117f, 0.000195f, + 0.993652f, 0.000219f, 0.991699f, 0.000246f, 0.989746f, 0.000278f, 0.987305f, 0.000315f, + 0.984375f, 0.000350f, 0.980957f, 0.000385f, 0.976562f, 0.000427f, 0.972168f, 0.000467f, + 0.967285f, 0.000509f, 0.960938f, 0.000548f, 0.954102f, 0.000587f, 0.946777f, 0.000623f, + 0.937988f, 0.000657f, 0.928711f, 0.000690f, 0.918457f, 0.000718f, 0.907715f, 0.000741f, + 0.895508f, 0.000762f, 0.882812f, 0.000778f, 0.869141f, 0.000791f, 0.854492f, 0.000798f, + 0.839355f, 0.000802f, 0.823242f, 0.000801f, 0.806152f, 0.000796f, 0.789062f, 0.000788f, + 0.770996f, 0.000777f, 0.752930f, 0.000762f, 0.733887f, 0.000745f, 0.714844f, 0.000726f, + 0.695312f, 0.000704f, 0.675293f, 0.000682f, 0.655273f, 0.000658f, 0.635254f, 0.000633f, + 0.615234f, 0.000607f, 0.595215f, 0.000582f, 0.575195f, 0.000556f, 0.555176f, 0.000530f, + 0.535645f, 0.000504f, 0.515625f, 0.000479f, 0.496582f, 0.000455f, 0.477539f, 0.000431f, + 0.458984f, 0.000407f, 0.440430f, 0.000385f, 0.422363f, 0.000363f, 0.404785f, 0.000343f, + 0.387695f, 0.000323f, 0.370850f, 0.000304f, 0.354736f, 0.000286f, 0.338867f, 0.000268f, + 0.999512f, 0.000119f, 0.999512f, 0.000119f, 0.999512f, 0.000119f, 0.999512f, 0.000119f, + 0.999512f, 0.000121f, 0.999512f, 0.000122f, 0.999512f, 0.000128f, 0.999512f, 0.000131f, + 0.999512f, 0.000139f, 0.999023f, 0.000149f, 0.998535f, 0.000161f, 0.998047f, 0.000179f, + 0.998047f, 0.000194f, 0.997070f, 0.000220f, 0.996094f, 0.000247f, 0.994629f, 0.000275f, + 0.993652f, 0.000309f, 0.991699f, 0.000344f, 0.989746f, 0.000385f, 0.986816f, 0.000429f, + 0.983887f, 0.000471f, 0.980469f, 0.000519f, 0.976074f, 0.000565f, 0.971680f, 0.000614f, + 0.966309f, 0.000664f, 0.959961f, 0.000710f, 0.953125f, 0.000754f, 0.945312f, 0.000797f, + 0.936523f, 0.000837f, 0.927246f, 0.000873f, 0.916992f, 0.000902f, 0.905762f, 0.000929f, + 0.893555f, 0.000950f, 0.880859f, 0.000966f, 0.866699f, 0.000977f, 0.852539f, 0.000981f, + 0.836914f, 0.000981f, 0.821289f, 0.000977f, 0.804688f, 0.000968f, 0.787109f, 0.000955f, + 0.769531f, 0.000937f, 0.751465f, 0.000917f, 0.732422f, 0.000894f, 0.713379f, 0.000868f, + 0.694336f, 0.000840f, 0.674805f, 0.000811f, 0.655273f, 0.000780f, 0.635254f, 0.000749f, + 0.615723f, 0.000716f, 0.595703f, 0.000685f, 0.575684f, 0.000653f, 0.556152f, 0.000621f, + 0.536621f, 0.000590f, 0.517090f, 0.000559f, 0.498291f, 0.000530f, 0.479492f, 0.000501f, + 0.460938f, 0.000473f, 0.442627f, 0.000446f, 0.424805f, 0.000420f, 0.407227f, 0.000396f, + 0.390137f, 0.000373f, 0.373535f, 0.000350f, 0.357422f, 0.000329f, 0.341553f, 0.000309f, + 0.999512f, 0.000187f, 0.999512f, 0.000187f, 0.999512f, 0.000188f, 0.999512f, 0.000188f, + 0.999512f, 0.000190f, 0.999512f, 0.000194f, 0.999512f, 0.000201f, 0.999023f, 0.000204f, + 0.999023f, 0.000213f, 0.999023f, 0.000228f, 0.998535f, 0.000242f, 0.998535f, 0.000264f, + 0.997559f, 0.000285f, 0.997070f, 0.000311f, 0.996094f, 0.000351f, 0.995117f, 0.000386f, + 0.993164f, 0.000429f, 0.991211f, 0.000470f, 0.989258f, 0.000520f, 0.986328f, 0.000575f, + 0.983398f, 0.000628f, 0.979492f, 0.000683f, 0.975586f, 0.000741f, 0.970703f, 0.000801f, + 0.965332f, 0.000855f, 0.958984f, 0.000910f, 0.951660f, 0.000961f, 0.943848f, 0.001009f, + 0.935059f, 0.001053f, 0.925781f, 0.001090f, 0.915039f, 0.001123f, 0.903809f, 0.001152f, + 0.891602f, 0.001172f, 0.878906f, 0.001186f, 0.864746f, 0.001194f, 0.850586f, 0.001195f, + 0.835449f, 0.001191f, 0.819336f, 0.001181f, 0.802734f, 0.001164f, 0.785645f, 0.001144f, + 0.768066f, 0.001121f, 0.750000f, 0.001092f, 0.731445f, 0.001061f, 0.712402f, 0.001027f, + 0.693359f, 0.000992f, 0.674316f, 0.000955f, 0.654785f, 0.000916f, 0.635254f, 0.000877f, + 0.615723f, 0.000838f, 0.596191f, 0.000799f, 0.576660f, 0.000760f, 0.557129f, 0.000721f, + 0.538086f, 0.000684f, 0.518555f, 0.000648f, 0.500000f, 0.000612f, 0.481445f, 0.000578f, + 0.462891f, 0.000545f, 0.444824f, 0.000513f, 0.427246f, 0.000483f, 0.409912f, 0.000454f, + 0.392822f, 0.000427f, 0.376221f, 0.000401f, 0.360107f, 0.000376f, 0.344482f, 0.000353f, + 0.999512f, 0.000284f, 0.999512f, 0.000284f, 0.999512f, 0.000284f, 0.999512f, 0.000285f, + 0.999512f, 0.000287f, 0.999512f, 0.000292f, 0.999512f, 0.000296f, 0.999023f, 0.000307f, + 0.999023f, 0.000320f, 0.999023f, 0.000338f, 0.998535f, 0.000349f, 0.998047f, 0.000381f, + 0.997559f, 0.000407f, 0.996582f, 0.000447f, 0.995605f, 0.000480f, 0.994629f, 0.000531f, + 0.992676f, 0.000579f, 0.990723f, 0.000637f, 0.988770f, 0.000693f, 0.985840f, 0.000755f, + 0.982422f, 0.000824f, 0.979004f, 0.000889f, 0.975098f, 0.000958f, 0.969727f, 0.001024f, + 0.963867f, 0.001090f, 0.957520f, 0.001152f, 0.950684f, 0.001211f, 0.942383f, 0.001263f, + 0.933594f, 0.001309f, 0.923828f, 0.001353f, 0.913086f, 0.001387f, 0.901855f, 0.001413f, + 0.889648f, 0.001432f, 0.876465f, 0.001443f, 0.862793f, 0.001446f, 0.848145f, 0.001442f, + 0.833008f, 0.001431f, 0.817383f, 0.001413f, 0.800781f, 0.001390f, 0.783691f, 0.001362f, + 0.766113f, 0.001328f, 0.748535f, 0.001291f, 0.729980f, 0.001250f, 0.711426f, 0.001207f, + 0.692871f, 0.001163f, 0.673828f, 0.001116f, 0.654785f, 0.001068f, 0.635254f, 0.001020f, + 0.616211f, 0.000973f, 0.596680f, 0.000926f, 0.577637f, 0.000878f, 0.558105f, 0.000833f, + 0.539062f, 0.000788f, 0.520508f, 0.000745f, 0.501465f, 0.000702f, 0.483154f, 0.000663f, + 0.465088f, 0.000624f, 0.447266f, 0.000587f, 0.429443f, 0.000552f, 0.412354f, 0.000518f, + 0.395508f, 0.000486f, 0.378906f, 0.000456f, 0.363037f, 0.000427f, 0.347168f, 0.000400f, + 0.999512f, 0.000417f, 0.999512f, 0.000417f, 0.999512f, 0.000418f, 0.999512f, 0.000419f, + 0.999512f, 0.000422f, 0.999512f, 0.000425f, 0.999023f, 0.000434f, 0.999023f, 0.000447f, + 0.999023f, 0.000462f, 0.999023f, 0.000480f, 0.998047f, 0.000508f, 0.998047f, 0.000538f, + 0.997070f, 0.000576f, 0.996582f, 0.000621f, 0.995605f, 0.000669f, 0.993652f, 0.000721f, + 0.992188f, 0.000784f, 0.990723f, 0.000849f, 0.987793f, 0.000918f, 0.985840f, 0.000996f, + 0.982422f, 0.001071f, 0.978516f, 0.001148f, 0.973633f, 0.001225f, 0.968750f, 0.001304f, + 0.962891f, 0.001378f, 0.956543f, 0.001447f, 0.948730f, 0.001511f, 0.940918f, 0.001568f, + 0.931641f, 0.001617f, 0.921875f, 0.001660f, 0.911621f, 0.001697f, 0.899902f, 0.001719f, + 0.887695f, 0.001735f, 0.874512f, 0.001740f, 0.860840f, 0.001738f, 0.846191f, 0.001725f, + 0.831055f, 0.001706f, 0.815430f, 0.001679f, 0.798828f, 0.001646f, 0.782227f, 0.001607f, + 0.764648f, 0.001562f, 0.747070f, 0.001514f, 0.729004f, 0.001462f, 0.710449f, 0.001409f, + 0.691895f, 0.001352f, 0.673340f, 0.001295f, 0.654297f, 0.001237f, 0.635254f, 0.001179f, + 0.616211f, 0.001122f, 0.597168f, 0.001065f, 0.578125f, 0.001010f, 0.559570f, 0.000955f, + 0.540527f, 0.000902f, 0.521973f, 0.000852f, 0.503418f, 0.000803f, 0.485352f, 0.000755f, + 0.467285f, 0.000710f, 0.449463f, 0.000668f, 0.431885f, 0.000626f, 0.414795f, 0.000587f, + 0.398193f, 0.000551f, 0.381836f, 0.000516f, 0.365723f, 0.000483f, 0.350098f, 0.000452f, + 0.999023f, 0.000597f, 0.999023f, 0.000597f, 0.999023f, 0.000597f, 0.999023f, 0.000598f, + 0.999023f, 0.000602f, 0.999023f, 0.000610f, 0.999023f, 0.000618f, 0.999023f, 0.000632f, + 0.998535f, 0.000651f, 0.998535f, 0.000675f, 0.998047f, 0.000704f, 0.997559f, 0.000742f, + 0.997070f, 0.000787f, 0.996094f, 0.000843f, 0.995117f, 0.000902f, 0.993652f, 0.000966f, + 0.992188f, 0.001039f, 0.990234f, 0.001117f, 0.987793f, 0.001197f, 0.984863f, 0.001286f, + 0.981445f, 0.001372f, 0.977539f, 0.001464f, 0.972656f, 0.001553f, 0.967773f, 0.001639f, + 0.961914f, 0.001722f, 0.955078f, 0.001798f, 0.947754f, 0.001868f, 0.938965f, 0.001928f, + 0.930176f, 0.001982f, 0.920410f, 0.002026f, 0.909668f, 0.002056f, 0.897949f, 0.002075f, + 0.885254f, 0.002085f, 0.872559f, 0.002083f, 0.858398f, 0.002071f, 0.844238f, 0.002048f, + 0.828613f, 0.002018f, 0.812988f, 0.001980f, 0.796875f, 0.001934f, 0.780273f, 0.001883f, + 0.763184f, 0.001824f, 0.745605f, 0.001763f, 0.728027f, 0.001698f, 0.709473f, 0.001632f, + 0.691406f, 0.001563f, 0.672852f, 0.001494f, 0.654297f, 0.001422f, 0.635254f, 0.001355f, + 0.616699f, 0.001286f, 0.598145f, 0.001218f, 0.579102f, 0.001152f, 0.560547f, 0.001089f, + 0.541992f, 0.001027f, 0.523438f, 0.000968f, 0.505371f, 0.000911f, 0.487305f, 0.000857f, + 0.469482f, 0.000804f, 0.451904f, 0.000755f, 0.434570f, 0.000708f, 0.417480f, 0.000663f, + 0.400879f, 0.000621f, 0.384521f, 0.000581f, 0.368652f, 0.000544f, 0.353027f, 0.000508f, + 0.999023f, 0.000833f, 0.999023f, 0.000833f, 0.999023f, 0.000834f, 0.999023f, 0.000835f, + 0.999023f, 0.000840f, 0.999023f, 0.000845f, 0.998535f, 0.000861f, 0.998535f, 0.000875f, + 0.998535f, 0.000897f, 0.998047f, 0.000928f, 0.997559f, 0.000965f, 0.997070f, 0.001007f, + 0.996582f, 0.001061f, 0.995605f, 0.001128f, 0.994629f, 0.001195f, 0.993164f, 0.001276f, + 0.991699f, 0.001362f, 0.989258f, 0.001453f, 0.986816f, 0.001539f, 0.983887f, 0.001645f, + 0.980469f, 0.001747f, 0.976562f, 0.001849f, 0.971680f, 0.001945f, 0.966309f, 0.002045f, + 0.959961f, 0.002136f, 0.953613f, 0.002218f, 0.945801f, 0.002291f, 0.937500f, 0.002357f, + 0.928223f, 0.002407f, 0.917969f, 0.002447f, 0.907227f, 0.002472f, 0.895508f, 0.002487f, + 0.883301f, 0.002485f, 0.870117f, 0.002474f, 0.856445f, 0.002451f, 0.841797f, 0.002417f, + 0.826660f, 0.002373f, 0.811035f, 0.002317f, 0.794922f, 0.002258f, 0.778320f, 0.002190f, + 0.761230f, 0.002117f, 0.744141f, 0.002041f, 0.726562f, 0.001961f, 0.708496f, 0.001880f, + 0.690430f, 0.001796f, 0.672363f, 0.001713f, 0.654297f, 0.001630f, 0.635742f, 0.001547f, + 0.617188f, 0.001466f, 0.598633f, 0.001387f, 0.580078f, 0.001310f, 0.561523f, 0.001235f, + 0.543457f, 0.001164f, 0.524902f, 0.001095f, 0.507324f, 0.001029f, 0.489258f, 0.000967f, + 0.471680f, 0.000906f, 0.454346f, 0.000850f, 0.437012f, 0.000796f, 0.420166f, 0.000745f, + 0.403564f, 0.000698f, 0.387451f, 0.000652f, 0.371582f, 0.000609f, 0.356201f, 0.000569f, + 0.998535f, 0.001139f, 0.998535f, 0.001139f, 0.998535f, 0.001140f, 0.998535f, 0.001142f, + 0.998535f, 0.001147f, 0.998535f, 0.001159f, 0.998535f, 0.001168f, 0.998047f, 0.001190f, + 0.998047f, 0.001217f, 0.997559f, 0.001254f, 0.997559f, 0.001301f, 0.997070f, 0.001356f, + 0.996094f, 0.001416f, 0.995605f, 0.001493f, 0.994141f, 0.001574f, 0.992676f, 0.001663f, + 0.990723f, 0.001759f, 0.988770f, 0.001867f, 0.986328f, 0.001980f, 0.982910f, 0.002087f, + 0.979492f, 0.002199f, 0.975586f, 0.002319f, 0.970703f, 0.002422f, 0.965332f, 0.002531f, + 0.958496f, 0.002628f, 0.952148f, 0.002714f, 0.944336f, 0.002792f, 0.935547f, 0.002851f, + 0.926270f, 0.002903f, 0.916016f, 0.002935f, 0.904785f, 0.002954f, 0.893066f, 0.002956f, + 0.880859f, 0.002947f, 0.867676f, 0.002920f, 0.853516f, 0.002882f, 0.839355f, 0.002831f, + 0.824219f, 0.002769f, 0.809082f, 0.002699f, 0.792969f, 0.002619f, 0.776367f, 0.002533f, + 0.759766f, 0.002443f, 0.742676f, 0.002350f, 0.725586f, 0.002251f, 0.708008f, 0.002151f, + 0.689941f, 0.002052f, 0.671875f, 0.001953f, 0.653809f, 0.001854f, 0.635742f, 0.001758f, + 0.617676f, 0.001663f, 0.599121f, 0.001572f, 0.581055f, 0.001482f, 0.562988f, 0.001395f, + 0.544922f, 0.001313f, 0.526855f, 0.001234f, 0.508789f, 0.001158f, 0.491455f, 0.001086f, + 0.473877f, 0.001018f, 0.456787f, 0.000954f, 0.439697f, 0.000892f, 0.422852f, 0.000834f, + 0.406494f, 0.000780f, 0.390381f, 0.000729f, 0.374512f, 0.000680f, 0.359131f, 0.000635f, + 0.998047f, 0.001528f, 0.998047f, 0.001528f, 0.998047f, 0.001529f, 0.998047f, 0.001532f, + 0.998047f, 0.001539f, 0.998047f, 0.001546f, 0.998047f, 0.001562f, 0.998047f, 0.001589f, + 0.997559f, 0.001621f, 0.997559f, 0.001668f, 0.996582f, 0.001715f, 0.996582f, 0.001777f, + 0.995605f, 0.001859f, 0.994629f, 0.001939f, 0.993652f, 0.002035f, 0.992188f, 0.002140f, + 0.990234f, 0.002243f, 0.987793f, 0.002369f, 0.985352f, 0.002489f, 0.981934f, 0.002621f, + 0.978516f, 0.002750f, 0.974121f, 0.002876f, 0.969238f, 0.002991f, 0.963867f, 0.003105f, + 0.957031f, 0.003206f, 0.950195f, 0.003300f, 0.942383f, 0.003374f, 0.933594f, 0.003431f, + 0.923828f, 0.003473f, 0.913574f, 0.003498f, 0.902344f, 0.003506f, 0.890625f, 0.003494f, + 0.878418f, 0.003468f, 0.865234f, 0.003426f, 0.851074f, 0.003366f, 0.836914f, 0.003296f, + 0.822266f, 0.003216f, 0.806641f, 0.003122f, 0.791016f, 0.003023f, 0.774902f, 0.002916f, + 0.758301f, 0.002804f, 0.741211f, 0.002689f, 0.724121f, 0.002573f, 0.707031f, 0.002453f, + 0.689453f, 0.002335f, 0.671875f, 0.002216f, 0.653809f, 0.002102f, 0.636230f, 0.001987f, + 0.618164f, 0.001878f, 0.600098f, 0.001771f, 0.582031f, 0.001668f, 0.564453f, 0.001569f, + 0.546387f, 0.001475f, 0.528809f, 0.001384f, 0.511230f, 0.001297f, 0.493652f, 0.001217f, + 0.476318f, 0.001139f, 0.459229f, 0.001065f, 0.442383f, 0.000996f, 0.425781f, 0.000930f, + 0.409424f, 0.000869f, 0.393311f, 0.000811f, 0.377686f, 0.000757f, 0.362305f, 0.000707f, + 0.997559f, 0.002018f, 0.997559f, 0.002018f, 0.997559f, 0.002018f, 0.997559f, 0.002022f, + 0.997559f, 0.002028f, 0.997559f, 0.002045f, 0.997559f, 0.002066f, 0.997559f, 0.002092f, + 0.997559f, 0.002129f, 0.996582f, 0.002176f, 0.996094f, 0.002235f, 0.995605f, 0.002312f, + 0.995605f, 0.002407f, 0.993652f, 0.002491f, 0.992676f, 0.002605f, 0.991211f, 0.002729f, + 0.989258f, 0.002846f, 0.987305f, 0.002987f, 0.984375f, 0.003120f, 0.980957f, 0.003263f, + 0.977051f, 0.003403f, 0.972656f, 0.003542f, 0.967285f, 0.003666f, 0.961914f, 0.003782f, + 0.955566f, 0.003889f, 0.947754f, 0.003967f, 0.939941f, 0.004044f, 0.931152f, 0.004097f, + 0.921387f, 0.004131f, 0.911133f, 0.004139f, 0.899902f, 0.004131f, 0.888184f, 0.004108f, + 0.875488f, 0.004055f, 0.862305f, 0.003990f, 0.848633f, 0.003914f, 0.834473f, 0.003819f, + 0.819824f, 0.003712f, 0.804199f, 0.003593f, 0.788574f, 0.003469f, 0.772949f, 0.003338f, + 0.756348f, 0.003201f, 0.739746f, 0.003063f, 0.723145f, 0.002924f, 0.706055f, 0.002781f, + 0.688965f, 0.002644f, 0.671387f, 0.002506f, 0.653809f, 0.002371f, 0.636230f, 0.002239f, + 0.618652f, 0.002111f, 0.601074f, 0.001989f, 0.583496f, 0.001871f, 0.565430f, 0.001759f, + 0.547852f, 0.001650f, 0.530273f, 0.001547f, 0.513184f, 0.001449f, 0.495850f, 0.001356f, + 0.478760f, 0.001269f, 0.461670f, 0.001185f, 0.445068f, 0.001107f, 0.428467f, 0.001035f, + 0.412354f, 0.000965f, 0.396240f, 0.000901f, 0.380615f, 0.000840f, 0.365479f, 0.000783f, + 0.997070f, 0.002625f, 0.997070f, 0.002625f, 0.997070f, 0.002626f, 0.997070f, 0.002630f, + 0.997070f, 0.002640f, 0.997070f, 0.002659f, 0.997070f, 0.002676f, 0.996582f, 0.002708f, + 0.996582f, 0.002752f, 0.996094f, 0.002813f, 0.995605f, 0.002886f, 0.995117f, 0.002956f, + 0.994141f, 0.003071f, 0.992676f, 0.003172f, 0.991699f, 0.003292f, 0.990234f, 0.003433f, + 0.988281f, 0.003580f, 0.985840f, 0.003727f, 0.982910f, 0.003870f, 0.979492f, 0.004028f, + 0.975586f, 0.004177f, 0.971191f, 0.004322f, 0.966309f, 0.004456f, 0.959961f, 0.004570f, + 0.953125f, 0.004669f, 0.945801f, 0.004757f, 0.937500f, 0.004826f, 0.928711f, 0.004864f, + 0.918945f, 0.004883f, 0.908691f, 0.004875f, 0.897461f, 0.004845f, 0.885254f, 0.004795f, + 0.872559f, 0.004723f, 0.859863f, 0.004631f, 0.846191f, 0.004520f, 0.832031f, 0.004398f, + 0.817383f, 0.004261f, 0.802246f, 0.004116f, 0.786621f, 0.003963f, 0.770996f, 0.003805f, + 0.754883f, 0.003639f, 0.738770f, 0.003475f, 0.722168f, 0.003307f, 0.705078f, 0.003143f, + 0.688477f, 0.002981f, 0.671387f, 0.002821f, 0.653809f, 0.002665f, 0.636719f, 0.002512f, + 0.619141f, 0.002367f, 0.602051f, 0.002226f, 0.584473f, 0.002090f, 0.566895f, 0.001963f, + 0.549805f, 0.001840f, 0.532227f, 0.001722f, 0.515137f, 0.001613f, 0.498047f, 0.001508f, + 0.481201f, 0.001409f, 0.464355f, 0.001316f, 0.447754f, 0.001228f, 0.431396f, 0.001145f, + 0.415283f, 0.001069f, 0.399414f, 0.000997f, 0.383789f, 0.000929f, 0.368652f, 0.000865f, + 0.996582f, 0.003370f, 0.996582f, 0.003370f, 0.996582f, 0.003372f, 0.996582f, 0.003378f, + 0.996582f, 0.003389f, 0.996094f, 0.003410f, 0.996094f, 0.003435f, 0.996094f, 0.003471f, + 0.996094f, 0.003523f, 0.995117f, 0.003588f, 0.995117f, 0.003664f, 0.994141f, 0.003754f, + 0.993164f, 0.003864f, 0.992676f, 0.003990f, 0.990723f, 0.004128f, 0.989746f, 0.004288f, + 0.987793f, 0.004429f, 0.984375f, 0.004601f, 0.981445f, 0.004757f, 0.978027f, 0.004925f, + 0.974121f, 0.005089f, 0.969727f, 0.005241f, 0.964355f, 0.005375f, 0.958008f, 0.005486f, + 0.951172f, 0.005596f, 0.943848f, 0.005665f, 0.935547f, 0.005718f, 0.925781f, 0.005737f, + 0.916016f, 0.005733f, 0.905762f, 0.005707f, 0.894531f, 0.005650f, 0.882324f, 0.005569f, + 0.870117f, 0.005466f, 0.856934f, 0.005341f, 0.843262f, 0.005199f, 0.829102f, 0.005043f, + 0.814941f, 0.004871f, 0.799805f, 0.004692f, 0.784668f, 0.004505f, 0.769043f, 0.004314f, + 0.753418f, 0.004116f, 0.737305f, 0.003922f, 0.721191f, 0.003729f, 0.704590f, 0.003536f, + 0.687988f, 0.003347f, 0.670898f, 0.003162f, 0.654297f, 0.002983f, 0.637207f, 0.002810f, + 0.620117f, 0.002642f, 0.603027f, 0.002481f, 0.585938f, 0.002329f, 0.568359f, 0.002182f, + 0.551270f, 0.002045f, 0.534180f, 0.001913f, 0.517090f, 0.001788f, 0.500488f, 0.001671f, + 0.483643f, 0.001560f, 0.467041f, 0.001456f, 0.450684f, 0.001358f, 0.434326f, 0.001266f, + 0.418213f, 0.001181f, 0.402588f, 0.001101f, 0.386963f, 0.001025f, 0.371826f, 0.000954f, + 0.995605f, 0.004276f, 0.995605f, 0.004276f, 0.995605f, 0.004280f, 0.995605f, 0.004284f, + 0.995605f, 0.004299f, 0.995117f, 0.004318f, 0.995117f, 0.004349f, 0.995117f, 0.004383f, + 0.994629f, 0.004456f, 0.994629f, 0.004524f, 0.994141f, 0.004612f, 0.993164f, 0.004704f, + 0.992676f, 0.004848f, 0.991699f, 0.004974f, 0.990234f, 0.005142f, 0.987793f, 0.005291f, + 0.986328f, 0.005474f, 0.982910f, 0.005638f, 0.980469f, 0.005825f, 0.976562f, 0.005989f, + 0.972656f, 0.006157f, 0.967773f, 0.006313f, 0.961914f, 0.006443f, 0.955566f, 0.006554f, + 0.948730f, 0.006645f, 0.940918f, 0.006702f, 0.932617f, 0.006733f, 0.923340f, 0.006733f, + 0.913574f, 0.006699f, 0.902832f, 0.006645f, 0.891602f, 0.006550f, 0.879395f, 0.006435f, + 0.867188f, 0.006294f, 0.854004f, 0.006130f, 0.840332f, 0.005951f, 0.826660f, 0.005756f, + 0.812500f, 0.005543f, 0.797363f, 0.005325f, 0.782715f, 0.005100f, 0.767090f, 0.004871f, + 0.751465f, 0.004642f, 0.735840f, 0.004414f, 0.719727f, 0.004185f, 0.703613f, 0.003960f, + 0.687500f, 0.003744f, 0.670898f, 0.003531f, 0.654297f, 0.003326f, 0.637695f, 0.003128f, + 0.620605f, 0.002939f, 0.604004f, 0.002756f, 0.586914f, 0.002584f, 0.569824f, 0.002420f, + 0.553223f, 0.002264f, 0.536133f, 0.002117f, 0.519531f, 0.001978f, 0.502930f, 0.001847f, + 0.486328f, 0.001723f, 0.469727f, 0.001607f, 0.453369f, 0.001498f, 0.437256f, 0.001395f, + 0.421387f, 0.001300f, 0.405762f, 0.001211f, 0.390381f, 0.001127f, 0.375244f, 0.001050f, + 0.994141f, 0.005367f, 0.994141f, 0.005367f, 0.994141f, 0.005371f, 0.994141f, 0.005375f, + 0.994141f, 0.005394f, 0.994141f, 0.005413f, 0.994141f, 0.005447f, 0.994141f, 0.005508f, + 0.993652f, 0.005558f, 0.993652f, 0.005650f, 0.992676f, 0.005741f, 0.991699f, 0.005848f, + 0.991211f, 0.006004f, 0.990234f, 0.006149f, 0.988281f, 0.006317f, 0.986328f, 0.006504f, + 0.984863f, 0.006687f, 0.981934f, 0.006866f, 0.978516f, 0.007050f, 0.974609f, 0.007233f, + 0.970215f, 0.007393f, 0.965820f, 0.007553f, 0.959961f, 0.007675f, 0.953125f, 0.007774f, + 0.946289f, 0.007843f, 0.938477f, 0.007889f, 0.929688f, 0.007889f, 0.920410f, 0.007858f, + 0.910156f, 0.007793f, 0.899414f, 0.007694f, 0.888672f, 0.007565f, 0.876465f, 0.007401f, + 0.864258f, 0.007214f, 0.851074f, 0.007008f, 0.837402f, 0.006779f, 0.823730f, 0.006535f, + 0.809570f, 0.006279f, 0.794922f, 0.006023f, 0.780273f, 0.005753f, 0.765137f, 0.005482f, + 0.750000f, 0.005215f, 0.734375f, 0.004944f, 0.718750f, 0.004681f, 0.703125f, 0.004425f, + 0.687012f, 0.004173f, 0.670898f, 0.003929f, 0.654297f, 0.003700f, 0.638184f, 0.003473f, + 0.621582f, 0.003260f, 0.604980f, 0.003056f, 0.588379f, 0.002861f, 0.571777f, 0.002676f, + 0.555176f, 0.002502f, 0.538574f, 0.002337f, 0.521973f, 0.002180f, 0.505371f, 0.002035f, + 0.488770f, 0.001898f, 0.472656f, 0.001769f, 0.456299f, 0.001649f, 0.440430f, 0.001534f, + 0.424561f, 0.001430f, 0.408936f, 0.001329f, 0.393555f, 0.001238f, 0.378418f, 0.001151f, + 0.993164f, 0.006672f, 0.993164f, 0.006672f, 0.993164f, 0.006676f, 0.993164f, 0.006687f, + 0.993164f, 0.006699f, 0.993164f, 0.006721f, 0.992676f, 0.006760f, 0.992676f, 0.006821f, + 0.992188f, 0.006897f, 0.991699f, 0.006973f, 0.991211f, 0.007099f, 0.990234f, 0.007206f, + 0.990234f, 0.007366f, 0.988281f, 0.007519f, 0.986328f, 0.007706f, 0.984863f, 0.007912f, + 0.982422f, 0.008087f, 0.979980f, 0.008286f, 0.977051f, 0.008476f, 0.972656f, 0.008667f, + 0.968262f, 0.008827f, 0.962891f, 0.008980f, 0.957520f, 0.009079f, 0.951172f, 0.009171f, + 0.943848f, 0.009216f, 0.935547f, 0.009224f, 0.926758f, 0.009193f, 0.917480f, 0.009125f, + 0.906738f, 0.009010f, 0.895996f, 0.008865f, 0.885254f, 0.008682f, 0.873047f, 0.008469f, + 0.860840f, 0.008232f, 0.847656f, 0.007973f, 0.834473f, 0.007690f, 0.820801f, 0.007397f, + 0.807129f, 0.007092f, 0.792969f, 0.006783f, 0.778320f, 0.006462f, 0.763184f, 0.006145f, + 0.748535f, 0.005833f, 0.733398f, 0.005524f, 0.717773f, 0.005219f, 0.702148f, 0.004925f, + 0.686523f, 0.004639f, 0.670898f, 0.004364f, 0.654785f, 0.004097f, 0.638672f, 0.003847f, + 0.622559f, 0.003605f, 0.605957f, 0.003376f, 0.589844f, 0.003157f, 0.573242f, 0.002951f, + 0.556641f, 0.002756f, 0.540527f, 0.002573f, 0.523926f, 0.002399f, 0.507812f, 0.002237f, + 0.491455f, 0.002085f, 0.475342f, 0.001943f, 0.459229f, 0.001809f, 0.443359f, 0.001684f, + 0.427734f, 0.001567f, 0.412109f, 0.001457f, 0.396973f, 0.001356f, 0.382080f, 0.001261f, + 0.991699f, 0.008217f, 0.991699f, 0.008217f, 0.991699f, 0.008217f, 0.991699f, 0.008232f, + 0.991211f, 0.008240f, 0.991211f, 0.008270f, 0.991211f, 0.008324f, 0.991211f, 0.008377f, + 0.990723f, 0.008461f, 0.990234f, 0.008553f, 0.989746f, 0.008682f, 0.988770f, 0.008820f, + 0.987793f, 0.008972f, 0.986816f, 0.009163f, 0.985352f, 0.009338f, 0.982910f, 0.009567f, + 0.980957f, 0.009758f, 0.977539f, 0.009956f, 0.974609f, 0.010155f, 0.970215f, 0.010330f, + 0.965820f, 0.010483f, 0.960449f, 0.010597f, 0.954590f, 0.010696f, 0.947754f, 0.010750f, + 0.940430f, 0.010757f, 0.932129f, 0.010735f, 0.923340f, 0.010651f, 0.913574f, 0.010536f, + 0.903809f, 0.010376f, 0.892578f, 0.010162f, 0.881348f, 0.009926f, 0.869629f, 0.009651f, + 0.857422f, 0.009354f, 0.844727f, 0.009026f, 0.831543f, 0.008690f, 0.817871f, 0.008331f, + 0.804199f, 0.007973f, 0.790527f, 0.007603f, 0.775879f, 0.007233f, 0.761719f, 0.006866f, + 0.747070f, 0.006500f, 0.731934f, 0.006145f, 0.716797f, 0.005798f, 0.701660f, 0.005466f, + 0.686523f, 0.005138f, 0.670898f, 0.004829f, 0.655273f, 0.004532f, 0.639160f, 0.004246f, + 0.623535f, 0.003975f, 0.607422f, 0.003719f, 0.591309f, 0.003477f, 0.575195f, 0.003246f, + 0.558594f, 0.003029f, 0.542480f, 0.002827f, 0.526367f, 0.002634f, 0.510254f, 0.002455f, + 0.494141f, 0.002285f, 0.478271f, 0.002129f, 0.462402f, 0.001980f, 0.446533f, 0.001843f, + 0.430908f, 0.001715f, 0.415527f, 0.001594f, 0.400391f, 0.001483f, 0.385498f, 0.001378f, + 0.989746f, 0.010040f, 0.989746f, 0.010040f, 0.989746f, 0.010040f, 0.989746f, 0.010048f, + 0.989746f, 0.010071f, 0.989746f, 0.010094f, 0.989258f, 0.010147f, 0.989258f, 0.010223f, + 0.988770f, 0.010300f, 0.988770f, 0.010406f, 0.987793f, 0.010529f, 0.986816f, 0.010696f, + 0.986328f, 0.010857f, 0.984863f, 0.011055f, 0.982422f, 0.011238f, 0.981445f, 0.011467f, + 0.978516f, 0.011673f, 0.975098f, 0.011871f, 0.972168f, 0.012062f, 0.967285f, 0.012215f, + 0.962402f, 0.012352f, 0.957031f, 0.012459f, 0.951172f, 0.012535f, 0.944336f, 0.012535f, + 0.937012f, 0.012520f, 0.928711f, 0.012428f, 0.919922f, 0.012299f, 0.910156f, 0.012115f, + 0.899414f, 0.011879f, 0.889160f, 0.011612f, 0.877441f, 0.011299f, 0.865723f, 0.010956f, + 0.853516f, 0.010582f, 0.841309f, 0.010193f, 0.828125f, 0.009773f, 0.814941f, 0.009361f, + 0.801270f, 0.008926f, 0.787598f, 0.008499f, 0.773926f, 0.008064f, 0.759766f, 0.007641f, + 0.745117f, 0.007225f, 0.730469f, 0.006817f, 0.716309f, 0.006424f, 0.701172f, 0.006042f, + 0.686035f, 0.005676f, 0.670898f, 0.005329f, 0.655273f, 0.004993f, 0.640137f, 0.004673f, + 0.624512f, 0.004372f, 0.608398f, 0.004086f, 0.592773f, 0.003817f, 0.576660f, 0.003561f, + 0.561035f, 0.003323f, 0.544922f, 0.003098f, 0.528809f, 0.002884f, 0.512695f, 0.002686f, + 0.497070f, 0.002501f, 0.481201f, 0.002327f, 0.465332f, 0.002165f, 0.449707f, 0.002014f, + 0.434326f, 0.001873f, 0.418945f, 0.001740f, 0.403809f, 0.001617f, 0.388916f, 0.001504f, + 0.987793f, 0.012169f, 0.987793f, 0.012169f, 0.987793f, 0.012169f, 0.987793f, 0.012184f, + 0.987305f, 0.012207f, 0.987305f, 0.012245f, 0.987305f, 0.012291f, 0.986816f, 0.012360f, + 0.986816f, 0.012459f, 0.986328f, 0.012573f, 0.985840f, 0.012695f, 0.984863f, 0.012878f, + 0.983887f, 0.013046f, 0.982422f, 0.013237f, 0.980469f, 0.013466f, 0.979004f, 0.013680f, + 0.976074f, 0.013878f, 0.972656f, 0.014069f, 0.969238f, 0.014259f, 0.964355f, 0.014397f, + 0.959961f, 0.014488f, 0.954102f, 0.014580f, 0.947754f, 0.014595f, 0.940430f, 0.014557f, + 0.933105f, 0.014481f, 0.925293f, 0.014328f, 0.915527f, 0.014122f, 0.906250f, 0.013870f, + 0.895996f, 0.013565f, 0.885254f, 0.013206f, 0.873535f, 0.012817f, 0.862305f, 0.012383f, + 0.850098f, 0.011932f, 0.837891f, 0.011452f, 0.824707f, 0.010963f, 0.812012f, 0.010460f, + 0.798828f, 0.009964f, 0.785156f, 0.009460f, 0.771484f, 0.008965f, 0.757812f, 0.008484f, + 0.743652f, 0.008003f, 0.729492f, 0.007542f, 0.715332f, 0.007095f, 0.700684f, 0.006668f, + 0.686035f, 0.006256f, 0.670898f, 0.005863f, 0.655762f, 0.005489f, 0.640625f, 0.005135f, + 0.625488f, 0.004799f, 0.609863f, 0.004478f, 0.594238f, 0.004181f, 0.578613f, 0.003901f, + 0.562988f, 0.003635f, 0.547363f, 0.003386f, 0.531250f, 0.003153f, 0.515625f, 0.002935f, + 0.500000f, 0.002729f, 0.484131f, 0.002539f, 0.468506f, 0.002361f, 0.453125f, 0.002195f, + 0.437744f, 0.002041f, 0.422363f, 0.001897f, 0.407471f, 0.001763f, 0.392578f, 0.001637f, + 0.985352f, 0.014641f, 0.985352f, 0.014641f, 0.984863f, 0.014648f, 0.984863f, 0.014656f, + 0.984863f, 0.014679f, 0.984863f, 0.014717f, 0.984863f, 0.014771f, 0.984375f, 0.014839f, + 0.984375f, 0.014938f, 0.983398f, 0.015060f, 0.983398f, 0.015244f, 0.981934f, 0.015388f, + 0.980957f, 0.015587f, 0.979492f, 0.015778f, 0.977539f, 0.015976f, 0.975586f, 0.016190f, + 0.972656f, 0.016388f, 0.969727f, 0.016571f, 0.965820f, 0.016739f, 0.961426f, 0.016861f, + 0.956055f, 0.016922f, 0.950684f, 0.016953f, 0.943848f, 0.016922f, 0.937012f, 0.016815f, + 0.929199f, 0.016663f, 0.920410f, 0.016434f, 0.911621f, 0.016144f, 0.901855f, 0.015793f, + 0.891602f, 0.015411f, 0.880859f, 0.014954f, 0.869629f, 0.014473f, 0.857910f, 0.013947f, + 0.846191f, 0.013390f, 0.833984f, 0.012825f, 0.821289f, 0.012253f, 0.809082f, 0.011665f, + 0.795898f, 0.011086f, 0.782715f, 0.010506f, 0.769531f, 0.009933f, 0.755859f, 0.009377f, + 0.742188f, 0.008842f, 0.728516f, 0.008316f, 0.714355f, 0.007812f, 0.700195f, 0.007336f, + 0.685547f, 0.006874f, 0.670898f, 0.006435f, 0.656250f, 0.006020f, 0.641602f, 0.005623f, + 0.626465f, 0.005253f, 0.611328f, 0.004902f, 0.596191f, 0.004570f, 0.580566f, 0.004261f, + 0.564941f, 0.003967f, 0.549316f, 0.003695f, 0.533691f, 0.003437f, 0.518066f, 0.003199f, + 0.502930f, 0.002975f, 0.487305f, 0.002766f, 0.471680f, 0.002571f, 0.456299f, 0.002388f, + 0.441162f, 0.002220f, 0.426025f, 0.002062f, 0.411133f, 0.001916f, 0.396240f, 0.001781f, + 0.982422f, 0.017502f, 0.982422f, 0.017502f, 0.982422f, 0.017502f, 0.982422f, 0.017517f, + 0.981934f, 0.017532f, 0.981934f, 0.017593f, 0.981934f, 0.017639f, 0.981934f, 0.017731f, + 0.981445f, 0.017838f, 0.980957f, 0.017960f, 0.979980f, 0.018112f, 0.979004f, 0.018295f, + 0.978027f, 0.018478f, 0.975586f, 0.018677f, 0.974609f, 0.018860f, 0.972168f, 0.019073f, + 0.969238f, 0.019287f, 0.965820f, 0.019455f, 0.962402f, 0.019562f, 0.958008f, 0.019653f, + 0.952637f, 0.019653f, 0.946289f, 0.019623f, 0.939453f, 0.019516f, 0.932617f, 0.019348f, + 0.924316f, 0.019089f, 0.916016f, 0.018784f, 0.907227f, 0.018387f, 0.897461f, 0.017944f, + 0.887207f, 0.017426f, 0.876465f, 0.016861f, 0.865234f, 0.016266f, 0.854004f, 0.015640f, + 0.842285f, 0.014999f, 0.830078f, 0.014320f, 0.818359f, 0.013641f, 0.805664f, 0.012962f, + 0.792969f, 0.012291f, 0.780273f, 0.011627f, 0.767090f, 0.010979f, 0.753906f, 0.010345f, + 0.740723f, 0.009735f, 0.727539f, 0.009155f, 0.713867f, 0.008591f, 0.699707f, 0.008049f, + 0.685547f, 0.007534f, 0.671387f, 0.007050f, 0.656738f, 0.006588f, 0.642578f, 0.006149f, + 0.627441f, 0.005737f, 0.612793f, 0.005352f, 0.597656f, 0.004986f, 0.582520f, 0.004642f, + 0.567383f, 0.004322f, 0.551758f, 0.004021f, 0.536621f, 0.003744f, 0.520996f, 0.003481f, + 0.505859f, 0.003235f, 0.490479f, 0.003006f, 0.475098f, 0.002794f, 0.459717f, 0.002596f, + 0.444580f, 0.002411f, 0.429688f, 0.002241f, 0.414795f, 0.002081f, 0.400146f, 0.001933f, + 0.979004f, 0.020798f, 0.979004f, 0.020798f, 0.979004f, 0.020798f, 0.979004f, 0.020813f, + 0.979004f, 0.020844f, 0.978516f, 0.020874f, 0.978516f, 0.020935f, 0.978027f, 0.021027f, + 0.978027f, 0.021149f, 0.977539f, 0.021286f, 0.977051f, 0.021454f, 0.975586f, 0.021622f, + 0.974121f, 0.021820f, 0.972656f, 0.021988f, 0.970215f, 0.022186f, 0.968750f, 0.022385f, + 0.965820f, 0.022552f, 0.961914f, 0.022675f, 0.958008f, 0.022736f, 0.953613f, 0.022751f, + 0.948242f, 0.022736f, 0.942383f, 0.022614f, 0.935547f, 0.022415f, 0.927734f, 0.022156f, + 0.919922f, 0.021790f, 0.911621f, 0.021362f, 0.901855f, 0.020859f, 0.892090f, 0.020279f, + 0.882324f, 0.019638f, 0.872070f, 0.018951f, 0.860840f, 0.018234f, 0.849609f, 0.017487f, + 0.838379f, 0.016708f, 0.826172f, 0.015930f, 0.814453f, 0.015144f, 0.802246f, 0.014359f, + 0.790527f, 0.013588f, 0.777832f, 0.012833f, 0.765137f, 0.012100f, 0.752441f, 0.011383f, + 0.739258f, 0.010696f, 0.726074f, 0.010040f, 0.712891f, 0.009415f, 0.699219f, 0.008812f, + 0.685547f, 0.008240f, 0.671875f, 0.007698f, 0.657715f, 0.007191f, 0.643555f, 0.006710f, + 0.628906f, 0.006252f, 0.614258f, 0.005829f, 0.599609f, 0.005428f, 0.584473f, 0.005051f, + 0.569336f, 0.004704f, 0.554199f, 0.004372f, 0.539062f, 0.004063f, 0.523926f, 0.003780f, + 0.508789f, 0.003513f, 0.493652f, 0.003263f, 0.478271f, 0.003033f, 0.463135f, 0.002817f, + 0.448242f, 0.002615f, 0.433350f, 0.002430f, 0.418457f, 0.002256f, 0.403809f, 0.002094f, + 0.975098f, 0.024582f, 0.975098f, 0.024567f, 0.975098f, 0.024582f, 0.975098f, 0.024597f, + 0.975098f, 0.024628f, 0.975098f, 0.024658f, 0.975098f, 0.024734f, 0.974609f, 0.024826f, + 0.973633f, 0.024933f, 0.973633f, 0.025055f, 0.972656f, 0.025223f, 0.972168f, 0.025421f, + 0.970215f, 0.025589f, 0.968262f, 0.025742f, 0.966309f, 0.025925f, 0.964355f, 0.026108f, + 0.960938f, 0.026230f, 0.957520f, 0.026321f, 0.953613f, 0.026352f, 0.948242f, 0.026260f, + 0.943848f, 0.026154f, 0.937500f, 0.025970f, 0.930664f, 0.025650f, 0.922852f, 0.025253f, + 0.915039f, 0.024765f, 0.906738f, 0.024200f, 0.897461f, 0.023560f, 0.887207f, 0.022827f, + 0.877441f, 0.022064f, 0.866699f, 0.021225f, 0.855957f, 0.020370f, 0.845215f, 0.019470f, + 0.833984f, 0.018570f, 0.822266f, 0.017654f, 0.811035f, 0.016754f, 0.799316f, 0.015854f, + 0.787109f, 0.014984f, 0.775391f, 0.014122f, 0.763184f, 0.013298f, 0.750488f, 0.012489f, + 0.737793f, 0.011726f, 0.725098f, 0.010986f, 0.712402f, 0.010284f, 0.699219f, 0.009621f, + 0.685547f, 0.008987f, 0.671875f, 0.008392f, 0.658203f, 0.007828f, 0.644531f, 0.007305f, + 0.630371f, 0.006802f, 0.615723f, 0.006336f, 0.601562f, 0.005898f, 0.586914f, 0.005489f, + 0.571777f, 0.005104f, 0.557129f, 0.004745f, 0.541992f, 0.004414f, 0.526855f, 0.004101f, + 0.511719f, 0.003809f, 0.496826f, 0.003538f, 0.481689f, 0.003286f, 0.466797f, 0.003052f, + 0.451904f, 0.002832f, 0.437012f, 0.002630f, 0.422363f, 0.002441f, 0.407715f, 0.002268f, + 0.970703f, 0.028870f, 0.970703f, 0.028870f, 0.970703f, 0.028885f, 0.970703f, 0.028900f, + 0.970703f, 0.028915f, 0.970703f, 0.028961f, 0.970215f, 0.029022f, 0.970215f, 0.029114f, + 0.969727f, 0.029251f, 0.968750f, 0.029373f, 0.968262f, 0.029526f, 0.966797f, 0.029678f, + 0.966309f, 0.029877f, 0.964844f, 0.030045f, 0.962402f, 0.030167f, 0.959473f, 0.030304f, + 0.956543f, 0.030411f, 0.953125f, 0.030411f, 0.948242f, 0.030319f, 0.943359f, 0.030197f, + 0.938477f, 0.029968f, 0.931641f, 0.029648f, 0.924805f, 0.029221f, 0.917969f, 0.028687f, + 0.909180f, 0.028030f, 0.900879f, 0.027313f, 0.891602f, 0.026505f, 0.881836f, 0.025620f, + 0.871582f, 0.024673f, 0.861816f, 0.023697f, 0.851074f, 0.022659f, 0.840820f, 0.021622f, + 0.829590f, 0.020569f, 0.818359f, 0.019516f, 0.807129f, 0.018478f, 0.795898f, 0.017456f, + 0.784180f, 0.016464f, 0.772461f, 0.015503f, 0.760742f, 0.014572f, 0.748535f, 0.013672f, + 0.736816f, 0.012817f, 0.724121f, 0.012001f, 0.711914f, 0.011215f, 0.698730f, 0.010483f, + 0.686035f, 0.009789f, 0.672852f, 0.009132f, 0.659180f, 0.008514f, 0.645508f, 0.007935f, + 0.631836f, 0.007389f, 0.617676f, 0.006878f, 0.603516f, 0.006397f, 0.588867f, 0.005951f, + 0.574219f, 0.005531f, 0.559570f, 0.005142f, 0.544922f, 0.004776f, 0.529785f, 0.004436f, + 0.515137f, 0.004120f, 0.500000f, 0.003828f, 0.485352f, 0.003555f, 0.470215f, 0.003302f, + 0.455566f, 0.003065f, 0.440918f, 0.002844f, 0.426270f, 0.002642f, 0.411621f, 0.002451f, + 0.965820f, 0.033752f, 0.965820f, 0.033752f, 0.965820f, 0.033752f, 0.965820f, 0.033783f, + 0.965820f, 0.033783f, 0.965820f, 0.033875f, 0.965332f, 0.033905f, 0.965332f, 0.033997f, + 0.964844f, 0.034088f, 0.963867f, 0.034241f, 0.963379f, 0.034393f, 0.962402f, 0.034546f, + 0.960938f, 0.034698f, 0.958496f, 0.034851f, 0.957520f, 0.034973f, 0.954102f, 0.035034f, + 0.951172f, 0.035034f, 0.947754f, 0.034943f, 0.942871f, 0.034821f, 0.937988f, 0.034576f, + 0.932129f, 0.034180f, 0.926270f, 0.033722f, 0.918945f, 0.033142f, 0.911133f, 0.032410f, + 0.902832f, 0.031616f, 0.894531f, 0.030685f, 0.885254f, 0.029694f, 0.876465f, 0.028641f, + 0.866699f, 0.027512f, 0.856445f, 0.026337f, 0.846191f, 0.025146f, 0.835449f, 0.023926f, + 0.825195f, 0.022720f, 0.814453f, 0.021515f, 0.803711f, 0.020340f, 0.792480f, 0.019165f, + 0.781250f, 0.018051f, 0.770020f, 0.016968f, 0.758789f, 0.015915f, 0.747070f, 0.014931f, + 0.735352f, 0.013977f, 0.723145f, 0.013069f, 0.710938f, 0.012215f, 0.698730f, 0.011398f, + 0.686035f, 0.010635f, 0.673340f, 0.009918f, 0.660156f, 0.009239f, 0.646484f, 0.008598f, + 0.633301f, 0.008003f, 0.619141f, 0.007446f, 0.605469f, 0.006927f, 0.591309f, 0.006439f, + 0.576660f, 0.005985f, 0.562500f, 0.005562f, 0.547852f, 0.005165f, 0.533203f, 0.004795f, + 0.518066f, 0.004456f, 0.503418f, 0.004135f, 0.488770f, 0.003841f, 0.474121f, 0.003565f, + 0.459229f, 0.003311f, 0.444580f, 0.003073f, 0.430176f, 0.002853f, 0.415771f, 0.002647f, + 0.960449f, 0.039276f, 0.960449f, 0.039276f, 0.960449f, 0.039276f, 0.960449f, 0.039307f, + 0.960449f, 0.039337f, 0.959961f, 0.039368f, 0.959961f, 0.039429f, 0.959961f, 0.039520f, + 0.959473f, 0.039612f, 0.958984f, 0.039764f, 0.958008f, 0.039886f, 0.956543f, 0.040009f, + 0.955566f, 0.040131f, 0.953125f, 0.040253f, 0.951172f, 0.040314f, 0.948242f, 0.040283f, + 0.945801f, 0.040222f, 0.940918f, 0.040039f, 0.936523f, 0.039764f, 0.931152f, 0.039368f, + 0.926270f, 0.038879f, 0.919434f, 0.038208f, 0.913086f, 0.037445f, 0.905273f, 0.036530f, + 0.897461f, 0.035522f, 0.888184f, 0.034393f, 0.879395f, 0.033173f, 0.870117f, 0.031891f, + 0.860352f, 0.030563f, 0.850586f, 0.029190f, 0.840820f, 0.027802f, 0.830566f, 0.026398f, + 0.820312f, 0.025009f, 0.810059f, 0.023636f, 0.799805f, 0.022308f, 0.789062f, 0.020996f, + 0.778809f, 0.019730f, 0.767578f, 0.018524f, 0.756348f, 0.017365f, 0.745605f, 0.016251f, + 0.733887f, 0.015213f, 0.722656f, 0.014206f, 0.710938f, 0.013260f, 0.698730f, 0.012367f, + 0.686523f, 0.011536f, 0.673828f, 0.010742f, 0.661133f, 0.010002f, 0.647949f, 0.009308f, + 0.634766f, 0.008659f, 0.621094f, 0.008057f, 0.607422f, 0.007488f, 0.593262f, 0.006958f, + 0.579102f, 0.006466f, 0.564941f, 0.006004f, 0.550781f, 0.005577f, 0.536133f, 0.005177f, + 0.521484f, 0.004807f, 0.506836f, 0.004463f, 0.492432f, 0.004143f, 0.477783f, 0.003847f, + 0.463135f, 0.003571f, 0.448730f, 0.003315f, 0.434082f, 0.003077f, 0.419922f, 0.002857f, + 0.954102f, 0.045502f, 0.954102f, 0.045502f, 0.954102f, 0.045502f, 0.954102f, 0.045532f, + 0.954102f, 0.045563f, 0.954102f, 0.045593f, 0.953613f, 0.045654f, 0.953613f, 0.045715f, + 0.953125f, 0.045868f, 0.952148f, 0.045990f, 0.951660f, 0.046082f, 0.950195f, 0.046143f, + 0.948242f, 0.046265f, 0.946777f, 0.046265f, 0.943848f, 0.046265f, 0.941895f, 0.046204f, + 0.938477f, 0.046021f, 0.935059f, 0.045685f, 0.929199f, 0.045258f, 0.925293f, 0.044708f, + 0.919434f, 0.044006f, 0.912109f, 0.043121f, 0.905273f, 0.042145f, 0.897949f, 0.041016f, + 0.890137f, 0.039734f, 0.881348f, 0.038391f, 0.872559f, 0.036926f, 0.863770f, 0.035431f, + 0.854004f, 0.033813f, 0.844727f, 0.032227f, 0.835449f, 0.030640f, 0.825195f, 0.029037f, + 0.815430f, 0.027451f, 0.806152f, 0.025909f, 0.795898f, 0.024399f, 0.785645f, 0.022934f, + 0.775391f, 0.021530f, 0.765137f, 0.020187f, 0.754883f, 0.018890f, 0.743652f, 0.017670f, + 0.732910f, 0.016510f, 0.721680f, 0.015411f, 0.710449f, 0.014374f, 0.698730f, 0.013405f, + 0.686523f, 0.012482f, 0.674316f, 0.011620f, 0.662109f, 0.010811f, 0.649414f, 0.010063f, + 0.636230f, 0.009354f, 0.623047f, 0.008698f, 0.609375f, 0.008080f, 0.595703f, 0.007507f, + 0.582031f, 0.006973f, 0.567871f, 0.006477f, 0.553711f, 0.006016f, 0.539551f, 0.005585f, + 0.524902f, 0.005180f, 0.510254f, 0.004810f, 0.496094f, 0.004463f, 0.481689f, 0.004147f, + 0.467041f, 0.003847f, 0.452637f, 0.003571f, 0.438232f, 0.003315f, 0.424072f, 0.003077f, + 0.947266f, 0.052490f, 0.947266f, 0.052490f, 0.947266f, 0.052490f, 0.947266f, 0.052521f, + 0.947266f, 0.052551f, 0.946777f, 0.052582f, 0.946777f, 0.052612f, 0.946289f, 0.052734f, + 0.945801f, 0.052795f, 0.945312f, 0.052887f, 0.944336f, 0.052948f, 0.942871f, 0.053040f, + 0.941406f, 0.053009f, 0.939941f, 0.053009f, 0.937012f, 0.052917f, 0.934570f, 0.052704f, + 0.931641f, 0.052399f, 0.926758f, 0.051971f, 0.922852f, 0.051331f, 0.917480f, 0.050568f, + 0.911133f, 0.049622f, 0.904297f, 0.048523f, 0.898438f, 0.047272f, 0.890137f, 0.045868f, + 0.882812f, 0.044312f, 0.874512f, 0.042694f, 0.865723f, 0.040955f, 0.856934f, 0.039154f, + 0.847656f, 0.037354f, 0.838867f, 0.035522f, 0.829590f, 0.033661f, 0.820312f, 0.031830f, + 0.811035f, 0.030060f, 0.801270f, 0.028305f, 0.791992f, 0.026611f, 0.782227f, 0.024994f, + 0.772461f, 0.023422f, 0.762695f, 0.021927f, 0.752441f, 0.020508f, 0.742188f, 0.019165f, + 0.731445f, 0.017883f, 0.721191f, 0.016678f, 0.709961f, 0.015556f, 0.698730f, 0.014488f, + 0.687012f, 0.013489f, 0.675293f, 0.012550f, 0.663086f, 0.011673f, 0.650879f, 0.010849f, + 0.638184f, 0.010086f, 0.625000f, 0.009369f, 0.611816f, 0.008705f, 0.598145f, 0.008087f, + 0.584961f, 0.007511f, 0.570801f, 0.006977f, 0.556641f, 0.006474f, 0.542480f, 0.006012f, + 0.528320f, 0.005581f, 0.514160f, 0.005180f, 0.499756f, 0.004807f, 0.485596f, 0.004459f, + 0.471191f, 0.004139f, 0.456787f, 0.003843f, 0.442383f, 0.003569f, 0.428467f, 0.003313f, + 0.939453f, 0.060333f, 0.939453f, 0.060333f, 0.939453f, 0.060333f, 0.939453f, 0.060333f, + 0.939453f, 0.060394f, 0.938965f, 0.060394f, 0.938965f, 0.060455f, 0.938477f, 0.060516f, + 0.937988f, 0.060577f, 0.937500f, 0.060638f, 0.936035f, 0.060669f, 0.935547f, 0.060669f, + 0.933594f, 0.060608f, 0.931641f, 0.060516f, 0.929688f, 0.060272f, 0.927246f, 0.059967f, + 0.922363f, 0.059448f, 0.918945f, 0.058868f, 0.914062f, 0.057953f, 0.908691f, 0.056946f, + 0.902832f, 0.055786f, 0.897461f, 0.054382f, 0.890137f, 0.052826f, 0.882324f, 0.051117f, + 0.874023f, 0.049255f, 0.866211f, 0.047302f, 0.858398f, 0.045288f, 0.849609f, 0.043213f, + 0.840820f, 0.041107f, 0.832031f, 0.038971f, 0.823730f, 0.036896f, 0.814453f, 0.034821f, + 0.806152f, 0.032806f, 0.796875f, 0.030853f, 0.788086f, 0.028961f, 0.778809f, 0.027161f, + 0.769531f, 0.025421f, 0.760254f, 0.023788f, 0.750488f, 0.022217f, 0.740723f, 0.020737f, + 0.730957f, 0.019333f, 0.720703f, 0.018021f, 0.709961f, 0.016785f, 0.698730f, 0.015625f, + 0.687500f, 0.014549f, 0.676270f, 0.013535f, 0.664551f, 0.012573f, 0.652344f, 0.011688f, + 0.640137f, 0.010864f, 0.627441f, 0.010086f, 0.614258f, 0.009369f, 0.601074f, 0.008698f, + 0.587402f, 0.008080f, 0.573730f, 0.007500f, 0.560059f, 0.006962f, 0.545898f, 0.006462f, + 0.531738f, 0.006001f, 0.517578f, 0.005569f, 0.503418f, 0.005165f, 0.489502f, 0.004795f, + 0.475098f, 0.004452f, 0.460938f, 0.004131f, 0.446777f, 0.003838f, 0.432861f, 0.003563f, + 0.930664f, 0.069031f, 0.930664f, 0.069031f, 0.930664f, 0.069031f, 0.930664f, 0.069031f, + 0.930664f, 0.069092f, 0.930664f, 0.069092f, 0.930176f, 0.069214f, 0.929688f, 0.069153f, + 0.929199f, 0.069214f, 0.929199f, 0.069275f, 0.927246f, 0.069214f, 0.926758f, 0.069153f, + 0.925293f, 0.069031f, 0.923340f, 0.068787f, 0.920410f, 0.068420f, 0.917480f, 0.067932f, + 0.914551f, 0.067261f, 0.911133f, 0.066345f, 0.905273f, 0.065247f, 0.900391f, 0.063965f, + 0.894043f, 0.062469f, 0.888184f, 0.060699f, 0.880859f, 0.058807f, 0.873535f, 0.056763f, + 0.866211f, 0.054565f, 0.858887f, 0.052277f, 0.850586f, 0.049896f, 0.841797f, 0.047485f, + 0.833496f, 0.045105f, 0.825684f, 0.042664f, 0.817383f, 0.040283f, 0.809082f, 0.037964f, + 0.800781f, 0.035706f, 0.792480f, 0.033539f, 0.784180f, 0.031433f, 0.775391f, 0.029449f, + 0.766602f, 0.027542f, 0.757812f, 0.025726f, 0.748535f, 0.024017f, 0.739258f, 0.022400f, + 0.729980f, 0.020874f, 0.719727f, 0.019440f, 0.709961f, 0.018097f, 0.699219f, 0.016830f, + 0.688477f, 0.015656f, 0.677246f, 0.014557f, 0.665527f, 0.013527f, 0.653809f, 0.012573f, + 0.641602f, 0.011681f, 0.629395f, 0.010841f, 0.616699f, 0.010071f, 0.603516f, 0.009346f, + 0.590332f, 0.008682f, 0.577148f, 0.008057f, 0.563477f, 0.007481f, 0.549316f, 0.006943f, + 0.535645f, 0.006443f, 0.521484f, 0.005978f, 0.507324f, 0.005550f, 0.493408f, 0.005150f, + 0.479248f, 0.004780f, 0.465332f, 0.004436f, 0.451172f, 0.004124f, 0.437256f, 0.003828f, + 0.920898f, 0.078735f, 0.920898f, 0.078735f, 0.920898f, 0.078735f, 0.920898f, 0.078735f, + 0.920898f, 0.078796f, 0.920898f, 0.078796f, 0.920410f, 0.078796f, 0.919922f, 0.078857f, + 0.919922f, 0.078857f, 0.918945f, 0.078796f, 0.917480f, 0.078735f, 0.916992f, 0.078613f, + 0.915039f, 0.078308f, 0.913086f, 0.077942f, 0.910645f, 0.077454f, 0.908691f, 0.076660f, + 0.905273f, 0.075745f, 0.899902f, 0.074585f, 0.895996f, 0.073181f, 0.889648f, 0.071533f, + 0.883789f, 0.069641f, 0.877930f, 0.067566f, 0.872070f, 0.065247f, 0.864258f, 0.062805f, + 0.856934f, 0.060242f, 0.849121f, 0.057556f, 0.841797f, 0.054810f, 0.833984f, 0.052063f, + 0.827148f, 0.049316f, 0.818848f, 0.046570f, 0.811035f, 0.043915f, 0.803223f, 0.041290f, + 0.795898f, 0.038788f, 0.788086f, 0.036377f, 0.779785f, 0.034058f, 0.771973f, 0.031830f, + 0.763672f, 0.029755f, 0.755371f, 0.027771f, 0.747070f, 0.025894f, 0.738281f, 0.024139f, + 0.729004f, 0.022476f, 0.719238f, 0.020935f, 0.709473f, 0.019470f, 0.699707f, 0.018097f, + 0.688965f, 0.016830f, 0.678223f, 0.015640f, 0.666992f, 0.014534f, 0.655762f, 0.013496f, + 0.643555f, 0.012535f, 0.631348f, 0.011642f, 0.619141f, 0.010803f, 0.606445f, 0.010033f, + 0.593262f, 0.009308f, 0.580078f, 0.008644f, 0.566406f, 0.008018f, 0.553223f, 0.007446f, + 0.539062f, 0.006908f, 0.525391f, 0.006413f, 0.511230f, 0.005951f, 0.497559f, 0.005527f, + 0.483643f, 0.005131f, 0.469482f, 0.004765f, 0.455566f, 0.004421f, 0.441650f, 0.004108f, + 0.910156f, 0.089539f, 0.910156f, 0.089539f, 0.910156f, 0.089539f, 0.910156f, 0.089539f, + 0.910156f, 0.089539f, 0.909668f, 0.089539f, 0.909668f, 0.089539f, 0.909180f, 0.089539f, + 0.908691f, 0.089478f, 0.907715f, 0.089417f, 0.907227f, 0.089233f, 0.905762f, 0.088989f, + 0.904297f, 0.088562f, 0.902832f, 0.088013f, 0.900391f, 0.087280f, 0.896973f, 0.086243f, + 0.895020f, 0.085083f, 0.889160f, 0.083557f, 0.884766f, 0.081787f, 0.878906f, 0.079712f, + 0.874512f, 0.077393f, 0.867676f, 0.074951f, 0.860840f, 0.072205f, 0.854492f, 0.069275f, + 0.848145f, 0.066223f, 0.840820f, 0.063171f, 0.833008f, 0.060059f, 0.826172f, 0.056885f, + 0.819336f, 0.053741f, 0.812012f, 0.050690f, 0.804688f, 0.047699f, 0.797852f, 0.044800f, + 0.790527f, 0.042023f, 0.783691f, 0.039337f, 0.776367f, 0.036804f, 0.768555f, 0.034393f, + 0.761230f, 0.032074f, 0.753418f, 0.029922f, 0.745117f, 0.027893f, 0.736816f, 0.025970f, + 0.728516f, 0.024170f, 0.719238f, 0.022491f, 0.709961f, 0.020905f, 0.700195f, 0.019440f, + 0.689941f, 0.018066f, 0.679688f, 0.016785f, 0.668457f, 0.015587f, 0.657227f, 0.014473f, + 0.645996f, 0.013443f, 0.633789f, 0.012474f, 0.621582f, 0.011581f, 0.609375f, 0.010750f, + 0.596191f, 0.009972f, 0.583496f, 0.009262f, 0.569824f, 0.008591f, 0.556641f, 0.007973f, + 0.542969f, 0.007404f, 0.529297f, 0.006874f, 0.515625f, 0.006378f, 0.501465f, 0.005920f, + 0.487793f, 0.005501f, 0.474121f, 0.005108f, 0.460205f, 0.004742f, 0.446289f, 0.004406f, + 0.898438f, 0.101440f, 0.898438f, 0.101440f, 0.898438f, 0.101440f, 0.898438f, 0.101440f, + 0.897949f, 0.101440f, 0.897949f, 0.101440f, 0.897461f, 0.101440f, 0.896973f, 0.101379f, + 0.896973f, 0.101318f, 0.895996f, 0.101135f, 0.895508f, 0.100830f, 0.894043f, 0.100464f, + 0.893066f, 0.099854f, 0.890625f, 0.099121f, 0.888184f, 0.098083f, 0.885254f, 0.096802f, + 0.882324f, 0.095215f, 0.878418f, 0.093323f, 0.872559f, 0.091125f, 0.869629f, 0.088623f, + 0.862793f, 0.085815f, 0.855957f, 0.082764f, 0.850098f, 0.079590f, 0.844727f, 0.076172f, + 0.837402f, 0.072693f, 0.831055f, 0.069092f, 0.824219f, 0.065491f, 0.817871f, 0.061981f, + 0.811035f, 0.058472f, 0.804688f, 0.055023f, 0.797852f, 0.051697f, 0.791992f, 0.048492f, + 0.785645f, 0.045410f, 0.778809f, 0.042480f, 0.771973f, 0.039673f, 0.765625f, 0.037018f, + 0.758789f, 0.034515f, 0.750977f, 0.032166f, 0.743652f, 0.029968f, 0.735840f, 0.027878f, + 0.727539f, 0.025940f, 0.718750f, 0.024124f, 0.709961f, 0.022430f, 0.700684f, 0.020844f, + 0.690918f, 0.019363f, 0.680664f, 0.017975f, 0.670410f, 0.016693f, 0.659180f, 0.015495f, + 0.647949f, 0.014389f, 0.636230f, 0.013359f, 0.624512f, 0.012398f, 0.611816f, 0.011505f, + 0.599609f, 0.010681f, 0.586426f, 0.009911f, 0.573730f, 0.009201f, 0.560547f, 0.008537f, + 0.546875f, 0.007927f, 0.533203f, 0.007355f, 0.519531f, 0.006828f, 0.505859f, 0.006340f, + 0.492432f, 0.005890f, 0.478516f, 0.005470f, 0.464844f, 0.005077f, 0.450928f, 0.004719f, + 0.885254f, 0.114624f, 0.885254f, 0.114624f, 0.885254f, 0.114624f, 0.885254f, 0.114624f, + 0.884766f, 0.114624f, 0.884766f, 0.114563f, 0.884766f, 0.114502f, 0.884277f, 0.114380f, + 0.883789f, 0.114258f, 0.883301f, 0.114014f, 0.882324f, 0.113525f, 0.881348f, 0.112976f, + 0.879395f, 0.112183f, 0.877441f, 0.111145f, 0.875977f, 0.109802f, 0.872559f, 0.108215f, + 0.869141f, 0.106201f, 0.865723f, 0.103821f, 0.860352f, 0.101196f, 0.854492f, 0.098145f, + 0.850586f, 0.094849f, 0.845215f, 0.091187f, 0.838379f, 0.087463f, 0.833496f, 0.083496f, + 0.826660f, 0.079468f, 0.820801f, 0.075378f, 0.814453f, 0.071289f, 0.809082f, 0.067322f, + 0.803711f, 0.063354f, 0.797363f, 0.059540f, 0.791992f, 0.055878f, 0.786133f, 0.052338f, + 0.780762f, 0.048950f, 0.774414f, 0.045746f, 0.768555f, 0.042664f, 0.762207f, 0.039795f, + 0.755859f, 0.037079f, 0.749023f, 0.034546f, 0.741699f, 0.032135f, 0.734863f, 0.029892f, + 0.727051f, 0.027802f, 0.718750f, 0.025833f, 0.710449f, 0.024002f, 0.701172f, 0.022293f, + 0.691895f, 0.020706f, 0.682129f, 0.019226f, 0.671875f, 0.017853f, 0.661133f, 0.016571f, + 0.650391f, 0.015381f, 0.639160f, 0.014282f, 0.626953f, 0.013252f, 0.615234f, 0.012299f, + 0.602539f, 0.011414f, 0.590332f, 0.010597f, 0.577148f, 0.009834f, 0.563965f, 0.009132f, + 0.550781f, 0.008476f, 0.537598f, 0.007866f, 0.523926f, 0.007309f, 0.510254f, 0.006786f, + 0.496826f, 0.006306f, 0.483154f, 0.005856f, 0.469482f, 0.005440f, 0.455811f, 0.005054f, + 0.870605f, 0.129028f, 0.870605f, 0.129028f, 0.870605f, 0.129028f, 0.870605f, 0.129028f, + 0.870605f, 0.129028f, 0.870605f, 0.129028f, 0.870117f, 0.128906f, 0.870117f, 0.128784f, + 0.869629f, 0.128540f, 0.869141f, 0.128052f, 0.868164f, 0.127563f, 0.867188f, 0.126709f, + 0.865723f, 0.125732f, 0.863281f, 0.124329f, 0.862305f, 0.122742f, 0.858887f, 0.120544f, + 0.854980f, 0.118103f, 0.850098f, 0.115173f, 0.847168f, 0.111938f, 0.843750f, 0.108276f, + 0.836426f, 0.104309f, 0.832031f, 0.100159f, 0.827148f, 0.095764f, 0.821289f, 0.091187f, + 0.815918f, 0.086609f, 0.810547f, 0.081970f, 0.806152f, 0.077393f, 0.800781f, 0.072937f, + 0.795410f, 0.068542f, 0.790039f, 0.064270f, 0.785645f, 0.060242f, 0.780762f, 0.056335f, + 0.775391f, 0.052643f, 0.770020f, 0.049133f, 0.765137f, 0.045807f, 0.759766f, 0.042694f, + 0.753906f, 0.039734f, 0.747559f, 0.036987f, 0.740723f, 0.034393f, 0.733887f, 0.031982f, + 0.726562f, 0.029739f, 0.719238f, 0.027618f, 0.710449f, 0.025650f, 0.702148f, 0.023834f, + 0.692871f, 0.022125f, 0.683594f, 0.020538f, 0.673828f, 0.019058f, 0.663574f, 0.017685f, + 0.652832f, 0.016418f, 0.641602f, 0.015244f, 0.629883f, 0.014153f, 0.618164f, 0.013138f, + 0.605957f, 0.012192f, 0.593750f, 0.011314f, 0.581055f, 0.010506f, 0.567871f, 0.009750f, + 0.555176f, 0.009056f, 0.541504f, 0.008408f, 0.528320f, 0.007809f, 0.514648f, 0.007252f, + 0.501465f, 0.006741f, 0.487793f, 0.006260f, 0.474365f, 0.005817f, 0.460938f, 0.005409f, + 0.854492f, 0.145020f, 0.854492f, 0.145020f, 0.854492f, 0.145020f, 0.854492f, 0.145020f, + 0.854492f, 0.144897f, 0.854492f, 0.144897f, 0.854004f, 0.144653f, 0.854492f, 0.144531f, + 0.854004f, 0.144165f, 0.853027f, 0.143555f, 0.852051f, 0.142822f, 0.851074f, 0.141724f, + 0.850586f, 0.140503f, 0.848145f, 0.138672f, 0.846191f, 0.136475f, 0.843262f, 0.133911f, + 0.839844f, 0.130859f, 0.835449f, 0.127319f, 0.832031f, 0.123474f, 0.828613f, 0.119141f, + 0.823242f, 0.114502f, 0.819824f, 0.109558f, 0.813477f, 0.104431f, 0.809570f, 0.099304f, + 0.804199f, 0.094055f, 0.799316f, 0.088867f, 0.794922f, 0.083740f, 0.791992f, 0.078735f, + 0.786621f, 0.073914f, 0.783203f, 0.069214f, 0.779297f, 0.064758f, 0.774902f, 0.060516f, + 0.770508f, 0.056488f, 0.765625f, 0.052673f, 0.761230f, 0.049072f, 0.756348f, 0.045715f, + 0.750977f, 0.042511f, 0.745605f, 0.039551f, 0.739746f, 0.036774f, 0.733398f, 0.034180f, + 0.726562f, 0.031738f, 0.719238f, 0.029495f, 0.711426f, 0.027390f, 0.703125f, 0.025421f, + 0.694336f, 0.023605f, 0.685059f, 0.021912f, 0.675781f, 0.020340f, 0.665527f, 0.018875f, + 0.655273f, 0.017517f, 0.644043f, 0.016251f, 0.632812f, 0.015091f, 0.621582f, 0.014008f, + 0.609375f, 0.013000f, 0.597168f, 0.012070f, 0.584473f, 0.011200f, 0.571777f, 0.010406f, + 0.559082f, 0.009659f, 0.545898f, 0.008972f, 0.532715f, 0.008339f, 0.519531f, 0.007748f, + 0.505859f, 0.007198f, 0.492676f, 0.006691f, 0.479248f, 0.006218f, 0.465820f, 0.005783f, + 0.837402f, 0.162476f, 0.837402f, 0.162476f, 0.837402f, 0.162476f, 0.837402f, 0.162354f, + 0.837402f, 0.162354f, 0.836914f, 0.162231f, 0.836914f, 0.161987f, 0.836426f, 0.161743f, + 0.836426f, 0.161133f, 0.835449f, 0.160522f, 0.835449f, 0.159546f, 0.834473f, 0.158203f, + 0.833496f, 0.156372f, 0.831055f, 0.154175f, 0.830078f, 0.151489f, 0.826660f, 0.148315f, + 0.823242f, 0.144531f, 0.821289f, 0.140381f, 0.817383f, 0.135620f, 0.812012f, 0.130615f, + 0.810547f, 0.125122f, 0.805176f, 0.119507f, 0.800293f, 0.113647f, 0.797852f, 0.107788f, + 0.792480f, 0.101868f, 0.788574f, 0.096008f, 0.785156f, 0.090332f, 0.782715f, 0.084839f, + 0.779297f, 0.079468f, 0.774902f, 0.074341f, 0.772461f, 0.069458f, 0.769531f, 0.064819f, + 0.765137f, 0.060486f, 0.761719f, 0.056366f, 0.758301f, 0.052490f, 0.753418f, 0.048828f, + 0.749023f, 0.045410f, 0.743652f, 0.042206f, 0.738770f, 0.039215f, 0.732422f, 0.036438f, + 0.726074f, 0.033844f, 0.719238f, 0.031433f, 0.711914f, 0.029190f, 0.704102f, 0.027100f, + 0.695801f, 0.025146f, 0.687012f, 0.023346f, 0.677734f, 0.021667f, 0.667969f, 0.020111f, + 0.657715f, 0.018646f, 0.646973f, 0.017319f, 0.636230f, 0.016068f, 0.624512f, 0.014923f, + 0.612793f, 0.013855f, 0.601074f, 0.012863f, 0.588379f, 0.011948f, 0.576172f, 0.011093f, + 0.563477f, 0.010300f, 0.550293f, 0.009567f, 0.537109f, 0.008896f, 0.523926f, 0.008263f, + 0.510742f, 0.007687f, 0.497559f, 0.007145f, 0.484375f, 0.006645f, 0.470947f, 0.006180f, + 0.818359f, 0.181519f, 0.818359f, 0.181519f, 0.818359f, 0.181519f, 0.817871f, 0.181519f, + 0.817871f, 0.181396f, 0.817871f, 0.181274f, 0.817871f, 0.181030f, 0.817871f, 0.180542f, + 0.817871f, 0.179932f, 0.817383f, 0.178955f, 0.816406f, 0.177612f, 0.815918f, 0.175903f, + 0.814941f, 0.173584f, 0.812500f, 0.170898f, 0.811035f, 0.167603f, 0.808594f, 0.163696f, + 0.805664f, 0.159180f, 0.802246f, 0.154175f, 0.799805f, 0.148560f, 0.796875f, 0.142700f, + 0.792480f, 0.136353f, 0.789551f, 0.129883f, 0.787598f, 0.123230f, 0.782227f, 0.116577f, + 0.780273f, 0.109985f, 0.777344f, 0.103516f, 0.774414f, 0.097168f, 0.771973f, 0.091125f, + 0.770508f, 0.085205f, 0.767578f, 0.079651f, 0.765625f, 0.074341f, 0.763184f, 0.069336f, + 0.760254f, 0.064636f, 0.757812f, 0.060181f, 0.754395f, 0.056000f, 0.750977f, 0.052063f, + 0.747559f, 0.048431f, 0.742188f, 0.044983f, 0.737793f, 0.041779f, 0.732422f, 0.038818f, + 0.726074f, 0.036041f, 0.719727f, 0.033447f, 0.712891f, 0.031052f, 0.705566f, 0.028824f, + 0.697266f, 0.026749f, 0.688965f, 0.024826f, 0.679688f, 0.023041f, 0.670410f, 0.021393f, + 0.660645f, 0.019852f, 0.649902f, 0.018433f, 0.639160f, 0.017105f, 0.627930f, 0.015869f, + 0.616211f, 0.014748f, 0.604492f, 0.013687f, 0.592773f, 0.012718f, 0.580078f, 0.011818f, + 0.567871f, 0.010979f, 0.554688f, 0.010201f, 0.541992f, 0.009483f, 0.528809f, 0.008812f, + 0.515625f, 0.008194f, 0.502441f, 0.007626f, 0.489502f, 0.007088f, 0.476318f, 0.006599f, + 0.797363f, 0.202393f, 0.797363f, 0.202393f, 0.797363f, 0.202393f, 0.797363f, 0.202393f, + 0.797363f, 0.202148f, 0.797363f, 0.202026f, 0.797363f, 0.201660f, 0.797363f, 0.201050f, + 0.796875f, 0.200195f, 0.796875f, 0.198975f, 0.796387f, 0.197266f, 0.795898f, 0.195068f, + 0.794922f, 0.192261f, 0.792969f, 0.188843f, 0.792480f, 0.184937f, 0.789551f, 0.180298f, + 0.787598f, 0.174927f, 0.785645f, 0.168823f, 0.782715f, 0.162231f, 0.779297f, 0.155273f, + 0.775879f, 0.148071f, 0.775391f, 0.140747f, 0.772461f, 0.133179f, 0.770508f, 0.125732f, + 0.767578f, 0.118347f, 0.766113f, 0.111206f, 0.764648f, 0.104248f, 0.763184f, 0.097595f, + 0.762695f, 0.091187f, 0.761719f, 0.085144f, 0.759277f, 0.079407f, 0.758301f, 0.073975f, + 0.755859f, 0.068909f, 0.754395f, 0.064087f, 0.751465f, 0.059631f, 0.748535f, 0.055450f, + 0.745117f, 0.051514f, 0.741211f, 0.047852f, 0.737305f, 0.044434f, 0.731934f, 0.041260f, + 0.726562f, 0.038300f, 0.720215f, 0.035553f, 0.713867f, 0.032990f, 0.706543f, 0.030624f, + 0.699219f, 0.028427f, 0.690918f, 0.026382f, 0.682129f, 0.024475f, 0.672852f, 0.022720f, + 0.663086f, 0.021088f, 0.652832f, 0.019577f, 0.642578f, 0.018173f, 0.631348f, 0.016876f, + 0.620117f, 0.015671f, 0.608398f, 0.014565f, 0.596680f, 0.013535f, 0.584473f, 0.012573f, + 0.572266f, 0.011681f, 0.559570f, 0.010857f, 0.546875f, 0.010101f, 0.533691f, 0.009392f, + 0.520996f, 0.008736f, 0.507812f, 0.008125f, 0.494629f, 0.007565f, 0.481689f, 0.007042f, + 0.774414f, 0.225098f, 0.774414f, 0.225098f, 0.774414f, 0.225098f, 0.774414f, 0.225098f, + 0.774414f, 0.224854f, 0.774902f, 0.224609f, 0.774414f, 0.224121f, 0.774414f, 0.223389f, + 0.774414f, 0.222290f, 0.773926f, 0.220581f, 0.773926f, 0.218628f, 0.773926f, 0.215942f, + 0.773438f, 0.212524f, 0.772461f, 0.208374f, 0.771484f, 0.203491f, 0.770508f, 0.197754f, + 0.769043f, 0.191284f, 0.766113f, 0.184204f, 0.763672f, 0.176514f, 0.760742f, 0.168457f, + 0.760742f, 0.160278f, 0.757812f, 0.151855f, 0.757812f, 0.143433f, 0.756836f, 0.135132f, + 0.754395f, 0.126953f, 0.755371f, 0.119141f, 0.755371f, 0.111511f, 0.754395f, 0.104309f, + 0.753418f, 0.097351f, 0.754395f, 0.090820f, 0.753906f, 0.084595f, 0.752441f, 0.078796f, + 0.751465f, 0.073303f, 0.750000f, 0.068176f, 0.748535f, 0.063354f, 0.746094f, 0.058899f, + 0.743164f, 0.054718f, 0.740234f, 0.050812f, 0.736816f, 0.047150f, 0.731934f, 0.043793f, + 0.727051f, 0.040649f, 0.721191f, 0.037720f, 0.714844f, 0.035004f, 0.708008f, 0.032501f, + 0.700684f, 0.030167f, 0.692871f, 0.027985f, 0.684570f, 0.025986f, 0.675781f, 0.024124f, + 0.666016f, 0.022385f, 0.656250f, 0.020782f, 0.645996f, 0.019302f, 0.635254f, 0.017929f, + 0.624023f, 0.016647f, 0.612793f, 0.015480f, 0.601074f, 0.014381f, 0.588867f, 0.013367f, + 0.576660f, 0.012428f, 0.563965f, 0.011559f, 0.551270f, 0.010750f, 0.539062f, 0.010002f, + 0.525879f, 0.009308f, 0.513184f, 0.008659f, 0.500000f, 0.008064f, 0.487061f, 0.007511f, + 0.750000f, 0.249878f, 0.749512f, 0.249878f, 0.750000f, 0.249878f, 0.750000f, 0.249756f, + 0.750000f, 0.249512f, 0.750000f, 0.249146f, 0.750000f, 0.248413f, 0.750488f, 0.247559f, + 0.750488f, 0.246094f, 0.750488f, 0.244141f, 0.750488f, 0.241577f, 0.750488f, 0.238281f, + 0.748535f, 0.234009f, 0.749512f, 0.229004f, 0.749023f, 0.223022f, 0.747070f, 0.216309f, + 0.745117f, 0.208496f, 0.743164f, 0.200195f, 0.744629f, 0.191406f, 0.741211f, 0.182251f, + 0.741699f, 0.172852f, 0.740234f, 0.163330f, 0.742676f, 0.154053f, 0.741211f, 0.144775f, + 0.743652f, 0.135864f, 0.744629f, 0.127197f, 0.743164f, 0.118958f, 0.744629f, 0.111145f, + 0.745605f, 0.103638f, 0.746582f, 0.096558f, 0.748047f, 0.089966f, 0.747559f, 0.083679f, + 0.747559f, 0.077820f, 0.746582f, 0.072327f, 0.745605f, 0.067261f, 0.744629f, 0.062469f, + 0.742676f, 0.058014f, 0.739746f, 0.053864f, 0.735840f, 0.049988f, 0.731934f, 0.046417f, + 0.727539f, 0.043091f, 0.722168f, 0.039978f, 0.716309f, 0.037079f, 0.709473f, 0.034424f, + 0.702637f, 0.031952f, 0.695312f, 0.029663f, 0.687012f, 0.027542f, 0.678223f, 0.025558f, + 0.668945f, 0.023743f, 0.659180f, 0.022049f, 0.649414f, 0.020477f, 0.638672f, 0.019028f, + 0.627930f, 0.017670f, 0.616699f, 0.016434f, 0.604980f, 0.015274f, 0.593262f, 0.014198f, + 0.581055f, 0.013206f, 0.568848f, 0.012283f, 0.556641f, 0.011429f, 0.543945f, 0.010643f, + 0.531250f, 0.009903f, 0.518066f, 0.009224f, 0.505371f, 0.008591f, 0.492676f, 0.008003f, + 0.723145f, 0.276611f, 0.723145f, 0.276611f, 0.723145f, 0.276611f, 0.723145f, 0.276611f, + 0.723145f, 0.276123f, 0.723145f, 0.275635f, 0.723145f, 0.274902f, 0.723633f, 0.273682f, + 0.723633f, 0.271973f, 0.724121f, 0.269531f, 0.724609f, 0.266113f, 0.725098f, 0.262207f, + 0.725098f, 0.257080f, 0.724609f, 0.250732f, 0.722656f, 0.243652f, 0.725586f, 0.235474f, + 0.724121f, 0.226685f, 0.723145f, 0.216919f, 0.722656f, 0.206787f, 0.720703f, 0.196289f, + 0.723145f, 0.185791f, 0.723633f, 0.175171f, 0.724121f, 0.164795f, 0.728027f, 0.154663f, + 0.730469f, 0.144897f, 0.731934f, 0.135498f, 0.734863f, 0.126587f, 0.737305f, 0.118103f, + 0.739258f, 0.110107f, 0.739746f, 0.102478f, 0.741699f, 0.095398f, 0.743164f, 0.088745f, + 0.743652f, 0.082520f, 0.743652f, 0.076660f, 0.743652f, 0.071228f, 0.742676f, 0.066101f, + 0.741211f, 0.061401f, 0.739258f, 0.057007f, 0.735840f, 0.052887f, 0.732422f, 0.049103f, + 0.728516f, 0.045563f, 0.723145f, 0.042297f, 0.717773f, 0.039246f, 0.711914f, 0.036438f, + 0.704590f, 0.033813f, 0.697754f, 0.031403f, 0.689453f, 0.029160f, 0.681152f, 0.027069f, + 0.671875f, 0.025146f, 0.662598f, 0.023346f, 0.652832f, 0.021698f, 0.642578f, 0.020157f, + 0.631836f, 0.018738f, 0.621094f, 0.017426f, 0.609375f, 0.016205f, 0.597656f, 0.015076f, + 0.585938f, 0.014023f, 0.573730f, 0.013054f, 0.561523f, 0.012146f, 0.548828f, 0.011314f, + 0.536621f, 0.010536f, 0.523926f, 0.009811f, 0.511230f, 0.009148f, 0.498291f, 0.008530f, + 0.693848f, 0.305664f, 0.693848f, 0.305664f, 0.693848f, 0.305664f, 0.693848f, 0.305664f, + 0.693848f, 0.305176f, 0.694336f, 0.304443f, 0.694824f, 0.303467f, 0.695312f, 0.302002f, + 0.695312f, 0.299561f, 0.696289f, 0.296631f, 0.696777f, 0.292725f, 0.696777f, 0.287598f, + 0.697754f, 0.281250f, 0.698242f, 0.273926f, 0.698730f, 0.265137f, 0.697266f, 0.255615f, + 0.699707f, 0.245239f, 0.699707f, 0.234131f, 0.700195f, 0.222412f, 0.702637f, 0.210693f, + 0.705078f, 0.198853f, 0.708496f, 0.187134f, 0.708984f, 0.175781f, 0.715332f, 0.164673f, + 0.718750f, 0.154053f, 0.722168f, 0.143921f, 0.724121f, 0.134277f, 0.727539f, 0.125244f, + 0.731934f, 0.116638f, 0.733398f, 0.108582f, 0.736816f, 0.101013f, 0.738281f, 0.093872f, + 0.740234f, 0.087219f, 0.741699f, 0.081055f, 0.741211f, 0.075256f, 0.741211f, 0.069885f, + 0.740723f, 0.064880f, 0.738281f, 0.060211f, 0.736328f, 0.055908f, 0.732910f, 0.051849f, + 0.729004f, 0.048157f, 0.724609f, 0.044678f, 0.719727f, 0.041473f, 0.713379f, 0.038483f, + 0.707031f, 0.035736f, 0.699707f, 0.033173f, 0.692383f, 0.030823f, 0.684082f, 0.028625f, + 0.675293f, 0.026596f, 0.666016f, 0.024704f, 0.656738f, 0.022964f, 0.646484f, 0.021347f, + 0.636230f, 0.019852f, 0.625488f, 0.018463f, 0.614258f, 0.017181f, 0.602539f, 0.015976f, + 0.590820f, 0.014877f, 0.578613f, 0.013855f, 0.566895f, 0.012901f, 0.554688f, 0.012024f, + 0.541992f, 0.011200f, 0.529297f, 0.010437f, 0.516602f, 0.009735f, 0.503906f, 0.009079f, + 0.662598f, 0.337158f, 0.662598f, 0.337158f, 0.662598f, 0.337158f, 0.662598f, 0.336914f, + 0.662598f, 0.336670f, 0.663086f, 0.335938f, 0.663086f, 0.334473f, 0.664062f, 0.332520f, + 0.665039f, 0.329834f, 0.666016f, 0.325928f, 0.665527f, 0.320801f, 0.667969f, 0.314697f, + 0.667480f, 0.306885f, 0.669922f, 0.298096f, 0.669434f, 0.287842f, 0.671387f, 0.276367f, + 0.675781f, 0.264404f, 0.675781f, 0.251465f, 0.677734f, 0.238403f, 0.681152f, 0.225342f, + 0.686035f, 0.212036f, 0.690430f, 0.199219f, 0.694824f, 0.186768f, 0.700684f, 0.174805f, + 0.702637f, 0.163330f, 0.708008f, 0.152466f, 0.714844f, 0.142212f, 0.718750f, 0.132446f, + 0.724609f, 0.123291f, 0.728516f, 0.114685f, 0.731445f, 0.106628f, 0.734375f, 0.099121f, + 0.736816f, 0.092102f, 0.738770f, 0.085510f, 0.740723f, 0.079407f, 0.740234f, 0.073730f, + 0.739258f, 0.068420f, 0.738770f, 0.063538f, 0.736328f, 0.058960f, 0.734375f, 0.054718f, + 0.730469f, 0.050781f, 0.726562f, 0.047150f, 0.721191f, 0.043762f, 0.715332f, 0.040619f, + 0.709473f, 0.037720f, 0.702637f, 0.035034f, 0.695312f, 0.032532f, 0.687500f, 0.030243f, + 0.678711f, 0.028107f, 0.669922f, 0.026123f, 0.660645f, 0.024277f, 0.650391f, 0.022583f, + 0.640137f, 0.021011f, 0.629395f, 0.019547f, 0.618652f, 0.018188f, 0.607422f, 0.016937f, + 0.595703f, 0.015778f, 0.583984f, 0.014694f, 0.572266f, 0.013695f, 0.560059f, 0.012764f, + 0.547852f, 0.011902f, 0.535156f, 0.011101f, 0.522461f, 0.010353f, 0.510254f, 0.009666f, + 0.628418f, 0.371338f, 0.628418f, 0.371338f, 0.628418f, 0.371094f, 0.628418f, 0.371094f, + 0.628418f, 0.370361f, 0.629395f, 0.369385f, 0.629883f, 0.367920f, 0.630859f, 0.365234f, + 0.631836f, 0.361816f, 0.633301f, 0.357178f, 0.634766f, 0.350830f, 0.635742f, 0.343262f, + 0.638184f, 0.333984f, 0.640137f, 0.322998f, 0.641113f, 0.311035f, 0.645508f, 0.297852f, + 0.647949f, 0.283691f, 0.652344f, 0.269043f, 0.657227f, 0.254395f, 0.662598f, 0.239868f, + 0.669922f, 0.225464f, 0.673340f, 0.211426f, 0.680664f, 0.197876f, 0.685547f, 0.184937f, + 0.693359f, 0.172729f, 0.700684f, 0.161011f, 0.705566f, 0.150146f, 0.711426f, 0.139771f, + 0.718750f, 0.130005f, 0.722168f, 0.120911f, 0.727051f, 0.112427f, 0.732422f, 0.104431f, + 0.733887f, 0.097046f, 0.737305f, 0.090088f, 0.738770f, 0.083618f, 0.740234f, 0.077637f, + 0.739258f, 0.072083f, 0.738281f, 0.066895f, 0.736816f, 0.062073f, 0.734375f, 0.057648f, + 0.731934f, 0.053497f, 0.728027f, 0.049683f, 0.723145f, 0.046112f, 0.717773f, 0.042816f, + 0.712402f, 0.039764f, 0.705566f, 0.036957f, 0.698242f, 0.034332f, 0.690430f, 0.031891f, + 0.682617f, 0.029663f, 0.673340f, 0.027573f, 0.664551f, 0.025650f, 0.654785f, 0.023865f, + 0.644531f, 0.022202f, 0.634277f, 0.020676f, 0.623535f, 0.019257f, 0.612305f, 0.017929f, + 0.601074f, 0.016708f, 0.589355f, 0.015579f, 0.577637f, 0.014526f, 0.565430f, 0.013550f, + 0.553223f, 0.012642f, 0.541016f, 0.011787f, 0.528809f, 0.011009f, 0.516113f, 0.010277f, + 0.591309f, 0.407959f, 0.591797f, 0.407959f, 0.591797f, 0.407959f, 0.591797f, 0.407471f, + 0.592285f, 0.406982f, 0.592773f, 0.405762f, 0.593750f, 0.403564f, 0.594727f, 0.400391f, + 0.596680f, 0.396240f, 0.598145f, 0.390137f, 0.600098f, 0.382568f, 0.602539f, 0.373047f, + 0.604980f, 0.361816f, 0.606934f, 0.348877f, 0.611816f, 0.334473f, 0.616699f, 0.319336f, + 0.620605f, 0.302979f, 0.627930f, 0.286865f, 0.634277f, 0.270508f, 0.638672f, 0.254150f, + 0.647949f, 0.238525f, 0.654297f, 0.223389f, 0.663086f, 0.208862f, 0.673828f, 0.195068f, + 0.680176f, 0.182007f, 0.689941f, 0.169678f, 0.696289f, 0.157959f, 0.705078f, 0.147095f, + 0.713867f, 0.136841f, 0.719727f, 0.127197f, 0.724121f, 0.118225f, 0.729980f, 0.109863f, + 0.731934f, 0.101990f, 0.735840f, 0.094727f, 0.737305f, 0.087952f, 0.738770f, 0.081604f, + 0.740234f, 0.075745f, 0.739258f, 0.070312f, 0.738281f, 0.065247f, 0.735840f, 0.060608f, + 0.733398f, 0.056274f, 0.729492f, 0.052246f, 0.725098f, 0.048523f, 0.720703f, 0.045074f, + 0.714355f, 0.041870f, 0.708496f, 0.038910f, 0.701660f, 0.036163f, 0.693848f, 0.033630f, + 0.686035f, 0.031281f, 0.677734f, 0.029099f, 0.668457f, 0.027069f, 0.659180f, 0.025192f, + 0.648926f, 0.023453f, 0.639160f, 0.021851f, 0.628418f, 0.020355f, 0.617676f, 0.018967f, + 0.605957f, 0.017685f, 0.594727f, 0.016495f, 0.583008f, 0.015388f, 0.571289f, 0.014366f, + 0.559570f, 0.013412f, 0.546875f, 0.012520f, 0.534668f, 0.011696f, 0.522461f, 0.010925f, + 0.551758f, 0.447754f, 0.551758f, 0.447754f, 0.552246f, 0.447510f, 0.552246f, 0.447266f, + 0.552734f, 0.446289f, 0.553223f, 0.444580f, 0.555176f, 0.441895f, 0.556152f, 0.438232f, + 0.558594f, 0.432617f, 0.561035f, 0.425049f, 0.563477f, 0.415527f, 0.566406f, 0.404053f, + 0.570312f, 0.390381f, 0.575195f, 0.375000f, 0.578613f, 0.358154f, 0.584473f, 0.340332f, + 0.593750f, 0.322266f, 0.600098f, 0.303955f, 0.611328f, 0.286133f, 0.617676f, 0.268555f, + 0.629395f, 0.251709f, 0.640625f, 0.235352f, 0.649902f, 0.219849f, 0.661621f, 0.205078f, + 0.671387f, 0.191284f, 0.678711f, 0.178223f, 0.688965f, 0.166016f, 0.699707f, 0.154419f, + 0.707031f, 0.143555f, 0.714844f, 0.133545f, 0.719727f, 0.124084f, 0.726074f, 0.115295f, + 0.731445f, 0.107056f, 0.734863f, 0.099365f, 0.737305f, 0.092285f, 0.739258f, 0.085632f, + 0.740234f, 0.079529f, 0.739746f, 0.073792f, 0.739258f, 0.068542f, 0.737793f, 0.063599f, + 0.734863f, 0.059082f, 0.731934f, 0.054871f, 0.727539f, 0.050964f, 0.723633f, 0.047394f, + 0.717773f, 0.044006f, 0.711426f, 0.040924f, 0.705078f, 0.038055f, 0.697754f, 0.035400f, + 0.689941f, 0.032928f, 0.681641f, 0.030655f, 0.672852f, 0.028534f, 0.663574f, 0.026581f, + 0.653809f, 0.024750f, 0.644043f, 0.023071f, 0.633301f, 0.021515f, 0.622559f, 0.020050f, + 0.611328f, 0.018707f, 0.600098f, 0.017456f, 0.588867f, 0.016296f, 0.577148f, 0.015221f, + 0.565430f, 0.014221f, 0.553223f, 0.013290f, 0.541504f, 0.012421f, 0.528809f, 0.011620f, + 0.509277f, 0.490234f, 0.509277f, 0.490234f, 0.509277f, 0.489990f, 0.509766f, 0.489502f, + 0.510254f, 0.488525f, 0.511230f, 0.486328f, 0.512695f, 0.482910f, 0.514160f, 0.478027f, + 0.517578f, 0.470947f, 0.520996f, 0.461670f, 0.523926f, 0.449707f, 0.528809f, 0.435303f, + 0.534180f, 0.418945f, 0.540527f, 0.400635f, 0.548340f, 0.381348f, 0.554688f, 0.361328f, + 0.566895f, 0.340820f, 0.577637f, 0.320801f, 0.588867f, 0.301270f, 0.601074f, 0.282471f, + 0.610352f, 0.264404f, 0.624023f, 0.247070f, 0.637207f, 0.230591f, 0.649414f, 0.215210f, + 0.662109f, 0.200562f, 0.672852f, 0.186768f, 0.685547f, 0.173828f, 0.693359f, 0.161743f, + 0.702148f, 0.150391f, 0.711426f, 0.139771f, 0.720703f, 0.129883f, 0.726074f, 0.120667f, + 0.730469f, 0.112061f, 0.733887f, 0.104065f, 0.738281f, 0.096619f, 0.739258f, 0.089722f, + 0.740234f, 0.083252f, 0.741699f, 0.077332f, 0.740723f, 0.071777f, 0.739258f, 0.066711f, + 0.736816f, 0.061951f, 0.734375f, 0.057556f, 0.730469f, 0.053497f, 0.726074f, 0.049713f, + 0.720703f, 0.046234f, 0.714844f, 0.042999f, 0.708496f, 0.039978f, 0.701172f, 0.037231f, + 0.693848f, 0.034637f, 0.685547f, 0.032257f, 0.677246f, 0.030060f, 0.667969f, 0.028000f, + 0.658691f, 0.026108f, 0.648926f, 0.024338f, 0.638672f, 0.022705f, 0.627930f, 0.021194f, + 0.617188f, 0.019775f, 0.605957f, 0.018463f, 0.594727f, 0.017258f, 0.583008f, 0.016129f, + 0.571289f, 0.015076f, 0.559570f, 0.014099f, 0.547852f, 0.013191f, 0.535645f, 0.012337f, + 0.463623f, 0.536133f, 0.463623f, 0.536133f, 0.463867f, 0.535645f, 0.464111f, 0.535156f, + 0.465088f, 0.533691f, 0.466064f, 0.530762f, 0.468506f, 0.526367f, 0.471191f, 0.520020f, + 0.474609f, 0.511230f, 0.478516f, 0.499268f, 0.483643f, 0.484375f, 0.489990f, 0.466797f, + 0.495361f, 0.447266f, 0.502441f, 0.425537f, 0.515137f, 0.403564f, 0.526855f, 0.380859f, + 0.540039f, 0.358887f, 0.553711f, 0.336914f, 0.564453f, 0.315918f, 0.587891f, 0.295898f, + 0.600098f, 0.276611f, 0.610840f, 0.258545f, 0.624512f, 0.241211f, 0.641113f, 0.225098f, + 0.657715f, 0.209717f, 0.668457f, 0.195312f, 0.678223f, 0.181763f, 0.687988f, 0.169067f, + 0.701172f, 0.157104f, 0.707031f, 0.146118f, 0.715332f, 0.135620f, 0.723145f, 0.125977f, + 0.728516f, 0.117126f, 0.734375f, 0.108704f, 0.736328f, 0.100952f, 0.739746f, 0.093750f, + 0.741699f, 0.087036f, 0.742188f, 0.080872f, 0.741699f, 0.075134f, 0.741211f, 0.069763f, + 0.739258f, 0.064819f, 0.736816f, 0.060272f, 0.733398f, 0.056030f, 0.729004f, 0.052124f, + 0.724121f, 0.048492f, 0.718750f, 0.045105f, 0.712402f, 0.041992f, 0.705078f, 0.039093f, + 0.698242f, 0.036407f, 0.689941f, 0.033905f, 0.681641f, 0.031616f, 0.672852f, 0.029480f, + 0.663574f, 0.027512f, 0.653809f, 0.025665f, 0.644043f, 0.023956f, 0.633301f, 0.022369f, + 0.622559f, 0.020889f, 0.611816f, 0.019516f, 0.601074f, 0.018250f, 0.589355f, 0.017059f, + 0.578125f, 0.015961f, 0.565918f, 0.014946f, 0.554199f, 0.013992f, 0.542480f, 0.013107f, + 0.414551f, 0.584961f, 0.414551f, 0.584961f, 0.414795f, 0.584961f, 0.415039f, 0.583984f, + 0.416260f, 0.582031f, 0.418457f, 0.578613f, 0.420166f, 0.572754f, 0.424072f, 0.563965f, + 0.428467f, 0.552246f, 0.433838f, 0.537109f, 0.441162f, 0.518066f, 0.448730f, 0.497070f, + 0.458984f, 0.473633f, 0.467773f, 0.449219f, 0.480713f, 0.424072f, 0.497559f, 0.399414f, + 0.511719f, 0.375244f, 0.529297f, 0.352051f, 0.543945f, 0.329834f, 0.566895f, 0.308838f, + 0.581543f, 0.288574f, 0.598633f, 0.269531f, 0.619629f, 0.251465f, 0.635742f, 0.234497f, + 0.646973f, 0.218506f, 0.659668f, 0.203369f, 0.674805f, 0.189331f, 0.684570f, 0.176025f, + 0.695801f, 0.163696f, 0.707031f, 0.152222f, 0.718750f, 0.141357f, 0.723145f, 0.131348f, + 0.729004f, 0.122009f, 0.734375f, 0.113342f, 0.738281f, 0.105286f, 0.741211f, 0.097778f, + 0.743164f, 0.090820f, 0.744629f, 0.084412f, 0.744629f, 0.078430f, 0.743652f, 0.072876f, + 0.742676f, 0.067749f, 0.739746f, 0.062988f, 0.735840f, 0.058624f, 0.731934f, 0.054535f, + 0.727539f, 0.050751f, 0.721680f, 0.047241f, 0.715820f, 0.044006f, 0.709473f, 0.040985f, + 0.702148f, 0.038208f, 0.694824f, 0.035614f, 0.686523f, 0.033234f, 0.677734f, 0.031006f, + 0.668457f, 0.028946f, 0.659180f, 0.027023f, 0.649414f, 0.025238f, 0.639160f, 0.023590f, + 0.628906f, 0.022049f, 0.618164f, 0.020630f, 0.606934f, 0.019287f, 0.595703f, 0.018051f, + 0.584473f, 0.016907f, 0.572754f, 0.015839f, 0.561035f, 0.014839f, 0.549316f, 0.013908f, + 0.361816f, 0.637695f, 0.361816f, 0.637695f, 0.362061f, 0.637207f, 0.362793f, 0.636230f, + 0.364258f, 0.633301f, 0.366455f, 0.628906f, 0.369873f, 0.621094f, 0.374512f, 0.609375f, + 0.378906f, 0.593750f, 0.387451f, 0.573730f, 0.396484f, 0.550293f, 0.407471f, 0.524414f, + 0.419189f, 0.497314f, 0.433594f, 0.469971f, 0.453613f, 0.442627f, 0.473633f, 0.416016f, + 0.488037f, 0.390381f, 0.509277f, 0.365967f, 0.528809f, 0.343262f, 0.549805f, 0.320801f, + 0.574707f, 0.299805f, 0.590332f, 0.280029f, 0.609375f, 0.261475f, 0.631836f, 0.243774f, + 0.641602f, 0.227173f, 0.659668f, 0.211426f, 0.671387f, 0.196777f, 0.685059f, 0.183105f, + 0.698730f, 0.170166f, 0.705078f, 0.158203f, 0.715820f, 0.146973f, 0.723145f, 0.136597f, + 0.730469f, 0.126831f, 0.737793f, 0.117920f, 0.740723f, 0.109558f, 0.741699f, 0.101807f, + 0.745117f, 0.094604f, 0.747559f, 0.087891f, 0.747070f, 0.081726f, 0.747070f, 0.075989f, + 0.744141f, 0.070679f, 0.742676f, 0.065796f, 0.739258f, 0.061218f, 0.735840f, 0.056976f, + 0.730957f, 0.053070f, 0.725586f, 0.049438f, 0.719727f, 0.046082f, 0.713867f, 0.042938f, + 0.706543f, 0.040070f, 0.699219f, 0.037384f, 0.690918f, 0.034882f, 0.682617f, 0.032562f, + 0.673828f, 0.030426f, 0.664551f, 0.028442f, 0.654785f, 0.026581f, 0.645020f, 0.024857f, + 0.634766f, 0.023254f, 0.624023f, 0.021774f, 0.613281f, 0.020386f, 0.602051f, 0.019089f, + 0.590820f, 0.017899f, 0.579590f, 0.016769f, 0.567871f, 0.015732f, 0.556641f, 0.014755f, + 0.305420f, 0.694336f, 0.305420f, 0.694336f, 0.305664f, 0.693848f, 0.306641f, 0.691895f, + 0.308105f, 0.687988f, 0.311279f, 0.681152f, 0.316162f, 0.669922f, 0.321777f, 0.654297f, + 0.330078f, 0.632812f, 0.344238f, 0.606934f, 0.353027f, 0.578125f, 0.367432f, 0.547852f, + 0.385498f, 0.517578f, 0.405273f, 0.487793f, 0.422852f, 0.458496f, 0.448730f, 0.431152f, + 0.473633f, 0.404541f, 0.493896f, 0.379639f, 0.519531f, 0.355469f, 0.539551f, 0.332520f, + 0.563477f, 0.310791f, 0.583008f, 0.290283f, 0.604004f, 0.270752f, 0.626953f, 0.252686f, + 0.642090f, 0.235352f, 0.657715f, 0.218994f, 0.672852f, 0.203857f, 0.686523f, 0.189575f, + 0.699219f, 0.176270f, 0.707031f, 0.163818f, 0.717285f, 0.152344f, 0.723633f, 0.141602f, + 0.730469f, 0.131592f, 0.739258f, 0.122375f, 0.741699f, 0.113708f, 0.745605f, 0.105713f, + 0.747559f, 0.098267f, 0.748047f, 0.091370f, 0.749023f, 0.085022f, 0.748535f, 0.079102f, + 0.747070f, 0.073608f, 0.746582f, 0.068542f, 0.742188f, 0.063843f, 0.739258f, 0.059448f, + 0.734375f, 0.055420f, 0.730469f, 0.051666f, 0.724609f, 0.048187f, 0.717773f, 0.044952f, + 0.710938f, 0.041962f, 0.704102f, 0.039154f, 0.695801f, 0.036591f, 0.687988f, 0.034180f, + 0.679199f, 0.031952f, 0.670410f, 0.029892f, 0.660645f, 0.027969f, 0.650879f, 0.026184f, + 0.640625f, 0.024521f, 0.630371f, 0.022964f, 0.619629f, 0.021515f, 0.608887f, 0.020172f, + 0.598145f, 0.018921f, 0.586914f, 0.017761f, 0.575195f, 0.016663f, 0.563965f, 0.015656f, + 0.244995f, 0.754395f, 0.245117f, 0.754395f, 0.245483f, 0.753418f, 0.246704f, 0.750977f, + 0.249634f, 0.745117f, 0.253662f, 0.734863f, 0.260010f, 0.717773f, 0.268555f, 0.694336f, + 0.277344f, 0.665527f, 0.292480f, 0.632812f, 0.309814f, 0.599121f, 0.331787f, 0.565918f, + 0.352539f, 0.533203f, 0.376465f, 0.501953f, 0.405518f, 0.472412f, 0.433838f, 0.444336f, + 0.456787f, 0.417236f, 0.488281f, 0.391357f, 0.510254f, 0.366211f, 0.540039f, 0.343018f, + 0.564941f, 0.320557f, 0.579590f, 0.299561f, 0.606445f, 0.279541f, 0.627441f, 0.260498f, + 0.638184f, 0.242676f, 0.666504f, 0.226074f, 0.670898f, 0.210327f, 0.687988f, 0.195801f, + 0.700684f, 0.182129f, 0.706055f, 0.169312f, 0.718262f, 0.157471f, 0.727539f, 0.146362f, + 0.735840f, 0.136108f, 0.738770f, 0.126587f, 0.743164f, 0.117737f, 0.746582f, 0.109497f, + 0.751953f, 0.101868f, 0.751953f, 0.094788f, 0.753906f, 0.088257f, 0.752930f, 0.082153f, + 0.750977f, 0.076538f, 0.749512f, 0.071289f, 0.745605f, 0.066406f, 0.742188f, 0.061951f, + 0.738281f, 0.057770f, 0.734375f, 0.053894f, 0.729004f, 0.050293f, 0.722656f, 0.046967f, + 0.715332f, 0.043854f, 0.708496f, 0.040985f, 0.701172f, 0.038330f, 0.693359f, 0.035828f, + 0.684570f, 0.033539f, 0.676270f, 0.031403f, 0.666992f, 0.029404f, 0.657227f, 0.027542f, + 0.646973f, 0.025818f, 0.636719f, 0.024200f, 0.626465f, 0.022705f, 0.615723f, 0.021301f, + 0.604980f, 0.020004f, 0.593750f, 0.018784f, 0.582520f, 0.017654f, 0.571289f, 0.016586f, + 0.180542f, 0.818848f, 0.180664f, 0.818848f, 0.181274f, 0.817383f, 0.183350f, 0.812988f, + 0.187134f, 0.802734f, 0.193237f, 0.784180f, 0.201416f, 0.757324f, 0.214355f, 0.723145f, + 0.231445f, 0.685547f, 0.248901f, 0.648438f, 0.272217f, 0.611816f, 0.302979f, 0.577148f, + 0.329834f, 0.544922f, 0.364258f, 0.514160f, 0.394043f, 0.484619f, 0.425781f, 0.456055f, + 0.456543f, 0.428467f, 0.481934f, 0.402344f, 0.512207f, 0.376709f, 0.540039f, 0.352783f, + 0.566406f, 0.329346f, 0.579102f, 0.307617f, 0.607910f, 0.286865f, 0.627930f, 0.267822f, + 0.645996f, 0.249512f, 0.661621f, 0.232178f, 0.677734f, 0.216309f, 0.691406f, 0.201172f, + 0.702637f, 0.187256f, 0.711426f, 0.174194f, 0.721680f, 0.161987f, 0.730957f, 0.150879f, + 0.736328f, 0.140259f, 0.742188f, 0.130493f, 0.746582f, 0.121582f, 0.750488f, 0.113159f, + 0.751953f, 0.105347f, 0.752930f, 0.098083f, 0.756836f, 0.091370f, 0.755859f, 0.085144f, + 0.755371f, 0.079346f, 0.752441f, 0.073975f, 0.750488f, 0.069031f, 0.746582f, 0.064392f, + 0.743652f, 0.060120f, 0.737793f, 0.056152f, 0.733398f, 0.052460f, 0.727051f, 0.049011f, + 0.720215f, 0.045837f, 0.713867f, 0.042847f, 0.706543f, 0.040100f, 0.699219f, 0.037537f, + 0.690430f, 0.035156f, 0.682129f, 0.032928f, 0.672852f, 0.030884f, 0.663086f, 0.028961f, + 0.653809f, 0.027161f, 0.644043f, 0.025497f, 0.633301f, 0.023941f, 0.622559f, 0.022491f, + 0.612305f, 0.021133f, 0.601074f, 0.019867f, 0.590332f, 0.018692f, 0.579102f, 0.017578f, + 0.111816f, 0.888184f, 0.112000f, 0.887207f, 0.112976f, 0.883789f, 0.115845f, 0.873047f, + 0.122864f, 0.849609f, 0.133301f, 0.813477f, 0.147217f, 0.770996f, 0.167236f, 0.728027f, + 0.196411f, 0.688965f, 0.222290f, 0.653320f, 0.258057f, 0.619629f, 0.293457f, 0.587402f, + 0.328613f, 0.556152f, 0.361328f, 0.524902f, 0.392578f, 0.495850f, 0.430420f, 0.466064f, + 0.459961f, 0.437744f, 0.482422f, 0.410889f, 0.511230f, 0.385010f, 0.536621f, 0.359863f, + 0.568848f, 0.336182f, 0.592773f, 0.313721f, 0.614258f, 0.293213f, 0.626953f, 0.273193f, + 0.646484f, 0.254639f, 0.657227f, 0.237427f, 0.683105f, 0.221191f, 0.693359f, 0.205933f, + 0.698242f, 0.191772f, 0.709473f, 0.178589f, 0.724609f, 0.166260f, 0.733398f, 0.154907f, + 0.739746f, 0.144165f, 0.745605f, 0.134399f, 0.750977f, 0.125122f, 0.753906f, 0.116577f, + 0.754883f, 0.108704f, 0.758301f, 0.101257f, 0.759766f, 0.094482f, 0.757812f, 0.088074f, + 0.759766f, 0.082092f, 0.758301f, 0.076660f, 0.756348f, 0.071594f, 0.752441f, 0.066833f, + 0.748047f, 0.062469f, 0.741699f, 0.058380f, 0.736816f, 0.054596f, 0.732910f, 0.051086f, + 0.726074f, 0.047791f, 0.719727f, 0.044769f, 0.711914f, 0.041901f, 0.704590f, 0.039276f, + 0.696289f, 0.036804f, 0.688477f, 0.034546f, 0.678711f, 0.032410f, 0.669922f, 0.030411f, + 0.660156f, 0.028564f, 0.650391f, 0.026840f, 0.640625f, 0.025223f, 0.630371f, 0.023727f, + 0.619629f, 0.022324f, 0.608887f, 0.020996f, 0.597656f, 0.019775f, 0.586914f, 0.018631f, + 0.038452f, 0.960938f, 0.039124f, 0.957520f, 0.042480f, 0.933594f, 0.051575f, 0.879395f, + 0.069275f, 0.824219f, 0.091064f, 0.785156f, 0.126343f, 0.753906f, 0.154419f, 0.725586f, + 0.192139f, 0.695312f, 0.234375f, 0.663086f, 0.273438f, 0.630371f, 0.305908f, 0.597656f, + 0.338379f, 0.565430f, 0.379150f, 0.532227f, 0.413818f, 0.501465f, 0.444336f, 0.471191f, + 0.471436f, 0.442383f, 0.504395f, 0.414795f, 0.531250f, 0.388672f, 0.547363f, 0.364014f, + 0.579590f, 0.340088f, 0.603516f, 0.317627f, 0.622559f, 0.297119f, 0.635742f, 0.276855f, + 0.669434f, 0.258301f, 0.670410f, 0.241089f, 0.685547f, 0.224854f, 0.699219f, 0.209717f, + 0.712402f, 0.195190f, 0.720703f, 0.182373f, 0.729980f, 0.169678f, 0.746582f, 0.158325f, + 0.744629f, 0.147705f, 0.748535f, 0.137695f, 0.760254f, 0.128296f, 0.757812f, 0.119629f, + 0.761230f, 0.111755f, 0.762207f, 0.104248f, 0.764160f, 0.097290f, 0.763184f, 0.090881f, + 0.762207f, 0.084900f, 0.760742f, 0.079285f, 0.759766f, 0.074097f, 0.755859f, 0.069275f, + 0.752930f, 0.064758f, 0.747559f, 0.060669f, 0.742676f, 0.056793f, 0.737305f, 0.053131f, + 0.731445f, 0.049774f, 0.725586f, 0.046661f, 0.718262f, 0.043732f, 0.710449f, 0.041077f, + 0.702637f, 0.038544f, 0.694336f, 0.036163f, 0.685547f, 0.033966f, 0.676758f, 0.031921f, + 0.667480f, 0.030014f, 0.657715f, 0.028229f, 0.647461f, 0.026566f, 0.637207f, 0.025009f, + 0.626953f, 0.023544f, 0.616699f, 0.022186f, 0.605957f, 0.020920f, 0.594727f, 0.019730f +}; + +static float ltc_disk_integral[64 * 64] = { + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.015873f, 0.047619f, 0.079365f, 0.111111f, 0.142857f, 0.174603f, 0.206349f, 0.238095f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000148f, 0.002454f, 0.008675f, 0.019560f, + 0.035433f, 0.056294f, 0.081819f, 0.111259f, 0.142857f, 0.174603f, 0.206349f, 0.238095f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000002f, 0.000761f, 0.003673f, 0.009403f, 0.018333f, 0.030683f, + 0.046556f, 0.065952f, 0.088768f, 0.114784f, 0.143618f, 0.174606f, 0.206349f, 0.238095f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000039f, 0.000969f, 0.003703f, 0.008684f, 0.016189f, 0.026395f, 0.039409f, + 0.055282f, 0.074014f, 0.095554f, 0.119795f, 0.146560f, 0.175573f, 0.206388f, 0.238095f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000047f, 0.000895f, 0.003265f, 0.007514f, 0.013873f, 0.022495f, 0.033483f, 0.046897f, + 0.062770f, 0.081102f, 0.101860f, 0.124985f, 0.150372f, 0.177868f, 0.207245f, 0.238143f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000028f, + 0.000695f, 0.002655f, 0.006230f, 0.011623f, 0.018976f, 0.028384f, 0.039915f, 0.053606f, + 0.069479f, 0.087534f, 0.107749f, 0.130087f, 0.154481f, 0.180833f, 0.209005f, 0.238791f, + 0.269869f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000465f, + 0.002017f, 0.004975f, 0.009533f, 0.015821f, 0.023934f, 0.033937f, 0.045874f, 0.059772f, + 0.075645f, 0.093493f, 0.113302f, 0.135045f, 0.158678f, 0.184136f, 0.211325f, 0.240113f, + 0.270306f, 0.301594f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000260f, 0.001426f, + 0.003823f, 0.007642f, 0.013012f, 0.020025f, 0.028745f, 0.039218f, 0.051475f, 0.065535f, + 0.081408f, 0.099094f, 0.118583f, 0.139856f, 0.162882f, 0.187615f, 0.213991f, 0.241918f, + 0.271267f, 0.301847f, 0.333333f, 0.365079f, 0.396826f, 0.428572f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000109f, 0.000921f, 0.002807f, + 0.005966f, 0.010528f, 0.016585f, 0.024200f, 0.033420f, 0.044278f, 0.056796f, 0.070988f, + 0.086861f, 0.104415f, 0.123643f, 0.144531f, 0.167057f, 0.191188f, 0.216878f, 0.244062f, + 0.272649f, 0.302509f, 0.333442f, 0.365079f, 0.396826f, 0.428572f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000024f, 0.000524f, 0.001947f, 0.004511f, + 0.008351f, 0.013561f, 0.020206f, 0.028332f, 0.037974f, 0.049155f, 0.061892f, 0.076194f, + 0.092067f, 0.109511f, 0.128520f, 0.149085f, 0.171189f, 0.194809f, 0.219910f, 0.246447f, + 0.274352f, 0.303535f, 0.333857f, 0.365104f, 0.396826f, 0.428572f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000242f, 0.001250f, 0.003275f, 0.006463f, + 0.010913f, 0.016693f, 0.023849f, 0.032418f, 0.042423f, 0.053881f, 0.066805f, 0.081201f, + 0.097074f, 0.114424f, 0.133246f, 0.153534f, 0.175275f, 0.198453f, 0.223042f, 0.249009f, + 0.276304f, 0.304862f, 0.334584f, 0.365322f, 0.396826f, 0.428571f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000074f, 0.000716f, 0.002252f, 0.004848f, 0.008610f, + 0.013608f, 0.019894f, 0.027502f, 0.036458f, 0.046780f, 0.058480f, 0.071567f, 0.086045f, + 0.101918f, 0.119186f, 0.137845f, 0.157891f, 0.179316f, 0.202106f, 0.226243f, 0.251704f, + 0.278451f, 0.306436f, 0.335586f, 0.365796f, 0.396900f, 0.428571f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000006f, 0.000342f, 0.001437f, 0.003492f, 0.006624f, 0.010911f, + 0.016406f, 0.023146f, 0.031157f, 0.040457f, 0.051059f, 0.062972f, 0.076203f, 0.090753f, + 0.106626f, 0.123822f, 0.142337f, 0.162170f, 0.183314f, 0.205760f, 0.229496f, 0.254502f, + 0.280753f, 0.308212f, 0.336825f, 0.366517f, 0.397167f, 0.428578f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000114f, 0.000820f, 0.002381f, 0.004935f, 0.008569f, 0.013339f, + 0.019286f, 0.026437f, 0.034810f, 0.044418f, 0.055271f, 0.067375f, 0.080733f, 0.095348f, + 0.111221f, 0.128352f, 0.146740f, 0.166382f, 0.187276f, 0.209413f, 0.232786f, 0.257382f, + 0.283181f, 0.310156f, 0.338269f, 0.367461f, 0.397646f, 0.428685f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000014f, 0.000390f, 0.001503f, 0.003525f, 0.006554f, 0.010655f, 0.015872f, + 0.022233f, 0.029758f, 0.038460f, 0.048347f, 0.059427f, 0.071702f, 0.085175f, 0.099848f, + 0.115721f, 0.132794f, 0.151067f, 0.170538f, 0.191204f, 0.213063f, 0.236107f, 0.260329f, + 0.285714f, 0.312243f, 0.339887f, 0.368604f, 0.398329f, 0.428961f, 0.460331f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000130f, 0.000845f, 0.002376f, 0.004845f, 0.008325f, 0.012864f, 0.018495f, + 0.025237f, 0.033105f, 0.042107f, 0.052249f, 0.063534f, 0.075965f, 0.089543f, 0.104269f, + 0.120142f, 0.137163f, 0.155330f, 0.174645f, 0.195106f, 0.216710f, 0.239454f, 0.263332f, + 0.288336f, 0.314451f, 0.341658f, 0.369924f, 0.399202f, 0.429416f, 0.460447f, 0.492064f, + 0.523809f, 0.555555f, 0.587301f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000016f, 0.000391f, 0.001475f, 0.003423f, 0.006322f, 0.010230f, 0.015179f, 0.021195f, + 0.028290f, 0.036474f, 0.045752f, 0.056128f, 0.067602f, 0.080176f, 0.093850f, 0.108623f, + 0.124496f, 0.141469f, 0.159541f, 0.178713f, 0.198985f, 0.220355f, 0.242823f, 0.266385f, + 0.291036f, 0.316767f, 0.343563f, 0.371402f, 0.400248f, 0.430047f, 0.460709f, 0.492079f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000123f, 0.000807f, 0.002272f, 0.004628f, 0.007942f, 0.012253f, 0.017589f, 0.023963f, + 0.031387f, 0.039864f, 0.049398f, 0.059990f, 0.071638f, 0.084344f, 0.098106f, 0.112923f, + 0.128796f, 0.145725f, 0.163709f, 0.182749f, 0.202847f, 0.224001f, 0.246214f, 0.269482f, + 0.293805f, 0.319176f, 0.345587f, 0.373021f, 0.401454f, 0.430844f, 0.461125f, 0.492187f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f, + 0.000356f, 0.001378f, 0.003225f, 0.005979f, 0.009689f, 0.014384f, 0.020083f, 0.026795f, + 0.034525f, 0.043276f, 0.053047f, 0.063839f, 0.075649f, 0.088476f, 0.102320f, 0.117178f, + 0.133051f, 0.149939f, 0.167841f, 0.186760f, 0.206696f, 0.227650f, 0.249625f, 0.272620f, + 0.296636f, 0.321671f, 0.347718f, 0.374768f, 0.402804f, 0.431796f, 0.461695f, 0.492420f, + 0.523822f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000100f, + 0.000725f, 0.002097f, 0.004323f, 0.007463f, 0.011553f, 0.016613f, 0.022655f, 0.029684f, + 0.037702f, 0.046708f, 0.056701f, 0.067680f, 0.079640f, 0.092581f, 0.106501f, 0.121397f, + 0.137270f, 0.154120f, 0.171946f, 0.190751f, 0.210537f, 0.231305f, 0.253057f, 0.275797f, + 0.299525f, 0.324242f, 0.349947f, 0.376633f, 0.404289f, 0.432895f, 0.462415f, 0.492788f, + 0.523909f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000005f, 0.000296f, + 0.001231f, 0.002960f, 0.005558f, 0.009072f, 0.013526f, 0.018933f, 0.025299f, 0.032627f, + 0.040916f, 0.050162f, 0.060364f, 0.071517f, 0.083619f, 0.096666f, 0.110656f, 0.125588f, + 0.141461f, 0.158275f, 0.176031f, 0.194730f, 0.214374f, 0.234967f, 0.256512f, 0.279011f, + 0.302468f, 0.326887f, 0.352266f, 0.378605f, 0.405897f, 0.434130f, 0.463277f, 0.493295f, + 0.524106f, 0.555561f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000068f, 0.000613f, + 0.001874f, 0.003958f, 0.006921f, 0.010796f, 0.015599f, 0.021336f, 0.028011f, 0.035623f, + 0.044167f, 0.053640f, 0.064038f, 0.075355f, 0.087589f, 0.100736f, 0.114793f, 0.129759f, + 0.145632f, 0.162412f, 0.180101f, 0.198700f, 0.218213f, 0.238641f, 0.259989f, 0.282262f, + 0.305464f, 0.329599f, 0.354670f, 0.380678f, 0.407622f, 0.435493f, 0.464275f, 0.493938f, + 0.524422f, 0.555624f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000223f, 0.001054f, + 0.002649f, 0.005086f, 0.008406f, 0.012629f, 0.017766f, 0.023820f, 0.030789f, 0.038669f, + 0.047455f, 0.057143f, 0.067726f, 0.079199f, 0.091558f, 0.104798f, 0.118918f, 0.133915f, + 0.149788f, 0.166537f, 0.184164f, 0.202669f, 0.222056f, 0.242329f, 0.263492f, 0.285551f, + 0.308510f, 0.332376f, 0.357153f, 0.382845f, 0.409454f, 0.436977f, 0.465404f, 0.494713f, + 0.524864f, 0.555779f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000037f, 0.000486f, 0.001621f, + 0.003553f, 0.006338f, 0.010004f, 0.014565f, 0.020024f, 0.026380f, 0.033629f, 0.041765f, + 0.050782f, 0.060673f, 0.071431f, 0.083052f, 0.095529f, 0.108859f, 0.123038f, 0.138065f, + 0.153938f, 0.170657f, 0.188224f, 0.206640f, 0.225909f, 0.246035f, 0.267022f, 0.288878f, + 0.311607f, 0.335216f, 0.359713f, 0.385103f, 0.411390f, 0.438576f, 0.466656f, 0.495617f, + 0.525431f, 0.556041f, 0.587338f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000149f, 0.000861f, 0.002312f, + 0.004581f, 0.007709f, 0.011713f, 0.016599f, 0.022367f, 0.029014f, 0.036531f, 0.044912f, + 0.054148f, 0.064233f, 0.075158f, 0.086918f, 0.099507f, 0.112922f, 0.127157f, 0.142212f, + 0.158085f, 0.174776f, 0.192287f, 0.210619f, 0.229775f, 0.249761f, 0.270582f, 0.292243f, + 0.314753f, 0.338118f, 0.362347f, 0.387447f, 0.413424f, 0.440284f, 0.468027f, 0.496645f, + 0.526122f, 0.556417f, 0.587451f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f, 0.000355f, 0.001353f, 0.003126f, + 0.005730f, 0.009194f, 0.013526f, 0.018728f, 0.024795f, 0.031720f, 0.039494f, 0.048109f, + 0.057555f, 0.067824f, 0.078909f, 0.090802f, 0.103499f, 0.116993f, 0.131282f, 0.146364f, + 0.162237f, 0.178902f, 0.196358f, 0.214610f, 0.233660f, 0.253512f, 0.274174f, 0.295650f, + 0.317950f, 0.341081f, 0.365053f, 0.389874f, 0.415553f, 0.442098f, 0.469512f, 0.497794f, + 0.526935f, 0.556908f, 0.587657f, 0.619060f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000083f, 0.000665f, 0.001962f, 0.004059f, + 0.006997f, 0.010790f, 0.015442f, 0.020949f, 0.027304f, 0.034497f, 0.042518f, 0.051358f, + 0.061005f, 0.071451f, 0.082688f, 0.094709f, 0.107507f, 0.121078f, 0.135419f, 0.150526f, + 0.166399f, 0.183038f, 0.200443f, 0.218618f, 0.237566f, 0.257291f, 0.277800f, 0.299100f, + 0.321199f, 0.344106f, 0.367830f, 0.392383f, 0.417774f, 0.444013f, 0.471107f, 0.499060f, + 0.527869f, 0.557517f, 0.587966f, 0.619130f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000233f, 0.001082f, 0.002688f, 0.005111f, + 0.008377f, 0.012493f, 0.017456f, 0.023260f, 0.029893f, 0.037345f, 0.045604f, 0.054659f, + 0.064499f, 0.075115f, 0.086498f, 0.098641f, 0.111537f, 0.125182f, 0.139571f, 0.154703f, + 0.170576f, 0.187190f, 0.204547f, 0.222648f, 0.241498f, 0.261101f, 0.281465f, 0.302595f, + 0.324501f, 0.347192f, 0.370679f, 0.394973f, 0.420085f, 0.446027f, 0.472810f, 0.500441f, + 0.528921f, 0.558244f, 0.588384f, 0.619281f, 0.650795f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000033f, 0.000477f, 0.001611f, 0.003532f, 0.006280f, + 0.009869f, 0.014301f, 0.019568f, 0.025659f, 0.032563f, 0.040265f, 0.048753f, 0.058016f, + 0.068042f, 0.078821f, 0.090344f, 0.102604f, 0.115594f, 0.129309f, 0.143745f, 0.158901f, + 0.174774f, 0.191365f, 0.208674f, 0.226705f, 0.245461f, 0.264947f, 0.285170f, 0.306137f, + 0.327857f, 0.350341f, 0.373598f, 0.397642f, 0.422485f, 0.448139f, 0.474619f, 0.501933f, + 0.530089f, 0.559087f, 0.588913f, 0.619525f, 0.650826f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000130f, 0.000821f, 0.002252f, 0.004491f, 0.007562f, + 0.011472f, 0.016213f, 0.021776f, 0.028147f, 0.035312f, 0.043256f, 0.051966f, 0.061430f, + 0.071635f, 0.082571f, 0.094229f, 0.106602f, 0.119682f, 0.133465f, 0.147947f, 0.163125f, + 0.178998f, 0.195566f, 0.212830f, 0.230793f, 0.249459f, 0.268832f, 0.288920f, 0.309730f, + 0.331271f, 0.353554f, 0.376590f, 0.400391f, 0.424973f, 0.450347f, 0.476531f, 0.503535f, + 0.531372f, 0.560047f, 0.589554f, 0.619869f, 0.650923f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000005f, 0.000309f, 0.001270f, 0.003008f, 0.005566f, 0.008959f, + 0.013183f, 0.018228f, 0.024080f, 0.030723f, 0.038142f, 0.046321f, 0.055246f, 0.064903f, + 0.075281f, 0.086369f, 0.098158f, 0.110639f, 0.123806f, 0.137655f, 0.152180f, 0.167380f, + 0.183253f, 0.199799f, 0.217020f, 0.234918f, 0.253496f, 0.272761f, 0.292719f, 0.313377f, + 0.334745f, 0.356833f, 0.379654f, 0.403221f, 0.427548f, 0.452651f, 0.478545f, 0.505246f, + 0.532768f, 0.561122f, 0.590309f, 0.620318f, 0.651102f, 0.682545f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000053f, 0.000579f, 0.001828f, 0.003878f, 0.006757f, 0.010468f, + 0.015002f, 0.020344f, 0.026479f, 0.033388f, 0.041054f, 0.049461f, 0.058594f, 0.068440f, + 0.078985f, 0.090220f, 0.102134f, 0.114721f, 0.127972f, 0.141884f, 0.156451f, 0.171672f, + 0.187545f, 0.204070f, 0.221249f, 0.239083f, 0.257578f, 0.276738f, 0.296569f, 0.317080f, + 0.338281f, 0.360181f, 0.382794f, 0.406133f, 0.430213f, 0.455050f, 0.480662f, 0.507065f, + 0.534278f, 0.562313f, 0.591180f, 0.620875f, 0.651373f, 0.682593f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000169f, 0.000949f, 0.002497f, 0.004864f, 0.008063f, 0.012089f, + 0.016929f, 0.022563f, 0.028974f, 0.036142f, 0.044049f, 0.052678f, 0.062014f, 0.072042f, + 0.082750f, 0.094127f, 0.106164f, 0.118852f, 0.132185f, 0.146157f, 0.160766f, 0.176007f, + 0.191880f, 0.208385f, 0.225523f, 0.243296f, 0.261709f, 0.280767f, 0.300476f, 0.320845f, + 0.341883f, 0.363601f, 0.386011f, 0.409128f, 0.432967f, 0.457545f, 0.482881f, 0.508992f, + 0.535899f, 0.563619f, 0.592165f, 0.621544f, 0.651743f, 0.682709f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000010f, 0.000368f, 0.001423f, 0.003279f, 0.005966f, 0.009485f, 0.013824f, + 0.018964f, 0.024886f, 0.031567f, 0.038988f, 0.047130f, 0.055975f, 0.065508f, 0.075714f, + 0.086580f, 0.098095f, 0.110251f, 0.123038f, 0.136450f, 0.150482f, 0.165129f, 0.180390f, + 0.196263f, 0.212748f, 0.229847f, 0.247561f, 0.265895f, 0.284854f, 0.304445f, 0.324675f, + 0.345555f, 0.367095f, 0.389309f, 0.412210f, 0.435814f, 0.460138f, 0.485203f, 0.511028f, + 0.537634f, 0.565041f, 0.593268f, 0.622327f, 0.652217f, 0.682907f, 0.714296f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000068f, 0.000658f, 0.002006f, 0.004178f, 0.007186f, 0.011024f, 0.015672f, + 0.021109f, 0.027312f, 0.034259f, 0.041928f, 0.050300f, 0.059356f, 0.069081f, 0.079460f, + 0.090480f, 0.102130f, 0.114400f, 0.127284f, 0.140772f, 0.154862f, 0.169548f, 0.184828f, + 0.200701f, 0.217167f, 0.234227f, 0.251884f, 0.270141f, 0.289004f, 0.308479f, 0.328575f, + 0.349301f, 0.370668f, 0.392689f, 0.415379f, 0.438754f, 0.462830f, 0.487630f, 0.513173f, + 0.539482f, 0.566579f, 0.594488f, 0.623226f, 0.652800f, 0.683198f, 0.714354f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000196f, 0.001048f, 0.002702f, 0.005194f, 0.008526f, 0.012680f, 0.017635f, + 0.023365f, 0.029846f, 0.037053f, 0.044965f, 0.053561f, 0.062824f, 0.072737f, 0.083284f, + 0.094454f, 0.106236f, 0.118619f, 0.131595f, 0.145159f, 0.159305f, 0.174028f, 0.189327f, + 0.205200f, 0.221647f, 0.238670f, 0.256270f, 0.274453f, 0.293222f, 0.312585f, 0.332550f, + 0.353126f, 0.374324f, 0.396158f, 0.418641f, 0.441790f, 0.465624f, 0.490163f, 0.515429f, + 0.541445f, 0.568236f, 0.595828f, 0.624242f, 0.653496f, 0.683588f, 0.714482f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000012f, 0.000407f, 0.001545f, 0.003514f, 0.006332f, 0.009987f, 0.014457f, 0.019715f, + 0.025734f, 0.032488f, 0.039952f, 0.048102f, 0.056919f, 0.066384f, 0.076480f, 0.087193f, + 0.098509f, 0.110419f, 0.122912f, 0.135980f, 0.149617f, 0.163817f, 0.178577f, 0.193894f, + 0.209767f, 0.226196f, 0.243182f, 0.260728f, 0.278837f, 0.297515f, 0.316768f, 0.336605f, + 0.357034f, 0.378067f, 0.399717f, 0.421998f, 0.444928f, 0.468523f, 0.492806f, 0.517798f, + 0.543525f, 0.570012f, 0.597288f, 0.625379f, 0.654307f, 0.684084f, 0.714693f, 0.746044f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000074f, 0.000713f, 0.002152f, 0.004446f, 0.007592f, 0.011571f, 0.016356f, 0.021915f, + 0.028220f, 0.035243f, 0.042959f, 0.051344f, 0.060377f, 0.070040f, 0.080316f, 0.091191f, + 0.102651f, 0.114686f, 0.127286f, 0.140443f, 0.154151f, 0.168405f, 0.183201f, 0.198536f, + 0.214409f, 0.230820f, 0.247770f, 0.265263f, 0.283301f, 0.301889f, 0.321035f, 0.340746f, + 0.361032f, 0.381904f, 0.403374f, 0.425457f, 0.448169f, 0.471530f, 0.495561f, 0.520284f, + 0.545725f, 0.571911f, 0.598873f, 0.626640f, 0.655239f, 0.684692f, 0.714999f, 0.746106f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000208f, 0.001121f, 0.002877f, 0.005501f, 0.008979f, 0.013283f, 0.018380f, 0.024238f, + 0.030826f, 0.038115f, 0.046079f, 0.054695f, 0.063941f, 0.073799f, 0.084252f, 0.095285f, + 0.106886f, 0.119044f, 0.131749f, 0.144994f, 0.158772f, 0.173078f, 0.187908f, 0.203261f, + 0.219134f, 0.235527f, 0.252443f, 0.269883f, 0.287851f, 0.306352f, 0.325393f, 0.344981f, + 0.365126f, 0.385839f, 0.407132f, 0.429020f, 0.451520f, 0.474651f, 0.498433f, 0.522890f, + 0.548048f, 0.573936f, 0.600584f, 0.628027f, 0.656295f, 0.685417f, 0.715406f, 0.746240f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000011f, + 0.000427f, 0.001638f, 0.003724f, 0.006685f, 0.010497f, 0.015125f, 0.020534f, 0.026688f, + 0.033557f, 0.041109f, 0.049318f, 0.058161f, 0.067617f, 0.077666f, 0.088293f, 0.099482f, + 0.111221f, 0.123499f, 0.136308f, 0.149639f, 0.163485f, 0.177843f, 0.192707f, 0.208077f, + 0.223950f, 0.240326f, 0.257208f, 0.274596f, 0.292496f, 0.310911f, 0.329849f, 0.349316f, + 0.369323f, 0.389880f, 0.410999f, 0.432696f, 0.454987f, 0.477890f, 0.501426f, 0.525620f, + 0.550498f, 0.576089f, 0.602427f, 0.629544f, 0.657479f, 0.686264f, 0.715924f, 0.746459f, + 0.777789f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000071f, + 0.000744f, 0.002274f, 0.004698f, 0.008002f, 0.012149f, 0.017102f, 0.022822f, 0.029271f, + 0.036417f, 0.044229f, 0.052681f, 0.061749f, 0.071411f, 0.081649f, 0.092447f, 0.103790f, + 0.115665f, 0.128062f, 0.140972f, 0.154387f, 0.168301f, 0.182709f, 0.197608f, 0.212994f, + 0.228867f, 0.245227f, 0.262074f, 0.279412f, 0.297244f, 0.315575f, 0.334412f, 0.353760f, + 0.373631f, 0.394034f, 0.414983f, 0.436491f, 0.458575f, 0.481253f, 0.504547f, 0.528481f, + 0.553081f, 0.578377f, 0.604404f, 0.631197f, 0.658795f, 0.687238f, 0.716559f, 0.746776f, + 0.777849f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000205f, + 0.001168f, 0.003033f, 0.005806f, 0.009456f, 0.013942f, 0.019220f, 0.025250f, 0.031992f, + 0.039414f, 0.047484f, 0.056176f, 0.065466f, 0.075333f, 0.085757f, 0.096724f, 0.108218f, + 0.120227f, 0.132741f, 0.145751f, 0.159249f, 0.173230f, 0.187687f, 0.202619f, 0.218021f, + 0.233894f, 0.250238f, 0.267052f, 0.284341f, 0.302106f, 0.320354f, 0.339090f, 0.358322f, + 0.378059f, 0.398311f, 0.419090f, 0.440412f, 0.462292f, 0.484748f, 0.507802f, 0.531477f, + 0.555802f, 0.580805f, 0.606522f, 0.632990f, 0.660250f, 0.688346f, 0.717319f, 0.747200f, + 0.777982f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000427f, + 0.001710f, 0.003925f, 0.007054f, 0.011055f, 0.015881f, 0.021485f, 0.027824f, 0.034859f, + 0.042554f, 0.050881f, 0.059811f, 0.069321f, 0.079390f, 0.089998f, 0.101132f, 0.112775f, + 0.124917f, 0.137547f, 0.150655f, 0.164236f, 0.178281f, 0.192788f, 0.207752f, 0.223171f, + 0.239044f, 0.255371f, 0.272153f, 0.289393f, 0.307093f, 0.325259f, 0.343896f, 0.363012f, + 0.382617f, 0.402719f, 0.423332f, 0.444469f, 0.466146f, 0.488383f, 0.511199f, 0.534618f, + 0.558668f, 0.583380f, 0.608787f, 0.634929f, 0.661849f, 0.689594f, 0.718211f, 0.747742f, + 0.778205f, 0.809530f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000059f, 0.000754f, + 0.002379f, 0.004956f, 0.008449f, 0.012806f, 0.017974f, 0.023905f, 0.030553f, 0.037879f, + 0.045847f, 0.054429f, 0.063595f, 0.073323f, 0.083592f, 0.094384f, 0.105682f, 0.117474f, + 0.129747f, 0.142491f, 0.155697f, 0.169358f, 0.183469f, 0.198024f, 0.213020f, 0.228455f, + 0.244329f, 0.260639f, 0.277389f, 0.294580f, 0.312216f, 0.330300f, 0.348840f, 0.367842f, + 0.387315f, 0.407270f, 0.427717f, 0.448671f, 0.470149f, 0.492167f, 0.514746f, 0.537911f, + 0.561688f, 0.586108f, 0.611206f, 0.637022f, 0.663599f, 0.690989f, 0.719242f, 0.748411f, + 0.778531f, 0.809583f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000187f, 0.001196f, + 0.003184f, 0.006136f, 0.010000f, 0.014716f, 0.020230f, 0.026488f, 0.033445f, 0.041062f, + 0.049303f, 0.058138f, 0.067540f, 0.077485f, 0.087953f, 0.098926f, 0.110388f, 0.122327f, + 0.134729f, 0.147587f, 0.160889f, 0.174631f, 0.188806f, 0.203409f, 0.218437f, 0.233888f, + 0.249761f, 0.266056f, 0.282774f, 0.299917f, 0.317488f, 0.335493f, 0.353936f, 0.372825f, + 0.392168f, 0.411976f, 0.432259f, 0.453032f, 0.474310f, 0.496111f, 0.518456f, 0.541367f, + 0.564872f, 0.589001f, 0.613789f, 0.639277f, 0.665510f, 0.692539f, 0.720422f, 0.749216f, + 0.778974f, 0.809711f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000409f, 0.001767f, + 0.004137f, 0.007474f, 0.011716f, 0.016797f, 0.022657f, 0.029244f, 0.036512f, 0.044420f, + 0.052933f, 0.062021f, 0.071657f, 0.081819f, 0.092485f, 0.103638f, 0.115263f, 0.127348f, + 0.139880f, 0.152849f, 0.166248f, 0.180070f, 0.194308f, 0.208958f, 0.224018f, 0.239485f, + 0.255359f, 0.271638f, 0.288324f, 0.305419f, 0.322927f, 0.340851f, 0.359199f, 0.377975f, + 0.397189f, 0.416851f, 0.436971f, 0.457564f, 0.478644f, 0.500229f, 0.522339f, 0.544997f, + 0.568230f, 0.592068f, 0.616546f, 0.641705f, 0.667590f, 0.694255f, 0.721760f, 0.750168f, + 0.779545f, 0.809933f, 0.841272f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000041f, 0.000744f, 0.002481f, + 0.005248f, 0.008982f, 0.013608f, 0.019058f, 0.025269f, 0.032188f, 0.039767f, 0.047967f, + 0.056752f, 0.066093f, 0.075963f, 0.086340f, 0.097203f, 0.108537f, 0.120325f, 0.132554f, + 0.145215f, 0.158296f, 0.171790f, 0.185691f, 0.199993f, 0.214691f, 0.229782f, 0.245265f, + 0.261138f, 0.277401f, 0.294056f, 0.311104f, 0.328548f, 0.346394f, 0.364645f, 0.383310f, + 0.402396f, 0.421912f, 0.441870f, 0.462283f, 0.483165f, 0.504535f, 0.526410f, 0.548816f, + 0.571776f, 0.595323f, 0.619489f, 0.644317f, 0.669852f, 0.696148f, 0.723267f, 0.751280f, + 0.780258f, 0.810268f, 0.841311f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000156f, 0.001209f, 0.003349f, + 0.006531f, 0.010672f, 0.015691f, 0.021515f, 0.028080f, 0.035332f, 0.043225f, 0.051717f, + 0.060775f, 0.070370f, 0.080474f, 0.091067f, 0.102128f, 0.113641f, 0.125591f, 0.137965f, + 0.150754f, 0.163947f, 0.177537f, 0.191516f, 0.205881f, 0.220626f, 0.235749f, 0.251248f, + 0.267121f, 0.283368f, 0.299992f, 0.316992f, 0.334374f, 0.352140f, 0.370296f, 0.388849f, + 0.407807f, 0.427178f, 0.446974f, 0.467207f, 0.487892f, 0.509046f, 0.530687f, 0.552839f, + 0.575527f, 0.598780f, 0.622634f, 0.647128f, 0.672308f, 0.698231f, 0.724958f, 0.752563f, + 0.781127f, 0.810733f, 0.841426f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000374f, 0.001821f, 0.004389f, + 0.008001f, 0.012559f, 0.017979f, 0.024182f, 0.031106f, 0.038695f, 0.046903f, 0.055690f, + 0.065023f, 0.074872f, 0.085211f, 0.096020f, 0.107279f, 0.118971f, 0.131084f, 0.143604f, + 0.156521f, 0.169825f, 0.183510f, 0.197569f, 0.211997f, 0.226789f, 0.241944f, 0.257458f, + 0.273331f, 0.289563f, 0.306154f, 0.323108f, 0.340426f, 0.358113f, 0.376175f, 0.394616f, + 0.413445f, 0.432671f, 0.452305f, 0.472358f, 0.492845f, 0.513783f, 0.535189f, 0.557087f, + 0.579500f, 0.602459f, 0.625997f, 0.650154f, 0.674976f, 0.700518f, 0.726845f, 0.754032f, + 0.782167f, 0.811344f, 0.841644f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000020f, 0.000719f, 0.002598f, 0.005618f, + 0.009675f, 0.014663f, 0.020490f, 0.027080f, 0.034367f, 0.042297f, 0.050824f, 0.059909f, + 0.069517f, 0.079622f, 0.090198f, 0.101224f, 0.112682f, 0.124555f, 0.136831f, 0.149496f, + 0.162542f, 0.175958f, 0.189739f, 0.203877f, 0.218368f, 0.233208f, 0.248393f, 0.263923f, + 0.279796f, 0.296012f, 0.312573f, 0.329479f, 0.346734f, 0.364342f, 0.382307f, 0.400637f, + 0.419337f, 0.438418f, 0.457889f, 0.477761f, 0.498050f, 0.518770f, 0.539940f, 0.561581f, + 0.583718f, 0.606380f, 0.629599f, 0.653415f, 0.677874f, 0.703030f, 0.728948f, 0.755706f, + 0.783396f, 0.812121f, 0.841989f, 0.873035f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000114f, 0.001215f, 0.003561f, 0.007056f, + 0.011574f, 0.017003f, 0.023248f, 0.030232f, 0.037888f, 0.046164f, 0.055014f, 0.064399f, + 0.074287f, 0.084650f, 0.095464f, 0.106709f, 0.118367f, 0.130423f, 0.142862f, 0.155674f, + 0.168849f, 0.182378f, 0.196255f, 0.210473f, 0.225027f, 0.239915f, 0.255132f, 0.270678f, + 0.286551f, 0.302751f, 0.319280f, 0.336138f, 0.353330f, 0.370858f, 0.388728f, 0.406944f, + 0.425515f, 0.444449f, 0.463756f, 0.483447f, 0.503535f, 0.524036f, 0.544968f, 0.566350f, + 0.588208f, 0.610569f, 0.633466f, 0.656936f, 0.681025f, 0.705788f, 0.731289f, 0.757606f, + 0.784834f, 0.813085f, 0.842485f, 0.873130f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000324f, 0.001887f, 0.004735f, 0.008727f, + 0.013724f, 0.019607f, 0.026280f, 0.033666f, 0.041699f, 0.050326f, 0.059504f, 0.069194f, + 0.079365f, 0.089989f, 0.101045f, 0.112512f, 0.124372f, 0.136611f, 0.149216f, 0.162176f, + 0.175482f, 0.189125f, 0.203098f, 0.217396f, 0.232015f, 0.246950f, 0.262200f, 0.277761f, + 0.293634f, 0.309819f, 0.326315f, 0.343126f, 0.360254f, 0.377701f, 0.395474f, 0.413577f, + 0.432018f, 0.450804f, 0.469944f, 0.489451f, 0.509337f, 0.529617f, 0.550307f, 0.571428f, + 0.593003f, 0.615059f, 0.637628f, 0.660746f, 0.684460f, 0.708820f, 0.733893f, 0.759756f, + 0.786505f, 0.814259f, 0.843157f, 0.873340f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000683f, 0.002764f, 0.006148f, 0.010661f, + 0.016155f, 0.022506f, 0.029620f, 0.037417f, 0.045835f, 0.054821f, 0.064333f, 0.074333f, + 0.084792f, 0.095683f, 0.106984f, 0.118675f, 0.130741f, 0.143166f, 0.155939f, 0.169049f, + 0.182487f, 0.196245f, 0.210317f, 0.224697f, 0.239380f, 0.254364f, 0.269646f, 0.285223f, + 0.301096f, 0.317265f, 0.333729f, 0.350491f, 0.367554f, 0.384920f, 0.402594f, 0.420582f, + 0.438891f, 0.457527f, 0.476499f, 0.495820f, 0.515500f, 0.535555f, 0.556000f, 0.576855f, + 0.598143f, 0.619888f, 0.642123f, 0.664883f, 0.688211f, 0.712160f, 0.736792f, 0.762186f, + 0.788439f, 0.815672f, 0.844034f, 0.873699f, 0.904765f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000066f, 0.001228f, 0.003880f, 0.007835f, 0.012895f, + 0.018905f, 0.025742f, 0.033309f, 0.041530f, 0.050342f, 0.059696f, 0.069550f, 0.079868f, + 0.090620f, 0.101783f, 0.113333f, 0.125254f, 0.137529f, 0.150144f, 0.163088f, 0.176351f, + 0.189924f, 0.203799f, 0.217970f, 0.232433f, 0.247182f, 0.262216f, 0.277530f, 0.293124f, + 0.308997f, 0.325149f, 0.341581f, 0.358294f, 0.375290f, 0.392573f, 0.410148f, 0.428019f, + 0.446192f, 0.464676f, 0.483478f, 0.502608f, 0.522079f, 0.541905f, 0.562100f, 0.582684f, + 0.603677f, 0.625106f, 0.646998f, 0.669390f, 0.692324f, 0.715849f, 0.740028f, 0.764937f, + 0.790673f, 0.817358f, 0.845150f, 0.874244f, 0.904828f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000260f, 0.002001f, 0.005278f, 0.009840f, 0.015475f, + 0.022025f, 0.029365f, 0.037402f, 0.046060f, 0.055280f, 0.065013f, 0.075218f, 0.085861f, + 0.096916f, 0.108356f, 0.120163f, 0.132319f, 0.144808f, 0.157618f, 0.170737f, 0.184155f, + 0.197866f, 0.211861f, 0.226134f, 0.240682f, 0.255499f, 0.270583f, 0.285931f, 0.301542f, + 0.317415f, 0.333550f, 0.349948f, 0.366610f, 0.383539f, 0.400738f, 0.418210f, 0.435961f, + 0.453997f, 0.472324f, 0.490951f, 0.509887f, 0.529144f, 0.548735f, 0.568674f, 0.588979f, + 0.609671f, 0.630773f, 0.652314f, 0.674328f, 0.696854f, 0.719942f, 0.743651f, 0.768057f, + 0.793253f, 0.819363f, 0.846547f, 0.875017f, 0.905021f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000642f, 0.003053f, 0.007010f, 0.012219f, 0.018462f, + 0.025577f, 0.033444f, 0.041970f, 0.051082f, 0.060724f, 0.070849f, 0.081417f, 0.092397f, + 0.103763f, 0.115491f, 0.127562f, 0.139960f, 0.152670f, 0.165679f, 0.178979f, 0.192558f, + 0.206410f, 0.220529f, 0.234907f, 0.249542f, 0.264428f, 0.279564f, 0.294947f, 0.310575f, + 0.326448f, 0.342566f, 0.358929f, 0.375540f, 0.392399f, 0.409511f, 0.426878f, 0.444506f, + 0.462400f, 0.480566f, 0.499013f, 0.517749f, 0.536785f, 0.556134f, 0.575809f, 0.595827f, + 0.616207f, 0.636973f, 0.658150f, 0.679772f, 0.701876f, 0.724509f, 0.747730f, 0.771609f, + 0.796240f, 0.821743f, 0.848280f, 0.876069f, 0.905404f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000020f, 0.001278f, 0.004450f, 0.009147f, 0.015050f, 0.021937f, + 0.029649f, 0.038068f, 0.047106f, 0.056694f, 0.066777f, 0.077310f, 0.088257f, 0.099588f, + 0.111277f, 0.123304f, 0.135650f, 0.148299f, 0.161237f, 0.174455f, 0.187941f, 0.201687f, + 0.215687f, 0.229933f, 0.244420f, 0.259145f, 0.274103f, 0.289293f, 0.304711f, 0.320357f, + 0.336230f, 0.352330f, 0.368658f, 0.385214f, 0.402002f, 0.419023f, 0.436282f, 0.453782f, + 0.471529f, 0.489528f, 0.507788f, 0.526317f, 0.545124f, 0.564221f, 0.583621f, 0.603341f, + 0.623397f, 0.643812f, 0.664611f, 0.685824f, 0.707488f, 0.729646f, 0.752354f, 0.775680f, + 0.799715f, 0.824574f, 0.850417f, 0.877466f, 0.906040f, 0.936528f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000183f, 0.002253f, 0.006282f, 0.011786f, 0.018436f, 0.026011f, + 0.034358f, 0.043364f, 0.052944f, 0.063033f, 0.073580f, 0.084544f, 0.095889f, 0.107588f, + 0.119617f, 0.131957f, 0.144591f, 0.157503f, 0.170682f, 0.184117f, 0.197799f, 0.211720f, + 0.225873f, 0.240253f, 0.254854f, 0.269673f, 0.284707f, 0.299953f, 0.315408f, 0.331073f, + 0.346946f, 0.363028f, 0.379318f, 0.395818f, 0.412530f, 0.429457f, 0.446602f, 0.463968f, + 0.481561f, 0.499386f, 0.517450f, 0.535761f, 0.554328f, 0.573162f, 0.592275f, 0.611681f, + 0.631398f, 0.651445f, 0.671845f, 0.692628f, 0.713827f, 0.735484f, 0.757650f, 0.780390f, + 0.803789f, 0.827960f, 0.853056f, 0.879298f, 0.907014f, 0.936691f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000617f, 0.003679f, 0.008674f, 0.015068f, 0.022531f, 0.030851f, + 0.039880f, 0.049515f, 0.059675f, 0.070300f, 0.081343f, 0.092764f, 0.104533f, 0.116624f, + 0.129015f, 0.141687f, 0.154626f, 0.167818f, 0.181252f, 0.194918f, 0.208807f, 0.222913f, + 0.237229f, 0.251750f, 0.266473f, 0.281392f, 0.296505f, 0.311811f, 0.327306f, 0.342991f, + 0.358864f, 0.374925f, 0.391176f, 0.407616f, 0.424249f, 0.441076f, 0.458100f, 0.475324f, + 0.492754f, 0.510394f, 0.528251f, 0.546331f, 0.564644f, 0.583198f, 0.602005f, 0.621078f, + 0.640434f, 0.660089f, 0.680066f, 0.700390f, 0.721094f, 0.742215f, 0.763800f, 0.785912f, + 0.808628f, 0.832055f, 0.856338f, 0.881690f, 0.908441f, 0.937125f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.001477f, 0.005732f, 0.011826f, 0.019212f, 0.027573f, 0.036710f, + 0.046487f, 0.056807f, 0.067598f, 0.078806f, 0.090386f, 0.102304f, 0.114532f, 0.127047f, + 0.139828f, 0.152861f, 0.166130f, 0.179624f, 0.193332f, 0.207247f, 0.221360f, 0.235666f, + 0.250158f, 0.264832f, 0.279684f, 0.294711f, 0.309911f, 0.325280f, 0.340819f, 0.356524f, + 0.372397f, 0.388438f, 0.404645f, 0.421022f, 0.437569f, 0.454287f, 0.471181f, 0.488253f, + 0.505507f, 0.522947f, 0.540580f, 0.558412f, 0.576449f, 0.594701f, 0.613178f, 0.631892f, + 0.650856f, 0.670088f, 0.689606f, 0.709434f, 0.729600f, 0.750138f, 0.771093f, 0.792519f, + 0.814488f, 0.837097f, 0.860481f, 0.884842f, 0.910494f, 0.937985f, 0.968254f, 1.000000f, + 0.000000f, 0.000096f, 0.003012f, 0.008704f, 0.016071f, 0.024590f, 0.033968f, 0.044025f, + 0.054641f, 0.065728f, 0.077225f, 0.089081f, 0.101260f, 0.113731f, 0.126469f, 0.139454f, + 0.152670f, 0.166101f, 0.179736f, 0.193565f, 0.207578f, 0.221769f, 0.236130f, 0.250656f, + 0.265343f, 0.280187f, 0.295183f, 0.310330f, 0.325624f, 0.341065f, 0.356650f, 0.372380f, + 0.388253f, 0.404269f, 0.420430f, 0.436735f, 0.453187f, 0.469786f, 0.486536f, 0.503439f, + 0.520498f, 0.537717f, 0.555102f, 0.572657f, 0.590390f, 0.608307f, 0.626419f, 0.644733f, + 0.663264f, 0.682025f, 0.701032f, 0.720308f, 0.739875f, 0.759764f, 0.780014f, 0.800673f, + 0.821803f, 0.843492f, 0.865860f, 0.889087f, 0.913466f, 0.939520f, 0.968350f, 1.000000f, + 0.000000f, 0.000727f, 0.005696f, 0.013170f, 0.022074f, 0.031940f, 0.042520f, 0.053660f, + 0.065258f, 0.077243f, 0.089562f, 0.102175f, 0.115050f, 0.128164f, 0.141495f, 0.155026f, + 0.168745f, 0.182639f, 0.196699f, 0.210915f, 0.225282f, 0.239792f, 0.254440f, 0.269223f, + 0.284135f, 0.299174f, 0.314337f, 0.329622f, 0.345026f, 0.360549f, 0.376189f, 0.391946f, + 0.407819f, 0.423808f, 0.439914f, 0.456137f, 0.472479f, 0.488940f, 0.505523f, 0.522230f, + 0.539064f, 0.556028f, 0.573125f, 0.590361f, 0.607741f, 0.625270f, 0.642957f, 0.660809f, + 0.678836f, 0.697050f, 0.715465f, 0.734098f, 0.752968f, 0.772101f, 0.791529f, 0.811290f, + 0.831438f, 0.852044f, 0.873210f, 0.895090f, 0.917932f, 0.942204f, 0.968981f, 1.000000f, + 0.000000f, 0.002796f, 0.010764f, 0.020645f, 0.031576f, 0.043202f, 0.055340f, 0.067877f, + 0.080740f, 0.093877f, 0.107250f, 0.120832f, 0.134598f, 0.148533f, 0.162620f, 0.176849f, + 0.191210f, 0.205694f, 0.220294f, 0.235005f, 0.249820f, 0.264737f, 0.279751f, 0.294859f, + 0.310058f, 0.325346f, 0.340721f, 0.356181f, 0.371725f, 0.387353f, 0.403063f, 0.418854f, + 0.434727f, 0.450682f, 0.466718f, 0.482837f, 0.499038f, 0.515324f, 0.531695f, 0.548153f, + 0.564700f, 0.581338f, 0.598070f, 0.614900f, 0.631830f, 0.648865f, 0.666011f, 0.683273f, + 0.700659f, 0.718176f, 0.735834f, 0.753646f, 0.771625f, 0.789790f, 0.808162f, 0.826771f, + 0.845654f, 0.864863f, 0.884472f, 0.904592f, 0.925407f, 0.947271f, 0.971050f, 1.000000f, + 0.000000f, 0.015873f, 0.031746f, 0.047619f, 0.063492f, 0.079365f, 0.095238f, 0.111111f, + 0.126984f, 0.142857f, 0.158730f, 0.174603f, 0.190476f, 0.206349f, 0.222222f, 0.238095f, + 0.253968f, 0.269841f, 0.285714f, 0.301587f, 0.317460f, 0.333333f, 0.349206f, 0.365079f, + 0.380952f, 0.396825f, 0.412698f, 0.428571f, 0.444444f, 0.460317f, 0.476190f, 0.492063f, + 0.507937f, 0.523810f, 0.539683f, 0.555556f, 0.571429f, 0.587302f, 0.603175f, 0.619048f, + 0.634921f, 0.650794f, 0.666667f, 0.682540f, 0.698413f, 0.714286f, 0.730159f, 0.746032f, + 0.761905f, 0.777778f, 0.793651f, 0.809524f, 0.825397f, 0.841270f, 0.857143f, 0.873016f, + 0.888889f, 0.904762f, 0.920635f, 0.936508f, 0.952381f, 0.968254f, 0.984127f, 1.000000f +}; + +static float btdf_split_sum_ggx[32][64 * 64] = { + { + 0.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, + 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.039917f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, + 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.999512f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, + }, + { + 0.000122f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.004147f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.897949f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000732f, 0.996094f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.002439f, + 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000366f, 0.078308f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.001098f, 0.992188f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.999512f, + 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.005001f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, + 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.902344f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.002928f, 0.997070f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 1.000000f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.301758f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.002562f, 0.996094f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.433594f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000244f, 0.004021f, 0.996582f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.001098f, 0.949219f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000610f, + 0.012039f, 0.998047f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.002073f, 0.993652f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000854f, 0.725586f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000610f, 0.011856f, 0.998047f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.002905f, 0.995117f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.001098f, 0.978027f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.314941f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000731f, 0.017670f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.005852f, 0.997559f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.003050f, + 0.996094f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.001957f, 0.993652f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.001586f, 0.990234f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.001220f, 0.986816f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.001220f, 0.984375f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, + 0.001098f, 0.985352f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.001220f, 0.989258f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.001341f, 0.993652f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.001586f, 0.996094f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.002802f, 0.997559f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000117f, 0.000122f, 0.000122f, + 0.000243f, 0.006088f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.026321f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000732f, 0.892578f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000975f, 0.993652f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.002317f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.017944f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000731f, 0.983887f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f, 0.000122f, 0.001653f, 0.998535f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.026108f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000732f, 0.995605f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.003777f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000365f, 0.991211f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.002195f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000364f, 0.993164f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.002672f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000360f, 0.998047f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.017075f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000731f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.997070f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.006874f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000480f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.996582f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000067f, 0.005440f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000365f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.995605f, 0.995117f, + 0.995117f, 0.995605f, 0.995117f, 0.995117f, + }, + { + 0.003168f, 0.995605f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000976f, 0.053314f, 0.994629f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000122f, 0.000122f, 0.000732f, 0.003660f, + 0.653809f, 0.995117f, 0.998047f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000488f, 0.001463f, 0.010452f, 0.947266f, 0.995605f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000853f, 0.002928f, 0.037750f, + 0.980957f, 0.996582f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000243f, 0.000610f, 0.001342f, 0.006100f, 0.314453f, 0.989746f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f, 0.001091f, 0.002317f, 0.015839f, 0.910645f, + 0.993652f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000366f, 0.000732f, 0.001463f, 0.005302f, 0.068909f, 0.977539f, 0.995605f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000732f, 0.001098f, 0.002560f, 0.011551f, 0.658691f, 0.989746f, + 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, + 0.000732f, 0.001585f, 0.004868f, 0.041077f, 0.958984f, 0.994141f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000732f, 0.001215f, 0.002802f, 0.010834f, 0.441895f, 0.987305f, 0.996094f, + 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000242f, 0.000488f, 0.000850f, + 0.001586f, 0.004753f, 0.039154f, 0.948242f, 0.993652f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.000732f, 0.001220f, 0.003159f, 0.012032f, 0.480713f, 0.985840f, 0.996094f, 0.998047f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000731f, 0.001097f, 0.001950f, + 0.005966f, 0.054413f, 0.957520f, 0.994141f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000486f, 0.000732f, 0.001534f, 0.003536f, 0.016937f, 0.726562f, 0.988281f, 0.996582f, 0.998047f, 0.999023f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000732f, 0.001098f, 0.002192f, 0.008278f, + 0.125244f, 0.974121f, 0.994629f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000365f, 0.000731f, 0.000947f, 0.001828f, 0.005314f, 0.031677f, 0.916016f, 0.991699f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000488f, 0.000732f, 0.001339f, 0.003294f, 0.014389f, 0.562012f, + 0.985840f, 0.996094f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f, + 0.000732f, 0.001098f, 0.002310f, 0.008163f, 0.123779f, 0.973633f, 0.994629f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000732f, 0.001097f, 0.002071f, 0.005669f, 0.041199f, 0.937988f, 0.992676f, + 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000118f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.000728f, 0.000732f, + 0.001585f, 0.004143f, 0.020813f, 0.813965f, 0.989746f, 0.996582f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000116f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000488f, 0.000732f, 0.001220f, 0.003292f, 0.012581f, 0.446533f, 0.984863f, 0.996094f, 0.998047f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000471f, 0.000732f, 0.001220f, 0.002796f, + 0.009338f, 0.161865f, 0.977051f, 0.995117f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000365f, 0.000732f, 0.001098f, 0.002285f, 0.006870f, 0.074097f, 0.965820f, 0.994141f, 0.997559f, 0.998535f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, 0.000731f, 0.001086f, 0.001945f, 0.005238f, 0.043732f, + 0.947754f, 0.993652f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000366f, + 0.000730f, 0.000893f, 0.001826f, 0.004871f, 0.030411f, 0.922852f, 0.992188f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000609f, 0.000732f, 0.001407f, 0.004375f, 0.023758f, 0.892090f, 0.992188f, + 0.997070f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000605f, 0.000732f, + 0.001579f, 0.003941f, 0.020767f, 0.862793f, 0.991699f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000238f, 0.000483f, 0.000732f, 0.001449f, 0.003654f, 0.018951f, 0.847656f, 0.991699f, 0.997559f, 0.998535f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000233f, 0.000485f, 0.000732f, 0.001308f, 0.003353f, + 0.018997f, 0.855469f, 0.991699f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000118f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000487f, 0.000732f, 0.001292f, 0.003649f, 0.019791f, 0.881836f, 0.992188f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000432f, 0.000732f, 0.001220f, 0.003635f, 0.021912f, 0.916992f, + 0.993652f, 0.997559f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000116f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f, + 0.000732f, 0.001245f, 0.004002f, 0.028107f, 0.946289f, 0.994141f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000085f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000475f, 0.000732f, 0.001611f, 0.004581f, 0.040466f, 0.966309f, 0.995605f, 0.998535f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f, 0.000732f, 0.001703f, + 0.005589f, 0.073486f, 0.979980f, 0.996094f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000475f, 0.000732f, 0.001706f, 0.006809f, 0.198730f, 0.987305f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000488f, 0.000732f, 0.002071f, 0.009590f, 0.647949f, + 0.992188f, 0.997559f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000710f, 0.001093f, 0.002541f, 0.015533f, 0.922852f, 0.995117f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000116f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000242f, 0.000728f, 0.001218f, 0.003387f, 0.034454f, 0.975586f, 0.996582f, 0.998535f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000731f, 0.001219f, + 0.004959f, 0.161865f, 0.989746f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000366f, 0.000731f, 0.001767f, 0.009331f, 0.849121f, 0.994629f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000487f, 0.000732f, 0.002644f, 0.024231f, 0.977051f, + 0.997559f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000685f, 0.001217f, 0.004139f, 0.195435f, 0.992676f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000362f, 0.000731f, 0.001570f, 0.010086f, 0.944824f, 0.997070f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000365f, 0.000745f, 0.002781f, + 0.051758f, 0.990723f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000599f, 0.001176f, 0.006641f, 0.899414f, 0.997070f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000731f, 0.002066f, 0.032654f, 0.991211f, 0.998535f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000448f, + 0.001088f, 0.005440f, 0.918457f, 0.997070f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000725f, 0.001822f, 0.038452f, 0.994141f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000329f, 0.000848f, 0.005672f, 0.972168f, + 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000581f, 0.001982f, 0.155273f, 0.997070f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000330f, 0.000848f, 0.009247f, 0.992676f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000589f, 0.002625f, + 0.958496f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.001199f, 0.083374f, 0.998047f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000716f, 0.007244f, 0.996582f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, + 0.002277f, 0.991211f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000070f, 0.000121f, 0.000122f, 0.000122f, 0.000854f, 0.950684f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000111f, 0.000121f, 0.000122f, 0.000475f, 0.067139f, 0.999512f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000118f, 0.000122f, + 0.000002f, 0.005859f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000014f, 0.001376f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000572f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000077f, 0.000002f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000103f, 0.992188f, 0.991699f, 0.991699f, 0.992188f, 0.992188f, 0.991699f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.940430f, 0.940430f, + 0.940918f, 0.940918f, 0.940430f, 0.940430f, + }, + { + 0.014023f, 0.979492f, 0.994629f, 0.997070f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000488f, 0.004757f, 0.163330f, 0.975098f, 0.993164f, 0.996582f, 0.997559f, 0.998535f, + 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000610f, 0.002928f, 0.017166f, + 0.563965f, 0.978027f, 0.992676f, 0.996094f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000364f, 0.000732f, 0.002192f, 0.006573f, 0.044952f, 0.830566f, 0.980957f, 0.992676f, 0.996094f, 0.997070f, 0.998047f, + 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 1.000000f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000366f, 0.000854f, 0.001586f, 0.004253f, 0.014313f, 0.130371f, + 0.919922f, 0.984375f, 0.993652f, 0.996094f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000488f, + 0.000854f, 0.001342f, 0.003025f, 0.007305f, 0.028870f, 0.407715f, 0.954590f, 0.987305f, 0.993652f, 0.996094f, 0.997070f, 0.998047f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000609f, 0.000842f, 0.000976f, 0.002193f, 0.005112f, 0.012505f, 0.066589f, 0.768066f, + 0.970703f, 0.989746f, 0.994629f, 0.996582f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000244f, 0.000599f, 0.000609f, 0.000976f, + 0.001829f, 0.003046f, 0.007256f, 0.023499f, 0.194946f, 0.908691f, 0.979980f, 0.991699f, 0.995117f, 0.996582f, 0.997559f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000244f, 0.000488f, 0.000609f, 0.000976f, 0.001583f, 0.002647f, 0.004726f, 0.012169f, 0.050537f, 0.568359f, 0.954102f, + 0.985840f, 0.993164f, 0.995605f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000488f, 0.000610f, 0.000975f, 0.001211f, 0.001946f, + 0.003532f, 0.007793f, 0.022446f, 0.139648f, 0.856445f, 0.974121f, 0.989746f, 0.994141f, 0.996094f, 0.997559f, 0.998047f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000241f, + 0.000310f, 0.000609f, 0.000807f, 0.001098f, 0.001822f, 0.002794f, 0.005699f, 0.012878f, 0.047821f, 0.469238f, 0.941406f, 0.982910f, + 0.991699f, 0.995117f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000244f, 0.000609f, 0.000732f, 0.001098f, 0.001461f, 0.002274f, 0.004025f, + 0.008247f, 0.023254f, 0.135254f, 0.833984f, 0.969727f, 0.987793f, 0.993652f, 0.995605f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000207f, 0.000244f, 0.000609f, + 0.000610f, 0.001096f, 0.001098f, 0.002071f, 0.003370f, 0.006172f, 0.014442f, 0.052795f, 0.486572f, 0.940430f, 0.981934f, 0.991699f, + 0.994629f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000485f, 0.000610f, 0.001080f, 0.001098f, 0.001742f, 0.002668f, 0.004692f, 0.010147f, + 0.028076f, 0.168701f, 0.854004f, 0.970703f, 0.988770f, 0.993652f, 0.996094f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000487f, 0.000610f, 0.000731f, + 0.001098f, 0.001413f, 0.002411f, 0.003895f, 0.007072f, 0.017242f, 0.069580f, 0.605957f, 0.948730f, 0.983398f, 0.992188f, 0.995117f, + 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000244f, 0.000244f, 0.000609f, 0.000610f, 0.001094f, 0.001337f, 0.001828f, 0.003275f, 0.005814f, 0.012054f, 0.036987f, + 0.270752f, 0.899414f, 0.975586f, 0.989746f, 0.993652f, 0.996094f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000241f, 0.000365f, 0.000597f, 0.000610f, 0.000970f, 0.001098f, + 0.001815f, 0.002771f, 0.005009f, 0.008888f, 0.023804f, 0.115845f, 0.775879f, 0.962891f, 0.986328f, 0.993164f, 0.995605f, 0.997070f, + 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000244f, 0.000536f, 0.000731f, 0.000937f, 0.001203f, 0.001581f, 0.002186f, 0.004005f, 0.007061f, 0.016830f, 0.061218f, 0.522949f, + 0.940430f, 0.981934f, 0.991211f, 0.994629f, 0.996582f, 0.997559f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000363f, 0.000487f, 0.000731f, 0.000732f, 0.001097f, 0.001339f, 0.002071f, + 0.003498f, 0.005947f, 0.012390f, 0.037964f, 0.268799f, 0.896973f, 0.975586f, 0.989258f, 0.994141f, 0.996094f, 0.997070f, 0.998047f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000366f, + 0.000609f, 0.000610f, 0.001094f, 0.001215f, 0.002056f, 0.003183f, 0.004742f, 0.009880f, 0.026337f, 0.139526f, 0.813477f, 0.966309f, + 0.986816f, 0.993164f, 0.996094f, 0.997070f, 0.997559f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000163f, 0.000363f, 0.000600f, 0.000731f, 0.001088f, 0.001216f, 0.001616f, 0.002640f, 0.004402f, + 0.008156f, 0.019669f, 0.083191f, 0.664062f, 0.953125f, 0.984375f, 0.992188f, 0.995117f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, + 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000244f, 0.000523f, 0.000731f, + 0.000732f, 0.001097f, 0.001690f, 0.002169f, 0.003998f, 0.006939f, 0.015808f, 0.055634f, 0.471191f, 0.935059f, 0.980957f, 0.991211f, + 0.995117f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000336f, 0.000486f, 0.000731f, 0.000732f, 0.001097f, 0.001558f, 0.002069f, 0.003525f, 0.006058f, 0.013062f, + 0.040894f, 0.306396f, 0.910156f, 0.978027f, 0.990234f, 0.994141f, 0.996582f, 0.997559f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000113f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000360f, 0.000515f, 0.000731f, 0.000731f, 0.001094f, + 0.001219f, 0.002148f, 0.003159f, 0.005577f, 0.011360f, 0.031952f, 0.203979f, 0.874512f, 0.973633f, 0.989258f, 0.994141f, 0.996582f, + 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000325f, 0.000366f, 0.000731f, 0.000731f, 0.001093f, 0.001219f, 0.001820f, 0.002916f, 0.005291f, 0.009758f, 0.026352f, 0.145020f, + 0.832520f, 0.969238f, 0.988281f, 0.993652f, 0.996094f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, 0.000440f, 0.000605f, 0.000731f, 0.001086f, 0.001097f, 0.001646f, + 0.002670f, 0.004230f, 0.008835f, 0.022415f, 0.112183f, 0.786133f, 0.966309f, 0.987793f, 0.993652f, 0.996094f, 0.997559f, 0.998047f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000272f, 0.000358f, + 0.000565f, 0.000731f, 0.000790f, 0.001210f, 0.001573f, 0.002434f, 0.004360f, 0.008102f, 0.020660f, 0.092896f, 0.741699f, 0.962891f, + 0.987305f, 0.993164f, 0.996094f, 0.997070f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000364f, 0.000723f, 0.000731f, 0.000731f, 0.001216f, 0.001698f, 0.002510f, 0.003998f, + 0.007484f, 0.018463f, 0.082336f, 0.709961f, 0.961426f, 0.986816f, 0.993652f, 0.996094f, 0.997559f, 0.998535f, 0.998535f, 0.999023f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000242f, 0.000362f, 0.000704f, 0.000730f, + 0.000845f, 0.001096f, 0.001513f, 0.002302f, 0.003941f, 0.007168f, 0.017746f, 0.076782f, 0.693848f, 0.961426f, 0.987305f, 0.993652f, + 0.996094f, 0.997559f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000364f, 0.000579f, 0.000728f, 0.000731f, 0.001096f, 0.001491f, 0.002069f, 0.003899f, 0.007195f, 0.017059f, + 0.075439f, 0.701172f, 0.962402f, 0.987793f, 0.993652f, 0.996094f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000357f, 0.000482f, 0.000730f, 0.000731f, 0.001094f, + 0.001334f, 0.002230f, 0.003708f, 0.007217f, 0.017410f, 0.079163f, 0.730469f, 0.965820f, 0.988281f, 0.994141f, 0.996582f, 0.998047f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000112f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000238f, + 0.000243f, 0.000365f, 0.000729f, 0.000731f, 0.001095f, 0.001330f, 0.002066f, 0.003637f, 0.007118f, 0.018112f, 0.087708f, 0.775391f, + 0.969238f, 0.989258f, 0.994629f, 0.997070f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000073f, 0.000121f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000323f, 0.000390f, 0.000729f, 0.000731f, 0.001094f, 0.001332f, 0.002275f, + 0.003782f, 0.007252f, 0.019379f, 0.105042f, 0.827637f, 0.973145f, 0.990723f, 0.994629f, 0.997070f, 0.998047f, 0.998535f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000114f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000369f, + 0.000729f, 0.000731f, 0.001093f, 0.001330f, 0.002209f, 0.003937f, 0.007896f, 0.021805f, 0.137207f, 0.876953f, 0.979004f, 0.991699f, + 0.995605f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000272f, 0.000479f, 0.000727f, 0.000731f, 0.001085f, 0.001331f, 0.002291f, 0.004105f, 0.008446f, + 0.025024f, 0.202271f, 0.916504f, 0.982910f, 0.993164f, 0.996094f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000120f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000360f, 0.000469f, 0.000681f, 0.000731f, + 0.001092f, 0.001331f, 0.002184f, 0.004227f, 0.009521f, 0.030899f, 0.335205f, 0.945312f, 0.986816f, 0.993652f, 0.996582f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000116f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000241f, 0.000429f, 0.000726f, 0.000731f, 0.001091f, 0.001649f, 0.002464f, 0.004810f, 0.010895f, 0.041931f, 0.563477f, + 0.963867f, 0.989746f, 0.995117f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000101f, 0.000120f, + 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000288f, 0.000481f, 0.000720f, 0.000731f, 0.001093f, 0.001571f, + 0.002735f, 0.005405f, 0.013199f, 0.064880f, 0.786133f, 0.976562f, 0.992188f, 0.995605f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000112f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f, + 0.000481f, 0.000727f, 0.000731f, 0.001093f, 0.001655f, 0.003132f, 0.005909f, 0.017181f, 0.123169f, 0.904297f, 0.984375f, 0.993652f, + 0.996582f, 0.998047f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000110f, 0.000120f, 0.000121f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000264f, 0.000392f, 0.000727f, 0.000835f, 0.001196f, 0.001765f, 0.003252f, 0.007343f, + 0.024521f, 0.304199f, 0.954102f, 0.989258f, 0.995605f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000034f, 0.000119f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000235f, 0.000375f, 0.000728f, + 0.000822f, 0.001095f, 0.002024f, 0.003952f, 0.009193f, 0.040894f, 0.694824f, 0.975586f, 0.992676f, 0.996582f, 0.998047f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000112f, 0.000121f, 0.000121f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000307f, 0.000475f, 0.000728f, 0.000943f, 0.001216f, 0.002283f, 0.004829f, 0.013008f, 0.092224f, 0.908203f, + 0.986328f, 0.995117f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000073f, 0.000118f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000576f, 0.000728f, 0.001073f, 0.001569f, + 0.002668f, 0.005947f, 0.020889f, 0.331543f, 0.965820f, 0.992188f, 0.996582f, 0.998047f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000100f, 0.000120f, 0.000121f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000362f, 0.000630f, 0.000729f, 0.001087f, 0.001567f, 0.003241f, 0.008240f, 0.043793f, 0.824219f, 0.984375f, 0.994629f, 0.997559f, + 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000075f, 0.000119f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000363f, 0.000689f, 0.000730f, 0.001185f, 0.002022f, 0.004108f, 0.013702f, + 0.161011f, 0.957031f, 0.991699f, 0.996582f, 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000105f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000156f, 0.000372f, 0.000689f, + 0.000730f, 0.001198f, 0.002651f, 0.006214f, 0.028854f, 0.750000f, 0.984375f, 0.995605f, 0.998047f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000102f, + 0.000118f, 0.000120f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000472f, 0.000724f, 0.000966f, 0.001658f, 0.003397f, 0.010582f, 0.116028f, 0.959473f, 0.993164f, + 0.997559f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000111f, 0.000119f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000130f, 0.000479f, 0.000726f, 0.001163f, 0.002157f, + 0.004829f, 0.024338f, 0.776855f, 0.987793f, 0.996582f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000097f, 0.000117f, + 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000219f, 0.000580f, 0.000728f, 0.001203f, 0.002872f, 0.009109f, 0.130371f, 0.972168f, 0.995117f, 0.998047f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000112f, 0.000118f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000333f, 0.000681f, 0.000940f, 0.001629f, 0.004120f, 0.025467f, 0.890625f, + 0.991699f, 0.997559f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000083f, 0.000116f, 0.000120f, + 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000353f, 0.000722f, + 0.000961f, 0.002403f, 0.009354f, 0.295166f, 0.985840f, 0.997070f, 0.999512f, 0.999023f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000105f, 0.000118f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000130f, 0.000427f, 0.000605f, 0.001345f, 0.004620f, 0.041229f, 0.966797f, 0.996094f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000074f, 0.000114f, 0.000119f, 0.000121f, + 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000089f, 0.000562f, 0.000942f, 0.002352f, 0.012459f, + 0.854004f, 0.994141f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000103f, 0.000117f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000007f, 0.000002f, + 0.000231f, 0.000596f, 0.001180f, 0.005474f, 0.211426f, 0.991211f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000111f, 0.000118f, 0.000120f, 0.000121f, + 0.000121f, 0.000122f, 0.000029f, 0.000004f, 0.000001f, 0.000348f, 0.000896f, 0.002764f, 0.032562f, 0.984375f, 0.998535f, 0.998535f, + 0.999023f, 0.998535f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000089f, 0.000116f, 0.000119f, 0.000121f, 0.000121f, 0.000121f, 0.000013f, 0.000003f, 0.000075f, 0.000586f, 0.001508f, + 0.010292f, 0.963379f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000107f, 0.000118f, 0.000120f, 0.000121f, 0.000116f, + 0.000008f, 0.000002f, 0.000233f, 0.000857f, 0.004566f, 0.834961f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000083f, 0.000114f, 0.000119f, 0.000120f, 0.000060f, 0.000005f, 0.000001f, 0.000557f, 0.002064f, 0.182373f, 0.997559f, 0.997559f, + 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000103f, 0.000117f, 0.000120f, 0.000024f, 0.000003f, 0.000168f, + 0.000968f, 0.026428f, 0.996582f, 0.997070f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000047f, + 0.000110f, 0.000118f, 0.000017f, 0.000002f, 0.000513f, 0.006870f, 0.995605f, 0.995605f, 0.995117f, 0.995117f, 0.995117f, 0.995117f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000096f, 0.000115f, 0.000011f, 0.000042f, 0.001919f, 0.992676f, 0.992676f, + 0.992676f, 0.992676f, 0.992676f, 0.992676f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000044f, 0.000109f, + 0.000008f, 0.000314f, 0.985840f, 0.985840f, 0.985840f, 0.985840f, 0.986328f, 0.985840f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000089f, 0.000060f, 0.964355f, 0.964355f, 0.963867f, 0.963867f, 0.963379f, 0.964355f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000022f, 0.818848f, 0.819824f, + 0.819336f, 0.819824f, 0.819824f, 0.819824f, + }, + { + 0.038849f, 0.941406f, 0.984375f, 0.992188f, 0.994141f, 0.996094f, 0.996582f, 0.997070f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 1.000000f, 1.000000f, 1.000000f, 0.999512f, 0.001582f, 0.014984f, 0.262451f, 0.930664f, 0.979980f, 0.989258f, 0.993164f, 0.995117f, + 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, 0.000244f, 0.002317f, 0.009003f, 0.047180f, + 0.524902f, 0.936523f, 0.978027f, 0.988281f, 0.992188f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, + 0.000122f, 0.001098f, 0.002560f, 0.006824f, 0.020493f, 0.108826f, 0.715820f, 0.946289f, 0.978516f, 0.988281f, 0.992188f, 0.994141f, + 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000607f, 0.001098f, 0.002310f, 0.005646f, 0.012825f, 0.040131f, 0.231201f, + 0.825195f, 0.954590f, 0.979980f, 0.988281f, 0.992188f, 0.994141f, 0.995117f, 0.996582f, 0.996582f, 0.997559f, 0.998047f, 0.998047f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000244f, 0.000609f, 0.001341f, + 0.002310f, 0.004208f, 0.008865f, 0.021591f, 0.074585f, 0.439209f, 0.885742f, 0.962402f, 0.981934f, 0.989258f, 0.992676f, 0.994141f, + 0.995605f, 0.996582f, 0.997070f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.999512f, + 0.000000f, 0.000122f, 0.000483f, 0.000610f, 0.001460f, 0.002192f, 0.003994f, 0.007030f, 0.013847f, 0.036316f, 0.146362f, 0.661621f, + 0.921875f, 0.969238f, 0.983398f, 0.989746f, 0.993164f, 0.994141f, 0.995605f, 0.996582f, 0.996582f, 0.997559f, 0.998047f, 0.998047f, + 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000243f, 0.000604f, 0.000730f, 0.001307f, 0.001944f, 0.003017f, + 0.004997f, 0.009834f, 0.021606f, 0.063416f, 0.295410f, 0.808594f, 0.944336f, 0.974609f, 0.985352f, 0.990234f, 0.993652f, 0.995117f, + 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 1.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000366f, + 0.000495f, 0.000731f, 0.001217f, 0.001823f, 0.002796f, 0.004398f, 0.007656f, 0.015366f, 0.035828f, 0.119263f, 0.531738f, 0.886230f, + 0.958496f, 0.979004f, 0.986816f, 0.991699f, 0.993652f, 0.995117f, 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000244f, 0.000366f, 0.000607f, 0.000731f, 0.001211f, 0.001650f, 0.002441f, 0.003975f, 0.006207f, + 0.011536f, 0.023315f, 0.060822f, 0.242798f, 0.744141f, 0.927734f, 0.969238f, 0.982422f, 0.989258f, 0.992188f, 0.994141f, 0.995605f, + 0.996094f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000211f, 0.000455f, 0.000486f, 0.000853f, + 0.001081f, 0.001810f, 0.002426f, 0.003759f, 0.005501f, 0.009094f, 0.016876f, 0.037109f, 0.114075f, 0.475586f, 0.862305f, 0.951172f, + 0.975586f, 0.985840f, 0.990234f, 0.992676f, 0.995117f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000364f, 0.000366f, 0.000464f, 0.000731f, 0.001093f, 0.001577f, 0.002235f, 0.002798f, 0.004841f, 0.007637f, 0.013008f, + 0.025635f, 0.063965f, 0.238403f, 0.720215f, 0.919434f, 0.965820f, 0.981445f, 0.987793f, 0.991211f, 0.993652f, 0.995117f, 0.996094f, + 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000238f, 0.000609f, 0.000712f, 0.000974f, 0.000976f, 0.001507f, + 0.002031f, 0.002680f, 0.004066f, 0.006294f, 0.010284f, 0.018326f, 0.040924f, 0.124146f, 0.485596f, 0.859375f, 0.949707f, 0.975586f, + 0.984375f, 0.989746f, 0.992676f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000113f, 0.000487f, + 0.000488f, 0.000610f, 0.000961f, 0.000976f, 0.001337f, 0.001705f, 0.002663f, 0.003521f, 0.005417f, 0.008408f, 0.014809f, 0.028793f, + 0.073120f, 0.270996f, 0.741699f, 0.922363f, 0.965332f, 0.980957f, 0.987793f, 0.991699f, 0.993652f, 0.995117f, 0.996094f, 0.997070f, + 0.997070f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000244f, 0.000224f, 0.000486f, 0.000609f, 0.000610f, 0.000973f, 0.000975f, 0.001306f, 0.001703f, 0.002350f, + 0.003239f, 0.004848f, 0.007122f, 0.011955f, 0.021820f, 0.048859f, 0.152710f, 0.554199f, 0.875977f, 0.953125f, 0.976562f, 0.985352f, + 0.990234f, 0.993164f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000234f, 0.000244f, 0.000485f, 0.000488f, 0.000610f, + 0.000969f, 0.000975f, 0.001335f, 0.001693f, 0.001991f, 0.002811f, 0.004097f, 0.006397f, 0.009903f, 0.017303f, 0.035034f, 0.094421f, + 0.354736f, 0.795898f, 0.933594f, 0.969238f, 0.981934f, 0.988281f, 0.991699f, 0.993652f, 0.995117f, 0.996094f, 0.997070f, 0.997559f, + 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000244f, 0.000244f, 0.000480f, 0.000608f, 0.000488f, 0.000922f, 0.000975f, 0.000976f, 0.001339f, 0.001827f, 0.002674f, 0.003891f, + 0.005688f, 0.008324f, 0.014320f, 0.026917f, 0.064392f, 0.216431f, 0.668945f, 0.904785f, 0.959961f, 0.978516f, 0.986816f, 0.990723f, + 0.993652f, 0.994141f, 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 1.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000188f, 0.000220f, 0.000480f, 0.000608f, 0.000609f, 0.000876f, 0.000975f, + 0.000976f, 0.001454f, 0.002068f, 0.002649f, 0.003481f, 0.004757f, 0.007801f, 0.012230f, 0.021698f, 0.046814f, 0.138306f, 0.506348f, + 0.859375f, 0.947754f, 0.974121f, 0.984375f, 0.989746f, 0.992188f, 0.994141f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, + 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000244f, + 0.000446f, 0.000487f, 0.000609f, 0.000731f, 0.000973f, 0.000975f, 0.001310f, 0.001823f, 0.002304f, 0.002869f, 0.004890f, 0.006813f, + 0.010475f, 0.017731f, 0.036163f, 0.095337f, 0.353516f, 0.792480f, 0.932129f, 0.968262f, 0.982422f, 0.988770f, 0.992188f, 0.993652f, + 0.995605f, 0.996094f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000241f, 0.000362f, 0.000487f, 0.000609f, 0.000609f, 0.000973f, 0.001213f, 0.001419f, + 0.001807f, 0.002068f, 0.002794f, 0.004070f, 0.005917f, 0.009140f, 0.015129f, 0.029053f, 0.070068f, 0.242554f, 0.700684f, 0.911621f, + 0.961914f, 0.979492f, 0.987305f, 0.991211f, 0.993164f, 0.995117f, 0.995605f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000243f, 0.000483f, 0.000603f, + 0.000609f, 0.000730f, 0.001076f, 0.000975f, 0.001327f, 0.001598f, 0.002056f, 0.002848f, 0.003519f, 0.005589f, 0.008041f, 0.013321f, + 0.024155f, 0.054718f, 0.171875f, 0.590332f, 0.885742f, 0.955566f, 0.977051f, 0.985840f, 0.990723f, 0.993164f, 0.994629f, 0.995605f, + 0.997070f, 0.997070f, 0.997559f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000192f, 0.000122f, 0.000244f, 0.000483f, 0.000606f, 0.000608f, 0.000731f, 0.000953f, 0.001095f, 0.001258f, 0.001575f, 0.002066f, + 0.002594f, 0.003857f, 0.004734f, 0.007683f, 0.011642f, 0.021179f, 0.044464f, 0.127930f, 0.476807f, 0.850586f, 0.947266f, 0.974121f, + 0.984375f, 0.989746f, 0.992676f, 0.994141f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000229f, 0.000239f, 0.000244f, 0.000343f, 0.000483f, 0.000608f, 0.000609f, + 0.000857f, 0.000973f, 0.001097f, 0.001571f, 0.002041f, 0.002399f, 0.002922f, 0.004471f, 0.006836f, 0.010643f, 0.018661f, 0.037354f, + 0.100037f, 0.378418f, 0.810547f, 0.937988f, 0.971191f, 0.983887f, 0.989258f, 0.992188f, 0.994141f, 0.995605f, 0.996582f, 0.997070f, + 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000161f, + 0.000230f, 0.000244f, 0.000486f, 0.000607f, 0.000609f, 0.000819f, 0.000972f, 0.000975f, 0.001431f, 0.001945f, 0.002283f, 0.003031f, + 0.004238f, 0.006424f, 0.009995f, 0.016068f, 0.032104f, 0.081360f, 0.302246f, 0.765625f, 0.928223f, 0.968750f, 0.982422f, 0.988770f, + 0.992676f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000240f, 0.000244f, 0.000450f, 0.000607f, 0.000609f, 0.000731f, 0.001084f, + 0.000974f, 0.001341f, 0.001910f, 0.002254f, 0.003216f, 0.004017f, 0.005692f, 0.008980f, 0.014832f, 0.028854f, 0.069641f, 0.248657f, + 0.719238f, 0.918945f, 0.965820f, 0.981445f, 0.988770f, 0.992188f, 0.994629f, 0.995605f, 0.996094f, 0.997070f, 0.997559f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000360f, + 0.000461f, 0.000607f, 0.000608f, 0.000731f, 0.001086f, 0.001202f, 0.001307f, 0.001592f, 0.002066f, 0.003134f, 0.003990f, 0.005611f, + 0.008133f, 0.013680f, 0.025986f, 0.061462f, 0.211670f, 0.676758f, 0.910156f, 0.963867f, 0.980957f, 0.988281f, 0.991699f, 0.994629f, + 0.995605f, 0.996582f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000240f, 0.000243f, 0.000482f, 0.000604f, 0.000608f, 0.000730f, 0.001040f, 0.001188f, 0.001287f, + 0.001574f, 0.002064f, 0.002613f, 0.003721f, 0.005428f, 0.008018f, 0.013161f, 0.024200f, 0.055573f, 0.186401f, 0.642578f, 0.904785f, + 0.962402f, 0.980469f, 0.987793f, 0.991699f, 0.994141f, 0.995605f, 0.996582f, 0.997070f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, + 0.999023f, 0.999023f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000480f, 0.000602f, + 0.000721f, 0.000705f, 0.000907f, 0.001094f, 0.001096f, 0.001493f, 0.002058f, 0.002607f, 0.003639f, 0.004826f, 0.007595f, 0.012413f, + 0.022171f, 0.051697f, 0.171143f, 0.619629f, 0.899414f, 0.961426f, 0.980957f, 0.987793f, 0.992188f, 0.994629f, 0.995605f, 0.996582f, + 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000172f, 0.000232f, 0.000243f, 0.000244f, 0.000576f, 0.000711f, 0.000608f, 0.000767f, 0.001089f, 0.001213f, 0.001509f, 0.002029f, + 0.002684f, 0.003550f, 0.005161f, 0.007107f, 0.011871f, 0.021545f, 0.049347f, 0.163086f, 0.609863f, 0.900391f, 0.962891f, 0.980957f, + 0.988281f, 0.992676f, 0.994629f, 0.996094f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000210f, 0.000122f, 0.000337f, 0.000290f, 0.000594f, 0.000726f, 0.000730f, + 0.000731f, 0.001090f, 0.001212f, 0.001506f, 0.002029f, 0.002335f, 0.003489f, 0.005077f, 0.007000f, 0.011398f, 0.021027f, 0.048218f, + 0.161133f, 0.614258f, 0.903809f, 0.963379f, 0.981934f, 0.988770f, 0.992188f, 0.994629f, 0.996094f, 0.997070f, 0.997559f, 0.998047f, + 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000281f, 0.000440f, 0.000683f, 0.000726f, 0.000730f, 0.000731f, 0.001087f, 0.001095f, 0.001485f, 0.001793f, 0.002214f, 0.002991f, + 0.004951f, 0.006912f, 0.011162f, 0.020905f, 0.048187f, 0.165527f, 0.633789f, 0.910156f, 0.965820f, 0.982422f, 0.989746f, 0.993164f, + 0.995117f, 0.996094f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000241f, 0.000243f, 0.000480f, 0.000725f, 0.000697f, 0.000731f, 0.001007f, + 0.001094f, 0.001360f, 0.001795f, 0.002161f, 0.003244f, 0.004871f, 0.006966f, 0.011330f, 0.020706f, 0.049591f, 0.178345f, 0.667969f, + 0.918457f, 0.968262f, 0.983887f, 0.990234f, 0.993652f, 0.995605f, 0.996582f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000086f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000243f, + 0.000465f, 0.000592f, 0.000729f, 0.000730f, 0.001079f, 0.001093f, 0.001332f, 0.001885f, 0.002129f, 0.003254f, 0.004818f, 0.006889f, + 0.011429f, 0.021957f, 0.052521f, 0.201294f, 0.714355f, 0.929199f, 0.972168f, 0.985352f, 0.991211f, 0.994141f, 0.995605f, 0.997070f, + 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000115f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000184f, 0.000241f, 0.000347f, 0.000453f, 0.000579f, 0.000728f, 0.000729f, 0.001034f, 0.001093f, 0.001292f, + 0.001857f, 0.002131f, 0.003296f, 0.004826f, 0.006958f, 0.011726f, 0.023071f, 0.057983f, 0.239258f, 0.767578f, 0.939453f, 0.976074f, + 0.987305f, 0.992676f, 0.994629f, 0.996094f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000088f, 0.000119f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000191f, 0.000242f, 0.000425f, 0.000558f, + 0.000723f, 0.000730f, 0.001058f, 0.001092f, 0.001297f, 0.001653f, 0.002352f, 0.003124f, 0.004860f, 0.007072f, 0.012131f, 0.024551f, + 0.066406f, 0.300537f, 0.820312f, 0.951172f, 0.979492f, 0.988281f, 0.993164f, 0.995117f, 0.996582f, 0.997070f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, + 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000227f, 0.000239f, 0.000341f, 0.000359f, 0.000587f, 0.000605f, 0.000729f, 0.001040f, 0.001185f, 0.001275f, 0.001849f, 0.002390f, + 0.003399f, 0.005001f, 0.007404f, 0.012871f, 0.027237f, 0.079529f, 0.395264f, 0.868164f, 0.960938f, 0.982910f, 0.990234f, 0.993164f, + 0.995605f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000211f, 0.000239f, 0.000307f, 0.000394f, 0.000704f, 0.000711f, 0.000728f, + 0.001001f, 0.001088f, 0.001204f, 0.001713f, 0.002367f, 0.003151f, 0.004639f, 0.007820f, 0.014084f, 0.030609f, 0.102722f, 0.527344f, + 0.906250f, 0.969727f, 0.985840f, 0.991699f, 0.994629f, 0.996094f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000117f, 0.000115f, 0.000121f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000196f, + 0.000332f, 0.000363f, 0.000686f, 0.000719f, 0.000723f, 0.000963f, 0.001089f, 0.001290f, 0.001849f, 0.002394f, 0.003458f, 0.004833f, + 0.008301f, 0.015579f, 0.036926f, 0.143188f, 0.676270f, 0.934570f, 0.976562f, 0.988281f, 0.992676f, 0.995605f, 0.996582f, 0.998047f, + 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000102f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000311f, 0.000345f, 0.000479f, 0.000723f, 0.000728f, 0.000934f, 0.001085f, + 0.001282f, 0.001821f, 0.002399f, 0.003355f, 0.005524f, 0.008881f, 0.017807f, 0.047058f, 0.222046f, 0.803223f, 0.954102f, 0.981445f, + 0.990723f, 0.994141f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000090f, 0.000116f, 0.000121f, 0.000121f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000201f, 0.000239f, 0.000358f, + 0.000618f, 0.000719f, 0.000727f, 0.000863f, 0.001087f, 0.001350f, 0.001945f, 0.002689f, 0.003731f, 0.005817f, 0.010033f, 0.021332f, + 0.064514f, 0.374512f, 0.885254f, 0.969238f, 0.986328f, 0.992676f, 0.995605f, 0.996582f, 0.998047f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000086f, 0.000117f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000164f, 0.000238f, 0.000353f, 0.000596f, 0.000591f, 0.000727f, 0.000901f, 0.001085f, 0.001266f, 0.001767f, + 0.002663f, 0.003914f, 0.006153f, 0.011612f, 0.026871f, 0.100525f, 0.605957f, 0.934082f, 0.978027f, 0.989746f, 0.994141f, 0.996094f, + 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000107f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000195f, 0.000323f, 0.000339f, 0.000461f, 0.000706f, + 0.000726f, 0.000845f, 0.001086f, 0.001298f, 0.001843f, 0.003027f, 0.004387f, 0.007011f, 0.013832f, 0.036530f, 0.183228f, 0.805664f, + 0.959961f, 0.984863f, 0.991699f, 0.995605f, 0.997070f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000117f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000224f, 0.000336f, 0.000464f, 0.000708f, 0.000726f, 0.000965f, 0.001083f, 0.001458f, 0.002180f, 0.003096f, 0.004425f, + 0.008377f, 0.017639f, 0.056610f, 0.390869f, 0.909180f, 0.975586f, 0.989746f, 0.994141f, 0.996582f, 0.998047f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000110f, 0.000113f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000135f, 0.000336f, 0.000467f, 0.000713f, 0.000725f, 0.000959f, + 0.001191f, 0.001287f, 0.001939f, 0.003231f, 0.005306f, 0.009888f, 0.024414f, 0.105835f, 0.709961f, 0.955078f, 0.984863f, 0.993164f, + 0.996094f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000061f, 0.000089f, + 0.000118f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000309f, + 0.000299f, 0.000460f, 0.000710f, 0.000724f, 0.000997f, 0.001073f, 0.001410f, 0.002117f, 0.003506f, 0.006031f, 0.012863f, 0.038391f, + 0.260742f, 0.892090f, 0.975098f, 0.990723f, 0.995117f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000085f, 0.000110f, 0.000118f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000317f, 0.000499f, 0.000706f, 0.000599f, 0.000851f, 0.001069f, 0.001633f, + 0.002367f, 0.003918f, 0.007580f, 0.017929f, 0.074646f, 0.645508f, 0.956055f, 0.986328f, 0.994141f, 0.996582f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000099f, 0.000113f, + 0.000119f, 0.000119f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000160f, 0.000326f, 0.000308f, + 0.000578f, 0.000602f, 0.000921f, 0.001071f, 0.001807f, 0.002783f, 0.004620f, 0.010017f, 0.029465f, 0.211792f, 0.896484f, 0.979004f, + 0.992188f, 0.996094f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000027f, 0.000103f, 0.000114f, 0.000118f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000090f, 0.000212f, 0.000309f, 0.000586f, 0.000602f, 0.000937f, 0.001147f, 0.002031f, 0.003237f, 0.006134f, + 0.014969f, 0.063171f, 0.665527f, 0.964355f, 0.989258f, 0.995117f, 0.999023f, 0.998535f, 0.999023f, 0.999023f, 0.998535f, 0.999023f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000018f, 0.000103f, 0.000113f, + 0.000117f, 0.000119f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000004f, 0.000002f, 0.000199f, 0.000390f, 0.000586f, 0.000665f, + 0.000946f, 0.001365f, 0.002207f, 0.003767f, 0.008308f, 0.025955f, 0.227661f, 0.924316f, 0.984863f, 0.994141f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000098f, 0.000109f, 0.000117f, 0.000119f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000011f, 0.000005f, 0.000003f, + 0.000002f, 0.000193f, 0.000388f, 0.000586f, 0.000659f, 0.000952f, 0.001580f, 0.002762f, 0.005363f, 0.013153f, 0.066589f, 0.781738f, + 0.977051f, 0.993164f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000075f, 0.000112f, + 0.000116f, 0.000118f, 0.000119f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, + 0.000088f, 0.000026f, 0.000010f, 0.000005f, 0.000003f, 0.000002f, 0.000186f, 0.000407f, 0.000586f, 0.000760f, 0.000986f, 0.001796f, + 0.003275f, 0.007565f, 0.026794f, 0.363281f, 0.959473f, 0.990723f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000010f, 0.000090f, 0.000110f, 0.000115f, 0.000117f, 0.000119f, 0.000120f, 0.000120f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000077f, 0.000023f, 0.000011f, 0.000005f, 0.000003f, 0.000002f, 0.000158f, + 0.000407f, 0.000587f, 0.000826f, 0.001264f, 0.002174f, 0.004894f, 0.013359f, 0.098511f, 0.911133f, 0.987793f, 0.998047f, 0.998047f, + 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000084f, 0.000107f, + 0.000114f, 0.000117f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000093f, 0.000024f, + 0.000011f, 0.000005f, 0.000003f, 0.000002f, 0.000220f, 0.000476f, 0.000585f, 0.000913f, 0.001374f, 0.002951f, 0.007511f, 0.034973f, + 0.736328f, 0.982910f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000056f, 0.000102f, 0.000112f, 0.000116f, 0.000117f, 0.000119f, 0.000120f, 0.000120f, + 0.000121f, 0.000121f, 0.000121f, 0.000075f, 0.000025f, 0.000010f, 0.000005f, 0.000003f, 0.000034f, 0.000222f, 0.000491f, 0.000589f, + 0.001020f, 0.001881f, 0.004669f, 0.015717f, 0.298340f, 0.974609f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000048f, 0.000095f, + 0.000106f, 0.000114f, 0.000117f, 0.000118f, 0.000119f, 0.000120f, 0.000120f, 0.000121f, 0.000089f, 0.000029f, 0.000012f, 0.000006f, + 0.000003f, 0.000002f, 0.000223f, 0.000525f, 0.000687f, 0.001122f, 0.002672f, 0.008255f, 0.079590f, 0.954590f, 0.996582f, 0.996582f, + 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000077f, 0.000104f, 0.000112f, 0.000115f, 0.000117f, 0.000119f, 0.000119f, + 0.000120f, 0.000109f, 0.000031f, 0.000013f, 0.000006f, 0.000003f, 0.000002f, 0.000254f, 0.000550f, 0.000846f, 0.001545f, 0.004223f, + 0.027771f, 0.901855f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000037f, + 0.000090f, 0.000107f, 0.000113f, 0.000116f, 0.000118f, 0.000119f, 0.000120f, 0.000041f, 0.000015f, 0.000007f, 0.000004f, 0.000002f, + 0.000271f, 0.000563f, 0.000786f, 0.002211f, 0.012207f, 0.711426f, 0.994629f, 0.994629f, 0.995117f, 0.994629f, 0.994629f, 0.994629f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000028f, 0.000083f, 0.000102f, 0.000110f, 0.000114f, 0.000117f, 0.000118f, + 0.000052f, 0.000019f, 0.000008f, 0.000004f, 0.000002f, 0.000314f, 0.000444f, 0.001049f, 0.005669f, 0.266846f, 0.993164f, 0.993652f, + 0.993164f, 0.993652f, 0.993164f, 0.993164f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000048f, 0.000089f, 0.000106f, 0.000112f, 0.000115f, 0.000077f, 0.000026f, 0.000010f, 0.000005f, 0.000079f, 0.000425f, 0.000405f, + 0.002468f, 0.064209f, 0.990234f, 0.990723f, 0.990234f, 0.990234f, 0.990234f, 0.991211f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000020f, 0.000075f, 0.000098f, 0.000108f, 0.000113f, 0.000044f, + 0.000016f, 0.000006f, 0.000027f, 0.000270f, 0.000825f, 0.018448f, 0.986328f, 0.986328f, 0.986328f, 0.986328f, 0.986328f, 0.986328f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000049f, 0.000085f, 0.000102f, 0.000070f, 0.000022f, 0.000008f, 0.000133f, 0.000295f, 0.005318f, 0.978516f, 0.979004f, + 0.977539f, 0.977539f, 0.978027f, 0.978516f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000066f, 0.000092f, 0.000036f, 0.000011f, + 0.000135f, 0.000925f, 0.959473f, 0.959961f, 0.959961f, 0.959473f, 0.959961f, 0.959473f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000027f, 0.000065f, 0.000016f, 0.000109f, 0.907715f, 0.907227f, 0.907715f, 0.907227f, 0.907715f, 0.907715f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000017f, 0.711914f, 0.712402f, + 0.711426f, 0.711426f, 0.711914f, 0.712402f, + }, + { + 0.076172f, 0.877441f, 0.964355f, 0.980957f, 0.987305f, 0.990723f, 0.992676f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, + 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.003897f, 0.033173f, 0.320557f, 0.863770f, 0.953613f, 0.975586f, 0.984863f, 0.988770f, + 0.991211f, 0.992676f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, + 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000975f, 0.005951f, 0.020935f, 0.093140f, + 0.501465f, 0.873047f, 0.950684f, 0.973145f, 0.981934f, 0.986816f, 0.990234f, 0.992188f, 0.993164f, 0.994629f, 0.995605f, 0.996094f, + 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000610f, 0.002430f, 0.006081f, 0.015915f, 0.045593f, 0.179810f, 0.635254f, 0.889648f, 0.951172f, 0.972168f, 0.981445f, 0.986328f, + 0.989746f, 0.991699f, 0.993652f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, + 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.001219f, 0.002796f, 0.006172f, 0.012848f, 0.028458f, 0.081177f, 0.301758f, + 0.733398f, 0.905273f, 0.953613f, 0.972168f, 0.981445f, 0.986328f, 0.989258f, 0.991699f, 0.993652f, 0.994141f, 0.995117f, 0.996094f, + 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000731f, 0.001706f, 0.003166f, + 0.005470f, 0.010406f, 0.020813f, 0.047089f, 0.136719f, 0.449951f, 0.803223f, 0.919434f, 0.957520f, 0.973633f, 0.981934f, 0.986328f, + 0.989746f, 0.991699f, 0.993164f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, + 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000244f, 0.000366f, 0.001214f, 0.001894f, 0.003159f, 0.005108f, 0.008720f, 0.015839f, 0.031586f, 0.074951f, 0.224121f, 0.596680f, + 0.851074f, 0.932617f, 0.962402f, 0.975586f, 0.982910f, 0.987305f, 0.989746f, 0.991699f, 0.993164f, 0.994141f, 0.995117f, 0.995605f, + 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000366f, 0.000731f, 0.000976f, 0.001827f, 0.002987f, 0.004757f, 0.007988f, + 0.013023f, 0.023544f, 0.048431f, 0.120239f, 0.352783f, 0.717285f, 0.887207f, 0.943848f, 0.966309f, 0.978027f, 0.983887f, 0.987305f, + 0.990234f, 0.992188f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.998047f, 0.998047f, + 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000434f, 0.000488f, 0.000704f, + 0.001218f, 0.002190f, 0.002783f, 0.004723f, 0.006878f, 0.011040f, 0.018372f, 0.034241f, 0.073242f, 0.194336f, 0.510742f, 0.803711f, + 0.912598f, 0.952637f, 0.970703f, 0.979004f, 0.984863f, 0.988281f, 0.991211f, 0.992676f, 0.994141f, 0.994629f, 0.995605f, 0.996094f, + 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000243f, 0.000488f, 0.000488f, 0.000916f, 0.001219f, 0.002308f, 0.002914f, 0.004124f, 0.006523f, 0.009537f, 0.014793f, + 0.025833f, 0.050446f, 0.116089f, 0.312744f, 0.661133f, 0.860840f, 0.931641f, 0.960449f, 0.974121f, 0.981445f, 0.986328f, 0.989258f, + 0.991211f, 0.992676f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000121f, 0.000356f, 0.000488f, 0.000609f, 0.000944f, 0.001339f, 0.002296f, + 0.002964f, 0.003880f, 0.005676f, 0.008476f, 0.012909f, 0.020874f, 0.036926f, 0.075500f, 0.187988f, 0.474854f, 0.774414f, 0.900391f, + 0.946289f, 0.966309f, 0.978027f, 0.983887f, 0.987793f, 0.990234f, 0.991699f, 0.993164f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, + 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000244f, 0.000483f, + 0.000488f, 0.000731f, 0.001070f, 0.001551f, 0.002024f, 0.002520f, 0.003990f, 0.004738f, 0.007584f, 0.010834f, 0.016800f, 0.028763f, + 0.054535f, 0.120728f, 0.309082f, 0.642090f, 0.848145f, 0.926270f, 0.957031f, 0.971191f, 0.980469f, 0.985352f, 0.988770f, 0.990723f, + 0.992188f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000122f, 0.000242f, 0.000485f, 0.000608f, 0.000731f, 0.001091f, 0.001339f, 0.001943f, 0.002602f, 0.003466f, + 0.004845f, 0.006649f, 0.009529f, 0.014824f, 0.023407f, 0.041351f, 0.083496f, 0.199951f, 0.482422f, 0.770996f, 0.896484f, 0.944336f, + 0.965332f, 0.976562f, 0.982910f, 0.986816f, 0.990234f, 0.991699f, 0.993164f, 0.994141f, 0.995117f, 0.995117f, 0.996094f, 0.996582f, + 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000121f, 0.000243f, 0.000243f, 0.000602f, 0.000609f, 0.000799f, + 0.001088f, 0.001459f, 0.001822f, 0.002432f, 0.003033f, 0.004375f, 0.006042f, 0.008560f, 0.012810f, 0.019791f, 0.032715f, 0.061584f, + 0.135254f, 0.335693f, 0.660156f, 0.853027f, 0.926758f, 0.956543f, 0.972168f, 0.980469f, 0.984863f, 0.988281f, 0.991211f, 0.992676f, + 0.993652f, 0.994141f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, + 0.000243f, 0.000366f, 0.000605f, 0.000730f, 0.000731f, 0.001201f, 0.001458f, 0.001804f, 0.002428f, 0.003593f, 0.004234f, 0.005745f, + 0.007755f, 0.011139f, 0.016754f, 0.027054f, 0.047424f, 0.097107f, 0.231323f, 0.525879f, 0.791016f, 0.902832f, 0.945801f, 0.966797f, + 0.977051f, 0.982910f, 0.987793f, 0.990234f, 0.991699f, 0.993164f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, + 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000116f, 0.000122f, 0.000365f, 0.000244f, 0.000602f, 0.000721f, 0.000730f, 0.000852f, 0.001451f, + 0.001842f, 0.002518f, 0.002993f, 0.004097f, 0.005253f, 0.007099f, 0.009865f, 0.014908f, 0.022827f, 0.038879f, 0.072815f, 0.163940f, + 0.396484f, 0.707031f, 0.869141f, 0.932129f, 0.960449f, 0.973145f, 0.980957f, 0.986328f, 0.988770f, 0.991211f, 0.992676f, 0.993652f, + 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000110f, 0.000361f, 0.000242f, 0.000244f, + 0.000602f, 0.000728f, 0.000853f, 0.001260f, 0.001569f, 0.001704f, 0.002287f, 0.003103f, 0.003857f, 0.004848f, 0.006680f, 0.009003f, + 0.012978f, 0.019897f, 0.032135f, 0.057983f, 0.121033f, 0.291504f, 0.604980f, 0.827148f, 0.915039f, 0.953125f, 0.969238f, 0.978516f, + 0.984375f, 0.988281f, 0.991211f, 0.992188f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.998047f, + 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000241f, 0.000241f, 0.000365f, 0.000365f, 0.000589f, 0.000852f, 0.000852f, 0.001246f, 0.001562f, 0.001812f, 0.002241f, + 0.002794f, 0.003633f, 0.004669f, 0.006069f, 0.008202f, 0.011772f, 0.016891f, 0.027618f, 0.047089f, 0.093506f, 0.216309f, 0.495605f, + 0.771484f, 0.894531f, 0.942383f, 0.965332f, 0.976074f, 0.982910f, 0.987305f, 0.989746f, 0.991699f, 0.993164f, 0.994629f, 0.995117f, + 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000364f, 0.000242f, 0.000487f, 0.000737f, 0.000730f, + 0.000974f, 0.001083f, 0.001520f, 0.001701f, 0.001938f, 0.002768f, 0.003658f, 0.004227f, 0.005741f, 0.007671f, 0.010796f, 0.015511f, + 0.023529f, 0.040009f, 0.074158f, 0.165405f, 0.395264f, 0.703613f, 0.868164f, 0.932129f, 0.959473f, 0.973633f, 0.980957f, 0.985840f, + 0.988770f, 0.991699f, 0.992676f, 0.994141f, 0.995117f, 0.995117f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, + 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000100f, 0.000000f, 0.000241f, + 0.000224f, 0.000487f, 0.000488f, 0.000710f, 0.000972f, 0.000848f, 0.001181f, 0.001333f, 0.001910f, 0.001830f, 0.002661f, 0.003298f, + 0.004154f, 0.005386f, 0.007271f, 0.009735f, 0.013908f, 0.021149f, 0.034149f, 0.062042f, 0.130371f, 0.313477f, 0.627930f, 0.837402f, + 0.919922f, 0.954590f, 0.970215f, 0.979492f, 0.985352f, 0.988770f, 0.991211f, 0.992676f, 0.993652f, 0.995117f, 0.995605f, 0.996094f, + 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000049f, 0.000242f, 0.000483f, 0.000606f, 0.000487f, 0.000695f, 0.000970f, 0.000974f, 0.001136f, + 0.001328f, 0.001694f, 0.002028f, 0.002617f, 0.002953f, 0.003847f, 0.004951f, 0.006653f, 0.009193f, 0.012672f, 0.018661f, 0.029968f, + 0.052673f, 0.106689f, 0.250977f, 0.549805f, 0.801758f, 0.907227f, 0.948242f, 0.967773f, 0.978027f, 0.984375f, 0.987793f, 0.990723f, + 0.992188f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000166f, 0.000243f, 0.000485f, 0.000487f, + 0.000487f, 0.000945f, 0.000834f, 0.000974f, 0.000974f, 0.001300f, 0.001810f, 0.002058f, 0.002573f, 0.002703f, 0.003761f, 0.004887f, + 0.006393f, 0.008514f, 0.011818f, 0.016937f, 0.026672f, 0.046051f, 0.089478f, 0.204712f, 0.476807f, 0.762207f, 0.891602f, 0.942383f, + 0.965820f, 0.976562f, 0.983398f, 0.987793f, 0.990234f, 0.992188f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, + 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000224f, 0.000358f, 0.000477f, 0.000486f, 0.000487f, 0.000580f, 0.000841f, 0.000973f, 0.001079f, 0.001255f, 0.001649f, + 0.002045f, 0.002241f, 0.002995f, 0.003841f, 0.004826f, 0.005920f, 0.007866f, 0.010925f, 0.015930f, 0.024109f, 0.040619f, 0.077454f, + 0.171509f, 0.412354f, 0.720215f, 0.876953f, 0.936035f, 0.962402f, 0.975098f, 0.982422f, 0.987305f, 0.990234f, 0.992188f, 0.993164f, + 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000165f, 0.000205f, 0.000411f, 0.000480f, 0.000486f, 0.000608f, 0.000688f, + 0.000966f, 0.000968f, 0.000974f, 0.001421f, 0.001489f, 0.001695f, 0.002090f, 0.002886f, 0.003326f, 0.004608f, 0.005604f, 0.007317f, + 0.010414f, 0.014862f, 0.022232f, 0.036469f, 0.067810f, 0.146973f, 0.359375f, 0.680664f, 0.861816f, 0.931152f, 0.959961f, 0.974609f, + 0.981934f, 0.986816f, 0.989746f, 0.991699f, 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, + 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000242f, + 0.000453f, 0.000539f, 0.000486f, 0.000487f, 0.000487f, 0.000957f, 0.000969f, 0.001202f, 0.001139f, 0.001393f, 0.001986f, 0.002045f, + 0.002863f, 0.003216f, 0.004128f, 0.005417f, 0.007378f, 0.009689f, 0.013466f, 0.020432f, 0.033722f, 0.060883f, 0.129395f, 0.318115f, + 0.642090f, 0.847656f, 0.926270f, 0.958008f, 0.973145f, 0.981934f, 0.986328f, 0.989746f, 0.992188f, 0.993164f, 0.994629f, 0.995605f, + 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000380f, 0.000482f, 0.000606f, 0.000607f, 0.000608f, 0.000829f, 0.000970f, + 0.000972f, 0.001070f, 0.001402f, 0.001812f, 0.002138f, 0.002619f, 0.003246f, 0.004082f, 0.005318f, 0.006699f, 0.009262f, 0.012764f, + 0.019318f, 0.031052f, 0.055878f, 0.116821f, 0.286621f, 0.610352f, 0.835938f, 0.922852f, 0.956543f, 0.973145f, 0.981445f, 0.986328f, + 0.989746f, 0.991699f, 0.993652f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000243f, 0.000350f, 0.000480f, + 0.000605f, 0.000596f, 0.000608f, 0.000890f, 0.000963f, 0.000972f, 0.000974f, 0.001316f, 0.001798f, 0.002058f, 0.002560f, 0.002811f, + 0.003983f, 0.005108f, 0.006489f, 0.008888f, 0.012314f, 0.018021f, 0.029495f, 0.051941f, 0.107422f, 0.263428f, 0.585449f, 0.827148f, + 0.919434f, 0.956055f, 0.971680f, 0.981445f, 0.986816f, 0.989746f, 0.992188f, 0.994141f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, + 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000130f, 0.000176f, 0.000462f, 0.000483f, 0.000604f, 0.000607f, 0.000638f, 0.000922f, 0.000965f, 0.000971f, 0.001235f, + 0.001376f, 0.001769f, 0.002041f, 0.002575f, 0.003130f, 0.003487f, 0.004936f, 0.006264f, 0.008415f, 0.012047f, 0.017517f, 0.027786f, + 0.049164f, 0.101257f, 0.249512f, 0.568848f, 0.821777f, 0.918945f, 0.956055f, 0.972168f, 0.981445f, 0.986816f, 0.990234f, 0.992188f, + 0.993652f, 0.995117f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000130f, 0.000122f, 0.000242f, 0.000352f, 0.000560f, 0.000602f, 0.000604f, + 0.000606f, 0.000767f, 0.001046f, 0.001089f, 0.000973f, 0.001327f, 0.001583f, 0.002033f, 0.002272f, 0.002657f, 0.003563f, 0.004589f, + 0.006138f, 0.008194f, 0.011299f, 0.016861f, 0.026718f, 0.047119f, 0.097656f, 0.240967f, 0.562500f, 0.821289f, 0.919922f, 0.957031f, + 0.973145f, 0.981934f, 0.987305f, 0.990234f, 0.992676f, 0.994141f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.998047f, 0.998047f, + 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000241f, 0.000314f, 0.000459f, 0.000600f, 0.000605f, 0.000598f, 0.000804f, 0.000958f, 0.001084f, 0.001104f, 0.001389f, 0.001709f, + 0.002041f, 0.002211f, 0.002645f, 0.003635f, 0.004467f, 0.005718f, 0.008072f, 0.011185f, 0.016846f, 0.026184f, 0.046112f, 0.094971f, + 0.239014f, 0.565430f, 0.825684f, 0.922363f, 0.958496f, 0.973633f, 0.983398f, 0.987793f, 0.990723f, 0.992676f, 0.994141f, 0.995605f, + 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000238f, 0.000122f, 0.000173f, 0.000246f, 0.000387f, 0.000480f, 0.000604f, 0.000604f, 0.000701f, + 0.000951f, 0.000968f, 0.001184f, 0.001315f, 0.001597f, 0.001899f, 0.002268f, 0.002813f, 0.003716f, 0.004372f, 0.005886f, 0.007759f, + 0.010918f, 0.015915f, 0.025726f, 0.045685f, 0.095459f, 0.243774f, 0.579102f, 0.833984f, 0.926270f, 0.960449f, 0.976074f, 0.983887f, + 0.988770f, 0.991211f, 0.993164f, 0.994629f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.999512f, 0.999512f, + 0.999023f, 0.999512f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000238f, 0.000237f, 0.000242f, + 0.000463f, 0.000585f, 0.000587f, 0.000718f, 0.000607f, 0.000885f, 0.001081f, 0.001087f, 0.001299f, 0.001553f, 0.001982f, 0.002104f, + 0.002777f, 0.003494f, 0.004406f, 0.005798f, 0.007645f, 0.010750f, 0.016159f, 0.025467f, 0.045959f, 0.097778f, 0.256104f, 0.603516f, + 0.847168f, 0.931152f, 0.963379f, 0.977539f, 0.985352f, 0.989258f, 0.991699f, 0.993652f, 0.995117f, 0.996094f, 0.996582f, 0.997559f, + 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000231f, 0.000122f, 0.000242f, 0.000242f, 0.000400f, 0.000525f, 0.000495f, 0.000605f, 0.000607f, 0.000898f, 0.001075f, + 0.001191f, 0.001133f, 0.001420f, 0.001794f, 0.002041f, 0.002733f, 0.003548f, 0.004448f, 0.005585f, 0.007656f, 0.010735f, 0.015671f, + 0.025589f, 0.047363f, 0.102783f, 0.276855f, 0.637695f, 0.862793f, 0.938477f, 0.966797f, 0.979004f, 0.985840f, 0.990234f, 0.992676f, + 0.994141f, 0.995117f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000226f, 0.000242f, 0.000470f, 0.000469f, + 0.000547f, 0.000711f, 0.000723f, 0.000829f, 0.001024f, 0.001188f, 0.001081f, 0.001415f, 0.001765f, 0.002048f, 0.002708f, 0.003252f, + 0.004448f, 0.005711f, 0.007557f, 0.010780f, 0.016220f, 0.026398f, 0.048950f, 0.111267f, 0.309082f, 0.680664f, 0.880371f, 0.945801f, + 0.970703f, 0.980957f, 0.986816f, 0.990723f, 0.993164f, 0.994629f, 0.995605f, 0.996582f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000204f, 0.000239f, 0.000242f, 0.000283f, 0.000479f, 0.000594f, 0.000603f, 0.000606f, 0.000779f, 0.001068f, 0.001084f, 0.001118f, + 0.001515f, 0.001926f, 0.002098f, 0.002674f, 0.002975f, 0.004040f, 0.005478f, 0.007488f, 0.010651f, 0.016327f, 0.027222f, 0.052460f, + 0.123718f, 0.355713f, 0.729980f, 0.899902f, 0.952637f, 0.973145f, 0.983887f, 0.988770f, 0.991699f, 0.994141f, 0.995117f, 0.996094f, + 0.997070f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000122f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000236f, 0.000207f, 0.000240f, 0.000435f, 0.000534f, 0.000594f, 0.000602f, + 0.000722f, 0.000727f, 0.000947f, 0.001081f, 0.001090f, 0.001471f, 0.001829f, 0.002010f, 0.002478f, 0.002956f, 0.004051f, 0.005753f, + 0.007717f, 0.011040f, 0.017105f, 0.028748f, 0.057159f, 0.142944f, 0.421387f, 0.780762f, 0.916992f, 0.960449f, 0.976562f, 0.985352f, + 0.989746f, 0.992676f, 0.994629f, 0.996094f, 0.997070f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000224f, 0.000232f, + 0.000230f, 0.000382f, 0.000472f, 0.000576f, 0.000715f, 0.000721f, 0.000727f, 0.001046f, 0.001078f, 0.001186f, 0.001434f, 0.001674f, + 0.002066f, 0.002546f, 0.003407f, 0.004181f, 0.005634f, 0.007542f, 0.011330f, 0.017609f, 0.031189f, 0.064392f, 0.172729f, 0.506836f, + 0.828125f, 0.933105f, 0.966309f, 0.980469f, 0.987305f, 0.991211f, 0.993652f, 0.995117f, 0.996582f, 0.997070f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000232f, 0.000234f, 0.000352f, 0.000461f, 0.000535f, 0.000594f, 0.000722f, 0.000725f, + 0.000921f, 0.001116f, 0.001192f, 0.001416f, 0.001637f, 0.001911f, 0.002380f, 0.002949f, 0.003948f, 0.005589f, 0.007942f, 0.011650f, + 0.018631f, 0.034302f, 0.075867f, 0.219238f, 0.607422f, 0.870605f, 0.946777f, 0.972656f, 0.983887f, 0.989258f, 0.992676f, 0.995117f, + 0.996094f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000239f, 0.000302f, + 0.000396f, 0.000564f, 0.000674f, 0.000617f, 0.000722f, 0.001003f, 0.001068f, 0.001084f, 0.001302f, 0.001598f, 0.001929f, 0.002375f, + 0.002935f, 0.004349f, 0.005714f, 0.007957f, 0.012306f, 0.020493f, 0.039001f, 0.092590f, 0.293213f, 0.711426f, 0.905762f, 0.958984f, + 0.978027f, 0.986328f, 0.990723f, 0.994141f, 0.995605f, 0.996582f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000232f, 0.000227f, 0.000240f, 0.000282f, 0.000542f, 0.000703f, 0.000718f, 0.000724f, 0.000833f, 0.001069f, + 0.001184f, 0.001346f, 0.001464f, 0.001898f, 0.002649f, 0.003164f, 0.004467f, 0.005863f, 0.008400f, 0.013199f, 0.022614f, 0.046051f, + 0.120605f, 0.406738f, 0.801270f, 0.931641f, 0.968262f, 0.982422f, 0.988770f, 0.992676f, 0.994629f, 0.996094f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000120f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000219f, 0.000237f, 0.000235f, 0.000241f, 0.000480f, + 0.000584f, 0.000715f, 0.000723f, 0.000775f, 0.001061f, 0.000959f, 0.001139f, 0.001526f, 0.001770f, 0.002546f, 0.003151f, 0.004250f, + 0.006195f, 0.009071f, 0.014595f, 0.026413f, 0.056763f, 0.169067f, 0.557617f, 0.869141f, 0.951172f, 0.976074f, 0.986328f, 0.990723f, + 0.994141f, 0.995605f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000120f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000216f, 0.000228f, 0.000285f, 0.000339f, 0.000454f, 0.000572f, 0.000595f, 0.000721f, 0.000604f, 0.000930f, 0.000958f, 0.001171f, + 0.001431f, 0.001888f, 0.002663f, 0.003256f, 0.004402f, 0.006527f, 0.009964f, 0.016281f, 0.031189f, 0.074524f, 0.258301f, 0.714355f, + 0.916016f, 0.965332f, 0.982422f, 0.989746f, 0.992676f, 0.995117f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000000f, 0.000063f, 0.000120f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000194f, 0.000184f, 0.000228f, 0.000340f, 0.000396f, 0.000668f, 0.000571f, + 0.000478f, 0.000602f, 0.000919f, 0.000956f, 0.001061f, 0.001497f, 0.001888f, 0.002565f, 0.003523f, 0.004578f, 0.006935f, 0.010765f, + 0.018417f, 0.038635f, 0.107727f, 0.416260f, 0.832520f, 0.946289f, 0.975586f, 0.986328f, 0.991699f, 0.994629f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000045f, 0.000118f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000234f, 0.000294f, 0.000220f, 0.000486f, 0.000579f, 0.000588f, 0.000669f, 0.000878f, 0.001038f, 0.001135f, 0.001451f, 0.001820f, + 0.002529f, 0.003551f, 0.005199f, 0.007542f, 0.012230f, 0.022369f, 0.051910f, 0.174927f, 0.630859f, 0.905273f, 0.965332f, 0.982910f, + 0.990234f, 0.993652f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000091f, + 0.000117f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000171f, 0.000151f, 0.000166f, 0.000195f, 0.000342f, 0.000452f, 0.000594f, 0.000599f, + 0.000862f, 0.001019f, 0.001135f, 0.001465f, 0.002031f, 0.002676f, 0.003714f, 0.005497f, 0.008286f, 0.014320f, 0.028854f, 0.077332f, + 0.322754f, 0.809082f, 0.946289f, 0.977051f, 0.987793f, 0.993164f, 0.998047f, 0.998535f, 0.998047f, 0.998047f, 0.998535f, 0.998047f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000079f, 0.000105f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000008f, 0.000006f, 0.000098f, 0.000137f, + 0.000233f, 0.000324f, 0.000566f, 0.000589f, 0.000618f, 0.000874f, 0.000941f, 0.001108f, 0.001621f, 0.001880f, 0.002726f, 0.003788f, + 0.005840f, 0.009583f, 0.017563f, 0.039368f, 0.133545f, 0.582520f, 0.906738f, 0.968262f, 0.984863f, 0.992188f, 0.998047f, 0.998047f, + 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000069f, 0.000114f, + 0.000117f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000021f, + 0.000013f, 0.000009f, 0.000006f, 0.000004f, 0.000090f, 0.000206f, 0.000305f, 0.000538f, 0.000585f, 0.000596f, 0.000869f, 0.000941f, + 0.001149f, 0.001516f, 0.002150f, 0.002729f, 0.004475f, 0.006660f, 0.011360f, 0.022690f, 0.061401f, 0.281494f, 0.813965f, 0.952148f, + 0.980957f, 0.990723f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000085f, 0.000114f, 0.000117f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000122f, 0.000122f, 0.000077f, 0.000041f, 0.000022f, 0.000013f, 0.000009f, 0.000006f, 0.000066f, 0.000107f, 0.000223f, 0.000250f, + 0.000532f, 0.000576f, 0.000593f, 0.000784f, 0.000937f, 0.001126f, 0.001523f, 0.002306f, 0.003193f, 0.004574f, 0.007717f, 0.014191f, + 0.032410f, 0.116577f, 0.595215f, 0.921875f, 0.974609f, 0.988770f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000056f, 0.000112f, + 0.000114f, 0.000118f, 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000074f, 0.000038f, 0.000021f, 0.000013f, 0.000009f, + 0.000006f, 0.000004f, 0.000003f, 0.000179f, 0.000258f, 0.000367f, 0.000469f, 0.000583f, 0.000770f, 0.000932f, 0.001131f, 0.001758f, + 0.002483f, 0.003517f, 0.005432f, 0.009232f, 0.019302f, 0.054504f, 0.293457f, 0.853516f, 0.964844f, 0.986816f, 0.997070f, 0.997070f, + 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000015f, 0.000084f, 0.000107f, 0.000113f, 0.000117f, 0.000118f, 0.000119f, 0.000120f, 0.000120f, + 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000076f, 0.000042f, 0.000023f, 0.000015f, 0.000009f, 0.000007f, 0.000005f, 0.000004f, 0.000147f, 0.000238f, 0.000457f, 0.000545f, + 0.000586f, 0.000821f, 0.000936f, 0.001139f, 0.001849f, 0.002665f, 0.003687f, 0.006367f, 0.011810f, 0.028931f, 0.120605f, 0.687988f, + 0.947754f, 0.982910f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000082f, 0.000095f, + 0.000111f, 0.000115f, 0.000117f, 0.000118f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000083f, 0.000042f, 0.000026f, 0.000015f, 0.000010f, 0.000007f, 0.000005f, + 0.000013f, 0.000086f, 0.000185f, 0.000309f, 0.000552f, 0.000577f, 0.000796f, 0.000925f, 0.001251f, 0.001838f, 0.002878f, 0.004509f, + 0.007572f, 0.016617f, 0.054932f, 0.391602f, 0.912109f, 0.978516f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996094f, 0.996094f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000095f, 0.000106f, 0.000112f, 0.000113f, 0.000115f, 0.000118f, 0.000118f, + 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000099f, 0.000048f, + 0.000027f, 0.000017f, 0.000011f, 0.000008f, 0.000006f, 0.000004f, 0.000089f, 0.000182f, 0.000347f, 0.000495f, 0.000570f, 0.000777f, + 0.000922f, 0.001316f, 0.001831f, 0.003004f, 0.005028f, 0.010078f, 0.028183f, 0.161865f, 0.833496f, 0.972168f, 0.995117f, 0.995605f, + 0.995605f, 0.995117f, 0.995117f, 0.995605f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000074f, + 0.000093f, 0.000107f, 0.000111f, 0.000115f, 0.000116f, 0.000117f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, + 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000057f, 0.000032f, 0.000021f, 0.000013f, 0.000008f, 0.000006f, 0.000005f, 0.000034f, + 0.000159f, 0.000267f, 0.000514f, 0.000566f, 0.000714f, 0.000888f, 0.001348f, 0.001995f, 0.003302f, 0.006447f, 0.015945f, 0.069153f, + 0.646484f, 0.960449f, 0.994629f, 0.995117f, 0.994629f, 0.995117f, 0.994629f, 0.995117f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000080f, 0.000095f, 0.000102f, 0.000109f, 0.000114f, 0.000115f, + 0.000116f, 0.000118f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000077f, 0.000044f, 0.000025f, + 0.000015f, 0.000011f, 0.000007f, 0.000005f, 0.000004f, 0.000106f, 0.000244f, 0.000476f, 0.000561f, 0.000622f, 0.000893f, 0.001266f, + 0.001968f, 0.003990f, 0.009476f, 0.033234f, 0.342529f, 0.940918f, 0.993652f, 0.993652f, 0.993652f, 0.993652f, 0.993652f, 0.993652f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000046f, 0.000079f, 0.000093f, 0.000104f, 0.000110f, 0.000111f, 0.000113f, 0.000116f, 0.000117f, 0.000118f, 0.000118f, 0.000119f, + 0.000119f, 0.000119f, 0.000092f, 0.000050f, 0.000029f, 0.000019f, 0.000012f, 0.000009f, 0.000006f, 0.000004f, 0.000061f, 0.000188f, + 0.000324f, 0.000456f, 0.000525f, 0.000657f, 0.001371f, 0.002445f, 0.005634f, 0.017563f, 0.135986f, 0.902832f, 0.992188f, 0.992188f, + 0.992676f, 0.992188f, 0.992676f, 0.992188f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000038f, 0.000075f, 0.000092f, 0.000100f, 0.000105f, + 0.000111f, 0.000112f, 0.000114f, 0.000116f, 0.000117f, 0.000117f, 0.000118f, 0.000118f, 0.000074f, 0.000041f, 0.000024f, 0.000016f, + 0.000010f, 0.000007f, 0.000005f, 0.000033f, 0.000167f, 0.000423f, 0.000410f, 0.000413f, 0.000575f, 0.001446f, 0.003387f, 0.009644f, + 0.056183f, 0.817383f, 0.990234f, 0.990234f, 0.990234f, 0.990723f, 0.990234f, 0.990723f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000011f, 0.000067f, 0.000084f, 0.000096f, 0.000103f, 0.000108f, 0.000110f, 0.000113f, 0.000115f, 0.000115f, + 0.000116f, 0.000104f, 0.000057f, 0.000035f, 0.000021f, 0.000013f, 0.000009f, 0.000006f, 0.000054f, 0.000161f, 0.000317f, 0.000332f, + 0.000393f, 0.000723f, 0.001760f, 0.005203f, 0.025345f, 0.617676f, 0.987793f, 0.987793f, 0.987793f, 0.988281f, 0.988281f, 0.988281f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000017f, 0.000052f, 0.000075f, + 0.000091f, 0.000097f, 0.000105f, 0.000108f, 0.000111f, 0.000113f, 0.000114f, 0.000085f, 0.000050f, 0.000031f, 0.000018f, 0.000012f, + 0.000008f, 0.000005f, 0.000095f, 0.000314f, 0.000306f, 0.000363f, 0.000813f, 0.002583f, 0.011734f, 0.308105f, 0.983887f, 0.984375f, + 0.984375f, 0.984375f, 0.983887f, 0.983887f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000037f, 0.000065f, 0.000083f, 0.000093f, 0.000099f, 0.000105f, 0.000108f, + 0.000110f, 0.000082f, 0.000045f, 0.000027f, 0.000017f, 0.000011f, 0.000007f, 0.000114f, 0.000245f, 0.000209f, 0.000379f, 0.001151f, + 0.005260f, 0.107971f, 0.977539f, 0.979004f, 0.978027f, 0.978027f, 0.978027f, 0.978027f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000007f, 0.000045f, 0.000069f, 0.000084f, 0.000093f, 0.000099f, 0.000104f, 0.000076f, 0.000044f, 0.000026f, 0.000016f, 0.000010f, + 0.000012f, 0.000152f, 0.000179f, 0.000373f, 0.001760f, 0.035522f, 0.969238f, 0.968750f, 0.968750f, 0.968750f, 0.968750f, 0.968750f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000014f, 0.000050f, 0.000070f, 0.000082f, + 0.000092f, 0.000075f, 0.000044f, 0.000026f, 0.000015f, 0.000009f, 0.000121f, 0.000117f, 0.000611f, 0.010231f, 0.951172f, 0.951172f, + 0.951172f, 0.951172f, 0.950684f, 0.951660f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000020f, 0.000047f, 0.000069f, 0.000077f, 0.000042f, 0.000024f, 0.000013f, 0.000078f, + 0.000130f, 0.001914f, 0.915039f, 0.915527f, 0.915039f, 0.915527f, 0.916016f, 0.915039f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000017f, 0.000047f, 0.000040f, 0.000019f, 0.000035f, 0.000188f, 0.833984f, 0.833496f, 0.833496f, 0.834473f, 0.834473f, 0.833984f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000014f, 0.000007f, 0.642578f, 0.643555f, + 0.643066f, 0.643555f, 0.642578f, 0.642578f, + }, + { + 0.113464f, 0.797852f, 0.930176f, 0.961914f, 0.974609f, 0.980469f, 0.984863f, 0.987793f, 0.989258f, 0.991211f, 0.992188f, 0.993164f, + 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, + 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.007183f, 0.058716f, 0.349609f, 0.784668f, 0.912598f, 0.952148f, 0.968262f, 0.977539f, + 0.981934f, 0.985352f, 0.988281f, 0.990234f, 0.991211f, 0.992188f, 0.993652f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.995605f, + 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.002432f, 0.011818f, 0.039581f, 0.143677f, + 0.482910f, 0.800293f, 0.908691f, 0.947266f, 0.964844f, 0.974609f, 0.980469f, 0.984375f, 0.987305f, 0.989258f, 0.990723f, 0.991699f, + 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, + 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.001096f, 0.005062f, 0.012482f, 0.030151f, 0.079956f, 0.239014f, 0.581055f, 0.819824f, 0.909180f, 0.946289f, 0.963379f, 0.973145f, + 0.979492f, 0.983398f, 0.986328f, 0.988281f, 0.990234f, 0.991699f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.996094f, + 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000610f, 0.002434f, 0.005779f, 0.012207f, 0.023972f, 0.052765f, 0.129883f, 0.342773f, + 0.660156f, 0.841309f, 0.914062f, 0.947266f, 0.963379f, 0.973145f, 0.979004f, 0.982910f, 0.985840f, 0.987793f, 0.989746f, 0.991211f, + 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, + 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000397f, 0.001559f, 0.003397f, 0.006058f, + 0.011177f, 0.020355f, 0.039307f, 0.083130f, 0.196777f, 0.452148f, 0.724121f, 0.862305f, 0.920410f, 0.949219f, 0.964355f, 0.973145f, + 0.979004f, 0.982910f, 0.985840f, 0.988770f, 0.989258f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.995605f, + 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000366f, 0.001097f, 0.002163f, 0.003523f, 0.006268f, 0.010941f, 0.017487f, 0.030930f, 0.058411f, 0.122925f, 0.281738f, 0.556152f, + 0.776367f, 0.881348f, 0.928223f, 0.951660f, 0.966309f, 0.973633f, 0.979492f, 0.983398f, 0.986328f, 0.988281f, 0.989746f, 0.991211f, + 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, + 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000728f, 0.001340f, 0.002533f, 0.003813f, 0.006081f, 0.009750f, 0.015419f, + 0.025177f, 0.044067f, 0.084473f, 0.179077f, 0.384033f, 0.649902f, 0.818848f, 0.897949f, 0.935547f, 0.956055f, 0.967285f, 0.975098f, + 0.980957f, 0.983887f, 0.986328f, 0.988281f, 0.990234f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, + 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000609f, 0.000854f, 0.001898f, + 0.002781f, 0.004246f, 0.006218f, 0.008835f, 0.013504f, 0.021362f, 0.035400f, 0.062347f, 0.121460f, 0.255127f, 0.495361f, 0.726562f, + 0.852539f, 0.912598f, 0.943359f, 0.959473f, 0.969238f, 0.976562f, 0.981445f, 0.984375f, 0.987305f, 0.988770f, 0.990234f, 0.991699f, + 0.992676f, 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, + 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000244f, 0.000244f, 0.000731f, 0.001295f, 0.002159f, 0.003092f, 0.004051f, 0.005836f, 0.008560f, 0.011925f, 0.018585f, 0.029373f, + 0.048950f, 0.088013f, 0.174194f, 0.354980f, 0.604492f, 0.788086f, 0.880371f, 0.925293f, 0.950195f, 0.963867f, 0.972168f, 0.978027f, + 0.982422f, 0.985840f, 0.987793f, 0.990234f, 0.991699f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, + 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000114f, 0.000244f, 0.000709f, 0.001089f, 0.001580f, 0.002100f, 0.002848f, 0.004028f, + 0.005646f, 0.008232f, 0.011276f, 0.016647f, 0.024948f, 0.039215f, 0.067566f, 0.125244f, 0.249878f, 0.471436f, 0.698242f, 0.834961f, + 0.902344f, 0.937012f, 0.955078f, 0.967773f, 0.974609f, 0.979492f, 0.983887f, 0.987305f, 0.988770f, 0.990723f, 0.991699f, 0.992676f, + 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, + 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000244f, 0.000480f, 0.001081f, + 0.001216f, 0.001684f, 0.002287f, 0.003113f, 0.004246f, 0.005711f, 0.007412f, 0.010658f, 0.014900f, 0.021408f, 0.033173f, 0.053711f, + 0.094299f, 0.179688f, 0.351807f, 0.591309f, 0.774902f, 0.871582f, 0.919922f, 0.946289f, 0.961426f, 0.971191f, 0.977051f, 0.981934f, + 0.984863f, 0.987305f, 0.989258f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, + 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000364f, 0.000366f, 0.000729f, 0.001195f, 0.001218f, 0.001693f, 0.002209f, 0.003038f, 0.004192f, 0.005249f, 0.006981f, + 0.009926f, 0.013405f, 0.019165f, 0.028473f, 0.044250f, 0.073975f, 0.134521f, 0.260010f, 0.476562f, 0.696289f, 0.830566f, 0.898438f, + 0.933594f, 0.954102f, 0.966309f, 0.974609f, 0.979492f, 0.982910f, 0.986328f, 0.988281f, 0.989746f, 0.991699f, 0.992676f, 0.993652f, + 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, + 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000226f, 0.000365f, 0.000488f, 0.000731f, 0.001090f, 0.001245f, 0.002028f, + 0.002169f, 0.003023f, 0.003952f, 0.005043f, 0.006790f, 0.009026f, 0.012276f, 0.016754f, 0.024628f, 0.037384f, 0.060120f, 0.104431f, + 0.196045f, 0.372803f, 0.604980f, 0.779785f, 0.872070f, 0.919922f, 0.945312f, 0.960938f, 0.970703f, 0.977539f, 0.980957f, 0.984863f, + 0.987305f, 0.989258f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, + 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000364f, 0.000487f, + 0.000488f, 0.000608f, 0.001092f, 0.001323f, 0.001909f, 0.002028f, 0.002829f, 0.003754f, 0.004940f, 0.006329f, 0.008850f, 0.011353f, + 0.015572f, 0.022110f, 0.032196f, 0.050293f, 0.083984f, 0.151978f, 0.288574f, 0.507812f, 0.715332f, 0.839844f, 0.902832f, 0.936035f, + 0.955566f, 0.966797f, 0.974609f, 0.979492f, 0.983887f, 0.986816f, 0.988281f, 0.989746f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, + 0.994629f, 0.995605f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000341f, 0.000486f, 0.000487f, 0.000591f, 0.000846f, 0.001213f, 0.001407f, 0.002018f, 0.002306f, 0.003119f, + 0.003736f, 0.004700f, 0.005936f, 0.007858f, 0.010498f, 0.013939f, 0.019913f, 0.028564f, 0.043060f, 0.069275f, 0.120972f, 0.225830f, + 0.416748f, 0.642090f, 0.798828f, 0.881836f, 0.924805f, 0.948730f, 0.962891f, 0.971191f, 0.978516f, 0.982422f, 0.985352f, 0.987793f, + 0.989746f, 0.991211f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, + 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000121f, 0.000122f, 0.000475f, 0.000486f, 0.000487f, 0.000714f, 0.000913f, + 0.001296f, 0.001350f, 0.001884f, 0.002163f, 0.002871f, 0.003702f, 0.004578f, 0.005573f, 0.007278f, 0.009819f, 0.013039f, 0.017883f, + 0.025589f, 0.037445f, 0.058655f, 0.099243f, 0.180542f, 0.338867f, 0.563965f, 0.751465f, 0.857422f, 0.912109f, 0.941406f, 0.958496f, + 0.968262f, 0.976074f, 0.980957f, 0.984375f, 0.986816f, 0.989258f, 0.990723f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, + 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000122f, 0.000242f, + 0.000417f, 0.000607f, 0.000602f, 0.000644f, 0.001016f, 0.001223f, 0.001337f, 0.002010f, 0.002087f, 0.002752f, 0.003380f, 0.004486f, + 0.005760f, 0.007523f, 0.009048f, 0.012169f, 0.016312f, 0.022949f, 0.033295f, 0.050812f, 0.082886f, 0.146851f, 0.275635f, 0.486572f, + 0.696777f, 0.828613f, 0.896484f, 0.933594f, 0.953613f, 0.965820f, 0.973633f, 0.979980f, 0.983887f, 0.986328f, 0.988770f, 0.990723f, + 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.997559f, + 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000262f, 0.000463f, 0.000603f, 0.000665f, 0.000716f, 0.001069f, 0.001322f, 0.001538f, + 0.001895f, 0.002293f, 0.003120f, 0.003323f, 0.004166f, 0.005638f, 0.006828f, 0.008942f, 0.011368f, 0.015465f, 0.021057f, 0.029663f, + 0.044861f, 0.070923f, 0.123169f, 0.228149f, 0.416504f, 0.640137f, 0.797363f, 0.880859f, 0.924805f, 0.948730f, 0.963379f, 0.971680f, + 0.978516f, 0.982422f, 0.985840f, 0.988281f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.996094f, + 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000120f, 0.000172f, 0.000243f, 0.000365f, 0.000475f, 0.000607f, + 0.000608f, 0.000609f, 0.001013f, 0.001424f, 0.001456f, 0.001904f, 0.002411f, 0.002903f, 0.003145f, 0.004314f, 0.004944f, 0.006607f, + 0.008156f, 0.010719f, 0.014297f, 0.018906f, 0.027069f, 0.040070f, 0.062103f, 0.104858f, 0.191162f, 0.355469f, 0.581543f, 0.762695f, + 0.863281f, 0.915039f, 0.943848f, 0.960449f, 0.970703f, 0.977051f, 0.981445f, 0.985840f, 0.987793f, 0.989746f, 0.991211f, 0.992676f, + 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.997070f, 0.997070f, 0.998047f, 0.997559f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000000f, 0.000000f, 0.000096f, + 0.000239f, 0.000241f, 0.000336f, 0.000482f, 0.000719f, 0.000729f, 0.000831f, 0.001049f, 0.001552f, 0.001576f, 0.001710f, 0.002373f, + 0.002846f, 0.003254f, 0.004051f, 0.005035f, 0.006405f, 0.007706f, 0.009987f, 0.013092f, 0.017715f, 0.024872f, 0.035980f, 0.055328f, + 0.091248f, 0.163330f, 0.305664f, 0.524902f, 0.726562f, 0.845215f, 0.906250f, 0.938965f, 0.957031f, 0.969238f, 0.976074f, 0.981445f, + 0.984863f, 0.987305f, 0.989258f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, + 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000000f, 0.000000f, 0.000000f, 0.000118f, 0.000120f, 0.000351f, 0.000364f, 0.000421f, 0.000480f, 0.000606f, 0.000728f, 0.000852f, + 0.001175f, 0.001535f, 0.001673f, 0.001671f, 0.002277f, 0.002743f, 0.003220f, 0.003922f, 0.004868f, 0.005951f, 0.007488f, 0.009430f, + 0.012527f, 0.016266f, 0.022964f, 0.033142f, 0.049805f, 0.080688f, 0.141846f, 0.265625f, 0.473145f, 0.688477f, 0.825684f, 0.897949f, + 0.934082f, 0.954102f, 0.966797f, 0.975098f, 0.980469f, 0.984375f, 0.987305f, 0.989258f, 0.991211f, 0.992676f, 0.993164f, 0.993652f, + 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999023f, + 0.999023f, 0.999023f, 0.999512f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000058f, 0.000235f, 0.000360f, 0.000243f, + 0.000440f, 0.000583f, 0.000847f, 0.000851f, 0.000852f, 0.001189f, 0.001411f, 0.001645f, 0.001898f, 0.002417f, 0.002617f, 0.003435f, + 0.003695f, 0.004616f, 0.005733f, 0.007278f, 0.009216f, 0.012016f, 0.015701f, 0.021561f, 0.030396f, 0.045746f, 0.073120f, 0.125732f, + 0.233521f, 0.428223f, 0.653320f, 0.807617f, 0.887695f, 0.929688f, 0.951660f, 0.965820f, 0.974121f, 0.980469f, 0.984375f, 0.986816f, + 0.989746f, 0.991211f, 0.992676f, 0.993164f, 0.994141f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, + 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000237f, 0.000237f, 0.000362f, 0.000365f, 0.000558f, 0.000814f, 0.000727f, 0.000729f, 0.000935f, 0.001189f, 0.001403f, + 0.001569f, 0.001989f, 0.002216f, 0.002533f, 0.003307f, 0.003906f, 0.004463f, 0.005646f, 0.006908f, 0.008980f, 0.011230f, 0.014755f, + 0.020020f, 0.028320f, 0.041931f, 0.065979f, 0.113098f, 0.209229f, 0.389648f, 0.620605f, 0.789551f, 0.879395f, 0.924805f, 0.950684f, + 0.964844f, 0.974121f, 0.979980f, 0.983398f, 0.987305f, 0.989258f, 0.991211f, 0.992676f, 0.993652f, 0.993652f, 0.995117f, 0.995605f, + 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000121f, 0.000241f, 0.000486f, 0.000575f, 0.000707f, + 0.000726f, 0.000971f, 0.000849f, 0.000966f, 0.001350f, 0.001660f, 0.001678f, 0.002224f, 0.002483f, 0.003197f, 0.003611f, 0.004200f, + 0.005318f, 0.006744f, 0.008476f, 0.010506f, 0.014145f, 0.019089f, 0.026627f, 0.039001f, 0.061096f, 0.103333f, 0.189819f, 0.358887f, + 0.591309f, 0.773438f, 0.872559f, 0.922363f, 0.948730f, 0.963867f, 0.973145f, 0.979492f, 0.983887f, 0.986816f, 0.989258f, 0.991211f, + 0.992188f, 0.993164f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000175f, 0.000361f, + 0.000481f, 0.000485f, 0.000364f, 0.000562f, 0.000703f, 0.000827f, 0.000842f, 0.000972f, 0.001172f, 0.001321f, 0.001675f, 0.001684f, + 0.002153f, 0.002455f, 0.003122f, 0.003391f, 0.004177f, 0.005314f, 0.006325f, 0.007896f, 0.010368f, 0.013527f, 0.018082f, 0.025162f, + 0.037140f, 0.057343f, 0.095886f, 0.175659f, 0.334473f, 0.567871f, 0.760742f, 0.866699f, 0.919922f, 0.947754f, 0.963379f, 0.972656f, + 0.979492f, 0.984375f, 0.987305f, 0.989258f, 0.991211f, 0.992676f, 0.993652f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.997070f, + 0.998047f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000325f, 0.000311f, 0.000243f, 0.000484f, 0.000486f, 0.000536f, 0.000698f, 0.000723f, 0.000844f, + 0.000972f, 0.001081f, 0.001312f, 0.001658f, 0.001914f, 0.001932f, 0.002390f, 0.003017f, 0.003668f, 0.004353f, 0.005199f, 0.006336f, + 0.007812f, 0.009972f, 0.012802f, 0.017029f, 0.024200f, 0.035034f, 0.053833f, 0.090027f, 0.164185f, 0.316162f, 0.549805f, 0.751465f, + 0.863281f, 0.918457f, 0.947266f, 0.963379f, 0.974121f, 0.979492f, 0.984375f, 0.987793f, 0.989746f, 0.991699f, 0.993164f, 0.994141f, + 0.995117f, 0.995605f, 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000231f, 0.000453f, 0.000480f, 0.000484f, + 0.000485f, 0.000486f, 0.000917f, 0.000963f, 0.000969f, 0.000970f, 0.001043f, 0.001288f, 0.001523f, 0.001684f, 0.001885f, 0.002464f, + 0.002531f, 0.003565f, 0.004124f, 0.004745f, 0.006077f, 0.007580f, 0.009605f, 0.012634f, 0.016953f, 0.023346f, 0.033386f, 0.051697f, + 0.085632f, 0.156250f, 0.303955f, 0.537598f, 0.746582f, 0.860840f, 0.918457f, 0.947754f, 0.963867f, 0.973633f, 0.979980f, 0.984863f, + 0.987793f, 0.990234f, 0.991699f, 0.993652f, 0.994141f, 0.995117f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000235f, 0.000239f, 0.000359f, 0.000484f, 0.000485f, 0.000486f, 0.000628f, 0.000957f, 0.000967f, 0.000969f, 0.001065f, + 0.001288f, 0.001602f, 0.001850f, 0.001995f, 0.002409f, 0.002523f, 0.003462f, 0.003838f, 0.004993f, 0.005917f, 0.007233f, 0.009338f, + 0.012230f, 0.015610f, 0.022415f, 0.032288f, 0.049805f, 0.082947f, 0.151489f, 0.296631f, 0.532715f, 0.745117f, 0.862793f, 0.919434f, + 0.948242f, 0.964844f, 0.974609f, 0.980957f, 0.985352f, 0.988281f, 0.990723f, 0.992676f, 0.994141f, 0.994629f, 0.995605f, 0.996094f, + 0.996582f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000187f, 0.000437f, 0.000473f, 0.000483f, 0.000485f, 0.000606f, + 0.000583f, 0.000711f, 0.000772f, 0.000968f, 0.001107f, 0.001287f, 0.001434f, 0.001662f, 0.001984f, 0.002449f, 0.002634f, 0.003145f, + 0.003777f, 0.004410f, 0.005722f, 0.007114f, 0.008926f, 0.011696f, 0.016006f, 0.021683f, 0.031342f, 0.048309f, 0.080750f, 0.149170f, + 0.294678f, 0.534668f, 0.749512f, 0.866211f, 0.922363f, 0.950684f, 0.966309f, 0.975586f, 0.981934f, 0.985840f, 0.989258f, 0.991699f, + 0.992676f, 0.994141f, 0.994629f, 0.996094f, 0.996582f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000247f, + 0.000238f, 0.000407f, 0.000482f, 0.000484f, 0.000604f, 0.000869f, 0.000909f, 0.000721f, 0.000955f, 0.001000f, 0.001241f, 0.001342f, + 0.001655f, 0.001721f, 0.002329f, 0.002623f, 0.003086f, 0.003677f, 0.004349f, 0.005600f, 0.006962f, 0.008835f, 0.011581f, 0.015274f, + 0.021286f, 0.030884f, 0.047760f, 0.079895f, 0.148926f, 0.298584f, 0.543945f, 0.758301f, 0.872559f, 0.925781f, 0.953125f, 0.967773f, + 0.977051f, 0.982910f, 0.986816f, 0.989258f, 0.991211f, 0.993164f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000237f, 0.000410f, 0.000472f, 0.000481f, 0.000483f, 0.000485f, 0.000687f, 0.000913f, + 0.000956f, 0.000966f, 0.000997f, 0.001341f, 0.001415f, 0.001813f, 0.002029f, 0.002043f, 0.002594f, 0.003210f, 0.003641f, 0.004734f, + 0.005356f, 0.006882f, 0.008675f, 0.011360f, 0.014816f, 0.020920f, 0.030380f, 0.047485f, 0.080200f, 0.151733f, 0.308105f, 0.561523f, + 0.772949f, 0.881348f, 0.931152f, 0.956055f, 0.969727f, 0.978516f, 0.983887f, 0.987793f, 0.990234f, 0.992188f, 0.993652f, 0.994629f, + 0.995605f, 0.996094f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000254f, 0.000345f, 0.000468f, + 0.000585f, 0.000482f, 0.000603f, 0.000485f, 0.000862f, 0.000928f, 0.000965f, 0.001174f, 0.001162f, 0.001405f, 0.001761f, 0.002016f, + 0.002182f, 0.002733f, 0.002831f, 0.003504f, 0.004456f, 0.005440f, 0.006775f, 0.008553f, 0.011055f, 0.014694f, 0.020859f, 0.030334f, + 0.047852f, 0.081970f, 0.157593f, 0.325439f, 0.586914f, 0.790527f, 0.890137f, 0.936523f, 0.959473f, 0.973145f, 0.980469f, 0.985352f, + 0.988770f, 0.990723f, 0.992676f, 0.994141f, 0.995117f, 0.996094f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000241f, 0.000237f, 0.000340f, 0.000457f, 0.000580f, 0.000481f, 0.000601f, 0.000605f, 0.000742f, 0.000951f, 0.000953f, + 0.001131f, 0.001257f, 0.001396f, 0.001730f, 0.001936f, 0.002102f, 0.002682f, 0.002762f, 0.003733f, 0.004425f, 0.005344f, 0.006516f, + 0.008354f, 0.010971f, 0.014793f, 0.020859f, 0.030640f, 0.048859f, 0.085144f, 0.167358f, 0.350586f, 0.620117f, 0.811035f, 0.900391f, + 0.942383f, 0.963379f, 0.975098f, 0.981934f, 0.986816f, 0.989746f, 0.992188f, 0.993164f, 0.994629f, 0.995117f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000131f, 0.000301f, 0.000430f, 0.000470f, 0.000593f, + 0.000571f, 0.000587f, 0.000693f, 0.000906f, 0.000959f, 0.000965f, 0.001094f, 0.001364f, 0.001522f, 0.001783f, 0.002094f, 0.002615f, + 0.003038f, 0.003365f, 0.004307f, 0.005135f, 0.006493f, 0.008347f, 0.011055f, 0.014824f, 0.020844f, 0.031204f, 0.050507f, 0.090027f, + 0.182129f, 0.385498f, 0.659668f, 0.834473f, 0.913086f, 0.949219f, 0.967285f, 0.978027f, 0.983887f, 0.987793f, 0.991211f, 0.992188f, + 0.994141f, 0.995117f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000189f, 0.000122f, 0.000122f, + 0.000241f, 0.000295f, 0.000425f, 0.000457f, 0.000592f, 0.000481f, 0.000603f, 0.000697f, 0.000926f, 0.000943f, 0.000960f, 0.001022f, + 0.001435f, 0.001632f, 0.001658f, 0.002024f, 0.002468f, 0.003010f, 0.003210f, 0.004124f, 0.005219f, 0.006351f, 0.008163f, 0.010933f, + 0.015030f, 0.021271f, 0.032257f, 0.053009f, 0.097534f, 0.203003f, 0.432373f, 0.704102f, 0.858887f, 0.924805f, 0.955566f, 0.970703f, + 0.979492f, 0.985840f, 0.989258f, 0.991699f, 0.993164f, 0.995117f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000214f, 0.000201f, 0.000239f, 0.000241f, 0.000383f, 0.000461f, 0.000474f, 0.000479f, 0.000598f, + 0.000736f, 0.000905f, 0.000947f, 0.001072f, 0.001180f, 0.001376f, 0.001572f, 0.001752f, 0.001900f, 0.002258f, 0.002792f, 0.003487f, + 0.004055f, 0.005161f, 0.006424f, 0.008209f, 0.010933f, 0.015030f, 0.021942f, 0.033630f, 0.056671f, 0.107666f, 0.233276f, 0.492188f, + 0.752441f, 0.881836f, 0.937012f, 0.961914f, 0.975098f, 0.982910f, 0.987305f, 0.990234f, 0.992676f, 0.994629f, 0.998535f, 0.998535f, + 0.998535f, 0.998047f, 0.998535f, 0.998535f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000132f, 0.000224f, 0.000129f, 0.000237f, 0.000240f, + 0.000337f, 0.000430f, 0.000468f, 0.000579f, 0.000593f, 0.000602f, 0.000881f, 0.000936f, 0.000956f, 0.000963f, 0.001282f, 0.001519f, + 0.001607f, 0.001852f, 0.002150f, 0.002737f, 0.003508f, 0.003990f, 0.005077f, 0.006516f, 0.008179f, 0.011185f, 0.015511f, 0.022446f, + 0.035614f, 0.061859f, 0.122681f, 0.275879f, 0.563965f, 0.798828f, 0.903809f, 0.946777f, 0.967773f, 0.978516f, 0.984863f, 0.988770f, + 0.991699f, 0.993652f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000149f, 0.000122f, 0.000207f, 0.000371f, 0.000430f, 0.000573f, 0.000591f, 0.000598f, 0.000597f, 0.000804f, + 0.000901f, 0.000948f, 0.001053f, 0.001083f, 0.001376f, 0.001584f, 0.001878f, 0.002331f, 0.002529f, 0.003376f, 0.003944f, 0.005230f, + 0.006504f, 0.008537f, 0.011459f, 0.015747f, 0.024002f, 0.038361f, 0.069458f, 0.144409f, 0.336914f, 0.644043f, 0.841797f, 0.922363f, + 0.957520f, 0.972656f, 0.981934f, 0.987305f, 0.990234f, 0.993164f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000230f, 0.000234f, 0.000235f, 0.000268f, 0.000400f, + 0.000448f, 0.000585f, 0.000590f, 0.000599f, 0.000641f, 0.000788f, 0.000930f, 0.000968f, 0.001107f, 0.001251f, 0.001656f, 0.001701f, + 0.002047f, 0.002691f, 0.003437f, 0.003998f, 0.004829f, 0.006329f, 0.008492f, 0.011757f, 0.016525f, 0.025345f, 0.042297f, 0.080200f, + 0.177490f, 0.420654f, 0.724121f, 0.878906f, 0.938965f, 0.964355f, 0.977539f, 0.984863f, 0.989746f, 0.992188f, 0.997559f, 0.997559f, + 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000214f, 0.000235f, 0.000228f, 0.000240f, 0.000429f, 0.000439f, 0.000574f, 0.000654f, 0.000583f, 0.000493f, 0.000788f, 0.000813f, + 0.000947f, 0.001062f, 0.001225f, 0.001569f, 0.001721f, 0.002048f, 0.002844f, 0.002979f, 0.003902f, 0.004997f, 0.006454f, 0.008698f, + 0.012192f, 0.018143f, 0.027634f, 0.047913f, 0.095886f, 0.228394f, 0.526855f, 0.796875f, 0.910156f, 0.953125f, 0.973145f, 0.982422f, + 0.987793f, 0.991699f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000205f, 0.000236f, 0.000232f, 0.000299f, 0.000446f, 0.000417f, + 0.000466f, 0.000580f, 0.000508f, 0.000710f, 0.000800f, 0.000940f, 0.000954f, 0.001228f, 0.001496f, 0.001631f, 0.002043f, 0.002798f, + 0.003359f, 0.004139f, 0.004951f, 0.006680f, 0.008995f, 0.012764f, 0.018860f, 0.030823f, 0.056061f, 0.120911f, 0.307617f, 0.645508f, + 0.855957f, 0.934082f, 0.964355f, 0.978516f, 0.985840f, 0.990234f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000226f, + 0.000122f, 0.000226f, 0.000373f, 0.000272f, 0.000325f, 0.000460f, 0.000471f, 0.000477f, 0.000673f, 0.000877f, 0.000929f, 0.000951f, + 0.001129f, 0.001446f, 0.001614f, 0.002096f, 0.002619f, 0.002939f, 0.003941f, 0.005363f, 0.006844f, 0.009491f, 0.013596f, 0.020905f, + 0.035370f, 0.068420f, 0.161743f, 0.426270f, 0.755859f, 0.900879f, 0.952148f, 0.973145f, 0.983398f, 0.989746f, 0.997070f, 0.997070f, + 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000111f, 0.000236f, 0.000297f, 0.000368f, 0.000449f, 0.000467f, + 0.000588f, 0.000641f, 0.000813f, 0.000924f, 0.001035f, 0.001124f, 0.001348f, 0.001764f, 0.001922f, 0.002439f, 0.003160f, 0.004005f, + 0.005280f, 0.007107f, 0.010109f, 0.014748f, 0.023148f, 0.041595f, 0.088440f, 0.232910f, 0.578125f, 0.841797f, 0.933594f, 0.965820f, + 0.980469f, 0.987305f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000014f, 0.000011f, 0.000116f, + 0.000148f, 0.000128f, 0.000369f, 0.000418f, 0.000563f, 0.000470f, 0.000592f, 0.000776f, 0.000901f, 0.000937f, 0.001112f, 0.001348f, + 0.001743f, 0.001904f, 0.002470f, 0.003187f, 0.003986f, 0.005360f, 0.007557f, 0.010674f, 0.016068f, 0.026871f, 0.051666f, 0.122925f, + 0.356445f, 0.729492f, 0.901855f, 0.955078f, 0.976074f, 0.985840f, 0.996094f, 0.996582f, 0.996094f, 0.996582f, 0.996094f, 0.996582f, + 0.000122f, 0.000122f, 0.000121f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000028f, 0.000019f, 0.000014f, 0.000011f, 0.000033f, 0.000118f, 0.000247f, 0.000305f, 0.000412f, 0.000447f, 0.000576f, 0.000587f, + 0.000693f, 0.000850f, 0.000949f, 0.001083f, 0.001319f, 0.001557f, 0.001957f, 0.002424f, 0.003340f, 0.004417f, 0.005688f, 0.007774f, + 0.011497f, 0.017731f, 0.032257f, 0.068604f, 0.189575f, 0.541992f, 0.843262f, 0.938477f, 0.970703f, 0.983887f, 0.995605f, 0.996094f, + 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000121f, 0.000118f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000067f, 0.000042f, 0.000028f, 0.000020f, 0.000015f, 0.000066f, 0.000009f, 0.000101f, 0.000118f, + 0.000260f, 0.000358f, 0.000520f, 0.000456f, 0.000563f, 0.000711f, 0.000872f, 0.000980f, 0.001059f, 0.001309f, 0.001699f, 0.002066f, + 0.002708f, 0.003248f, 0.004166f, 0.005836f, 0.008224f, 0.012619f, 0.021484f, 0.041260f, 0.101074f, 0.323486f, 0.733887f, 0.912109f, + 0.962402f, 0.980957f, 0.995117f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000000f, 0.000000f, 0.000119f, 0.000119f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000105f, 0.000067f, 0.000042f, 0.000029f, 0.000022f, + 0.000015f, 0.000011f, 0.000040f, 0.000033f, 0.000153f, 0.000204f, 0.000313f, 0.000501f, 0.000554f, 0.000575f, 0.000585f, 0.000778f, + 0.000925f, 0.000980f, 0.001245f, 0.001634f, 0.001989f, 0.002413f, 0.003433f, 0.004028f, 0.005989f, 0.008911f, 0.014374f, 0.026443f, + 0.057495f, 0.170166f, 0.549805f, 0.864746f, 0.951172f, 0.977051f, 0.994629f, 0.994629f, 0.994629f, 0.994629f, 0.995605f, 0.994629f, + 0.000000f, 0.000046f, 0.000088f, 0.000118f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000108f, 0.000069f, 0.000047f, 0.000030f, 0.000022f, 0.000016f, 0.000012f, 0.000052f, 0.000081f, 0.000100f, 0.000184f, 0.000226f, + 0.000400f, 0.000467f, 0.000452f, 0.000597f, 0.000807f, 0.000895f, 0.000942f, 0.001219f, 0.001611f, 0.002022f, 0.002352f, 0.003222f, + 0.004177f, 0.006481f, 0.009850f, 0.017517f, 0.034668f, 0.090637f, 0.331055f, 0.776367f, 0.932129f, 0.972656f, 0.994141f, 0.994141f, + 0.994629f, 0.994141f, 0.994629f, 0.994629f, 0.000000f, 0.000000f, 0.000000f, 0.000107f, 0.000115f, 0.000112f, 0.000119f, 0.000118f, + 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000117f, 0.000072f, 0.000049f, 0.000032f, 0.000023f, 0.000017f, 0.000013f, + 0.000011f, 0.000008f, 0.000075f, 0.000151f, 0.000207f, 0.000305f, 0.000509f, 0.000499f, 0.000560f, 0.000704f, 0.000863f, 0.000917f, + 0.001220f, 0.001505f, 0.001740f, 0.002174f, 0.003153f, 0.004559f, 0.007095f, 0.011826f, 0.022247f, 0.051147f, 0.173462f, 0.618652f, + 0.902344f, 0.966309f, 0.993164f, 0.993652f, 0.992676f, 0.992676f, 0.993164f, 0.993164f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000060f, 0.000102f, 0.000113f, 0.000117f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000120f, + 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000078f, + 0.000052f, 0.000038f, 0.000027f, 0.000019f, 0.000015f, 0.000011f, 0.000054f, 0.000007f, 0.000085f, 0.000108f, 0.000258f, 0.000466f, + 0.000533f, 0.000560f, 0.000662f, 0.000849f, 0.000856f, 0.000965f, 0.001180f, 0.001678f, 0.002075f, 0.003193f, 0.005016f, 0.008095f, + 0.014343f, 0.030899f, 0.090820f, 0.401367f, 0.848145f, 0.956543f, 0.992188f, 0.992188f, 0.992188f, 0.992676f, 0.991699f, 0.992188f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000059f, 0.000096f, 0.000107f, 0.000112f, 0.000115f, 0.000116f, + 0.000117f, 0.000118f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, + 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000088f, 0.000059f, 0.000041f, 0.000031f, 0.000022f, 0.000017f, 0.000013f, 0.000010f, + 0.000056f, 0.000091f, 0.000183f, 0.000201f, 0.000309f, 0.000506f, 0.000547f, 0.000525f, 0.000629f, 0.000613f, 0.000817f, 0.001012f, + 0.001640f, 0.002420f, 0.003588f, 0.005520f, 0.009453f, 0.019119f, 0.050415f, 0.214722f, 0.751465f, 0.943848f, 0.990723f, 0.990723f, + 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000055f, 0.000095f, 0.000103f, 0.000105f, 0.000112f, 0.000114f, 0.000115f, 0.000117f, 0.000117f, 0.000117f, 0.000118f, + 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, 0.000105f, 0.000069f, 0.000048f, + 0.000035f, 0.000025f, 0.000019f, 0.000015f, 0.000011f, 0.000014f, 0.000008f, 0.000071f, 0.000193f, 0.000311f, 0.000315f, 0.000524f, + 0.000483f, 0.000558f, 0.000591f, 0.000705f, 0.000950f, 0.001389f, 0.002428f, 0.003494f, 0.006321f, 0.012306f, 0.029480f, 0.108948f, + 0.581543f, 0.924316f, 0.989746f, 0.989746f, 0.989258f, 0.989746f, 0.989258f, 0.989746f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000069f, 0.000096f, 0.000103f, 0.000107f, + 0.000109f, 0.000112f, 0.000113f, 0.000115f, 0.000115f, 0.000116f, 0.000117f, 0.000117f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, + 0.000119f, 0.000119f, 0.000119f, 0.000084f, 0.000061f, 0.000042f, 0.000031f, 0.000023f, 0.000018f, 0.000014f, 0.000011f, 0.000009f, + 0.000095f, 0.000127f, 0.000223f, 0.000402f, 0.000432f, 0.000399f, 0.000494f, 0.000535f, 0.000557f, 0.000933f, 0.001474f, 0.002300f, + 0.004192f, 0.007919f, 0.017838f, 0.057068f, 0.360840f, 0.890625f, 0.986816f, 0.987793f, 0.987305f, 0.987305f, 0.987793f, 0.987305f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000035f, 0.000041f, 0.000088f, 0.000098f, 0.000103f, 0.000106f, 0.000110f, 0.000110f, 0.000113f, 0.000113f, + 0.000115f, 0.000116f, 0.000116f, 0.000117f, 0.000117f, 0.000117f, 0.000117f, 0.000118f, 0.000111f, 0.000074f, 0.000053f, 0.000038f, + 0.000029f, 0.000022f, 0.000016f, 0.000013f, 0.000010f, 0.000008f, 0.000073f, 0.000152f, 0.000296f, 0.000369f, 0.000365f, 0.000437f, + 0.000507f, 0.000661f, 0.000876f, 0.001451f, 0.002531f, 0.004898f, 0.010384f, 0.031113f, 0.183838f, 0.833008f, 0.984375f, 0.984863f, + 0.984863f, 0.984375f, 0.984863f, 0.984863f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000024f, 0.000044f, 0.000073f, + 0.000087f, 0.000097f, 0.000102f, 0.000105f, 0.000108f, 0.000110f, 0.000111f, 0.000113f, 0.000114f, 0.000114f, 0.000115f, 0.000115f, + 0.000116f, 0.000116f, 0.000101f, 0.000070f, 0.000052f, 0.000037f, 0.000027f, 0.000021f, 0.000016f, 0.000013f, 0.000010f, 0.000008f, + 0.000083f, 0.000183f, 0.000352f, 0.000355f, 0.000362f, 0.000365f, 0.000528f, 0.000790f, 0.001469f, 0.003029f, 0.005970f, 0.017242f, + 0.089050f, 0.728516f, 0.980957f, 0.981445f, 0.981445f, 0.980957f, 0.980957f, 0.981445f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000033f, 0.000041f, 0.000073f, 0.000083f, 0.000088f, 0.000097f, 0.000102f, + 0.000105f, 0.000108f, 0.000108f, 0.000111f, 0.000112f, 0.000113f, 0.000113f, 0.000114f, 0.000097f, 0.000068f, 0.000049f, 0.000038f, + 0.000028f, 0.000021f, 0.000016f, 0.000013f, 0.000010f, 0.000056f, 0.000151f, 0.000243f, 0.000264f, 0.000221f, 0.000328f, 0.000449f, + 0.000850f, 0.001612f, 0.003340f, 0.009361f, 0.043121f, 0.548340f, 0.976074f, 0.976562f, 0.975586f, 0.976074f, 0.976074f, 0.976562f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000019f, 0.000052f, 0.000065f, 0.000077f, 0.000088f, 0.000094f, 0.000098f, 0.000100f, 0.000104f, 0.000106f, 0.000108f, + 0.000109f, 0.000110f, 0.000095f, 0.000069f, 0.000052f, 0.000037f, 0.000028f, 0.000021f, 0.000017f, 0.000013f, 0.000025f, 0.000063f, + 0.000195f, 0.000233f, 0.000205f, 0.000264f, 0.000401f, 0.000789f, 0.001532f, 0.004520f, 0.020844f, 0.321289f, 0.969238f, 0.968750f, + 0.969238f, 0.968750f, 0.969238f, 0.969238f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000018f, 0.000039f, 0.000053f, + 0.000066f, 0.000079f, 0.000086f, 0.000090f, 0.000096f, 0.000100f, 0.000102f, 0.000105f, 0.000098f, 0.000074f, 0.000053f, 0.000041f, + 0.000031f, 0.000023f, 0.000017f, 0.000013f, 0.000028f, 0.000139f, 0.000189f, 0.000179f, 0.000219f, 0.000333f, 0.000840f, 0.002119f, + 0.009193f, 0.144775f, 0.958496f, 0.958496f, 0.958008f, 0.958496f, 0.958008f, 0.958008f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000025f, 0.000040f, 0.000052f, 0.000067f, 0.000077f, 0.000082f, + 0.000089f, 0.000093f, 0.000097f, 0.000079f, 0.000059f, 0.000044f, 0.000033f, 0.000024f, 0.000018f, 0.000014f, 0.000034f, 0.000084f, + 0.000157f, 0.000199f, 0.000309f, 0.000817f, 0.003424f, 0.054901f, 0.940918f, 0.940918f, 0.940918f, 0.940918f, 0.941406f, 0.940430f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000021f, 0.000040f, 0.000054f, 0.000063f, 0.000072f, 0.000078f, 0.000085f, 0.000065f, 0.000049f, + 0.000036f, 0.000026f, 0.000019f, 0.000014f, 0.000042f, 0.000114f, 0.000122f, 0.000276f, 0.001024f, 0.016357f, 0.912109f, 0.912598f, + 0.911621f, 0.912598f, 0.911621f, 0.913086f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000016f, 0.000032f, 0.000045f, 0.000056f, 0.000065f, 0.000054f, 0.000039f, 0.000028f, 0.000019f, 0.000013f, 0.000049f, 0.000079f, + 0.000226f, 0.003199f, 0.860840f, 0.859863f, 0.860352f, 0.860840f, 0.860840f, 0.860352f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000021f, 0.000035f, + 0.000040f, 0.000027f, 0.000018f, 0.000013f, 0.000033f, 0.000333f, 0.764160f, 0.765137f, 0.764648f, 0.764648f, 0.764648f, 0.765137f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000011f, 0.000009f, 0.600586f, 0.602051f, + 0.602051f, 0.601562f, 0.601074f, 0.601074f, + }, + { + 0.142456f, 0.713867f, 0.883789f, 0.933105f, 0.953613f, 0.964844f, 0.972168f, 0.977539f, 0.980957f, 0.983398f, 0.985352f, 0.987305f, + 0.989258f, 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, + 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, + 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.012886f, 0.087646f, 0.360840f, 0.709473f, 0.859863f, 0.916992f, 0.943848f, 0.958496f, + 0.967773f, 0.973633f, 0.978516f, 0.980957f, 0.984375f, 0.986328f, 0.987793f, 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, + 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, + 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.003895f, 0.020126f, 0.063599f, 0.188721f, + 0.464844f, 0.727539f, 0.853027f, 0.909668f, 0.938477f, 0.954590f, 0.965332f, 0.971680f, 0.976562f, 0.979980f, 0.982910f, 0.985840f, + 0.986816f, 0.988770f, 0.990234f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, + 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, + 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.002062f, 0.008438f, 0.021774f, 0.049713f, 0.117676f, 0.279541f, 0.541016f, 0.751465f, 0.855469f, 0.909180f, 0.936035f, 0.952637f, + 0.963379f, 0.970703f, 0.975098f, 0.979492f, 0.982910f, 0.984863f, 0.986328f, 0.987793f, 0.989258f, 0.990234f, 0.990723f, 0.992188f, + 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, + 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.001335f, 0.004597f, 0.010628f, 0.020844f, 0.040283f, 0.082764f, 0.177612f, 0.366211f, + 0.605469f, 0.773926f, 0.863281f, 0.910156f, 0.936035f, 0.952148f, 0.962402f, 0.969727f, 0.975098f, 0.979004f, 0.982422f, 0.984863f, + 0.986328f, 0.988281f, 0.988770f, 0.989746f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, + 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, + 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000851f, 0.002769f, 0.006130f, 0.010994f, + 0.019394f, 0.034943f, 0.063293f, 0.122253f, 0.244019f, 0.448242f, 0.660156f, 0.798828f, 0.872559f, 0.914062f, 0.937988f, 0.954102f, + 0.961914f, 0.970215f, 0.974609f, 0.978516f, 0.981934f, 0.984375f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.991211f, 0.991699f, + 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, + 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000466f, 0.001933f, 0.003809f, 0.007095f, 0.011353f, 0.018204f, 0.030029f, 0.050568f, 0.090759f, 0.170898f, 0.318848f, 0.526367f, + 0.708496f, 0.820801f, 0.884277f, 0.918457f, 0.940918f, 0.954102f, 0.963867f, 0.970215f, 0.975098f, 0.978516f, 0.981934f, 0.984863f, + 0.986328f, 0.988281f, 0.988770f, 0.990234f, 0.991211f, 0.991699f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.994629f, 0.995605f, + 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000487f, 0.001685f, 0.002766f, 0.004467f, 0.007305f, 0.011215f, 0.017136f, 0.026489f, + 0.042419f, 0.071716f, 0.125244f, 0.228271f, 0.399658f, 0.599609f, 0.751953f, 0.842773f, 0.894531f, 0.924805f, 0.943359f, 0.955566f, + 0.965820f, 0.971191f, 0.976562f, 0.979980f, 0.981934f, 0.984863f, 0.986816f, 0.988281f, 0.989258f, 0.990723f, 0.991211f, 0.992188f, + 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, + 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000965f, 0.002024f, 0.003202f, + 0.005009f, 0.007050f, 0.011070f, 0.015869f, 0.023987f, 0.036835f, 0.058563f, 0.097168f, 0.169800f, 0.297852f, 0.484131f, 0.664062f, + 0.789062f, 0.861816f, 0.905273f, 0.930176f, 0.947266f, 0.958984f, 0.967285f, 0.972168f, 0.976562f, 0.980469f, 0.982910f, 0.984863f, + 0.986816f, 0.988770f, 0.989746f, 0.990723f, 0.992188f, 0.992188f, 0.993652f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, + 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000244f, 0.000974f, 0.001576f, 0.002403f, 0.003510f, 0.005344f, 0.007332f, 0.010567f, 0.015099f, 0.022064f, 0.032104f, 0.048706f, + 0.078003f, 0.130249f, 0.224243f, 0.378174f, 0.566406f, 0.720703f, 0.820312f, 0.879883f, 0.915039f, 0.936523f, 0.951660f, 0.961426f, + 0.968262f, 0.974121f, 0.978027f, 0.980957f, 0.983887f, 0.985840f, 0.987793f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, + 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, + 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000240f, 0.000609f, 0.001096f, 0.001580f, 0.002674f, 0.004131f, 0.005245f, 0.007660f, + 0.010757f, 0.014221f, 0.019775f, 0.028381f, 0.041870f, 0.064697f, 0.103638f, 0.173706f, 0.293945f, 0.466553f, 0.642090f, 0.769531f, + 0.849121f, 0.895996f, 0.924316f, 0.942871f, 0.956055f, 0.963867f, 0.970703f, 0.975098f, 0.979004f, 0.981934f, 0.984863f, 0.986328f, + 0.988770f, 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, + 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000000f, 0.000608f, 0.001062f, 0.001268f, + 0.002001f, 0.003099f, 0.003937f, 0.005379f, 0.007595f, 0.010078f, 0.013176f, 0.018524f, 0.025787f, 0.036896f, 0.054932f, 0.085327f, + 0.137573f, 0.229980f, 0.376953f, 0.555664f, 0.708984f, 0.810547f, 0.873047f, 0.909180f, 0.933594f, 0.948730f, 0.959961f, 0.967285f, + 0.973145f, 0.977539f, 0.980469f, 0.983398f, 0.985840f, 0.986816f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, + 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, + 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000244f, 0.000606f, 0.000609f, 0.001317f, 0.001564f, 0.002674f, 0.003273f, 0.004402f, 0.005630f, 0.007141f, 0.009514f, 0.012398f, + 0.016678f, 0.023331f, 0.032776f, 0.047363f, 0.071594f, 0.112610f, 0.183960f, 0.303711f, 0.470215f, 0.639648f, 0.766113f, 0.844727f, + 0.892090f, 0.921875f, 0.941895f, 0.954590f, 0.963379f, 0.970215f, 0.975098f, 0.979004f, 0.981934f, 0.984863f, 0.986328f, 0.987793f, + 0.989746f, 0.991211f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996094f, + 0.996582f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000244f, 0.000727f, 0.000803f, 0.001575f, 0.002035f, 0.002821f, 0.003527f, + 0.004475f, 0.005421f, 0.007023f, 0.009491f, 0.011879f, 0.015976f, 0.021530f, 0.029587f, 0.041809f, 0.061737f, 0.094360f, 0.150146f, + 0.246460f, 0.393066f, 0.566406f, 0.712891f, 0.812500f, 0.872070f, 0.909180f, 0.933105f, 0.948242f, 0.959961f, 0.967773f, 0.972656f, + 0.977539f, 0.980957f, 0.982910f, 0.986328f, 0.987305f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, + 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000244f, 0.000244f, 0.000471f, 0.000727f, + 0.000967f, 0.001572f, 0.002161f, 0.002680f, 0.003246f, 0.004337f, 0.005241f, 0.006950f, 0.009087f, 0.011497f, 0.015038f, 0.019913f, + 0.026688f, 0.037537f, 0.054352f, 0.080383f, 0.125122f, 0.202515f, 0.327148f, 0.493652f, 0.656250f, 0.774414f, 0.849609f, 0.895508f, + 0.923828f, 0.942383f, 0.954590f, 0.963867f, 0.971191f, 0.975586f, 0.979004f, 0.982422f, 0.984863f, 0.987305f, 0.988281f, 0.989746f, + 0.990723f, 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, + 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999023f, + 0.000121f, 0.000244f, 0.000244f, 0.000715f, 0.001089f, 0.001278f, 0.001781f, 0.002275f, 0.002548f, 0.003334f, 0.004150f, 0.005314f, + 0.006824f, 0.008430f, 0.011200f, 0.014145f, 0.018631f, 0.024750f, 0.033905f, 0.047760f, 0.069885f, 0.106445f, 0.169312f, 0.273682f, + 0.426270f, 0.596191f, 0.732422f, 0.823242f, 0.879883f, 0.914062f, 0.936035f, 0.950684f, 0.960938f, 0.968750f, 0.973633f, 0.978516f, + 0.981934f, 0.984375f, 0.986328f, 0.988281f, 0.989258f, 0.990234f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, + 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999512f, + 0.999023f, 0.999512f, 0.999512f, 0.999023f, 0.000241f, 0.000244f, 0.000365f, 0.000600f, 0.000961f, 0.000972f, 0.001621f, 0.001697f, + 0.002274f, 0.002684f, 0.003359f, 0.004238f, 0.005573f, 0.006691f, 0.008057f, 0.010529f, 0.013832f, 0.017593f, 0.022812f, 0.031174f, + 0.042786f, 0.061462f, 0.092407f, 0.143799f, 0.231201f, 0.366943f, 0.535645f, 0.688477f, 0.794922f, 0.861816f, 0.902832f, 0.928711f, + 0.945801f, 0.957520f, 0.966797f, 0.972656f, 0.976562f, 0.980469f, 0.983398f, 0.985840f, 0.987793f, 0.989258f, 0.990234f, 0.991699f, + 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, + 0.998047f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000243f, 0.000365f, 0.000365f, + 0.000798f, 0.000968f, 0.001249f, 0.001528f, 0.001798f, 0.002457f, 0.002798f, 0.003494f, 0.004353f, 0.005306f, 0.006363f, 0.008141f, + 0.010147f, 0.012596f, 0.016006f, 0.021423f, 0.028503f, 0.039185f, 0.055420f, 0.081116f, 0.124390f, 0.198120f, 0.316895f, 0.478516f, + 0.641113f, 0.763672f, 0.842773f, 0.891113f, 0.921387f, 0.941406f, 0.954590f, 0.963867f, 0.970215f, 0.975586f, 0.979492f, 0.982910f, + 0.985352f, 0.987305f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, + 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000238f, 0.000365f, 0.000365f, 0.000598f, 0.000820f, 0.001200f, 0.001279f, 0.001631f, 0.001736f, 0.002172f, 0.002874f, + 0.003576f, 0.004391f, 0.005096f, 0.006176f, 0.007545f, 0.009674f, 0.012505f, 0.015945f, 0.020187f, 0.026550f, 0.035706f, 0.049835f, + 0.072510f, 0.109253f, 0.171631f, 0.275391f, 0.426514f, 0.594238f, 0.730469f, 0.822754f, 0.877930f, 0.913574f, 0.936523f, 0.951172f, + 0.961426f, 0.969727f, 0.974609f, 0.978027f, 0.982422f, 0.984863f, 0.986816f, 0.988770f, 0.989746f, 0.991699f, 0.992188f, 0.993164f, + 0.993652f, 0.994629f, 0.994629f, 0.995117f, 0.996094f, 0.996094f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000364f, 0.000486f, 0.000487f, 0.000562f, 0.000822f, 0.000967f, + 0.001213f, 0.001871f, 0.001803f, 0.002485f, 0.002796f, 0.003410f, 0.004242f, 0.005070f, 0.006153f, 0.007698f, 0.009262f, 0.011635f, + 0.014709f, 0.019104f, 0.024521f, 0.033295f, 0.045746f, 0.065674f, 0.096741f, 0.150635f, 0.241455f, 0.380127f, 0.548828f, 0.698242f, + 0.802246f, 0.867188f, 0.906738f, 0.931152f, 0.948242f, 0.959473f, 0.967285f, 0.973633f, 0.978516f, 0.981445f, 0.984375f, 0.986328f, + 0.988281f, 0.989258f, 0.990723f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.996582f, + 0.997559f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000350f, 0.000483f, + 0.000486f, 0.000604f, 0.000743f, 0.001093f, 0.001187f, 0.001297f, 0.001601f, 0.001921f, 0.002501f, 0.002922f, 0.003296f, 0.004200f, + 0.005211f, 0.006054f, 0.007603f, 0.008904f, 0.011169f, 0.014091f, 0.017685f, 0.023331f, 0.030991f, 0.042358f, 0.059326f, 0.087646f, + 0.134521f, 0.213867f, 0.341309f, 0.506348f, 0.665039f, 0.780762f, 0.854492f, 0.899414f, 0.927246f, 0.945312f, 0.957520f, 0.966309f, + 0.973145f, 0.977539f, 0.981445f, 0.984375f, 0.986328f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, + 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000000f, 0.000120f, 0.000360f, 0.000485f, 0.000486f, 0.000487f, 0.000604f, 0.000947f, 0.001201f, 0.001374f, 0.001715f, + 0.002127f, 0.002239f, 0.002876f, 0.003426f, 0.004063f, 0.005276f, 0.005810f, 0.006744f, 0.008713f, 0.010597f, 0.013680f, 0.016754f, + 0.021744f, 0.028778f, 0.039093f, 0.054901f, 0.079956f, 0.121399f, 0.191895f, 0.307861f, 0.468262f, 0.633301f, 0.760742f, 0.842285f, + 0.892090f, 0.923340f, 0.942383f, 0.956543f, 0.965332f, 0.972168f, 0.977539f, 0.980469f, 0.983887f, 0.985840f, 0.988281f, 0.989746f, + 0.990723f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000121f, 0.000219f, 0.000474f, 0.000484f, 0.000486f, 0.000487f, + 0.000720f, 0.001108f, 0.001199f, 0.001209f, 0.001689f, 0.002253f, 0.002489f, 0.002916f, 0.003714f, 0.004040f, 0.005054f, 0.006001f, + 0.006737f, 0.008713f, 0.010376f, 0.012665f, 0.016251f, 0.020615f, 0.027145f, 0.036499f, 0.050720f, 0.073181f, 0.110474f, 0.174072f, + 0.280518f, 0.434570f, 0.604980f, 0.742188f, 0.830566f, 0.885742f, 0.918945f, 0.940918f, 0.954102f, 0.964355f, 0.971680f, 0.977051f, + 0.980957f, 0.984375f, 0.986816f, 0.988281f, 0.989746f, 0.990723f, 0.992188f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, + 0.996582f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000000f, 0.000120f, 0.000239f, + 0.000319f, 0.000475f, 0.000484f, 0.000485f, 0.000618f, 0.000844f, 0.001094f, 0.001201f, 0.001570f, 0.001782f, 0.002010f, 0.002407f, + 0.003046f, 0.003099f, 0.004208f, 0.004700f, 0.005882f, 0.006878f, 0.007980f, 0.009949f, 0.012344f, 0.015358f, 0.019821f, 0.026047f, + 0.034271f, 0.047455f, 0.067993f, 0.102112f, 0.160034f, 0.258057f, 0.406494f, 0.578613f, 0.723633f, 0.820312f, 0.880371f, 0.916016f, + 0.938965f, 0.953125f, 0.963867f, 0.971191f, 0.976562f, 0.980469f, 0.983887f, 0.985840f, 0.988770f, 0.989746f, 0.991699f, 0.992676f, + 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.999023f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000242f, 0.000455f, 0.000481f, 0.000583f, 0.000601f, 0.000804f, 0.000912f, 0.001247f, + 0.001319f, 0.001571f, 0.001793f, 0.002337f, 0.002464f, 0.003099f, 0.003164f, 0.003809f, 0.004627f, 0.005764f, 0.006397f, 0.008118f, + 0.009605f, 0.011917f, 0.015083f, 0.018692f, 0.024384f, 0.032806f, 0.044983f, 0.063477f, 0.095337f, 0.148560f, 0.240112f, 0.382324f, + 0.556641f, 0.708984f, 0.812500f, 0.875488f, 0.913574f, 0.937500f, 0.953125f, 0.963867f, 0.971191f, 0.977051f, 0.980957f, 0.983887f, + 0.986816f, 0.988281f, 0.990234f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.995605f, 0.995605f, 0.996094f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000240f, 0.000242f, 0.000524f, 0.000597f, + 0.000604f, 0.000606f, 0.000674f, 0.001040f, 0.001238f, 0.001427f, 0.001637f, 0.001670f, 0.002104f, 0.002432f, 0.002775f, 0.003416f, + 0.003860f, 0.004482f, 0.005573f, 0.006374f, 0.007828f, 0.009384f, 0.011635f, 0.014175f, 0.018219f, 0.023224f, 0.031052f, 0.042603f, + 0.060730f, 0.089661f, 0.139526f, 0.225464f, 0.363525f, 0.538574f, 0.696289f, 0.806152f, 0.872559f, 0.912109f, 0.937012f, 0.952637f, + 0.963867f, 0.971191f, 0.976562f, 0.981445f, 0.984863f, 0.987305f, 0.988770f, 0.990723f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, + 0.995117f, 0.996094f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, + 0.000192f, 0.000240f, 0.000242f, 0.000535f, 0.000478f, 0.000600f, 0.000843f, 0.000925f, 0.001027f, 0.001236f, 0.001502f, 0.001490f, + 0.001658f, 0.002256f, 0.002430f, 0.002880f, 0.003056f, 0.003983f, 0.004292f, 0.005333f, 0.006264f, 0.007393f, 0.009064f, 0.011131f, + 0.013741f, 0.017242f, 0.022690f, 0.029922f, 0.040680f, 0.057831f, 0.085022f, 0.132446f, 0.214844f, 0.349121f, 0.524414f, 0.688477f, + 0.801758f, 0.871094f, 0.912109f, 0.937500f, 0.953125f, 0.964355f, 0.971680f, 0.977539f, 0.981445f, 0.985352f, 0.987305f, 0.989258f, + 0.991211f, 0.992188f, 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, 0.000232f, 0.000233f, 0.000363f, 0.000457f, 0.000714f, 0.000724f, 0.000727f, + 0.000847f, 0.000992f, 0.001177f, 0.001525f, 0.001560f, 0.001740f, 0.002090f, 0.002329f, 0.002718f, 0.003372f, 0.003902f, 0.004307f, + 0.005184f, 0.005886f, 0.007446f, 0.008667f, 0.010574f, 0.013588f, 0.016556f, 0.021744f, 0.028854f, 0.039124f, 0.055176f, 0.081726f, + 0.127075f, 0.206421f, 0.338867f, 0.515625f, 0.683105f, 0.800293f, 0.870605f, 0.912598f, 0.937500f, 0.954590f, 0.965332f, 0.973145f, + 0.978516f, 0.982422f, 0.985840f, 0.988281f, 0.989746f, 0.991211f, 0.992676f, 0.993652f, 0.994141f, 0.995117f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000103f, 0.000120f, 0.000240f, 0.000240f, + 0.000484f, 0.000574f, 0.000596f, 0.000837f, 0.000820f, 0.000859f, 0.000985f, 0.001070f, 0.001509f, 0.001554f, 0.001785f, 0.002214f, + 0.002476f, 0.002754f, 0.002991f, 0.003487f, 0.004303f, 0.005074f, 0.005920f, 0.007126f, 0.008743f, 0.010361f, 0.013023f, 0.016403f, + 0.021011f, 0.027817f, 0.037811f, 0.053375f, 0.079041f, 0.123291f, 0.201172f, 0.333252f, 0.511719f, 0.682129f, 0.801270f, 0.872070f, + 0.914062f, 0.939941f, 0.955078f, 0.966309f, 0.973633f, 0.979004f, 0.982910f, 0.986328f, 0.988770f, 0.990234f, 0.991699f, 0.992676f, + 0.993652f, 0.995117f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000079f, 0.000053f, 0.000118f, 0.000418f, 0.000358f, 0.000363f, 0.000678f, 0.000708f, 0.000825f, 0.000838f, 0.000878f, 0.001146f, + 0.000978f, 0.001483f, 0.001541f, 0.001769f, 0.001812f, 0.002434f, 0.002699f, 0.003225f, 0.003298f, 0.004002f, 0.004948f, 0.005932f, + 0.007084f, 0.008461f, 0.010414f, 0.012665f, 0.015915f, 0.020615f, 0.027023f, 0.036743f, 0.051941f, 0.077332f, 0.120789f, 0.198608f, + 0.331543f, 0.512695f, 0.686523f, 0.805664f, 0.875488f, 0.917480f, 0.941406f, 0.957031f, 0.968262f, 0.975098f, 0.980469f, 0.983887f, + 0.986816f, 0.989258f, 0.990723f, 0.992188f, 0.993164f, 0.994629f, 0.998047f, 0.998047f, 0.998535f, 0.998047f, 0.998535f, 0.998535f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000109f, 0.000232f, 0.000349f, 0.000478f, 0.000483f, 0.000483f, 0.000609f, + 0.000795f, 0.000835f, 0.000806f, 0.000726f, 0.001022f, 0.001222f, 0.001442f, 0.001536f, 0.001650f, 0.001714f, 0.002377f, 0.002588f, + 0.003159f, 0.003643f, 0.004036f, 0.004929f, 0.005718f, 0.006813f, 0.008072f, 0.009880f, 0.012527f, 0.015854f, 0.020035f, 0.026352f, + 0.035950f, 0.051178f, 0.076416f, 0.119751f, 0.198730f, 0.334229f, 0.519531f, 0.694824f, 0.812988f, 0.880859f, 0.920898f, 0.944336f, + 0.958984f, 0.969727f, 0.976562f, 0.980957f, 0.984863f, 0.987793f, 0.989746f, 0.991211f, 0.992676f, 0.993652f, 0.997559f, 0.998047f, + 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000068f, 0.000265f, + 0.000361f, 0.000478f, 0.000480f, 0.000479f, 0.000568f, 0.000693f, 0.000714f, 0.000806f, 0.000843f, 0.000919f, 0.001222f, 0.001376f, + 0.001531f, 0.001554f, 0.001987f, 0.002342f, 0.002558f, 0.002798f, 0.003132f, 0.004021f, 0.004864f, 0.005455f, 0.006664f, 0.008110f, + 0.009613f, 0.011955f, 0.015335f, 0.019608f, 0.025879f, 0.035522f, 0.050629f, 0.075623f, 0.120239f, 0.201416f, 0.342041f, 0.533203f, + 0.707031f, 0.821777f, 0.887695f, 0.925293f, 0.946777f, 0.961914f, 0.971680f, 0.977539f, 0.982422f, 0.985352f, 0.988281f, 0.989746f, + 0.992188f, 0.993164f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000000f, 0.000122f, 0.000322f, 0.000241f, 0.000478f, 0.000480f, 0.000480f, 0.000510f, 0.000695f, 0.000710f, + 0.000958f, 0.000765f, 0.001075f, 0.001116f, 0.001318f, 0.001606f, 0.001546f, 0.001916f, 0.002306f, 0.002499f, 0.002905f, 0.003202f, + 0.003914f, 0.004498f, 0.005459f, 0.006611f, 0.007687f, 0.009331f, 0.011757f, 0.014923f, 0.019241f, 0.025833f, 0.035492f, 0.050507f, + 0.076233f, 0.122131f, 0.207153f, 0.355225f, 0.551758f, 0.724609f, 0.833496f, 0.894531f, 0.930664f, 0.951660f, 0.964844f, 0.973145f, + 0.979492f, 0.983887f, 0.986816f, 0.989258f, 0.991211f, 0.993164f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.997559f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000351f, 0.000458f, 0.000476f, + 0.000480f, 0.000482f, 0.000528f, 0.000650f, 0.000704f, 0.000956f, 0.000828f, 0.000963f, 0.001111f, 0.001265f, 0.001474f, 0.001806f, + 0.001872f, 0.002308f, 0.002445f, 0.002701f, 0.003229f, 0.003851f, 0.004375f, 0.005356f, 0.006317f, 0.007458f, 0.009300f, 0.011574f, + 0.014725f, 0.019165f, 0.025696f, 0.035461f, 0.050812f, 0.077637f, 0.125977f, 0.216797f, 0.374756f, 0.576660f, 0.745117f, 0.848145f, + 0.904785f, 0.936523f, 0.956055f, 0.967773f, 0.975586f, 0.980957f, 0.984863f, 0.987793f, 0.990234f, 0.992188f, 0.997070f, 0.997559f, + 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000292f, 0.000224f, 0.000452f, 0.000453f, 0.000479f, 0.000480f, 0.000517f, 0.000614f, 0.000902f, 0.000712f, 0.000959f, + 0.000978f, 0.001100f, 0.001276f, 0.001461f, 0.001524f, 0.001651f, 0.002041f, 0.002350f, 0.002853f, 0.003433f, 0.003622f, 0.004166f, + 0.005043f, 0.006187f, 0.007534f, 0.009209f, 0.011551f, 0.014908f, 0.019012f, 0.025406f, 0.035461f, 0.051575f, 0.079651f, 0.131714f, + 0.230957f, 0.401367f, 0.607910f, 0.769531f, 0.863281f, 0.914062f, 0.942871f, 0.959961f, 0.970703f, 0.978027f, 0.982910f, 0.986816f, + 0.988770f, 0.991699f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000238f, 0.000355f, 0.000449f, 0.000462f, 0.000474f, 0.000477f, + 0.000482f, 0.000846f, 0.000726f, 0.000706f, 0.000953f, 0.000889f, 0.001012f, 0.001259f, 0.001390f, 0.001755f, 0.001658f, 0.002060f, + 0.002369f, 0.002539f, 0.003170f, 0.003460f, 0.004131f, 0.004993f, 0.006008f, 0.007431f, 0.009109f, 0.011444f, 0.014252f, 0.019058f, + 0.025574f, 0.036011f, 0.053162f, 0.083435f, 0.140381f, 0.250488f, 0.436035f, 0.645996f, 0.795898f, 0.880371f, 0.924316f, 0.949219f, + 0.963867f, 0.973145f, 0.980469f, 0.984863f, 0.988281f, 0.990723f, 0.997070f, 0.997559f, 0.997070f, 0.997559f, 0.997559f, 0.997070f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000239f, + 0.000306f, 0.000440f, 0.000437f, 0.000474f, 0.000478f, 0.000481f, 0.000523f, 0.000664f, 0.000731f, 0.000802f, 0.000935f, 0.001022f, + 0.001173f, 0.001314f, 0.001504f, 0.001831f, 0.001984f, 0.002317f, 0.002472f, 0.003199f, 0.003370f, 0.004189f, 0.004868f, 0.005924f, + 0.007320f, 0.008926f, 0.011421f, 0.014595f, 0.019119f, 0.026260f, 0.036987f, 0.055176f, 0.088440f, 0.152466f, 0.277832f, 0.479980f, + 0.686523f, 0.823242f, 0.895508f, 0.933105f, 0.955566f, 0.969238f, 0.976562f, 0.982422f, 0.986816f, 0.989746f, 0.996582f, 0.997070f, + 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000194f, 0.000280f, 0.000417f, 0.000448f, 0.000468f, 0.000476f, 0.000479f, 0.000490f, + 0.000845f, 0.000688f, 0.000740f, 0.000945f, 0.000998f, 0.001148f, 0.001266f, 0.001414f, 0.001475f, 0.001667f, 0.002262f, 0.002537f, + 0.003019f, 0.003288f, 0.004223f, 0.004768f, 0.005890f, 0.007259f, 0.009026f, 0.011360f, 0.014297f, 0.019272f, 0.026474f, 0.038116f, + 0.058197f, 0.095032f, 0.168945f, 0.313965f, 0.533203f, 0.731445f, 0.850098f, 0.911133f, 0.942871f, 0.961914f, 0.972656f, 0.979980f, + 0.984863f, 0.988770f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000000f, 0.000122f, 0.000000f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000187f, 0.000233f, 0.000141f, 0.000271f, 0.000341f, + 0.000380f, 0.000465f, 0.000473f, 0.000590f, 0.000605f, 0.000798f, 0.000847f, 0.000934f, 0.000946f, 0.000836f, 0.001009f, 0.001142f, + 0.001430f, 0.001495f, 0.001850f, 0.002111f, 0.002541f, 0.003035f, 0.003300f, 0.004139f, 0.004913f, 0.005718f, 0.007141f, 0.008934f, + 0.011475f, 0.014832f, 0.019653f, 0.027573f, 0.039917f, 0.062225f, 0.104919f, 0.192017f, 0.362305f, 0.594238f, 0.775879f, 0.875977f, + 0.925293f, 0.952148f, 0.967773f, 0.977051f, 0.983398f, 0.988281f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996094f, 0.996582f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000238f, 0.000243f, 0.000238f, 0.000424f, 0.000453f, 0.000467f, 0.000475f, 0.000581f, 0.000689f, 0.000795f, + 0.000634f, 0.000823f, 0.001014f, 0.000900f, 0.001083f, 0.001485f, 0.001731f, 0.001851f, 0.002056f, 0.002373f, 0.002621f, 0.003445f, + 0.004082f, 0.004578f, 0.005821f, 0.007217f, 0.008881f, 0.011330f, 0.014778f, 0.020416f, 0.028473f, 0.042419f, 0.067993f, 0.118286f, + 0.225342f, 0.425293f, 0.661621f, 0.818848f, 0.899902f, 0.939453f, 0.960449f, 0.973145f, 0.980957f, 0.985840f, 0.995605f, 0.996094f, + 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000205f, 0.000224f, 0.000122f, 0.000231f, 0.000245f, 0.000411f, 0.000520f, + 0.000463f, 0.000470f, 0.000587f, 0.000361f, 0.000712f, 0.000694f, 0.000815f, 0.000978f, 0.001055f, 0.001105f, 0.001390f, 0.001438f, + 0.001705f, 0.001984f, 0.002333f, 0.002546f, 0.003408f, 0.003876f, 0.004627f, 0.005783f, 0.007198f, 0.008995f, 0.011383f, 0.015396f, + 0.020828f, 0.030029f, 0.045654f, 0.075439f, 0.137451f, 0.271973f, 0.503418f, 0.728516f, 0.857910f, 0.920410f, 0.951172f, 0.968262f, + 0.977539f, 0.984375f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000173f, 0.000150f, 0.000278f, 0.000376f, 0.000427f, 0.000470f, 0.000352f, 0.000356f, 0.000475f, 0.000441f, 0.000709f, 0.000774f, + 0.000970f, 0.001013f, 0.000998f, 0.001193f, 0.001397f, 0.001677f, 0.001957f, 0.002268f, 0.002529f, 0.003353f, 0.003874f, 0.004555f, + 0.005692f, 0.007160f, 0.008987f, 0.011543f, 0.015732f, 0.021896f, 0.032135f, 0.050140f, 0.086548f, 0.165894f, 0.337646f, 0.593750f, + 0.791504f, 0.892090f, 0.938477f, 0.961914f, 0.974609f, 0.982422f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.995117f, 0.995605f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000187f, 0.000130f, 0.000231f, 0.000315f, 0.000298f, 0.000332f, 0.000343f, + 0.000465f, 0.000472f, 0.000579f, 0.000717f, 0.000839f, 0.000932f, 0.000817f, 0.001086f, 0.001090f, 0.001545f, 0.001735f, 0.001837f, + 0.002485f, 0.002493f, 0.003288f, 0.003828f, 0.004520f, 0.005833f, 0.007156f, 0.009193f, 0.012123f, 0.015839f, 0.022934f, 0.034760f, + 0.056488f, 0.102600f, 0.208862f, 0.427734f, 0.687988f, 0.846191f, 0.919434f, 0.952637f, 0.969727f, 0.979980f, 0.993652f, 0.994629f, + 0.994141f, 0.994629f, 0.994629f, 0.994629f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000133f, + 0.000141f, 0.000234f, 0.000300f, 0.000397f, 0.000436f, 0.000456f, 0.000465f, 0.000534f, 0.000663f, 0.000810f, 0.000796f, 0.000812f, + 0.001062f, 0.001237f, 0.001428f, 0.001565f, 0.001818f, 0.002182f, 0.002783f, 0.002943f, 0.003773f, 0.004715f, 0.005482f, 0.007195f, + 0.009285f, 0.012207f, 0.016922f, 0.024567f, 0.038483f, 0.066101f, 0.127563f, 0.274170f, 0.540527f, 0.774414f, 0.891113f, 0.940430f, + 0.965332f, 0.977539f, 0.993652f, 0.994141f, 0.994629f, 0.994141f, 0.994629f, 0.994141f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000124f, 0.000116f, 0.000119f, 0.000125f, 0.000121f, 0.000197f, 0.000323f, 0.000418f, 0.000446f, 0.000433f, + 0.000467f, 0.000612f, 0.000710f, 0.000783f, 0.000911f, 0.000817f, 0.001161f, 0.001343f, 0.001514f, 0.001707f, 0.002081f, 0.002386f, + 0.002882f, 0.003609f, 0.004627f, 0.005478f, 0.007011f, 0.009384f, 0.012695f, 0.017960f, 0.026901f, 0.044067f, 0.080078f, 0.167114f, + 0.374023f, 0.664062f, 0.845703f, 0.923340f, 0.957031f, 0.974121f, 0.992676f, 0.993652f, 0.993164f, 0.993652f, 0.993652f, 0.993164f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000052f, 0.000039f, 0.000029f, 0.000054f, 0.000045f, 0.000118f, + 0.000128f, 0.000231f, 0.000387f, 0.000429f, 0.000446f, 0.000544f, 0.000539f, 0.000648f, 0.000749f, 0.000790f, 0.000978f, 0.001102f, + 0.001195f, 0.001501f, 0.001761f, 0.001978f, 0.002661f, 0.003170f, 0.003519f, 0.004509f, 0.005344f, 0.007004f, 0.009361f, 0.013229f, + 0.019196f, 0.030258f, 0.052002f, 0.102661f, 0.234131f, 0.511230f, 0.774902f, 0.898438f, 0.947754f, 0.970215f, 0.992188f, 0.992676f, + 0.993164f, 0.992676f, 0.992188f, 0.992188f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000070f, 0.000052f, + 0.000038f, 0.000030f, 0.000023f, 0.000060f, 0.000116f, 0.000121f, 0.000252f, 0.000337f, 0.000306f, 0.000435f, 0.000450f, 0.000562f, + 0.000584f, 0.000722f, 0.000858f, 0.000888f, 0.000969f, 0.001230f, 0.001429f, 0.001576f, 0.001827f, 0.002361f, 0.002863f, 0.003267f, + 0.004047f, 0.005394f, 0.007256f, 0.009781f, 0.013855f, 0.021439f, 0.035034f, 0.065063f, 0.141724f, 0.346680f, 0.665527f, 0.859375f, + 0.934570f, 0.965820f, 0.991699f, 0.991699f, 0.991699f, 0.992188f, 0.991699f, 0.991699f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, + 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000099f, 0.000069f, 0.000051f, 0.000039f, 0.000030f, 0.000023f, 0.000024f, 0.000115f, 0.000103f, 0.000224f, + 0.000204f, 0.000339f, 0.000407f, 0.000437f, 0.000452f, 0.000489f, 0.000663f, 0.000821f, 0.000922f, 0.001004f, 0.001086f, 0.001279f, + 0.001554f, 0.001651f, 0.001997f, 0.002390f, 0.003136f, 0.004223f, 0.005508f, 0.007339f, 0.010094f, 0.014854f, 0.024048f, 0.042664f, + 0.087036f, 0.213867f, 0.516113f, 0.799805f, 0.915527f, 0.958984f, 0.990723f, 0.991211f, 0.990723f, 0.990723f, 0.990723f, 0.991211f, + 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000096f, 0.000073f, 0.000053f, 0.000040f, 0.000031f, + 0.000025f, 0.000020f, 0.000017f, 0.000105f, 0.000110f, 0.000135f, 0.000235f, 0.000380f, 0.000462f, 0.000513f, 0.000556f, 0.000638f, + 0.000804f, 0.000868f, 0.000897f, 0.001002f, 0.001079f, 0.001246f, 0.001596f, 0.002153f, 0.002213f, 0.003094f, 0.004158f, 0.005306f, + 0.007458f, 0.010887f, 0.017166f, 0.028748f, 0.055176f, 0.128174f, 0.350586f, 0.703613f, 0.888184f, 0.951172f, 0.988770f, 0.989746f, + 0.989746f, 0.989746f, 0.989746f, 0.989746f, 0.000122f, 0.000120f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000101f, 0.000073f, 0.000057f, 0.000043f, 0.000033f, 0.000027f, 0.000021f, 0.000018f, 0.000105f, 0.000112f, 0.000111f, 0.000161f, + 0.000320f, 0.000390f, 0.000421f, 0.000438f, 0.000559f, 0.000665f, 0.000735f, 0.000719f, 0.000704f, 0.000887f, 0.001223f, 0.001384f, + 0.001867f, 0.002462f, 0.003216f, 0.004032f, 0.005367f, 0.007988f, 0.012054f, 0.019943f, 0.035919f, 0.078064f, 0.215332f, 0.566895f, + 0.845703f, 0.939941f, 0.987793f, 0.988281f, 0.987793f, 0.987793f, 0.988281f, 0.988281f, 0.000000f, 0.000120f, 0.000120f, 0.000120f, + 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, + 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000103f, 0.000077f, 0.000061f, 0.000046f, 0.000037f, 0.000030f, 0.000023f, + 0.000019f, 0.000016f, 0.000039f, 0.000094f, 0.000181f, 0.000205f, 0.000350f, 0.000392f, 0.000423f, 0.000510f, 0.000619f, 0.000672f, + 0.000705f, 0.000632f, 0.000807f, 0.001038f, 0.001278f, 0.001894f, 0.002245f, 0.002758f, 0.003883f, 0.005863f, 0.008636f, 0.013672f, + 0.023880f, 0.048828f, 0.127441f, 0.400879f, 0.779297f, 0.925781f, 0.985840f, 0.986328f, 0.986328f, 0.985840f, 0.986328f, 0.986328f, + 0.000000f, 0.000100f, 0.000108f, 0.000118f, 0.000119f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000120f, 0.000120f, + 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000111f, 0.000086f, + 0.000066f, 0.000051f, 0.000041f, 0.000032f, 0.000026f, 0.000021f, 0.000018f, 0.000015f, 0.000086f, 0.000131f, 0.000190f, 0.000293f, + 0.000419f, 0.000481f, 0.000477f, 0.000438f, 0.000542f, 0.000564f, 0.000599f, 0.000700f, 0.000916f, 0.001122f, 0.001589f, 0.001997f, + 0.002678f, 0.004017f, 0.005814f, 0.009361f, 0.015808f, 0.031250f, 0.075989f, 0.250732f, 0.676758f, 0.904297f, 0.983887f, 0.983887f, + 0.983887f, 0.984375f, 0.984375f, 0.983887f, 0.000000f, 0.000000f, 0.000077f, 0.000112f, 0.000104f, 0.000115f, 0.000115f, 0.000117f, + 0.000117f, 0.000117f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000119f, 0.000118f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, + 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000097f, 0.000076f, 0.000060f, 0.000046f, 0.000037f, 0.000030f, 0.000024f, 0.000020f, + 0.000045f, 0.000063f, 0.000091f, 0.000140f, 0.000202f, 0.000333f, 0.000305f, 0.000399f, 0.000462f, 0.000452f, 0.000535f, 0.000531f, + 0.000631f, 0.000866f, 0.000858f, 0.001307f, 0.001844f, 0.002823f, 0.004070f, 0.006264f, 0.010536f, 0.020035f, 0.045990f, 0.145996f, + 0.532227f, 0.874023f, 0.980957f, 0.981445f, 0.980957f, 0.981445f, 0.980957f, 0.981445f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000091f, 0.000103f, 0.000105f, 0.000106f, 0.000111f, 0.000113f, 0.000115f, 0.000114f, 0.000116f, 0.000116f, 0.000117f, 0.000117f, + 0.000117f, 0.000117f, 0.000117f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000112f, 0.000084f, 0.000069f, + 0.000055f, 0.000043f, 0.000036f, 0.000028f, 0.000024f, 0.000020f, 0.000028f, 0.000039f, 0.000083f, 0.000141f, 0.000211f, 0.000262f, + 0.000413f, 0.000305f, 0.000370f, 0.000358f, 0.000489f, 0.000564f, 0.000599f, 0.000893f, 0.001084f, 0.001696f, 0.002697f, 0.004074f, + 0.006836f, 0.012878f, 0.028122f, 0.083496f, 0.364014f, 0.826660f, 0.976562f, 0.977539f, 0.977051f, 0.977539f, 0.978027f, 0.977051f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000015f, 0.000086f, 0.000077f, 0.000103f, 0.000100f, 0.000109f, + 0.000110f, 0.000111f, 0.000112f, 0.000112f, 0.000114f, 0.000114f, 0.000115f, 0.000115f, 0.000116f, 0.000115f, 0.000116f, 0.000116f, + 0.000117f, 0.000117f, 0.000117f, 0.000100f, 0.000079f, 0.000066f, 0.000053f, 0.000041f, 0.000035f, 0.000028f, 0.000023f, 0.000019f, + 0.000017f, 0.000034f, 0.000113f, 0.000174f, 0.000257f, 0.000325f, 0.000356f, 0.000324f, 0.000409f, 0.000454f, 0.000474f, 0.000659f, + 0.000778f, 0.001243f, 0.001575f, 0.002472f, 0.004105f, 0.007957f, 0.016800f, 0.047852f, 0.217529f, 0.755371f, 0.972656f, 0.973145f, + 0.973145f, 0.973145f, 0.973145f, 0.973145f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000028f, 0.000049f, 0.000085f, 0.000081f, 0.000096f, 0.000101f, 0.000104f, 0.000106f, 0.000108f, 0.000109f, 0.000110f, + 0.000111f, 0.000112f, 0.000113f, 0.000113f, 0.000114f, 0.000114f, 0.000114f, 0.000115f, 0.000115f, 0.000096f, 0.000078f, 0.000064f, + 0.000051f, 0.000043f, 0.000035f, 0.000029f, 0.000024f, 0.000020f, 0.000026f, 0.000055f, 0.000087f, 0.000135f, 0.000248f, 0.000261f, + 0.000274f, 0.000258f, 0.000296f, 0.000359f, 0.000474f, 0.000627f, 0.001012f, 0.001484f, 0.002630f, 0.004536f, 0.010277f, 0.027405f, + 0.119507f, 0.645996f, 0.966797f, 0.967285f, 0.967285f, 0.967285f, 0.966797f, 0.966797f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000014f, 0.000021f, 0.000065f, 0.000074f, + 0.000077f, 0.000091f, 0.000091f, 0.000099f, 0.000098f, 0.000103f, 0.000103f, 0.000106f, 0.000107f, 0.000108f, 0.000109f, 0.000110f, + 0.000111f, 0.000111f, 0.000112f, 0.000096f, 0.000079f, 0.000064f, 0.000053f, 0.000043f, 0.000036f, 0.000030f, 0.000024f, 0.000021f, + 0.000018f, 0.000028f, 0.000072f, 0.000125f, 0.000233f, 0.000243f, 0.000220f, 0.000258f, 0.000320f, 0.000353f, 0.000630f, 0.000932f, + 0.001324f, 0.002357f, 0.005402f, 0.014534f, 0.062561f, 0.493164f, 0.958008f, 0.958008f, 0.958984f, 0.958496f, 0.958496f, 0.958008f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000011f, 0.000035f, 0.000041f, 0.000064f, 0.000074f, 0.000081f, 0.000082f, 0.000090f, + 0.000092f, 0.000096f, 0.000099f, 0.000100f, 0.000102f, 0.000104f, 0.000105f, 0.000106f, 0.000107f, 0.000099f, 0.000082f, 0.000067f, + 0.000055f, 0.000047f, 0.000038f, 0.000031f, 0.000026f, 0.000022f, 0.000018f, 0.000037f, 0.000071f, 0.000111f, 0.000190f, 0.000204f, + 0.000153f, 0.000245f, 0.000299f, 0.000482f, 0.000790f, 0.001330f, 0.002619f, 0.007282f, 0.031097f, 0.318115f, 0.946289f, 0.946777f, + 0.946777f, 0.946777f, 0.946777f, 0.946777f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000008f, 0.000029f, 0.000044f, 0.000055f, 0.000063f, 0.000073f, 0.000075f, 0.000081f, 0.000087f, 0.000090f, 0.000092f, + 0.000094f, 0.000097f, 0.000099f, 0.000100f, 0.000087f, 0.000071f, 0.000059f, 0.000049f, 0.000040f, 0.000034f, 0.000028f, 0.000024f, + 0.000020f, 0.000016f, 0.000072f, 0.000114f, 0.000169f, 0.000147f, 0.000181f, 0.000246f, 0.000367f, 0.000626f, 0.001325f, 0.003117f, + 0.013741f, 0.167480f, 0.929688f, 0.929688f, 0.929688f, 0.930176f, 0.930664f, 0.930176f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000019f, + 0.000030f, 0.000044f, 0.000049f, 0.000062f, 0.000068f, 0.000072f, 0.000078f, 0.000081f, 0.000084f, 0.000087f, 0.000090f, 0.000079f, + 0.000065f, 0.000054f, 0.000044f, 0.000037f, 0.000030f, 0.000025f, 0.000021f, 0.000017f, 0.000052f, 0.000100f, 0.000132f, 0.000130f, + 0.000164f, 0.000297f, 0.000552f, 0.001273f, 0.005009f, 0.071594f, 0.903809f, 0.905273f, 0.904297f, 0.904785f, 0.904785f, 0.904785f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000013f, 0.000028f, 0.000036f, + 0.000045f, 0.000053f, 0.000060f, 0.000066f, 0.000071f, 0.000075f, 0.000071f, 0.000058f, 0.000049f, 0.000040f, 0.000033f, 0.000027f, + 0.000022f, 0.000018f, 0.000032f, 0.000078f, 0.000090f, 0.000123f, 0.000175f, 0.000441f, 0.001637f, 0.022537f, 0.865234f, 0.865234f, + 0.865723f, 0.865723f, 0.865234f, 0.864746f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000017f, 0.000027f, 0.000036f, 0.000042f, + 0.000050f, 0.000056f, 0.000052f, 0.000043f, 0.000035f, 0.000028f, 0.000022f, 0.000018f, 0.000049f, 0.000055f, 0.000047f, 0.000108f, + 0.000342f, 0.004566f, 0.802734f, 0.803711f, 0.803711f, 0.803711f, 0.803711f, 0.803711f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000013f, 0.000022f, 0.000030f, 0.000033f, 0.000027f, + 0.000021f, 0.000015f, 0.000011f, 0.000031f, 0.000045f, 0.000449f, 0.708496f, 0.707520f, 0.708984f, 0.708496f, 0.707520f, 0.708008f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000011f, 0.000006f, 0.000007f, 0.575195f, 0.575195f, + 0.575195f, 0.575195f, 0.575195f, 0.575195f, + }, + { + 0.158813f, 0.632812f, 0.824219f, 0.891602f, 0.924805f, 0.942383f, 0.954102f, 0.962402f, 0.968262f, 0.972656f, 0.976074f, 0.978516f, + 0.980957f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988770f, 0.989746f, 0.989746f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, + 0.993652f, 0.993652f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, + 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.019775f, 0.115845f, 0.361084f, 0.642578f, 0.798340f, 0.872559f, 0.911133f, 0.933594f, + 0.947266f, 0.957031f, 0.964355f, 0.968750f, 0.973145f, 0.976562f, 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986816f, 0.987793f, + 0.988770f, 0.989258f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, + 0.995605f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, + 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.006638f, 0.031082f, 0.089661f, 0.222168f, + 0.448242f, 0.663086f, 0.794434f, 0.864258f, 0.903320f, 0.926758f, 0.942383f, 0.953613f, 0.961426f, 0.966797f, 0.972168f, 0.975586f, + 0.978027f, 0.980469f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.989258f, 0.990234f, 0.991211f, 0.991699f, 0.992188f, + 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, + 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.003246f, 0.013367f, 0.032806f, 0.072754f, 0.152954f, 0.304199f, 0.509766f, 0.687500f, 0.797852f, 0.862305f, 0.900391f, 0.923828f, + 0.940430f, 0.950684f, 0.959473f, 0.965820f, 0.970703f, 0.974121f, 0.977051f, 0.979492f, 0.981934f, 0.983887f, 0.985840f, 0.987305f, + 0.987793f, 0.989258f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992188f, 0.993164f, 0.993652f, 0.993652f, 0.994629f, 0.995117f, + 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, + 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.002029f, 0.007267f, 0.016678f, 0.032288f, 0.061462f, 0.115051f, 0.215088f, 0.376709f, + 0.562988f, 0.712891f, 0.807617f, 0.865234f, 0.901367f, 0.923828f, 0.939453f, 0.950684f, 0.958984f, 0.965332f, 0.970215f, 0.974609f, + 0.977051f, 0.979980f, 0.981934f, 0.983887f, 0.984863f, 0.986328f, 0.988281f, 0.988770f, 0.989746f, 0.990723f, 0.990723f, 0.991699f, + 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, + 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.001274f, 0.004623f, 0.009880f, 0.017792f, + 0.030869f, 0.052673f, 0.091431f, 0.160645f, 0.277832f, 0.442383f, 0.610352f, 0.737793f, 0.819824f, 0.870605f, 0.902832f, 0.924805f, + 0.939941f, 0.950195f, 0.958496f, 0.964844f, 0.970215f, 0.973633f, 0.977051f, 0.979980f, 0.981934f, 0.983398f, 0.984863f, 0.986328f, + 0.987305f, 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, + 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.997559f, 0.998047f, + 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000943f, 0.003231f, 0.006317f, 0.011040f, 0.018051f, 0.029190f, 0.046936f, 0.075867f, 0.125488f, 0.210449f, 0.341797f, 0.503906f, + 0.652344f, 0.761230f, 0.832031f, 0.877441f, 0.906738f, 0.927734f, 0.940918f, 0.951172f, 0.959473f, 0.965820f, 0.970703f, 0.974121f, + 0.977051f, 0.979492f, 0.981934f, 0.983398f, 0.985352f, 0.987305f, 0.988281f, 0.989258f, 0.990234f, 0.990723f, 0.991211f, 0.992188f, + 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, + 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000731f, 0.001970f, 0.004425f, 0.007351f, 0.011627f, 0.017975f, 0.027161f, 0.041779f, + 0.064270f, 0.101685f, 0.164917f, 0.265137f, 0.406494f, 0.561035f, 0.692383f, 0.785156f, 0.845703f, 0.884766f, 0.911621f, 0.930176f, + 0.942871f, 0.953125f, 0.959961f, 0.965332f, 0.970703f, 0.974121f, 0.977539f, 0.979492f, 0.982422f, 0.983887f, 0.985840f, 0.987305f, + 0.987793f, 0.989258f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, + 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.000487f, 0.001872f, 0.003445f, 0.005367f, + 0.008400f, 0.012405f, 0.017822f, 0.025345f, 0.037964f, 0.056244f, 0.085327f, 0.132935f, 0.210327f, 0.325928f, 0.471924f, 0.615723f, + 0.729004f, 0.807617f, 0.859375f, 0.894043f, 0.916504f, 0.934570f, 0.945801f, 0.955078f, 0.961426f, 0.967285f, 0.972168f, 0.975586f, + 0.978516f, 0.980957f, 0.982422f, 0.984863f, 0.985840f, 0.986816f, 0.988770f, 0.989258f, 0.990723f, 0.991699f, 0.992188f, 0.992676f, + 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.997070f, 0.997070f, 0.997559f, + 0.997559f, 0.998047f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.000363f, 0.001300f, 0.002499f, 0.003784f, 0.006153f, 0.008896f, 0.012367f, 0.017227f, 0.024185f, 0.034241f, 0.049591f, 0.072754f, + 0.111023f, 0.170776f, 0.263184f, 0.391113f, 0.535645f, 0.665527f, 0.761719f, 0.828613f, 0.871582f, 0.902344f, 0.922852f, 0.937988f, + 0.949219f, 0.957031f, 0.963867f, 0.968750f, 0.972656f, 0.976074f, 0.979004f, 0.981445f, 0.983887f, 0.984863f, 0.986328f, 0.988281f, + 0.989258f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993652f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, + 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999023f, 0.999023f, 0.000365f, 0.000972f, 0.001874f, 0.003323f, 0.004669f, 0.006599f, 0.008919f, 0.012360f, + 0.016785f, 0.022720f, 0.031616f, 0.044647f, 0.064026f, 0.094055f, 0.141235f, 0.215332f, 0.323486f, 0.459229f, 0.597168f, 0.710449f, + 0.791992f, 0.847656f, 0.885254f, 0.910645f, 0.929199f, 0.941895f, 0.952148f, 0.960449f, 0.965332f, 0.970703f, 0.974121f, 0.977539f, + 0.979980f, 0.981934f, 0.984375f, 0.985840f, 0.987305f, 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.993164f, 0.993164f, + 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, + 0.998047f, 0.998535f, 0.999023f, 0.999512f, 0.999023f, 0.999512f, 0.999512f, 0.999023f, 0.000244f, 0.000764f, 0.001375f, 0.002415f, + 0.003582f, 0.004963f, 0.006973f, 0.008751f, 0.011726f, 0.016113f, 0.021683f, 0.029129f, 0.040283f, 0.057098f, 0.081421f, 0.119019f, + 0.178955f, 0.268311f, 0.390625f, 0.528809f, 0.654785f, 0.751465f, 0.820312f, 0.866211f, 0.896973f, 0.919434f, 0.935547f, 0.946777f, + 0.956055f, 0.962402f, 0.968262f, 0.972168f, 0.975098f, 0.979004f, 0.981445f, 0.983398f, 0.985352f, 0.986816f, 0.987793f, 0.989258f, + 0.990723f, 0.991211f, 0.992188f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, + 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000122f, 0.000606f, 0.001439f, 0.002058f, 0.002743f, 0.004169f, 0.005035f, 0.006775f, 0.009010f, 0.012085f, 0.015717f, 0.020813f, + 0.027573f, 0.037170f, 0.050812f, 0.071472f, 0.102905f, 0.151489f, 0.225708f, 0.332031f, 0.463623f, 0.596191f, 0.707031f, 0.787598f, + 0.844238f, 0.881348f, 0.908691f, 0.927246f, 0.940918f, 0.951660f, 0.958984f, 0.965820f, 0.970215f, 0.974121f, 0.977539f, 0.979980f, + 0.982422f, 0.984375f, 0.985840f, 0.987305f, 0.988281f, 0.990234f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, + 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000118f, 0.000846f, 0.001303f, 0.001593f, 0.002180f, 0.003050f, 0.004353f, 0.005577f, + 0.006954f, 0.009331f, 0.011826f, 0.015007f, 0.019653f, 0.025391f, 0.034119f, 0.046112f, 0.063660f, 0.090210f, 0.130737f, 0.192139f, + 0.283203f, 0.404053f, 0.537598f, 0.658691f, 0.753418f, 0.818848f, 0.865234f, 0.896973f, 0.918945f, 0.934570f, 0.946289f, 0.955566f, + 0.962402f, 0.967285f, 0.972168f, 0.976074f, 0.979004f, 0.981445f, 0.983398f, 0.985840f, 0.986816f, 0.988281f, 0.989258f, 0.990723f, + 0.991211f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, + 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000117f, 0.000487f, 0.000957f, 0.001514f, + 0.002008f, 0.002619f, 0.003424f, 0.004551f, 0.005836f, 0.007381f, 0.009155f, 0.011459f, 0.014366f, 0.018646f, 0.024017f, 0.031281f, + 0.042664f, 0.057068f, 0.080139f, 0.113586f, 0.165894f, 0.243164f, 0.352051f, 0.481934f, 0.610840f, 0.716309f, 0.793945f, 0.847168f, + 0.884766f, 0.910645f, 0.928223f, 0.942383f, 0.952637f, 0.959961f, 0.965332f, 0.970703f, 0.975098f, 0.978027f, 0.980957f, 0.983398f, + 0.984863f, 0.986816f, 0.988281f, 0.989258f, 0.990723f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, + 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997559f, 0.997070f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000000f, 0.000608f, 0.000952f, 0.001111f, 0.001660f, 0.002102f, 0.002817f, 0.003517f, 0.004742f, 0.005585f, 0.007080f, 0.008980f, + 0.011078f, 0.014191f, 0.017838f, 0.022614f, 0.029404f, 0.038940f, 0.052551f, 0.071533f, 0.100769f, 0.145020f, 0.211548f, 0.307373f, + 0.430176f, 0.561523f, 0.676758f, 0.764648f, 0.828613f, 0.872070f, 0.900879f, 0.921875f, 0.937012f, 0.948730f, 0.957520f, 0.964355f, + 0.969238f, 0.973633f, 0.977539f, 0.979980f, 0.982422f, 0.984863f, 0.986328f, 0.987793f, 0.988770f, 0.990234f, 0.991211f, 0.991699f, + 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000244f, 0.000576f, 0.000727f, 0.001083f, 0.001186f, 0.001810f, 0.002558f, 0.002968f, + 0.003725f, 0.004913f, 0.005955f, 0.007011f, 0.008759f, 0.010918f, 0.013718f, 0.016953f, 0.021423f, 0.027832f, 0.035980f, 0.047913f, + 0.064941f, 0.090332f, 0.128174f, 0.185791f, 0.270264f, 0.384033f, 0.514160f, 0.638184f, 0.736328f, 0.807617f, 0.856934f, 0.891602f, + 0.915039f, 0.932617f, 0.945801f, 0.954102f, 0.962402f, 0.968262f, 0.972168f, 0.976562f, 0.979492f, 0.981445f, 0.983887f, 0.985840f, + 0.987305f, 0.988281f, 0.990234f, 0.990723f, 0.992188f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, + 0.996582f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000000f, 0.000244f, 0.000708f, 0.000903f, + 0.001129f, 0.001511f, 0.002031f, 0.002565f, 0.003189f, 0.004112f, 0.004696f, 0.005989f, 0.006954f, 0.008865f, 0.010826f, 0.013031f, + 0.016312f, 0.020493f, 0.026154f, 0.033966f, 0.044159f, 0.059845f, 0.081665f, 0.114929f, 0.164917f, 0.239624f, 0.343750f, 0.469971f, + 0.598145f, 0.706055f, 0.786133f, 0.842773f, 0.881348f, 0.908203f, 0.927246f, 0.941895f, 0.952148f, 0.959961f, 0.966797f, 0.971191f, + 0.976074f, 0.978516f, 0.981445f, 0.983887f, 0.985352f, 0.987305f, 0.988281f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, + 0.994141f, 0.994629f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000122f, 0.000244f, 0.000482f, 0.000674f, 0.001029f, 0.001440f, 0.001746f, 0.002153f, 0.002804f, 0.003206f, 0.003859f, 0.004948f, + 0.005722f, 0.007206f, 0.008568f, 0.010498f, 0.012413f, 0.015793f, 0.019989f, 0.024826f, 0.031799f, 0.041382f, 0.054932f, 0.074768f, + 0.103882f, 0.147949f, 0.213867f, 0.308838f, 0.429932f, 0.560059f, 0.675781f, 0.765625f, 0.827148f, 0.871582f, 0.901367f, 0.923340f, + 0.937988f, 0.949707f, 0.958496f, 0.965820f, 0.969727f, 0.974609f, 0.978027f, 0.980469f, 0.983398f, 0.985840f, 0.986816f, 0.988281f, + 0.989258f, 0.990723f, 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000244f, 0.000244f, 0.000363f, 0.000604f, 0.000834f, 0.001020f, 0.001548f, 0.001970f, + 0.002262f, 0.002548f, 0.003157f, 0.003914f, 0.004681f, 0.005962f, 0.006943f, 0.008263f, 0.010277f, 0.012589f, 0.015144f, 0.018951f, + 0.023788f, 0.030014f, 0.039001f, 0.051056f, 0.069092f, 0.094666f, 0.133911f, 0.192993f, 0.279053f, 0.394287f, 0.524414f, 0.646484f, + 0.743652f, 0.812988f, 0.861328f, 0.895020f, 0.917969f, 0.935547f, 0.947754f, 0.957520f, 0.963867f, 0.969238f, 0.974121f, 0.978027f, + 0.980469f, 0.983398f, 0.984863f, 0.987305f, 0.988281f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, + 0.995117f, 0.996094f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000118f, 0.000244f, 0.000244f, 0.000584f, + 0.000837f, 0.000847f, 0.001295f, 0.001681f, 0.002018f, 0.002348f, 0.003014f, 0.003157f, 0.004124f, 0.004547f, 0.005432f, 0.006607f, + 0.008163f, 0.010071f, 0.011925f, 0.014786f, 0.017990f, 0.022659f, 0.028824f, 0.036621f, 0.047882f, 0.063477f, 0.087158f, 0.122559f, + 0.175781f, 0.254639f, 0.363037f, 0.492188f, 0.618652f, 0.722168f, 0.799805f, 0.852051f, 0.889648f, 0.914551f, 0.932129f, 0.944824f, + 0.955078f, 0.962891f, 0.968262f, 0.973633f, 0.977051f, 0.980469f, 0.982910f, 0.984863f, 0.987305f, 0.988281f, 0.990234f, 0.991211f, + 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000242f, 0.000243f, 0.000243f, 0.000481f, 0.000742f, 0.000843f, 0.000969f, 0.001348f, 0.001726f, 0.001791f, 0.002348f, 0.002853f, + 0.003452f, 0.003735f, 0.004757f, 0.005516f, 0.006744f, 0.008102f, 0.009621f, 0.011948f, 0.014320f, 0.017365f, 0.021698f, 0.027298f, + 0.034546f, 0.044891f, 0.059875f, 0.081055f, 0.112915f, 0.161255f, 0.234009f, 0.335693f, 0.462646f, 0.592285f, 0.702637f, 0.785645f, + 0.843750f, 0.883301f, 0.911133f, 0.929688f, 0.944336f, 0.954590f, 0.961914f, 0.967773f, 0.973633f, 0.977539f, 0.980469f, 0.982910f, + 0.985352f, 0.986816f, 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000100f, 0.000216f, 0.000243f, 0.000365f, 0.000517f, 0.000836f, 0.000964f, 0.001148f, + 0.001472f, 0.001674f, 0.001785f, 0.002438f, 0.002815f, 0.003490f, 0.004070f, 0.004837f, 0.005608f, 0.006630f, 0.008095f, 0.009483f, + 0.011551f, 0.013847f, 0.016953f, 0.020584f, 0.025879f, 0.033051f, 0.042664f, 0.055817f, 0.075500f, 0.105103f, 0.149536f, 0.216553f, + 0.312988f, 0.436768f, 0.568359f, 0.685059f, 0.773926f, 0.835449f, 0.878418f, 0.907227f, 0.927734f, 0.943359f, 0.953125f, 0.962402f, + 0.967285f, 0.973145f, 0.977051f, 0.980469f, 0.983887f, 0.985352f, 0.987305f, 0.989258f, 0.990234f, 0.991699f, 0.992188f, 0.993164f, + 0.994141f, 0.994629f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000150f, 0.000242f, 0.000364f, + 0.000441f, 0.000627f, 0.000916f, 0.000959f, 0.000968f, 0.001463f, 0.001671f, 0.002222f, 0.002577f, 0.002714f, 0.003479f, 0.004208f, + 0.004723f, 0.005669f, 0.006886f, 0.007637f, 0.009315f, 0.011154f, 0.013596f, 0.016205f, 0.019821f, 0.024963f, 0.031250f, 0.040375f, + 0.053009f, 0.071167f, 0.098511f, 0.139648f, 0.202271f, 0.293457f, 0.414307f, 0.548340f, 0.669434f, 0.762695f, 0.829590f, 0.874512f, + 0.904785f, 0.926758f, 0.941895f, 0.953613f, 0.961914f, 0.968262f, 0.973633f, 0.977539f, 0.980957f, 0.983398f, 0.985352f, 0.987793f, + 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.994629f, 0.998047f, 0.998535f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, + 0.000000f, 0.000231f, 0.000232f, 0.000363f, 0.000486f, 0.000503f, 0.000724f, 0.001104f, 0.001080f, 0.001271f, 0.001509f, 0.001976f, + 0.002247f, 0.002476f, 0.002895f, 0.003553f, 0.004192f, 0.004871f, 0.005623f, 0.006332f, 0.007584f, 0.008957f, 0.010849f, 0.012917f, + 0.015396f, 0.019226f, 0.023941f, 0.030060f, 0.038513f, 0.050385f, 0.067627f, 0.093140f, 0.131714f, 0.190674f, 0.278076f, 0.395752f, + 0.530273f, 0.655762f, 0.753906f, 0.823242f, 0.870605f, 0.903320f, 0.925781f, 0.941406f, 0.953125f, 0.961914f, 0.969238f, 0.974121f, + 0.978027f, 0.980957f, 0.983887f, 0.985840f, 0.988281f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.997559f, 0.998047f, + 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000000f, 0.000009f, 0.000116f, 0.000360f, 0.000484f, 0.000485f, 0.000536f, 0.000827f, + 0.000935f, 0.001077f, 0.001204f, 0.001561f, 0.001974f, 0.002136f, 0.002777f, 0.002964f, 0.003517f, 0.004192f, 0.004711f, 0.005505f, + 0.006283f, 0.007408f, 0.008713f, 0.010674f, 0.012375f, 0.015099f, 0.018677f, 0.022797f, 0.028732f, 0.036835f, 0.047974f, 0.064270f, + 0.088318f, 0.124634f, 0.180664f, 0.264893f, 0.380615f, 0.516113f, 0.645020f, 0.747559f, 0.819824f, 0.870117f, 0.902344f, 0.925293f, + 0.941406f, 0.953613f, 0.962402f, 0.969238f, 0.974121f, 0.978027f, 0.981934f, 0.984375f, 0.986328f, 0.988281f, 0.989746f, 0.990723f, + 0.992676f, 0.993164f, 0.997559f, 0.998047f, 0.998047f, 0.997559f, 0.998047f, 0.998047f, 0.000000f, 0.000000f, 0.000074f, 0.000337f, + 0.000481f, 0.000484f, 0.000485f, 0.000556f, 0.000823f, 0.001143f, 0.001187f, 0.001391f, 0.001781f, 0.002155f, 0.002327f, 0.002760f, + 0.003008f, 0.003433f, 0.004101f, 0.004681f, 0.005417f, 0.006443f, 0.007393f, 0.008560f, 0.010345f, 0.012177f, 0.014496f, 0.018127f, + 0.022125f, 0.027740f, 0.035736f, 0.046173f, 0.061920f, 0.084717f, 0.119324f, 0.173218f, 0.254883f, 0.368652f, 0.505371f, 0.637207f, + 0.742676f, 0.818359f, 0.868164f, 0.902832f, 0.925781f, 0.942383f, 0.953613f, 0.963379f, 0.970215f, 0.975098f, 0.979004f, 0.982422f, + 0.984863f, 0.986328f, 0.988770f, 0.990723f, 0.991699f, 0.992676f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, + 0.000000f, 0.000000f, 0.000000f, 0.000188f, 0.000358f, 0.000481f, 0.000484f, 0.000484f, 0.000704f, 0.000852f, 0.001165f, 0.001316f, + 0.001500f, 0.001685f, 0.001933f, 0.002079f, 0.002720f, 0.003136f, 0.003727f, 0.003723f, 0.004513f, 0.005207f, 0.006275f, 0.007236f, + 0.008453f, 0.010056f, 0.011848f, 0.014191f, 0.017212f, 0.021652f, 0.026978f, 0.034241f, 0.044678f, 0.058990f, 0.081421f, 0.114929f, + 0.167236f, 0.247070f, 0.360596f, 0.498291f, 0.632812f, 0.741211f, 0.818359f, 0.869629f, 0.903809f, 0.927734f, 0.943848f, 0.955566f, + 0.964355f, 0.970703f, 0.976074f, 0.979492f, 0.982422f, 0.985840f, 0.987793f, 0.989258f, 0.990723f, 0.992188f, 0.997070f, 0.997559f, + 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000121f, 0.000120f, 0.000288f, 0.000357f, 0.000479f, 0.000483f, + 0.000535f, 0.000711f, 0.000862f, 0.001256f, 0.001351f, 0.001502f, 0.001719f, 0.002146f, 0.002037f, 0.002653f, 0.003248f, 0.003222f, + 0.003820f, 0.004456f, 0.005173f, 0.006008f, 0.007072f, 0.008247f, 0.009758f, 0.011826f, 0.013771f, 0.016861f, 0.020935f, 0.025986f, + 0.032928f, 0.043030f, 0.057587f, 0.078918f, 0.111755f, 0.162964f, 0.241943f, 0.355713f, 0.495117f, 0.632324f, 0.742676f, 0.819336f, + 0.871582f, 0.905762f, 0.929688f, 0.945312f, 0.957031f, 0.965332f, 0.972168f, 0.976562f, 0.980957f, 0.983887f, 0.986328f, 0.988281f, + 0.990234f, 0.991699f, 0.997070f, 0.997559f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000000f, 0.000000f, 0.000121f, + 0.000200f, 0.000412f, 0.000471f, 0.000599f, 0.000598f, 0.000596f, 0.000805f, 0.001099f, 0.001334f, 0.001417f, 0.001456f, 0.001723f, + 0.002102f, 0.002283f, 0.002579f, 0.003208f, 0.003233f, 0.003740f, 0.004574f, 0.005287f, 0.006012f, 0.006870f, 0.008018f, 0.009354f, + 0.011208f, 0.013542f, 0.016495f, 0.020370f, 0.025284f, 0.032410f, 0.041901f, 0.056183f, 0.077087f, 0.109558f, 0.160278f, 0.239380f, + 0.354492f, 0.496094f, 0.635254f, 0.747070f, 0.823730f, 0.875488f, 0.908691f, 0.931641f, 0.947266f, 0.958008f, 0.966309f, 0.972656f, + 0.978027f, 0.981445f, 0.984863f, 0.986816f, 0.989258f, 0.990723f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, + 0.000000f, 0.000000f, 0.000000f, 0.000117f, 0.000237f, 0.000239f, 0.000430f, 0.000465f, 0.000599f, 0.000724f, 0.000716f, 0.000815f, + 0.000981f, 0.001334f, 0.001299f, 0.001545f, 0.001617f, 0.001935f, 0.002110f, 0.002501f, 0.002823f, 0.003408f, 0.003790f, 0.004467f, + 0.005112f, 0.005848f, 0.006718f, 0.007942f, 0.009514f, 0.011093f, 0.013092f, 0.015945f, 0.019608f, 0.024689f, 0.031494f, 0.041046f, + 0.054901f, 0.075989f, 0.108032f, 0.158936f, 0.239014f, 0.356201f, 0.500488f, 0.642090f, 0.753418f, 0.830566f, 0.880859f, 0.912598f, + 0.935059f, 0.950195f, 0.960449f, 0.968262f, 0.975098f, 0.979980f, 0.982910f, 0.985352f, 0.987793f, 0.990234f, 0.996582f, 0.997070f, + 0.997070f, 0.996582f, 0.997070f, 0.996582f, 0.000000f, 0.000000f, 0.000000f, 0.000117f, 0.000120f, 0.000121f, 0.000312f, 0.000407f, + 0.000707f, 0.000597f, 0.000648f, 0.000720f, 0.000941f, 0.001008f, 0.001229f, 0.001289f, 0.001423f, 0.001726f, 0.002060f, 0.002211f, + 0.002506f, 0.002985f, 0.003036f, 0.003683f, 0.004066f, 0.004833f, 0.005592f, 0.006611f, 0.007675f, 0.008965f, 0.010811f, 0.012833f, + 0.015854f, 0.019485f, 0.024429f, 0.031036f, 0.040466f, 0.054108f, 0.074890f, 0.107727f, 0.159180f, 0.241699f, 0.362549f, 0.510742f, + 0.653809f, 0.763184f, 0.837891f, 0.887207f, 0.917480f, 0.938477f, 0.953613f, 0.962891f, 0.970703f, 0.976562f, 0.980469f, 0.984375f, + 0.986816f, 0.988770f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000000f, 0.000000f, 0.000000f, 0.000117f, + 0.000118f, 0.000120f, 0.000129f, 0.000434f, 0.000536f, 0.000613f, 0.000716f, 0.000799f, 0.000720f, 0.000768f, 0.001024f, 0.001202f, + 0.001501f, 0.001530f, 0.001568f, 0.001897f, 0.002190f, 0.002502f, 0.002893f, 0.003105f, 0.003551f, 0.004021f, 0.004791f, 0.005405f, + 0.006313f, 0.007309f, 0.008720f, 0.010712f, 0.012657f, 0.015472f, 0.018982f, 0.023697f, 0.030579f, 0.040009f, 0.054138f, 0.075012f, + 0.107849f, 0.161377f, 0.247070f, 0.373047f, 0.525391f, 0.667969f, 0.776855f, 0.847656f, 0.894043f, 0.923340f, 0.942871f, 0.956543f, + 0.965820f, 0.973145f, 0.978027f, 0.982422f, 0.985352f, 0.987793f, 0.996094f, 0.996094f, 0.996582f, 0.996094f, 0.996582f, 0.996094f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000081f, 0.000116f, 0.000227f, 0.000360f, 0.000366f, 0.000642f, 0.000691f, 0.000711f, + 0.000806f, 0.000721f, 0.000925f, 0.000947f, 0.001155f, 0.001478f, 0.001554f, 0.001612f, 0.001929f, 0.002354f, 0.002291f, 0.002712f, + 0.003029f, 0.003441f, 0.003876f, 0.004452f, 0.005276f, 0.006256f, 0.007149f, 0.008568f, 0.010040f, 0.012566f, 0.015160f, 0.018677f, + 0.023376f, 0.030411f, 0.039642f, 0.053986f, 0.075134f, 0.109436f, 0.165527f, 0.255127f, 0.387695f, 0.544434f, 0.686523f, 0.791016f, + 0.858398f, 0.901367f, 0.928711f, 0.947266f, 0.959961f, 0.968262f, 0.975098f, 0.980469f, 0.983887f, 0.987305f, 0.995605f, 0.996094f, + 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000088f, 0.000085f, 0.000338f, 0.000351f, + 0.000359f, 0.000480f, 0.000539f, 0.000698f, 0.000798f, 0.000793f, 0.000834f, 0.000891f, 0.000941f, 0.001143f, 0.001422f, 0.001512f, + 0.001833f, 0.001955f, 0.002144f, 0.002426f, 0.002716f, 0.003262f, 0.003572f, 0.003860f, 0.004456f, 0.005173f, 0.006191f, 0.006939f, + 0.008545f, 0.010162f, 0.012375f, 0.014969f, 0.018555f, 0.023376f, 0.029953f, 0.039673f, 0.054077f, 0.076477f, 0.112000f, 0.171509f, + 0.268066f, 0.408203f, 0.569336f, 0.709961f, 0.808105f, 0.872070f, 0.910645f, 0.935059f, 0.951660f, 0.963379f, 0.971680f, 0.977539f, + 0.982422f, 0.985840f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000116f, 0.000340f, 0.000353f, 0.000349f, 0.000480f, 0.000576f, 0.000668f, 0.000700f, 0.000818f, 0.000833f, + 0.000787f, 0.001125f, 0.001110f, 0.001407f, 0.001489f, 0.001563f, 0.001804f, 0.002073f, 0.002285f, 0.002409f, 0.002985f, 0.003052f, + 0.003853f, 0.004433f, 0.005100f, 0.006046f, 0.007046f, 0.008156f, 0.009827f, 0.012138f, 0.014740f, 0.018311f, 0.023071f, 0.029770f, + 0.040009f, 0.054810f, 0.078003f, 0.116150f, 0.180176f, 0.284668f, 0.434570f, 0.599121f, 0.735352f, 0.827637f, 0.885254f, 0.919922f, + 0.941895f, 0.957031f, 0.967285f, 0.975098f, 0.979980f, 0.984375f, 0.995117f, 0.995117f, 0.995117f, 0.995117f, 0.995117f, 0.995605f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000000f, 0.000122f, 0.000235f, 0.000320f, 0.000351f, 0.000353f, 0.000478f, + 0.000602f, 0.000651f, 0.000793f, 0.000706f, 0.000816f, 0.000814f, 0.000898f, 0.001062f, 0.001259f, 0.001441f, 0.001564f, 0.001772f, + 0.001743f, 0.002134f, 0.002512f, 0.002668f, 0.003193f, 0.003746f, 0.004341f, 0.004902f, 0.005909f, 0.006920f, 0.008125f, 0.009605f, + 0.011711f, 0.014549f, 0.018280f, 0.023163f, 0.030334f, 0.040375f, 0.055939f, 0.080566f, 0.122070f, 0.192383f, 0.307373f, 0.467773f, + 0.634277f, 0.763184f, 0.846191f, 0.897461f, 0.928711f, 0.948730f, 0.962402f, 0.971680f, 0.978516f, 0.982422f, 0.994141f, 0.994629f, + 0.994629f, 0.995117f, 0.995117f, 0.995117f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000185f, 0.000190f, + 0.000272f, 0.000281f, 0.000464f, 0.000466f, 0.000476f, 0.000521f, 0.000654f, 0.000680f, 0.000699f, 0.000815f, 0.000814f, 0.000890f, + 0.001110f, 0.001283f, 0.001311f, 0.001590f, 0.001727f, 0.001801f, 0.002020f, 0.002312f, 0.002897f, 0.003267f, 0.003592f, 0.004143f, + 0.004810f, 0.005844f, 0.006618f, 0.008018f, 0.009697f, 0.011597f, 0.014374f, 0.018127f, 0.023056f, 0.030258f, 0.041107f, 0.057373f, + 0.084045f, 0.129517f, 0.208618f, 0.337646f, 0.508789f, 0.673828f, 0.793457f, 0.866211f, 0.911133f, 0.938965f, 0.955566f, 0.967285f, + 0.975586f, 0.980469f, 0.994141f, 0.994141f, 0.994629f, 0.994629f, 0.994629f, 0.994141f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000226f, 0.000431f, 0.000456f, 0.000467f, 0.000352f, 0.000496f, 0.000588f, + 0.000891f, 0.000771f, 0.000803f, 0.000947f, 0.000972f, 0.001078f, 0.001033f, 0.001279f, 0.001436f, 0.001483f, 0.001831f, 0.002033f, + 0.002264f, 0.002710f, 0.002996f, 0.003582f, 0.004032f, 0.004665f, 0.005592f, 0.006527f, 0.007820f, 0.009323f, 0.011581f, 0.014328f, + 0.018219f, 0.023239f, 0.030777f, 0.042084f, 0.059448f, 0.089233f, 0.140869f, 0.230713f, 0.375977f, 0.556641f, 0.715332f, 0.822266f, + 0.885742f, 0.924316f, 0.947266f, 0.962402f, 0.972656f, 0.978516f, 0.993164f, 0.994141f, 0.994141f, 0.994141f, 0.994141f, 0.994141f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000283f, 0.000229f, 0.000425f, + 0.000303f, 0.000336f, 0.000469f, 0.000474f, 0.000728f, 0.000663f, 0.000883f, 0.000695f, 0.000679f, 0.000858f, 0.000919f, 0.000980f, + 0.001218f, 0.001330f, 0.001665f, 0.001637f, 0.002054f, 0.002335f, 0.002508f, 0.002880f, 0.003323f, 0.004055f, 0.004730f, 0.005463f, + 0.006485f, 0.007740f, 0.009293f, 0.011566f, 0.014175f, 0.017944f, 0.023346f, 0.031433f, 0.043304f, 0.063232f, 0.096313f, 0.155518f, + 0.260498f, 0.424561f, 0.611328f, 0.758789f, 0.852051f, 0.904785f, 0.937012f, 0.955566f, 0.968262f, 0.977051f, 0.992676f, 0.992676f, + 0.993164f, 0.993652f, 0.993164f, 0.993652f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000256f, 0.000216f, 0.000406f, 0.000426f, 0.000457f, 0.000453f, 0.000472f, 0.000651f, 0.000593f, 0.000876f, + 0.000571f, 0.000590f, 0.000819f, 0.000809f, 0.001000f, 0.001224f, 0.001293f, 0.001637f, 0.001790f, 0.001863f, 0.002298f, 0.002550f, + 0.002995f, 0.003201f, 0.003933f, 0.004677f, 0.005360f, 0.006447f, 0.007763f, 0.009377f, 0.011330f, 0.014420f, 0.017944f, 0.023560f, + 0.032196f, 0.045380f, 0.067383f, 0.105469f, 0.175659f, 0.301025f, 0.484375f, 0.669922f, 0.801270f, 0.879395f, 0.922852f, 0.948242f, + 0.963379f, 0.974121f, 0.992188f, 0.992188f, 0.992188f, 0.993164f, 0.992188f, 0.993164f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000230f, 0.000206f, 0.000355f, 0.000335f, 0.000305f, + 0.000461f, 0.000565f, 0.000474f, 0.000429f, 0.000520f, 0.000758f, 0.000777f, 0.000668f, 0.000821f, 0.001013f, 0.001089f, 0.001325f, + 0.001570f, 0.001787f, 0.001707f, 0.002037f, 0.002457f, 0.002892f, 0.003359f, 0.003881f, 0.004616f, 0.005203f, 0.006336f, 0.007477f, + 0.009048f, 0.011345f, 0.014015f, 0.018356f, 0.024307f, 0.033661f, 0.048279f, 0.073303f, 0.118774f, 0.204102f, 0.354492f, 0.554688f, + 0.729492f, 0.840332f, 0.902832f, 0.937988f, 0.958008f, 0.971191f, 0.991699f, 0.992188f, 0.992188f, 0.991699f, 0.992188f, 0.991699f, + 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000205f, 0.000248f, 0.000213f, 0.000344f, 0.000437f, 0.000351f, 0.000352f, 0.000359f, 0.000389f, 0.000482f, 0.000676f, 0.000560f, + 0.000806f, 0.000813f, 0.000927f, 0.001230f, 0.001392f, 0.001526f, 0.001627f, 0.001629f, 0.002047f, 0.002321f, 0.002661f, 0.003317f, + 0.003752f, 0.004406f, 0.005119f, 0.005936f, 0.007156f, 0.009003f, 0.010941f, 0.013985f, 0.018539f, 0.025131f, 0.035248f, 0.051880f, + 0.081543f, 0.137207f, 0.244507f, 0.424561f, 0.632812f, 0.787598f, 0.876465f, 0.924805f, 0.951172f, 0.966797f, 0.990723f, 0.991211f, + 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000224f, 0.000171f, 0.000276f, 0.000278f, 0.000288f, 0.000329f, 0.000365f, + 0.000459f, 0.000483f, 0.000626f, 0.000716f, 0.000767f, 0.000793f, 0.000800f, 0.000897f, 0.000976f, 0.001156f, 0.001322f, 0.001427f, + 0.001799f, 0.001997f, 0.002256f, 0.002773f, 0.002806f, 0.003515f, 0.004040f, 0.004910f, 0.005730f, 0.007046f, 0.008858f, 0.011124f, + 0.014374f, 0.018982f, 0.026123f, 0.037659f, 0.057129f, 0.093445f, 0.164062f, 0.301514f, 0.511230f, 0.712402f, 0.838867f, 0.906738f, + 0.942383f, 0.961914f, 0.989746f, 0.990234f, 0.989746f, 0.990234f, 0.989746f, 0.990234f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000173f, 0.000140f, + 0.000138f, 0.000232f, 0.000291f, 0.000318f, 0.000338f, 0.000346f, 0.000422f, 0.000368f, 0.000680f, 0.000722f, 0.000765f, 0.000766f, + 0.000803f, 0.001069f, 0.001103f, 0.001185f, 0.001611f, 0.001593f, 0.001939f, 0.002211f, 0.002569f, 0.003008f, 0.003239f, 0.003952f, + 0.004681f, 0.005630f, 0.007008f, 0.008720f, 0.011200f, 0.014587f, 0.019653f, 0.027527f, 0.040955f, 0.064514f, 0.110413f, 0.204224f, + 0.381104f, 0.609863f, 0.785645f, 0.881836f, 0.931152f, 0.956543f, 0.988770f, 0.989258f, 0.989258f, 0.989258f, 0.989258f, 0.988770f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, + 0.000121f, 0.000123f, 0.000121f, 0.000090f, 0.000102f, 0.000063f, 0.000156f, 0.000248f, 0.000333f, 0.000321f, 0.000431f, 0.000392f, + 0.000349f, 0.000434f, 0.000674f, 0.000741f, 0.000776f, 0.000936f, 0.000888f, 0.001049f, 0.001179f, 0.001326f, 0.001686f, 0.001732f, + 0.002050f, 0.002150f, 0.002453f, 0.003016f, 0.003601f, 0.004444f, 0.005692f, 0.006741f, 0.008324f, 0.011093f, 0.014709f, 0.020752f, + 0.029800f, 0.045654f, 0.074951f, 0.136108f, 0.264893f, 0.486816f, 0.710938f, 0.848145f, 0.916992f, 0.950684f, 0.987305f, 0.987793f, + 0.987793f, 0.988281f, 0.987793f, 0.987793f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000100f, 0.000049f, 0.000039f, 0.000125f, 0.000121f, + 0.000184f, 0.000280f, 0.000366f, 0.000392f, 0.000333f, 0.000341f, 0.000477f, 0.000597f, 0.000607f, 0.000747f, 0.000767f, 0.000961f, + 0.000936f, 0.001056f, 0.001306f, 0.001388f, 0.001633f, 0.001836f, 0.001997f, 0.002348f, 0.002878f, 0.003332f, 0.004131f, 0.005165f, + 0.006519f, 0.008568f, 0.011444f, 0.015419f, 0.021881f, 0.032532f, 0.052032f, 0.091187f, 0.177246f, 0.357910f, 0.610352f, 0.800781f, + 0.897461f, 0.942871f, 0.985352f, 0.986328f, 0.986816f, 0.986328f, 0.986328f, 0.986328f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000099f, 0.000076f, + 0.000060f, 0.000108f, 0.000040f, 0.000127f, 0.000127f, 0.000121f, 0.000200f, 0.000265f, 0.000360f, 0.000316f, 0.000428f, 0.000455f, + 0.000456f, 0.000583f, 0.000682f, 0.000750f, 0.000773f, 0.000824f, 0.000937f, 0.001220f, 0.001262f, 0.001384f, 0.001622f, 0.001862f, + 0.002157f, 0.002817f, 0.003414f, 0.004082f, 0.004993f, 0.006561f, 0.008560f, 0.011696f, 0.016022f, 0.023529f, 0.036469f, 0.062286f, + 0.117126f, 0.245605f, 0.487549f, 0.732910f, 0.870605f, 0.933105f, 0.983887f, 0.984863f, 0.984863f, 0.984863f, 0.984375f, 0.984863f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000096f, 0.000075f, 0.000061f, 0.000083f, 0.000096f, 0.000034f, 0.000101f, 0.000121f, 0.000137f, + 0.000211f, 0.000324f, 0.000381f, 0.000373f, 0.000420f, 0.000472f, 0.000494f, 0.000690f, 0.000793f, 0.000768f, 0.000853f, 0.000867f, + 0.000978f, 0.001003f, 0.001145f, 0.001416f, 0.001888f, 0.002125f, 0.002491f, 0.003004f, 0.003864f, 0.005028f, 0.006500f, 0.008682f, + 0.011856f, 0.016922f, 0.025757f, 0.042603f, 0.078247f, 0.161743f, 0.358398f, 0.641602f, 0.833496f, 0.920410f, 0.981934f, 0.982910f, + 0.982910f, 0.982910f, 0.982910f, 0.982910f, 0.000122f, 0.000000f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000097f, 0.000078f, 0.000062f, 0.000051f, + 0.000043f, 0.000072f, 0.000030f, 0.000060f, 0.000109f, 0.000206f, 0.000216f, 0.000333f, 0.000347f, 0.000395f, 0.000415f, 0.000458f, + 0.000568f, 0.000664f, 0.000709f, 0.000598f, 0.000781f, 0.000628f, 0.001053f, 0.001046f, 0.001179f, 0.001579f, 0.001649f, 0.002386f, + 0.002857f, 0.003727f, 0.004894f, 0.006363f, 0.008789f, 0.012314f, 0.018616f, 0.029709f, 0.052429f, 0.105652f, 0.244385f, 0.524414f, + 0.782715f, 0.904785f, 0.979492f, 0.980957f, 0.979980f, 0.979980f, 0.980469f, 0.980469f, 0.000000f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, + 0.000120f, 0.000097f, 0.000079f, 0.000065f, 0.000054f, 0.000045f, 0.000073f, 0.000032f, 0.000089f, 0.000038f, 0.000134f, 0.000138f, + 0.000211f, 0.000333f, 0.000370f, 0.000400f, 0.000420f, 0.000496f, 0.000566f, 0.000494f, 0.000584f, 0.000714f, 0.000708f, 0.000843f, + 0.001056f, 0.001019f, 0.001327f, 0.001812f, 0.001908f, 0.002798f, 0.003479f, 0.004578f, 0.006195f, 0.008881f, 0.012901f, 0.020599f, + 0.035339f, 0.069214f, 0.159058f, 0.394531f, 0.709961f, 0.882812f, 0.977051f, 0.978027f, 0.977539f, 0.976562f, 0.977051f, 0.977539f, + 0.000000f, 0.000121f, 0.000120f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, + 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000120f, 0.000102f, 0.000084f, 0.000071f, 0.000059f, 0.000048f, 0.000041f, + 0.000035f, 0.000062f, 0.000026f, 0.000098f, 0.000103f, 0.000136f, 0.000230f, 0.000327f, 0.000356f, 0.000338f, 0.000387f, 0.000499f, + 0.000577f, 0.000627f, 0.000669f, 0.000611f, 0.000699f, 0.000904f, 0.000893f, 0.001340f, 0.001666f, 0.002068f, 0.002377f, 0.003105f, + 0.004345f, 0.006218f, 0.009178f, 0.013962f, 0.024170f, 0.045441f, 0.101868f, 0.271973f, 0.612305f, 0.853027f, 0.973145f, 0.974121f, + 0.973633f, 0.974121f, 0.973633f, 0.974121f, 0.000121f, 0.000120f, 0.000119f, 0.000120f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, + 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000108f, + 0.000091f, 0.000075f, 0.000063f, 0.000053f, 0.000045f, 0.000039f, 0.000034f, 0.000040f, 0.000090f, 0.000068f, 0.000104f, 0.000127f, + 0.000220f, 0.000302f, 0.000412f, 0.000316f, 0.000444f, 0.000495f, 0.000428f, 0.000510f, 0.000463f, 0.000614f, 0.000726f, 0.000719f, + 0.001164f, 0.001533f, 0.001707f, 0.002079f, 0.002848f, 0.004189f, 0.006142f, 0.009491f, 0.016113f, 0.029343f, 0.064758f, 0.175415f, + 0.490723f, 0.812012f, 0.968750f, 0.969727f, 0.969238f, 0.969727f, 0.969727f, 0.969727f, 0.000000f, 0.000117f, 0.000117f, 0.000115f, + 0.000118f, 0.000118f, 0.000117f, 0.000117f, 0.000117f, 0.000117f, 0.000118f, 0.000117f, 0.000117f, 0.000118f, 0.000117f, 0.000117f, + 0.000117f, 0.000117f, 0.000117f, 0.000118f, 0.000117f, 0.000100f, 0.000082f, 0.000070f, 0.000060f, 0.000051f, 0.000043f, 0.000038f, + 0.000033f, 0.000053f, 0.000027f, 0.000089f, 0.000105f, 0.000137f, 0.000227f, 0.000277f, 0.000293f, 0.000284f, 0.000300f, 0.000420f, + 0.000367f, 0.000473f, 0.000467f, 0.000555f, 0.000625f, 0.000870f, 0.001177f, 0.001563f, 0.001982f, 0.002714f, 0.004051f, 0.006134f, + 0.010384f, 0.018967f, 0.040314f, 0.108887f, 0.358643f, 0.755859f, 0.962891f, 0.963867f, 0.964355f, 0.963867f, 0.963379f, 0.963379f, + 0.000000f, 0.000000f, 0.000098f, 0.000103f, 0.000111f, 0.000112f, 0.000112f, 0.000114f, 0.000113f, 0.000115f, 0.000114f, 0.000115f, + 0.000115f, 0.000115f, 0.000115f, 0.000115f, 0.000116f, 0.000116f, 0.000116f, 0.000116f, 0.000116f, 0.000116f, 0.000109f, 0.000094f, + 0.000078f, 0.000067f, 0.000058f, 0.000050f, 0.000043f, 0.000038f, 0.000033f, 0.000054f, 0.000025f, 0.000078f, 0.000091f, 0.000173f, + 0.000203f, 0.000252f, 0.000331f, 0.000277f, 0.000264f, 0.000407f, 0.000342f, 0.000444f, 0.000470f, 0.000542f, 0.000773f, 0.001081f, + 0.001245f, 0.001682f, 0.002602f, 0.003744f, 0.006248f, 0.011566f, 0.025040f, 0.065491f, 0.236938f, 0.678223f, 0.956055f, 0.956543f, + 0.956543f, 0.956543f, 0.957031f, 0.957031f, 0.000000f, 0.000000f, 0.000021f, 0.000080f, 0.000072f, 0.000089f, 0.000100f, 0.000099f, + 0.000105f, 0.000107f, 0.000107f, 0.000110f, 0.000109f, 0.000110f, 0.000111f, 0.000111f, 0.000112f, 0.000112f, 0.000112f, 0.000113f, + 0.000113f, 0.000113f, 0.000113f, 0.000113f, 0.000105f, 0.000090f, 0.000078f, 0.000067f, 0.000057f, 0.000050f, 0.000043f, 0.000038f, + 0.000033f, 0.000029f, 0.000025f, 0.000055f, 0.000091f, 0.000130f, 0.000225f, 0.000275f, 0.000254f, 0.000290f, 0.000259f, 0.000378f, + 0.000333f, 0.000362f, 0.000458f, 0.000587f, 0.000876f, 0.001062f, 0.001382f, 0.002398f, 0.003763f, 0.006603f, 0.014496f, 0.038300f, + 0.143677f, 0.573730f, 0.946777f, 0.947266f, 0.947266f, 0.947266f, 0.948242f, 0.947266f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000014f, 0.000036f, 0.000072f, 0.000082f, 0.000080f, 0.000094f, 0.000096f, 0.000099f, 0.000098f, 0.000103f, 0.000103f, + 0.000103f, 0.000106f, 0.000105f, 0.000107f, 0.000107f, 0.000108f, 0.000108f, 0.000109f, 0.000109f, 0.000109f, 0.000105f, 0.000090f, + 0.000078f, 0.000067f, 0.000059f, 0.000051f, 0.000045f, 0.000039f, 0.000034f, 0.000030f, 0.000026f, 0.000045f, 0.000086f, 0.000108f, + 0.000143f, 0.000212f, 0.000227f, 0.000204f, 0.000231f, 0.000263f, 0.000315f, 0.000354f, 0.000481f, 0.000702f, 0.000888f, 0.001257f, + 0.002018f, 0.003738f, 0.007675f, 0.021317f, 0.080933f, 0.444336f, 0.934082f, 0.935059f, 0.935059f, 0.935059f, 0.935059f, 0.935059f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000024f, 0.000038f, 0.000059f, + 0.000063f, 0.000076f, 0.000080f, 0.000085f, 0.000089f, 0.000091f, 0.000092f, 0.000095f, 0.000097f, 0.000099f, 0.000098f, 0.000101f, + 0.000101f, 0.000102f, 0.000103f, 0.000104f, 0.000104f, 0.000091f, 0.000080f, 0.000069f, 0.000062f, 0.000053f, 0.000046f, 0.000041f, + 0.000035f, 0.000032f, 0.000027f, 0.000039f, 0.000052f, 0.000103f, 0.000139f, 0.000178f, 0.000190f, 0.000178f, 0.000185f, 0.000247f, + 0.000274f, 0.000368f, 0.000528f, 0.000637f, 0.001027f, 0.001937f, 0.003853f, 0.010445f, 0.041718f, 0.304199f, 0.917480f, 0.917480f, + 0.917969f, 0.917480f, 0.918457f, 0.917969f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000023f, 0.000037f, 0.000048f, 0.000048f, 0.000063f, 0.000063f, + 0.000074f, 0.000077f, 0.000080f, 0.000083f, 0.000086f, 0.000088f, 0.000090f, 0.000091f, 0.000092f, 0.000094f, 0.000095f, 0.000096f, + 0.000084f, 0.000073f, 0.000064f, 0.000057f, 0.000049f, 0.000043f, 0.000037f, 0.000033f, 0.000029f, 0.000025f, 0.000060f, 0.000061f, + 0.000087f, 0.000118f, 0.000156f, 0.000131f, 0.000175f, 0.000226f, 0.000230f, 0.000373f, 0.000507f, 0.000992f, 0.001814f, 0.004639f, + 0.018799f, 0.176758f, 0.894043f, 0.894531f, 0.895508f, 0.895020f, 0.895020f, 0.895996f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000019f, 0.000028f, 0.000034f, 0.000043f, 0.000052f, 0.000057f, 0.000062f, 0.000067f, + 0.000070f, 0.000074f, 0.000075f, 0.000079f, 0.000081f, 0.000083f, 0.000085f, 0.000076f, 0.000068f, 0.000059f, 0.000051f, 0.000046f, + 0.000040f, 0.000035f, 0.000030f, 0.000026f, 0.000028f, 0.000038f, 0.000072f, 0.000100f, 0.000120f, 0.000107f, 0.000152f, 0.000156f, + 0.000254f, 0.000436f, 0.000722f, 0.001875f, 0.007088f, 0.083069f, 0.863281f, 0.862305f, 0.863281f, 0.862305f, 0.863281f, 0.862793f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000005f, 0.000015f, 0.000022f, 0.000030f, 0.000037f, 0.000042f, 0.000048f, 0.000053f, 0.000058f, 0.000060f, + 0.000064f, 0.000067f, 0.000069f, 0.000061f, 0.000053f, 0.000047f, 0.000041f, 0.000036f, 0.000031f, 0.000027f, 0.000023f, 0.000020f, + 0.000036f, 0.000063f, 0.000082f, 0.000081f, 0.000104f, 0.000149f, 0.000263f, 0.000616f, 0.002337f, 0.028168f, 0.816406f, 0.816895f, + 0.816895f, 0.816895f, 0.817383f, 0.816895f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000003f, 0.000011f, 0.000019f, 0.000026f, 0.000031f, 0.000036f, 0.000041f, 0.000045f, 0.000050f, 0.000047f, + 0.000041f, 0.000036f, 0.000031f, 0.000027f, 0.000023f, 0.000019f, 0.000028f, 0.000029f, 0.000053f, 0.000052f, 0.000072f, 0.000165f, + 0.000511f, 0.006050f, 0.751465f, 0.752441f, 0.752930f, 0.752441f, 0.752441f, 0.752930f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000011f, 0.000017f, 0.000021f, 0.000027f, 0.000028f, 0.000024f, 0.000020f, 0.000017f, + 0.000013f, 0.000020f, 0.000021f, 0.000029f, 0.000057f, 0.000588f, 0.665039f, 0.664551f, 0.665527f, 0.665039f, 0.665039f, 0.665039f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000009f, 0.000006f, 0.000004f, 0.000007f, 0.557129f, 0.558105f, + 0.557617f, 0.557617f, 0.558594f, 0.558105f, + }, + { + 0.163818f, 0.558105f, 0.755859f, 0.841797f, 0.886230f, 0.912109f, 0.929199f, 0.941406f, 0.950195f, 0.957031f, 0.961914f, 0.966309f, + 0.970215f, 0.972656f, 0.975586f, 0.978027f, 0.979492f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.987305f, 0.988770f, + 0.989258f, 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.993652f, 0.993652f, 0.994141f, 0.995117f, + 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.998047f, 0.998047f, + 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.027023f, 0.138184f, 0.353760f, 0.583984f, 0.735352f, 0.819336f, 0.868652f, 0.898926f, + 0.918945f, 0.933594f, 0.943848f, 0.952148f, 0.958984f, 0.963867f, 0.967773f, 0.971680f, 0.974121f, 0.976562f, 0.978516f, 0.980469f, + 0.982422f, 0.983398f, 0.984863f, 0.986328f, 0.986816f, 0.988281f, 0.989258f, 0.989746f, 0.990723f, 0.990723f, 0.991699f, 0.992676f, + 0.993164f, 0.993164f, 0.993652f, 0.994141f, 0.994141f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, + 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.009819f, 0.044250f, 0.113525f, 0.244995f, + 0.430420f, 0.608887f, 0.733887f, 0.810547f, 0.860352f, 0.892578f, 0.913086f, 0.929688f, 0.940918f, 0.949219f, 0.956055f, 0.961426f, + 0.966309f, 0.970215f, 0.972656f, 0.975586f, 0.977539f, 0.979980f, 0.980957f, 0.983398f, 0.983887f, 0.985352f, 0.986328f, 0.987793f, + 0.988281f, 0.989746f, 0.989746f, 0.991211f, 0.991699f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.993652f, 0.994141f, 0.995117f, + 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.004848f, 0.020447f, 0.046814f, 0.096313f, 0.183228f, 0.319092f, 0.484375f, 0.631836f, 0.739258f, 0.810547f, 0.857422f, 0.888672f, + 0.910645f, 0.925781f, 0.938965f, 0.947754f, 0.954590f, 0.960449f, 0.964355f, 0.968750f, 0.971191f, 0.974609f, 0.977051f, 0.979004f, + 0.980957f, 0.982422f, 0.983887f, 0.985840f, 0.986816f, 0.987793f, 0.988770f, 0.989258f, 0.990234f, 0.990723f, 0.991211f, 0.991699f, + 0.992676f, 0.992676f, 0.993652f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, + 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.003096f, 0.011017f, 0.024399f, 0.046600f, 0.083191f, 0.145386f, 0.243774f, 0.379395f, + 0.529297f, 0.656738f, 0.750977f, 0.813965f, 0.857910f, 0.887695f, 0.909668f, 0.925293f, 0.937500f, 0.946289f, 0.953613f, 0.959473f, + 0.964355f, 0.968262f, 0.971191f, 0.974121f, 0.976562f, 0.979004f, 0.980957f, 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.987793f, + 0.988281f, 0.989258f, 0.989746f, 0.991211f, 0.991699f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, + 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, + 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.001808f, 0.006992f, 0.014923f, 0.026413f, + 0.044403f, 0.073120f, 0.119446f, 0.193115f, 0.300537f, 0.433594f, 0.568848f, 0.680664f, 0.763184f, 0.821289f, 0.860840f, 0.890137f, + 0.909668f, 0.925293f, 0.937500f, 0.945801f, 0.953613f, 0.959473f, 0.963867f, 0.968262f, 0.971680f, 0.974609f, 0.977051f, 0.979004f, + 0.980957f, 0.982422f, 0.983887f, 0.984863f, 0.986816f, 0.987305f, 0.987793f, 0.989746f, 0.989746f, 0.991211f, 0.991699f, 0.992188f, + 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.994629f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997070f, + 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.001668f, 0.005253f, 0.010010f, 0.016602f, 0.026459f, 0.042023f, 0.065369f, 0.101868f, 0.158081f, 0.241455f, 0.354248f, 0.483887f, + 0.606934f, 0.706055f, 0.777832f, 0.830566f, 0.867188f, 0.893066f, 0.912109f, 0.926270f, 0.938477f, 0.946289f, 0.953125f, 0.959473f, + 0.964355f, 0.968750f, 0.971680f, 0.975098f, 0.977051f, 0.979492f, 0.980957f, 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.987305f, + 0.988770f, 0.989746f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.993164f, 0.994141f, 0.994629f, 0.994629f, 0.995117f, 0.995605f, + 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998047f, 0.998535f, 0.999023f, 0.999023f, + 0.999512f, 0.999512f, 0.999512f, 0.999023f, 0.001086f, 0.003477f, 0.006756f, 0.011604f, 0.018066f, 0.027222f, 0.039978f, 0.059448f, + 0.088257f, 0.132690f, 0.198120f, 0.291504f, 0.408447f, 0.531250f, 0.641602f, 0.728516f, 0.793457f, 0.839844f, 0.873047f, 0.896973f, + 0.915527f, 0.929199f, 0.939941f, 0.948730f, 0.955566f, 0.960938f, 0.965332f, 0.969238f, 0.972168f, 0.975098f, 0.977539f, 0.979492f, + 0.981445f, 0.983398f, 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.989258f, 0.989746f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, + 0.993652f, 0.994141f, 0.994629f, 0.994629f, 0.995605f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f, + 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000982f, 0.002764f, 0.004925f, 0.008194f, + 0.012703f, 0.018417f, 0.026154f, 0.037964f, 0.053894f, 0.078552f, 0.113770f, 0.166626f, 0.242310f, 0.343262f, 0.460449f, 0.576660f, + 0.675293f, 0.753418f, 0.809570f, 0.851074f, 0.879883f, 0.902344f, 0.919434f, 0.931152f, 0.941895f, 0.950195f, 0.956055f, 0.960938f, + 0.965820f, 0.969727f, 0.973145f, 0.976074f, 0.978027f, 0.980469f, 0.981934f, 0.983887f, 0.985352f, 0.986328f, 0.987793f, 0.988770f, + 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, + 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000723f, 0.002268f, 0.003639f, 0.006371f, 0.009392f, 0.013046f, 0.018570f, 0.026016f, 0.035919f, 0.049957f, 0.070618f, 0.099609f, + 0.142212f, 0.204590f, 0.290039f, 0.396973f, 0.512207f, 0.619141f, 0.707520f, 0.775391f, 0.825195f, 0.860352f, 0.887207f, 0.907715f, + 0.923340f, 0.935547f, 0.944824f, 0.951660f, 0.958496f, 0.963379f, 0.967773f, 0.971191f, 0.974121f, 0.977051f, 0.979492f, 0.980957f, + 0.982910f, 0.984375f, 0.985352f, 0.987305f, 0.988281f, 0.989258f, 0.989746f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993164f, + 0.994141f, 0.994629f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000364f, 0.001690f, 0.003056f, 0.004982f, 0.007217f, 0.010124f, 0.013931f, 0.018738f, + 0.025177f, 0.034332f, 0.045990f, 0.063599f, 0.088501f, 0.124146f, 0.175781f, 0.248047f, 0.341797f, 0.451416f, 0.562012f, 0.659668f, + 0.738281f, 0.797852f, 0.841797f, 0.872559f, 0.896484f, 0.914062f, 0.928711f, 0.938477f, 0.947266f, 0.954590f, 0.959473f, 0.964844f, + 0.969238f, 0.972168f, 0.975098f, 0.977539f, 0.979980f, 0.981934f, 0.983398f, 0.985352f, 0.986816f, 0.987793f, 0.988770f, 0.989746f, + 0.990723f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, + 0.997070f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000365f, 0.001221f, 0.002531f, 0.003979f, + 0.005829f, 0.007874f, 0.010475f, 0.013962f, 0.018402f, 0.024368f, 0.032257f, 0.042847f, 0.057983f, 0.079346f, 0.109375f, 0.153198f, + 0.214233f, 0.295898f, 0.397705f, 0.506836f, 0.609863f, 0.698730f, 0.767578f, 0.817871f, 0.854980f, 0.883301f, 0.903809f, 0.920410f, + 0.933105f, 0.942871f, 0.950195f, 0.957031f, 0.962402f, 0.966797f, 0.970703f, 0.973633f, 0.976562f, 0.979004f, 0.981445f, 0.982910f, + 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.989746f, 0.989746f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, + 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.000343f, 0.001357f, 0.002039f, 0.003130f, 0.004398f, 0.006432f, 0.008141f, 0.010925f, 0.014008f, 0.018326f, 0.023331f, 0.030655f, + 0.040558f, 0.053680f, 0.071960f, 0.098206f, 0.134644f, 0.187012f, 0.258057f, 0.349854f, 0.455566f, 0.562012f, 0.656738f, 0.734863f, + 0.792969f, 0.836914f, 0.868652f, 0.894043f, 0.912598f, 0.926758f, 0.937988f, 0.947266f, 0.954590f, 0.960449f, 0.964355f, 0.968750f, + 0.972656f, 0.975586f, 0.978027f, 0.980469f, 0.981934f, 0.983398f, 0.985840f, 0.986816f, 0.988281f, 0.989258f, 0.990723f, 0.990723f, + 0.991699f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000244f, 0.001185f, 0.001561f, 0.002504f, 0.003990f, 0.005272f, 0.006573f, 0.008606f, + 0.010933f, 0.013878f, 0.017715f, 0.022415f, 0.029068f, 0.038086f, 0.049774f, 0.066162f, 0.088257f, 0.120361f, 0.164917f, 0.227173f, + 0.308838f, 0.407959f, 0.515137f, 0.615723f, 0.700684f, 0.767090f, 0.817383f, 0.854492f, 0.882812f, 0.904297f, 0.920898f, 0.932617f, + 0.943359f, 0.951172f, 0.957520f, 0.962891f, 0.967773f, 0.971191f, 0.974121f, 0.977539f, 0.979492f, 0.981445f, 0.983887f, 0.985352f, + 0.986816f, 0.988281f, 0.988770f, 0.989258f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, + 0.995605f, 0.996582f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000243f, 0.000847f, 0.001555f, 0.002224f, + 0.003141f, 0.004093f, 0.005264f, 0.006817f, 0.008850f, 0.010948f, 0.014053f, 0.017456f, 0.022339f, 0.028351f, 0.036011f, 0.046326f, + 0.060791f, 0.080444f, 0.107788f, 0.146851f, 0.201660f, 0.274658f, 0.366699f, 0.470215f, 0.574707f, 0.666016f, 0.740234f, 0.797363f, + 0.839355f, 0.871094f, 0.895508f, 0.913574f, 0.927734f, 0.938965f, 0.947754f, 0.955566f, 0.960449f, 0.965332f, 0.969727f, 0.973145f, + 0.976074f, 0.979004f, 0.981445f, 0.982910f, 0.984863f, 0.986328f, 0.987305f, 0.988770f, 0.989258f, 0.990723f, 0.991699f, 0.992188f, + 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.996094f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000244f, 0.000767f, 0.001042f, 0.001934f, 0.002502f, 0.003588f, 0.004292f, 0.005558f, 0.006824f, 0.008667f, 0.010872f, 0.013802f, + 0.017426f, 0.021637f, 0.027176f, 0.033936f, 0.043304f, 0.056549f, 0.073914f, 0.098083f, 0.132446f, 0.180664f, 0.245239f, 0.330078f, + 0.429199f, 0.533203f, 0.631348f, 0.711914f, 0.775879f, 0.823242f, 0.860352f, 0.886230f, 0.907227f, 0.923340f, 0.935059f, 0.944824f, + 0.952148f, 0.958984f, 0.964844f, 0.968750f, 0.972168f, 0.975586f, 0.978516f, 0.980957f, 0.982422f, 0.983887f, 0.985840f, 0.987305f, + 0.988770f, 0.989746f, 0.990234f, 0.992188f, 0.992676f, 0.992676f, 0.994141f, 0.994141f, 0.995117f, 0.995605f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000000f, 0.000485f, 0.001062f, 0.001658f, 0.002398f, 0.002998f, 0.003805f, 0.004723f, + 0.006004f, 0.007084f, 0.009102f, 0.011093f, 0.013489f, 0.016876f, 0.020813f, 0.025803f, 0.032257f, 0.040924f, 0.052673f, 0.068298f, + 0.090149f, 0.120239f, 0.162598f, 0.221313f, 0.298096f, 0.392822f, 0.496582f, 0.597656f, 0.684082f, 0.754883f, 0.807617f, 0.848145f, + 0.877930f, 0.900391f, 0.917969f, 0.931641f, 0.941406f, 0.950684f, 0.957031f, 0.962402f, 0.967773f, 0.971680f, 0.974609f, 0.978027f, + 0.980469f, 0.982422f, 0.984375f, 0.985840f, 0.987305f, 0.988281f, 0.989746f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, + 0.994141f, 0.995117f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000244f, 0.000477f, 0.000852f, 0.001439f, + 0.002045f, 0.002424f, 0.003101f, 0.004093f, 0.004887f, 0.005989f, 0.007751f, 0.008606f, 0.011002f, 0.013420f, 0.016251f, 0.020035f, + 0.024628f, 0.030579f, 0.039093f, 0.049255f, 0.063599f, 0.083191f, 0.109924f, 0.148071f, 0.200928f, 0.270996f, 0.359863f, 0.461670f, + 0.564453f, 0.656738f, 0.732910f, 0.791992f, 0.836426f, 0.869629f, 0.894531f, 0.913086f, 0.928223f, 0.939453f, 0.949219f, 0.956055f, + 0.961914f, 0.966797f, 0.970703f, 0.975098f, 0.977051f, 0.979492f, 0.982422f, 0.983887f, 0.985352f, 0.987305f, 0.988770f, 0.989746f, + 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.998047f, 0.998535f, 0.998535f, 0.998047f, 0.998047f, 0.998535f, + 0.000242f, 0.000650f, 0.000847f, 0.001138f, 0.001621f, 0.002239f, 0.002527f, 0.003325f, 0.004227f, 0.005165f, 0.006462f, 0.007389f, + 0.008904f, 0.011024f, 0.013130f, 0.015915f, 0.019272f, 0.023819f, 0.029205f, 0.036652f, 0.046417f, 0.059418f, 0.077209f, 0.101562f, + 0.136230f, 0.183350f, 0.248047f, 0.331055f, 0.429688f, 0.533203f, 0.630859f, 0.711426f, 0.776367f, 0.824219f, 0.861328f, 0.887695f, + 0.908691f, 0.924805f, 0.937500f, 0.946777f, 0.954102f, 0.960938f, 0.966309f, 0.970215f, 0.974121f, 0.977539f, 0.979492f, 0.981934f, + 0.983887f, 0.985840f, 0.987305f, 0.989258f, 0.989746f, 0.990723f, 0.991211f, 0.992676f, 0.993164f, 0.994141f, 0.997559f, 0.998047f, + 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000089f, 0.000243f, 0.000827f, 0.000964f, 0.001418f, 0.001579f, 0.002296f, 0.002914f, + 0.003632f, 0.004280f, 0.005344f, 0.006130f, 0.007545f, 0.008949f, 0.010498f, 0.012733f, 0.015686f, 0.018646f, 0.023010f, 0.028229f, + 0.034851f, 0.044098f, 0.056122f, 0.072388f, 0.094788f, 0.125610f, 0.168945f, 0.228271f, 0.306396f, 0.401123f, 0.504883f, 0.604492f, + 0.691895f, 0.760742f, 0.813477f, 0.853027f, 0.881836f, 0.904297f, 0.921387f, 0.934570f, 0.944824f, 0.953125f, 0.959961f, 0.964844f, + 0.969727f, 0.973633f, 0.976562f, 0.979492f, 0.981934f, 0.983887f, 0.986328f, 0.987305f, 0.988281f, 0.989258f, 0.991211f, 0.992188f, + 0.992676f, 0.993652f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000069f, 0.000461f, 0.000609f, 0.000933f, + 0.001088f, 0.001488f, 0.001900f, 0.002378f, 0.003101f, 0.003687f, 0.004547f, 0.005276f, 0.006233f, 0.007282f, 0.008820f, 0.010239f, + 0.012581f, 0.015312f, 0.018341f, 0.022095f, 0.027344f, 0.034027f, 0.041687f, 0.053467f, 0.067810f, 0.088440f, 0.117126f, 0.156616f, + 0.211426f, 0.284180f, 0.375977f, 0.478760f, 0.581543f, 0.672363f, 0.746094f, 0.802734f, 0.845703f, 0.877441f, 0.900879f, 0.918457f, + 0.933105f, 0.943848f, 0.951660f, 0.959473f, 0.964355f, 0.968750f, 0.974121f, 0.977051f, 0.979492f, 0.982422f, 0.984375f, 0.985840f, + 0.987305f, 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, + 0.000244f, 0.000348f, 0.000606f, 0.000737f, 0.001079f, 0.001458f, 0.001783f, 0.002192f, 0.002924f, 0.003231f, 0.003862f, 0.004551f, + 0.005169f, 0.006367f, 0.007381f, 0.008682f, 0.010590f, 0.012199f, 0.014900f, 0.017761f, 0.021530f, 0.026108f, 0.032349f, 0.039642f, + 0.050446f, 0.064392f, 0.083313f, 0.109436f, 0.145996f, 0.197021f, 0.266357f, 0.354248f, 0.455811f, 0.560059f, 0.654785f, 0.732910f, + 0.793457f, 0.837891f, 0.873047f, 0.897461f, 0.917480f, 0.931641f, 0.941895f, 0.951172f, 0.958984f, 0.964844f, 0.969727f, 0.973633f, + 0.977051f, 0.979980f, 0.981934f, 0.984375f, 0.985840f, 0.988281f, 0.989258f, 0.990234f, 0.991211f, 0.992676f, 0.997070f, 0.997559f, + 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000244f, 0.000520f, 0.000592f, 0.000720f, 0.000812f, 0.001174f, 0.001500f, 0.001884f, + 0.002178f, 0.002831f, 0.003321f, 0.003885f, 0.004471f, 0.005436f, 0.006275f, 0.007584f, 0.008675f, 0.010521f, 0.012238f, 0.014557f, + 0.017197f, 0.020874f, 0.025467f, 0.030960f, 0.038208f, 0.047821f, 0.061249f, 0.078552f, 0.103149f, 0.136841f, 0.184937f, 0.249878f, + 0.334473f, 0.435059f, 0.539551f, 0.638184f, 0.720215f, 0.784668f, 0.832031f, 0.868164f, 0.894531f, 0.914062f, 0.929688f, 0.942383f, + 0.950684f, 0.958984f, 0.964844f, 0.970215f, 0.974121f, 0.977539f, 0.979980f, 0.982422f, 0.984863f, 0.985840f, 0.988281f, 0.989258f, + 0.990723f, 0.992188f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997559f, 0.997559f, 0.000000f, 0.000243f, 0.000351f, 0.000603f, + 0.000708f, 0.001079f, 0.001493f, 0.001752f, 0.001936f, 0.002171f, 0.002911f, 0.003382f, 0.003906f, 0.004578f, 0.005222f, 0.006161f, + 0.007362f, 0.008850f, 0.010010f, 0.011971f, 0.014145f, 0.016983f, 0.020477f, 0.024582f, 0.029739f, 0.036804f, 0.045837f, 0.057648f, + 0.074829f, 0.097534f, 0.130127f, 0.174438f, 0.236572f, 0.318604f, 0.416992f, 0.523926f, 0.624023f, 0.709961f, 0.777344f, 0.827148f, + 0.865234f, 0.893066f, 0.914062f, 0.929688f, 0.941406f, 0.951660f, 0.958496f, 0.965820f, 0.969238f, 0.974609f, 0.977539f, 0.980469f, + 0.983398f, 0.985352f, 0.986816f, 0.988281f, 0.989746f, 0.990723f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, + 0.000243f, 0.000244f, 0.000456f, 0.000592f, 0.000602f, 0.001025f, 0.001282f, 0.001656f, 0.001856f, 0.002073f, 0.002535f, 0.002768f, + 0.003487f, 0.003822f, 0.004574f, 0.005589f, 0.006519f, 0.007336f, 0.008453f, 0.009911f, 0.011581f, 0.013985f, 0.016373f, 0.019638f, + 0.023819f, 0.028473f, 0.035339f, 0.043945f, 0.055939f, 0.071350f, 0.093140f, 0.123474f, 0.165771f, 0.225342f, 0.304199f, 0.402344f, + 0.509277f, 0.612305f, 0.702148f, 0.771973f, 0.824219f, 0.863281f, 0.891113f, 0.913086f, 0.930176f, 0.942383f, 0.951660f, 0.959473f, + 0.965820f, 0.970215f, 0.974609f, 0.977539f, 0.980957f, 0.983887f, 0.985352f, 0.987305f, 0.988770f, 0.990723f, 0.996582f, 0.996582f, + 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000000f, 0.000243f, 0.000276f, 0.000557f, 0.000594f, 0.000849f, 0.000845f, 0.001282f, + 0.001520f, 0.001774f, 0.002119f, 0.002499f, 0.002840f, 0.003252f, 0.004005f, 0.004555f, 0.005245f, 0.006168f, 0.007233f, 0.008301f, + 0.009911f, 0.011330f, 0.013748f, 0.015945f, 0.019089f, 0.023071f, 0.027786f, 0.034058f, 0.042542f, 0.053619f, 0.068237f, 0.089539f, + 0.117798f, 0.158325f, 0.215698f, 0.293213f, 0.389893f, 0.498291f, 0.603027f, 0.694824f, 0.767090f, 0.821777f, 0.862305f, 0.891113f, + 0.914062f, 0.930176f, 0.942383f, 0.952148f, 0.959473f, 0.965820f, 0.971680f, 0.975098f, 0.978516f, 0.981445f, 0.983887f, 0.985840f, + 0.988281f, 0.989258f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996094f, 0.996582f, 0.000240f, 0.000240f, 0.000242f, 0.000365f, + 0.000678f, 0.000779f, 0.000957f, 0.001003f, 0.001390f, 0.001656f, 0.001828f, 0.002274f, 0.002455f, 0.003210f, 0.003704f, 0.004097f, + 0.004616f, 0.005409f, 0.006180f, 0.007092f, 0.008453f, 0.009521f, 0.011154f, 0.013397f, 0.015656f, 0.018509f, 0.022247f, 0.026810f, + 0.032928f, 0.041046f, 0.051727f, 0.065613f, 0.085205f, 0.113098f, 0.152832f, 0.208496f, 0.284424f, 0.380371f, 0.489258f, 0.596680f, + 0.690918f, 0.764648f, 0.821777f, 0.862305f, 0.892578f, 0.914551f, 0.931152f, 0.943848f, 0.953613f, 0.960938f, 0.967773f, 0.971680f, + 0.976074f, 0.979492f, 0.982422f, 0.984863f, 0.986816f, 0.988281f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.996094f, + 0.000000f, 0.000242f, 0.000242f, 0.000364f, 0.000465f, 0.000803f, 0.000927f, 0.000956f, 0.001275f, 0.001335f, 0.001570f, 0.001968f, + 0.002184f, 0.002726f, 0.003069f, 0.003294f, 0.003906f, 0.004662f, 0.005245f, 0.006027f, 0.007191f, 0.008202f, 0.009460f, 0.010735f, + 0.012970f, 0.015404f, 0.018051f, 0.021484f, 0.026321f, 0.032135f, 0.039581f, 0.049805f, 0.063538f, 0.082458f, 0.109497f, 0.147827f, + 0.202393f, 0.277344f, 0.373535f, 0.483887f, 0.593262f, 0.688477f, 0.764648f, 0.821289f, 0.863281f, 0.894043f, 0.916016f, 0.932129f, + 0.944336f, 0.954590f, 0.962402f, 0.968262f, 0.973633f, 0.977051f, 0.980957f, 0.983398f, 0.985352f, 0.987793f, 0.995605f, 0.996094f, + 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.000000f, 0.000239f, 0.000360f, 0.000362f, 0.000363f, 0.000475f, 0.000767f, 0.000931f, + 0.000951f, 0.001211f, 0.001491f, 0.001634f, 0.002129f, 0.002457f, 0.002678f, 0.002995f, 0.003393f, 0.003922f, 0.004711f, 0.005135f, + 0.005955f, 0.006935f, 0.008072f, 0.009270f, 0.010841f, 0.012558f, 0.014618f, 0.017502f, 0.020828f, 0.025269f, 0.030884f, 0.038269f, + 0.048218f, 0.061554f, 0.080505f, 0.106567f, 0.144287f, 0.197998f, 0.272705f, 0.369141f, 0.480469f, 0.591797f, 0.690430f, 0.767090f, + 0.824707f, 0.866699f, 0.896484f, 0.918457f, 0.934570f, 0.946777f, 0.956543f, 0.963379f, 0.969727f, 0.974609f, 0.978027f, 0.981934f, + 0.984375f, 0.986328f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000000f, 0.000208f, 0.000238f, 0.000362f, + 0.000363f, 0.000555f, 0.000600f, 0.000888f, 0.001140f, 0.001140f, 0.001272f, 0.001661f, 0.001811f, 0.002041f, 0.002550f, 0.002636f, + 0.002941f, 0.003492f, 0.004032f, 0.004593f, 0.005062f, 0.005875f, 0.007015f, 0.007965f, 0.009079f, 0.010300f, 0.012291f, 0.014229f, + 0.016937f, 0.020248f, 0.024689f, 0.030151f, 0.037354f, 0.047028f, 0.060211f, 0.078491f, 0.104431f, 0.141602f, 0.195068f, 0.270264f, + 0.367676f, 0.480957f, 0.594238f, 0.693848f, 0.770996f, 0.828613f, 0.869629f, 0.898438f, 0.921875f, 0.937012f, 0.949219f, 0.958008f, + 0.964844f, 0.971680f, 0.976074f, 0.979980f, 0.982422f, 0.985840f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.995117f, 0.995117f, + 0.000000f, 0.000000f, 0.000229f, 0.000358f, 0.000479f, 0.000362f, 0.000498f, 0.000634f, 0.000836f, 0.000927f, 0.001288f, 0.001244f, + 0.001605f, 0.001732f, 0.002106f, 0.002478f, 0.002613f, 0.003183f, 0.003510f, 0.004021f, 0.004528f, 0.005047f, 0.005768f, 0.006859f, + 0.007759f, 0.008865f, 0.009933f, 0.011742f, 0.013741f, 0.016678f, 0.019897f, 0.024017f, 0.029297f, 0.036469f, 0.045990f, 0.058990f, + 0.077026f, 0.102722f, 0.140015f, 0.193604f, 0.269531f, 0.369141f, 0.485107f, 0.600098f, 0.700195f, 0.777344f, 0.833984f, 0.873535f, + 0.903809f, 0.924316f, 0.940430f, 0.951172f, 0.960938f, 0.968262f, 0.973145f, 0.978027f, 0.980957f, 0.983887f, 0.994629f, 0.995117f, + 0.995117f, 0.995605f, 0.995117f, 0.995117f, 0.000000f, 0.000000f, 0.000078f, 0.000353f, 0.000354f, 0.000360f, 0.000482f, 0.000573f, + 0.000757f, 0.000923f, 0.001230f, 0.001266f, 0.001485f, 0.001679f, 0.001963f, 0.002161f, 0.002235f, 0.002739f, 0.003115f, 0.003563f, + 0.003933f, 0.004436f, 0.004917f, 0.005623f, 0.006599f, 0.007469f, 0.008484f, 0.010101f, 0.011665f, 0.013695f, 0.016403f, 0.019531f, + 0.023300f, 0.028870f, 0.035889f, 0.045135f, 0.058014f, 0.075928f, 0.101746f, 0.139160f, 0.193848f, 0.271729f, 0.374023f, 0.492920f, + 0.609863f, 0.709473f, 0.786133f, 0.842285f, 0.880859f, 0.908691f, 0.928711f, 0.943848f, 0.954102f, 0.963867f, 0.969727f, 0.975098f, + 0.979004f, 0.982422f, 0.994141f, 0.994629f, 0.994141f, 0.994141f, 0.994141f, 0.994629f, 0.000000f, 0.000000f, 0.000000f, 0.000330f, + 0.000336f, 0.000352f, 0.000478f, 0.000481f, 0.000676f, 0.000822f, 0.001072f, 0.001228f, 0.001283f, 0.001417f, 0.001621f, 0.001938f, + 0.001953f, 0.002377f, 0.002737f, 0.002914f, 0.003624f, 0.003721f, 0.004555f, 0.004845f, 0.005531f, 0.006325f, 0.007244f, 0.008255f, + 0.009911f, 0.011467f, 0.013496f, 0.016068f, 0.018951f, 0.022888f, 0.028183f, 0.035126f, 0.044617f, 0.057220f, 0.075134f, 0.101501f, + 0.139526f, 0.195679f, 0.276123f, 0.381592f, 0.503418f, 0.622070f, 0.721680f, 0.796387f, 0.850098f, 0.887207f, 0.914551f, 0.933594f, + 0.947266f, 0.957520f, 0.966797f, 0.972656f, 0.977539f, 0.980957f, 0.993164f, 0.994141f, 0.994141f, 0.994141f, 0.994141f, 0.994141f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000243f, 0.000466f, 0.000474f, 0.000475f, 0.000600f, 0.000740f, 0.000796f, 0.001130f, + 0.001333f, 0.001339f, 0.001440f, 0.001575f, 0.001961f, 0.002031f, 0.002388f, 0.002563f, 0.003174f, 0.003345f, 0.003555f, 0.004143f, + 0.004681f, 0.005333f, 0.006191f, 0.007111f, 0.008278f, 0.009666f, 0.011177f, 0.013451f, 0.015511f, 0.018707f, 0.022629f, 0.027847f, + 0.034515f, 0.043976f, 0.056671f, 0.075012f, 0.101685f, 0.140869f, 0.199341f, 0.282959f, 0.393311f, 0.519043f, 0.639160f, 0.736328f, + 0.809082f, 0.860352f, 0.896484f, 0.920898f, 0.939453f, 0.951660f, 0.961914f, 0.969238f, 0.975098f, 0.979492f, 0.993164f, 0.993652f, + 0.994141f, 0.993652f, 0.993652f, 0.993652f, 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000120f, 0.000367f, 0.000448f, 0.000589f, + 0.000595f, 0.000719f, 0.000707f, 0.000809f, 0.000966f, 0.001217f, 0.001369f, 0.001405f, 0.001579f, 0.001786f, 0.002100f, 0.002260f, + 0.002600f, 0.002762f, 0.003023f, 0.003531f, 0.004219f, 0.004810f, 0.005409f, 0.006092f, 0.007053f, 0.008064f, 0.009163f, 0.010941f, + 0.012733f, 0.015251f, 0.018280f, 0.022202f, 0.027573f, 0.034271f, 0.043732f, 0.056458f, 0.075134f, 0.102661f, 0.143433f, 0.205078f, + 0.293701f, 0.409668f, 0.538574f, 0.658203f, 0.753418f, 0.823242f, 0.870605f, 0.905273f, 0.927734f, 0.943848f, 0.956055f, 0.964844f, + 0.972168f, 0.977539f, 0.992188f, 0.992676f, 0.993164f, 0.993652f, 0.993164f, 0.992676f, 0.000000f, 0.000000f, 0.000000f, 0.000111f, + 0.000224f, 0.000231f, 0.000314f, 0.000562f, 0.000589f, 0.000699f, 0.000717f, 0.000776f, 0.000926f, 0.000968f, 0.001242f, 0.001360f, + 0.001487f, 0.001564f, 0.001713f, 0.002073f, 0.002169f, 0.002380f, 0.002941f, 0.003229f, 0.003534f, 0.003914f, 0.004509f, 0.005127f, + 0.005939f, 0.006596f, 0.007812f, 0.009354f, 0.010559f, 0.012581f, 0.015007f, 0.018021f, 0.022079f, 0.027191f, 0.034119f, 0.043427f, + 0.057190f, 0.075623f, 0.104492f, 0.147949f, 0.213135f, 0.308105f, 0.430664f, 0.562500f, 0.681641f, 0.772949f, 0.839355f, 0.884277f, + 0.913574f, 0.934570f, 0.950195f, 0.961426f, 0.969238f, 0.975098f, 0.991211f, 0.992676f, 0.992676f, 0.992676f, 0.992676f, 0.992188f, + 0.000000f, 0.000000f, 0.000000f, 0.000084f, 0.000117f, 0.000119f, 0.000367f, 0.000473f, 0.000555f, 0.000576f, 0.000674f, 0.000713f, + 0.000816f, 0.000913f, 0.001049f, 0.001168f, 0.001263f, 0.001473f, 0.001580f, 0.001781f, 0.002005f, 0.002123f, 0.002316f, 0.002674f, + 0.003094f, 0.003475f, 0.003967f, 0.004318f, 0.004833f, 0.005798f, 0.006699f, 0.007801f, 0.008888f, 0.010429f, 0.012268f, 0.014824f, + 0.017792f, 0.021790f, 0.026978f, 0.033844f, 0.043518f, 0.057068f, 0.077148f, 0.107605f, 0.154053f, 0.224609f, 0.326904f, 0.456543f, + 0.591797f, 0.708984f, 0.795410f, 0.855957f, 0.895508f, 0.923340f, 0.942383f, 0.955566f, 0.965332f, 0.973145f, 0.991211f, 0.991699f, + 0.992188f, 0.992188f, 0.992188f, 0.991699f, 0.000000f, 0.000000f, 0.000000f, 0.000092f, 0.000070f, 0.000236f, 0.000119f, 0.000376f, + 0.000433f, 0.000561f, 0.000688f, 0.000586f, 0.000742f, 0.000842f, 0.000881f, 0.000937f, 0.001141f, 0.001300f, 0.001434f, 0.001464f, + 0.001598f, 0.001829f, 0.002062f, 0.002338f, 0.002583f, 0.003036f, 0.003460f, 0.003704f, 0.004383f, 0.004986f, 0.005615f, 0.006439f, + 0.007267f, 0.008797f, 0.010330f, 0.012146f, 0.014473f, 0.017532f, 0.021622f, 0.026535f, 0.033539f, 0.043579f, 0.058044f, 0.079041f, + 0.111572f, 0.162109f, 0.239746f, 0.350830f, 0.488770f, 0.625000f, 0.737305f, 0.817871f, 0.871582f, 0.908203f, 0.932129f, 0.949219f, + 0.961914f, 0.970215f, 0.990234f, 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.000000f, 0.000000f, 0.000000f, 0.000080f, + 0.000100f, 0.000115f, 0.000335f, 0.000350f, 0.000355f, 0.000473f, 0.000633f, 0.000678f, 0.000695f, 0.000694f, 0.000812f, 0.000733f, + 0.001109f, 0.001098f, 0.001260f, 0.001452f, 0.001377f, 0.001534f, 0.001972f, 0.001982f, 0.002232f, 0.002567f, 0.002764f, 0.003273f, + 0.003542f, 0.004181f, 0.004738f, 0.005466f, 0.006268f, 0.007126f, 0.008614f, 0.010170f, 0.012093f, 0.014359f, 0.017075f, 0.021042f, + 0.026459f, 0.033722f, 0.044159f, 0.059113f, 0.082092f, 0.117249f, 0.173218f, 0.259766f, 0.382080f, 0.526367f, 0.662598f, 0.768066f, + 0.840332f, 0.889648f, 0.920410f, 0.940918f, 0.956543f, 0.966309f, 0.989746f, 0.990234f, 0.990723f, 0.990723f, 0.990723f, 0.990723f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000191f, 0.000236f, 0.000335f, 0.000337f, 0.000466f, 0.000399f, 0.000608f, + 0.000626f, 0.000669f, 0.000696f, 0.000808f, 0.000859f, 0.000915f, 0.000903f, 0.001168f, 0.001245f, 0.001500f, 0.001525f, 0.001863f, + 0.001941f, 0.002121f, 0.002399f, 0.002861f, 0.002953f, 0.003632f, 0.004105f, 0.004745f, 0.005333f, 0.006317f, 0.007236f, 0.008255f, + 0.009857f, 0.011414f, 0.014015f, 0.016922f, 0.020828f, 0.026321f, 0.034149f, 0.044861f, 0.061279f, 0.085571f, 0.124878f, 0.187866f, + 0.285645f, 0.420654f, 0.570801f, 0.703125f, 0.799805f, 0.864258f, 0.905273f, 0.932129f, 0.950684f, 0.963379f, 0.988770f, 0.989258f, + 0.989746f, 0.989746f, 0.989746f, 0.989746f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000000f, 0.000122f, 0.000125f, 0.000232f, + 0.000360f, 0.000342f, 0.000463f, 0.000388f, 0.000569f, 0.000638f, 0.000671f, 0.000791f, 0.000774f, 0.000943f, 0.000774f, 0.001018f, + 0.001044f, 0.001245f, 0.001377f, 0.001410f, 0.001643f, 0.001970f, 0.002041f, 0.002316f, 0.002758f, 0.003023f, 0.003433f, 0.003859f, + 0.004444f, 0.005180f, 0.006134f, 0.006920f, 0.008102f, 0.009354f, 0.011475f, 0.013649f, 0.016739f, 0.021011f, 0.026566f, 0.034454f, + 0.046051f, 0.063843f, 0.090942f, 0.135498f, 0.207642f, 0.319580f, 0.467529f, 0.620605f, 0.745605f, 0.830566f, 0.886230f, 0.920898f, + 0.943848f, 0.958984f, 0.987793f, 0.988281f, 0.988770f, 0.988770f, 0.988281f, 0.988770f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, + 0.000122f, 0.000122f, 0.000188f, 0.000200f, 0.000332f, 0.000417f, 0.000338f, 0.000459f, 0.000349f, 0.000558f, 0.000642f, 0.000636f, + 0.000629f, 0.000807f, 0.000695f, 0.000747f, 0.000827f, 0.001058f, 0.001182f, 0.001269f, 0.001422f, 0.001472f, 0.001921f, 0.002100f, + 0.002337f, 0.002462f, 0.003073f, 0.003374f, 0.003708f, 0.004265f, 0.004826f, 0.005646f, 0.006596f, 0.007710f, 0.008926f, 0.011063f, + 0.013580f, 0.016495f, 0.020737f, 0.026459f, 0.035126f, 0.047791f, 0.066833f, 0.097778f, 0.149170f, 0.233887f, 0.363037f, 0.523438f, + 0.674805f, 0.788086f, 0.860352f, 0.906250f, 0.935547f, 0.954102f, 0.986328f, 0.987305f, 0.987305f, 0.987305f, 0.987305f, 0.987793f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000175f, 0.000155f, 0.000319f, 0.000241f, 0.000318f, + 0.000455f, 0.000462f, 0.000496f, 0.000593f, 0.000516f, 0.000564f, 0.000667f, 0.000668f, 0.000715f, 0.000749f, 0.000925f, 0.001111f, + 0.001246f, 0.001381f, 0.001443f, 0.001856f, 0.001997f, 0.002264f, 0.002363f, 0.002880f, 0.003212f, 0.003727f, 0.004208f, 0.004673f, + 0.005394f, 0.006367f, 0.007404f, 0.009003f, 0.010651f, 0.013138f, 0.016312f, 0.020767f, 0.027054f, 0.036377f, 0.050262f, 0.071655f, + 0.107361f, 0.167969f, 0.269287f, 0.418457f, 0.587402f, 0.730957f, 0.828125f, 0.888184f, 0.924805f, 0.948242f, 0.984863f, 0.986328f, + 0.986328f, 0.985840f, 0.986328f, 0.986328f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, + 0.000202f, 0.000133f, 0.000215f, 0.000263f, 0.000304f, 0.000442f, 0.000332f, 0.000365f, 0.000403f, 0.000549f, 0.000607f, 0.000750f, + 0.000788f, 0.000802f, 0.000841f, 0.000958f, 0.001049f, 0.001188f, 0.001354f, 0.001318f, 0.001582f, 0.001928f, 0.002064f, 0.002321f, + 0.002594f, 0.003042f, 0.003222f, 0.003796f, 0.004440f, 0.005112f, 0.006081f, 0.007259f, 0.008736f, 0.010612f, 0.013077f, 0.016464f, + 0.020950f, 0.027664f, 0.037506f, 0.052795f, 0.077698f, 0.120361f, 0.194336f, 0.317627f, 0.486572f, 0.657227f, 0.785156f, 0.865234f, + 0.913086f, 0.942871f, 0.983887f, 0.984863f, 0.984375f, 0.984863f, 0.984375f, 0.984863f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000152f, 0.000257f, 0.000243f, 0.000288f, 0.000345f, 0.000228f, + 0.000358f, 0.000363f, 0.000432f, 0.000494f, 0.000530f, 0.000582f, 0.000762f, 0.000771f, 0.000913f, 0.000978f, 0.001100f, 0.001305f, + 0.001373f, 0.001706f, 0.001712f, 0.001922f, 0.002155f, 0.002569f, 0.002573f, 0.003094f, 0.003401f, 0.004272f, 0.004978f, 0.005829f, + 0.006924f, 0.008453f, 0.010452f, 0.012871f, 0.016617f, 0.021072f, 0.028427f, 0.039429f, 0.056732f, 0.086243f, 0.138916f, 0.231812f, + 0.381592f, 0.566406f, 0.726562f, 0.833496f, 0.896973f, 0.933594f, 0.981934f, 0.982910f, 0.982910f, 0.982910f, 0.982910f, 0.982910f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000127f, 0.000215f, + 0.000159f, 0.000233f, 0.000284f, 0.000326f, 0.000339f, 0.000339f, 0.000352f, 0.000394f, 0.000623f, 0.000622f, 0.000731f, 0.000730f, + 0.000741f, 0.000829f, 0.000914f, 0.001017f, 0.001151f, 0.001469f, 0.001263f, 0.001480f, 0.001740f, 0.002069f, 0.002104f, 0.002443f, + 0.002831f, 0.003519f, 0.003929f, 0.004627f, 0.005455f, 0.006634f, 0.008316f, 0.009949f, 0.012596f, 0.016495f, 0.021729f, 0.029877f, + 0.042084f, 0.062805f, 0.098694f, 0.165283f, 0.284668f, 0.465088f, 0.654297f, 0.793945f, 0.877930f, 0.924805f, 0.979980f, 0.980957f, + 0.980957f, 0.981445f, 0.981445f, 0.980957f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, + 0.000121f, 0.000121f, 0.000150f, 0.000163f, 0.000069f, 0.000057f, 0.000121f, 0.000231f, 0.000291f, 0.000304f, 0.000334f, 0.000339f, + 0.000346f, 0.000569f, 0.000648f, 0.000674f, 0.000649f, 0.000697f, 0.000772f, 0.000834f, 0.000972f, 0.001005f, 0.001189f, 0.001359f, + 0.001237f, 0.001567f, 0.001794f, 0.001963f, 0.002378f, 0.002712f, 0.002867f, 0.003853f, 0.004330f, 0.005196f, 0.006516f, 0.008026f, + 0.009888f, 0.012703f, 0.016479f, 0.022110f, 0.031158f, 0.045746f, 0.070557f, 0.117004f, 0.204956f, 0.360596f, 0.564453f, 0.740723f, + 0.852051f, 0.912598f, 0.977539f, 0.979492f, 0.979492f, 0.979004f, 0.979492f, 0.979004f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000098f, 0.000082f, 0.000067f, 0.000056f, 0.000124f, + 0.000193f, 0.000240f, 0.000258f, 0.000310f, 0.000326f, 0.000335f, 0.000341f, 0.000471f, 0.000613f, 0.000494f, 0.000716f, 0.000742f, + 0.000804f, 0.000873f, 0.000832f, 0.001070f, 0.001120f, 0.001146f, 0.001225f, 0.001696f, 0.001814f, 0.002041f, 0.002419f, 0.002941f, + 0.003433f, 0.004154f, 0.004818f, 0.006077f, 0.007652f, 0.009521f, 0.012444f, 0.017029f, 0.023193f, 0.033539f, 0.050690f, 0.082092f, + 0.144043f, 0.265869f, 0.463379f, 0.672363f, 0.818848f, 0.898438f, 0.975586f, 0.976562f, 0.976562f, 0.976562f, 0.976074f, 0.976562f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000114f, + 0.000096f, 0.000079f, 0.000125f, 0.000056f, 0.000142f, 0.000120f, 0.000195f, 0.000246f, 0.000321f, 0.000305f, 0.000319f, 0.000395f, + 0.000442f, 0.000540f, 0.000642f, 0.000638f, 0.000696f, 0.000674f, 0.000687f, 0.000857f, 0.000955f, 0.001128f, 0.001224f, 0.001364f, + 0.001347f, 0.001555f, 0.001910f, 0.002245f, 0.002714f, 0.003229f, 0.003824f, 0.004673f, 0.005676f, 0.007225f, 0.009293f, 0.012802f, + 0.017273f, 0.024368f, 0.036682f, 0.058075f, 0.100952f, 0.188721f, 0.358154f, 0.587891f, 0.775879f, 0.881348f, 0.972168f, 0.972656f, + 0.972656f, 0.973145f, 0.973145f, 0.973633f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000112f, 0.000093f, 0.000079f, 0.000067f, 0.000057f, 0.000049f, 0.000133f, 0.000137f, + 0.000163f, 0.000244f, 0.000328f, 0.000366f, 0.000356f, 0.000415f, 0.000436f, 0.000543f, 0.000555f, 0.000638f, 0.000597f, 0.000702f, + 0.000786f, 0.000648f, 0.000891f, 0.000804f, 0.001218f, 0.001070f, 0.001355f, 0.001731f, 0.002171f, 0.002352f, 0.002796f, 0.003546f, + 0.004189f, 0.005558f, 0.006939f, 0.009209f, 0.012337f, 0.017776f, 0.026016f, 0.040833f, 0.069946f, 0.130981f, 0.262207f, 0.489258f, + 0.719238f, 0.859375f, 0.968262f, 0.969238f, 0.969727f, 0.969727f, 0.969727f, 0.969727f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000110f, 0.000093f, 0.000080f, + 0.000068f, 0.000094f, 0.000119f, 0.000117f, 0.000120f, 0.000123f, 0.000173f, 0.000263f, 0.000263f, 0.000359f, 0.000386f, 0.000390f, + 0.000401f, 0.000556f, 0.000549f, 0.000573f, 0.000502f, 0.000707f, 0.000789f, 0.000629f, 0.000847f, 0.001003f, 0.001024f, 0.001242f, + 0.001423f, 0.001877f, 0.002012f, 0.002571f, 0.003071f, 0.003925f, 0.005131f, 0.006767f, 0.009140f, 0.012672f, 0.018509f, 0.028992f, + 0.048309f, 0.089233f, 0.183838f, 0.383545f, 0.646973f, 0.830078f, 0.963867f, 0.964844f, 0.964844f, 0.965820f, 0.965820f, 0.965820f, + 0.000000f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, + 0.000119f, 0.000119f, 0.000113f, 0.000095f, 0.000083f, 0.000070f, 0.000061f, 0.000054f, 0.000048f, 0.000042f, 0.000115f, 0.000112f, + 0.000151f, 0.000213f, 0.000309f, 0.000298f, 0.000359f, 0.000337f, 0.000382f, 0.000440f, 0.000576f, 0.000477f, 0.000453f, 0.000690f, + 0.000687f, 0.000795f, 0.000776f, 0.000911f, 0.001117f, 0.001119f, 0.001352f, 0.002001f, 0.002140f, 0.002832f, 0.003609f, 0.004715f, + 0.006302f, 0.008835f, 0.013115f, 0.020004f, 0.032867f, 0.060333f, 0.124512f, 0.281982f, 0.557617f, 0.794434f, 0.959473f, 0.959961f, + 0.960449f, 0.960449f, 0.960449f, 0.959961f, 0.000122f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000119f, + 0.000119f, 0.000119f, 0.000119f, 0.000119f, 0.000118f, 0.000118f, 0.000118f, 0.000116f, 0.000098f, 0.000087f, 0.000076f, 0.000065f, + 0.000057f, 0.000050f, 0.000045f, 0.000091f, 0.000074f, 0.000106f, 0.000185f, 0.000193f, 0.000228f, 0.000328f, 0.000323f, 0.000399f, + 0.000429f, 0.000498f, 0.000552f, 0.000432f, 0.000542f, 0.000592f, 0.000599f, 0.000729f, 0.000734f, 0.000885f, 0.001304f, 0.001273f, + 0.001756f, 0.001931f, 0.002445f, 0.003120f, 0.004456f, 0.006165f, 0.008751f, 0.013466f, 0.022141f, 0.040192f, 0.082397f, 0.195679f, + 0.455322f, 0.745117f, 0.952637f, 0.953613f, 0.953613f, 0.954102f, 0.952637f, 0.953613f, 0.000000f, 0.000120f, 0.000120f, 0.000119f, + 0.000119f, 0.000119f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000118f, 0.000117f, 0.000117f, 0.000117f, 0.000117f, 0.000117f, + 0.000117f, 0.000104f, 0.000092f, 0.000079f, 0.000071f, 0.000062f, 0.000055f, 0.000049f, 0.000044f, 0.000039f, 0.000099f, 0.000106f, + 0.000158f, 0.000169f, 0.000241f, 0.000274f, 0.000293f, 0.000389f, 0.000360f, 0.000399f, 0.000387f, 0.000446f, 0.000401f, 0.000530f, + 0.000565f, 0.000691f, 0.000722f, 0.000848f, 0.001147f, 0.001418f, 0.001677f, 0.002087f, 0.002972f, 0.004169f, 0.005623f, 0.008835f, + 0.014404f, 0.026077f, 0.053467f, 0.129395f, 0.346924f, 0.685059f, 0.943848f, 0.945801f, 0.945801f, 0.945312f, 0.945801f, 0.945801f, + 0.000000f, 0.000000f, 0.000117f, 0.000116f, 0.000117f, 0.000117f, 0.000116f, 0.000116f, 0.000115f, 0.000116f, 0.000115f, 0.000116f, + 0.000115f, 0.000115f, 0.000115f, 0.000115f, 0.000115f, 0.000115f, 0.000110f, 0.000097f, 0.000086f, 0.000077f, 0.000067f, 0.000060f, + 0.000053f, 0.000048f, 0.000043f, 0.000061f, 0.000090f, 0.000083f, 0.000139f, 0.000139f, 0.000216f, 0.000254f, 0.000307f, 0.000358f, + 0.000269f, 0.000377f, 0.000324f, 0.000369f, 0.000405f, 0.000455f, 0.000524f, 0.000706f, 0.000701f, 0.001012f, 0.001206f, 0.001316f, + 0.001663f, 0.002350f, 0.003571f, 0.005505f, 0.008873f, 0.016006f, 0.033234f, 0.081848f, 0.244751f, 0.605469f, 0.934082f, 0.935059f, + 0.936035f, 0.935547f, 0.935547f, 0.935547f, 0.000105f, 0.000114f, 0.000113f, 0.000113f, 0.000111f, 0.000111f, 0.000112f, 0.000111f, + 0.000112f, 0.000112f, 0.000112f, 0.000112f, 0.000111f, 0.000112f, 0.000112f, 0.000112f, 0.000112f, 0.000112f, 0.000112f, 0.000112f, + 0.000105f, 0.000093f, 0.000083f, 0.000074f, 0.000066f, 0.000059f, 0.000053f, 0.000048f, 0.000043f, 0.000062f, 0.000052f, 0.000063f, + 0.000092f, 0.000146f, 0.000176f, 0.000216f, 0.000227f, 0.000263f, 0.000244f, 0.000267f, 0.000370f, 0.000326f, 0.000360f, 0.000391f, + 0.000505f, 0.000618f, 0.000726f, 0.000969f, 0.001117f, 0.001651f, 0.002131f, 0.003090f, 0.005188f, 0.009499f, 0.019836f, 0.049042f, + 0.159180f, 0.509766f, 0.921875f, 0.922852f, 0.922852f, 0.922363f, 0.923340f, 0.922852f, 0.000000f, 0.000000f, 0.000065f, 0.000098f, + 0.000096f, 0.000101f, 0.000100f, 0.000104f, 0.000104f, 0.000103f, 0.000106f, 0.000106f, 0.000106f, 0.000105f, 0.000107f, 0.000107f, + 0.000106f, 0.000107f, 0.000107f, 0.000108f, 0.000107f, 0.000108f, 0.000104f, 0.000092f, 0.000082f, 0.000075f, 0.000067f, 0.000059f, + 0.000054f, 0.000048f, 0.000044f, 0.000039f, 0.000037f, 0.000058f, 0.000066f, 0.000122f, 0.000137f, 0.000175f, 0.000208f, 0.000194f, + 0.000208f, 0.000240f, 0.000270f, 0.000281f, 0.000323f, 0.000364f, 0.000479f, 0.000591f, 0.000712f, 0.000986f, 0.001224f, 0.001896f, + 0.002996f, 0.005196f, 0.010506f, 0.027527f, 0.095581f, 0.399658f, 0.905762f, 0.906738f, 0.906250f, 0.905762f, 0.905762f, 0.907227f, + 0.000000f, 0.000000f, 0.000000f, 0.000017f, 0.000030f, 0.000054f, 0.000061f, 0.000081f, 0.000087f, 0.000088f, 0.000089f, 0.000093f, + 0.000093f, 0.000096f, 0.000096f, 0.000097f, 0.000098f, 0.000099f, 0.000098f, 0.000100f, 0.000100f, 0.000101f, 0.000100f, 0.000101f, + 0.000101f, 0.000092f, 0.000082f, 0.000074f, 0.000067f, 0.000060f, 0.000054f, 0.000049f, 0.000045f, 0.000040f, 0.000036f, 0.000037f, + 0.000059f, 0.000077f, 0.000093f, 0.000143f, 0.000155f, 0.000188f, 0.000178f, 0.000184f, 0.000231f, 0.000234f, 0.000272f, 0.000352f, + 0.000420f, 0.000525f, 0.000764f, 0.001091f, 0.001653f, 0.002705f, 0.005474f, 0.013939f, 0.051880f, 0.283691f, 0.883789f, 0.884766f, + 0.885254f, 0.885254f, 0.885742f, 0.885254f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000013f, + 0.000032f, 0.000046f, 0.000050f, 0.000060f, 0.000065f, 0.000065f, 0.000075f, 0.000078f, 0.000080f, 0.000079f, 0.000084f, 0.000083f, + 0.000087f, 0.000087f, 0.000089f, 0.000090f, 0.000091f, 0.000091f, 0.000092f, 0.000092f, 0.000083f, 0.000075f, 0.000068f, 0.000062f, + 0.000056f, 0.000050f, 0.000046f, 0.000042f, 0.000037f, 0.000039f, 0.000044f, 0.000072f, 0.000068f, 0.000089f, 0.000125f, 0.000124f, + 0.000126f, 0.000153f, 0.000183f, 0.000212f, 0.000219f, 0.000311f, 0.000363f, 0.000566f, 0.000846f, 0.001332f, 0.002522f, 0.006252f, + 0.023834f, 0.175415f, 0.855957f, 0.856934f, 0.856934f, 0.856934f, 0.857422f, 0.856934f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000024f, 0.000028f, + 0.000040f, 0.000044f, 0.000051f, 0.000053f, 0.000060f, 0.000063f, 0.000064f, 0.000067f, 0.000071f, 0.000072f, 0.000074f, 0.000076f, + 0.000077f, 0.000079f, 0.000079f, 0.000075f, 0.000068f, 0.000062f, 0.000056f, 0.000051f, 0.000046f, 0.000042f, 0.000038f, 0.000034f, + 0.000031f, 0.000030f, 0.000045f, 0.000079f, 0.000081f, 0.000107f, 0.000114f, 0.000106f, 0.000144f, 0.000136f, 0.000171f, 0.000254f, + 0.000377f, 0.000531f, 0.001037f, 0.002504f, 0.009140f, 0.088379f, 0.818848f, 0.820801f, 0.819824f, 0.820312f, 0.819336f, 0.820801f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000014f, 0.000021f, 0.000028f, + 0.000034f, 0.000036f, 0.000042f, 0.000046f, 0.000049f, 0.000052f, 0.000054f, 0.000056f, 0.000059f, 0.000061f, 0.000064f, 0.000061f, + 0.000055f, 0.000050f, 0.000045f, 0.000041f, 0.000037f, 0.000033f, 0.000030f, 0.000027f, 0.000024f, 0.000033f, 0.000060f, 0.000059f, + 0.000075f, 0.000073f, 0.000101f, 0.000089f, 0.000144f, 0.000226f, 0.000384f, 0.000847f, 0.003033f, 0.031860f, 0.770020f, 0.770996f, + 0.772461f, 0.771973f, 0.772461f, 0.771973f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000010f, 0.000016f, + 0.000021f, 0.000023f, 0.000029f, 0.000032f, 0.000036f, 0.000039f, 0.000042f, 0.000044f, 0.000042f, 0.000038f, 0.000035f, 0.000031f, + 0.000028f, 0.000025f, 0.000022f, 0.000020f, 0.000017f, 0.000024f, 0.000040f, 0.000047f, 0.000053f, 0.000063f, 0.000087f, 0.000190f, + 0.000666f, 0.007278f, 0.708496f, 0.709961f, 0.710449f, 0.710938f, 0.710938f, 0.710449f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, + 0.000005f, 0.000010f, 0.000014f, 0.000018f, 0.000021f, 0.000024f, 0.000024f, 0.000021f, 0.000018f, 0.000016f, 0.000014f, 0.000012f, + 0.000008f, 0.000020f, 0.000022f, 0.000025f, 0.000073f, 0.000744f, 0.632324f, 0.632812f, 0.633789f, 0.633789f, 0.633301f, 0.632812f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000007f, 0.000006f, 0.000004f, 0.000005f, 0.000007f, 0.543945f, 0.545410f, + 0.545410f, 0.545410f, 0.546387f, 0.545898f, + }, + { + 0.159546f, 0.492676f, 0.684570f, 0.783203f, 0.838379f, 0.873535f, 0.897949f, 0.913574f, 0.926270f, 0.936035f, 0.943359f, 0.950195f, + 0.955566f, 0.959473f, 0.963379f, 0.966797f, 0.969238f, 0.972168f, 0.973633f, 0.976562f, 0.978027f, 0.979492f, 0.980957f, 0.982422f, + 0.983887f, 0.984863f, 0.985840f, 0.986816f, 0.987793f, 0.988770f, 0.989258f, 0.989746f, 0.990234f, 0.990723f, 0.991699f, 0.992676f, + 0.993164f, 0.993652f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, + 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.034119f, 0.154175f, 0.341309f, 0.532227f, 0.672363f, 0.763184f, 0.820801f, 0.858398f, + 0.885742f, 0.904297f, 0.918945f, 0.929199f, 0.938965f, 0.945801f, 0.951660f, 0.956543f, 0.961426f, 0.964355f, 0.968262f, 0.970703f, + 0.973145f, 0.975586f, 0.977539f, 0.979004f, 0.980469f, 0.981934f, 0.983398f, 0.984375f, 0.985352f, 0.986328f, 0.987305f, 0.988281f, + 0.988770f, 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, + 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.999023f, + 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.013390f, 0.056915f, 0.134155f, 0.257080f, + 0.412109f, 0.560547f, 0.675781f, 0.755859f, 0.812012f, 0.851074f, 0.877930f, 0.898926f, 0.913574f, 0.925781f, 0.935059f, 0.942871f, + 0.949707f, 0.954590f, 0.959473f, 0.963379f, 0.966797f, 0.969238f, 0.971680f, 0.975098f, 0.976562f, 0.978516f, 0.979980f, 0.980957f, + 0.982422f, 0.984375f, 0.985352f, 0.985840f, 0.987305f, 0.987793f, 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.991699f, 0.992188f, + 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995605f, 0.995605f, 0.995605f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, + 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, + 0.006939f, 0.027863f, 0.061951f, 0.117859f, 0.204834f, 0.324707f, 0.460205f, 0.585449f, 0.684570f, 0.757324f, 0.810059f, 0.847168f, + 0.874023f, 0.895996f, 0.910645f, 0.922852f, 0.933105f, 0.940918f, 0.947754f, 0.953613f, 0.958496f, 0.961914f, 0.965820f, 0.968750f, + 0.971680f, 0.974121f, 0.976074f, 0.978027f, 0.979492f, 0.981445f, 0.982910f, 0.983887f, 0.984863f, 0.986328f, 0.987305f, 0.988281f, + 0.988770f, 0.989746f, 0.990234f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, + 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.998535f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.004211f, 0.016022f, 0.034119f, 0.061432f, 0.104797f, 0.170288f, 0.262695f, 0.377686f, + 0.499756f, 0.608887f, 0.696777f, 0.762207f, 0.810547f, 0.847168f, 0.873535f, 0.893066f, 0.910156f, 0.922852f, 0.932617f, 0.939941f, + 0.946777f, 0.953125f, 0.958496f, 0.961914f, 0.965332f, 0.968750f, 0.971680f, 0.973633f, 0.975586f, 0.977539f, 0.979492f, 0.981445f, + 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.987793f, 0.987793f, 0.989258f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992676f, + 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, + 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999023f, 0.999512f, 0.999023f, 0.999023f, 0.002724f, 0.010384f, 0.020813f, 0.036285f, + 0.059784f, 0.093933f, 0.145508f, 0.218018f, 0.313232f, 0.424072f, 0.534180f, 0.632812f, 0.709961f, 0.769531f, 0.815918f, 0.848145f, + 0.874512f, 0.894043f, 0.909668f, 0.922363f, 0.932129f, 0.939941f, 0.946777f, 0.953125f, 0.958008f, 0.961914f, 0.965332f, 0.968750f, + 0.971680f, 0.973633f, 0.976562f, 0.978516f, 0.979980f, 0.981445f, 0.982910f, 0.984863f, 0.985352f, 0.986816f, 0.987793f, 0.988281f, + 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, + 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, + 0.002113f, 0.007004f, 0.014091f, 0.023895f, 0.037811f, 0.057373f, 0.085632f, 0.127075f, 0.185425f, 0.263672f, 0.360596f, 0.465576f, + 0.566895f, 0.655762f, 0.725586f, 0.779297f, 0.822266f, 0.853516f, 0.877441f, 0.895996f, 0.911621f, 0.923828f, 0.933105f, 0.940918f, + 0.947754f, 0.953613f, 0.957520f, 0.962402f, 0.965820f, 0.968750f, 0.972168f, 0.974121f, 0.976074f, 0.978027f, 0.980469f, 0.981934f, + 0.983398f, 0.984863f, 0.985352f, 0.986328f, 0.988281f, 0.988281f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, + 0.993652f, 0.994629f, 0.994629f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.001575f, 0.005211f, 0.010040f, 0.016220f, 0.025665f, 0.037415f, 0.054138f, 0.078491f, + 0.112915f, 0.160156f, 0.225464f, 0.308594f, 0.405029f, 0.506348f, 0.599121f, 0.678711f, 0.743164f, 0.791016f, 0.829590f, 0.859375f, + 0.881836f, 0.899414f, 0.913086f, 0.924805f, 0.934570f, 0.942383f, 0.948730f, 0.955078f, 0.958984f, 0.963379f, 0.966797f, 0.970215f, + 0.972168f, 0.974609f, 0.977051f, 0.979004f, 0.980957f, 0.981934f, 0.983398f, 0.984863f, 0.986328f, 0.987305f, 0.988281f, 0.989258f, + 0.990234f, 0.991211f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996094f, + 0.996582f, 0.997559f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.000985f, 0.004086f, 0.007362f, 0.011887f, + 0.018127f, 0.026199f, 0.036804f, 0.052002f, 0.072754f, 0.101318f, 0.140747f, 0.195190f, 0.266113f, 0.352539f, 0.448730f, 0.543945f, + 0.630371f, 0.702637f, 0.759277f, 0.803711f, 0.839355f, 0.865234f, 0.886719f, 0.903320f, 0.916504f, 0.927734f, 0.936523f, 0.944336f, + 0.950195f, 0.955566f, 0.959961f, 0.964355f, 0.967773f, 0.970215f, 0.973145f, 0.975586f, 0.978027f, 0.979004f, 0.980957f, 0.982910f, + 0.984375f, 0.985352f, 0.987305f, 0.987305f, 0.988770f, 0.990234f, 0.990234f, 0.991699f, 0.991699f, 0.993164f, 0.993164f, 0.993652f, + 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.999023f, + 0.000829f, 0.002878f, 0.005596f, 0.009109f, 0.013359f, 0.019089f, 0.026901f, 0.036774f, 0.049347f, 0.067200f, 0.091736f, 0.125854f, + 0.171631f, 0.232544f, 0.308594f, 0.397461f, 0.491455f, 0.581055f, 0.659668f, 0.724609f, 0.775879f, 0.817383f, 0.848633f, 0.873047f, + 0.892090f, 0.907715f, 0.920410f, 0.930664f, 0.939453f, 0.946289f, 0.951660f, 0.957520f, 0.960938f, 0.965820f, 0.968750f, 0.972168f, + 0.974609f, 0.976562f, 0.978516f, 0.980469f, 0.981934f, 0.983887f, 0.984863f, 0.986328f, 0.986816f, 0.988770f, 0.989746f, 0.990234f, + 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996582f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000836f, 0.002403f, 0.004837f, 0.006950f, 0.010269f, 0.014679f, 0.019699f, 0.026291f, + 0.035431f, 0.046875f, 0.062744f, 0.084045f, 0.113403f, 0.152588f, 0.204712f, 0.271729f, 0.353271f, 0.443115f, 0.532715f, 0.617188f, + 0.688477f, 0.748047f, 0.793945f, 0.829102f, 0.857422f, 0.880371f, 0.898438f, 0.912598f, 0.924316f, 0.934082f, 0.941406f, 0.948242f, + 0.954590f, 0.959473f, 0.963379f, 0.967285f, 0.970215f, 0.973145f, 0.975586f, 0.977539f, 0.979980f, 0.981445f, 0.982910f, 0.984375f, + 0.985840f, 0.987305f, 0.988281f, 0.988770f, 0.990234f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, + 0.995605f, 0.996094f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.000698f, 0.002052f, 0.003618f, 0.005703f, + 0.008430f, 0.011230f, 0.015083f, 0.019821f, 0.026474f, 0.034393f, 0.044922f, 0.059204f, 0.077698f, 0.102661f, 0.136963f, 0.182373f, + 0.241089f, 0.314941f, 0.398926f, 0.489014f, 0.575195f, 0.652344f, 0.717285f, 0.769043f, 0.810059f, 0.842773f, 0.869141f, 0.888672f, + 0.904785f, 0.917969f, 0.928711f, 0.936523f, 0.945312f, 0.951660f, 0.957031f, 0.961426f, 0.964844f, 0.968750f, 0.971680f, 0.974121f, + 0.976562f, 0.979004f, 0.980469f, 0.982422f, 0.983887f, 0.985352f, 0.986816f, 0.987793f, 0.988770f, 0.990234f, 0.990723f, 0.991699f, + 0.992676f, 0.993164f, 0.994141f, 0.994141f, 0.994629f, 0.995605f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, + 0.000244f, 0.001565f, 0.002975f, 0.004433f, 0.006596f, 0.008957f, 0.012215f, 0.015533f, 0.020294f, 0.026062f, 0.033722f, 0.042816f, + 0.055237f, 0.071960f, 0.094543f, 0.124023f, 0.164185f, 0.216309f, 0.281738f, 0.360352f, 0.446533f, 0.534180f, 0.615234f, 0.686523f, + 0.743652f, 0.790527f, 0.825684f, 0.855957f, 0.878418f, 0.895996f, 0.911133f, 0.923340f, 0.933105f, 0.941406f, 0.948242f, 0.953613f, + 0.959473f, 0.963379f, 0.966797f, 0.970703f, 0.973145f, 0.976074f, 0.978516f, 0.980469f, 0.982422f, 0.983398f, 0.984863f, 0.986328f, + 0.987305f, 0.989258f, 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.998047f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.000365f, 0.001394f, 0.002546f, 0.004055f, 0.005394f, 0.007465f, 0.009674f, 0.012070f, + 0.015556f, 0.019913f, 0.025696f, 0.032623f, 0.041046f, 0.052643f, 0.067383f, 0.087463f, 0.113708f, 0.148315f, 0.194946f, 0.254395f, + 0.326416f, 0.408691f, 0.495117f, 0.579102f, 0.654297f, 0.716797f, 0.768066f, 0.809570f, 0.843262f, 0.868652f, 0.888184f, 0.904785f, + 0.918457f, 0.929199f, 0.937500f, 0.945801f, 0.951660f, 0.957520f, 0.961914f, 0.965820f, 0.969238f, 0.972656f, 0.975098f, 0.978027f, + 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986328f, 0.987793f, 0.989258f, 0.989746f, 0.991211f, 0.991211f, 0.992188f, 0.993164f, + 0.993652f, 0.994629f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.000596f, 0.001077f, 0.001882f, 0.003033f, + 0.004559f, 0.006241f, 0.007805f, 0.010002f, 0.012840f, 0.015900f, 0.019974f, 0.025131f, 0.031250f, 0.039337f, 0.049988f, 0.063843f, + 0.080933f, 0.105164f, 0.135986f, 0.176880f, 0.230103f, 0.296631f, 0.374268f, 0.459961f, 0.544434f, 0.623535f, 0.691895f, 0.748535f, + 0.792969f, 0.829102f, 0.857422f, 0.880371f, 0.897949f, 0.913086f, 0.924805f, 0.934570f, 0.942383f, 0.949219f, 0.955566f, 0.960938f, + 0.964844f, 0.968750f, 0.971191f, 0.974121f, 0.977051f, 0.979004f, 0.980957f, 0.982910f, 0.984863f, 0.985840f, 0.987305f, 0.989258f, + 0.989746f, 0.991211f, 0.991211f, 0.992676f, 0.993164f, 0.993652f, 0.997559f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, + 0.000243f, 0.001173f, 0.001889f, 0.002661f, 0.003933f, 0.005131f, 0.006496f, 0.008324f, 0.010574f, 0.013115f, 0.015839f, 0.019913f, + 0.024445f, 0.030609f, 0.037781f, 0.047333f, 0.059906f, 0.075928f, 0.097229f, 0.124939f, 0.161743f, 0.209595f, 0.271240f, 0.343994f, + 0.426758f, 0.511719f, 0.592773f, 0.666504f, 0.727051f, 0.776855f, 0.815918f, 0.847656f, 0.871582f, 0.892090f, 0.907715f, 0.920898f, + 0.931152f, 0.940918f, 0.947754f, 0.953613f, 0.958496f, 0.963867f, 0.967773f, 0.970703f, 0.974121f, 0.976074f, 0.979004f, 0.980469f, + 0.982910f, 0.984375f, 0.985840f, 0.987305f, 0.988770f, 0.990234f, 0.990234f, 0.992188f, 0.992188f, 0.993164f, 0.997070f, 0.997559f, + 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.000351f, 0.000842f, 0.001560f, 0.002363f, 0.003258f, 0.004131f, 0.005272f, 0.007179f, + 0.008682f, 0.010643f, 0.013016f, 0.016037f, 0.019516f, 0.024078f, 0.029602f, 0.036591f, 0.045044f, 0.056641f, 0.071350f, 0.090576f, + 0.116211f, 0.149414f, 0.193237f, 0.248779f, 0.317871f, 0.396973f, 0.481201f, 0.564453f, 0.640137f, 0.705566f, 0.759766f, 0.802734f, + 0.836914f, 0.863281f, 0.885742f, 0.902832f, 0.916992f, 0.927734f, 0.937012f, 0.945801f, 0.952637f, 0.958008f, 0.961914f, 0.966309f, + 0.970703f, 0.974121f, 0.976074f, 0.978516f, 0.980957f, 0.982910f, 0.984863f, 0.985840f, 0.987305f, 0.988281f, 0.989746f, 0.990723f, + 0.991211f, 0.992676f, 0.997070f, 0.997559f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.000000f, 0.000886f, 0.001405f, 0.001915f, + 0.002651f, 0.003870f, 0.004845f, 0.006035f, 0.006912f, 0.008812f, 0.010887f, 0.013229f, 0.016022f, 0.019196f, 0.023590f, 0.028992f, + 0.035248f, 0.043304f, 0.053711f, 0.066956f, 0.085083f, 0.107727f, 0.138428f, 0.178589f, 0.229980f, 0.293945f, 0.370117f, 0.453369f, + 0.537109f, 0.616699f, 0.685059f, 0.743164f, 0.790039f, 0.826660f, 0.856445f, 0.878906f, 0.897949f, 0.913574f, 0.925293f, 0.935547f, + 0.943848f, 0.951172f, 0.957031f, 0.961914f, 0.966797f, 0.970215f, 0.973145f, 0.976562f, 0.979004f, 0.980469f, 0.982910f, 0.984375f, + 0.985840f, 0.987305f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, + 0.000104f, 0.000719f, 0.001065f, 0.001970f, 0.002544f, 0.003149f, 0.004230f, 0.005138f, 0.006119f, 0.007580f, 0.009201f, 0.010902f, + 0.013260f, 0.015526f, 0.019272f, 0.022858f, 0.027512f, 0.033569f, 0.041199f, 0.050873f, 0.063782f, 0.079895f, 0.101135f, 0.128906f, + 0.165771f, 0.213745f, 0.273193f, 0.345703f, 0.427002f, 0.511719f, 0.592773f, 0.666016f, 0.727051f, 0.776367f, 0.817871f, 0.848633f, + 0.875000f, 0.894531f, 0.909668f, 0.922852f, 0.934082f, 0.942383f, 0.949707f, 0.956055f, 0.961914f, 0.966309f, 0.970215f, 0.973145f, + 0.976562f, 0.978516f, 0.980957f, 0.982910f, 0.984375f, 0.986328f, 0.987305f, 0.988281f, 0.989746f, 0.991211f, 0.996582f, 0.997070f, + 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000240f, 0.000686f, 0.001052f, 0.001375f, 0.002308f, 0.002735f, 0.003510f, 0.004269f, + 0.005173f, 0.006649f, 0.007442f, 0.009109f, 0.011246f, 0.012886f, 0.015732f, 0.018829f, 0.022354f, 0.026672f, 0.032867f, 0.039764f, + 0.048492f, 0.060455f, 0.075806f, 0.095276f, 0.121033f, 0.155273f, 0.199097f, 0.255859f, 0.324463f, 0.404053f, 0.488525f, 0.571289f, + 0.646484f, 0.711426f, 0.765625f, 0.808105f, 0.841797f, 0.869141f, 0.890137f, 0.907227f, 0.920898f, 0.931641f, 0.940918f, 0.948730f, + 0.955078f, 0.960449f, 0.965820f, 0.969727f, 0.972656f, 0.976562f, 0.978516f, 0.980957f, 0.982910f, 0.984863f, 0.986328f, 0.987793f, + 0.989746f, 0.990723f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.000244f, 0.000597f, 0.000939f, 0.001369f, + 0.001999f, 0.002329f, 0.003105f, 0.003786f, 0.004395f, 0.005413f, 0.006474f, 0.007793f, 0.009254f, 0.010971f, 0.012970f, 0.015526f, + 0.018112f, 0.022049f, 0.026581f, 0.031586f, 0.038666f, 0.046967f, 0.057617f, 0.071777f, 0.089783f, 0.113953f, 0.145264f, 0.186646f, + 0.239990f, 0.305908f, 0.383301f, 0.467285f, 0.551270f, 0.629883f, 0.697266f, 0.754883f, 0.799805f, 0.835938f, 0.864258f, 0.886719f, + 0.905273f, 0.918945f, 0.931152f, 0.940918f, 0.948242f, 0.955078f, 0.961426f, 0.965332f, 0.969727f, 0.973633f, 0.976074f, 0.979004f, + 0.980957f, 0.983398f, 0.984863f, 0.987305f, 0.988281f, 0.989258f, 0.996094f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, + 0.000000f, 0.000475f, 0.000891f, 0.001390f, 0.001730f, 0.002060f, 0.002501f, 0.003109f, 0.003836f, 0.004837f, 0.005852f, 0.006859f, + 0.007740f, 0.009216f, 0.010918f, 0.012863f, 0.014915f, 0.017731f, 0.021317f, 0.025482f, 0.030930f, 0.037262f, 0.044891f, 0.055115f, + 0.068298f, 0.085510f, 0.107910f, 0.137207f, 0.176025f, 0.226929f, 0.289551f, 0.364746f, 0.447998f, 0.532715f, 0.613770f, 0.685547f, + 0.744629f, 0.791992f, 0.830078f, 0.860352f, 0.884277f, 0.903320f, 0.917969f, 0.930176f, 0.939941f, 0.947754f, 0.954590f, 0.961426f, + 0.966309f, 0.970215f, 0.973145f, 0.976562f, 0.979492f, 0.981445f, 0.983398f, 0.985352f, 0.987793f, 0.988281f, 0.995605f, 0.996094f, + 0.996094f, 0.996582f, 0.996094f, 0.996094f, 0.000102f, 0.000243f, 0.000844f, 0.001124f, 0.001554f, 0.002077f, 0.002098f, 0.002682f, + 0.003357f, 0.004280f, 0.005035f, 0.005764f, 0.006805f, 0.007633f, 0.009354f, 0.010872f, 0.012665f, 0.015099f, 0.017258f, 0.020599f, + 0.024887f, 0.029495f, 0.035522f, 0.042999f, 0.053070f, 0.065125f, 0.081299f, 0.102661f, 0.130371f, 0.166992f, 0.215088f, 0.275635f, + 0.348877f, 0.431641f, 0.517578f, 0.600098f, 0.672852f, 0.735352f, 0.785645f, 0.826172f, 0.856934f, 0.881836f, 0.900879f, 0.916992f, + 0.930176f, 0.940430f, 0.947754f, 0.955078f, 0.960938f, 0.966309f, 0.969238f, 0.973633f, 0.977051f, 0.979492f, 0.981934f, 0.983887f, + 0.986328f, 0.987793f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000241f, 0.000242f, 0.000823f, 0.000956f, + 0.001225f, 0.001549f, 0.002031f, 0.002613f, 0.003124f, 0.003574f, 0.004467f, 0.004955f, 0.005672f, 0.006752f, 0.007603f, 0.009186f, + 0.010704f, 0.012741f, 0.014366f, 0.017487f, 0.020142f, 0.024002f, 0.028915f, 0.034943f, 0.041656f, 0.050964f, 0.062622f, 0.077881f, + 0.097961f, 0.124207f, 0.158936f, 0.204590f, 0.263184f, 0.334961f, 0.416748f, 0.502930f, 0.587891f, 0.664062f, 0.728516f, 0.780762f, + 0.822266f, 0.854492f, 0.879395f, 0.900879f, 0.916504f, 0.928711f, 0.940430f, 0.948730f, 0.955566f, 0.961914f, 0.967285f, 0.970215f, + 0.974121f, 0.977539f, 0.979980f, 0.982422f, 0.984863f, 0.986816f, 0.994629f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, + 0.000000f, 0.000473f, 0.000607f, 0.000921f, 0.000957f, 0.001448f, 0.001884f, 0.002270f, 0.002703f, 0.002998f, 0.003862f, 0.004307f, + 0.005074f, 0.005665f, 0.006737f, 0.007851f, 0.009216f, 0.010735f, 0.012459f, 0.014572f, 0.016998f, 0.019821f, 0.023605f, 0.027969f, + 0.033783f, 0.040192f, 0.049286f, 0.060303f, 0.074829f, 0.093750f, 0.118774f, 0.152222f, 0.195801f, 0.252441f, 0.322754f, 0.404053f, + 0.491943f, 0.577637f, 0.655273f, 0.722168f, 0.776367f, 0.820312f, 0.854004f, 0.878906f, 0.900879f, 0.916992f, 0.929688f, 0.940430f, + 0.949707f, 0.956055f, 0.962402f, 0.967285f, 0.971191f, 0.975586f, 0.978516f, 0.980957f, 0.983398f, 0.985352f, 0.994141f, 0.995117f, + 0.995117f, 0.995605f, 0.995117f, 0.995605f, 0.000000f, 0.000444f, 0.000605f, 0.000649f, 0.000926f, 0.001096f, 0.001624f, 0.001669f, + 0.002373f, 0.002716f, 0.003231f, 0.003769f, 0.004395f, 0.005005f, 0.005878f, 0.006710f, 0.007793f, 0.008957f, 0.010712f, 0.012230f, + 0.014244f, 0.016693f, 0.019531f, 0.022827f, 0.027100f, 0.032318f, 0.038971f, 0.047302f, 0.058105f, 0.072021f, 0.089966f, 0.114319f, + 0.146362f, 0.188965f, 0.244019f, 0.312988f, 0.394287f, 0.482178f, 0.569824f, 0.650391f, 0.718262f, 0.774414f, 0.819336f, 0.853027f, + 0.880371f, 0.900879f, 0.917969f, 0.930664f, 0.940918f, 0.950684f, 0.957031f, 0.962891f, 0.968262f, 0.972656f, 0.976562f, 0.979004f, + 0.981934f, 0.984375f, 0.994141f, 0.994629f, 0.994629f, 0.995117f, 0.994629f, 0.995117f, 0.000000f, 0.000336f, 0.000601f, 0.000712f, + 0.000810f, 0.001174f, 0.001286f, 0.001618f, 0.002037f, 0.002592f, 0.002920f, 0.003223f, 0.003847f, 0.004463f, 0.005119f, 0.006020f, + 0.006783f, 0.007957f, 0.008888f, 0.010590f, 0.012230f, 0.013885f, 0.016220f, 0.019318f, 0.022278f, 0.026474f, 0.031403f, 0.037781f, + 0.046021f, 0.055969f, 0.069397f, 0.086975f, 0.110413f, 0.140991f, 0.182739f, 0.236694f, 0.304932f, 0.385986f, 0.475586f, 0.563965f, + 0.646484f, 0.716797f, 0.772461f, 0.818359f, 0.853027f, 0.880859f, 0.901855f, 0.918945f, 0.932129f, 0.942383f, 0.951172f, 0.958496f, + 0.964355f, 0.969238f, 0.973633f, 0.977051f, 0.979980f, 0.982910f, 0.993652f, 0.994141f, 0.994629f, 0.994141f, 0.994141f, 0.994629f, + 0.000000f, 0.000244f, 0.000418f, 0.000597f, 0.000600f, 0.001085f, 0.001236f, 0.001535f, 0.001970f, 0.002096f, 0.002354f, 0.002834f, + 0.003323f, 0.003822f, 0.004463f, 0.005146f, 0.005798f, 0.006859f, 0.007587f, 0.008827f, 0.009956f, 0.011833f, 0.013725f, 0.015945f, + 0.018585f, 0.021988f, 0.025665f, 0.030807f, 0.036774f, 0.044373f, 0.054108f, 0.067383f, 0.084229f, 0.106812f, 0.137207f, 0.177734f, + 0.230835f, 0.299072f, 0.380127f, 0.470215f, 0.560547f, 0.644531f, 0.715820f, 0.774414f, 0.820312f, 0.854980f, 0.882324f, 0.903809f, + 0.921387f, 0.933594f, 0.944824f, 0.952637f, 0.960449f, 0.965820f, 0.971191f, 0.974609f, 0.978027f, 0.981934f, 0.993164f, 0.994629f, + 0.994141f, 0.994141f, 0.994141f, 0.994141f, 0.000000f, 0.000244f, 0.000411f, 0.000589f, 0.000820f, 0.000729f, 0.001086f, 0.001301f, + 0.001677f, 0.001935f, 0.002312f, 0.002678f, 0.002846f, 0.003590f, 0.003914f, 0.004578f, 0.005020f, 0.005753f, 0.006706f, 0.007710f, + 0.008911f, 0.010155f, 0.011528f, 0.013504f, 0.015747f, 0.018036f, 0.021408f, 0.024994f, 0.029816f, 0.035858f, 0.043152f, 0.053009f, + 0.065491f, 0.082031f, 0.104065f, 0.133789f, 0.174072f, 0.226929f, 0.294434f, 0.376465f, 0.467773f, 0.560059f, 0.644531f, 0.717285f, + 0.777344f, 0.823242f, 0.857910f, 0.885742f, 0.906738f, 0.922852f, 0.936523f, 0.947266f, 0.955078f, 0.961426f, 0.967285f, 0.972656f, + 0.976562f, 0.979980f, 0.992676f, 0.993164f, 0.993652f, 0.993652f, 0.993652f, 0.993652f, 0.000000f, 0.000243f, 0.000243f, 0.000442f, + 0.000695f, 0.000759f, 0.000837f, 0.001089f, 0.001625f, 0.001702f, 0.002045f, 0.002176f, 0.002756f, 0.003063f, 0.003687f, 0.003893f, + 0.004456f, 0.005337f, 0.006062f, 0.006523f, 0.007572f, 0.008430f, 0.009880f, 0.011612f, 0.013237f, 0.015114f, 0.017487f, 0.020584f, + 0.024445f, 0.028931f, 0.034729f, 0.042023f, 0.051788f, 0.063843f, 0.079956f, 0.102295f, 0.131592f, 0.171021f, 0.223877f, 0.292236f, + 0.375000f, 0.468018f, 0.562012f, 0.648438f, 0.721191f, 0.781250f, 0.826660f, 0.862305f, 0.888672f, 0.909668f, 0.926270f, 0.938965f, + 0.949707f, 0.957520f, 0.964355f, 0.969727f, 0.974121f, 0.978027f, 0.992676f, 0.993164f, 0.993164f, 0.992676f, 0.993164f, 0.993164f, + 0.000000f, 0.000242f, 0.000242f, 0.000242f, 0.000564f, 0.000692f, 0.000826f, 0.001094f, 0.001280f, 0.001457f, 0.001673f, 0.002232f, + 0.002411f, 0.002789f, 0.003174f, 0.003649f, 0.003859f, 0.004349f, 0.004990f, 0.005898f, 0.006622f, 0.007496f, 0.008209f, 0.009583f, + 0.011284f, 0.013062f, 0.014763f, 0.017120f, 0.020020f, 0.023804f, 0.028412f, 0.033905f, 0.041016f, 0.050140f, 0.062469f, 0.078552f, + 0.100159f, 0.129272f, 0.169067f, 0.222290f, 0.291504f, 0.376465f, 0.470703f, 0.566406f, 0.653320f, 0.728027f, 0.786621f, 0.832031f, + 0.866699f, 0.893555f, 0.914062f, 0.929688f, 0.942383f, 0.952148f, 0.959961f, 0.966797f, 0.972168f, 0.976074f, 0.991211f, 0.992188f, + 0.992676f, 0.992188f, 0.992676f, 0.992676f, 0.000241f, 0.000241f, 0.000240f, 0.000242f, 0.000486f, 0.000637f, 0.000916f, 0.000933f, + 0.001003f, 0.001284f, 0.001584f, 0.001925f, 0.002134f, 0.002502f, 0.002731f, 0.003134f, 0.003435f, 0.004036f, 0.004379f, 0.005077f, + 0.005688f, 0.006557f, 0.007347f, 0.007942f, 0.009506f, 0.010712f, 0.012527f, 0.014603f, 0.016693f, 0.019592f, 0.023285f, 0.027512f, + 0.033173f, 0.040283f, 0.049347f, 0.061432f, 0.077271f, 0.098938f, 0.128052f, 0.168091f, 0.222168f, 0.292725f, 0.379150f, 0.476807f, + 0.573730f, 0.662598f, 0.735840f, 0.794434f, 0.839844f, 0.873535f, 0.898926f, 0.918945f, 0.934082f, 0.945312f, 0.955566f, 0.962402f, + 0.969238f, 0.974609f, 0.990723f, 0.991699f, 0.992188f, 0.992188f, 0.992188f, 0.992188f, 0.000000f, 0.000238f, 0.000240f, 0.000362f, + 0.000362f, 0.000521f, 0.000631f, 0.000909f, 0.000937f, 0.001249f, 0.001373f, 0.001693f, 0.001746f, 0.002184f, 0.002436f, 0.002680f, + 0.003094f, 0.003576f, 0.003828f, 0.004463f, 0.004990f, 0.005589f, 0.006439f, 0.006943f, 0.008217f, 0.009384f, 0.010719f, 0.012184f, + 0.014130f, 0.016373f, 0.019241f, 0.022675f, 0.027161f, 0.032379f, 0.039307f, 0.048645f, 0.060455f, 0.076416f, 0.097778f, 0.127441f, + 0.168213f, 0.223633f, 0.296387f, 0.385986f, 0.485107f, 0.583984f, 0.673340f, 0.746582f, 0.804199f, 0.848633f, 0.880371f, 0.905273f, + 0.923828f, 0.938477f, 0.949707f, 0.958984f, 0.965820f, 0.972656f, 0.990234f, 0.991211f, 0.991211f, 0.991211f, 0.991211f, 0.991211f, + 0.000000f, 0.000234f, 0.000238f, 0.000236f, 0.000360f, 0.000482f, 0.000614f, 0.000786f, 0.000900f, 0.001056f, 0.001336f, 0.001466f, + 0.001671f, 0.001907f, 0.002333f, 0.002546f, 0.002871f, 0.003067f, 0.003500f, 0.003813f, 0.004425f, 0.004574f, 0.005459f, 0.006092f, + 0.006660f, 0.007660f, 0.008987f, 0.010071f, 0.011841f, 0.013847f, 0.016022f, 0.018829f, 0.022339f, 0.026779f, 0.031677f, 0.038910f, + 0.047913f, 0.059601f, 0.075684f, 0.097290f, 0.127319f, 0.169189f, 0.226807f, 0.302490f, 0.394775f, 0.497314f, 0.598633f, 0.686523f, + 0.759766f, 0.814941f, 0.857422f, 0.888672f, 0.912109f, 0.930176f, 0.943359f, 0.954102f, 0.962402f, 0.968750f, 0.988770f, 0.990234f, + 0.990234f, 0.990234f, 0.991211f, 0.990723f, 0.000000f, 0.000036f, 0.000166f, 0.000357f, 0.000356f, 0.000478f, 0.000566f, 0.000638f, + 0.000893f, 0.001146f, 0.001242f, 0.001330f, 0.001502f, 0.001773f, 0.001918f, 0.002024f, 0.002501f, 0.002604f, 0.003067f, 0.003334f, + 0.003708f, 0.004044f, 0.004646f, 0.005268f, 0.006241f, 0.006931f, 0.007774f, 0.008911f, 0.010277f, 0.011475f, 0.013542f, 0.015732f, + 0.018417f, 0.022049f, 0.026154f, 0.031189f, 0.038269f, 0.047119f, 0.059265f, 0.075256f, 0.097534f, 0.128906f, 0.172119f, 0.231934f, + 0.311035f, 0.407715f, 0.513184f, 0.615723f, 0.703613f, 0.773926f, 0.827637f, 0.867188f, 0.897461f, 0.919434f, 0.936035f, 0.948730f, + 0.958984f, 0.966309f, 0.988770f, 0.989746f, 0.989746f, 0.990234f, 0.989746f, 0.989746f, 0.000000f, 0.000028f, 0.000093f, 0.000334f, + 0.000465f, 0.000472f, 0.000373f, 0.000685f, 0.000695f, 0.001027f, 0.001128f, 0.001155f, 0.001419f, 0.001435f, 0.001760f, 0.001850f, + 0.002241f, 0.002373f, 0.002604f, 0.002821f, 0.003334f, 0.003666f, 0.004139f, 0.004627f, 0.005207f, 0.005886f, 0.006596f, 0.007580f, + 0.008705f, 0.009911f, 0.011520f, 0.013237f, 0.015427f, 0.017944f, 0.021423f, 0.025497f, 0.030945f, 0.037537f, 0.046692f, 0.058624f, + 0.075317f, 0.098267f, 0.130493f, 0.176025f, 0.239136f, 0.323242f, 0.424561f, 0.533691f, 0.636230f, 0.723145f, 0.790039f, 0.841797f, + 0.880371f, 0.906738f, 0.926758f, 0.941406f, 0.953613f, 0.963379f, 0.987793f, 0.988770f, 0.988770f, 0.989258f, 0.989258f, 0.989258f, + 0.000000f, 0.000000f, 0.000047f, 0.000321f, 0.000332f, 0.000351f, 0.000470f, 0.000596f, 0.000655f, 0.000727f, 0.001008f, 0.001112f, + 0.001350f, 0.001379f, 0.001380f, 0.001751f, 0.002008f, 0.002151f, 0.002327f, 0.002548f, 0.002691f, 0.003056f, 0.003475f, 0.003925f, + 0.004749f, 0.005161f, 0.005863f, 0.006538f, 0.007153f, 0.008453f, 0.009789f, 0.010986f, 0.013168f, 0.015121f, 0.017563f, 0.020966f, + 0.025009f, 0.030151f, 0.037048f, 0.046570f, 0.058624f, 0.075623f, 0.099243f, 0.133667f, 0.181641f, 0.249756f, 0.338623f, 0.445312f, + 0.556641f, 0.659180f, 0.744141f, 0.808594f, 0.855957f, 0.890137f, 0.916992f, 0.934570f, 0.949219f, 0.959473f, 0.986816f, 0.987793f, + 0.987793f, 0.987793f, 0.987793f, 0.988281f, 0.000000f, 0.000000f, 0.000000f, 0.000244f, 0.000429f, 0.000440f, 0.000348f, 0.000592f, + 0.000606f, 0.000755f, 0.000690f, 0.000935f, 0.001172f, 0.001257f, 0.001368f, 0.001458f, 0.001786f, 0.001809f, 0.002060f, 0.002274f, + 0.002478f, 0.002642f, 0.002987f, 0.003435f, 0.003866f, 0.004337f, 0.005066f, 0.005409f, 0.006355f, 0.007111f, 0.008011f, 0.009392f, + 0.011032f, 0.012321f, 0.014717f, 0.017319f, 0.020432f, 0.024551f, 0.029953f, 0.036835f, 0.045929f, 0.058716f, 0.076416f, 0.101562f, + 0.137695f, 0.189453f, 0.262451f, 0.358154f, 0.470215f, 0.584961f, 0.686523f, 0.767578f, 0.828125f, 0.871582f, 0.903809f, 0.926270f, + 0.941895f, 0.956055f, 0.985352f, 0.986328f, 0.986816f, 0.986816f, 0.986816f, 0.986816f, 0.000000f, 0.000000f, 0.000000f, 0.000119f, + 0.000237f, 0.000314f, 0.000570f, 0.000575f, 0.000583f, 0.000632f, 0.000651f, 0.000789f, 0.000947f, 0.001097f, 0.001300f, 0.001320f, + 0.001384f, 0.001443f, 0.001641f, 0.001869f, 0.002047f, 0.002396f, 0.002634f, 0.003025f, 0.003412f, 0.003757f, 0.004238f, 0.004620f, + 0.005463f, 0.006168f, 0.007072f, 0.008080f, 0.009155f, 0.010590f, 0.012306f, 0.014175f, 0.016769f, 0.020081f, 0.023972f, 0.029495f, + 0.036560f, 0.045959f, 0.059265f, 0.078125f, 0.104797f, 0.143677f, 0.199951f, 0.279785f, 0.382812f, 0.500977f, 0.616699f, 0.716309f, + 0.791992f, 0.847168f, 0.887207f, 0.915527f, 0.936523f, 0.950684f, 0.984375f, 0.985352f, 0.986328f, 0.985840f, 0.986328f, 0.985840f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000205f, 0.000239f, 0.000299f, 0.000537f, 0.000574f, 0.000696f, 0.000583f, 0.000740f, + 0.000778f, 0.000867f, 0.001013f, 0.001257f, 0.001325f, 0.001277f, 0.001416f, 0.001718f, 0.001965f, 0.002079f, 0.002356f, 0.002577f, + 0.002771f, 0.003305f, 0.003693f, 0.004028f, 0.004593f, 0.005234f, 0.005905f, 0.006802f, 0.007698f, 0.008553f, 0.009995f, 0.011635f, + 0.013824f, 0.016174f, 0.019547f, 0.023544f, 0.029114f, 0.036377f, 0.046417f, 0.060211f, 0.080017f, 0.108643f, 0.151611f, 0.213379f, + 0.301758f, 0.414062f, 0.537598f, 0.653320f, 0.748047f, 0.817871f, 0.868164f, 0.903320f, 0.928711f, 0.945801f, 0.982910f, 0.983887f, + 0.984375f, 0.984375f, 0.984863f, 0.984375f, 0.000000f, 0.000000f, 0.000045f, 0.000105f, 0.000114f, 0.000340f, 0.000371f, 0.000501f, + 0.000639f, 0.000554f, 0.000687f, 0.000675f, 0.000711f, 0.000738f, 0.000824f, 0.001092f, 0.001040f, 0.001185f, 0.001212f, 0.001408f, + 0.001624f, 0.001813f, 0.001982f, 0.002182f, 0.002634f, 0.002748f, 0.003252f, 0.003540f, 0.004089f, 0.004505f, 0.005001f, 0.005657f, + 0.006500f, 0.007195f, 0.008286f, 0.009750f, 0.011208f, 0.013420f, 0.015762f, 0.019226f, 0.023209f, 0.029144f, 0.036591f, 0.047150f, + 0.061615f, 0.082947f, 0.114014f, 0.161621f, 0.231323f, 0.329834f, 0.451416f, 0.579590f, 0.692871f, 0.780273f, 0.844238f, 0.888184f, + 0.917969f, 0.939453f, 0.981445f, 0.982422f, 0.982910f, 0.982910f, 0.982910f, 0.982910f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000208f, 0.000311f, 0.000238f, 0.000337f, 0.000524f, 0.000617f, 0.000533f, 0.000675f, 0.000665f, 0.000776f, 0.000840f, 0.000819f, + 0.000902f, 0.001169f, 0.001130f, 0.001178f, 0.001382f, 0.001571f, 0.001941f, 0.001932f, 0.002138f, 0.002306f, 0.002586f, 0.002937f, + 0.003468f, 0.003740f, 0.004292f, 0.004704f, 0.005444f, 0.006081f, 0.007019f, 0.008255f, 0.009521f, 0.010796f, 0.012840f, 0.015503f, + 0.018784f, 0.023178f, 0.029129f, 0.036774f, 0.047699f, 0.063416f, 0.086548f, 0.121399f, 0.175293f, 0.254883f, 0.365234f, 0.496582f, + 0.626953f, 0.733398f, 0.813477f, 0.869629f, 0.906738f, 0.933105f, 0.979980f, 0.980957f, 0.981445f, 0.981445f, 0.980957f, 0.981445f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000208f, 0.000312f, 0.000236f, 0.000343f, 0.000475f, 0.000496f, 0.000528f, + 0.000659f, 0.000582f, 0.000685f, 0.000710f, 0.000761f, 0.000784f, 0.000941f, 0.001013f, 0.001117f, 0.001339f, 0.001500f, 0.001623f, + 0.001769f, 0.002039f, 0.002298f, 0.002565f, 0.002802f, 0.003119f, 0.003471f, 0.003857f, 0.004658f, 0.005177f, 0.005836f, 0.006752f, + 0.007324f, 0.008911f, 0.010422f, 0.012527f, 0.015373f, 0.018585f, 0.022964f, 0.029037f, 0.037231f, 0.049072f, 0.066345f, 0.091492f, + 0.131470f, 0.193359f, 0.285645f, 0.409912f, 0.548828f, 0.676758f, 0.776367f, 0.845703f, 0.893066f, 0.924805f, 0.978027f, 0.979492f, + 0.979492f, 0.979004f, 0.979492f, 0.979492f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000166f, 0.000228f, 0.000227f, + 0.000369f, 0.000337f, 0.000368f, 0.000452f, 0.000500f, 0.000547f, 0.000543f, 0.000575f, 0.000623f, 0.000723f, 0.000783f, 0.000874f, + 0.001141f, 0.001226f, 0.001279f, 0.001336f, 0.001499f, 0.001655f, 0.001922f, 0.002090f, 0.002453f, 0.002298f, 0.003139f, 0.003181f, + 0.003674f, 0.004166f, 0.004814f, 0.005447f, 0.006348f, 0.007179f, 0.008736f, 0.010406f, 0.012321f, 0.014984f, 0.018219f, 0.022934f, + 0.028824f, 0.037598f, 0.050476f, 0.069397f, 0.098694f, 0.144775f, 0.218018f, 0.325439f, 0.464111f, 0.607910f, 0.729492f, 0.817383f, + 0.876953f, 0.915527f, 0.976562f, 0.977539f, 0.977539f, 0.977051f, 0.977051f, 0.977539f, 0.000000f, 0.000000f, 0.000000f, 0.000122f, + 0.000122f, 0.000122f, 0.000154f, 0.000200f, 0.000267f, 0.000316f, 0.000324f, 0.000449f, 0.000319f, 0.000379f, 0.000515f, 0.000519f, + 0.000558f, 0.000628f, 0.000645f, 0.000690f, 0.000777f, 0.000940f, 0.001096f, 0.001204f, 0.001278f, 0.001485f, 0.001670f, 0.001929f, + 0.001961f, 0.002016f, 0.002367f, 0.002785f, 0.003025f, 0.003248f, 0.003805f, 0.004539f, 0.004845f, 0.005733f, 0.006851f, 0.008278f, + 0.010017f, 0.011841f, 0.014542f, 0.017807f, 0.022705f, 0.029190f, 0.038544f, 0.052612f, 0.073853f, 0.108093f, 0.162842f, 0.250977f, + 0.377930f, 0.529785f, 0.672363f, 0.782715f, 0.855957f, 0.904297f, 0.973145f, 0.974121f, 0.974609f, 0.975586f, 0.974609f, 0.975098f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000158f, 0.000121f, 0.000190f, 0.000238f, 0.000397f, 0.000354f, + 0.000364f, 0.000365f, 0.000440f, 0.000474f, 0.000509f, 0.000612f, 0.000611f, 0.000648f, 0.000804f, 0.000755f, 0.000943f, 0.001050f, + 0.001221f, 0.001340f, 0.001338f, 0.001443f, 0.001635f, 0.001822f, 0.002083f, 0.002226f, 0.002480f, 0.002682f, 0.003185f, 0.003609f, + 0.003948f, 0.005074f, 0.005558f, 0.006741f, 0.007904f, 0.009384f, 0.011360f, 0.014000f, 0.017883f, 0.022675f, 0.029648f, 0.039917f, + 0.055695f, 0.080261f, 0.120728f, 0.188354f, 0.296143f, 0.443848f, 0.603027f, 0.737793f, 0.831055f, 0.891113f, 0.970703f, 0.971680f, + 0.972168f, 0.972656f, 0.971680f, 0.972168f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f, + 0.000121f, 0.000251f, 0.000260f, 0.000278f, 0.000315f, 0.000334f, 0.000235f, 0.000357f, 0.000442f, 0.000513f, 0.000504f, 0.000598f, + 0.000556f, 0.000771f, 0.000831f, 0.000886f, 0.000977f, 0.001145f, 0.001105f, 0.001244f, 0.001281f, 0.001431f, 0.001544f, 0.001850f, + 0.001986f, 0.002131f, 0.002537f, 0.002737f, 0.003252f, 0.003826f, 0.004555f, 0.005184f, 0.006199f, 0.007195f, 0.009041f, 0.011337f, + 0.013878f, 0.017395f, 0.022552f, 0.030502f, 0.041962f, 0.059875f, 0.089111f, 0.139404f, 0.224609f, 0.357910f, 0.524902f, 0.684082f, + 0.800781f, 0.875977f, 0.967773f, 0.968750f, 0.968262f, 0.968750f, 0.969238f, 0.969238f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, + 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000095f, 0.000081f, 0.000217f, 0.000149f, 0.000204f, 0.000212f, 0.000338f, + 0.000345f, 0.000348f, 0.000456f, 0.000463f, 0.000495f, 0.000570f, 0.000583f, 0.000748f, 0.000799f, 0.000731f, 0.000965f, 0.001041f, + 0.001071f, 0.001210f, 0.001318f, 0.001238f, 0.001410f, 0.001631f, 0.001932f, 0.002327f, 0.002577f, 0.003057f, 0.003452f, 0.003956f, + 0.004639f, 0.005714f, 0.006817f, 0.008446f, 0.010605f, 0.013443f, 0.017319f, 0.022964f, 0.031021f, 0.044281f, 0.065857f, 0.102112f, + 0.166504f, 0.277344f, 0.439941f, 0.617188f, 0.762207f, 0.856445f, 0.963379f, 0.964355f, 0.965332f, 0.964844f, 0.965332f, 0.965332f, + 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000107f, 0.000091f, 0.000161f, + 0.000119f, 0.000184f, 0.000266f, 0.000284f, 0.000314f, 0.000319f, 0.000334f, 0.000344f, 0.000565f, 0.000455f, 0.000488f, 0.000667f, + 0.000710f, 0.000713f, 0.000787f, 0.000755f, 0.000849f, 0.000972f, 0.001097f, 0.001286f, 0.001427f, 0.001556f, 0.001667f, 0.001687f, + 0.002155f, 0.002369f, 0.002674f, 0.003086f, 0.003710f, 0.004536f, 0.005585f, 0.006783f, 0.007957f, 0.010262f, 0.013115f, 0.017212f, + 0.023102f, 0.032715f, 0.047943f, 0.074158f, 0.121155f, 0.207520f, 0.353027f, 0.541504f, 0.715332f, 0.834473f, 0.959473f, 0.960449f, + 0.960938f, 0.960938f, 0.960938f, 0.961426f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, + 0.000120f, 0.000120f, 0.000103f, 0.000089f, 0.000077f, 0.000080f, 0.000121f, 0.000218f, 0.000209f, 0.000245f, 0.000303f, 0.000316f, + 0.000388f, 0.000341f, 0.000549f, 0.000594f, 0.000604f, 0.000679f, 0.000625f, 0.000628f, 0.000795f, 0.000883f, 0.000857f, 0.000991f, + 0.001166f, 0.000955f, 0.001194f, 0.001347f, 0.001548f, 0.001804f, 0.002048f, 0.002388f, 0.002911f, 0.003130f, 0.003933f, 0.004845f, + 0.006031f, 0.007385f, 0.009705f, 0.012688f, 0.017044f, 0.023788f, 0.034882f, 0.053284f, 0.086670f, 0.151123f, 0.271484f, 0.457031f, + 0.658203f, 0.805176f, 0.954102f, 0.955078f, 0.956055f, 0.956055f, 0.956055f, 0.955566f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, + 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000116f, 0.000101f, 0.000088f, 0.000077f, 0.000131f, 0.000071f, + 0.000146f, 0.000200f, 0.000237f, 0.000270f, 0.000289f, 0.000302f, 0.000311f, 0.000441f, 0.000396f, 0.000588f, 0.000630f, 0.000570f, + 0.000575f, 0.000537f, 0.000589f, 0.000750f, 0.000721f, 0.001048f, 0.001122f, 0.000951f, 0.001243f, 0.001346f, 0.001703f, 0.001592f, + 0.001880f, 0.002340f, 0.002804f, 0.003637f, 0.004356f, 0.005329f, 0.006805f, 0.009094f, 0.012566f, 0.017181f, 0.025040f, 0.038147f, + 0.061249f, 0.107788f, 0.200195f, 0.369629f, 0.587891f, 0.771973f, 0.948242f, 0.949707f, 0.950195f, 0.949707f, 0.950195f, 0.950195f, + 0.000000f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000119f, 0.000114f, + 0.000101f, 0.000088f, 0.000079f, 0.000070f, 0.000063f, 0.000136f, 0.000136f, 0.000183f, 0.000207f, 0.000277f, 0.000271f, 0.000291f, + 0.000369f, 0.000344f, 0.000494f, 0.000459f, 0.000515f, 0.000509f, 0.000532f, 0.000504f, 0.000716f, 0.000589f, 0.000691f, 0.000902f, + 0.000972f, 0.000968f, 0.001067f, 0.001483f, 0.001780f, 0.001652f, 0.002090f, 0.002602f, 0.003113f, 0.003738f, 0.004738f, 0.006420f, + 0.008522f, 0.012100f, 0.017334f, 0.026489f, 0.042786f, 0.074524f, 0.142578f, 0.283936f, 0.509277f, 0.729492f, 0.940918f, 0.941895f, + 0.942383f, 0.942383f, 0.942383f, 0.942871f, 0.000122f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000119f, + 0.000119f, 0.000118f, 0.000118f, 0.000118f, 0.000116f, 0.000102f, 0.000090f, 0.000081f, 0.000091f, 0.000066f, 0.000059f, 0.000110f, + 0.000109f, 0.000155f, 0.000184f, 0.000227f, 0.000297f, 0.000333f, 0.000355f, 0.000349f, 0.000344f, 0.000421f, 0.000459f, 0.000561f, + 0.000600f, 0.000563f, 0.000630f, 0.000563f, 0.000682f, 0.000737f, 0.000892f, 0.001037f, 0.001026f, 0.001163f, 0.001743f, 0.001782f, + 0.002117f, 0.002573f, 0.003389f, 0.004429f, 0.005871f, 0.007942f, 0.011841f, 0.018066f, 0.029190f, 0.050842f, 0.098511f, 0.207397f, + 0.422363f, 0.677734f, 0.932129f, 0.933594f, 0.933594f, 0.934082f, 0.934082f, 0.934082f, 0.000000f, 0.000121f, 0.000120f, 0.000119f, + 0.000119f, 0.000119f, 0.000118f, 0.000118f, 0.000118f, 0.000117f, 0.000117f, 0.000117f, 0.000117f, 0.000116f, 0.000104f, 0.000093f, + 0.000084f, 0.000076f, 0.000069f, 0.000091f, 0.000057f, 0.000051f, 0.000112f, 0.000120f, 0.000179f, 0.000232f, 0.000225f, 0.000283f, + 0.000301f, 0.000308f, 0.000353f, 0.000437f, 0.000395f, 0.000523f, 0.000486f, 0.000504f, 0.000469f, 0.000614f, 0.000581f, 0.000755f, + 0.000789f, 0.001121f, 0.000981f, 0.001218f, 0.001565f, 0.001795f, 0.002296f, 0.002958f, 0.003866f, 0.005329f, 0.007675f, 0.011658f, + 0.019043f, 0.033478f, 0.065430f, 0.144043f, 0.331299f, 0.613770f, 0.921387f, 0.922852f, 0.923340f, 0.923340f, 0.923340f, 0.923340f, + 0.000000f, 0.000000f, 0.000119f, 0.000118f, 0.000118f, 0.000117f, 0.000116f, 0.000116f, 0.000116f, 0.000116f, 0.000115f, 0.000115f, + 0.000115f, 0.000115f, 0.000114f, 0.000108f, 0.000097f, 0.000087f, 0.000079f, 0.000072f, 0.000065f, 0.000060f, 0.000094f, 0.000050f, + 0.000104f, 0.000104f, 0.000121f, 0.000164f, 0.000195f, 0.000247f, 0.000265f, 0.000328f, 0.000290f, 0.000355f, 0.000395f, 0.000356f, + 0.000361f, 0.000459f, 0.000470f, 0.000515f, 0.000580f, 0.000624f, 0.000751f, 0.000964f, 0.001105f, 0.001279f, 0.001413f, 0.001823f, + 0.002441f, 0.003407f, 0.004852f, 0.007210f, 0.011803f, 0.021225f, 0.041473f, 0.095032f, 0.244019f, 0.537598f, 0.907715f, 0.910156f, + 0.910156f, 0.909180f, 0.909668f, 0.911133f, 0.000120f, 0.000118f, 0.000117f, 0.000116f, 0.000114f, 0.000114f, 0.000114f, 0.000113f, + 0.000113f, 0.000112f, 0.000112f, 0.000112f, 0.000111f, 0.000112f, 0.000111f, 0.000111f, 0.000111f, 0.000101f, 0.000093f, 0.000084f, + 0.000077f, 0.000070f, 0.000064f, 0.000059f, 0.000074f, 0.000079f, 0.000059f, 0.000087f, 0.000097f, 0.000128f, 0.000185f, 0.000213f, + 0.000265f, 0.000235f, 0.000239f, 0.000288f, 0.000299f, 0.000371f, 0.000341f, 0.000369f, 0.000460f, 0.000446f, 0.000490f, 0.000602f, + 0.000694f, 0.000904f, 0.001012f, 0.001234f, 0.001544f, 0.002096f, 0.002989f, 0.004299f, 0.006840f, 0.012383f, 0.024948f, 0.059204f, + 0.166626f, 0.452637f, 0.892578f, 0.894043f, 0.894043f, 0.894531f, 0.894531f, 0.894043f, 0.000115f, 0.000107f, 0.000108f, 0.000111f, + 0.000108f, 0.000109f, 0.000108f, 0.000108f, 0.000108f, 0.000107f, 0.000108f, 0.000107f, 0.000107f, 0.000106f, 0.000107f, 0.000107f, + 0.000106f, 0.000107f, 0.000106f, 0.000097f, 0.000090f, 0.000082f, 0.000075f, 0.000069f, 0.000063f, 0.000058f, 0.000053f, 0.000070f, + 0.000073f, 0.000085f, 0.000077f, 0.000088f, 0.000136f, 0.000168f, 0.000190f, 0.000204f, 0.000199f, 0.000252f, 0.000233f, 0.000270f, + 0.000325f, 0.000295f, 0.000348f, 0.000383f, 0.000435f, 0.000534f, 0.000581f, 0.000803f, 0.001004f, 0.001330f, 0.001812f, 0.002489f, + 0.003944f, 0.006832f, 0.013748f, 0.033997f, 0.104858f, 0.356689f, 0.873047f, 0.873047f, 0.875000f, 0.874023f, 0.874023f, 0.874023f, + 0.000000f, 0.000071f, 0.000063f, 0.000094f, 0.000092f, 0.000094f, 0.000093f, 0.000098f, 0.000098f, 0.000098f, 0.000098f, 0.000099f, + 0.000098f, 0.000099f, 0.000099f, 0.000099f, 0.000099f, 0.000099f, 0.000099f, 0.000100f, 0.000100f, 0.000094f, 0.000087f, 0.000080f, + 0.000074f, 0.000068f, 0.000062f, 0.000058f, 0.000053f, 0.000049f, 0.000059f, 0.000059f, 0.000045f, 0.000078f, 0.000082f, 0.000118f, + 0.000155f, 0.000160f, 0.000174f, 0.000180f, 0.000226f, 0.000213f, 0.000248f, 0.000258f, 0.000288f, 0.000352f, 0.000396f, 0.000465f, + 0.000566f, 0.000789f, 0.000941f, 0.001343f, 0.002199f, 0.003616f, 0.006912f, 0.017380f, 0.058960f, 0.259521f, 0.847656f, 0.849121f, + 0.850586f, 0.850098f, 0.849121f, 0.850586f, 0.000000f, 0.000000f, 0.000019f, 0.000044f, 0.000048f, 0.000061f, 0.000071f, 0.000073f, + 0.000076f, 0.000079f, 0.000079f, 0.000082f, 0.000082f, 0.000082f, 0.000085f, 0.000086f, 0.000087f, 0.000086f, 0.000088f, 0.000087f, + 0.000089f, 0.000089f, 0.000089f, 0.000090f, 0.000084f, 0.000078f, 0.000072f, 0.000067f, 0.000062f, 0.000057f, 0.000052f, 0.000049f, + 0.000045f, 0.000041f, 0.000038f, 0.000040f, 0.000062f, 0.000092f, 0.000100f, 0.000121f, 0.000144f, 0.000133f, 0.000137f, 0.000170f, + 0.000181f, 0.000168f, 0.000215f, 0.000286f, 0.000327f, 0.000397f, 0.000504f, 0.000738f, 0.001039f, 0.001729f, 0.003317f, 0.007721f, + 0.028458f, 0.166626f, 0.815430f, 0.818359f, 0.818359f, 0.817383f, 0.818848f, 0.818359f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000008f, 0.000016f, 0.000031f, 0.000035f, 0.000048f, 0.000050f, 0.000053f, 0.000058f, 0.000059f, + 0.000063f, 0.000064f, 0.000067f, 0.000067f, 0.000070f, 0.000071f, 0.000072f, 0.000073f, 0.000075f, 0.000075f, 0.000076f, 0.000075f, + 0.000069f, 0.000064f, 0.000060f, 0.000055f, 0.000051f, 0.000047f, 0.000043f, 0.000040f, 0.000037f, 0.000034f, 0.000040f, 0.000041f, + 0.000054f, 0.000069f, 0.000096f, 0.000111f, 0.000109f, 0.000113f, 0.000142f, 0.000136f, 0.000158f, 0.000196f, 0.000237f, 0.000349f, + 0.000423f, 0.000744f, 0.001380f, 0.003214f, 0.011124f, 0.088135f, 0.777344f, 0.779297f, 0.780273f, 0.779785f, 0.779785f, 0.779785f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000003f, 0.000007f, 0.000021f, 0.000023f, 0.000031f, 0.000034f, 0.000038f, 0.000041f, 0.000043f, 0.000047f, + 0.000049f, 0.000050f, 0.000053f, 0.000055f, 0.000056f, 0.000057f, 0.000059f, 0.000060f, 0.000055f, 0.000051f, 0.000048f, 0.000044f, + 0.000041f, 0.000038f, 0.000035f, 0.000032f, 0.000029f, 0.000028f, 0.000028f, 0.000037f, 0.000044f, 0.000064f, 0.000078f, 0.000072f, + 0.000089f, 0.000098f, 0.000104f, 0.000146f, 0.000200f, 0.000272f, 0.000479f, 0.001077f, 0.003733f, 0.033752f, 0.729492f, 0.730957f, + 0.732422f, 0.731934f, 0.732422f, 0.732422f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000006f, 0.000009f, 0.000013f, 0.000019f, 0.000021f, 0.000025f, 0.000027f, 0.000030f, + 0.000033f, 0.000034f, 0.000037f, 0.000039f, 0.000041f, 0.000039f, 0.000036f, 0.000033f, 0.000031f, 0.000028f, 0.000026f, 0.000024f, + 0.000021f, 0.000019f, 0.000017f, 0.000023f, 0.000033f, 0.000041f, 0.000043f, 0.000058f, 0.000061f, 0.000081f, 0.000121f, 0.000248f, + 0.000821f, 0.008255f, 0.673340f, 0.674805f, 0.674316f, 0.674805f, 0.674805f, 0.673828f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000006f, 0.000010f, 0.000013f, + 0.000015f, 0.000017f, 0.000020f, 0.000022f, 0.000021f, 0.000019f, 0.000017f, 0.000015f, 0.000013f, 0.000012f, 0.000010f, 0.000011f, + 0.000016f, 0.000019f, 0.000019f, 0.000036f, 0.000090f, 0.000897f, 0.606934f, 0.609863f, 0.609375f, 0.609863f, 0.609863f, 0.610352f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000001f, 0.000003f, 0.000006f, 0.000005f, 0.000004f, 0.000003f, 0.000004f, 0.000008f, 0.534668f, 0.536621f, + 0.537109f, 0.537109f, 0.536621f, 0.536621f, + }, + { + 0.149292f, 0.432373f, 0.614258f, 0.719238f, 0.784180f, 0.826660f, 0.856934f, 0.879883f, 0.896484f, 0.909180f, 0.919922f, 0.928711f, + 0.936035f, 0.942383f, 0.947266f, 0.952148f, 0.956055f, 0.959473f, 0.962891f, 0.965820f, 0.968262f, 0.970703f, 0.972656f, 0.974609f, + 0.976562f, 0.978027f, 0.979492f, 0.980469f, 0.981934f, 0.983398f, 0.984863f, 0.985352f, 0.986328f, 0.987305f, 0.988281f, 0.989258f, + 0.989746f, 0.990234f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.996094f, + 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.998047f, 0.998047f, 0.998535f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999512f, 0.999512f, 0.999512f, 0.999023f, 0.040161f, 0.161255f, 0.324951f, 0.486572f, 0.612305f, 0.704590f, 0.767090f, 0.811523f, + 0.844238f, 0.868652f, 0.887695f, 0.902344f, 0.913574f, 0.924316f, 0.932129f, 0.937988f, 0.944336f, 0.949707f, 0.954102f, 0.957520f, + 0.960938f, 0.964355f, 0.966797f, 0.969727f, 0.971191f, 0.973633f, 0.975586f, 0.977539f, 0.979004f, 0.980469f, 0.981445f, 0.982910f, + 0.983887f, 0.985352f, 0.985840f, 0.987305f, 0.987793f, 0.988770f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, + 0.993164f, 0.993652f, 0.994141f, 0.995117f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, + 0.999023f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999023f, 0.017395f, 0.068542f, 0.149292f, 0.262451f, + 0.392822f, 0.518066f, 0.621582f, 0.700195f, 0.759766f, 0.803711f, 0.836426f, 0.862305f, 0.880859f, 0.896484f, 0.909668f, 0.919434f, + 0.929199f, 0.935547f, 0.941895f, 0.947754f, 0.952637f, 0.956055f, 0.959961f, 0.963867f, 0.965820f, 0.968750f, 0.970703f, 0.973145f, + 0.975098f, 0.977051f, 0.979004f, 0.979980f, 0.981934f, 0.983398f, 0.983887f, 0.984863f, 0.985840f, 0.986816f, 0.987793f, 0.989258f, + 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.992188f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995605f, 0.996094f, 0.996094f, + 0.996582f, 0.997070f, 0.997559f, 0.997559f, 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999512f, 0.999023f, + 0.009125f, 0.035492f, 0.075806f, 0.135864f, 0.219971f, 0.324707f, 0.437012f, 0.543457f, 0.633789f, 0.704102f, 0.758789f, 0.802246f, + 0.833496f, 0.857910f, 0.878418f, 0.894043f, 0.906738f, 0.917480f, 0.925781f, 0.933594f, 0.940918f, 0.946777f, 0.951172f, 0.954590f, + 0.959473f, 0.962891f, 0.965820f, 0.968262f, 0.971191f, 0.973145f, 0.975098f, 0.976562f, 0.978516f, 0.979980f, 0.981445f, 0.982422f, + 0.983887f, 0.985840f, 0.986328f, 0.987305f, 0.988281f, 0.988770f, 0.989746f, 0.990234f, 0.991699f, 0.992188f, 0.992676f, 0.993652f, + 0.994141f, 0.994629f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996582f, 0.997559f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.005848f, 0.021225f, 0.043640f, 0.076782f, 0.124084f, 0.189575f, 0.274414f, 0.372559f, + 0.473633f, 0.567383f, 0.646973f, 0.711426f, 0.761230f, 0.801758f, 0.833496f, 0.857422f, 0.876953f, 0.893066f, 0.905273f, 0.916504f, + 0.925293f, 0.932617f, 0.939941f, 0.945801f, 0.950684f, 0.955566f, 0.958984f, 0.962402f, 0.965820f, 0.968262f, 0.970703f, 0.972656f, + 0.975098f, 0.977051f, 0.978516f, 0.980469f, 0.981934f, 0.982422f, 0.983887f, 0.985840f, 0.986328f, 0.987305f, 0.988281f, 0.989258f, + 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.995117f, 0.996094f, 0.996094f, 0.997070f, + 0.997559f, 0.997559f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.998535f, 0.003937f, 0.014107f, 0.027664f, 0.047211f, + 0.075195f, 0.113953f, 0.166748f, 0.236328f, 0.320312f, 0.412354f, 0.504395f, 0.589844f, 0.661621f, 0.719727f, 0.768066f, 0.805664f, + 0.834961f, 0.858398f, 0.877441f, 0.893066f, 0.906738f, 0.916992f, 0.926270f, 0.933105f, 0.940430f, 0.946289f, 0.951172f, 0.955566f, + 0.959473f, 0.962891f, 0.965820f, 0.968262f, 0.970703f, 0.973145f, 0.975098f, 0.977051f, 0.979004f, 0.980469f, 0.981934f, 0.983398f, + 0.984375f, 0.985840f, 0.986328f, 0.987305f, 0.988770f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.992676f, 0.993652f, 0.994629f, + 0.994629f, 0.995117f, 0.995605f, 0.995605f, 0.996582f, 0.997070f, 0.998535f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.998535f, + 0.002962f, 0.009674f, 0.019348f, 0.031708f, 0.049255f, 0.072754f, 0.105164f, 0.149048f, 0.206665f, 0.278076f, 0.361572f, 0.448730f, + 0.534668f, 0.611816f, 0.677734f, 0.730957f, 0.775879f, 0.809570f, 0.837891f, 0.861328f, 0.879395f, 0.894531f, 0.907227f, 0.916992f, + 0.926270f, 0.934082f, 0.940918f, 0.946289f, 0.951172f, 0.956055f, 0.959473f, 0.962891f, 0.966797f, 0.969238f, 0.971191f, 0.973633f, + 0.976074f, 0.977539f, 0.979492f, 0.980957f, 0.982422f, 0.983398f, 0.984863f, 0.986328f, 0.986816f, 0.988281f, 0.989746f, 0.989746f, + 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.994629f, 0.995605f, 0.996094f, 0.997070f, 0.998535f, 0.999023f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.001900f, 0.007225f, 0.013733f, 0.022552f, 0.033661f, 0.049164f, 0.070374f, 0.097534f, + 0.135132f, 0.183350f, 0.244507f, 0.317871f, 0.400146f, 0.483643f, 0.562988f, 0.633301f, 0.693848f, 0.743652f, 0.784180f, 0.816895f, + 0.842773f, 0.865234f, 0.882812f, 0.896973f, 0.908691f, 0.919434f, 0.927734f, 0.935547f, 0.942383f, 0.947266f, 0.952637f, 0.957031f, + 0.960938f, 0.964355f, 0.967285f, 0.969727f, 0.971680f, 0.974609f, 0.976074f, 0.978027f, 0.979980f, 0.981445f, 0.982910f, 0.984375f, + 0.985840f, 0.986328f, 0.988281f, 0.988770f, 0.989746f, 0.990723f, 0.991699f, 0.992188f, 0.993164f, 0.993652f, 0.994629f, 0.995117f, + 0.995605f, 0.996094f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.001921f, 0.005543f, 0.010223f, 0.016312f, + 0.024918f, 0.035217f, 0.049164f, 0.067017f, 0.091125f, 0.122986f, 0.164673f, 0.217896f, 0.282471f, 0.356934f, 0.436768f, 0.516602f, + 0.590820f, 0.656250f, 0.711426f, 0.757812f, 0.794922f, 0.825684f, 0.850098f, 0.870605f, 0.885742f, 0.900879f, 0.912109f, 0.921387f, + 0.929688f, 0.937500f, 0.943848f, 0.949219f, 0.953125f, 0.958496f, 0.961426f, 0.964844f, 0.967773f, 0.970703f, 0.973145f, 0.975098f, + 0.977539f, 0.979004f, 0.980957f, 0.982422f, 0.983887f, 0.985352f, 0.986328f, 0.987793f, 0.988770f, 0.989258f, 0.990723f, 0.991211f, + 0.992188f, 0.993164f, 0.993652f, 0.994141f, 0.994629f, 0.995117f, 0.998047f, 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.998047f, + 0.001360f, 0.004257f, 0.007988f, 0.013092f, 0.018753f, 0.026352f, 0.035645f, 0.048096f, 0.064270f, 0.085449f, 0.113770f, 0.149292f, + 0.195190f, 0.251953f, 0.320557f, 0.395020f, 0.474121f, 0.549316f, 0.618652f, 0.678223f, 0.729492f, 0.770996f, 0.805176f, 0.833496f, + 0.855957f, 0.875977f, 0.891113f, 0.904785f, 0.915039f, 0.924316f, 0.933105f, 0.939453f, 0.945312f, 0.950684f, 0.955078f, 0.959473f, + 0.962891f, 0.966309f, 0.969727f, 0.972168f, 0.974121f, 0.976562f, 0.978516f, 0.979980f, 0.981934f, 0.983398f, 0.984375f, 0.986328f, + 0.986816f, 0.988281f, 0.989746f, 0.990234f, 0.991699f, 0.992188f, 0.992676f, 0.994141f, 0.994141f, 0.994629f, 0.998047f, 0.998047f, + 0.998535f, 0.998047f, 0.998047f, 0.998047f, 0.001075f, 0.003492f, 0.006275f, 0.010223f, 0.014473f, 0.019821f, 0.026581f, 0.035492f, + 0.046967f, 0.061829f, 0.080750f, 0.105164f, 0.136475f, 0.177246f, 0.227783f, 0.288818f, 0.358154f, 0.433594f, 0.509277f, 0.581543f, + 0.645508f, 0.701172f, 0.747070f, 0.783691f, 0.817383f, 0.842773f, 0.864258f, 0.881836f, 0.896484f, 0.908691f, 0.918945f, 0.928223f, + 0.935547f, 0.941895f, 0.948730f, 0.952637f, 0.957031f, 0.962402f, 0.964844f, 0.967773f, 0.970703f, 0.973633f, 0.975586f, 0.977539f, + 0.979492f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, + 0.993164f, 0.994141f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.997559f, 0.998047f, 0.000967f, 0.002928f, 0.005283f, 0.007759f, + 0.011612f, 0.015823f, 0.020966f, 0.027802f, 0.035461f, 0.045959f, 0.059235f, 0.075928f, 0.097778f, 0.126099f, 0.162598f, 0.207153f, + 0.261963f, 0.326416f, 0.398193f, 0.471680f, 0.543945f, 0.612305f, 0.671875f, 0.722656f, 0.765137f, 0.799805f, 0.828125f, 0.854004f, + 0.872070f, 0.888184f, 0.902344f, 0.914062f, 0.923340f, 0.931641f, 0.938965f, 0.945312f, 0.950684f, 0.955566f, 0.958984f, 0.962891f, + 0.966309f, 0.969727f, 0.972168f, 0.974609f, 0.977051f, 0.978516f, 0.980469f, 0.982422f, 0.984375f, 0.985352f, 0.987305f, 0.987793f, + 0.988770f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.997559f, 0.997559f, 0.997559f, 0.998047f, 0.997559f, 0.998047f, + 0.000602f, 0.002605f, 0.004345f, 0.006706f, 0.009590f, 0.012650f, 0.016617f, 0.021423f, 0.027893f, 0.035004f, 0.044495f, 0.056610f, + 0.072327f, 0.092285f, 0.116821f, 0.148926f, 0.189697f, 0.238892f, 0.298340f, 0.365723f, 0.437988f, 0.511230f, 0.579590f, 0.642090f, + 0.698242f, 0.744141f, 0.781738f, 0.814453f, 0.840332f, 0.861816f, 0.880371f, 0.895996f, 0.907715f, 0.918945f, 0.928223f, 0.935547f, + 0.942871f, 0.948730f, 0.953125f, 0.958008f, 0.961914f, 0.965332f, 0.968750f, 0.971680f, 0.973633f, 0.976562f, 0.978516f, 0.979980f, + 0.981934f, 0.983398f, 0.985352f, 0.986816f, 0.988281f, 0.988770f, 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.997070f, 0.997559f, + 0.997559f, 0.997070f, 0.997070f, 0.997070f, 0.000607f, 0.001955f, 0.003616f, 0.005772f, 0.007656f, 0.010269f, 0.013496f, 0.017273f, + 0.022018f, 0.027466f, 0.034729f, 0.043488f, 0.054932f, 0.068359f, 0.086365f, 0.108765f, 0.137939f, 0.174316f, 0.219360f, 0.273926f, + 0.336670f, 0.406494f, 0.478516f, 0.549316f, 0.614746f, 0.673340f, 0.722656f, 0.765137f, 0.800293f, 0.828125f, 0.853516f, 0.872070f, + 0.888672f, 0.902832f, 0.914551f, 0.924316f, 0.932129f, 0.940430f, 0.946289f, 0.951660f, 0.956055f, 0.960449f, 0.964355f, 0.967773f, + 0.970703f, 0.972656f, 0.975586f, 0.978027f, 0.980469f, 0.981934f, 0.983398f, 0.985352f, 0.986328f, 0.988281f, 0.988770f, 0.990234f, + 0.990723f, 0.992188f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.000600f, 0.001813f, 0.003101f, 0.004559f, + 0.006580f, 0.008873f, 0.011047f, 0.014091f, 0.017639f, 0.022049f, 0.027557f, 0.033997f, 0.042297f, 0.052704f, 0.065369f, 0.081238f, + 0.101929f, 0.127930f, 0.161255f, 0.202515f, 0.252686f, 0.311523f, 0.378174f, 0.449707f, 0.519531f, 0.587891f, 0.647949f, 0.701660f, + 0.746582f, 0.784668f, 0.817383f, 0.843262f, 0.864746f, 0.882324f, 0.896973f, 0.910156f, 0.920898f, 0.929688f, 0.937012f, 0.943848f, + 0.949707f, 0.955078f, 0.959473f, 0.963379f, 0.966797f, 0.970215f, 0.973145f, 0.975098f, 0.978027f, 0.980469f, 0.982422f, 0.983887f, + 0.984863f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.991211f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.997070f, + 0.000604f, 0.001429f, 0.002676f, 0.003708f, 0.005745f, 0.006973f, 0.009270f, 0.011452f, 0.014503f, 0.018295f, 0.022369f, 0.027222f, + 0.033417f, 0.040833f, 0.050171f, 0.062744f, 0.077454f, 0.095886f, 0.119995f, 0.150391f, 0.187622f, 0.234253f, 0.289307f, 0.353027f, + 0.421631f, 0.492676f, 0.561523f, 0.625488f, 0.681152f, 0.730469f, 0.770996f, 0.806152f, 0.833984f, 0.857422f, 0.876465f, 0.893066f, + 0.906250f, 0.916992f, 0.926758f, 0.935059f, 0.942871f, 0.948242f, 0.954102f, 0.958496f, 0.962891f, 0.966309f, 0.969727f, 0.972168f, + 0.975098f, 0.977539f, 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986328f, 0.987793f, 0.989258f, 0.990234f, 0.996094f, 0.996582f, + 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.000365f, 0.001367f, 0.002123f, 0.003353f, 0.004692f, 0.006054f, 0.007675f, 0.009819f, + 0.012314f, 0.014862f, 0.018066f, 0.022064f, 0.026901f, 0.032471f, 0.039764f, 0.048584f, 0.060089f, 0.073730f, 0.090698f, 0.112854f, + 0.140381f, 0.175415f, 0.218018f, 0.269775f, 0.329834f, 0.396240f, 0.467285f, 0.537598f, 0.603516f, 0.662109f, 0.712891f, 0.757324f, + 0.793945f, 0.823730f, 0.849121f, 0.869629f, 0.887695f, 0.902344f, 0.914062f, 0.924805f, 0.932129f, 0.940430f, 0.947266f, 0.952148f, + 0.957031f, 0.962402f, 0.966309f, 0.969238f, 0.972656f, 0.975586f, 0.977051f, 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986328f, + 0.988281f, 0.988770f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000356f, 0.001341f, 0.001913f, 0.002897f, + 0.003983f, 0.005322f, 0.006607f, 0.008514f, 0.010399f, 0.012451f, 0.015282f, 0.018356f, 0.021912f, 0.026443f, 0.031982f, 0.038635f, + 0.047150f, 0.057495f, 0.070007f, 0.086609f, 0.106689f, 0.131714f, 0.164429f, 0.203613f, 0.252441f, 0.310059f, 0.374512f, 0.444092f, + 0.514160f, 0.582031f, 0.643066f, 0.697266f, 0.743652f, 0.783691f, 0.814941f, 0.842773f, 0.865234f, 0.882812f, 0.897949f, 0.910645f, + 0.922363f, 0.931152f, 0.938965f, 0.945801f, 0.952148f, 0.957520f, 0.961426f, 0.965820f, 0.969727f, 0.972168f, 0.975098f, 0.977539f, + 0.979980f, 0.981934f, 0.983887f, 0.985352f, 0.986816f, 0.988281f, 0.995117f, 0.995605f, 0.996094f, 0.996094f, 0.996094f, 0.996094f, + 0.000243f, 0.000937f, 0.001662f, 0.002617f, 0.003527f, 0.004555f, 0.005642f, 0.007217f, 0.008820f, 0.010483f, 0.012383f, 0.015175f, + 0.018341f, 0.022049f, 0.026245f, 0.031067f, 0.037903f, 0.045563f, 0.054962f, 0.066956f, 0.082092f, 0.101074f, 0.124939f, 0.154663f, + 0.191528f, 0.237305f, 0.291992f, 0.354492f, 0.422852f, 0.492676f, 0.562012f, 0.625488f, 0.682617f, 0.731934f, 0.772949f, 0.807129f, + 0.835449f, 0.859863f, 0.878906f, 0.895020f, 0.908203f, 0.920898f, 0.929199f, 0.937988f, 0.945312f, 0.951660f, 0.957031f, 0.961914f, + 0.965332f, 0.968750f, 0.972656f, 0.975098f, 0.977539f, 0.979980f, 0.982422f, 0.983887f, 0.986328f, 0.987793f, 0.995117f, 0.995605f, + 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.000362f, 0.000970f, 0.001489f, 0.002251f, 0.002892f, 0.003727f, 0.004978f, 0.006264f, + 0.007530f, 0.009125f, 0.010551f, 0.012756f, 0.015259f, 0.018097f, 0.021637f, 0.025986f, 0.030594f, 0.036804f, 0.044006f, 0.053162f, + 0.064148f, 0.078003f, 0.096130f, 0.118042f, 0.146118f, 0.181030f, 0.224487f, 0.276123f, 0.336670f, 0.403320f, 0.473633f, 0.543457f, + 0.609375f, 0.667480f, 0.719238f, 0.763184f, 0.799316f, 0.829590f, 0.854492f, 0.875488f, 0.892578f, 0.906738f, 0.918945f, 0.928711f, + 0.937012f, 0.944336f, 0.951172f, 0.956543f, 0.961426f, 0.965820f, 0.968750f, 0.972656f, 0.975098f, 0.978027f, 0.980469f, 0.982910f, + 0.984375f, 0.985840f, 0.994629f, 0.995117f, 0.995117f, 0.995117f, 0.995117f, 0.995117f, 0.000346f, 0.000923f, 0.001273f, 0.002010f, + 0.002619f, 0.003689f, 0.004452f, 0.005177f, 0.006290f, 0.007561f, 0.009033f, 0.010902f, 0.012970f, 0.015495f, 0.018280f, 0.021576f, + 0.024948f, 0.030304f, 0.035400f, 0.042480f, 0.051086f, 0.061401f, 0.074890f, 0.091187f, 0.112427f, 0.138794f, 0.171631f, 0.212158f, + 0.262451f, 0.320557f, 0.385986f, 0.456055f, 0.525391f, 0.593262f, 0.654297f, 0.708984f, 0.754883f, 0.792969f, 0.824707f, 0.850098f, + 0.872070f, 0.890137f, 0.904785f, 0.917480f, 0.927734f, 0.937012f, 0.944336f, 0.951172f, 0.956055f, 0.961914f, 0.966309f, 0.969727f, + 0.973145f, 0.976074f, 0.978516f, 0.980469f, 0.982910f, 0.984863f, 0.993652f, 0.995117f, 0.994629f, 0.994629f, 0.994629f, 0.994629f, + 0.000242f, 0.000666f, 0.001081f, 0.001806f, 0.002512f, 0.003397f, 0.003866f, 0.004894f, 0.005566f, 0.006859f, 0.007957f, 0.009506f, + 0.011009f, 0.013046f, 0.015266f, 0.018173f, 0.021027f, 0.024811f, 0.029526f, 0.034790f, 0.041443f, 0.049835f, 0.059265f, 0.071899f, + 0.087769f, 0.107422f, 0.132202f, 0.163208f, 0.201782f, 0.249512f, 0.305908f, 0.370361f, 0.440430f, 0.511230f, 0.578613f, 0.642090f, + 0.698730f, 0.746582f, 0.787109f, 0.819824f, 0.848145f, 0.869141f, 0.888672f, 0.903809f, 0.916992f, 0.927246f, 0.936523f, 0.943848f, + 0.951660f, 0.957031f, 0.961426f, 0.965820f, 0.970215f, 0.973145f, 0.976074f, 0.979004f, 0.981445f, 0.983398f, 0.994141f, 0.994141f, + 0.994629f, 0.994141f, 0.994629f, 0.994141f, 0.000242f, 0.000709f, 0.000917f, 0.001194f, 0.002018f, 0.002634f, 0.003504f, 0.003918f, + 0.005020f, 0.005726f, 0.006935f, 0.008141f, 0.009666f, 0.011040f, 0.012848f, 0.014961f, 0.017624f, 0.020660f, 0.024368f, 0.028381f, + 0.033905f, 0.040283f, 0.047760f, 0.057312f, 0.069214f, 0.083984f, 0.102539f, 0.126221f, 0.155640f, 0.193359f, 0.238892f, 0.293701f, + 0.356689f, 0.425537f, 0.497070f, 0.568359f, 0.632812f, 0.690918f, 0.739746f, 0.782227f, 0.816406f, 0.845703f, 0.868652f, 0.887695f, + 0.903320f, 0.916992f, 0.927734f, 0.937012f, 0.944824f, 0.951660f, 0.957031f, 0.962891f, 0.966797f, 0.971191f, 0.973633f, 0.976562f, + 0.979492f, 0.981934f, 0.992676f, 0.993652f, 0.994141f, 0.993652f, 0.993652f, 0.994141f, 0.000244f, 0.000660f, 0.000918f, 0.001343f, + 0.002117f, 0.002407f, 0.002779f, 0.003626f, 0.004246f, 0.005207f, 0.005913f, 0.007145f, 0.008163f, 0.009438f, 0.011101f, 0.012871f, + 0.014999f, 0.017426f, 0.020096f, 0.024185f, 0.027725f, 0.032623f, 0.038910f, 0.046387f, 0.055298f, 0.066467f, 0.080627f, 0.098328f, + 0.120972f, 0.149658f, 0.184814f, 0.229492f, 0.282715f, 0.344727f, 0.414062f, 0.486084f, 0.556641f, 0.624023f, 0.683594f, 0.735352f, + 0.778320f, 0.814453f, 0.843750f, 0.867188f, 0.887207f, 0.903320f, 0.916504f, 0.928223f, 0.937500f, 0.945312f, 0.953125f, 0.958008f, + 0.964355f, 0.967285f, 0.971680f, 0.975098f, 0.978516f, 0.980957f, 0.992676f, 0.993652f, 0.994141f, 0.993652f, 0.993652f, 0.993164f, + 0.000200f, 0.000480f, 0.000808f, 0.001303f, 0.001680f, 0.002104f, 0.002510f, 0.002934f, 0.003468f, 0.004429f, 0.005539f, 0.006046f, + 0.006889f, 0.008438f, 0.009415f, 0.011108f, 0.012787f, 0.014572f, 0.017517f, 0.020279f, 0.023483f, 0.027359f, 0.031860f, 0.037964f, + 0.045227f, 0.053711f, 0.064148f, 0.077759f, 0.095093f, 0.116272f, 0.143311f, 0.177856f, 0.221191f, 0.273193f, 0.334473f, 0.403320f, + 0.476318f, 0.548828f, 0.617188f, 0.677734f, 0.730957f, 0.775879f, 0.812500f, 0.842285f, 0.866699f, 0.887695f, 0.903809f, 0.916992f, + 0.928711f, 0.938477f, 0.946777f, 0.953125f, 0.959473f, 0.963867f, 0.968750f, 0.972656f, 0.976074f, 0.979004f, 0.992188f, 0.992676f, + 0.993164f, 0.993164f, 0.992676f, 0.993164f, 0.000243f, 0.000469f, 0.000878f, 0.001158f, 0.001382f, 0.001801f, 0.002220f, 0.002699f, + 0.003273f, 0.004063f, 0.004715f, 0.005447f, 0.005917f, 0.007099f, 0.008385f, 0.009521f, 0.011032f, 0.012627f, 0.014870f, 0.016922f, + 0.019836f, 0.023010f, 0.026642f, 0.031174f, 0.036926f, 0.043549f, 0.051941f, 0.062561f, 0.075317f, 0.091553f, 0.112427f, 0.138428f, + 0.172485f, 0.213867f, 0.265381f, 0.326172f, 0.394775f, 0.467773f, 0.541504f, 0.610840f, 0.673340f, 0.728516f, 0.774414f, 0.812012f, + 0.842773f, 0.867676f, 0.887695f, 0.904297f, 0.918457f, 0.929688f, 0.939453f, 0.948242f, 0.955078f, 0.959961f, 0.965820f, 0.970215f, + 0.974121f, 0.977051f, 0.991211f, 0.993164f, 0.993164f, 0.992188f, 0.993164f, 0.992188f, 0.000000f, 0.000242f, 0.000799f, 0.000998f, + 0.001273f, 0.001671f, 0.002069f, 0.002485f, 0.003212f, 0.003578f, 0.003948f, 0.004559f, 0.005524f, 0.006321f, 0.007046f, 0.008438f, + 0.009438f, 0.010986f, 0.012390f, 0.014320f, 0.016663f, 0.019165f, 0.022476f, 0.025833f, 0.030487f, 0.035675f, 0.042358f, 0.050018f, + 0.060211f, 0.072693f, 0.088379f, 0.108948f, 0.134766f, 0.166626f, 0.208008f, 0.258545f, 0.318848f, 0.387451f, 0.461670f, 0.536621f, + 0.606934f, 0.671387f, 0.727539f, 0.773438f, 0.811523f, 0.843750f, 0.868164f, 0.889160f, 0.906250f, 0.920410f, 0.932617f, 0.941895f, + 0.949707f, 0.956055f, 0.962402f, 0.967285f, 0.971680f, 0.975586f, 0.990723f, 0.991699f, 0.991699f, 0.992188f, 0.992188f, 0.991699f, + 0.000237f, 0.000482f, 0.000772f, 0.000877f, 0.001109f, 0.001494f, 0.001991f, 0.002041f, 0.002537f, 0.002975f, 0.003469f, 0.004128f, + 0.004841f, 0.005550f, 0.006306f, 0.007359f, 0.008369f, 0.009415f, 0.010788f, 0.012306f, 0.014160f, 0.016571f, 0.018921f, 0.021896f, + 0.025497f, 0.029587f, 0.034576f, 0.041260f, 0.049011f, 0.058319f, 0.070557f, 0.086060f, 0.105774f, 0.130737f, 0.162720f, 0.203247f, + 0.252930f, 0.313477f, 0.382568f, 0.457275f, 0.532715f, 0.605469f, 0.671387f, 0.728027f, 0.774902f, 0.814453f, 0.844727f, 0.870605f, + 0.891113f, 0.909180f, 0.922852f, 0.934082f, 0.943359f, 0.951660f, 0.958008f, 0.964355f, 0.968750f, 0.973145f, 0.990234f, 0.990723f, + 0.991699f, 0.991211f, 0.991211f, 0.991211f, 0.000235f, 0.000461f, 0.000484f, 0.000891f, 0.001105f, 0.001346f, 0.001634f, 0.001936f, + 0.002438f, 0.002874f, 0.003353f, 0.003925f, 0.004189f, 0.004887f, 0.005684f, 0.006279f, 0.007298f, 0.008339f, 0.009384f, 0.010674f, + 0.012360f, 0.013901f, 0.016113f, 0.018677f, 0.021469f, 0.024841f, 0.029144f, 0.033783f, 0.039948f, 0.047272f, 0.056915f, 0.068726f, + 0.083801f, 0.102905f, 0.127563f, 0.159058f, 0.199341f, 0.248901f, 0.309570f, 0.379395f, 0.454834f, 0.532715f, 0.606934f, 0.672852f, + 0.729980f, 0.778320f, 0.817383f, 0.849121f, 0.874512f, 0.895020f, 0.911621f, 0.924805f, 0.937012f, 0.946289f, 0.954102f, 0.960938f, + 0.965820f, 0.971191f, 0.989258f, 0.990234f, 0.990723f, 0.991211f, 0.990723f, 0.990723f, 0.000000f, 0.000360f, 0.000477f, 0.000756f, + 0.000896f, 0.001065f, 0.001570f, 0.001622f, 0.002064f, 0.002525f, 0.002819f, 0.003004f, 0.003700f, 0.004356f, 0.005077f, 0.005428f, + 0.006283f, 0.007370f, 0.008339f, 0.009323f, 0.010567f, 0.012070f, 0.013672f, 0.015839f, 0.018066f, 0.020844f, 0.024002f, 0.028183f, + 0.033051f, 0.039246f, 0.046417f, 0.055450f, 0.067200f, 0.082031f, 0.100586f, 0.125122f, 0.156250f, 0.196167f, 0.245972f, 0.307129f, + 0.378174f, 0.454834f, 0.533203f, 0.608398f, 0.675781f, 0.734375f, 0.782715f, 0.821777f, 0.853516f, 0.878906f, 0.898926f, 0.915039f, + 0.929199f, 0.939941f, 0.948730f, 0.956055f, 0.963379f, 0.968262f, 0.988770f, 0.989746f, 0.990234f, 0.989746f, 0.989746f, 0.990234f, + 0.000000f, 0.000256f, 0.000467f, 0.000590f, 0.000772f, 0.001095f, 0.001356f, 0.001781f, 0.001984f, 0.002161f, 0.002546f, 0.002956f, + 0.003338f, 0.003899f, 0.004440f, 0.004986f, 0.005486f, 0.006310f, 0.006969f, 0.008148f, 0.009148f, 0.010284f, 0.011902f, 0.013573f, + 0.015465f, 0.017853f, 0.020340f, 0.023590f, 0.027298f, 0.032227f, 0.038208f, 0.045563f, 0.054047f, 0.065796f, 0.080322f, 0.098999f, + 0.122864f, 0.153809f, 0.193970f, 0.244629f, 0.306396f, 0.378662f, 0.457031f, 0.536621f, 0.613770f, 0.681641f, 0.740723f, 0.788574f, + 0.827637f, 0.858398f, 0.884277f, 0.903320f, 0.919922f, 0.932129f, 0.942871f, 0.951660f, 0.959961f, 0.965820f, 0.987305f, 0.988281f, + 0.989258f, 0.989258f, 0.989258f, 0.989258f, 0.000244f, 0.000243f, 0.000583f, 0.000585f, 0.000822f, 0.001073f, 0.001159f, 0.001452f, + 0.001525f, 0.002001f, 0.002201f, 0.002714f, 0.002932f, 0.003525f, 0.003904f, 0.004482f, 0.004997f, 0.005581f, 0.006233f, 0.006954f, + 0.007820f, 0.008949f, 0.009941f, 0.011482f, 0.013168f, 0.015099f, 0.017151f, 0.020111f, 0.022949f, 0.026947f, 0.031647f, 0.037354f, + 0.044342f, 0.053375f, 0.064331f, 0.078857f, 0.097351f, 0.121033f, 0.152588f, 0.192749f, 0.244263f, 0.307129f, 0.380615f, 0.461426f, + 0.543457f, 0.621582f, 0.690430f, 0.748047f, 0.796387f, 0.834961f, 0.865723f, 0.889160f, 0.908691f, 0.924316f, 0.937500f, 0.946777f, + 0.955078f, 0.962891f, 0.986328f, 0.987793f, 0.988770f, 0.988770f, 0.988770f, 0.988770f, 0.000000f, 0.000243f, 0.000308f, 0.000541f, + 0.000801f, 0.000827f, 0.001057f, 0.001280f, 0.001460f, 0.001781f, 0.002090f, 0.002481f, 0.002756f, 0.003054f, 0.003321f, 0.003948f, + 0.004303f, 0.004898f, 0.005306f, 0.006405f, 0.006954f, 0.007851f, 0.008537f, 0.009918f, 0.011208f, 0.012825f, 0.014534f, 0.016861f, + 0.019379f, 0.022629f, 0.026276f, 0.030838f, 0.036407f, 0.043488f, 0.051819f, 0.063416f, 0.077209f, 0.095825f, 0.119812f, 0.151489f, + 0.192749f, 0.245361f, 0.309814f, 0.385986f, 0.469238f, 0.552246f, 0.630859f, 0.699707f, 0.757324f, 0.805176f, 0.842773f, 0.873047f, + 0.895508f, 0.914062f, 0.929688f, 0.941406f, 0.952148f, 0.959473f, 0.985840f, 0.986816f, 0.987305f, 0.987305f, 0.987305f, 0.987305f, + 0.000000f, 0.000243f, 0.000242f, 0.000548f, 0.000695f, 0.000803f, 0.001053f, 0.001198f, 0.001363f, 0.001513f, 0.001886f, 0.002069f, + 0.002447f, 0.002676f, 0.003138f, 0.003551f, 0.003868f, 0.004261f, 0.004936f, 0.005337f, 0.005852f, 0.006615f, 0.007519f, 0.008575f, + 0.009705f, 0.010872f, 0.012688f, 0.014397f, 0.016479f, 0.019119f, 0.022064f, 0.025589f, 0.030304f, 0.035828f, 0.042603f, 0.050812f, + 0.062012f, 0.076355f, 0.094971f, 0.119263f, 0.151367f, 0.193726f, 0.247925f, 0.314941f, 0.393311f, 0.478271f, 0.563965f, 0.642578f, + 0.711914f, 0.769043f, 0.815430f, 0.851562f, 0.881348f, 0.902832f, 0.921387f, 0.934570f, 0.945801f, 0.955078f, 0.984375f, 0.986328f, + 0.986328f, 0.986328f, 0.986328f, 0.986328f, 0.000000f, 0.000234f, 0.000239f, 0.000308f, 0.000597f, 0.000690f, 0.000868f, 0.000937f, + 0.001189f, 0.001404f, 0.001696f, 0.001854f, 0.002180f, 0.002249f, 0.002672f, 0.002979f, 0.003494f, 0.003761f, 0.004257f, 0.004745f, + 0.005154f, 0.005821f, 0.006561f, 0.007557f, 0.008575f, 0.009575f, 0.010963f, 0.012238f, 0.014130f, 0.016113f, 0.018539f, 0.021545f, + 0.025162f, 0.029404f, 0.034851f, 0.041626f, 0.050354f, 0.061218f, 0.075562f, 0.094482f, 0.119507f, 0.152344f, 0.196167f, 0.252197f, + 0.322266f, 0.404053f, 0.490967f, 0.577637f, 0.658203f, 0.726074f, 0.782715f, 0.827637f, 0.861816f, 0.889648f, 0.910645f, 0.926758f, + 0.940918f, 0.950684f, 0.983398f, 0.985352f, 0.984863f, 0.985352f, 0.985840f, 0.985352f, 0.000000f, 0.000240f, 0.000237f, 0.000239f, + 0.000436f, 0.000648f, 0.000661f, 0.000892f, 0.001089f, 0.001484f, 0.001446f, 0.001586f, 0.001896f, 0.002176f, 0.002325f, 0.002634f, + 0.003057f, 0.003315f, 0.003561f, 0.004150f, 0.004578f, 0.005180f, 0.005768f, 0.006485f, 0.007286f, 0.008400f, 0.009453f, 0.010429f, + 0.011795f, 0.013680f, 0.015671f, 0.018005f, 0.020981f, 0.024521f, 0.028748f, 0.034119f, 0.040863f, 0.049622f, 0.060303f, 0.074829f, + 0.094116f, 0.119995f, 0.154297f, 0.199341f, 0.258301f, 0.331787f, 0.416504f, 0.507812f, 0.595703f, 0.675781f, 0.743164f, 0.797852f, + 0.840820f, 0.873535f, 0.899414f, 0.919434f, 0.934082f, 0.947266f, 0.982422f, 0.983887f, 0.983887f, 0.984375f, 0.984375f, 0.983887f, + 0.000136f, 0.000115f, 0.000237f, 0.000238f, 0.000358f, 0.000452f, 0.000759f, 0.000961f, 0.001026f, 0.001113f, 0.001433f, 0.001564f, + 0.001659f, 0.001955f, 0.002024f, 0.002384f, 0.002647f, 0.002974f, 0.003267f, 0.003611f, 0.003971f, 0.004498f, 0.005043f, 0.005539f, + 0.006344f, 0.007168f, 0.007942f, 0.009010f, 0.010353f, 0.011711f, 0.013458f, 0.015213f, 0.017548f, 0.020279f, 0.023926f, 0.028061f, + 0.033356f, 0.040283f, 0.048615f, 0.060455f, 0.074890f, 0.094727f, 0.121216f, 0.156860f, 0.204102f, 0.266846f, 0.344238f, 0.433105f, + 0.526855f, 0.616699f, 0.696289f, 0.761230f, 0.813965f, 0.854492f, 0.884766f, 0.909180f, 0.927734f, 0.941895f, 0.980957f, 0.982422f, + 0.982910f, 0.982422f, 0.982422f, 0.982910f, 0.000000f, 0.000103f, 0.000208f, 0.000356f, 0.000355f, 0.000400f, 0.000454f, 0.000861f, + 0.000922f, 0.001202f, 0.001088f, 0.001401f, 0.001493f, 0.001779f, 0.001881f, 0.002180f, 0.002329f, 0.002483f, 0.002846f, 0.003178f, + 0.003542f, 0.003914f, 0.004406f, 0.004871f, 0.005352f, 0.006119f, 0.006927f, 0.007904f, 0.008759f, 0.009972f, 0.011284f, 0.013046f, + 0.014938f, 0.016998f, 0.019943f, 0.023224f, 0.027161f, 0.032776f, 0.039917f, 0.048218f, 0.059937f, 0.075134f, 0.095642f, 0.123169f, + 0.160767f, 0.211670f, 0.278320f, 0.360352f, 0.454102f, 0.550293f, 0.640625f, 0.718262f, 0.781738f, 0.831055f, 0.869141f, 0.897461f, + 0.919434f, 0.936035f, 0.979492f, 0.980957f, 0.980957f, 0.981934f, 0.981445f, 0.981445f, 0.000000f, 0.000192f, 0.000191f, 0.000350f, + 0.000352f, 0.000354f, 0.000599f, 0.000721f, 0.000835f, 0.001044f, 0.000988f, 0.001141f, 0.001255f, 0.001479f, 0.001705f, 0.001815f, + 0.001843f, 0.002151f, 0.002369f, 0.002831f, 0.003067f, 0.003431f, 0.003698f, 0.004295f, 0.004738f, 0.005352f, 0.005859f, 0.006615f, + 0.007587f, 0.008583f, 0.009682f, 0.010735f, 0.012405f, 0.014381f, 0.016708f, 0.018921f, 0.022736f, 0.026947f, 0.032104f, 0.039032f, + 0.048004f, 0.059784f, 0.075500f, 0.096924f, 0.125977f, 0.166626f, 0.221069f, 0.292969f, 0.380371f, 0.479004f, 0.577637f, 0.667969f, + 0.743164f, 0.803711f, 0.849609f, 0.883789f, 0.910645f, 0.930176f, 0.977539f, 0.979492f, 0.979492f, 0.979492f, 0.979980f, 0.979492f, + 0.000000f, 0.000000f, 0.000191f, 0.000214f, 0.000441f, 0.000465f, 0.000351f, 0.000656f, 0.000672f, 0.000957f, 0.000881f, 0.001092f, + 0.001209f, 0.001259f, 0.001315f, 0.001583f, 0.001630f, 0.001834f, 0.002033f, 0.002367f, 0.002596f, 0.002924f, 0.003387f, 0.003693f, + 0.004063f, 0.004601f, 0.004986f, 0.005676f, 0.006557f, 0.006973f, 0.007801f, 0.008781f, 0.010475f, 0.012100f, 0.013817f, 0.015625f, + 0.018784f, 0.021927f, 0.026260f, 0.031677f, 0.038879f, 0.048004f, 0.059845f, 0.076233f, 0.098633f, 0.130005f, 0.173950f, 0.233032f, + 0.311035f, 0.405518f, 0.507812f, 0.608887f, 0.698242f, 0.769531f, 0.826172f, 0.868164f, 0.899414f, 0.922852f, 0.976074f, 0.977539f, + 0.977539f, 0.977051f, 0.978027f, 0.978027f, 0.000000f, 0.000000f, 0.000117f, 0.000211f, 0.000326f, 0.000573f, 0.000574f, 0.000583f, + 0.000584f, 0.000659f, 0.000901f, 0.001014f, 0.001064f, 0.001033f, 0.001163f, 0.001234f, 0.001546f, 0.001585f, 0.001894f, 0.002085f, + 0.002361f, 0.002504f, 0.003023f, 0.003147f, 0.003580f, 0.004032f, 0.004314f, 0.004936f, 0.005215f, 0.006081f, 0.006725f, 0.007927f, + 0.008743f, 0.009918f, 0.011642f, 0.013367f, 0.015404f, 0.018219f, 0.021545f, 0.025787f, 0.031174f, 0.038361f, 0.047577f, 0.060425f, + 0.077881f, 0.102051f, 0.135376f, 0.182861f, 0.249023f, 0.333984f, 0.436035f, 0.542969f, 0.644043f, 0.730469f, 0.798340f, 0.848633f, + 0.886719f, 0.914062f, 0.973633f, 0.974609f, 0.975098f, 0.976074f, 0.975098f, 0.976074f, 0.000000f, 0.000000f, 0.000114f, 0.000112f, + 0.000271f, 0.000510f, 0.000450f, 0.000565f, 0.000572f, 0.000581f, 0.000654f, 0.000825f, 0.000954f, 0.001085f, 0.001050f, 0.001087f, + 0.001282f, 0.001547f, 0.001585f, 0.001825f, 0.002066f, 0.002182f, 0.002384f, 0.002659f, 0.003172f, 0.003357f, 0.003721f, 0.004238f, + 0.004505f, 0.005024f, 0.005878f, 0.006512f, 0.007324f, 0.008293f, 0.009201f, 0.011040f, 0.012993f, 0.015007f, 0.017639f, 0.020920f, + 0.025131f, 0.030899f, 0.038269f, 0.047760f, 0.061188f, 0.079651f, 0.105469f, 0.142944f, 0.195801f, 0.268799f, 0.363525f, 0.472168f, + 0.582520f, 0.683594f, 0.765137f, 0.826660f, 0.872070f, 0.905273f, 0.972168f, 0.973633f, 0.973145f, 0.973633f, 0.973633f, 0.973633f, + 0.000000f, 0.000000f, 0.000000f, 0.000111f, 0.000224f, 0.000412f, 0.000494f, 0.000543f, 0.000561f, 0.000680f, 0.000665f, 0.000675f, + 0.000679f, 0.000797f, 0.000926f, 0.001122f, 0.001132f, 0.001207f, 0.001375f, 0.001606f, 0.001838f, 0.001963f, 0.002163f, 0.002314f, + 0.002480f, 0.002956f, 0.003189f, 0.003489f, 0.003744f, 0.004311f, 0.004749f, 0.005276f, 0.005867f, 0.006962f, 0.008186f, 0.008987f, + 0.010498f, 0.012283f, 0.014374f, 0.017075f, 0.020355f, 0.024719f, 0.030640f, 0.037720f, 0.048309f, 0.062134f, 0.082336f, 0.110840f, + 0.151978f, 0.212891f, 0.294922f, 0.399170f, 0.515137f, 0.628418f, 0.724609f, 0.799805f, 0.854980f, 0.894043f, 0.968750f, 0.970215f, + 0.970703f, 0.971191f, 0.970703f, 0.970703f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000228f, 0.000233f, 0.000436f, 0.000457f, + 0.000621f, 0.000546f, 0.000622f, 0.000633f, 0.000576f, 0.000644f, 0.000717f, 0.000909f, 0.000994f, 0.001127f, 0.001179f, 0.001267f, + 0.001513f, 0.001628f, 0.001742f, 0.001974f, 0.002111f, 0.002403f, 0.002810f, 0.003139f, 0.003231f, 0.003466f, 0.004021f, 0.004459f, + 0.004971f, 0.005581f, 0.006809f, 0.007568f, 0.008759f, 0.010002f, 0.011665f, 0.013847f, 0.016342f, 0.019714f, 0.024368f, 0.030106f, + 0.037811f, 0.048706f, 0.063843f, 0.085327f, 0.118042f, 0.164917f, 0.234131f, 0.328125f, 0.443359f, 0.565430f, 0.677246f, 0.767578f, + 0.833496f, 0.882812f, 0.965820f, 0.967285f, 0.967773f, 0.968262f, 0.967773f, 0.968262f, 0.000000f, 0.000000f, 0.000000f, 0.000214f, + 0.000210f, 0.000296f, 0.000309f, 0.000386f, 0.000462f, 0.000482f, 0.000525f, 0.000572f, 0.000525f, 0.000558f, 0.000689f, 0.000685f, + 0.000841f, 0.000934f, 0.001008f, 0.001182f, 0.001271f, 0.001412f, 0.001757f, 0.001787f, 0.001769f, 0.002110f, 0.002321f, 0.002331f, + 0.002737f, 0.002951f, 0.003189f, 0.003588f, 0.004253f, 0.004627f, 0.005505f, 0.006119f, 0.006969f, 0.008018f, 0.009583f, 0.010971f, + 0.013245f, 0.015915f, 0.019257f, 0.023651f, 0.030014f, 0.038086f, 0.049683f, 0.066406f, 0.091125f, 0.127441f, 0.182617f, 0.262939f, + 0.370605f, 0.497070f, 0.623047f, 0.729004f, 0.810547f, 0.867188f, 0.962891f, 0.963867f, 0.964844f, 0.964844f, 0.964355f, 0.964355f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000200f, 0.000215f, 0.000229f, 0.000319f, 0.000330f, 0.000411f, 0.000491f, 0.000527f, + 0.000547f, 0.000560f, 0.000634f, 0.000648f, 0.000716f, 0.000778f, 0.000855f, 0.000998f, 0.001182f, 0.001111f, 0.001274f, 0.001625f, + 0.001584f, 0.001559f, 0.001864f, 0.002037f, 0.002296f, 0.002438f, 0.002600f, 0.002993f, 0.003290f, 0.003801f, 0.004467f, 0.005085f, + 0.005508f, 0.006519f, 0.007645f, 0.008743f, 0.010757f, 0.012558f, 0.014946f, 0.018661f, 0.023422f, 0.029556f, 0.038574f, 0.050964f, + 0.069702f, 0.097351f, 0.140015f, 0.205566f, 0.301025f, 0.424561f, 0.559082f, 0.683594f, 0.781250f, 0.852051f, 0.958496f, 0.960449f, + 0.960938f, 0.960938f, 0.960938f, 0.960449f, 0.000000f, 0.000000f, 0.000122f, 0.000122f, 0.000122f, 0.000194f, 0.000214f, 0.000251f, + 0.000302f, 0.000365f, 0.000370f, 0.000429f, 0.000495f, 0.000521f, 0.000504f, 0.000547f, 0.000632f, 0.000656f, 0.000695f, 0.000795f, + 0.000922f, 0.001074f, 0.001125f, 0.001192f, 0.001166f, 0.001303f, 0.001555f, 0.001575f, 0.001763f, 0.001970f, 0.002232f, 0.002560f, + 0.002657f, 0.003082f, 0.003559f, 0.003799f, 0.004620f, 0.005241f, 0.006081f, 0.007103f, 0.008385f, 0.009796f, 0.012192f, 0.014702f, + 0.018234f, 0.022934f, 0.029556f, 0.039307f, 0.053009f, 0.073547f, 0.106628f, 0.157715f, 0.237793f, 0.351318f, 0.490479f, 0.629883f, + 0.746094f, 0.832031f, 0.954590f, 0.956055f, 0.956055f, 0.957031f, 0.956543f, 0.956055f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000121f, 0.000146f, 0.000191f, 0.000200f, 0.000255f, 0.000232f, 0.000252f, 0.000359f, 0.000291f, 0.000342f, 0.000406f, 0.000498f, + 0.000520f, 0.000533f, 0.000632f, 0.000605f, 0.000689f, 0.000768f, 0.000908f, 0.001013f, 0.001087f, 0.001030f, 0.001211f, 0.001318f, + 0.001497f, 0.001609f, 0.001753f, 0.001957f, 0.002234f, 0.002352f, 0.002663f, 0.003040f, 0.003635f, 0.004082f, 0.004723f, 0.005516f, + 0.006367f, 0.007675f, 0.009224f, 0.011360f, 0.013695f, 0.017868f, 0.022598f, 0.029724f, 0.040222f, 0.055542f, 0.080078f, 0.119202f, + 0.182617f, 0.281738f, 0.417725f, 0.568848f, 0.705566f, 0.807129f, 0.948730f, 0.951172f, 0.951172f, 0.951172f, 0.951660f, 0.951660f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000203f, 0.000186f, 0.000184f, 0.000321f, + 0.000231f, 0.000337f, 0.000359f, 0.000430f, 0.000455f, 0.000531f, 0.000502f, 0.000517f, 0.000728f, 0.000643f, 0.000673f, 0.000816f, + 0.000930f, 0.000991f, 0.001028f, 0.001161f, 0.001284f, 0.001369f, 0.001474f, 0.001719f, 0.001781f, 0.001883f, 0.002258f, 0.002518f, + 0.002831f, 0.003201f, 0.003744f, 0.004349f, 0.005127f, 0.006130f, 0.007210f, 0.008423f, 0.010696f, 0.013405f, 0.017136f, 0.022522f, + 0.030029f, 0.041321f, 0.059631f, 0.089050f, 0.138062f, 0.218994f, 0.343750f, 0.500488f, 0.657227f, 0.780762f, 0.943848f, 0.945312f, + 0.945312f, 0.945801f, 0.945801f, 0.946289f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000121f, 0.000121f, 0.000120f, + 0.000118f, 0.000137f, 0.000139f, 0.000241f, 0.000202f, 0.000304f, 0.000313f, 0.000332f, 0.000357f, 0.000420f, 0.000435f, 0.000463f, + 0.000645f, 0.000544f, 0.000700f, 0.000717f, 0.000669f, 0.000834f, 0.000865f, 0.000916f, 0.001109f, 0.001193f, 0.001246f, 0.001300f, + 0.001488f, 0.001538f, 0.001806f, 0.001929f, 0.002001f, 0.002462f, 0.002666f, 0.003260f, 0.003904f, 0.004364f, 0.005325f, 0.006306f, + 0.008041f, 0.009720f, 0.012718f, 0.016525f, 0.022217f, 0.030579f, 0.043854f, 0.065247f, 0.101929f, 0.166016f, 0.273193f, 0.428223f, + 0.600586f, 0.748047f, 0.936523f, 0.938477f, 0.938965f, 0.939453f, 0.938965f, 0.938965f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, + 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000114f, 0.000102f, 0.000090f, 0.000096f, 0.000131f, 0.000245f, 0.000276f, 0.000257f, + 0.000307f, 0.000316f, 0.000322f, 0.000373f, 0.000411f, 0.000440f, 0.000433f, 0.000650f, 0.000578f, 0.000704f, 0.000746f, 0.000723f, + 0.000819f, 0.000756f, 0.000758f, 0.000878f, 0.001009f, 0.001270f, 0.001399f, 0.001530f, 0.001798f, 0.001803f, 0.002151f, 0.002317f, + 0.002728f, 0.003222f, 0.003782f, 0.004612f, 0.005951f, 0.006985f, 0.009308f, 0.011955f, 0.016052f, 0.022324f, 0.031525f, 0.047272f, + 0.073853f, 0.122192f, 0.209717f, 0.352783f, 0.537109f, 0.709473f, 0.928223f, 0.930664f, 0.931152f, 0.930664f, 0.931641f, 0.931152f, + 0.000000f, 0.000000f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000120f, 0.000119f, 0.000119f, 0.000111f, 0.000100f, 0.000139f, + 0.000082f, 0.000154f, 0.000121f, 0.000216f, 0.000147f, 0.000271f, 0.000288f, 0.000298f, 0.000386f, 0.000463f, 0.000370f, 0.000485f, + 0.000555f, 0.000530f, 0.000578f, 0.000574f, 0.000612f, 0.000712f, 0.000776f, 0.000716f, 0.000931f, 0.000831f, 0.000967f, 0.001154f, + 0.001176f, 0.001284f, 0.001497f, 0.001884f, 0.002270f, 0.002415f, 0.002947f, 0.003412f, 0.004032f, 0.005066f, 0.006485f, 0.008400f, + 0.011215f, 0.015404f, 0.022079f, 0.033264f, 0.052124f, 0.087646f, 0.155029f, 0.279297f, 0.465820f, 0.664062f, 0.918945f, 0.921387f, + 0.921875f, 0.922363f, 0.922363f, 0.921875f, 0.000000f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000119f, 0.000119f, 0.000119f, + 0.000118f, 0.000118f, 0.000110f, 0.000100f, 0.000091f, 0.000082f, 0.000075f, 0.000095f, 0.000166f, 0.000113f, 0.000163f, 0.000248f, + 0.000258f, 0.000277f, 0.000336f, 0.000301f, 0.000445f, 0.000495f, 0.000473f, 0.000505f, 0.000494f, 0.000470f, 0.000584f, 0.000752f, + 0.000821f, 0.000814f, 0.000845f, 0.000807f, 0.000932f, 0.000996f, 0.001380f, 0.001481f, 0.001507f, 0.001757f, 0.002146f, 0.002443f, + 0.002869f, 0.003546f, 0.004559f, 0.005878f, 0.007561f, 0.010475f, 0.015320f, 0.022675f, 0.036133f, 0.060883f, 0.110352f, 0.211670f, + 0.389160f, 0.610352f, 0.908691f, 0.909180f, 0.910645f, 0.912109f, 0.909668f, 0.910156f, 0.000000f, 0.000121f, 0.000120f, 0.000119f, + 0.000119f, 0.000118f, 0.000118f, 0.000117f, 0.000117f, 0.000117f, 0.000116f, 0.000110f, 0.000100f, 0.000099f, 0.000083f, 0.000077f, + 0.000071f, 0.000081f, 0.000087f, 0.000166f, 0.000177f, 0.000233f, 0.000238f, 0.000273f, 0.000325f, 0.000357f, 0.000292f, 0.000406f, + 0.000418f, 0.000440f, 0.000428f, 0.000568f, 0.000459f, 0.000628f, 0.000678f, 0.000688f, 0.000647f, 0.000830f, 0.000925f, 0.001111f, + 0.001011f, 0.001420f, 0.001504f, 0.001771f, 0.001997f, 0.002495f, 0.003147f, 0.003944f, 0.005077f, 0.006958f, 0.010040f, 0.015053f, + 0.023727f, 0.040680f, 0.075989f, 0.153076f, 0.312012f, 0.547363f, 0.894531f, 0.897461f, 0.897949f, 0.897949f, 0.897949f, 0.898438f, + 0.000000f, 0.000000f, 0.000119f, 0.000118f, 0.000118f, 0.000117f, 0.000116f, 0.000116f, 0.000115f, 0.000115f, 0.000114f, 0.000114f, + 0.000111f, 0.000101f, 0.000093f, 0.000086f, 0.000079f, 0.000095f, 0.000095f, 0.000090f, 0.000117f, 0.000109f, 0.000158f, 0.000199f, + 0.000207f, 0.000223f, 0.000286f, 0.000288f, 0.000267f, 0.000347f, 0.000368f, 0.000450f, 0.000377f, 0.000460f, 0.000504f, 0.000498f, + 0.000494f, 0.000616f, 0.000632f, 0.000699f, 0.000755f, 0.000938f, 0.000978f, 0.001222f, 0.001355f, 0.001673f, 0.002016f, 0.002539f, + 0.003258f, 0.004410f, 0.006332f, 0.009285f, 0.014847f, 0.025864f, 0.049042f, 0.104736f, 0.236572f, 0.477295f, 0.879395f, 0.881348f, + 0.882324f, 0.881836f, 0.882324f, 0.882324f, 0.000000f, 0.000119f, 0.000118f, 0.000116f, 0.000115f, 0.000114f, 0.000114f, 0.000113f, + 0.000112f, 0.000112f, 0.000111f, 0.000111f, 0.000110f, 0.000110f, 0.000103f, 0.000095f, 0.000088f, 0.000081f, 0.000076f, 0.000070f, + 0.000065f, 0.000100f, 0.000104f, 0.000099f, 0.000120f, 0.000145f, 0.000190f, 0.000204f, 0.000213f, 0.000230f, 0.000241f, 0.000279f, + 0.000325f, 0.000322f, 0.000328f, 0.000381f, 0.000351f, 0.000466f, 0.000452f, 0.000516f, 0.000591f, 0.000622f, 0.000733f, 0.000882f, + 0.000895f, 0.001092f, 0.001456f, 0.001765f, 0.002069f, 0.002821f, 0.003851f, 0.005558f, 0.008865f, 0.015579f, 0.029999f, 0.066895f, + 0.167480f, 0.400391f, 0.860352f, 0.862793f, 0.863281f, 0.864258f, 0.863281f, 0.863770f, 0.000119f, 0.000114f, 0.000113f, 0.000113f, + 0.000111f, 0.000110f, 0.000109f, 0.000109f, 0.000108f, 0.000107f, 0.000107f, 0.000107f, 0.000106f, 0.000105f, 0.000106f, 0.000105f, + 0.000098f, 0.000090f, 0.000084f, 0.000078f, 0.000073f, 0.000068f, 0.000063f, 0.000063f, 0.000066f, 0.000053f, 0.000080f, 0.000107f, + 0.000126f, 0.000150f, 0.000188f, 0.000187f, 0.000206f, 0.000205f, 0.000235f, 0.000242f, 0.000277f, 0.000340f, 0.000323f, 0.000308f, + 0.000417f, 0.000411f, 0.000445f, 0.000536f, 0.000622f, 0.000673f, 0.000887f, 0.000985f, 0.001289f, 0.001623f, 0.002337f, 0.003241f, + 0.004929f, 0.008560f, 0.016739f, 0.039307f, 0.109619f, 0.317383f, 0.837402f, 0.840332f, 0.841309f, 0.840820f, 0.840820f, 0.841309f, + 0.000000f, 0.000106f, 0.000099f, 0.000104f, 0.000102f, 0.000101f, 0.000100f, 0.000101f, 0.000101f, 0.000100f, 0.000099f, 0.000100f, + 0.000099f, 0.000099f, 0.000099f, 0.000098f, 0.000098f, 0.000098f, 0.000093f, 0.000086f, 0.000080f, 0.000075f, 0.000070f, 0.000065f, + 0.000061f, 0.000057f, 0.000059f, 0.000054f, 0.000061f, 0.000080f, 0.000087f, 0.000101f, 0.000136f, 0.000147f, 0.000163f, 0.000171f, + 0.000179f, 0.000205f, 0.000223f, 0.000237f, 0.000281f, 0.000272f, 0.000299f, 0.000364f, 0.000373f, 0.000448f, 0.000507f, 0.000643f, + 0.000801f, 0.001000f, 0.001276f, 0.001765f, 0.002712f, 0.004585f, 0.008492f, 0.020462f, 0.063721f, 0.233643f, 0.811035f, 0.813477f, + 0.814453f, 0.813965f, 0.813965f, 0.814453f, 0.000000f, 0.000057f, 0.000085f, 0.000085f, 0.000083f, 0.000085f, 0.000087f, 0.000086f, + 0.000087f, 0.000087f, 0.000086f, 0.000087f, 0.000087f, 0.000086f, 0.000087f, 0.000087f, 0.000088f, 0.000086f, 0.000088f, 0.000087f, + 0.000087f, 0.000081f, 0.000076f, 0.000071f, 0.000067f, 0.000063f, 0.000058f, 0.000055f, 0.000051f, 0.000048f, 0.000046f, 0.000042f, + 0.000051f, 0.000063f, 0.000081f, 0.000101f, 0.000122f, 0.000137f, 0.000147f, 0.000143f, 0.000157f, 0.000183f, 0.000205f, 0.000188f, + 0.000196f, 0.000249f, 0.000310f, 0.000329f, 0.000413f, 0.000534f, 0.000679f, 0.000944f, 0.001365f, 0.002199f, 0.004150f, 0.009369f, + 0.031677f, 0.153564f, 0.779297f, 0.781250f, 0.782227f, 0.782715f, 0.781738f, 0.781250f, 0.000000f, 0.000000f, 0.000000f, 0.000009f, + 0.000030f, 0.000048f, 0.000051f, 0.000054f, 0.000055f, 0.000059f, 0.000060f, 0.000065f, 0.000065f, 0.000066f, 0.000068f, 0.000068f, + 0.000070f, 0.000070f, 0.000071f, 0.000071f, 0.000072f, 0.000073f, 0.000073f, 0.000073f, 0.000071f, 0.000066f, 0.000062f, 0.000058f, + 0.000055f, 0.000051f, 0.000048f, 0.000045f, 0.000042f, 0.000039f, 0.000044f, 0.000036f, 0.000046f, 0.000056f, 0.000067f, 0.000085f, + 0.000099f, 0.000108f, 0.000107f, 0.000113f, 0.000139f, 0.000144f, 0.000165f, 0.000169f, 0.000196f, 0.000266f, 0.000311f, 0.000426f, + 0.000598f, 0.000948f, 0.001744f, 0.003975f, 0.012856f, 0.084351f, 0.739746f, 0.743164f, 0.743652f, 0.743652f, 0.743652f, 0.743164f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f, 0.000012f, 0.000020f, + 0.000028f, 0.000030f, 0.000033f, 0.000034f, 0.000041f, 0.000041f, 0.000045f, 0.000047f, 0.000048f, 0.000049f, 0.000051f, 0.000052f, + 0.000054f, 0.000054f, 0.000056f, 0.000057f, 0.000056f, 0.000052f, 0.000049f, 0.000046f, 0.000043f, 0.000041f, 0.000038f, 0.000035f, + 0.000033f, 0.000031f, 0.000029f, 0.000029f, 0.000036f, 0.000055f, 0.000048f, 0.000067f, 0.000067f, 0.000073f, 0.000075f, 0.000097f, + 0.000085f, 0.000111f, 0.000137f, 0.000191f, 0.000233f, 0.000371f, 0.000609f, 0.001319f, 0.004341f, 0.033844f, 0.696289f, 0.698730f, + 0.699219f, 0.698242f, 0.698730f, 0.698730f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000007f, + 0.000009f, 0.000012f, 0.000015f, 0.000020f, 0.000022f, 0.000023f, 0.000026f, 0.000029f, 0.000030f, 0.000032f, 0.000033f, 0.000035f, + 0.000037f, 0.000037f, 0.000036f, 0.000034f, 0.000032f, 0.000030f, 0.000028f, 0.000026f, 0.000024f, 0.000022f, 0.000021f, 0.000019f, + 0.000024f, 0.000024f, 0.000029f, 0.000037f, 0.000043f, 0.000046f, 0.000059f, 0.000058f, 0.000075f, 0.000095f, 0.000160f, 0.000306f, + 0.001006f, 0.008865f, 0.643066f, 0.647461f, 0.647949f, 0.647461f, 0.647949f, 0.648438f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000003f, 0.000005f, 0.000007f, 0.000010f, 0.000012f, 0.000013f, 0.000015f, 0.000017f, + 0.000019f, 0.000020f, 0.000018f, 0.000017f, 0.000015f, 0.000014f, 0.000013f, 0.000012f, 0.000010f, 0.000012f, 0.000014f, 0.000018f, + 0.000018f, 0.000025f, 0.000028f, 0.000045f, 0.000110f, 0.001030f, 0.586914f, 0.589844f, 0.590820f, 0.591309f, 0.591309f, 0.590820f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000002f, 0.000004f, 0.000005f, 0.000004f, 0.000004f, 0.000003f, 0.000003f, 0.000004f, 0.000009f, 0.527344f, 0.529785f, + 0.529785f, 0.530273f, 0.530762f, 0.530762f, + }, + { + 0.135132f, 0.377441f, 0.544434f, 0.653320f, 0.724609f, 0.773926f, 0.811035f, 0.838867f, 0.860840f, 0.876465f, 0.891113f, 0.902832f, + 0.912109f, 0.920898f, 0.928223f, 0.934082f, 0.938965f, 0.943848f, 0.948242f, 0.952637f, 0.955566f, 0.958984f, 0.961914f, 0.964844f, + 0.966797f, 0.969238f, 0.971191f, 0.973145f, 0.975098f, 0.976562f, 0.978027f, 0.979492f, 0.980469f, 0.982422f, 0.983398f, 0.984863f, + 0.985840f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.989746f, 0.990234f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994141f, + 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999512f, 0.999512f, 0.999512f, + 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.044891f, 0.163330f, 0.306885f, 0.444336f, 0.559570f, 0.645020f, 0.710938f, 0.760742f, + 0.797852f, 0.827148f, 0.850098f, 0.868652f, 0.883789f, 0.895996f, 0.907227f, 0.916016f, 0.923340f, 0.930176f, 0.936523f, 0.941406f, + 0.946777f, 0.950684f, 0.954102f, 0.957031f, 0.960938f, 0.963379f, 0.965820f, 0.968262f, 0.970703f, 0.972168f, 0.974609f, 0.976562f, + 0.977539f, 0.979492f, 0.980469f, 0.981934f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.987793f, 0.988770f, 0.988770f, 0.990234f, + 0.991211f, 0.991699f, 0.992676f, 0.993164f, 0.993164f, 0.994141f, 0.995605f, 0.995605f, 0.996094f, 0.996582f, 0.997070f, 0.997559f, + 0.998047f, 0.998535f, 0.999512f, 0.999512f, 0.999512f, 0.999023f, 0.999023f, 0.999023f, 0.020325f, 0.077820f, 0.158936f, 0.260498f, + 0.372314f, 0.479736f, 0.572754f, 0.648438f, 0.707520f, 0.754883f, 0.791016f, 0.820312f, 0.843750f, 0.862793f, 0.878906f, 0.891602f, + 0.903320f, 0.912598f, 0.920898f, 0.928223f, 0.933594f, 0.939941f, 0.944824f, 0.949219f, 0.952637f, 0.956543f, 0.959961f, 0.962402f, + 0.965332f, 0.967773f, 0.970215f, 0.971680f, 0.974121f, 0.976074f, 0.977539f, 0.979004f, 0.980957f, 0.981445f, 0.983398f, 0.984375f, + 0.985352f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.990234f, 0.991211f, 0.992188f, 0.992676f, 0.993164f, 0.994141f, 0.994629f, + 0.995605f, 0.996094f, 0.996582f, 0.996582f, 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.998535f, + 0.012032f, 0.042908f, 0.088196f, 0.149292f, 0.228027f, 0.319824f, 0.415527f, 0.506348f, 0.586914f, 0.653809f, 0.709473f, 0.752441f, + 0.787598f, 0.817383f, 0.840820f, 0.860352f, 0.876465f, 0.889648f, 0.900879f, 0.910156f, 0.918945f, 0.926270f, 0.933105f, 0.938965f, + 0.944336f, 0.948730f, 0.952637f, 0.956055f, 0.958984f, 0.962402f, 0.965332f, 0.967773f, 0.970215f, 0.972656f, 0.974609f, 0.976562f, + 0.978027f, 0.979492f, 0.980957f, 0.982422f, 0.983887f, 0.984375f, 0.985352f, 0.986816f, 0.987793f, 0.988770f, 0.989746f, 0.990234f, + 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.996094f, 0.996094f, 0.996582f, 0.997559f, 0.998535f, 0.998535f, + 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.007637f, 0.026825f, 0.053436f, 0.090759f, 0.140137f, 0.203125f, 0.279053f, 0.363281f, + 0.449463f, 0.529785f, 0.601562f, 0.663574f, 0.713379f, 0.756348f, 0.789551f, 0.816895f, 0.840332f, 0.858887f, 0.875488f, 0.887695f, + 0.900391f, 0.909668f, 0.918945f, 0.926270f, 0.932617f, 0.938477f, 0.943848f, 0.948242f, 0.952148f, 0.955566f, 0.959473f, 0.962402f, + 0.965332f, 0.967773f, 0.970215f, 0.972168f, 0.974121f, 0.976562f, 0.978516f, 0.979492f, 0.980957f, 0.981934f, 0.984375f, 0.985352f, + 0.985840f, 0.987793f, 0.988281f, 0.989258f, 0.990723f, 0.991211f, 0.991699f, 0.992676f, 0.993652f, 0.994141f, 0.994629f, 0.995605f, + 0.996094f, 0.997070f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.004784f, 0.018082f, 0.035400f, 0.058868f, + 0.089783f, 0.130981f, 0.183716f, 0.248047f, 0.321289f, 0.400391f, 0.478760f, 0.552734f, 0.617188f, 0.673828f, 0.720703f, 0.759766f, + 0.792480f, 0.818359f, 0.840820f, 0.859863f, 0.875000f, 0.888184f, 0.899902f, 0.910645f, 0.918945f, 0.926270f, 0.931641f, 0.938965f, + 0.943848f, 0.948242f, 0.952148f, 0.957031f, 0.959473f, 0.962891f, 0.965332f, 0.968262f, 0.970215f, 0.972656f, 0.975098f, 0.977051f, + 0.978516f, 0.979980f, 0.981445f, 0.982910f, 0.984863f, 0.985352f, 0.986328f, 0.987305f, 0.988770f, 0.989746f, 0.990723f, 0.991699f, + 0.992676f, 0.993164f, 0.994141f, 0.994629f, 0.995605f, 0.996094f, 0.998047f, 0.998535f, 0.998047f, 0.998047f, 0.998047f, 0.998047f, + 0.004044f, 0.012550f, 0.024628f, 0.040466f, 0.060760f, 0.087708f, 0.122742f, 0.167236f, 0.222534f, 0.287109f, 0.358643f, 0.432617f, + 0.506348f, 0.573242f, 0.632812f, 0.685059f, 0.728516f, 0.766602f, 0.797363f, 0.822266f, 0.843750f, 0.861328f, 0.877441f, 0.890625f, + 0.901367f, 0.910645f, 0.919434f, 0.926758f, 0.933105f, 0.940430f, 0.944824f, 0.948730f, 0.953125f, 0.957520f, 0.960449f, 0.963867f, + 0.966309f, 0.969238f, 0.970703f, 0.973633f, 0.976074f, 0.977539f, 0.979004f, 0.980469f, 0.982422f, 0.983398f, 0.984863f, 0.986816f, + 0.986816f, 0.988281f, 0.989746f, 0.990723f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.994629f, 0.995117f, 0.998047f, 0.998047f, + 0.998047f, 0.998047f, 0.998047f, 0.998047f, 0.002975f, 0.009315f, 0.017868f, 0.029129f, 0.043243f, 0.062012f, 0.084961f, 0.115540f, + 0.154419f, 0.201660f, 0.257812f, 0.322754f, 0.391846f, 0.463135f, 0.530762f, 0.594727f, 0.650391f, 0.698730f, 0.739258f, 0.773926f, + 0.803711f, 0.826660f, 0.847656f, 0.865723f, 0.879883f, 0.892090f, 0.903809f, 0.913086f, 0.921387f, 0.928223f, 0.935059f, 0.940918f, + 0.945801f, 0.950684f, 0.954102f, 0.958008f, 0.961426f, 0.964844f, 0.967285f, 0.970215f, 0.972168f, 0.974609f, 0.976074f, 0.978027f, + 0.979980f, 0.981934f, 0.983398f, 0.984375f, 0.985352f, 0.987305f, 0.988281f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, + 0.993652f, 0.994629f, 0.997559f, 0.998047f, 0.998047f, 0.997559f, 0.997559f, 0.997559f, 0.002329f, 0.007256f, 0.013611f, 0.021790f, + 0.032043f, 0.044617f, 0.061554f, 0.082336f, 0.108765f, 0.142578f, 0.184448f, 0.234375f, 0.292725f, 0.357422f, 0.424805f, 0.493164f, + 0.556641f, 0.615723f, 0.666504f, 0.711914f, 0.750977f, 0.782715f, 0.809570f, 0.832520f, 0.853516f, 0.868652f, 0.882812f, 0.895508f, + 0.905762f, 0.916016f, 0.923340f, 0.931152f, 0.936523f, 0.942383f, 0.947266f, 0.951172f, 0.956055f, 0.958984f, 0.962402f, 0.965820f, + 0.968750f, 0.971191f, 0.973633f, 0.975586f, 0.977539f, 0.979980f, 0.980957f, 0.982422f, 0.983887f, 0.985352f, 0.985840f, 0.988281f, + 0.989746f, 0.990234f, 0.991211f, 0.991699f, 0.993164f, 0.993652f, 0.997070f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, + 0.001871f, 0.006084f, 0.010963f, 0.016953f, 0.024277f, 0.033722f, 0.046234f, 0.060669f, 0.079224f, 0.103638f, 0.132812f, 0.169678f, + 0.214478f, 0.267090f, 0.326172f, 0.390137f, 0.456543f, 0.519531f, 0.581543f, 0.636230f, 0.685547f, 0.726562f, 0.762207f, 0.792969f, + 0.818359f, 0.839844f, 0.858398f, 0.874023f, 0.887695f, 0.898926f, 0.909668f, 0.918945f, 0.926270f, 0.933105f, 0.938965f, 0.944336f, + 0.949219f, 0.953613f, 0.958008f, 0.961426f, 0.964844f, 0.967773f, 0.969727f, 0.972168f, 0.974609f, 0.976074f, 0.979004f, 0.979980f, + 0.981934f, 0.983887f, 0.985352f, 0.986328f, 0.987793f, 0.989746f, 0.989746f, 0.990723f, 0.991211f, 0.992676f, 0.996582f, 0.997070f, + 0.997559f, 0.997070f, 0.997070f, 0.997070f, 0.001322f, 0.004795f, 0.008530f, 0.013504f, 0.018921f, 0.026154f, 0.035065f, 0.045807f, + 0.059662f, 0.076416f, 0.098267f, 0.124512f, 0.157715f, 0.197388f, 0.244873f, 0.299805f, 0.359619f, 0.423096f, 0.487549f, 0.549316f, + 0.605957f, 0.657715f, 0.703125f, 0.741211f, 0.774902f, 0.802734f, 0.827148f, 0.847656f, 0.865234f, 0.879883f, 0.893066f, 0.903320f, + 0.913086f, 0.920898f, 0.929199f, 0.935547f, 0.941406f, 0.947266f, 0.951172f, 0.956055f, 0.959473f, 0.962891f, 0.965332f, 0.969238f, + 0.971191f, 0.974121f, 0.976562f, 0.977539f, 0.979980f, 0.981445f, 0.982910f, 0.984863f, 0.986328f, 0.988281f, 0.988281f, 0.989746f, + 0.990723f, 0.991699f, 0.996582f, 0.996582f, 0.997070f, 0.997070f, 0.997070f, 0.996582f, 0.001077f, 0.003971f, 0.006985f, 0.010750f, + 0.015579f, 0.020920f, 0.027420f, 0.035522f, 0.045776f, 0.058228f, 0.074097f, 0.093140f, 0.117310f, 0.146851f, 0.182495f, 0.225952f, + 0.276611f, 0.332764f, 0.394287f, 0.456543f, 0.518555f, 0.577637f, 0.630371f, 0.679199f, 0.720703f, 0.756836f, 0.787598f, 0.813477f, + 0.836426f, 0.855469f, 0.872070f, 0.885742f, 0.897949f, 0.908203f, 0.917480f, 0.925293f, 0.933105f, 0.939453f, 0.944336f, 0.949219f, + 0.954590f, 0.957520f, 0.961426f, 0.964844f, 0.968262f, 0.970703f, 0.974121f, 0.975586f, 0.978027f, 0.979492f, 0.981445f, 0.983398f, + 0.984863f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.991211f, 0.996094f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, + 0.000954f, 0.003330f, 0.005733f, 0.008904f, 0.012505f, 0.016617f, 0.022446f, 0.028351f, 0.036041f, 0.045807f, 0.056854f, 0.071350f, + 0.088867f, 0.110596f, 0.137451f, 0.170654f, 0.209717f, 0.256592f, 0.309326f, 0.366943f, 0.427979f, 0.489502f, 0.549316f, 0.604980f, + 0.655762f, 0.700195f, 0.738770f, 0.772461f, 0.801270f, 0.825195f, 0.845703f, 0.864258f, 0.879395f, 0.893066f, 0.903809f, 0.914062f, + 0.922363f, 0.929688f, 0.936523f, 0.942871f, 0.947266f, 0.952148f, 0.956055f, 0.960449f, 0.963867f, 0.966797f, 0.969727f, 0.972656f, + 0.975586f, 0.976562f, 0.979004f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988770f, 0.989746f, 0.995605f, 0.996094f, + 0.996094f, 0.996094f, 0.996094f, 0.996094f, 0.000949f, 0.002804f, 0.004730f, 0.007236f, 0.010384f, 0.014160f, 0.018478f, 0.023102f, + 0.028992f, 0.036346f, 0.044647f, 0.055542f, 0.068481f, 0.085144f, 0.105286f, 0.130005f, 0.159668f, 0.195557f, 0.238647f, 0.287842f, + 0.343018f, 0.402588f, 0.463135f, 0.522949f, 0.580566f, 0.632812f, 0.680664f, 0.721680f, 0.757812f, 0.788574f, 0.814453f, 0.836914f, + 0.856934f, 0.872070f, 0.887207f, 0.899414f, 0.909668f, 0.918945f, 0.926758f, 0.933594f, 0.940430f, 0.946289f, 0.950684f, 0.954590f, + 0.959473f, 0.963379f, 0.966797f, 0.969238f, 0.972168f, 0.975098f, 0.977051f, 0.979492f, 0.980957f, 0.982910f, 0.984375f, 0.986328f, + 0.987793f, 0.988770f, 0.995117f, 0.996094f, 0.995605f, 0.996094f, 0.996094f, 0.995605f, 0.000828f, 0.002361f, 0.004116f, 0.006119f, + 0.008797f, 0.011391f, 0.014854f, 0.018890f, 0.023666f, 0.029083f, 0.036011f, 0.044434f, 0.053986f, 0.066589f, 0.081543f, 0.100159f, + 0.122314f, 0.149536f, 0.183350f, 0.222900f, 0.269043f, 0.321533f, 0.378418f, 0.438477f, 0.499023f, 0.556641f, 0.611328f, 0.661133f, + 0.703613f, 0.742188f, 0.775391f, 0.804199f, 0.828613f, 0.849121f, 0.866211f, 0.881348f, 0.894043f, 0.905762f, 0.916016f, 0.924316f, + 0.931641f, 0.938477f, 0.944336f, 0.949707f, 0.954590f, 0.958496f, 0.962402f, 0.966309f, 0.969238f, 0.972168f, 0.974121f, 0.977051f, + 0.979004f, 0.980957f, 0.982910f, 0.984863f, 0.985840f, 0.987793f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, + 0.000606f, 0.001948f, 0.003483f, 0.005394f, 0.007290f, 0.009735f, 0.012352f, 0.015747f, 0.019485f, 0.023788f, 0.029358f, 0.035706f, + 0.043732f, 0.053162f, 0.064331f, 0.077942f, 0.094971f, 0.116089f, 0.140991f, 0.172485f, 0.209473f, 0.252686f, 0.302002f, 0.356934f, + 0.415283f, 0.475830f, 0.534180f, 0.589844f, 0.641602f, 0.687500f, 0.728516f, 0.763184f, 0.792969f, 0.819336f, 0.841309f, 0.860840f, + 0.876953f, 0.890625f, 0.902344f, 0.913086f, 0.921875f, 0.930176f, 0.937012f, 0.943359f, 0.948242f, 0.954102f, 0.958008f, 0.961914f, + 0.965820f, 0.969238f, 0.971680f, 0.974609f, 0.977051f, 0.979004f, 0.981445f, 0.983398f, 0.984863f, 0.986816f, 0.994141f, 0.994629f, + 0.995117f, 0.995117f, 0.995117f, 0.994629f, 0.000672f, 0.001569f, 0.002895f, 0.004528f, 0.006180f, 0.008324f, 0.010864f, 0.013161f, + 0.016357f, 0.020096f, 0.024216f, 0.029327f, 0.035583f, 0.042664f, 0.051453f, 0.062073f, 0.075012f, 0.091125f, 0.110291f, 0.134155f, + 0.162476f, 0.197266f, 0.238037f, 0.285156f, 0.337646f, 0.395020f, 0.454590f, 0.513672f, 0.570312f, 0.624023f, 0.672363f, 0.714844f, + 0.750977f, 0.783691f, 0.811035f, 0.834473f, 0.854004f, 0.872070f, 0.886230f, 0.899414f, 0.911133f, 0.918945f, 0.928223f, 0.936035f, + 0.942871f, 0.948242f, 0.953613f, 0.957031f, 0.961426f, 0.965820f, 0.968750f, 0.972168f, 0.974121f, 0.976562f, 0.979492f, 0.981445f, + 0.983398f, 0.985352f, 0.994141f, 0.994629f, 0.995117f, 0.995117f, 0.995117f, 0.994629f, 0.000413f, 0.001430f, 0.002577f, 0.004269f, + 0.005703f, 0.007137f, 0.008888f, 0.011124f, 0.013885f, 0.016891f, 0.020355f, 0.024384f, 0.029221f, 0.035217f, 0.041748f, 0.049988f, + 0.060059f, 0.072083f, 0.086914f, 0.105286f, 0.126953f, 0.154175f, 0.186523f, 0.224731f, 0.269287f, 0.320557f, 0.375732f, 0.434570f, + 0.493896f, 0.552246f, 0.606934f, 0.655762f, 0.701660f, 0.740723f, 0.774902f, 0.803711f, 0.827637f, 0.848633f, 0.867188f, 0.882812f, + 0.895996f, 0.908203f, 0.917969f, 0.926758f, 0.934570f, 0.941895f, 0.947266f, 0.952637f, 0.957520f, 0.960938f, 0.965820f, 0.968750f, + 0.971680f, 0.974609f, 0.977051f, 0.979980f, 0.981934f, 0.983887f, 0.993652f, 0.994629f, 0.994141f, 0.994141f, 0.994141f, 0.994141f, + 0.000240f, 0.001406f, 0.002373f, 0.003283f, 0.004620f, 0.006264f, 0.007744f, 0.009552f, 0.011711f, 0.014069f, 0.017273f, 0.020584f, + 0.024429f, 0.028946f, 0.034393f, 0.041046f, 0.048798f, 0.058289f, 0.070312f, 0.083618f, 0.100403f, 0.121338f, 0.146118f, 0.177002f, + 0.213257f, 0.255371f, 0.304443f, 0.358887f, 0.416504f, 0.476562f, 0.534668f, 0.590332f, 0.642090f, 0.688965f, 0.729492f, 0.766113f, + 0.796387f, 0.822754f, 0.844727f, 0.862305f, 0.880371f, 0.894043f, 0.905762f, 0.916992f, 0.926270f, 0.934082f, 0.940918f, 0.946777f, + 0.953125f, 0.956543f, 0.961426f, 0.964844f, 0.969238f, 0.972656f, 0.974609f, 0.977539f, 0.979980f, 0.982422f, 0.992676f, 0.994141f, + 0.993652f, 0.993652f, 0.993652f, 0.993652f, 0.000242f, 0.001257f, 0.001991f, 0.003138f, 0.004299f, 0.005302f, 0.006584f, 0.008308f, + 0.010048f, 0.012283f, 0.014526f, 0.017578f, 0.020340f, 0.023972f, 0.028671f, 0.033661f, 0.040161f, 0.047821f, 0.056213f, 0.067261f, + 0.080444f, 0.096191f, 0.115784f, 0.139771f, 0.168457f, 0.203125f, 0.243286f, 0.290527f, 0.343506f, 0.400879f, 0.459473f, 0.519043f, + 0.576172f, 0.629395f, 0.678223f, 0.721191f, 0.757324f, 0.789062f, 0.816895f, 0.839844f, 0.859863f, 0.877930f, 0.892578f, 0.904297f, + 0.915527f, 0.925293f, 0.933105f, 0.940430f, 0.946777f, 0.952148f, 0.957031f, 0.961914f, 0.965820f, 0.969238f, 0.973145f, 0.975586f, + 0.978516f, 0.980469f, 0.992188f, 0.993652f, 0.993164f, 0.993164f, 0.993652f, 0.993164f, 0.000434f, 0.001172f, 0.001865f, 0.002825f, + 0.003633f, 0.004757f, 0.005722f, 0.007175f, 0.009010f, 0.010651f, 0.012520f, 0.014412f, 0.017532f, 0.020599f, 0.024139f, 0.028488f, + 0.033356f, 0.039001f, 0.046295f, 0.054749f, 0.064758f, 0.077209f, 0.092834f, 0.111084f, 0.134033f, 0.160767f, 0.193604f, 0.233032f, + 0.278320f, 0.329590f, 0.386230f, 0.445068f, 0.504395f, 0.563477f, 0.617188f, 0.666504f, 0.711426f, 0.750000f, 0.783691f, 0.812500f, + 0.836426f, 0.857422f, 0.875488f, 0.891113f, 0.903809f, 0.915039f, 0.924805f, 0.933105f, 0.940430f, 0.947266f, 0.953125f, 0.958496f, + 0.962402f, 0.966309f, 0.969727f, 0.973145f, 0.976562f, 0.978516f, 0.991699f, 0.992188f, 0.992676f, 0.993164f, 0.993164f, 0.992676f, + 0.000358f, 0.000835f, 0.001738f, 0.002270f, 0.002996f, 0.004078f, 0.005157f, 0.006416f, 0.007904f, 0.009331f, 0.010826f, 0.012245f, + 0.014938f, 0.017303f, 0.020233f, 0.023926f, 0.027954f, 0.032715f, 0.038147f, 0.045166f, 0.053070f, 0.062561f, 0.074768f, 0.089661f, + 0.106689f, 0.128052f, 0.154175f, 0.185547f, 0.223022f, 0.266846f, 0.317383f, 0.373047f, 0.431152f, 0.491943f, 0.550293f, 0.606445f, + 0.658203f, 0.704102f, 0.744141f, 0.779297f, 0.809082f, 0.833984f, 0.855957f, 0.875000f, 0.889648f, 0.903320f, 0.915039f, 0.924805f, + 0.933594f, 0.940918f, 0.947754f, 0.954102f, 0.958984f, 0.962402f, 0.966797f, 0.970703f, 0.974121f, 0.977539f, 0.990723f, 0.992188f, + 0.992676f, 0.992676f, 0.992188f, 0.992676f, 0.000428f, 0.000789f, 0.001460f, 0.002172f, 0.002695f, 0.003561f, 0.004608f, 0.005848f, + 0.006886f, 0.007736f, 0.009560f, 0.011078f, 0.012817f, 0.015015f, 0.017563f, 0.020157f, 0.023666f, 0.027145f, 0.031891f, 0.037384f, + 0.044189f, 0.051788f, 0.061188f, 0.072327f, 0.085999f, 0.102966f, 0.123413f, 0.148071f, 0.178101f, 0.214478f, 0.256836f, 0.306396f, + 0.360840f, 0.419678f, 0.479736f, 0.540527f, 0.597656f, 0.649902f, 0.697754f, 0.738770f, 0.775391f, 0.805664f, 0.831543f, 0.854004f, + 0.873535f, 0.889160f, 0.902832f, 0.915039f, 0.925293f, 0.934082f, 0.941895f, 0.948730f, 0.954102f, 0.959961f, 0.963867f, 0.968262f, + 0.971680f, 0.975586f, 0.990723f, 0.991699f, 0.991699f, 0.991699f, 0.991699f, 0.991211f, 0.000237f, 0.000782f, 0.001245f, 0.001923f, + 0.002417f, 0.003225f, 0.004101f, 0.005062f, 0.005920f, 0.007030f, 0.008102f, 0.009743f, 0.011009f, 0.013054f, 0.015190f, 0.017380f, + 0.020126f, 0.023346f, 0.027161f, 0.031464f, 0.036316f, 0.042664f, 0.050110f, 0.058807f, 0.069946f, 0.083191f, 0.099121f, 0.118835f, + 0.142822f, 0.171997f, 0.206665f, 0.248413f, 0.296143f, 0.350586f, 0.408936f, 0.469727f, 0.530762f, 0.589844f, 0.643555f, 0.691895f, + 0.734375f, 0.772461f, 0.803223f, 0.830566f, 0.854492f, 0.873047f, 0.889648f, 0.903809f, 0.916016f, 0.926270f, 0.935059f, 0.943359f, + 0.949219f, 0.955566f, 0.960938f, 0.965332f, 0.969727f, 0.973145f, 0.989746f, 0.990723f, 0.990723f, 0.990723f, 0.991211f, 0.990723f, + 0.000243f, 0.000793f, 0.001210f, 0.001616f, 0.002260f, 0.003069f, 0.003649f, 0.004444f, 0.005322f, 0.006088f, 0.006954f, 0.008278f, + 0.009766f, 0.011139f, 0.012970f, 0.014908f, 0.016968f, 0.019897f, 0.023193f, 0.026962f, 0.030792f, 0.035522f, 0.041931f, 0.048920f, + 0.057404f, 0.067993f, 0.080383f, 0.095825f, 0.114929f, 0.137695f, 0.165771f, 0.199585f, 0.241089f, 0.287842f, 0.341553f, 0.400391f, + 0.462402f, 0.523438f, 0.583008f, 0.638184f, 0.687988f, 0.732422f, 0.770020f, 0.802246f, 0.830566f, 0.854004f, 0.873047f, 0.891113f, + 0.904785f, 0.916992f, 0.926758f, 0.936523f, 0.943848f, 0.951172f, 0.956543f, 0.961914f, 0.966797f, 0.971191f, 0.989258f, 0.990234f, + 0.990234f, 0.990234f, 0.990234f, 0.989746f, 0.000000f, 0.000484f, 0.000973f, 0.001453f, 0.001999f, 0.002689f, 0.003359f, 0.003864f, + 0.004726f, 0.005444f, 0.006516f, 0.007404f, 0.008461f, 0.009720f, 0.011261f, 0.012985f, 0.014908f, 0.017120f, 0.019699f, 0.022614f, + 0.026093f, 0.030228f, 0.034668f, 0.040619f, 0.047699f, 0.055756f, 0.066284f, 0.078308f, 0.092834f, 0.111328f, 0.133423f, 0.160889f, + 0.194214f, 0.233765f, 0.281006f, 0.334473f, 0.392822f, 0.455078f, 0.517090f, 0.578125f, 0.634766f, 0.686035f, 0.730957f, 0.768555f, + 0.803223f, 0.831055f, 0.854492f, 0.875488f, 0.892090f, 0.906250f, 0.918457f, 0.929688f, 0.937988f, 0.945801f, 0.952148f, 0.958496f, + 0.963867f, 0.968750f, 0.988281f, 0.989258f, 0.989746f, 0.989258f, 0.989746f, 0.989258f, 0.000241f, 0.000699f, 0.000835f, 0.001354f, + 0.002066f, 0.002405f, 0.003073f, 0.003466f, 0.003847f, 0.004868f, 0.005798f, 0.006325f, 0.007446f, 0.008553f, 0.009789f, 0.011375f, + 0.013031f, 0.014702f, 0.016937f, 0.019455f, 0.022171f, 0.025467f, 0.029541f, 0.034271f, 0.039734f, 0.046295f, 0.054291f, 0.063904f, + 0.075745f, 0.089966f, 0.107727f, 0.129395f, 0.156250f, 0.188965f, 0.228394f, 0.274658f, 0.327637f, 0.386963f, 0.449219f, 0.512695f, + 0.574707f, 0.632324f, 0.684570f, 0.730469f, 0.770508f, 0.804688f, 0.832520f, 0.857422f, 0.876953f, 0.893066f, 0.908691f, 0.920410f, + 0.931152f, 0.940430f, 0.947754f, 0.954590f, 0.960938f, 0.965820f, 0.986816f, 0.988770f, 0.988770f, 0.988770f, 0.988770f, 0.988770f, + 0.000122f, 0.000480f, 0.000793f, 0.001184f, 0.001847f, 0.002220f, 0.002459f, 0.003109f, 0.003740f, 0.004234f, 0.005127f, 0.005730f, + 0.006557f, 0.007458f, 0.008469f, 0.009911f, 0.011162f, 0.012848f, 0.014519f, 0.016693f, 0.019135f, 0.021820f, 0.025024f, 0.028931f, + 0.033508f, 0.038757f, 0.045135f, 0.052856f, 0.062042f, 0.073547f, 0.087646f, 0.104736f, 0.126099f, 0.152588f, 0.184570f, 0.223511f, + 0.269775f, 0.323242f, 0.382324f, 0.445801f, 0.510254f, 0.573242f, 0.631348f, 0.685059f, 0.731934f, 0.772461f, 0.806641f, 0.834961f, + 0.859375f, 0.879883f, 0.897461f, 0.911133f, 0.923828f, 0.933594f, 0.942383f, 0.950195f, 0.956055f, 0.962402f, 0.985840f, 0.987305f, + 0.987793f, 0.987793f, 0.988281f, 0.987793f, 0.000244f, 0.000471f, 0.000666f, 0.001267f, 0.001592f, 0.001838f, 0.002251f, 0.002855f, + 0.003225f, 0.003828f, 0.004372f, 0.005112f, 0.005695f, 0.006340f, 0.007534f, 0.008797f, 0.009895f, 0.011215f, 0.012604f, 0.014503f, + 0.016602f, 0.018738f, 0.021408f, 0.024567f, 0.028305f, 0.032654f, 0.037872f, 0.043732f, 0.051239f, 0.060669f, 0.071716f, 0.085510f, + 0.102356f, 0.123230f, 0.149170f, 0.180664f, 0.219849f, 0.265869f, 0.319092f, 0.379150f, 0.443604f, 0.508789f, 0.572754f, 0.633301f, + 0.686523f, 0.734863f, 0.775391f, 0.809570f, 0.838379f, 0.862305f, 0.883301f, 0.900391f, 0.914551f, 0.926270f, 0.937012f, 0.944824f, + 0.953125f, 0.959473f, 0.985352f, 0.986816f, 0.986816f, 0.986816f, 0.986816f, 0.986816f, 0.000242f, 0.000346f, 0.000827f, 0.001065f, + 0.001428f, 0.001572f, 0.001984f, 0.002367f, 0.002851f, 0.003277f, 0.003786f, 0.004501f, 0.005253f, 0.005955f, 0.006573f, 0.007736f, + 0.008659f, 0.009880f, 0.011177f, 0.012459f, 0.014153f, 0.016403f, 0.018173f, 0.020859f, 0.024017f, 0.027496f, 0.031708f, 0.036682f, + 0.042877f, 0.050446f, 0.059174f, 0.070068f, 0.083374f, 0.100159f, 0.120728f, 0.145874f, 0.177612f, 0.216187f, 0.262695f, 0.316650f, + 0.377686f, 0.443115f, 0.509766f, 0.575195f, 0.635742f, 0.691406f, 0.738281f, 0.779785f, 0.813965f, 0.843750f, 0.866699f, 0.887207f, + 0.904297f, 0.918945f, 0.930176f, 0.940918f, 0.948730f, 0.956055f, 0.984375f, 0.985840f, 0.985840f, 0.985840f, 0.986328f, 0.985840f, + 0.000242f, 0.000540f, 0.000708f, 0.000830f, 0.001143f, 0.001451f, 0.001861f, 0.002249f, 0.002661f, 0.003010f, 0.003435f, 0.003922f, + 0.004707f, 0.005165f, 0.005787f, 0.006840f, 0.007374f, 0.008545f, 0.009651f, 0.011147f, 0.012581f, 0.014084f, 0.015991f, 0.017899f, + 0.020325f, 0.023392f, 0.026978f, 0.031113f, 0.035919f, 0.042023f, 0.049103f, 0.057831f, 0.068420f, 0.081543f, 0.098145f, 0.118530f, + 0.143921f, 0.175293f, 0.213989f, 0.260742f, 0.316162f, 0.377441f, 0.444336f, 0.512207f, 0.579590f, 0.641113f, 0.696289f, 0.744629f, + 0.786621f, 0.820801f, 0.849609f, 0.872559f, 0.892578f, 0.908691f, 0.922363f, 0.934570f, 0.944336f, 0.951660f, 0.982910f, 0.984375f, + 0.984863f, 0.984863f, 0.985352f, 0.984863f, 0.000106f, 0.000477f, 0.000649f, 0.000901f, 0.001110f, 0.001206f, 0.001630f, 0.002121f, + 0.002192f, 0.002743f, 0.003128f, 0.003538f, 0.003941f, 0.004688f, 0.005276f, 0.005905f, 0.006546f, 0.007568f, 0.008461f, 0.009483f, + 0.010674f, 0.011864f, 0.013649f, 0.015549f, 0.017731f, 0.020111f, 0.023010f, 0.026199f, 0.030304f, 0.035278f, 0.040833f, 0.047821f, + 0.056580f, 0.066895f, 0.079895f, 0.096191f, 0.116760f, 0.141968f, 0.173584f, 0.212646f, 0.260498f, 0.316162f, 0.379883f, 0.447754f, + 0.517578f, 0.584961f, 0.647949f, 0.704102f, 0.752930f, 0.792969f, 0.827148f, 0.855957f, 0.877930f, 0.898438f, 0.914062f, 0.928223f, + 0.938965f, 0.948242f, 0.981445f, 0.983398f, 0.983887f, 0.983887f, 0.983887f, 0.983398f, 0.000208f, 0.000456f, 0.000582f, 0.000788f, + 0.001016f, 0.001428f, 0.001507f, 0.001769f, 0.002203f, 0.002525f, 0.002718f, 0.003187f, 0.003761f, 0.004238f, 0.004635f, 0.005348f, + 0.005901f, 0.006805f, 0.007500f, 0.008545f, 0.009270f, 0.010437f, 0.011742f, 0.013344f, 0.015198f, 0.017242f, 0.019516f, 0.022430f, + 0.025665f, 0.029922f, 0.034180f, 0.040161f, 0.046936f, 0.055420f, 0.065735f, 0.078552f, 0.094666f, 0.114563f, 0.140503f, 0.172485f, + 0.212646f, 0.260986f, 0.318359f, 0.383545f, 0.453125f, 0.524414f, 0.593750f, 0.656738f, 0.712891f, 0.761230f, 0.801270f, 0.835938f, + 0.862305f, 0.885742f, 0.904785f, 0.919922f, 0.933594f, 0.943359f, 0.980469f, 0.982422f, 0.982422f, 0.981934f, 0.982422f, 0.982422f, + 0.000170f, 0.000350f, 0.000583f, 0.000682f, 0.000845f, 0.001036f, 0.001265f, 0.001821f, 0.001953f, 0.002163f, 0.002525f, 0.002771f, + 0.003418f, 0.003729f, 0.004040f, 0.004871f, 0.005188f, 0.005726f, 0.006512f, 0.007130f, 0.008087f, 0.009018f, 0.010216f, 0.011490f, + 0.013084f, 0.014565f, 0.016891f, 0.019073f, 0.021851f, 0.025253f, 0.029022f, 0.033539f, 0.039124f, 0.045563f, 0.054230f, 0.064270f, + 0.077271f, 0.093323f, 0.113403f, 0.139648f, 0.172485f, 0.213379f, 0.262939f, 0.322266f, 0.389404f, 0.461426f, 0.534180f, 0.604492f, + 0.668457f, 0.724609f, 0.772461f, 0.812500f, 0.845703f, 0.872070f, 0.894043f, 0.911621f, 0.926758f, 0.938477f, 0.979004f, 0.980469f, + 0.980957f, 0.980957f, 0.980957f, 0.980957f, 0.000000f, 0.000332f, 0.000583f, 0.000583f, 0.000848f, 0.000959f, 0.001125f, 0.001425f, + 0.001810f, 0.001899f, 0.002300f, 0.002529f, 0.002996f, 0.003162f, 0.003607f, 0.004150f, 0.004761f, 0.005146f, 0.005791f, 0.006329f, + 0.007099f, 0.008110f, 0.008949f, 0.009941f, 0.011253f, 0.012756f, 0.014565f, 0.016434f, 0.018707f, 0.021271f, 0.024475f, 0.028290f, + 0.032745f, 0.037964f, 0.044769f, 0.052795f, 0.063416f, 0.076050f, 0.092102f, 0.113464f, 0.139526f, 0.172974f, 0.214600f, 0.266602f, + 0.327637f, 0.397461f, 0.471191f, 0.546387f, 0.617188f, 0.682129f, 0.737793f, 0.784668f, 0.823730f, 0.854980f, 0.881348f, 0.902344f, + 0.918945f, 0.933105f, 0.977539f, 0.979492f, 0.979492f, 0.979492f, 0.979492f, 0.979492f, 0.000000f, 0.000243f, 0.000553f, 0.000575f, + 0.000591f, 0.000798f, 0.000991f, 0.001234f, 0.001419f, 0.001812f, 0.001935f, 0.002186f, 0.002518f, 0.002975f, 0.003202f, 0.003614f, + 0.004047f, 0.004425f, 0.005013f, 0.005718f, 0.006172f, 0.007046f, 0.007740f, 0.008835f, 0.009819f, 0.011192f, 0.012444f, 0.014114f, + 0.015884f, 0.018204f, 0.020844f, 0.023392f, 0.027420f, 0.031921f, 0.037170f, 0.043610f, 0.052032f, 0.062408f, 0.075256f, 0.091675f, + 0.112610f, 0.140015f, 0.173950f, 0.217651f, 0.271973f, 0.335693f, 0.407715f, 0.484619f, 0.561035f, 0.633789f, 0.698242f, 0.752930f, + 0.798828f, 0.836426f, 0.867676f, 0.891602f, 0.911621f, 0.926270f, 0.975098f, 0.977539f, 0.978516f, 0.977539f, 0.977539f, 0.978027f, + 0.000121f, 0.000121f, 0.000241f, 0.000385f, 0.000684f, 0.000693f, 0.000932f, 0.001156f, 0.001410f, 0.001648f, 0.001893f, 0.002184f, + 0.002367f, 0.002579f, 0.002872f, 0.003319f, 0.003653f, 0.003922f, 0.004425f, 0.004925f, 0.005436f, 0.006180f, 0.006836f, 0.007645f, + 0.008278f, 0.009476f, 0.010788f, 0.012169f, 0.013695f, 0.015305f, 0.017319f, 0.020111f, 0.022858f, 0.026718f, 0.030975f, 0.036255f, + 0.042938f, 0.051270f, 0.061493f, 0.074768f, 0.091187f, 0.112976f, 0.140747f, 0.176392f, 0.222168f, 0.278809f, 0.345703f, 0.421387f, + 0.500488f, 0.578613f, 0.651855f, 0.715820f, 0.769531f, 0.813965f, 0.850586f, 0.878418f, 0.901855f, 0.920410f, 0.973633f, 0.975586f, + 0.976074f, 0.976562f, 0.976562f, 0.975098f, 0.000240f, 0.000120f, 0.000281f, 0.000333f, 0.000498f, 0.000680f, 0.000684f, 0.001083f, + 0.001312f, 0.001618f, 0.001606f, 0.001834f, 0.002087f, 0.002316f, 0.002735f, 0.002792f, 0.003084f, 0.003386f, 0.003944f, 0.004353f, + 0.004761f, 0.005390f, 0.005997f, 0.006615f, 0.007389f, 0.008324f, 0.008987f, 0.010284f, 0.011703f, 0.013382f, 0.014717f, 0.016953f, + 0.019424f, 0.022278f, 0.026047f, 0.030029f, 0.035492f, 0.042145f, 0.050446f, 0.060608f, 0.073975f, 0.091187f, 0.113831f, 0.142700f, + 0.180176f, 0.228271f, 0.288086f, 0.359131f, 0.437988f, 0.519531f, 0.600098f, 0.673340f, 0.735352f, 0.787598f, 0.830566f, 0.865234f, + 0.891602f, 0.913086f, 0.971680f, 0.974121f, 0.974121f, 0.974121f, 0.974121f, 0.974609f, 0.000000f, 0.000239f, 0.000236f, 0.000425f, + 0.000487f, 0.000608f, 0.000850f, 0.001012f, 0.001140f, 0.001260f, 0.001410f, 0.001640f, 0.001953f, 0.002003f, 0.002342f, 0.002434f, + 0.002686f, 0.002934f, 0.003305f, 0.003771f, 0.004169f, 0.004692f, 0.005028f, 0.005817f, 0.006371f, 0.007179f, 0.007919f, 0.008965f, + 0.009857f, 0.011261f, 0.012703f, 0.014229f, 0.016312f, 0.018494f, 0.021744f, 0.025024f, 0.029633f, 0.034790f, 0.041199f, 0.049561f, + 0.060242f, 0.073608f, 0.091675f, 0.114502f, 0.144897f, 0.185547f, 0.236328f, 0.300049f, 0.375732f, 0.458496f, 0.542969f, 0.624023f, + 0.696289f, 0.758301f, 0.808105f, 0.847656f, 0.879395f, 0.903809f, 0.968750f, 0.971191f, 0.972168f, 0.971680f, 0.972168f, 0.971680f, + 0.000000f, 0.000217f, 0.000235f, 0.000235f, 0.000321f, 0.000560f, 0.000588f, 0.000897f, 0.001034f, 0.001040f, 0.001246f, 0.001369f, + 0.001611f, 0.001692f, 0.001942f, 0.002153f, 0.002337f, 0.002638f, 0.002878f, 0.003330f, 0.003672f, 0.003986f, 0.004498f, 0.004826f, + 0.005535f, 0.006176f, 0.006561f, 0.007538f, 0.008362f, 0.009544f, 0.010612f, 0.011879f, 0.013794f, 0.015839f, 0.018326f, 0.020889f, + 0.024567f, 0.028625f, 0.033783f, 0.040527f, 0.049133f, 0.059998f, 0.073608f, 0.092041f, 0.116394f, 0.148682f, 0.191528f, 0.246582f, + 0.315186f, 0.395508f, 0.482910f, 0.570312f, 0.651367f, 0.722168f, 0.781738f, 0.828613f, 0.866211f, 0.895508f, 0.966797f, 0.968750f, + 0.969238f, 0.969727f, 0.969238f, 0.969238f, 0.000000f, 0.000108f, 0.000215f, 0.000346f, 0.000352f, 0.000501f, 0.000783f, 0.000828f, + 0.000954f, 0.000980f, 0.001130f, 0.001353f, 0.001429f, 0.001522f, 0.001690f, 0.001760f, 0.002172f, 0.002363f, 0.002522f, 0.002777f, + 0.003202f, 0.003550f, 0.004040f, 0.004364f, 0.004734f, 0.005192f, 0.005909f, 0.006271f, 0.007015f, 0.007957f, 0.008774f, 0.010185f, + 0.011681f, 0.013306f, 0.015327f, 0.017517f, 0.020264f, 0.023636f, 0.027740f, 0.033234f, 0.039856f, 0.048340f, 0.059387f, 0.074097f, + 0.093567f, 0.118896f, 0.153931f, 0.200073f, 0.260254f, 0.334473f, 0.420410f, 0.511719f, 0.601562f, 0.682129f, 0.750488f, 0.807617f, + 0.851074f, 0.884277f, 0.963867f, 0.966309f, 0.966797f, 0.966797f, 0.966797f, 0.966797f, 0.000000f, 0.000059f, 0.000292f, 0.000331f, + 0.000344f, 0.000613f, 0.000532f, 0.000703f, 0.000853f, 0.000915f, 0.000936f, 0.001102f, 0.001284f, 0.001430f, 0.001417f, 0.001475f, + 0.001791f, 0.001989f, 0.002161f, 0.002388f, 0.002775f, 0.003017f, 0.003357f, 0.003763f, 0.004124f, 0.004383f, 0.004917f, 0.005436f, + 0.005840f, 0.006733f, 0.007511f, 0.008667f, 0.009567f, 0.011032f, 0.012474f, 0.014610f, 0.016739f, 0.019379f, 0.022873f, 0.027252f, + 0.032410f, 0.039062f, 0.048065f, 0.059296f, 0.074646f, 0.094971f, 0.123108f, 0.161011f, 0.211426f, 0.277344f, 0.358154f, 0.450195f, + 0.545410f, 0.636230f, 0.715332f, 0.781250f, 0.832520f, 0.872070f, 0.960449f, 0.962402f, 0.963867f, 0.963379f, 0.962891f, 0.963379f, + 0.000000f, 0.000000f, 0.000098f, 0.000301f, 0.000315f, 0.000566f, 0.000587f, 0.000627f, 0.000643f, 0.000795f, 0.000974f, 0.001023f, + 0.000987f, 0.001031f, 0.001245f, 0.001470f, 0.001637f, 0.001820f, 0.001884f, 0.002146f, 0.002357f, 0.002630f, 0.002913f, 0.003164f, + 0.003380f, 0.003824f, 0.004189f, 0.004353f, 0.004940f, 0.005688f, 0.006409f, 0.007347f, 0.008018f, 0.009163f, 0.010559f, 0.012039f, + 0.013695f, 0.016144f, 0.018723f, 0.022354f, 0.026337f, 0.031433f, 0.038818f, 0.047546f, 0.059662f, 0.075623f, 0.097473f, 0.127808f, + 0.169556f, 0.225830f, 0.299072f, 0.387451f, 0.486084f, 0.583984f, 0.674805f, 0.751465f, 0.812012f, 0.859375f, 0.957031f, 0.958984f, + 0.959473f, 0.959961f, 0.959961f, 0.959961f, 0.000000f, 0.000000f, 0.000004f, 0.000078f, 0.000408f, 0.000432f, 0.000563f, 0.000560f, + 0.000566f, 0.000623f, 0.000782f, 0.000829f, 0.000896f, 0.000956f, 0.001056f, 0.001249f, 0.001414f, 0.001473f, 0.001646f, 0.001764f, + 0.002066f, 0.002230f, 0.002436f, 0.002651f, 0.003012f, 0.003252f, 0.003414f, 0.004055f, 0.004143f, 0.004784f, 0.005356f, 0.006077f, + 0.006870f, 0.007538f, 0.008728f, 0.009834f, 0.011322f, 0.013130f, 0.015427f, 0.017914f, 0.021271f, 0.025436f, 0.030960f, 0.038086f, + 0.047485f, 0.060303f, 0.077087f, 0.101196f, 0.134521f, 0.180786f, 0.244507f, 0.326172f, 0.423584f, 0.527832f, 0.628418f, 0.716797f, + 0.788086f, 0.843262f, 0.953125f, 0.955566f, 0.955566f, 0.956543f, 0.956055f, 0.956543f, 0.000000f, 0.000000f, 0.000000f, 0.000236f, + 0.000320f, 0.000484f, 0.000521f, 0.000549f, 0.000556f, 0.000584f, 0.000574f, 0.000690f, 0.000758f, 0.000841f, 0.001003f, 0.001013f, + 0.001169f, 0.001292f, 0.001437f, 0.001658f, 0.001830f, 0.002001f, 0.002081f, 0.002146f, 0.002434f, 0.002712f, 0.002964f, 0.003220f, + 0.003513f, 0.003963f, 0.004410f, 0.004875f, 0.005608f, 0.006245f, 0.007179f, 0.008118f, 0.009201f, 0.010582f, 0.012360f, 0.014343f, + 0.016968f, 0.020401f, 0.024628f, 0.030365f, 0.037567f, 0.047455f, 0.060913f, 0.079529f, 0.105774f, 0.143555f, 0.196167f, 0.268799f, + 0.361084f, 0.467041f, 0.576172f, 0.676758f, 0.760254f, 0.825195f, 0.948242f, 0.951660f, 0.951660f, 0.951660f, 0.951660f, 0.951660f, + 0.000000f, 0.000000f, 0.000000f, 0.000122f, 0.000257f, 0.000334f, 0.000390f, 0.000496f, 0.000520f, 0.000539f, 0.000590f, 0.000602f, + 0.000646f, 0.000725f, 0.000909f, 0.000949f, 0.001023f, 0.001121f, 0.001181f, 0.001308f, 0.001474f, 0.001457f, 0.001714f, 0.002007f, + 0.001929f, 0.002039f, 0.002468f, 0.002672f, 0.003025f, 0.003317f, 0.003635f, 0.004047f, 0.004433f, 0.004864f, 0.005756f, 0.006493f, + 0.007515f, 0.008331f, 0.009697f, 0.011383f, 0.014000f, 0.016235f, 0.019653f, 0.024185f, 0.029465f, 0.037109f, 0.047699f, 0.062164f, + 0.082642f, 0.112488f, 0.155151f, 0.216919f, 0.300049f, 0.404541f, 0.520020f, 0.631836f, 0.728516f, 0.805664f, 0.943848f, 0.946289f, + 0.946777f, 0.946777f, 0.947266f, 0.947266f, 0.000000f, 0.000000f, 0.000122f, 0.000088f, 0.000219f, 0.000229f, 0.000355f, 0.000414f, + 0.000482f, 0.000545f, 0.000559f, 0.000568f, 0.000481f, 0.000668f, 0.000636f, 0.000728f, 0.000924f, 0.000980f, 0.001017f, 0.001109f, + 0.001258f, 0.001353f, 0.001451f, 0.001564f, 0.001621f, 0.001740f, 0.002066f, 0.002289f, 0.002459f, 0.002621f, 0.002975f, 0.003349f, + 0.003588f, 0.003998f, 0.004723f, 0.005116f, 0.006035f, 0.006859f, 0.007957f, 0.009064f, 0.010658f, 0.012711f, 0.015511f, 0.018555f, + 0.023026f, 0.028854f, 0.037140f, 0.048035f, 0.064026f, 0.086914f, 0.121033f, 0.171387f, 0.244141f, 0.341797f, 0.458740f, 0.580078f, + 0.691895f, 0.780762f, 0.937988f, 0.940430f, 0.941406f, 0.940918f, 0.941895f, 0.941406f, 0.000000f, 0.000000f, 0.000000f, 0.000080f, + 0.000211f, 0.000221f, 0.000225f, 0.000192f, 0.000352f, 0.000368f, 0.000397f, 0.000529f, 0.000510f, 0.000504f, 0.000540f, 0.000671f, + 0.000694f, 0.000763f, 0.000902f, 0.000998f, 0.001063f, 0.001074f, 0.001128f, 0.001407f, 0.001370f, 0.001449f, 0.001682f, 0.001635f, + 0.001976f, 0.002108f, 0.002335f, 0.002558f, 0.002905f, 0.003176f, 0.003637f, 0.003948f, 0.004650f, 0.005341f, 0.006237f, 0.007034f, + 0.008415f, 0.009811f, 0.012032f, 0.014565f, 0.017731f, 0.022324f, 0.028427f, 0.036713f, 0.048859f, 0.066406f, 0.092957f, 0.133057f, + 0.193848f, 0.281250f, 0.395508f, 0.524902f, 0.648926f, 0.754395f, 0.931152f, 0.934570f, 0.934570f, 0.934570f, 0.935547f, 0.935059f, + 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000181f, 0.000196f, 0.000236f, 0.000250f, 0.000226f, 0.000281f, 0.000335f, 0.000457f, + 0.000406f, 0.000511f, 0.000522f, 0.000593f, 0.000539f, 0.000663f, 0.000661f, 0.000779f, 0.000978f, 0.000855f, 0.000937f, 0.001128f, + 0.001163f, 0.001253f, 0.001241f, 0.001531f, 0.001595f, 0.001796f, 0.001888f, 0.002226f, 0.002350f, 0.002609f, 0.002787f, 0.003260f, + 0.003656f, 0.004303f, 0.004910f, 0.005577f, 0.006683f, 0.007603f, 0.009102f, 0.011017f, 0.013603f, 0.016968f, 0.021652f, 0.027939f, + 0.037109f, 0.050262f, 0.070374f, 0.101624f, 0.150391f, 0.225220f, 0.331543f, 0.463867f, 0.601074f, 0.723145f, 0.923828f, 0.927246f, + 0.927246f, 0.928223f, 0.927734f, 0.928223f, 0.000000f, 0.000000f, 0.000122f, 0.000121f, 0.000121f, 0.000174f, 0.000156f, 0.000204f, + 0.000180f, 0.000221f, 0.000246f, 0.000346f, 0.000313f, 0.000426f, 0.000468f, 0.000482f, 0.000559f, 0.000582f, 0.000536f, 0.000611f, + 0.000770f, 0.000666f, 0.000919f, 0.000947f, 0.001013f, 0.000948f, 0.001129f, 0.001169f, 0.001463f, 0.001579f, 0.001540f, 0.001555f, + 0.001888f, 0.002007f, 0.002390f, 0.002623f, 0.002708f, 0.003235f, 0.003584f, 0.004223f, 0.005001f, 0.005791f, 0.006905f, 0.008118f, + 0.010117f, 0.012512f, 0.015961f, 0.020798f, 0.027374f, 0.037628f, 0.052673f, 0.076172f, 0.114197f, 0.175659f, 0.270752f, 0.399658f, + 0.546875f, 0.687012f, 0.915527f, 0.918457f, 0.919434f, 0.919434f, 0.919434f, 0.919434f, 0.000000f, 0.000000f, 0.000121f, 0.000121f, + 0.000121f, 0.000120f, 0.000139f, 0.000141f, 0.000152f, 0.000186f, 0.000209f, 0.000222f, 0.000297f, 0.000330f, 0.000367f, 0.000403f, + 0.000433f, 0.000456f, 0.000457f, 0.000484f, 0.000521f, 0.000544f, 0.000594f, 0.000807f, 0.000790f, 0.000841f, 0.000784f, 0.001025f, + 0.001112f, 0.001014f, 0.001146f, 0.001287f, 0.001485f, 0.001541f, 0.001740f, 0.002014f, 0.002264f, 0.002460f, 0.002825f, 0.003124f, + 0.003683f, 0.004177f, 0.005024f, 0.006004f, 0.007454f, 0.009041f, 0.011833f, 0.014839f, 0.019791f, 0.027283f, 0.038361f, 0.055817f, + 0.084656f, 0.133057f, 0.213013f, 0.334717f, 0.488770f, 0.645996f, 0.905762f, 0.909668f, 0.909668f, 0.909180f, 0.910645f, 0.908691f, + 0.000000f, 0.000000f, 0.000121f, 0.000121f, 0.000120f, 0.000120f, 0.000119f, 0.000115f, 0.000104f, 0.000105f, 0.000203f, 0.000235f, + 0.000185f, 0.000290f, 0.000201f, 0.000306f, 0.000259f, 0.000370f, 0.000401f, 0.000428f, 0.000596f, 0.000617f, 0.000474f, 0.000593f, + 0.000641f, 0.000676f, 0.000682f, 0.000826f, 0.000897f, 0.000934f, 0.000972f, 0.000972f, 0.001213f, 0.001281f, 0.001410f, 0.001451f, + 0.001562f, 0.001786f, 0.002031f, 0.002417f, 0.002764f, 0.003162f, 0.003763f, 0.004406f, 0.005310f, 0.006454f, 0.008156f, 0.010849f, + 0.014305f, 0.019318f, 0.027328f, 0.039856f, 0.061310f, 0.097717f, 0.162354f, 0.270752f, 0.424805f, 0.599609f, 0.894043f, 0.897949f, + 0.898438f, 0.898438f, 0.898926f, 0.898438f, 0.000000f, 0.000121f, 0.000121f, 0.000120f, 0.000119f, 0.000119f, 0.000118f, 0.000118f, + 0.000112f, 0.000102f, 0.000094f, 0.000109f, 0.000131f, 0.000145f, 0.000232f, 0.000171f, 0.000278f, 0.000230f, 0.000347f, 0.000331f, + 0.000379f, 0.000381f, 0.000512f, 0.000427f, 0.000541f, 0.000566f, 0.000547f, 0.000613f, 0.000706f, 0.000660f, 0.000809f, 0.000941f, + 0.000950f, 0.001035f, 0.001069f, 0.001220f, 0.001149f, 0.001314f, 0.001603f, 0.001801f, 0.002062f, 0.002394f, 0.002737f, 0.003057f, + 0.003771f, 0.004471f, 0.005875f, 0.007217f, 0.009651f, 0.013344f, 0.018829f, 0.027710f, 0.043091f, 0.069214f, 0.119141f, 0.210571f, + 0.358398f, 0.544922f, 0.881348f, 0.883789f, 0.885254f, 0.885742f, 0.885254f, 0.885254f, 0.000000f, 0.000121f, 0.000120f, 0.000119f, + 0.000119f, 0.000118f, 0.000117f, 0.000116f, 0.000116f, 0.000110f, 0.000101f, 0.000094f, 0.000087f, 0.000157f, 0.000151f, 0.000168f, + 0.000146f, 0.000219f, 0.000214f, 0.000261f, 0.000313f, 0.000363f, 0.000311f, 0.000415f, 0.000476f, 0.000448f, 0.000429f, 0.000460f, + 0.000481f, 0.000560f, 0.000544f, 0.000695f, 0.000626f, 0.000789f, 0.000877f, 0.000894f, 0.000948f, 0.001177f, 0.001175f, 0.001366f, + 0.001487f, 0.001738f, 0.002008f, 0.002304f, 0.002663f, 0.003250f, 0.004002f, 0.004932f, 0.006416f, 0.008636f, 0.012344f, 0.018127f, + 0.028610f, 0.047150f, 0.083923f, 0.156860f, 0.291260f, 0.487305f, 0.866211f, 0.869141f, 0.870605f, 0.870117f, 0.871094f, 0.870117f, + 0.000000f, 0.000000f, 0.000119f, 0.000118f, 0.000117f, 0.000116f, 0.000115f, 0.000115f, 0.000114f, 0.000114f, 0.000109f, 0.000101f, + 0.000094f, 0.000087f, 0.000081f, 0.000085f, 0.000129f, 0.000150f, 0.000176f, 0.000193f, 0.000216f, 0.000257f, 0.000241f, 0.000302f, + 0.000259f, 0.000299f, 0.000397f, 0.000403f, 0.000384f, 0.000402f, 0.000425f, 0.000582f, 0.000467f, 0.000614f, 0.000660f, 0.000625f, + 0.000650f, 0.000819f, 0.000790f, 0.000879f, 0.001001f, 0.001140f, 0.001403f, 0.001555f, 0.001844f, 0.002213f, 0.002636f, 0.003235f, + 0.004082f, 0.005604f, 0.007896f, 0.011292f, 0.018005f, 0.030472f, 0.055786f, 0.109985f, 0.224976f, 0.421875f, 0.848145f, 0.852539f, + 0.853027f, 0.852539f, 0.852539f, 0.853027f, 0.000000f, 0.000119f, 0.000118f, 0.000116f, 0.000115f, 0.000114f, 0.000113f, 0.000112f, + 0.000111f, 0.000111f, 0.000110f, 0.000108f, 0.000101f, 0.000094f, 0.000088f, 0.000082f, 0.000077f, 0.000109f, 0.000068f, 0.000102f, + 0.000127f, 0.000158f, 0.000177f, 0.000192f, 0.000207f, 0.000214f, 0.000249f, 0.000278f, 0.000296f, 0.000320f, 0.000330f, 0.000342f, + 0.000415f, 0.000371f, 0.000389f, 0.000508f, 0.000463f, 0.000586f, 0.000606f, 0.000649f, 0.000724f, 0.000841f, 0.000910f, 0.001065f, + 0.001236f, 0.001475f, 0.001807f, 0.002138f, 0.002716f, 0.003622f, 0.004921f, 0.006950f, 0.010574f, 0.018433f, 0.034607f, 0.072449f, + 0.163818f, 0.352295f, 0.827637f, 0.831055f, 0.831543f, 0.832031f, 0.833008f, 0.832520f, 0.000120f, 0.000116f, 0.000114f, 0.000113f, + 0.000111f, 0.000110f, 0.000109f, 0.000108f, 0.000107f, 0.000106f, 0.000106f, 0.000105f, 0.000104f, 0.000101f, 0.000094f, 0.000088f, + 0.000083f, 0.000078f, 0.000073f, 0.000092f, 0.000064f, 0.000097f, 0.000073f, 0.000105f, 0.000125f, 0.000162f, 0.000179f, 0.000177f, + 0.000191f, 0.000221f, 0.000241f, 0.000235f, 0.000270f, 0.000277f, 0.000287f, 0.000329f, 0.000319f, 0.000428f, 0.000417f, 0.000409f, + 0.000524f, 0.000537f, 0.000612f, 0.000750f, 0.000770f, 0.000961f, 0.001153f, 0.001347f, 0.001702f, 0.002081f, 0.002903f, 0.003956f, + 0.006184f, 0.010368f, 0.019592f, 0.043427f, 0.109924f, 0.280518f, 0.803223f, 0.806152f, 0.807617f, 0.808594f, 0.809082f, 0.808105f, + 0.000000f, 0.000111f, 0.000106f, 0.000107f, 0.000104f, 0.000103f, 0.000101f, 0.000101f, 0.000101f, 0.000100f, 0.000099f, 0.000098f, + 0.000097f, 0.000097f, 0.000097f, 0.000094f, 0.000088f, 0.000083f, 0.000078f, 0.000073f, 0.000069f, 0.000070f, 0.000061f, 0.000068f, + 0.000059f, 0.000067f, 0.000084f, 0.000097f, 0.000128f, 0.000137f, 0.000165f, 0.000160f, 0.000176f, 0.000185f, 0.000217f, 0.000239f, + 0.000237f, 0.000238f, 0.000272f, 0.000281f, 0.000314f, 0.000372f, 0.000395f, 0.000430f, 0.000504f, 0.000578f, 0.000665f, 0.000856f, + 0.000969f, 0.001210f, 0.001594f, 0.002216f, 0.003370f, 0.005527f, 0.010170f, 0.023239f, 0.066101f, 0.207275f, 0.775391f, 0.779785f, + 0.780273f, 0.780762f, 0.780273f, 0.780762f, 0.000000f, 0.000094f, 0.000097f, 0.000095f, 0.000092f, 0.000091f, 0.000091f, 0.000090f, + 0.000089f, 0.000089f, 0.000088f, 0.000088f, 0.000087f, 0.000086f, 0.000087f, 0.000086f, 0.000086f, 0.000085f, 0.000081f, 0.000076f, + 0.000072f, 0.000068f, 0.000064f, 0.000060f, 0.000057f, 0.000054f, 0.000058f, 0.000048f, 0.000048f, 0.000069f, 0.000068f, 0.000092f, + 0.000110f, 0.000122f, 0.000133f, 0.000136f, 0.000146f, 0.000154f, 0.000175f, 0.000194f, 0.000204f, 0.000206f, 0.000238f, 0.000262f, + 0.000266f, 0.000338f, 0.000361f, 0.000432f, 0.000527f, 0.000659f, 0.000848f, 0.001183f, 0.001713f, 0.002661f, 0.004921f, 0.010887f, + 0.033936f, 0.138428f, 0.743652f, 0.747559f, 0.748047f, 0.748535f, 0.749512f, 0.749023f, 0.000045f, 0.000047f, 0.000059f, 0.000059f, + 0.000063f, 0.000068f, 0.000068f, 0.000068f, 0.000067f, 0.000069f, 0.000068f, 0.000070f, 0.000070f, 0.000070f, 0.000071f, 0.000070f, + 0.000071f, 0.000071f, 0.000071f, 0.000071f, 0.000071f, 0.000069f, 0.000065f, 0.000062f, 0.000058f, 0.000055f, 0.000052f, 0.000049f, + 0.000046f, 0.000044f, 0.000041f, 0.000050f, 0.000051f, 0.000048f, 0.000061f, 0.000070f, 0.000084f, 0.000095f, 0.000107f, 0.000104f, + 0.000111f, 0.000128f, 0.000143f, 0.000154f, 0.000157f, 0.000186f, 0.000198f, 0.000216f, 0.000268f, 0.000315f, 0.000414f, 0.000537f, + 0.000735f, 0.001149f, 0.002075f, 0.004669f, 0.014175f, 0.077881f, 0.707031f, 0.710449f, 0.712402f, 0.711914f, 0.712891f, 0.712402f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f, 0.000013f, 0.000029f, 0.000028f, 0.000037f, 0.000035f, 0.000039f, + 0.000043f, 0.000043f, 0.000045f, 0.000045f, 0.000048f, 0.000048f, 0.000050f, 0.000051f, 0.000052f, 0.000052f, 0.000053f, 0.000054f, + 0.000054f, 0.000053f, 0.000050f, 0.000048f, 0.000045f, 0.000043f, 0.000040f, 0.000038f, 0.000036f, 0.000034f, 0.000032f, 0.000030f, + 0.000028f, 0.000030f, 0.000038f, 0.000043f, 0.000057f, 0.000069f, 0.000072f, 0.000073f, 0.000082f, 0.000095f, 0.000101f, 0.000099f, + 0.000116f, 0.000130f, 0.000184f, 0.000211f, 0.000301f, 0.000443f, 0.000737f, 0.001601f, 0.004978f, 0.032593f, 0.666504f, 0.669922f, + 0.669922f, 0.672363f, 0.670898f, 0.670410f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000010f, 0.000012f, 0.000015f, 0.000018f, 0.000021f, + 0.000022f, 0.000023f, 0.000025f, 0.000028f, 0.000029f, 0.000029f, 0.000031f, 0.000033f, 0.000033f, 0.000035f, 0.000035f, 0.000035f, + 0.000033f, 0.000031f, 0.000029f, 0.000028f, 0.000026f, 0.000024f, 0.000023f, 0.000021f, 0.000020f, 0.000019f, 0.000022f, 0.000022f, + 0.000030f, 0.000038f, 0.000042f, 0.000041f, 0.000052f, 0.000047f, 0.000064f, 0.000072f, 0.000078f, 0.000129f, 0.000201f, 0.000382f, + 0.001180f, 0.009117f, 0.620605f, 0.624512f, 0.625000f, 0.625000f, 0.625000f, 0.625488f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000003f, 0.000005f, 0.000007f, 0.000008f, 0.000010f, 0.000011f, 0.000012f, 0.000014f, 0.000016f, 0.000016f, 0.000018f, 0.000017f, + 0.000016f, 0.000015f, 0.000014f, 0.000013f, 0.000012f, 0.000011f, 0.000010f, 0.000009f, 0.000011f, 0.000014f, 0.000018f, 0.000018f, + 0.000021f, 0.000028f, 0.000035f, 0.000053f, 0.000136f, 0.001152f, 0.571777f, 0.575684f, 0.575684f, 0.576172f, 0.576660f, 0.576660f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, + 0.000002f, 0.000004f, 0.000004f, 0.000004f, 0.000003f, 0.000003f, 0.000002f, 0.000004f, 0.000003f, 0.000011f, 0.520020f, 0.523926f, + 0.524902f, 0.524902f, 0.524902f, 0.524902f, + }, + { + 0.119934f, 0.328857f, 0.480713f, 0.586914f, 0.663086f, 0.717773f, 0.759766f, 0.791504f, 0.818359f, 0.838867f, 0.856934f, 0.871094f, + 0.883301f, 0.894043f, 0.902832f, 0.911621f, 0.917969f, 0.924805f, 0.930664f, 0.936035f, 0.939941f, 0.944824f, 0.948242f, 0.951660f, + 0.954590f, 0.958008f, 0.961426f, 0.962891f, 0.966309f, 0.967285f, 0.970215f, 0.972656f, 0.973633f, 0.975586f, 0.977539f, 0.978516f, + 0.979980f, 0.981445f, 0.982910f, 0.984375f, 0.985352f, 0.986328f, 0.987793f, 0.988770f, 0.989746f, 0.990234f, 0.991699f, 0.992676f, + 0.993164f, 0.993652f, 0.994629f, 0.995117f, 0.996094f, 0.996582f, 0.997559f, 0.998047f, 0.998535f, 0.999023f, 0.999512f, 0.999023f, + 0.999023f, 0.998535f, 0.998535f, 0.998047f, 0.046875f, 0.160400f, 0.286621f, 0.405518f, 0.507812f, 0.590820f, 0.656250f, 0.708008f, + 0.748535f, 0.781250f, 0.809082f, 0.830566f, 0.848633f, 0.864258f, 0.877441f, 0.888672f, 0.898926f, 0.906738f, 0.915039f, 0.921387f, + 0.928223f, 0.933105f, 0.937988f, 0.942871f, 0.946777f, 0.950684f, 0.954102f, 0.957031f, 0.959961f, 0.962402f, 0.965332f, 0.966797f, + 0.969727f, 0.971191f, 0.973145f, 0.975098f, 0.977539f, 0.978027f, 0.980469f, 0.981934f, 0.982910f, 0.984375f, 0.985352f, 0.986816f, + 0.987793f, 0.988770f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993164f, 0.993652f, 0.994629f, 0.995605f, 0.996582f, 0.996582f, + 0.997559f, 0.998047f, 0.999023f, 0.999023f, 0.999023f, 0.998535f, 0.998535f, 0.998047f, 0.023788f, 0.084473f, 0.163696f, 0.255615f, + 0.351807f, 0.445312f, 0.527832f, 0.597656f, 0.656738f, 0.703613f, 0.742676f, 0.775879f, 0.802734f, 0.824707f, 0.843262f, 0.858887f, + 0.873047f, 0.884766f, 0.895508f, 0.903809f, 0.913086f, 0.919434f, 0.925781f, 0.931641f, 0.937012f, 0.941406f, 0.945801f, 0.949707f, + 0.953125f, 0.956543f, 0.959473f, 0.962402f, 0.964844f, 0.967285f, 0.969238f, 0.972168f, 0.973633f, 0.975098f, 0.977539f, 0.979492f, + 0.980469f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.986816f, 0.988281f, 0.988770f, 0.989746f, 0.990723f, 0.992188f, 0.992676f, + 0.993652f, 0.994629f, 0.995605f, 0.996094f, 0.996582f, 0.997559f, 0.998535f, 0.998535f, 0.998535f, 0.998047f, 0.998047f, 0.997559f, + 0.014595f, 0.050110f, 0.097717f, 0.158569f, 0.230347f, 0.311523f, 0.394531f, 0.473145f, 0.544922f, 0.606934f, 0.660645f, 0.705566f, + 0.743164f, 0.775391f, 0.800781f, 0.822266f, 0.841309f, 0.856934f, 0.870605f, 0.883301f, 0.894043f, 0.902832f, 0.911133f, 0.918945f, + 0.925293f, 0.931152f, 0.936035f, 0.941406f, 0.945801f, 0.949707f, 0.953125f, 0.956055f, 0.959473f, 0.962402f, 0.964844f, 0.967285f, + 0.970215f, 0.972168f, 0.974121f, 0.975098f, 0.977539f, 0.979004f, 0.980957f, 0.981934f, 0.983398f, 0.984375f, 0.985840f, 0.987305f, + 0.988281f, 0.989258f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.994629f, 0.995117f, 0.995605f, 0.996582f, 0.998535f, 0.998535f, + 0.998535f, 0.998047f, 0.998047f, 0.997559f, 0.009178f, 0.032379f, 0.062561f, 0.102417f, 0.151611f, 0.210938f, 0.279785f, 0.352783f, + 0.426758f, 0.496826f, 0.561035f, 0.618164f, 0.666992f, 0.708496f, 0.744141f, 0.773926f, 0.800781f, 0.821777f, 0.840820f, 0.856445f, + 0.870117f, 0.882324f, 0.893066f, 0.901855f, 0.910645f, 0.918457f, 0.925293f, 0.930176f, 0.935547f, 0.941406f, 0.946289f, 0.949707f, + 0.953125f, 0.956543f, 0.959961f, 0.962891f, 0.965332f, 0.967773f, 0.969727f, 0.972656f, 0.974121f, 0.976074f, 0.977539f, 0.979492f, + 0.981445f, 0.982422f, 0.984375f, 0.985840f, 0.986328f, 0.987793f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, + 0.994629f, 0.995605f, 0.998047f, 0.998047f, 0.998047f, 0.997559f, 0.997559f, 0.997559f, 0.006382f, 0.022430f, 0.042908f, 0.068970f, + 0.102844f, 0.144653f, 0.195557f, 0.253906f, 0.318848f, 0.386230f, 0.454590f, 0.518066f, 0.577148f, 0.628906f, 0.675293f, 0.714844f, + 0.748535f, 0.777344f, 0.802246f, 0.823730f, 0.841797f, 0.856934f, 0.871094f, 0.882812f, 0.893555f, 0.902832f, 0.911133f, 0.918457f, + 0.925293f, 0.930176f, 0.937012f, 0.940918f, 0.945801f, 0.950195f, 0.953613f, 0.957031f, 0.960449f, 0.963379f, 0.966309f, 0.968262f, + 0.970703f, 0.973145f, 0.974609f, 0.976562f, 0.978516f, 0.980469f, 0.981934f, 0.983398f, 0.984375f, 0.985840f, 0.988281f, 0.988770f, + 0.989746f, 0.990723f, 0.991699f, 0.992676f, 0.993652f, 0.994629f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997559f, 0.997070f, + 0.004585f, 0.015961f, 0.030930f, 0.049133f, 0.072144f, 0.101013f, 0.137451f, 0.181519f, 0.232544f, 0.290039f, 0.352539f, 0.416748f, + 0.479736f, 0.538574f, 0.592773f, 0.641602f, 0.684570f, 0.723145f, 0.754395f, 0.782715f, 0.805176f, 0.825195f, 0.843750f, 0.859863f, + 0.872559f, 0.884766f, 0.895020f, 0.904297f, 0.912109f, 0.919922f, 0.926270f, 0.932129f, 0.937500f, 0.942383f, 0.946289f, 0.950195f, + 0.955078f, 0.958008f, 0.961426f, 0.964355f, 0.967285f, 0.969238f, 0.971680f, 0.974121f, 0.975586f, 0.977539f, 0.979492f, 0.980957f, + 0.982910f, 0.984375f, 0.985840f, 0.986328f, 0.988281f, 0.989746f, 0.990723f, 0.992188f, 0.992676f, 0.993164f, 0.997559f, 0.997559f, + 0.997070f, 0.997070f, 0.997070f, 0.997070f, 0.003483f, 0.012291f, 0.023209f, 0.036041f, 0.052429f, 0.073486f, 0.099182f, 0.131226f, + 0.169678f, 0.214844f, 0.266846f, 0.323242f, 0.383545f, 0.444580f, 0.503418f, 0.559082f, 0.609375f, 0.655762f, 0.695312f, 0.730957f, + 0.760254f, 0.788086f, 0.810059f, 0.829590f, 0.847168f, 0.862793f, 0.875488f, 0.886719f, 0.896973f, 0.906250f, 0.914551f, 0.921387f, + 0.927734f, 0.933594f, 0.938965f, 0.944336f, 0.948242f, 0.952148f, 0.956543f, 0.958984f, 0.961914f, 0.965332f, 0.968262f, 0.970703f, + 0.972656f, 0.974609f, 0.977051f, 0.979004f, 0.980469f, 0.981934f, 0.983887f, 0.985352f, 0.986328f, 0.987793f, 0.989746f, 0.990234f, + 0.991699f, 0.992676f, 0.996582f, 0.997070f, 0.997070f, 0.996582f, 0.996582f, 0.996094f, 0.002962f, 0.009613f, 0.017792f, 0.027481f, + 0.039429f, 0.055176f, 0.073914f, 0.096985f, 0.125610f, 0.159180f, 0.199707f, 0.246216f, 0.297607f, 0.353760f, 0.412842f, 0.470215f, + 0.526367f, 0.578613f, 0.626953f, 0.669434f, 0.707031f, 0.740723f, 0.769043f, 0.794922f, 0.814941f, 0.835449f, 0.851074f, 0.866699f, + 0.879395f, 0.890137f, 0.899902f, 0.909180f, 0.916992f, 0.924316f, 0.929688f, 0.936035f, 0.941406f, 0.945312f, 0.950195f, 0.953613f, + 0.957520f, 0.960938f, 0.963867f, 0.966797f, 0.969238f, 0.971680f, 0.974121f, 0.976562f, 0.979004f, 0.979980f, 0.981934f, 0.982910f, + 0.984375f, 0.986816f, 0.987793f, 0.988770f, 0.990234f, 0.991699f, 0.996582f, 0.996582f, 0.996582f, 0.996582f, 0.996094f, 0.996094f, + 0.002077f, 0.007637f, 0.013802f, 0.021606f, 0.031006f, 0.042419f, 0.055969f, 0.073242f, 0.094055f, 0.119446f, 0.150513f, 0.186401f, + 0.228638f, 0.276123f, 0.328857f, 0.384277f, 0.440674f, 0.496338f, 0.549805f, 0.598633f, 0.644043f, 0.683594f, 0.719727f, 0.750977f, + 0.779297f, 0.802246f, 0.823730f, 0.840820f, 0.855957f, 0.871582f, 0.882324f, 0.893555f, 0.903809f, 0.911621f, 0.920410f, 0.926758f, + 0.932617f, 0.938477f, 0.943359f, 0.947754f, 0.953125f, 0.955566f, 0.959473f, 0.962402f, 0.965332f, 0.968262f, 0.970703f, 0.972656f, + 0.976074f, 0.977051f, 0.979492f, 0.981445f, 0.983398f, 0.984863f, 0.986328f, 0.987793f, 0.989258f, 0.990723f, 0.995605f, 0.996094f, + 0.996094f, 0.996094f, 0.996094f, 0.995605f, 0.002014f, 0.006035f, 0.011299f, 0.017410f, 0.024368f, 0.033020f, 0.043701f, 0.056458f, + 0.072205f, 0.091431f, 0.114807f, 0.141968f, 0.174316f, 0.213257f, 0.256836f, 0.306152f, 0.358887f, 0.413330f, 0.468018f, 0.520996f, + 0.572266f, 0.618652f, 0.661621f, 0.699707f, 0.732910f, 0.762695f, 0.788574f, 0.810547f, 0.830078f, 0.848145f, 0.862305f, 0.875977f, + 0.887695f, 0.898438f, 0.907227f, 0.915527f, 0.922852f, 0.929199f, 0.936035f, 0.940918f, 0.946289f, 0.950684f, 0.953613f, 0.958496f, + 0.960938f, 0.964355f, 0.967285f, 0.970215f, 0.972656f, 0.975586f, 0.977539f, 0.979492f, 0.980957f, 0.982910f, 0.984863f, 0.986328f, + 0.987793f, 0.988770f, 0.995117f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.001496f, 0.005196f, 0.009201f, 0.013985f, + 0.019806f, 0.026413f, 0.034943f, 0.044647f, 0.056641f, 0.070923f, 0.088623f, 0.109680f, 0.135254f, 0.164795f, 0.200073f, 0.240845f, + 0.285645f, 0.335449f, 0.387939f, 0.441650f, 0.495850f, 0.546875f, 0.595215f, 0.639160f, 0.679199f, 0.715820f, 0.746582f, 0.774414f, + 0.798828f, 0.819824f, 0.837402f, 0.854492f, 0.869629f, 0.881348f, 0.893066f, 0.902832f, 0.912109f, 0.918945f, 0.926758f, 0.933105f, + 0.938477f, 0.943359f, 0.948730f, 0.952637f, 0.956055f, 0.960449f, 0.963379f, 0.966797f, 0.969238f, 0.972656f, 0.975098f, 0.977051f, + 0.979004f, 0.981445f, 0.982910f, 0.984375f, 0.986328f, 0.987305f, 0.994629f, 0.995605f, 0.995117f, 0.995117f, 0.995117f, 0.994629f, + 0.001187f, 0.004314f, 0.007740f, 0.011337f, 0.016373f, 0.021759f, 0.028198f, 0.035889f, 0.045197f, 0.056580f, 0.069946f, 0.085938f, + 0.105408f, 0.128784f, 0.155884f, 0.187866f, 0.225830f, 0.268066f, 0.315186f, 0.365479f, 0.418213f, 0.471680f, 0.522949f, 0.572754f, + 0.617676f, 0.659668f, 0.697754f, 0.730957f, 0.760742f, 0.787109f, 0.809570f, 0.830078f, 0.846680f, 0.862793f, 0.875488f, 0.888184f, + 0.898926f, 0.907715f, 0.916016f, 0.923340f, 0.930664f, 0.936523f, 0.941895f, 0.947754f, 0.951660f, 0.955566f, 0.959473f, 0.963867f, + 0.966309f, 0.969238f, 0.972168f, 0.974121f, 0.976562f, 0.979004f, 0.980957f, 0.982910f, 0.984863f, 0.986816f, 0.994141f, 0.994629f, + 0.994629f, 0.994629f, 0.994629f, 0.994141f, 0.001187f, 0.003733f, 0.006496f, 0.009918f, 0.013634f, 0.017899f, 0.023026f, 0.029343f, + 0.036621f, 0.045227f, 0.055786f, 0.068298f, 0.083740f, 0.101135f, 0.122314f, 0.147827f, 0.177612f, 0.212891f, 0.252686f, 0.297119f, + 0.345215f, 0.395996f, 0.448730f, 0.500488f, 0.550781f, 0.597656f, 0.641113f, 0.680664f, 0.716309f, 0.747559f, 0.774414f, 0.799316f, + 0.820312f, 0.838867f, 0.855957f, 0.870117f, 0.883301f, 0.894531f, 0.904785f, 0.913086f, 0.920898f, 0.928223f, 0.935059f, 0.940430f, + 0.945312f, 0.950684f, 0.955566f, 0.958496f, 0.962891f, 0.965820f, 0.968750f, 0.971680f, 0.974609f, 0.976562f, 0.978516f, 0.980957f, + 0.982910f, 0.984863f, 0.994141f, 0.994141f, 0.994629f, 0.994141f, 0.994141f, 0.994629f, 0.000998f, 0.003178f, 0.005444f, 0.008179f, + 0.011337f, 0.015091f, 0.019058f, 0.024368f, 0.029587f, 0.037140f, 0.045197f, 0.055115f, 0.066772f, 0.080688f, 0.097229f, 0.117371f, + 0.140869f, 0.169312f, 0.201538f, 0.238770f, 0.280762f, 0.326660f, 0.376709f, 0.427490f, 0.479248f, 0.530273f, 0.578613f, 0.623535f, + 0.664551f, 0.701660f, 0.733887f, 0.763672f, 0.790039f, 0.812500f, 0.832520f, 0.849121f, 0.865234f, 0.878906f, 0.890625f, 0.901367f, + 0.910645f, 0.919434f, 0.926758f, 0.933105f, 0.939453f, 0.944824f, 0.949707f, 0.954590f, 0.958008f, 0.961914f, 0.965332f, 0.968750f, + 0.971680f, 0.974121f, 0.977051f, 0.979004f, 0.980957f, 0.982910f, 0.993164f, 0.993164f, 0.994141f, 0.993652f, 0.993652f, 0.993164f, + 0.000948f, 0.002638f, 0.004784f, 0.007153f, 0.009590f, 0.012505f, 0.016388f, 0.020599f, 0.025299f, 0.031097f, 0.037323f, 0.045197f, + 0.054047f, 0.065002f, 0.078674f, 0.094055f, 0.112305f, 0.134399f, 0.160889f, 0.191040f, 0.226318f, 0.265869f, 0.310303f, 0.358154f, + 0.409180f, 0.459473f, 0.510254f, 0.559082f, 0.606445f, 0.648926f, 0.687500f, 0.722168f, 0.753418f, 0.781250f, 0.804199f, 0.825684f, + 0.843262f, 0.860840f, 0.874512f, 0.886719f, 0.898926f, 0.907227f, 0.916992f, 0.924805f, 0.932129f, 0.937988f, 0.943848f, 0.949219f, + 0.954102f, 0.958496f, 0.961426f, 0.965332f, 0.968750f, 0.972168f, 0.974609f, 0.977051f, 0.979492f, 0.981445f, 0.992188f, 0.993164f, + 0.993164f, 0.993164f, 0.993164f, 0.992676f, 0.000696f, 0.002352f, 0.004002f, 0.006138f, 0.008446f, 0.010826f, 0.013840f, 0.017258f, + 0.021194f, 0.025970f, 0.031128f, 0.037140f, 0.044281f, 0.053436f, 0.063660f, 0.076050f, 0.090271f, 0.107727f, 0.128662f, 0.152832f, + 0.182007f, 0.214111f, 0.252930f, 0.295166f, 0.341553f, 0.390625f, 0.442139f, 0.492676f, 0.541992f, 0.589844f, 0.633301f, 0.674316f, + 0.710938f, 0.743652f, 0.772461f, 0.796875f, 0.819824f, 0.839355f, 0.854980f, 0.870605f, 0.884277f, 0.895508f, 0.906738f, 0.915527f, + 0.923828f, 0.931152f, 0.937500f, 0.944336f, 0.949219f, 0.953613f, 0.958008f, 0.962402f, 0.965332f, 0.968750f, 0.972168f, 0.974609f, + 0.977051f, 0.979980f, 0.991211f, 0.992676f, 0.992188f, 0.992188f, 0.992188f, 0.992676f, 0.000838f, 0.002033f, 0.003664f, 0.005077f, + 0.007282f, 0.009415f, 0.011749f, 0.014931f, 0.017853f, 0.021606f, 0.025864f, 0.031219f, 0.037231f, 0.044464f, 0.052338f, 0.062500f, + 0.073853f, 0.087463f, 0.104065f, 0.123230f, 0.146362f, 0.173340f, 0.205078f, 0.240845f, 0.281982f, 0.326660f, 0.374756f, 0.425049f, + 0.476807f, 0.526855f, 0.574219f, 0.620117f, 0.662598f, 0.699219f, 0.733398f, 0.764160f, 0.791016f, 0.813965f, 0.833984f, 0.851074f, + 0.867676f, 0.880859f, 0.893555f, 0.904785f, 0.914062f, 0.922852f, 0.930176f, 0.937012f, 0.942383f, 0.948242f, 0.953125f, 0.957520f, + 0.962402f, 0.966309f, 0.969238f, 0.973145f, 0.975098f, 0.978027f, 0.991699f, 0.991699f, 0.992676f, 0.992188f, 0.991699f, 0.992188f, + 0.000600f, 0.001687f, 0.003023f, 0.004963f, 0.006405f, 0.008163f, 0.010368f, 0.012718f, 0.015480f, 0.018311f, 0.022064f, 0.026169f, + 0.031097f, 0.036926f, 0.043457f, 0.051392f, 0.060669f, 0.071350f, 0.084473f, 0.100220f, 0.118103f, 0.140259f, 0.166016f, 0.195679f, + 0.230469f, 0.269531f, 0.313232f, 0.360596f, 0.410156f, 0.460693f, 0.511719f, 0.560547f, 0.607422f, 0.650879f, 0.689941f, 0.724609f, + 0.756348f, 0.784180f, 0.808594f, 0.828613f, 0.847656f, 0.864258f, 0.879395f, 0.892090f, 0.903320f, 0.912598f, 0.921875f, 0.929688f, + 0.936523f, 0.942871f, 0.947754f, 0.953125f, 0.957520f, 0.961914f, 0.966309f, 0.969238f, 0.972656f, 0.975586f, 0.990234f, 0.991211f, + 0.991211f, 0.991699f, 0.991211f, 0.991211f, 0.000269f, 0.001538f, 0.002800f, 0.003868f, 0.005524f, 0.007179f, 0.008987f, 0.011063f, + 0.013084f, 0.015747f, 0.019211f, 0.022324f, 0.026474f, 0.031311f, 0.036530f, 0.042969f, 0.050201f, 0.059174f, 0.069641f, 0.081543f, + 0.096680f, 0.114075f, 0.134644f, 0.158691f, 0.187622f, 0.220581f, 0.258301f, 0.300781f, 0.347168f, 0.395996f, 0.447266f, 0.498291f, + 0.547852f, 0.595215f, 0.640625f, 0.680176f, 0.717285f, 0.749512f, 0.778320f, 0.803223f, 0.825684f, 0.845215f, 0.862793f, 0.877441f, + 0.890625f, 0.901855f, 0.912109f, 0.920898f, 0.929688f, 0.937012f, 0.942871f, 0.949707f, 0.954102f, 0.958496f, 0.962402f, 0.966309f, + 0.970215f, 0.974121f, 0.989746f, 0.990234f, 0.990723f, 0.990723f, 0.990723f, 0.990234f, 0.000341f, 0.001337f, 0.002573f, 0.003475f, + 0.004765f, 0.006329f, 0.007717f, 0.009499f, 0.011642f, 0.014107f, 0.016556f, 0.019470f, 0.022491f, 0.026169f, 0.030945f, 0.036011f, + 0.042389f, 0.049042f, 0.057678f, 0.067993f, 0.079468f, 0.093384f, 0.110046f, 0.129883f, 0.152710f, 0.180420f, 0.212158f, 0.248291f, + 0.289551f, 0.334961f, 0.383301f, 0.434570f, 0.485596f, 0.536133f, 0.584473f, 0.630371f, 0.671875f, 0.710449f, 0.743652f, 0.773926f, + 0.799316f, 0.823242f, 0.843262f, 0.860352f, 0.875977f, 0.889648f, 0.901367f, 0.911621f, 0.921387f, 0.929688f, 0.937012f, 0.943848f, + 0.950195f, 0.955078f, 0.959473f, 0.963379f, 0.967773f, 0.971191f, 0.988770f, 0.989746f, 0.990234f, 0.990234f, 0.990234f, 0.990234f, + 0.000564f, 0.001324f, 0.002092f, 0.003191f, 0.004471f, 0.005348f, 0.007069f, 0.008438f, 0.010201f, 0.011810f, 0.014297f, 0.016586f, + 0.019470f, 0.022644f, 0.026428f, 0.030579f, 0.035797f, 0.041718f, 0.048248f, 0.056213f, 0.065857f, 0.076782f, 0.090271f, 0.106262f, + 0.125122f, 0.147095f, 0.173462f, 0.204224f, 0.239746f, 0.279785f, 0.323730f, 0.372314f, 0.422607f, 0.474121f, 0.526367f, 0.575195f, + 0.621582f, 0.664062f, 0.703613f, 0.738770f, 0.769043f, 0.796387f, 0.820312f, 0.841797f, 0.858887f, 0.875488f, 0.889648f, 0.900879f, + 0.912598f, 0.921875f, 0.930664f, 0.937500f, 0.944336f, 0.950195f, 0.955566f, 0.959961f, 0.964844f, 0.968750f, 0.987305f, 0.989258f, + 0.989258f, 0.989258f, 0.989258f, 0.988770f, 0.000369f, 0.001128f, 0.001871f, 0.002792f, 0.003712f, 0.004723f, 0.006016f, 0.007542f, + 0.008896f, 0.010773f, 0.012421f, 0.014381f, 0.016632f, 0.019791f, 0.022354f, 0.025955f, 0.030609f, 0.035065f, 0.040924f, 0.047333f, + 0.055084f, 0.064209f, 0.075012f, 0.087769f, 0.102966f, 0.120911f, 0.142456f, 0.167358f, 0.197144f, 0.231812f, 0.270752f, 0.314209f, + 0.362549f, 0.412598f, 0.464844f, 0.515625f, 0.566895f, 0.614258f, 0.657715f, 0.698730f, 0.734863f, 0.766602f, 0.794922f, 0.818848f, + 0.839844f, 0.858887f, 0.875000f, 0.889648f, 0.901855f, 0.912598f, 0.922852f, 0.931152f, 0.938965f, 0.945312f, 0.951660f, 0.957520f, + 0.961426f, 0.966309f, 0.986816f, 0.988281f, 0.988281f, 0.988770f, 0.988281f, 0.988281f, 0.000466f, 0.000900f, 0.001792f, 0.002695f, + 0.003458f, 0.004204f, 0.005356f, 0.006512f, 0.007896f, 0.009300f, 0.010895f, 0.012459f, 0.014786f, 0.016739f, 0.019424f, 0.022461f, + 0.026062f, 0.029831f, 0.034851f, 0.039764f, 0.046417f, 0.053711f, 0.062164f, 0.072388f, 0.085205f, 0.099365f, 0.117004f, 0.137573f, + 0.162231f, 0.190674f, 0.224121f, 0.262451f, 0.305664f, 0.353027f, 0.403809f, 0.456055f, 0.508301f, 0.559082f, 0.608398f, 0.652832f, + 0.694824f, 0.731445f, 0.764160f, 0.793945f, 0.817871f, 0.839355f, 0.858398f, 0.875488f, 0.890137f, 0.902832f, 0.913574f, 0.923828f, + 0.932617f, 0.940918f, 0.946777f, 0.953613f, 0.958984f, 0.963379f, 0.985840f, 0.987305f, 0.987305f, 0.987793f, 0.987305f, 0.987305f, + 0.000234f, 0.001040f, 0.001661f, 0.002392f, 0.003101f, 0.003681f, 0.004944f, 0.005844f, 0.007065f, 0.008217f, 0.009247f, 0.010925f, + 0.012894f, 0.014549f, 0.017090f, 0.019455f, 0.022385f, 0.025650f, 0.029449f, 0.033936f, 0.039215f, 0.045135f, 0.052612f, 0.060944f, + 0.070312f, 0.082397f, 0.096924f, 0.113525f, 0.133179f, 0.156860f, 0.184814f, 0.217773f, 0.255127f, 0.298340f, 0.345215f, 0.395996f, + 0.448242f, 0.501953f, 0.553223f, 0.603516f, 0.649414f, 0.691895f, 0.729980f, 0.763184f, 0.792480f, 0.818359f, 0.841309f, 0.858887f, + 0.877441f, 0.891113f, 0.904785f, 0.915527f, 0.925781f, 0.933594f, 0.941895f, 0.949219f, 0.955566f, 0.960449f, 0.984863f, 0.985840f, + 0.986328f, 0.986816f, 0.986328f, 0.986816f, 0.000241f, 0.000808f, 0.001395f, 0.001986f, 0.002731f, 0.003429f, 0.004131f, 0.005402f, + 0.006077f, 0.007347f, 0.008522f, 0.009544f, 0.011345f, 0.013046f, 0.014534f, 0.016953f, 0.019241f, 0.022339f, 0.025208f, 0.029175f, + 0.033691f, 0.038300f, 0.044067f, 0.051331f, 0.059143f, 0.068726f, 0.080322f, 0.093567f, 0.109802f, 0.129883f, 0.152466f, 0.179810f, + 0.211792f, 0.249390f, 0.291748f, 0.338623f, 0.389404f, 0.442139f, 0.496338f, 0.548340f, 0.599121f, 0.645996f, 0.689941f, 0.728516f, + 0.762695f, 0.792969f, 0.818848f, 0.842285f, 0.862793f, 0.878906f, 0.894043f, 0.906250f, 0.917969f, 0.927734f, 0.935547f, 0.944336f, + 0.951172f, 0.957031f, 0.983398f, 0.985352f, 0.985840f, 0.985352f, 0.985840f, 0.985352f, 0.000340f, 0.000735f, 0.001377f, 0.001853f, + 0.002382f, 0.003159f, 0.004021f, 0.004642f, 0.005604f, 0.006340f, 0.007298f, 0.008591f, 0.009895f, 0.011154f, 0.012871f, 0.014580f, + 0.016876f, 0.019180f, 0.022141f, 0.024979f, 0.028748f, 0.032745f, 0.037964f, 0.043213f, 0.050171f, 0.057831f, 0.066833f, 0.078247f, + 0.091553f, 0.107178f, 0.125977f, 0.148315f, 0.175415f, 0.207153f, 0.244019f, 0.286377f, 0.333008f, 0.383789f, 0.437744f, 0.491943f, + 0.545410f, 0.597168f, 0.645508f, 0.688965f, 0.729004f, 0.764160f, 0.794434f, 0.821289f, 0.843750f, 0.864258f, 0.881348f, 0.895996f, + 0.909180f, 0.920898f, 0.929199f, 0.938965f, 0.946777f, 0.952637f, 0.982910f, 0.983887f, 0.984863f, 0.984863f, 0.984375f, 0.984863f, + 0.000236f, 0.000605f, 0.001135f, 0.001415f, 0.002329f, 0.002747f, 0.003551f, 0.004158f, 0.004723f, 0.005535f, 0.006687f, 0.007534f, + 0.008545f, 0.009979f, 0.011375f, 0.012993f, 0.014656f, 0.016754f, 0.018921f, 0.021759f, 0.024506f, 0.028183f, 0.032043f, 0.036743f, + 0.042236f, 0.048645f, 0.056030f, 0.065125f, 0.075928f, 0.089050f, 0.104370f, 0.122681f, 0.145142f, 0.171509f, 0.202759f, 0.239258f, + 0.281250f, 0.328369f, 0.379639f, 0.433838f, 0.489014f, 0.543945f, 0.596191f, 0.645020f, 0.690430f, 0.730957f, 0.766113f, 0.797852f, + 0.824219f, 0.846680f, 0.867188f, 0.884766f, 0.899414f, 0.912109f, 0.923828f, 0.933105f, 0.942383f, 0.949707f, 0.980957f, 0.982910f, + 0.983398f, 0.983398f, 0.983887f, 0.982910f, 0.000214f, 0.000710f, 0.001021f, 0.001429f, 0.001858f, 0.002607f, 0.003220f, 0.003738f, + 0.004459f, 0.005032f, 0.005726f, 0.006748f, 0.007748f, 0.008659f, 0.010002f, 0.011368f, 0.012985f, 0.014656f, 0.016525f, 0.018921f, + 0.021286f, 0.024231f, 0.027649f, 0.031464f, 0.035858f, 0.041321f, 0.047363f, 0.054840f, 0.063538f, 0.074097f, 0.086609f, 0.101990f, + 0.120117f, 0.141846f, 0.168213f, 0.199219f, 0.235352f, 0.277344f, 0.324707f, 0.376953f, 0.432373f, 0.488037f, 0.543457f, 0.597168f, + 0.646973f, 0.692871f, 0.732910f, 0.769531f, 0.801270f, 0.828125f, 0.850586f, 0.871582f, 0.888184f, 0.903809f, 0.915527f, 0.927246f, + 0.936523f, 0.946289f, 0.979492f, 0.981445f, 0.981934f, 0.982422f, 0.981934f, 0.981934f, 0.000000f, 0.000468f, 0.001076f, 0.001489f, + 0.002048f, 0.002413f, 0.002853f, 0.003468f, 0.003952f, 0.004444f, 0.005211f, 0.005917f, 0.006733f, 0.007763f, 0.008713f, 0.010262f, + 0.011368f, 0.012733f, 0.014458f, 0.016296f, 0.018478f, 0.021072f, 0.023666f, 0.026810f, 0.030746f, 0.035278f, 0.040131f, 0.046295f, + 0.053711f, 0.062195f, 0.072327f, 0.084717f, 0.099487f, 0.117371f, 0.139038f, 0.164795f, 0.195923f, 0.232422f, 0.274414f, 0.322266f, + 0.374756f, 0.431641f, 0.488525f, 0.545410f, 0.599121f, 0.650879f, 0.697754f, 0.738770f, 0.774414f, 0.806641f, 0.832520f, 0.856445f, + 0.875488f, 0.893555f, 0.907715f, 0.920410f, 0.931152f, 0.940918f, 0.978027f, 0.980469f, 0.980469f, 0.980957f, 0.980957f, 0.980957f, + 0.000279f, 0.000497f, 0.000763f, 0.001353f, 0.001794f, 0.002079f, 0.002451f, 0.002956f, 0.003498f, 0.004150f, 0.004589f, 0.005310f, + 0.006130f, 0.006958f, 0.007828f, 0.008888f, 0.009895f, 0.011124f, 0.012772f, 0.014282f, 0.016235f, 0.018127f, 0.020630f, 0.022873f, + 0.026321f, 0.029938f, 0.034241f, 0.039368f, 0.045319f, 0.052338f, 0.060852f, 0.070801f, 0.082947f, 0.097595f, 0.115051f, 0.136353f, + 0.162231f, 0.193481f, 0.229858f, 0.272217f, 0.321777f, 0.375000f, 0.432373f, 0.490479f, 0.548340f, 0.604004f, 0.655762f, 0.702637f, + 0.743652f, 0.780273f, 0.812500f, 0.838867f, 0.862305f, 0.881348f, 0.897949f, 0.912598f, 0.925293f, 0.935547f, 0.976562f, 0.978516f, + 0.979492f, 0.979980f, 0.979492f, 0.979004f, 0.000110f, 0.000473f, 0.000781f, 0.001262f, 0.001584f, 0.001890f, 0.002270f, 0.002607f, + 0.003241f, 0.003704f, 0.004055f, 0.004795f, 0.005356f, 0.005997f, 0.006760f, 0.007896f, 0.008896f, 0.009918f, 0.011200f, 0.012451f, + 0.013802f, 0.015556f, 0.017838f, 0.020065f, 0.022751f, 0.025864f, 0.029358f, 0.033600f, 0.038574f, 0.044342f, 0.050995f, 0.059296f, + 0.069214f, 0.081116f, 0.095459f, 0.113159f, 0.133911f, 0.160400f, 0.191406f, 0.228638f, 0.272217f, 0.321289f, 0.375732f, 0.434326f, + 0.493896f, 0.552734f, 0.609863f, 0.662109f, 0.709961f, 0.750977f, 0.787598f, 0.819336f, 0.846680f, 0.868164f, 0.887695f, 0.904297f, + 0.917969f, 0.930176f, 0.975098f, 0.977539f, 0.977051f, 0.977539f, 0.977539f, 0.977539f, 0.000242f, 0.000464f, 0.000831f, 0.001027f, + 0.001271f, 0.001722f, 0.001965f, 0.002243f, 0.002714f, 0.003036f, 0.003651f, 0.004025f, 0.004902f, 0.005638f, 0.006176f, 0.006943f, + 0.007763f, 0.008789f, 0.009804f, 0.010872f, 0.012070f, 0.013695f, 0.015381f, 0.017395f, 0.019608f, 0.022232f, 0.025009f, 0.028885f, + 0.032623f, 0.037659f, 0.043182f, 0.050018f, 0.058167f, 0.067810f, 0.079224f, 0.093811f, 0.111328f, 0.132324f, 0.158569f, 0.190063f, + 0.228149f, 0.271973f, 0.322510f, 0.378906f, 0.438477f, 0.499756f, 0.560059f, 0.618164f, 0.671387f, 0.718750f, 0.760742f, 0.796875f, + 0.826660f, 0.854492f, 0.875000f, 0.894531f, 0.911133f, 0.923828f, 0.973145f, 0.976074f, 0.975586f, 0.976074f, 0.976074f, 0.977051f, + 0.000242f, 0.000552f, 0.000701f, 0.001063f, 0.001186f, 0.001462f, 0.001690f, 0.002340f, 0.002703f, 0.002728f, 0.003325f, 0.003828f, + 0.004333f, 0.004913f, 0.005474f, 0.006077f, 0.006943f, 0.007607f, 0.008553f, 0.009460f, 0.010582f, 0.011871f, 0.013451f, 0.015091f, + 0.016983f, 0.019165f, 0.021637f, 0.024673f, 0.027863f, 0.031525f, 0.036713f, 0.041962f, 0.048615f, 0.056396f, 0.066162f, 0.077942f, + 0.092590f, 0.110046f, 0.130981f, 0.157593f, 0.189331f, 0.228394f, 0.273926f, 0.325684f, 0.383301f, 0.444580f, 0.507324f, 0.569824f, + 0.627441f, 0.682129f, 0.729980f, 0.770508f, 0.807129f, 0.837402f, 0.863281f, 0.884766f, 0.902832f, 0.917969f, 0.971191f, 0.973633f, + 0.974609f, 0.974121f, 0.974609f, 0.974609f, 0.000239f, 0.000239f, 0.000658f, 0.000899f, 0.001204f, 0.001252f, 0.001629f, 0.001815f, + 0.002470f, 0.002430f, 0.003134f, 0.003321f, 0.003925f, 0.004238f, 0.004856f, 0.005341f, 0.006161f, 0.006615f, 0.007511f, 0.008224f, + 0.009277f, 0.010445f, 0.011818f, 0.013046f, 0.014473f, 0.016510f, 0.018814f, 0.021057f, 0.023834f, 0.027237f, 0.030853f, 0.035675f, + 0.040894f, 0.047241f, 0.055145f, 0.064758f, 0.076782f, 0.090942f, 0.108398f, 0.130371f, 0.157104f, 0.189819f, 0.229248f, 0.276367f, + 0.329834f, 0.390137f, 0.453125f, 0.517578f, 0.580566f, 0.640625f, 0.694336f, 0.741699f, 0.782715f, 0.817871f, 0.848145f, 0.872559f, + 0.893555f, 0.910645f, 0.969727f, 0.971191f, 0.972656f, 0.972168f, 0.972168f, 0.972168f, 0.000222f, 0.000463f, 0.000620f, 0.000837f, + 0.000900f, 0.001048f, 0.001381f, 0.001820f, 0.001957f, 0.002329f, 0.002747f, 0.002964f, 0.003330f, 0.003986f, 0.004322f, 0.004677f, + 0.005302f, 0.005760f, 0.006569f, 0.007359f, 0.008141f, 0.009293f, 0.010101f, 0.011452f, 0.012779f, 0.014496f, 0.016144f, 0.018097f, + 0.020157f, 0.023148f, 0.026611f, 0.029785f, 0.034515f, 0.039856f, 0.046478f, 0.054016f, 0.063843f, 0.075378f, 0.089233f, 0.107666f, + 0.129639f, 0.156860f, 0.190674f, 0.231445f, 0.280518f, 0.336426f, 0.398193f, 0.463379f, 0.530273f, 0.595215f, 0.654785f, 0.708984f, + 0.755371f, 0.796875f, 0.831543f, 0.860352f, 0.883789f, 0.903809f, 0.966797f, 0.968750f, 0.969727f, 0.970215f, 0.970215f, 0.969727f, + 0.000000f, 0.000345f, 0.000464f, 0.000686f, 0.000782f, 0.001030f, 0.001139f, 0.001598f, 0.001846f, 0.002237f, 0.002489f, 0.002684f, + 0.003067f, 0.003344f, 0.003895f, 0.004158f, 0.004845f, 0.005131f, 0.005886f, 0.006561f, 0.007195f, 0.007912f, 0.008965f, 0.009941f, + 0.010956f, 0.012383f, 0.013893f, 0.015602f, 0.017303f, 0.019623f, 0.022156f, 0.025452f, 0.028976f, 0.033722f, 0.038910f, 0.045288f, + 0.052887f, 0.062561f, 0.074097f, 0.088623f, 0.106812f, 0.129639f, 0.157715f, 0.192261f, 0.235107f, 0.285889f, 0.344482f, 0.408691f, + 0.476807f, 0.545410f, 0.610840f, 0.671387f, 0.725098f, 0.771484f, 0.811035f, 0.843750f, 0.871582f, 0.894043f, 0.964355f, 0.967285f, + 0.967285f, 0.967773f, 0.967773f, 0.967773f, 0.000000f, 0.000320f, 0.000576f, 0.000572f, 0.000767f, 0.000945f, 0.001066f, 0.001375f, + 0.001848f, 0.001980f, 0.002190f, 0.002399f, 0.002695f, 0.002943f, 0.003397f, 0.003664f, 0.004063f, 0.004566f, 0.005119f, 0.005688f, + 0.006130f, 0.007057f, 0.007778f, 0.008675f, 0.009590f, 0.010666f, 0.011971f, 0.013443f, 0.015129f, 0.016953f, 0.018875f, 0.021576f, + 0.024658f, 0.028488f, 0.032959f, 0.037811f, 0.043793f, 0.051819f, 0.061371f, 0.073181f, 0.088257f, 0.106506f, 0.129883f, 0.159180f, + 0.195679f, 0.240479f, 0.293457f, 0.355225f, 0.422852f, 0.492432f, 0.563477f, 0.629883f, 0.690918f, 0.743652f, 0.789062f, 0.827148f, + 0.858398f, 0.884277f, 0.961914f, 0.964844f, 0.964355f, 0.964844f, 0.964355f, 0.965332f, 0.000000f, 0.000242f, 0.000435f, 0.000547f, + 0.000688f, 0.000803f, 0.001175f, 0.001318f, 0.001593f, 0.001652f, 0.001961f, 0.002209f, 0.002481f, 0.002716f, 0.002911f, 0.003210f, + 0.003595f, 0.004005f, 0.004490f, 0.004894f, 0.005508f, 0.006107f, 0.006714f, 0.007462f, 0.008438f, 0.009277f, 0.010170f, 0.011436f, + 0.012756f, 0.014145f, 0.016205f, 0.018433f, 0.020966f, 0.023819f, 0.027405f, 0.031464f, 0.036713f, 0.043152f, 0.050842f, 0.060577f, + 0.071960f, 0.087219f, 0.106689f, 0.130371f, 0.161377f, 0.199585f, 0.246948f, 0.303467f, 0.367920f, 0.439697f, 0.512207f, 0.584473f, + 0.651855f, 0.712402f, 0.764160f, 0.808105f, 0.844727f, 0.875000f, 0.958008f, 0.961426f, 0.961914f, 0.961914f, 0.962402f, 0.961914f, + 0.000000f, 0.000237f, 0.000266f, 0.000387f, 0.000557f, 0.000691f, 0.000774f, 0.001221f, 0.001455f, 0.001492f, 0.001769f, 0.001896f, + 0.002151f, 0.002386f, 0.002529f, 0.002911f, 0.003147f, 0.003523f, 0.003862f, 0.004311f, 0.004848f, 0.005260f, 0.005795f, 0.006416f, + 0.007114f, 0.007942f, 0.008667f, 0.009666f, 0.010818f, 0.012184f, 0.013718f, 0.015541f, 0.017685f, 0.020126f, 0.023056f, 0.026306f, + 0.030853f, 0.035797f, 0.042053f, 0.049683f, 0.059784f, 0.072144f, 0.086914f, 0.106873f, 0.132202f, 0.164429f, 0.205200f, 0.255615f, + 0.315918f, 0.384521f, 0.458984f, 0.534668f, 0.607910f, 0.676758f, 0.735840f, 0.785645f, 0.828125f, 0.862305f, 0.955566f, 0.958008f, + 0.958984f, 0.958496f, 0.958984f, 0.958984f, 0.000000f, 0.000119f, 0.000234f, 0.000484f, 0.000603f, 0.000758f, 0.000934f, 0.000999f, + 0.001200f, 0.001343f, 0.001534f, 0.001725f, 0.001860f, 0.002056f, 0.002235f, 0.002445f, 0.002783f, 0.003115f, 0.003448f, 0.003757f, + 0.004192f, 0.004723f, 0.005077f, 0.005653f, 0.006172f, 0.006527f, 0.007328f, 0.008247f, 0.009140f, 0.010368f, 0.011711f, 0.013351f, + 0.014702f, 0.016937f, 0.019226f, 0.022156f, 0.025604f, 0.029877f, 0.034668f, 0.040710f, 0.048920f, 0.058624f, 0.071289f, 0.087219f, + 0.107727f, 0.134521f, 0.168701f, 0.212769f, 0.267090f, 0.331543f, 0.404785f, 0.482910f, 0.561523f, 0.635742f, 0.702637f, 0.760742f, + 0.809570f, 0.849121f, 0.951660f, 0.954590f, 0.955566f, 0.955566f, 0.956055f, 0.955566f, 0.000238f, 0.000218f, 0.000229f, 0.000242f, + 0.000313f, 0.000859f, 0.000623f, 0.000978f, 0.001021f, 0.001150f, 0.001320f, 0.001431f, 0.001546f, 0.001746f, 0.001895f, 0.002106f, + 0.002502f, 0.002630f, 0.002926f, 0.003296f, 0.003651f, 0.003918f, 0.004391f, 0.004910f, 0.005249f, 0.005558f, 0.006413f, 0.007114f, + 0.007866f, 0.008789f, 0.009872f, 0.011093f, 0.012413f, 0.013939f, 0.015945f, 0.018692f, 0.021225f, 0.024643f, 0.028687f, 0.033936f, + 0.040192f, 0.047791f, 0.058014f, 0.070923f, 0.087585f, 0.109131f, 0.137573f, 0.174683f, 0.222290f, 0.280762f, 0.350830f, 0.428955f, + 0.511230f, 0.592285f, 0.666992f, 0.733398f, 0.789062f, 0.834473f, 0.947754f, 0.951172f, 0.951660f, 0.951172f, 0.951660f, 0.951172f, + 0.000000f, 0.000205f, 0.000222f, 0.000344f, 0.000301f, 0.000775f, 0.000827f, 0.000719f, 0.000944f, 0.000976f, 0.001306f, 0.001249f, + 0.001404f, 0.001569f, 0.001604f, 0.001819f, 0.002182f, 0.002354f, 0.002569f, 0.002857f, 0.003113f, 0.003426f, 0.003649f, 0.004112f, + 0.004307f, 0.004925f, 0.005508f, 0.005802f, 0.006565f, 0.007450f, 0.008125f, 0.009079f, 0.010269f, 0.011665f, 0.013565f, 0.015213f, + 0.017410f, 0.020203f, 0.023743f, 0.028168f, 0.032684f, 0.039062f, 0.047058f, 0.057404f, 0.070984f, 0.088623f, 0.111389f, 0.142090f, + 0.182373f, 0.234253f, 0.298828f, 0.375000f, 0.458008f, 0.543945f, 0.627441f, 0.702148f, 0.765137f, 0.818359f, 0.942871f, 0.946289f, + 0.947266f, 0.947266f, 0.946777f, 0.947266f, 0.000064f, 0.000095f, 0.000197f, 0.000213f, 0.000459f, 0.000491f, 0.000647f, 0.000696f, + 0.000884f, 0.000911f, 0.001121f, 0.001115f, 0.001234f, 0.001371f, 0.001410f, 0.001743f, 0.001905f, 0.002016f, 0.002207f, 0.002438f, + 0.002714f, 0.002939f, 0.003183f, 0.003323f, 0.003727f, 0.004143f, 0.004555f, 0.005276f, 0.005531f, 0.006264f, 0.006702f, 0.007572f, + 0.008705f, 0.009712f, 0.011238f, 0.012650f, 0.014320f, 0.016815f, 0.019516f, 0.022400f, 0.026566f, 0.031799f, 0.038055f, 0.046417f, + 0.057037f, 0.071350f, 0.089722f, 0.114868f, 0.148193f, 0.192749f, 0.249878f, 0.321045f, 0.404053f, 0.493408f, 0.583008f, 0.666016f, + 0.739258f, 0.799316f, 0.937988f, 0.941406f, 0.941895f, 0.942383f, 0.942383f, 0.942383f, 0.000000f, 0.000007f, 0.000144f, 0.000427f, + 0.000443f, 0.000566f, 0.000589f, 0.000615f, 0.000725f, 0.000731f, 0.000896f, 0.000953f, 0.001062f, 0.001167f, 0.001344f, 0.001345f, + 0.001636f, 0.001774f, 0.001893f, 0.002069f, 0.002350f, 0.002457f, 0.002678f, 0.002743f, 0.003105f, 0.003513f, 0.003830f, 0.004227f, + 0.004589f, 0.005047f, 0.005669f, 0.006176f, 0.007153f, 0.007896f, 0.008911f, 0.010231f, 0.011818f, 0.013618f, 0.015465f, 0.018188f, + 0.021576f, 0.025452f, 0.030533f, 0.037048f, 0.045685f, 0.056915f, 0.071533f, 0.091675f, 0.118958f, 0.156006f, 0.205444f, 0.270020f, + 0.349609f, 0.439941f, 0.533691f, 0.625977f, 0.708984f, 0.778320f, 0.931641f, 0.936035f, 0.936523f, 0.937012f, 0.937012f, 0.937012f, + 0.000000f, 0.000000f, 0.000137f, 0.000262f, 0.000432f, 0.000437f, 0.000444f, 0.000590f, 0.000558f, 0.000606f, 0.000817f, 0.000877f, + 0.000909f, 0.000951f, 0.001191f, 0.001244f, 0.001373f, 0.001506f, 0.001702f, 0.001690f, 0.001955f, 0.001940f, 0.002283f, 0.002340f, + 0.002571f, 0.002871f, 0.003265f, 0.003475f, 0.003910f, 0.004181f, 0.004608f, 0.005112f, 0.005833f, 0.006416f, 0.007145f, 0.008209f, + 0.009636f, 0.010750f, 0.012642f, 0.014481f, 0.017197f, 0.020203f, 0.024353f, 0.029694f, 0.036041f, 0.045105f, 0.056702f, 0.072388f, + 0.094482f, 0.124329f, 0.166504f, 0.223022f, 0.295898f, 0.384766f, 0.482910f, 0.582031f, 0.675293f, 0.754883f, 0.926270f, 0.929688f, + 0.930664f, 0.930664f, 0.931152f, 0.930664f, 0.000000f, 0.000000f, 0.000000f, 0.000232f, 0.000357f, 0.000411f, 0.000513f, 0.000527f, + 0.000490f, 0.000504f, 0.000653f, 0.000750f, 0.000780f, 0.000976f, 0.000942f, 0.000967f, 0.001180f, 0.001252f, 0.001385f, 0.001425f, + 0.001559f, 0.001801f, 0.001886f, 0.002144f, 0.002111f, 0.002354f, 0.002645f, 0.002827f, 0.003187f, 0.003414f, 0.003792f, 0.004360f, + 0.004662f, 0.005146f, 0.005875f, 0.006783f, 0.007610f, 0.008797f, 0.010033f, 0.011566f, 0.013565f, 0.016006f, 0.019165f, 0.023163f, + 0.028320f, 0.035400f, 0.044647f, 0.057129f, 0.074402f, 0.098572f, 0.132812f, 0.180542f, 0.245728f, 0.330078f, 0.428955f, 0.535156f, + 0.638184f, 0.728516f, 0.919434f, 0.922852f, 0.923828f, 0.923828f, 0.923828f, 0.924316f, 0.000000f, 0.000000f, 0.000000f, 0.000114f, + 0.000248f, 0.000359f, 0.000386f, 0.000342f, 0.000465f, 0.000461f, 0.000490f, 0.000609f, 0.000638f, 0.000694f, 0.000807f, 0.000923f, + 0.000961f, 0.001074f, 0.001123f, 0.001268f, 0.001311f, 0.001494f, 0.001537f, 0.001754f, 0.001899f, 0.001917f, 0.002199f, 0.002241f, + 0.002583f, 0.002769f, 0.003101f, 0.003441f, 0.003775f, 0.004200f, 0.004787f, 0.005272f, 0.006062f, 0.006702f, 0.007732f, 0.009102f, + 0.010582f, 0.012466f, 0.014984f, 0.017990f, 0.021957f, 0.027222f, 0.034332f, 0.044128f, 0.057434f, 0.076538f, 0.104126f, 0.143799f, + 0.199829f, 0.275879f, 0.373047f, 0.482422f, 0.594727f, 0.698730f, 0.910645f, 0.914551f, 0.916504f, 0.916016f, 0.916504f, 0.915527f, + 0.000000f, 0.000000f, 0.000000f, 0.000121f, 0.000221f, 0.000222f, 0.000392f, 0.000402f, 0.000396f, 0.000434f, 0.000476f, 0.000548f, + 0.000536f, 0.000644f, 0.000642f, 0.000793f, 0.000795f, 0.000912f, 0.000953f, 0.000989f, 0.001164f, 0.001197f, 0.001285f, 0.001480f, + 0.001511f, 0.001674f, 0.001703f, 0.001901f, 0.002075f, 0.002340f, 0.002499f, 0.002800f, 0.003019f, 0.003296f, 0.003695f, 0.004093f, + 0.004780f, 0.005260f, 0.006207f, 0.006939f, 0.008034f, 0.009598f, 0.011353f, 0.013702f, 0.016678f, 0.020874f, 0.026062f, 0.033539f, + 0.044006f, 0.058746f, 0.080139f, 0.111877f, 0.158447f, 0.226318f, 0.317627f, 0.428711f, 0.548828f, 0.665039f, 0.901367f, 0.907227f, + 0.907715f, 0.908203f, 0.908203f, 0.907227f, 0.000000f, 0.000000f, 0.000122f, 0.000173f, 0.000191f, 0.000215f, 0.000224f, 0.000261f, + 0.000340f, 0.000374f, 0.000380f, 0.000496f, 0.000416f, 0.000535f, 0.000592f, 0.000622f, 0.000701f, 0.000772f, 0.000742f, 0.000774f, + 0.000990f, 0.000945f, 0.001088f, 0.001105f, 0.001348f, 0.001231f, 0.001460f, 0.001620f, 0.001758f, 0.001941f, 0.002008f, 0.002092f, + 0.002430f, 0.002615f, 0.002886f, 0.003208f, 0.003519f, 0.004112f, 0.004704f, 0.005371f, 0.006149f, 0.007351f, 0.008659f, 0.010201f, + 0.012550f, 0.015549f, 0.019577f, 0.025436f, 0.032928f, 0.044220f, 0.060608f, 0.084961f, 0.123474f, 0.180664f, 0.263184f, 0.372314f, + 0.498291f, 0.626465f, 0.892578f, 0.895996f, 0.896973f, 0.896973f, 0.897949f, 0.897949f, 0.000000f, 0.000000f, 0.000121f, 0.000121f, + 0.000120f, 0.000192f, 0.000201f, 0.000222f, 0.000222f, 0.000276f, 0.000295f, 0.000344f, 0.000433f, 0.000470f, 0.000485f, 0.000549f, + 0.000555f, 0.000558f, 0.000566f, 0.000639f, 0.000678f, 0.000757f, 0.000840f, 0.000905f, 0.000999f, 0.000946f, 0.001018f, 0.001309f, + 0.001402f, 0.001417f, 0.001624f, 0.001692f, 0.001869f, 0.002003f, 0.002184f, 0.002602f, 0.002851f, 0.003157f, 0.003595f, 0.004063f, + 0.004734f, 0.005398f, 0.006275f, 0.007542f, 0.009148f, 0.011383f, 0.014275f, 0.018250f, 0.024063f, 0.032135f, 0.044922f, 0.063721f, + 0.093811f, 0.139648f, 0.211914f, 0.314697f, 0.444092f, 0.584961f, 0.879883f, 0.884766f, 0.885254f, 0.885742f, 0.886230f, 0.885742f, + 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000120f, 0.000154f, 0.000150f, 0.000160f, 0.000202f, 0.000217f, 0.000308f, 0.000319f, + 0.000278f, 0.000392f, 0.000362f, 0.000432f, 0.000416f, 0.000448f, 0.000495f, 0.000526f, 0.000710f, 0.000754f, 0.000657f, 0.000755f, + 0.000806f, 0.000919f, 0.000815f, 0.001080f, 0.001152f, 0.001207f, 0.001218f, 0.001373f, 0.001320f, 0.001685f, 0.001764f, 0.001819f, + 0.002068f, 0.002380f, 0.002668f, 0.003033f, 0.003584f, 0.003979f, 0.004829f, 0.005402f, 0.006630f, 0.008080f, 0.010254f, 0.013069f, + 0.017044f, 0.023422f, 0.031647f, 0.046417f, 0.068604f, 0.104919f, 0.165161f, 0.258789f, 0.387207f, 0.537598f, 0.867188f, 0.871582f, + 0.872559f, 0.872559f, 0.872559f, 0.873047f, 0.000000f, 0.000121f, 0.000120f, 0.000120f, 0.000119f, 0.000118f, 0.000122f, 0.000108f, + 0.000143f, 0.000149f, 0.000184f, 0.000194f, 0.000189f, 0.000210f, 0.000321f, 0.000282f, 0.000376f, 0.000420f, 0.000533f, 0.000437f, + 0.000467f, 0.000477f, 0.000587f, 0.000519f, 0.000673f, 0.000662f, 0.000679f, 0.000845f, 0.000881f, 0.000863f, 0.001016f, 0.001093f, + 0.001176f, 0.001191f, 0.001336f, 0.001561f, 0.001573f, 0.001754f, 0.001919f, 0.002264f, 0.002596f, 0.002911f, 0.003372f, 0.003870f, + 0.004723f, 0.005733f, 0.007092f, 0.008965f, 0.011650f, 0.015701f, 0.022339f, 0.032043f, 0.048370f, 0.076050f, 0.124084f, 0.204834f, + 0.328369f, 0.485596f, 0.852539f, 0.856934f, 0.858887f, 0.858887f, 0.858887f, 0.858398f, 0.000000f, 0.000121f, 0.000120f, 0.000119f, + 0.000118f, 0.000117f, 0.000116f, 0.000114f, 0.000105f, 0.000110f, 0.000165f, 0.000133f, 0.000157f, 0.000240f, 0.000256f, 0.000257f, + 0.000249f, 0.000303f, 0.000342f, 0.000346f, 0.000485f, 0.000510f, 0.000398f, 0.000493f, 0.000492f, 0.000524f, 0.000590f, 0.000585f, + 0.000601f, 0.000740f, 0.000647f, 0.000871f, 0.000834f, 0.000969f, 0.001020f, 0.001190f, 0.001244f, 0.001432f, 0.001393f, 0.001702f, + 0.001912f, 0.002171f, 0.002445f, 0.002958f, 0.003330f, 0.004025f, 0.004860f, 0.006161f, 0.007896f, 0.010742f, 0.014671f, 0.021378f, + 0.032928f, 0.052612f, 0.089050f, 0.155884f, 0.268555f, 0.430664f, 0.836426f, 0.841309f, 0.841309f, 0.842285f, 0.842773f, 0.842285f, + 0.000000f, 0.000000f, 0.000119f, 0.000117f, 0.000116f, 0.000115f, 0.000114f, 0.000114f, 0.000111f, 0.000103f, 0.000097f, 0.000118f, + 0.000115f, 0.000130f, 0.000176f, 0.000130f, 0.000223f, 0.000235f, 0.000244f, 0.000252f, 0.000274f, 0.000389f, 0.000309f, 0.000430f, + 0.000340f, 0.000399f, 0.000408f, 0.000459f, 0.000514f, 0.000501f, 0.000519f, 0.000657f, 0.000588f, 0.000775f, 0.000813f, 0.000789f, + 0.000904f, 0.001076f, 0.001027f, 0.001170f, 0.001342f, 0.001425f, 0.001662f, 0.002005f, 0.002298f, 0.002699f, 0.003227f, 0.003990f, + 0.005062f, 0.006855f, 0.009415f, 0.013504f, 0.020905f, 0.034424f, 0.060333f, 0.112000f, 0.210693f, 0.371094f, 0.816406f, 0.822754f, + 0.822754f, 0.823242f, 0.823242f, 0.823730f, 0.000000f, 0.000119f, 0.000117f, 0.000116f, 0.000114f, 0.000113f, 0.000112f, 0.000111f, + 0.000110f, 0.000109f, 0.000102f, 0.000095f, 0.000090f, 0.000084f, 0.000093f, 0.000103f, 0.000118f, 0.000165f, 0.000162f, 0.000190f, + 0.000204f, 0.000218f, 0.000223f, 0.000237f, 0.000256f, 0.000272f, 0.000344f, 0.000365f, 0.000365f, 0.000396f, 0.000386f, 0.000412f, + 0.000530f, 0.000466f, 0.000492f, 0.000615f, 0.000611f, 0.000748f, 0.000712f, 0.000795f, 0.000908f, 0.000971f, 0.001106f, 0.001353f, + 0.001572f, 0.001822f, 0.002251f, 0.002676f, 0.003290f, 0.004349f, 0.005951f, 0.008316f, 0.012543f, 0.021149f, 0.038025f, 0.075500f, + 0.156006f, 0.308838f, 0.794922f, 0.800293f, 0.800781f, 0.801270f, 0.801758f, 0.802246f, 0.000121f, 0.000116f, 0.000114f, 0.000113f, + 0.000111f, 0.000109f, 0.000108f, 0.000107f, 0.000106f, 0.000104f, 0.000104f, 0.000100f, 0.000094f, 0.000088f, 0.000083f, 0.000078f, + 0.000074f, 0.000105f, 0.000078f, 0.000122f, 0.000113f, 0.000153f, 0.000174f, 0.000175f, 0.000207f, 0.000216f, 0.000225f, 0.000215f, + 0.000262f, 0.000308f, 0.000297f, 0.000287f, 0.000307f, 0.000342f, 0.000363f, 0.000411f, 0.000401f, 0.000453f, 0.000522f, 0.000555f, + 0.000680f, 0.000701f, 0.000751f, 0.000873f, 0.000966f, 0.001181f, 0.001445f, 0.001666f, 0.002077f, 0.002512f, 0.003359f, 0.004856f, + 0.007347f, 0.012001f, 0.022049f, 0.046417f, 0.107117f, 0.245361f, 0.770508f, 0.775879f, 0.776367f, 0.776855f, 0.777344f, 0.777832f, + 0.000000f, 0.000113f, 0.000108f, 0.000107f, 0.000104f, 0.000103f, 0.000101f, 0.000100f, 0.000099f, 0.000098f, 0.000097f, 0.000096f, + 0.000095f, 0.000091f, 0.000086f, 0.000081f, 0.000077f, 0.000073f, 0.000069f, 0.000079f, 0.000084f, 0.000091f, 0.000074f, 0.000100f, + 0.000117f, 0.000140f, 0.000144f, 0.000166f, 0.000174f, 0.000178f, 0.000225f, 0.000197f, 0.000234f, 0.000239f, 0.000273f, 0.000289f, + 0.000283f, 0.000293f, 0.000338f, 0.000386f, 0.000386f, 0.000432f, 0.000459f, 0.000525f, 0.000625f, 0.000691f, 0.000800f, 0.001004f, + 0.001227f, 0.001479f, 0.001984f, 0.002745f, 0.003983f, 0.006413f, 0.011642f, 0.025269f, 0.066040f, 0.182495f, 0.743164f, 0.748535f, + 0.749023f, 0.749512f, 0.750000f, 0.749512f, 0.000000f, 0.000102f, 0.000101f, 0.000098f, 0.000094f, 0.000093f, 0.000092f, 0.000090f, + 0.000089f, 0.000088f, 0.000087f, 0.000086f, 0.000085f, 0.000084f, 0.000085f, 0.000082f, 0.000078f, 0.000074f, 0.000070f, 0.000066f, + 0.000063f, 0.000060f, 0.000057f, 0.000056f, 0.000061f, 0.000060f, 0.000073f, 0.000087f, 0.000100f, 0.000105f, 0.000124f, 0.000136f, + 0.000140f, 0.000140f, 0.000159f, 0.000179f, 0.000186f, 0.000205f, 0.000214f, 0.000229f, 0.000248f, 0.000267f, 0.000299f, 0.000344f, + 0.000367f, 0.000422f, 0.000496f, 0.000557f, 0.000639f, 0.000837f, 0.001037f, 0.001419f, 0.002081f, 0.003202f, 0.005730f, 0.012199f, + 0.034943f, 0.122925f, 0.711426f, 0.716797f, 0.718750f, 0.718262f, 0.718262f, 0.718750f, 0.000094f, 0.000079f, 0.000078f, 0.000074f, + 0.000074f, 0.000075f, 0.000074f, 0.000073f, 0.000071f, 0.000072f, 0.000070f, 0.000071f, 0.000071f, 0.000070f, 0.000070f, 0.000069f, + 0.000070f, 0.000069f, 0.000068f, 0.000065f, 0.000062f, 0.000059f, 0.000056f, 0.000053f, 0.000050f, 0.000048f, 0.000045f, 0.000044f, + 0.000041f, 0.000050f, 0.000050f, 0.000061f, 0.000068f, 0.000085f, 0.000091f, 0.000101f, 0.000102f, 0.000107f, 0.000119f, 0.000129f, + 0.000144f, 0.000151f, 0.000160f, 0.000184f, 0.000212f, 0.000213f, 0.000235f, 0.000294f, 0.000315f, 0.000392f, 0.000505f, 0.000637f, + 0.000880f, 0.001400f, 0.002462f, 0.005333f, 0.015160f, 0.070312f, 0.678223f, 0.683105f, 0.684082f, 0.684570f, 0.684570f, 0.684570f, + 0.000000f, 0.000000f, 0.000023f, 0.000034f, 0.000032f, 0.000038f, 0.000037f, 0.000044f, 0.000043f, 0.000047f, 0.000045f, 0.000047f, + 0.000049f, 0.000049f, 0.000049f, 0.000048f, 0.000051f, 0.000050f, 0.000051f, 0.000051f, 0.000052f, 0.000052f, 0.000052f, 0.000049f, + 0.000047f, 0.000045f, 0.000042f, 0.000040f, 0.000038f, 0.000036f, 0.000035f, 0.000033f, 0.000031f, 0.000029f, 0.000038f, 0.000037f, + 0.000042f, 0.000051f, 0.000055f, 0.000067f, 0.000074f, 0.000073f, 0.000083f, 0.000093f, 0.000088f, 0.000102f, 0.000122f, 0.000122f, + 0.000142f, 0.000169f, 0.000206f, 0.000265f, 0.000355f, 0.000531f, 0.000897f, 0.001822f, 0.005493f, 0.030579f, 0.640137f, 0.644531f, + 0.647461f, 0.647949f, 0.647461f, 0.648438f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000001f, 0.000000f, 0.000008f, 0.000012f, 0.000014f, 0.000014f, 0.000019f, 0.000021f, 0.000022f, 0.000024f, 0.000026f, 0.000027f, + 0.000027f, 0.000028f, 0.000029f, 0.000031f, 0.000031f, 0.000032f, 0.000032f, 0.000033f, 0.000033f, 0.000032f, 0.000030f, 0.000029f, + 0.000027f, 0.000026f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000019f, 0.000018f, 0.000021f, 0.000024f, 0.000028f, 0.000033f, + 0.000043f, 0.000041f, 0.000046f, 0.000053f, 0.000050f, 0.000059f, 0.000068f, 0.000094f, 0.000096f, 0.000140f, 0.000239f, 0.000447f, + 0.001340f, 0.009087f, 0.600098f, 0.605957f, 0.606934f, 0.606934f, 0.607422f, 0.606934f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000004f, 0.000006f, 0.000006f, + 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000013f, 0.000014f, 0.000015f, 0.000016f, 0.000017f, 0.000016f, 0.000015f, 0.000014f, + 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000010f, 0.000009f, 0.000008f, 0.000012f, 0.000014f, 0.000018f, 0.000017f, 0.000022f, + 0.000022f, 0.000026f, 0.000040f, 0.000060f, 0.000157f, 0.001244f, 0.557129f, 0.563477f, 0.563477f, 0.564941f, 0.564941f, 0.564941f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000002f, 0.000003f, + 0.000003f, 0.000004f, 0.000003f, 0.000003f, 0.000003f, 0.000002f, 0.000003f, 0.000003f, 0.000003f, 0.000012f, 0.513672f, 0.520020f, + 0.520020f, 0.520508f, 0.521484f, 0.521484f, + }, + { + 0.103943f, 0.284912f, 0.422119f, 0.523438f, 0.600586f, 0.659668f, 0.705078f, 0.741699f, 0.771484f, 0.795898f, 0.816895f, 0.834961f, + 0.850586f, 0.862793f, 0.874512f, 0.884277f, 0.894043f, 0.901855f, 0.909180f, 0.915039f, 0.921387f, 0.926270f, 0.932129f, 0.936035f, + 0.940430f, 0.944336f, 0.948242f, 0.951660f, 0.954590f, 0.957520f, 0.959961f, 0.962891f, 0.965332f, 0.967285f, 0.969727f, 0.971680f, + 0.973145f, 0.975586f, 0.977051f, 0.979004f, 0.979980f, 0.981934f, 0.983887f, 0.984375f, 0.985840f, 0.986816f, 0.988770f, 0.989258f, + 0.990723f, 0.992188f, 0.992676f, 0.993652f, 0.994629f, 0.995605f, 0.996582f, 0.997559f, 0.998535f, 0.999023f, 0.999512f, 0.999023f, + 0.998535f, 0.998047f, 0.997559f, 0.997070f, 0.046997f, 0.153564f, 0.264160f, 0.369385f, 0.460205f, 0.538574f, 0.602051f, 0.654785f, + 0.697754f, 0.733398f, 0.762695f, 0.787598f, 0.809082f, 0.827637f, 0.843262f, 0.856934f, 0.868652f, 0.880859f, 0.889648f, 0.898438f, + 0.906738f, 0.912598f, 0.918945f, 0.924805f, 0.929688f, 0.935059f, 0.938965f, 0.943359f, 0.947266f, 0.951172f, 0.954102f, 0.956543f, + 0.959961f, 0.961914f, 0.964844f, 0.966797f, 0.969727f, 0.971191f, 0.974121f, 0.975098f, 0.977051f, 0.979492f, 0.980469f, 0.981934f, + 0.983887f, 0.985352f, 0.985840f, 0.987305f, 0.989258f, 0.990234f, 0.991211f, 0.992188f, 0.993164f, 0.994141f, 0.995117f, 0.996094f, + 0.996582f, 0.997559f, 0.999023f, 0.998535f, 0.998047f, 0.997559f, 0.997070f, 0.997070f, 0.025940f, 0.088501f, 0.162964f, 0.246094f, + 0.331055f, 0.411865f, 0.486328f, 0.550293f, 0.606934f, 0.655762f, 0.695312f, 0.729980f, 0.758301f, 0.783691f, 0.804199f, 0.823730f, + 0.838867f, 0.853027f, 0.865723f, 0.877441f, 0.887207f, 0.895996f, 0.904785f, 0.911133f, 0.916992f, 0.923828f, 0.928223f, 0.933594f, + 0.937988f, 0.942871f, 0.946777f, 0.950195f, 0.953613f, 0.956543f, 0.959473f, 0.962402f, 0.964844f, 0.967285f, 0.970215f, 0.971680f, + 0.973633f, 0.976074f, 0.977539f, 0.979492f, 0.980469f, 0.982422f, 0.984863f, 0.985352f, 0.986816f, 0.987793f, 0.989258f, 0.990234f, + 0.991699f, 0.992676f, 0.994141f, 0.995117f, 0.995605f, 0.996582f, 0.998535f, 0.998047f, 0.998047f, 0.997559f, 0.997070f, 0.996582f, + 0.016159f, 0.055176f, 0.104126f, 0.162720f, 0.229126f, 0.300781f, 0.372803f, 0.442871f, 0.506836f, 0.563477f, 0.613281f, 0.657715f, + 0.696289f, 0.729004f, 0.757324f, 0.782227f, 0.802734f, 0.821289f, 0.837402f, 0.852539f, 0.865234f, 0.875977f, 0.885742f, 0.895508f, + 0.903320f, 0.910156f, 0.917480f, 0.922852f, 0.928711f, 0.934082f, 0.937988f, 0.942871f, 0.947266f, 0.950195f, 0.954102f, 0.957031f, + 0.959473f, 0.962402f, 0.964844f, 0.968262f, 0.969727f, 0.972168f, 0.974121f, 0.976562f, 0.978516f, 0.979980f, 0.981934f, 0.982910f, + 0.983887f, 0.985840f, 0.986816f, 0.988770f, 0.989746f, 0.991211f, 0.992188f, 0.993652f, 0.994141f, 0.995117f, 0.998047f, 0.997559f, + 0.997559f, 0.997070f, 0.996582f, 0.996582f, 0.010841f, 0.036865f, 0.070007f, 0.110962f, 0.159546f, 0.214355f, 0.276367f, 0.340576f, + 0.405029f, 0.465820f, 0.523926f, 0.576172f, 0.623535f, 0.664062f, 0.699707f, 0.731445f, 0.758301f, 0.782227f, 0.803223f, 0.821289f, + 0.837891f, 0.852051f, 0.864258f, 0.875488f, 0.884766f, 0.894531f, 0.903320f, 0.910156f, 0.916992f, 0.923828f, 0.928223f, 0.933594f, + 0.938477f, 0.943359f, 0.947266f, 0.950684f, 0.954102f, 0.957520f, 0.960449f, 0.962891f, 0.965820f, 0.968750f, 0.971191f, 0.973145f, + 0.975586f, 0.977539f, 0.978516f, 0.980957f, 0.982422f, 0.984375f, 0.985352f, 0.987305f, 0.988281f, 0.989746f, 0.990723f, 0.992188f, + 0.993164f, 0.994141f, 0.997559f, 0.997559f, 0.997070f, 0.996582f, 0.996582f, 0.996094f, 0.007637f, 0.026566f, 0.049896f, 0.078247f, + 0.113403f, 0.154663f, 0.202637f, 0.255371f, 0.313232f, 0.372314f, 0.431152f, 0.488037f, 0.540039f, 0.588867f, 0.633301f, 0.670898f, + 0.704102f, 0.734375f, 0.761230f, 0.785156f, 0.804688f, 0.822754f, 0.838867f, 0.852539f, 0.864746f, 0.876953f, 0.886230f, 0.895996f, + 0.903320f, 0.910645f, 0.917480f, 0.923828f, 0.929199f, 0.935059f, 0.938965f, 0.943359f, 0.948730f, 0.952148f, 0.954590f, 0.958496f, + 0.961426f, 0.964355f, 0.966797f, 0.969238f, 0.971680f, 0.974121f, 0.976074f, 0.978027f, 0.979980f, 0.981445f, 0.982910f, 0.984863f, + 0.986816f, 0.987793f, 0.989258f, 0.990723f, 0.991699f, 0.993164f, 0.996582f, 0.996582f, 0.996094f, 0.996094f, 0.996094f, 0.995605f, + 0.005714f, 0.019485f, 0.036194f, 0.056976f, 0.082336f, 0.113342f, 0.149048f, 0.191284f, 0.238770f, 0.290039f, 0.344727f, 0.400391f, + 0.454590f, 0.507324f, 0.557129f, 0.602539f, 0.642578f, 0.679199f, 0.711426f, 0.740234f, 0.766602f, 0.788574f, 0.807617f, 0.825195f, + 0.841309f, 0.854980f, 0.867676f, 0.877930f, 0.888184f, 0.896484f, 0.904785f, 0.912109f, 0.918945f, 0.925293f, 0.930176f, 0.935547f, + 0.940918f, 0.944336f, 0.948730f, 0.952637f, 0.956055f, 0.959473f, 0.962402f, 0.965332f, 0.967773f, 0.970703f, 0.972656f, 0.975098f, + 0.977051f, 0.979004f, 0.981445f, 0.982910f, 0.984375f, 0.985840f, 0.987793f, 0.989258f, 0.990234f, 0.991211f, 0.996094f, 0.996094f, + 0.996094f, 0.996094f, 0.995605f, 0.995117f, 0.004505f, 0.014908f, 0.027634f, 0.043274f, 0.061707f, 0.084045f, 0.111694f, 0.143921f, + 0.180542f, 0.223877f, 0.270996f, 0.320557f, 0.373291f, 0.425781f, 0.478027f, 0.526855f, 0.573242f, 0.615723f, 0.654785f, 0.688965f, + 0.720215f, 0.747559f, 0.771973f, 0.793457f, 0.812500f, 0.829102f, 0.844238f, 0.858398f, 0.870117f, 0.881348f, 0.890625f, 0.898926f, + 0.906738f, 0.914062f, 0.921387f, 0.926758f, 0.932617f, 0.937500f, 0.942383f, 0.945801f, 0.950684f, 0.954102f, 0.958008f, 0.960938f, + 0.964355f, 0.966797f, 0.969727f, 0.972656f, 0.974609f, 0.976562f, 0.978516f, 0.980469f, 0.981934f, 0.984375f, 0.985840f, 0.987793f, + 0.988281f, 0.990234f, 0.995605f, 0.995605f, 0.995605f, 0.995605f, 0.995117f, 0.994629f, 0.003691f, 0.011925f, 0.021622f, 0.033203f, + 0.047241f, 0.065247f, 0.085266f, 0.109558f, 0.138550f, 0.172363f, 0.210205f, 0.253418f, 0.299805f, 0.348877f, 0.400146f, 0.450195f, + 0.499512f, 0.546387f, 0.589844f, 0.629883f, 0.666016f, 0.700195f, 0.728516f, 0.755371f, 0.778320f, 0.798828f, 0.817383f, 0.833984f, + 0.848145f, 0.861816f, 0.874023f, 0.883789f, 0.893555f, 0.902344f, 0.910645f, 0.916992f, 0.922852f, 0.929688f, 0.934570f, 0.938965f, + 0.944336f, 0.948730f, 0.951660f, 0.956543f, 0.959473f, 0.962891f, 0.965820f, 0.968262f, 0.970703f, 0.974121f, 0.976074f, 0.978516f, + 0.979980f, 0.981934f, 0.983887f, 0.985840f, 0.987305f, 0.988281f, 0.994629f, 0.995117f, 0.995117f, 0.994629f, 0.994629f, 0.994141f, + 0.002726f, 0.009560f, 0.017136f, 0.026871f, 0.037415f, 0.050079f, 0.066406f, 0.084717f, 0.107849f, 0.133423f, 0.164062f, 0.198853f, + 0.238281f, 0.281250f, 0.327148f, 0.375977f, 0.424805f, 0.473877f, 0.521973f, 0.564941f, 0.606934f, 0.644531f, 0.679199f, 0.710449f, + 0.738770f, 0.764160f, 0.786133f, 0.805664f, 0.824219f, 0.838867f, 0.853516f, 0.866211f, 0.876953f, 0.887695f, 0.896484f, 0.905762f, + 0.912598f, 0.919922f, 0.925781f, 0.932129f, 0.937500f, 0.942383f, 0.946777f, 0.951660f, 0.955078f, 0.958984f, 0.961426f, 0.965332f, + 0.967773f, 0.970703f, 0.972656f, 0.975586f, 0.978027f, 0.979492f, 0.981934f, 0.983887f, 0.984863f, 0.986816f, 0.994629f, 0.994629f, + 0.994629f, 0.994141f, 0.994141f, 0.993652f, 0.002487f, 0.007553f, 0.013863f, 0.021439f, 0.029755f, 0.040771f, 0.052643f, 0.067444f, + 0.084473f, 0.104980f, 0.128784f, 0.157227f, 0.189087f, 0.224609f, 0.265381f, 0.308838f, 0.354004f, 0.401611f, 0.450439f, 0.496582f, + 0.541992f, 0.583984f, 0.623047f, 0.660645f, 0.693359f, 0.722168f, 0.749512f, 0.772949f, 0.793457f, 0.812988f, 0.830078f, 0.845215f, + 0.859375f, 0.871094f, 0.882812f, 0.892090f, 0.900879f, 0.908691f, 0.916504f, 0.922852f, 0.930176f, 0.935547f, 0.940430f, 0.944824f, + 0.949219f, 0.952637f, 0.956543f, 0.960449f, 0.963867f, 0.967285f, 0.970215f, 0.972656f, 0.974609f, 0.977539f, 0.979492f, 0.981934f, + 0.983887f, 0.985352f, 0.993652f, 0.994141f, 0.994141f, 0.993652f, 0.993652f, 0.993164f, 0.001893f, 0.006641f, 0.011551f, 0.017319f, + 0.024612f, 0.032959f, 0.042023f, 0.053772f, 0.067444f, 0.083435f, 0.102356f, 0.123840f, 0.150024f, 0.179688f, 0.213501f, 0.250488f, + 0.291992f, 0.335938f, 0.381592f, 0.427246f, 0.473877f, 0.518555f, 0.563477f, 0.603027f, 0.640625f, 0.676270f, 0.707031f, 0.735352f, + 0.760254f, 0.782715f, 0.802734f, 0.821777f, 0.838379f, 0.851562f, 0.865234f, 0.876953f, 0.886719f, 0.896484f, 0.905273f, 0.913086f, + 0.921387f, 0.927734f, 0.933105f, 0.938477f, 0.942871f, 0.948242f, 0.951660f, 0.955566f, 0.959961f, 0.963867f, 0.966309f, 0.969238f, + 0.972168f, 0.975098f, 0.977539f, 0.979492f, 0.981934f, 0.983887f, 0.993164f, 0.993652f, 0.993164f, 0.993164f, 0.993164f, 0.992676f, + 0.001740f, 0.005634f, 0.009407f, 0.014992f, 0.020157f, 0.026840f, 0.035156f, 0.043793f, 0.054718f, 0.067505f, 0.082092f, 0.099731f, + 0.120239f, 0.143921f, 0.171265f, 0.202393f, 0.237915f, 0.276367f, 0.318848f, 0.362793f, 0.407959f, 0.454346f, 0.499023f, 0.542480f, + 0.583984f, 0.623535f, 0.659180f, 0.691895f, 0.721680f, 0.748047f, 0.772461f, 0.793457f, 0.812988f, 0.829102f, 0.845215f, 0.859863f, + 0.872559f, 0.883789f, 0.893555f, 0.902344f, 0.911133f, 0.918457f, 0.924805f, 0.930664f, 0.937012f, 0.941895f, 0.947266f, 0.951172f, + 0.956055f, 0.959473f, 0.962402f, 0.966309f, 0.968750f, 0.972168f, 0.974609f, 0.977051f, 0.979492f, 0.981934f, 0.992188f, 0.992676f, + 0.992676f, 0.992676f, 0.992188f, 0.992676f, 0.001502f, 0.004482f, 0.008278f, 0.012276f, 0.016800f, 0.022644f, 0.029129f, 0.036194f, + 0.045197f, 0.055298f, 0.067017f, 0.080750f, 0.096863f, 0.115906f, 0.138184f, 0.163940f, 0.192993f, 0.225952f, 0.262695f, 0.302490f, + 0.344971f, 0.389648f, 0.434814f, 0.480469f, 0.523926f, 0.566406f, 0.605957f, 0.643066f, 0.677246f, 0.708496f, 0.736816f, 0.761719f, + 0.784668f, 0.804688f, 0.823242f, 0.840332f, 0.854004f, 0.867188f, 0.878906f, 0.890137f, 0.898438f, 0.907715f, 0.916016f, 0.922852f, + 0.930176f, 0.935547f, 0.940918f, 0.946289f, 0.950684f, 0.955078f, 0.959473f, 0.961914f, 0.966309f, 0.969238f, 0.972168f, 0.974609f, + 0.977539f, 0.979492f, 0.991211f, 0.992188f, 0.991699f, 0.992188f, 0.991699f, 0.991211f, 0.001411f, 0.003645f, 0.007160f, 0.010414f, + 0.014397f, 0.018677f, 0.024338f, 0.030426f, 0.037384f, 0.045654f, 0.055054f, 0.066101f, 0.079529f, 0.094543f, 0.112793f, 0.133057f, + 0.157227f, 0.183960f, 0.215210f, 0.250488f, 0.288086f, 0.329102f, 0.372314f, 0.416992f, 0.461914f, 0.505859f, 0.549316f, 0.589355f, + 0.627930f, 0.664062f, 0.695801f, 0.725098f, 0.752441f, 0.775879f, 0.797363f, 0.815918f, 0.833984f, 0.849121f, 0.863281f, 0.875488f, + 0.886230f, 0.895996f, 0.904785f, 0.914062f, 0.920898f, 0.928223f, 0.935059f, 0.940918f, 0.945312f, 0.950195f, 0.954102f, 0.958984f, + 0.962402f, 0.966309f, 0.969238f, 0.972656f, 0.974609f, 0.977539f, 0.990234f, 0.992188f, 0.991211f, 0.991211f, 0.990723f, 0.991211f, + 0.000926f, 0.003523f, 0.006207f, 0.008949f, 0.012718f, 0.016312f, 0.020447f, 0.025467f, 0.031128f, 0.037994f, 0.045532f, 0.054901f, + 0.065430f, 0.077576f, 0.091797f, 0.109131f, 0.128418f, 0.151245f, 0.176636f, 0.206055f, 0.238525f, 0.275146f, 0.314697f, 0.357178f, + 0.400391f, 0.445312f, 0.489746f, 0.531738f, 0.574219f, 0.613281f, 0.650391f, 0.683594f, 0.714355f, 0.742188f, 0.768066f, 0.790039f, + 0.810059f, 0.828125f, 0.843262f, 0.858398f, 0.871582f, 0.883789f, 0.893555f, 0.903809f, 0.912598f, 0.919434f, 0.926758f, 0.933594f, + 0.939453f, 0.944336f, 0.950195f, 0.954590f, 0.958008f, 0.962402f, 0.966309f, 0.969727f, 0.972656f, 0.975586f, 0.989746f, 0.990723f, + 0.990723f, 0.990234f, 0.990234f, 0.990234f, 0.001140f, 0.003021f, 0.005527f, 0.008102f, 0.010445f, 0.013977f, 0.017349f, 0.021637f, + 0.026535f, 0.031677f, 0.038330f, 0.045776f, 0.054382f, 0.064392f, 0.076233f, 0.089844f, 0.105713f, 0.123840f, 0.145020f, 0.169556f, + 0.196899f, 0.229248f, 0.263672f, 0.302002f, 0.342529f, 0.385986f, 0.429932f, 0.473877f, 0.517578f, 0.560547f, 0.600586f, 0.638184f, + 0.672852f, 0.704590f, 0.733398f, 0.759277f, 0.782715f, 0.803711f, 0.823242f, 0.840820f, 0.854980f, 0.869141f, 0.881348f, 0.892090f, + 0.902344f, 0.910645f, 0.919922f, 0.927246f, 0.933105f, 0.938965f, 0.944824f, 0.949707f, 0.954102f, 0.959473f, 0.962891f, 0.966309f, + 0.969727f, 0.972168f, 0.988770f, 0.990234f, 0.989746f, 0.989746f, 0.989746f, 0.989258f, 0.000870f, 0.002666f, 0.004578f, 0.006737f, + 0.009430f, 0.012077f, 0.015381f, 0.018463f, 0.022293f, 0.027313f, 0.032654f, 0.038727f, 0.045746f, 0.053619f, 0.063232f, 0.074524f, + 0.087219f, 0.102356f, 0.119324f, 0.139648f, 0.162842f, 0.189941f, 0.219482f, 0.253174f, 0.289795f, 0.329346f, 0.372070f, 0.415039f, + 0.459717f, 0.503418f, 0.546387f, 0.587402f, 0.625977f, 0.661621f, 0.694336f, 0.725586f, 0.752441f, 0.776855f, 0.798828f, 0.818359f, + 0.837402f, 0.852539f, 0.866699f, 0.878906f, 0.891113f, 0.900879f, 0.910156f, 0.918457f, 0.926270f, 0.932617f, 0.938965f, 0.944824f, + 0.950195f, 0.955078f, 0.958984f, 0.962891f, 0.966797f, 0.970703f, 0.987793f, 0.988770f, 0.989258f, 0.989258f, 0.988770f, 0.988770f, + 0.000835f, 0.002302f, 0.004078f, 0.005802f, 0.008026f, 0.010490f, 0.013153f, 0.016235f, 0.019485f, 0.023636f, 0.027847f, 0.033081f, + 0.038849f, 0.045441f, 0.053253f, 0.062500f, 0.072571f, 0.085205f, 0.098999f, 0.115662f, 0.135254f, 0.156860f, 0.182373f, 0.211060f, + 0.243042f, 0.279053f, 0.318115f, 0.359619f, 0.402832f, 0.447021f, 0.490234f, 0.533691f, 0.575195f, 0.615234f, 0.651855f, 0.686035f, + 0.717285f, 0.746094f, 0.771484f, 0.793945f, 0.813965f, 0.833496f, 0.848633f, 0.864258f, 0.877930f, 0.889648f, 0.900391f, 0.909180f, + 0.918945f, 0.926270f, 0.932129f, 0.939453f, 0.945312f, 0.950684f, 0.955566f, 0.959473f, 0.963867f, 0.967773f, 0.987305f, 0.988281f, + 0.988281f, 0.988281f, 0.988281f, 0.987793f, 0.000815f, 0.001984f, 0.003475f, 0.005302f, 0.007103f, 0.009354f, 0.011528f, 0.013977f, + 0.017197f, 0.020111f, 0.023788f, 0.027771f, 0.033447f, 0.038452f, 0.045013f, 0.052704f, 0.061066f, 0.071228f, 0.082886f, 0.096313f, + 0.112488f, 0.130737f, 0.151245f, 0.175659f, 0.203125f, 0.234619f, 0.269043f, 0.306885f, 0.347656f, 0.390381f, 0.434570f, 0.478760f, + 0.522461f, 0.564453f, 0.605957f, 0.644043f, 0.678223f, 0.710449f, 0.739746f, 0.766602f, 0.791016f, 0.811035f, 0.831055f, 0.847168f, + 0.862793f, 0.875977f, 0.888672f, 0.899414f, 0.909180f, 0.917480f, 0.926270f, 0.933105f, 0.939941f, 0.945801f, 0.950684f, 0.955566f, + 0.960938f, 0.964844f, 0.985840f, 0.987305f, 0.987793f, 0.987305f, 0.987305f, 0.987305f, 0.000587f, 0.002005f, 0.003122f, 0.004707f, + 0.006283f, 0.007778f, 0.009972f, 0.012581f, 0.014435f, 0.017426f, 0.020691f, 0.024475f, 0.028519f, 0.033203f, 0.038513f, 0.044708f, + 0.051727f, 0.060028f, 0.069763f, 0.080627f, 0.093506f, 0.109009f, 0.125977f, 0.146362f, 0.169678f, 0.196533f, 0.226685f, 0.259766f, + 0.297119f, 0.337646f, 0.380127f, 0.424072f, 0.468018f, 0.512207f, 0.555176f, 0.596680f, 0.635254f, 0.671387f, 0.704590f, 0.734863f, + 0.762207f, 0.787109f, 0.809082f, 0.828613f, 0.846191f, 0.860840f, 0.875977f, 0.888184f, 0.899902f, 0.908691f, 0.918457f, 0.926270f, + 0.934082f, 0.940430f, 0.947266f, 0.951660f, 0.958008f, 0.961914f, 0.984863f, 0.986328f, 0.986816f, 0.986816f, 0.986328f, 0.986328f, + 0.000475f, 0.001671f, 0.003019f, 0.004379f, 0.005592f, 0.006882f, 0.008682f, 0.010757f, 0.012856f, 0.015343f, 0.018112f, 0.021164f, + 0.024353f, 0.028595f, 0.033020f, 0.038086f, 0.044006f, 0.050812f, 0.058594f, 0.067993f, 0.078735f, 0.091248f, 0.105530f, 0.122009f, + 0.142212f, 0.164062f, 0.189697f, 0.219238f, 0.251953f, 0.288330f, 0.328125f, 0.369629f, 0.413818f, 0.458008f, 0.503418f, 0.547363f, + 0.588867f, 0.628418f, 0.665039f, 0.699707f, 0.730469f, 0.758301f, 0.784668f, 0.807129f, 0.826660f, 0.844727f, 0.862305f, 0.875977f, + 0.888672f, 0.900879f, 0.910156f, 0.919434f, 0.927734f, 0.935059f, 0.941406f, 0.947754f, 0.953125f, 0.958496f, 0.983887f, 0.985352f, + 0.985352f, 0.985352f, 0.984863f, 0.985352f, 0.000325f, 0.001517f, 0.002554f, 0.003811f, 0.004990f, 0.006638f, 0.007706f, 0.009399f, + 0.011177f, 0.013580f, 0.015671f, 0.018478f, 0.021393f, 0.024612f, 0.028442f, 0.032990f, 0.037750f, 0.043427f, 0.050354f, 0.057861f, + 0.066101f, 0.076294f, 0.088684f, 0.102417f, 0.119080f, 0.137451f, 0.159058f, 0.183838f, 0.212524f, 0.244385f, 0.280273f, 0.319336f, + 0.361084f, 0.405029f, 0.449707f, 0.494873f, 0.539551f, 0.582031f, 0.622559f, 0.660156f, 0.695801f, 0.727539f, 0.756348f, 0.782715f, + 0.805664f, 0.826172f, 0.845215f, 0.861328f, 0.875977f, 0.889648f, 0.901367f, 0.910645f, 0.920410f, 0.928711f, 0.937012f, 0.942871f, + 0.949219f, 0.955078f, 0.982422f, 0.983887f, 0.984375f, 0.984375f, 0.983887f, 0.983887f, 0.000349f, 0.001533f, 0.002413f, 0.003326f, + 0.004463f, 0.005524f, 0.006954f, 0.008202f, 0.010025f, 0.011864f, 0.013924f, 0.015884f, 0.018478f, 0.021484f, 0.024658f, 0.028671f, + 0.032562f, 0.037170f, 0.042969f, 0.049194f, 0.056641f, 0.065063f, 0.074951f, 0.086182f, 0.099731f, 0.115662f, 0.133789f, 0.154175f, + 0.178589f, 0.206421f, 0.237671f, 0.272949f, 0.312012f, 0.352783f, 0.396973f, 0.442627f, 0.487793f, 0.532227f, 0.576660f, 0.617188f, + 0.657227f, 0.692383f, 0.725586f, 0.754395f, 0.780762f, 0.805664f, 0.826172f, 0.845215f, 0.861816f, 0.876465f, 0.890137f, 0.902344f, + 0.912598f, 0.921875f, 0.930176f, 0.937988f, 0.945312f, 0.952148f, 0.981445f, 0.982910f, 0.982910f, 0.983398f, 0.983398f, 0.983398f, + 0.000475f, 0.001141f, 0.002058f, 0.002846f, 0.004120f, 0.005013f, 0.006207f, 0.007664f, 0.009193f, 0.010368f, 0.012222f, 0.014404f, + 0.016403f, 0.018799f, 0.021439f, 0.024567f, 0.028076f, 0.032379f, 0.036652f, 0.042145f, 0.048157f, 0.055389f, 0.063660f, 0.073059f, + 0.083740f, 0.097046f, 0.112366f, 0.129517f, 0.149780f, 0.173584f, 0.200684f, 0.231812f, 0.266357f, 0.304688f, 0.346680f, 0.390137f, + 0.435547f, 0.481445f, 0.526367f, 0.572266f, 0.613770f, 0.653320f, 0.690430f, 0.723633f, 0.754395f, 0.781250f, 0.806152f, 0.826172f, + 0.847168f, 0.862793f, 0.878906f, 0.892090f, 0.904297f, 0.914551f, 0.924316f, 0.933105f, 0.940430f, 0.947754f, 0.979492f, 0.981934f, + 0.981934f, 0.981934f, 0.981445f, 0.981445f, 0.000239f, 0.000882f, 0.001744f, 0.002878f, 0.003819f, 0.004532f, 0.005550f, 0.006653f, + 0.007942f, 0.009277f, 0.010628f, 0.012421f, 0.014397f, 0.016312f, 0.018845f, 0.021576f, 0.024536f, 0.027817f, 0.031860f, 0.036346f, + 0.041595f, 0.047333f, 0.054138f, 0.062317f, 0.071350f, 0.081970f, 0.094299f, 0.109070f, 0.126221f, 0.146118f, 0.169067f, 0.195801f, + 0.226196f, 0.260742f, 0.298584f, 0.340088f, 0.384277f, 0.429688f, 0.476807f, 0.522461f, 0.568359f, 0.611328f, 0.651855f, 0.689453f, + 0.723633f, 0.754395f, 0.782715f, 0.807617f, 0.829590f, 0.848145f, 0.865723f, 0.880859f, 0.894531f, 0.906738f, 0.917969f, 0.927246f, + 0.936035f, 0.943359f, 0.978027f, 0.979980f, 0.980469f, 0.980469f, 0.980469f, 0.980469f, 0.000240f, 0.000948f, 0.001495f, 0.002592f, + 0.003241f, 0.004055f, 0.004856f, 0.006111f, 0.007133f, 0.008125f, 0.009445f, 0.011108f, 0.012474f, 0.014374f, 0.016586f, 0.018784f, + 0.021286f, 0.024475f, 0.027481f, 0.031403f, 0.035828f, 0.040710f, 0.046204f, 0.052704f, 0.060577f, 0.069519f, 0.079651f, 0.092224f, + 0.106506f, 0.122986f, 0.142456f, 0.165161f, 0.191284f, 0.221924f, 0.255615f, 0.293457f, 0.335205f, 0.379395f, 0.425537f, 0.472900f, + 0.519531f, 0.566406f, 0.610840f, 0.652344f, 0.689941f, 0.724609f, 0.755371f, 0.784180f, 0.808594f, 0.831055f, 0.851562f, 0.869141f, + 0.884277f, 0.897461f, 0.909668f, 0.920410f, 0.930176f, 0.937988f, 0.976562f, 0.979004f, 0.979492f, 0.979492f, 0.979492f, 0.979492f, + 0.000302f, 0.000863f, 0.001315f, 0.002195f, 0.002905f, 0.003592f, 0.004784f, 0.005478f, 0.006199f, 0.007389f, 0.008545f, 0.009811f, + 0.011185f, 0.012787f, 0.014603f, 0.016342f, 0.018784f, 0.021347f, 0.024033f, 0.027496f, 0.031006f, 0.034790f, 0.039856f, 0.045288f, + 0.051636f, 0.059052f, 0.067566f, 0.078003f, 0.089905f, 0.103760f, 0.119934f, 0.139282f, 0.161865f, 0.187622f, 0.217407f, 0.251221f, + 0.288818f, 0.330811f, 0.375244f, 0.422607f, 0.470703f, 0.518066f, 0.565430f, 0.609863f, 0.651855f, 0.691406f, 0.726562f, 0.758301f, + 0.787109f, 0.812500f, 0.835449f, 0.855957f, 0.872559f, 0.887695f, 0.901367f, 0.913574f, 0.923828f, 0.933105f, 0.975098f, 0.977539f, + 0.977539f, 0.977539f, 0.978027f, 0.977051f, 0.000240f, 0.000808f, 0.001537f, 0.002106f, 0.002493f, 0.003729f, 0.004036f, 0.004982f, + 0.005539f, 0.006454f, 0.007526f, 0.008690f, 0.009987f, 0.011421f, 0.012894f, 0.014618f, 0.016464f, 0.018539f, 0.021118f, 0.023865f, + 0.026794f, 0.030487f, 0.034241f, 0.038879f, 0.044067f, 0.050690f, 0.057678f, 0.066040f, 0.076111f, 0.087524f, 0.101379f, 0.117737f, + 0.136353f, 0.158325f, 0.183594f, 0.213501f, 0.247192f, 0.284912f, 0.327393f, 0.372803f, 0.420410f, 0.468750f, 0.518066f, 0.565430f, + 0.611328f, 0.654297f, 0.694336f, 0.729980f, 0.762207f, 0.791504f, 0.817383f, 0.839844f, 0.859863f, 0.876953f, 0.891602f, 0.905762f, + 0.917480f, 0.928711f, 0.973633f, 0.975098f, 0.976562f, 0.975586f, 0.976562f, 0.976562f, 0.000240f, 0.000587f, 0.001223f, 0.001691f, + 0.002499f, 0.003008f, 0.003643f, 0.004295f, 0.004795f, 0.005726f, 0.006649f, 0.007671f, 0.008766f, 0.010002f, 0.011307f, 0.012764f, + 0.014465f, 0.016388f, 0.018387f, 0.020599f, 0.023453f, 0.026291f, 0.029572f, 0.033417f, 0.037964f, 0.043427f, 0.049316f, 0.056519f, + 0.064819f, 0.074219f, 0.085693f, 0.099121f, 0.115112f, 0.133301f, 0.155273f, 0.180420f, 0.210205f, 0.244751f, 0.282715f, 0.324951f, + 0.371338f, 0.419434f, 0.468994f, 0.518555f, 0.566895f, 0.613770f, 0.658203f, 0.698242f, 0.735352f, 0.766602f, 0.796875f, 0.821289f, + 0.844238f, 0.863770f, 0.881836f, 0.896973f, 0.910156f, 0.922363f, 0.971191f, 0.974121f, 0.974609f, 0.974121f, 0.974609f, 0.974609f, + 0.000228f, 0.000671f, 0.001122f, 0.001607f, 0.002291f, 0.002836f, 0.003319f, 0.003817f, 0.004509f, 0.005253f, 0.005894f, 0.006840f, + 0.007820f, 0.008972f, 0.010086f, 0.011391f, 0.012848f, 0.014328f, 0.016266f, 0.018158f, 0.020447f, 0.022720f, 0.026031f, 0.029053f, + 0.032593f, 0.037109f, 0.042236f, 0.048340f, 0.055115f, 0.063049f, 0.072632f, 0.083801f, 0.097351f, 0.112488f, 0.130493f, 0.152222f, + 0.178101f, 0.208008f, 0.241943f, 0.280762f, 0.323730f, 0.370117f, 0.419434f, 0.470459f, 0.520996f, 0.570801f, 0.617676f, 0.663086f, + 0.704102f, 0.740234f, 0.773438f, 0.802246f, 0.829102f, 0.850098f, 0.870117f, 0.887695f, 0.902832f, 0.916016f, 0.969238f, 0.972168f, + 0.972168f, 0.972656f, 0.972656f, 0.972168f, 0.000121f, 0.000526f, 0.001092f, 0.001670f, 0.001744f, 0.002420f, 0.002945f, 0.003237f, + 0.004013f, 0.004894f, 0.005421f, 0.005932f, 0.006996f, 0.007904f, 0.008873f, 0.009995f, 0.011391f, 0.012756f, 0.014053f, 0.015884f, + 0.017715f, 0.019775f, 0.022324f, 0.025406f, 0.028290f, 0.032349f, 0.036560f, 0.041412f, 0.047058f, 0.053772f, 0.061493f, 0.070862f, + 0.081848f, 0.094666f, 0.110229f, 0.128662f, 0.150024f, 0.175903f, 0.205566f, 0.239990f, 0.279785f, 0.323486f, 0.370850f, 0.421143f, + 0.473633f, 0.524902f, 0.576172f, 0.625000f, 0.668457f, 0.710938f, 0.748535f, 0.781250f, 0.810059f, 0.835449f, 0.857910f, 0.877441f, + 0.894531f, 0.908691f, 0.966797f, 0.970215f, 0.970703f, 0.970703f, 0.970703f, 0.970215f, 0.000127f, 0.000521f, 0.001083f, 0.001460f, + 0.001684f, 0.002111f, 0.002563f, 0.003048f, 0.003618f, 0.004124f, 0.004936f, 0.005543f, 0.006340f, 0.007111f, 0.008049f, 0.008774f, + 0.009865f, 0.011162f, 0.012360f, 0.013840f, 0.015465f, 0.017181f, 0.019531f, 0.021973f, 0.024582f, 0.027847f, 0.031342f, 0.035706f, + 0.040100f, 0.045990f, 0.052521f, 0.060089f, 0.069214f, 0.080017f, 0.093079f, 0.108521f, 0.126709f, 0.148071f, 0.174072f, 0.204224f, + 0.239502f, 0.279541f, 0.324219f, 0.373047f, 0.424805f, 0.477295f, 0.530762f, 0.583008f, 0.632324f, 0.677246f, 0.719727f, 0.756348f, + 0.789551f, 0.819336f, 0.842773f, 0.866211f, 0.885742f, 0.901855f, 0.965332f, 0.967773f, 0.968262f, 0.967773f, 0.968750f, 0.968262f, + 0.000244f, 0.000397f, 0.001001f, 0.001181f, 0.001642f, 0.001872f, 0.002460f, 0.002712f, 0.003061f, 0.003723f, 0.004520f, 0.005043f, + 0.005547f, 0.006451f, 0.007057f, 0.007828f, 0.008942f, 0.009872f, 0.010857f, 0.012131f, 0.013557f, 0.015198f, 0.017059f, 0.019241f, + 0.021454f, 0.024048f, 0.027069f, 0.030594f, 0.034332f, 0.039001f, 0.044952f, 0.050873f, 0.058716f, 0.067505f, 0.078369f, 0.091309f, + 0.106506f, 0.124695f, 0.146484f, 0.172852f, 0.203369f, 0.239014f, 0.280273f, 0.326172f, 0.376465f, 0.429443f, 0.483643f, 0.538574f, + 0.591309f, 0.641602f, 0.687500f, 0.729492f, 0.766602f, 0.800293f, 0.828613f, 0.854004f, 0.874512f, 0.893555f, 0.961914f, 0.965332f, + 0.965820f, 0.966309f, 0.966309f, 0.965820f, 0.000243f, 0.000453f, 0.000888f, 0.001245f, 0.001342f, 0.001847f, 0.002060f, 0.002541f, + 0.002991f, 0.003355f, 0.003679f, 0.004379f, 0.005177f, 0.005413f, 0.006283f, 0.007038f, 0.007896f, 0.008507f, 0.009552f, 0.010628f, + 0.011909f, 0.013306f, 0.015038f, 0.016388f, 0.018433f, 0.020752f, 0.023254f, 0.026413f, 0.029617f, 0.033447f, 0.037842f, 0.043701f, + 0.049896f, 0.057190f, 0.066101f, 0.076660f, 0.089600f, 0.104553f, 0.123230f, 0.145386f, 0.171387f, 0.202637f, 0.239624f, 0.281982f, + 0.329346f, 0.380859f, 0.436035f, 0.491943f, 0.547852f, 0.602539f, 0.653809f, 0.699707f, 0.741699f, 0.778320f, 0.811035f, 0.838867f, + 0.862793f, 0.884766f, 0.959961f, 0.963379f, 0.963379f, 0.963379f, 0.964355f, 0.963379f, 0.000241f, 0.000452f, 0.000798f, 0.001119f, + 0.001220f, 0.001430f, 0.001902f, 0.002277f, 0.002737f, 0.002893f, 0.003624f, 0.003937f, 0.004436f, 0.005089f, 0.005669f, 0.006226f, + 0.006680f, 0.007519f, 0.008568f, 0.009384f, 0.010422f, 0.011795f, 0.012840f, 0.014526f, 0.016235f, 0.017929f, 0.020218f, 0.022736f, + 0.025146f, 0.028580f, 0.032684f, 0.036896f, 0.042511f, 0.048431f, 0.055634f, 0.064453f, 0.075317f, 0.088196f, 0.103333f, 0.121948f, + 0.144287f, 0.171143f, 0.203491f, 0.241577f, 0.285156f, 0.334229f, 0.387939f, 0.444580f, 0.501953f, 0.559570f, 0.614746f, 0.666504f, + 0.712402f, 0.755371f, 0.791504f, 0.823242f, 0.851074f, 0.875000f, 0.956543f, 0.959961f, 0.960938f, 0.960449f, 0.960449f, 0.960449f, + 0.000000f, 0.000263f, 0.000693f, 0.000873f, 0.001183f, 0.001447f, 0.001476f, 0.002068f, 0.002171f, 0.002857f, 0.003164f, 0.003542f, + 0.003778f, 0.004326f, 0.004906f, 0.005436f, 0.006126f, 0.006687f, 0.007229f, 0.008377f, 0.009232f, 0.010223f, 0.011436f, 0.012527f, + 0.013832f, 0.015747f, 0.017365f, 0.019363f, 0.021667f, 0.024231f, 0.027695f, 0.031769f, 0.035889f, 0.041016f, 0.047028f, 0.054504f, + 0.063110f, 0.073975f, 0.086487f, 0.101807f, 0.120972f, 0.143555f, 0.171753f, 0.204956f, 0.244263f, 0.289551f, 0.340576f, 0.396484f, + 0.455078f, 0.514648f, 0.573730f, 0.630371f, 0.681152f, 0.729004f, 0.770020f, 0.806641f, 0.837402f, 0.863770f, 0.953613f, 0.956543f, + 0.957520f, 0.957031f, 0.957031f, 0.958008f, 0.000000f, 0.000356f, 0.000641f, 0.000870f, 0.000998f, 0.001134f, 0.001495f, 0.001724f, + 0.002436f, 0.002478f, 0.002775f, 0.003113f, 0.003435f, 0.003864f, 0.004314f, 0.004704f, 0.005276f, 0.005886f, 0.006599f, 0.007309f, + 0.008003f, 0.008987f, 0.009987f, 0.010941f, 0.012192f, 0.013466f, 0.015030f, 0.016708f, 0.018906f, 0.021103f, 0.023788f, 0.026886f, + 0.030457f, 0.034943f, 0.040009f, 0.045959f, 0.053162f, 0.061920f, 0.072144f, 0.085205f, 0.101257f, 0.120422f, 0.143555f, 0.172363f, + 0.206909f, 0.248047f, 0.295410f, 0.349121f, 0.407715f, 0.468750f, 0.530762f, 0.589844f, 0.647949f, 0.699707f, 0.746094f, 0.786621f, + 0.823242f, 0.852051f, 0.950195f, 0.953125f, 0.954102f, 0.954102f, 0.954102f, 0.954102f, 0.000231f, 0.000449f, 0.000516f, 0.000760f, + 0.000868f, 0.001152f, 0.001403f, 0.001773f, 0.002165f, 0.002245f, 0.002550f, 0.002783f, 0.003277f, 0.003660f, 0.003782f, 0.004120f, + 0.004631f, 0.005268f, 0.005795f, 0.006344f, 0.007053f, 0.007835f, 0.008598f, 0.009460f, 0.010689f, 0.011551f, 0.012726f, 0.014359f, + 0.016052f, 0.017975f, 0.020218f, 0.022812f, 0.025803f, 0.029251f, 0.033386f, 0.038574f, 0.044556f, 0.051941f, 0.060577f, 0.071045f, + 0.084106f, 0.100342f, 0.119751f, 0.144043f, 0.174194f, 0.209961f, 0.253418f, 0.303467f, 0.359619f, 0.420898f, 0.483887f, 0.547852f, + 0.609375f, 0.667480f, 0.719727f, 0.765625f, 0.804688f, 0.839844f, 0.946289f, 0.949707f, 0.950195f, 0.950684f, 0.950684f, 0.950195f, + 0.000201f, 0.000336f, 0.000452f, 0.000627f, 0.000793f, 0.000966f, 0.001134f, 0.001578f, 0.001790f, 0.001896f, 0.002254f, 0.002464f, + 0.002825f, 0.003012f, 0.003414f, 0.003626f, 0.004131f, 0.004608f, 0.005058f, 0.005642f, 0.006191f, 0.006771f, 0.007378f, 0.008057f, + 0.009132f, 0.009918f, 0.010826f, 0.012314f, 0.013794f, 0.015381f, 0.017197f, 0.019257f, 0.021912f, 0.024841f, 0.028259f, 0.032318f, + 0.037262f, 0.043427f, 0.050537f, 0.059021f, 0.070007f, 0.083191f, 0.099609f, 0.120239f, 0.145508f, 0.176636f, 0.214600f, 0.260254f, + 0.313232f, 0.372803f, 0.437012f, 0.503418f, 0.568359f, 0.631836f, 0.688965f, 0.741211f, 0.786621f, 0.825195f, 0.941406f, 0.946289f, + 0.946289f, 0.946777f, 0.946289f, 0.947266f, 0.000000f, 0.000317f, 0.000445f, 0.000453f, 0.000781f, 0.000794f, 0.001183f, 0.001289f, + 0.001479f, 0.001832f, 0.001874f, 0.002256f, 0.002270f, 0.002716f, 0.002960f, 0.003273f, 0.003630f, 0.003948f, 0.004467f, 0.004833f, + 0.005451f, 0.005962f, 0.006367f, 0.007088f, 0.007717f, 0.008400f, 0.009506f, 0.010445f, 0.011658f, 0.012993f, 0.014618f, 0.016357f, + 0.018524f, 0.021210f, 0.023712f, 0.027252f, 0.031219f, 0.036041f, 0.041962f, 0.049194f, 0.057892f, 0.068604f, 0.082642f, 0.099304f, + 0.120728f, 0.147217f, 0.180054f, 0.221191f, 0.269287f, 0.325928f, 0.388916f, 0.457275f, 0.525391f, 0.593262f, 0.657715f, 0.714355f, + 0.766113f, 0.809082f, 0.937500f, 0.940918f, 0.941895f, 0.941895f, 0.941895f, 0.942383f, 0.000243f, 0.000238f, 0.000411f, 0.000532f, + 0.000530f, 0.000764f, 0.000853f, 0.001171f, 0.001417f, 0.001545f, 0.001799f, 0.001900f, 0.002094f, 0.002354f, 0.002577f, 0.002703f, + 0.003155f, 0.003428f, 0.003809f, 0.004227f, 0.004677f, 0.004997f, 0.005386f, 0.005913f, 0.006741f, 0.007225f, 0.008057f, 0.008873f, + 0.009819f, 0.011101f, 0.012253f, 0.013725f, 0.015488f, 0.017410f, 0.019791f, 0.022598f, 0.025635f, 0.030014f, 0.034973f, 0.040527f, + 0.047729f, 0.056702f, 0.067505f, 0.081848f, 0.099609f, 0.121521f, 0.149902f, 0.185181f, 0.228516f, 0.280762f, 0.341553f, 0.408936f, + 0.480225f, 0.552246f, 0.622070f, 0.686035f, 0.742188f, 0.792480f, 0.932129f, 0.935547f, 0.937012f, 0.937012f, 0.936523f, 0.937500f, + 0.000000f, 0.000232f, 0.000330f, 0.000512f, 0.000523f, 0.000907f, 0.000953f, 0.001018f, 0.001234f, 0.001344f, 0.001610f, 0.001612f, + 0.001845f, 0.002054f, 0.002218f, 0.002453f, 0.002829f, 0.003105f, 0.003300f, 0.003712f, 0.003853f, 0.004280f, 0.004631f, 0.005112f, + 0.005665f, 0.006279f, 0.006779f, 0.007481f, 0.008362f, 0.009270f, 0.010338f, 0.011505f, 0.012848f, 0.014549f, 0.016403f, 0.018936f, + 0.021622f, 0.024750f, 0.028900f, 0.033447f, 0.039185f, 0.046448f, 0.055603f, 0.067078f, 0.081238f, 0.100037f, 0.123230f, 0.153564f, + 0.191284f, 0.238525f, 0.295166f, 0.361084f, 0.432861f, 0.507812f, 0.582520f, 0.653320f, 0.717285f, 0.772461f, 0.926270f, 0.931152f, + 0.931152f, 0.932129f, 0.932129f, 0.932129f, 0.000118f, 0.000219f, 0.000227f, 0.000405f, 0.000689f, 0.000726f, 0.000910f, 0.000847f, + 0.001072f, 0.001114f, 0.001388f, 0.001447f, 0.001656f, 0.001811f, 0.001897f, 0.002253f, 0.002373f, 0.002617f, 0.002796f, 0.003054f, + 0.003414f, 0.003681f, 0.003929f, 0.004353f, 0.004902f, 0.005322f, 0.005863f, 0.006424f, 0.007000f, 0.007755f, 0.008675f, 0.009506f, + 0.010704f, 0.012215f, 0.013557f, 0.015686f, 0.017807f, 0.020630f, 0.023376f, 0.027328f, 0.032013f, 0.038177f, 0.045288f, 0.054626f, + 0.066284f, 0.081543f, 0.100891f, 0.125977f, 0.158447f, 0.199951f, 0.251465f, 0.313965f, 0.384521f, 0.461670f, 0.540527f, 0.617188f, + 0.688965f, 0.750977f, 0.920410f, 0.924805f, 0.925781f, 0.926270f, 0.926758f, 0.925781f, 0.000230f, 0.000198f, 0.000217f, 0.000338f, + 0.000584f, 0.000786f, 0.000699f, 0.000893f, 0.000954f, 0.000959f, 0.001153f, 0.001165f, 0.001375f, 0.001545f, 0.001752f, 0.001752f, + 0.002062f, 0.002235f, 0.002399f, 0.002699f, 0.002853f, 0.002995f, 0.003372f, 0.003603f, 0.003944f, 0.004513f, 0.004704f, 0.005226f, + 0.005878f, 0.006527f, 0.006992f, 0.007889f, 0.008919f, 0.010002f, 0.011124f, 0.012604f, 0.014526f, 0.016510f, 0.019104f, 0.022308f, + 0.026077f, 0.030701f, 0.036774f, 0.044098f, 0.053558f, 0.065735f, 0.081299f, 0.101990f, 0.129517f, 0.164917f, 0.210938f, 0.268066f, + 0.336914f, 0.413818f, 0.496094f, 0.579102f, 0.657227f, 0.727539f, 0.913574f, 0.917969f, 0.918945f, 0.919434f, 0.919922f, 0.919922f, + 0.000000f, 0.000101f, 0.000214f, 0.000208f, 0.000339f, 0.000461f, 0.000577f, 0.000780f, 0.000777f, 0.000840f, 0.000853f, 0.001064f, + 0.001198f, 0.001327f, 0.001489f, 0.001687f, 0.001809f, 0.001884f, 0.002008f, 0.002129f, 0.002434f, 0.002514f, 0.002949f, 0.003000f, + 0.003351f, 0.003674f, 0.003918f, 0.004356f, 0.004875f, 0.005310f, 0.005768f, 0.006458f, 0.007244f, 0.008255f, 0.008949f, 0.010361f, + 0.011589f, 0.013290f, 0.015335f, 0.017776f, 0.020828f, 0.024521f, 0.029236f, 0.035431f, 0.042694f, 0.052490f, 0.065369f, 0.082336f, + 0.104492f, 0.134277f, 0.173828f, 0.225464f, 0.290039f, 0.365234f, 0.449707f, 0.536133f, 0.623047f, 0.702637f, 0.905273f, 0.911133f, + 0.912598f, 0.913086f, 0.913086f, 0.913086f, 0.000000f, 0.000167f, 0.000167f, 0.000316f, 0.000432f, 0.000444f, 0.000608f, 0.000611f, + 0.000678f, 0.000750f, 0.000899f, 0.000925f, 0.001043f, 0.001125f, 0.001222f, 0.001343f, 0.001470f, 0.001608f, 0.001679f, 0.001804f, + 0.001976f, 0.002234f, 0.002361f, 0.002710f, 0.002748f, 0.003035f, 0.003290f, 0.003647f, 0.003990f, 0.004295f, 0.004745f, 0.005318f, + 0.005920f, 0.006618f, 0.007347f, 0.008270f, 0.009361f, 0.010719f, 0.012291f, 0.014221f, 0.016693f, 0.019592f, 0.023239f, 0.027969f, + 0.033752f, 0.041534f, 0.051666f, 0.065369f, 0.083618f, 0.108276f, 0.141357f, 0.186035f, 0.244141f, 0.316650f, 0.400635f, 0.491699f, + 0.585938f, 0.672852f, 0.897461f, 0.903320f, 0.904297f, 0.903809f, 0.903809f, 0.904297f, 0.000000f, 0.000098f, 0.000145f, 0.000289f, + 0.000399f, 0.000424f, 0.000429f, 0.000382f, 0.000529f, 0.000613f, 0.000660f, 0.000836f, 0.000907f, 0.000940f, 0.001005f, 0.001188f, + 0.001306f, 0.001451f, 0.001420f, 0.001554f, 0.001667f, 0.001783f, 0.001955f, 0.002125f, 0.002357f, 0.002493f, 0.002760f, 0.002867f, + 0.003298f, 0.003626f, 0.003878f, 0.004341f, 0.004704f, 0.005356f, 0.005905f, 0.006512f, 0.007435f, 0.008377f, 0.009598f, 0.011055f, + 0.012978f, 0.015388f, 0.018036f, 0.021698f, 0.026337f, 0.032532f, 0.040192f, 0.050995f, 0.065125f, 0.085510f, 0.113037f, 0.150513f, + 0.201538f, 0.268799f, 0.351318f, 0.444824f, 0.543457f, 0.641602f, 0.888672f, 0.894043f, 0.894531f, 0.895508f, 0.895020f, 0.895508f, + 0.000000f, 0.000000f, 0.000032f, 0.000169f, 0.000338f, 0.000372f, 0.000468f, 0.000471f, 0.000460f, 0.000493f, 0.000588f, 0.000715f, + 0.000762f, 0.000912f, 0.000831f, 0.001001f, 0.001043f, 0.001133f, 0.001242f, 0.001312f, 0.001446f, 0.001529f, 0.001647f, 0.001829f, + 0.001982f, 0.002121f, 0.002165f, 0.002438f, 0.002628f, 0.002865f, 0.003113f, 0.003424f, 0.003622f, 0.004131f, 0.004639f, 0.005222f, + 0.005875f, 0.006622f, 0.007496f, 0.008575f, 0.009987f, 0.011665f, 0.013985f, 0.016617f, 0.019913f, 0.024704f, 0.030960f, 0.039185f, + 0.050323f, 0.066284f, 0.088196f, 0.119568f, 0.163208f, 0.223511f, 0.302002f, 0.395752f, 0.499756f, 0.605957f, 0.878418f, 0.883301f, + 0.884766f, 0.884766f, 0.885254f, 0.885254f, 0.000000f, 0.000000f, 0.000000f, 0.000216f, 0.000237f, 0.000338f, 0.000387f, 0.000341f, + 0.000435f, 0.000441f, 0.000461f, 0.000577f, 0.000544f, 0.000720f, 0.000813f, 0.000823f, 0.000912f, 0.000936f, 0.000994f, 0.001026f, + 0.001240f, 0.001268f, 0.001365f, 0.001415f, 0.001590f, 0.001565f, 0.001870f, 0.001929f, 0.002123f, 0.002377f, 0.002430f, 0.002565f, + 0.002947f, 0.003384f, 0.003662f, 0.004105f, 0.004513f, 0.005047f, 0.005741f, 0.006550f, 0.007549f, 0.008865f, 0.010612f, 0.012466f, + 0.015350f, 0.018677f, 0.023270f, 0.029800f, 0.038361f, 0.050323f, 0.067932f, 0.092590f, 0.129395f, 0.181274f, 0.253418f, 0.345459f, + 0.452637f, 0.567383f, 0.866699f, 0.872559f, 0.873047f, 0.873535f, 0.873047f, 0.873535f, 0.000000f, 0.000000f, 0.000121f, 0.000182f, + 0.000187f, 0.000237f, 0.000264f, 0.000360f, 0.000360f, 0.000397f, 0.000398f, 0.000412f, 0.000432f, 0.000546f, 0.000575f, 0.000690f, + 0.000731f, 0.000727f, 0.000807f, 0.000843f, 0.000924f, 0.001034f, 0.001093f, 0.001111f, 0.001251f, 0.001249f, 0.001334f, 0.001612f, + 0.001717f, 0.001820f, 0.002090f, 0.002161f, 0.002354f, 0.002600f, 0.002787f, 0.003119f, 0.003586f, 0.003878f, 0.004452f, 0.004913f, + 0.005772f, 0.006508f, 0.007679f, 0.009285f, 0.011086f, 0.013840f, 0.016968f, 0.021820f, 0.028259f, 0.037628f, 0.050812f, 0.070129f, + 0.099670f, 0.143433f, 0.207031f, 0.294922f, 0.403076f, 0.525879f, 0.853516f, 0.859375f, 0.860840f, 0.860352f, 0.862305f, 0.861328f, + 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000181f, 0.000198f, 0.000181f, 0.000240f, 0.000275f, 0.000311f, 0.000427f, 0.000447f, + 0.000395f, 0.000472f, 0.000456f, 0.000557f, 0.000518f, 0.000562f, 0.000635f, 0.000664f, 0.000868f, 0.000887f, 0.000865f, 0.001025f, + 0.001014f, 0.001164f, 0.001096f, 0.001317f, 0.001382f, 0.001432f, 0.001445f, 0.001765f, 0.001744f, 0.002100f, 0.002144f, 0.002350f, + 0.002655f, 0.002947f, 0.003294f, 0.003780f, 0.004265f, 0.004971f, 0.005699f, 0.006786f, 0.007957f, 0.009636f, 0.011932f, 0.015823f, + 0.020142f, 0.026749f, 0.036530f, 0.051392f, 0.073792f, 0.109375f, 0.164185f, 0.244629f, 0.351562f, 0.479980f, 0.839355f, 0.844727f, + 0.846680f, 0.847656f, 0.847168f, 0.846680f, 0.000000f, 0.000121f, 0.000120f, 0.000119f, 0.000162f, 0.000133f, 0.000170f, 0.000201f, + 0.000204f, 0.000222f, 0.000258f, 0.000285f, 0.000324f, 0.000327f, 0.000422f, 0.000395f, 0.000431f, 0.000517f, 0.000632f, 0.000529f, + 0.000589f, 0.000592f, 0.000735f, 0.000714f, 0.000795f, 0.000778f, 0.000823f, 0.001063f, 0.001080f, 0.001141f, 0.001154f, 0.001308f, + 0.001439f, 0.001546f, 0.001689f, 0.001886f, 0.001978f, 0.002174f, 0.002377f, 0.002798f, 0.003277f, 0.003519f, 0.004181f, 0.004780f, + 0.005768f, 0.006863f, 0.008644f, 0.010750f, 0.014030f, 0.018448f, 0.025635f, 0.036194f, 0.053223f, 0.080811f, 0.125610f, 0.196533f, + 0.299316f, 0.430176f, 0.822754f, 0.830078f, 0.831055f, 0.831543f, 0.832031f, 0.831543f, 0.000000f, 0.000121f, 0.000120f, 0.000118f, + 0.000117f, 0.000120f, 0.000123f, 0.000151f, 0.000154f, 0.000175f, 0.000254f, 0.000190f, 0.000211f, 0.000306f, 0.000335f, 0.000358f, + 0.000394f, 0.000417f, 0.000443f, 0.000410f, 0.000565f, 0.000565f, 0.000491f, 0.000623f, 0.000616f, 0.000631f, 0.000738f, 0.000676f, + 0.000759f, 0.000924f, 0.000895f, 0.001030f, 0.001064f, 0.001176f, 0.001267f, 0.001438f, 0.001518f, 0.001704f, 0.001742f, 0.002028f, + 0.002384f, 0.002703f, 0.002972f, 0.003393f, 0.004051f, 0.004959f, 0.005993f, 0.007271f, 0.009277f, 0.012390f, 0.016968f, 0.024368f, + 0.036560f, 0.056610f, 0.091797f, 0.151245f, 0.246460f, 0.379639f, 0.805664f, 0.812500f, 0.813477f, 0.813965f, 0.813965f, 0.813965f, + 0.000000f, 0.000000f, 0.000118f, 0.000117f, 0.000116f, 0.000114f, 0.000113f, 0.000108f, 0.000127f, 0.000153f, 0.000133f, 0.000202f, + 0.000217f, 0.000223f, 0.000242f, 0.000186f, 0.000280f, 0.000304f, 0.000318f, 0.000342f, 0.000338f, 0.000473f, 0.000360f, 0.000484f, + 0.000422f, 0.000514f, 0.000527f, 0.000571f, 0.000633f, 0.000568f, 0.000639f, 0.000816f, 0.000789f, 0.000889f, 0.000891f, 0.000966f, + 0.001125f, 0.001276f, 0.001316f, 0.001496f, 0.001658f, 0.001818f, 0.002047f, 0.002502f, 0.002781f, 0.003201f, 0.003914f, 0.004795f, + 0.006096f, 0.007996f, 0.010918f, 0.015617f, 0.023697f, 0.037567f, 0.063477f, 0.111084f, 0.194824f, 0.324951f, 0.786133f, 0.792969f, + 0.794434f, 0.793945f, 0.794922f, 0.794434f, 0.000000f, 0.000119f, 0.000117f, 0.000115f, 0.000113f, 0.000112f, 0.000110f, 0.000109f, + 0.000104f, 0.000098f, 0.000099f, 0.000136f, 0.000112f, 0.000126f, 0.000175f, 0.000189f, 0.000196f, 0.000220f, 0.000216f, 0.000247f, + 0.000258f, 0.000274f, 0.000285f, 0.000309f, 0.000308f, 0.000321f, 0.000381f, 0.000390f, 0.000475f, 0.000511f, 0.000485f, 0.000501f, + 0.000641f, 0.000588f, 0.000652f, 0.000764f, 0.000808f, 0.000952f, 0.000906f, 0.001037f, 0.001110f, 0.001249f, 0.001411f, 0.001647f, + 0.001894f, 0.002159f, 0.002687f, 0.003223f, 0.004036f, 0.005150f, 0.006989f, 0.009644f, 0.014420f, 0.023361f, 0.040802f, 0.076050f, + 0.146362f, 0.269287f, 0.763184f, 0.770996f, 0.771973f, 0.771973f, 0.772461f, 0.772461f, 0.000121f, 0.000116f, 0.000114f, 0.000112f, + 0.000109f, 0.000108f, 0.000106f, 0.000105f, 0.000104f, 0.000101f, 0.000095f, 0.000090f, 0.000085f, 0.000083f, 0.000104f, 0.000097f, + 0.000094f, 0.000154f, 0.000127f, 0.000178f, 0.000197f, 0.000194f, 0.000233f, 0.000213f, 0.000279f, 0.000294f, 0.000293f, 0.000258f, + 0.000319f, 0.000394f, 0.000344f, 0.000369f, 0.000394f, 0.000410f, 0.000438f, 0.000509f, 0.000514f, 0.000580f, 0.000617f, 0.000684f, + 0.000807f, 0.000812f, 0.000914f, 0.001094f, 0.001183f, 0.001436f, 0.001639f, 0.002033f, 0.002523f, 0.003073f, 0.004063f, 0.005680f, + 0.008560f, 0.013466f, 0.024109f, 0.047791f, 0.102051f, 0.213867f, 0.740234f, 0.746582f, 0.748047f, 0.748535f, 0.749023f, 0.749023f, + 0.000000f, 0.000113f, 0.000108f, 0.000107f, 0.000104f, 0.000102f, 0.000099f, 0.000099f, 0.000097f, 0.000096f, 0.000095f, 0.000091f, + 0.000086f, 0.000081f, 0.000077f, 0.000073f, 0.000085f, 0.000091f, 0.000070f, 0.000102f, 0.000117f, 0.000131f, 0.000145f, 0.000148f, + 0.000171f, 0.000178f, 0.000178f, 0.000207f, 0.000225f, 0.000209f, 0.000285f, 0.000238f, 0.000260f, 0.000298f, 0.000331f, 0.000360f, + 0.000371f, 0.000346f, 0.000407f, 0.000443f, 0.000494f, 0.000516f, 0.000578f, 0.000662f, 0.000767f, 0.000847f, 0.001004f, 0.001149f, + 0.001451f, 0.001783f, 0.002310f, 0.003262f, 0.004593f, 0.007309f, 0.012985f, 0.026703f, 0.064026f, 0.158813f, 0.712891f, 0.719238f, + 0.722168f, 0.721680f, 0.722168f, 0.722656f, 0.000000f, 0.000105f, 0.000102f, 0.000098f, 0.000094f, 0.000092f, 0.000091f, 0.000089f, + 0.000088f, 0.000086f, 0.000085f, 0.000084f, 0.000083f, 0.000080f, 0.000076f, 0.000073f, 0.000069f, 0.000065f, 0.000062f, 0.000059f, + 0.000068f, 0.000063f, 0.000069f, 0.000074f, 0.000087f, 0.000102f, 0.000112f, 0.000130f, 0.000137f, 0.000129f, 0.000143f, 0.000168f, + 0.000180f, 0.000178f, 0.000189f, 0.000198f, 0.000222f, 0.000240f, 0.000262f, 0.000285f, 0.000304f, 0.000317f, 0.000339f, 0.000399f, + 0.000439f, 0.000490f, 0.000570f, 0.000658f, 0.000781f, 0.000988f, 0.001235f, 0.001674f, 0.002407f, 0.003725f, 0.006485f, 0.013199f, + 0.034546f, 0.107605f, 0.682129f, 0.691406f, 0.692871f, 0.691406f, 0.692871f, 0.692871f, 0.000105f, 0.000089f, 0.000085f, 0.000080f, + 0.000078f, 0.000078f, 0.000075f, 0.000074f, 0.000072f, 0.000072f, 0.000070f, 0.000071f, 0.000069f, 0.000069f, 0.000069f, 0.000068f, + 0.000066f, 0.000063f, 0.000060f, 0.000057f, 0.000054f, 0.000052f, 0.000049f, 0.000047f, 0.000046f, 0.000045f, 0.000048f, 0.000055f, + 0.000060f, 0.000068f, 0.000083f, 0.000087f, 0.000092f, 0.000103f, 0.000109f, 0.000117f, 0.000130f, 0.000150f, 0.000148f, 0.000142f, + 0.000167f, 0.000186f, 0.000210f, 0.000213f, 0.000232f, 0.000280f, 0.000292f, 0.000329f, 0.000391f, 0.000456f, 0.000596f, 0.000764f, + 0.001065f, 0.001633f, 0.002806f, 0.005909f, 0.015488f, 0.062378f, 0.651367f, 0.659668f, 0.661133f, 0.661133f, 0.660645f, 0.661621f, + 0.000034f, 0.000037f, 0.000048f, 0.000051f, 0.000047f, 0.000049f, 0.000047f, 0.000051f, 0.000049f, 0.000051f, 0.000049f, 0.000050f, + 0.000051f, 0.000050f, 0.000050f, 0.000049f, 0.000051f, 0.000050f, 0.000051f, 0.000050f, 0.000049f, 0.000047f, 0.000045f, 0.000043f, + 0.000041f, 0.000039f, 0.000037f, 0.000035f, 0.000033f, 0.000032f, 0.000030f, 0.000029f, 0.000034f, 0.000041f, 0.000046f, 0.000057f, + 0.000063f, 0.000067f, 0.000065f, 0.000072f, 0.000083f, 0.000093f, 0.000096f, 0.000102f, 0.000102f, 0.000135f, 0.000134f, 0.000151f, + 0.000184f, 0.000198f, 0.000245f, 0.000306f, 0.000425f, 0.000607f, 0.001032f, 0.002081f, 0.005886f, 0.027924f, 0.617188f, 0.625977f, + 0.627441f, 0.627930f, 0.626953f, 0.628418f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000006f, 0.000010f, 0.000014f, + 0.000016f, 0.000014f, 0.000019f, 0.000022f, 0.000022f, 0.000022f, 0.000025f, 0.000026f, 0.000027f, 0.000028f, 0.000029f, 0.000029f, + 0.000029f, 0.000030f, 0.000030f, 0.000031f, 0.000032f, 0.000032f, 0.000031f, 0.000030f, 0.000028f, 0.000027f, 0.000026f, 0.000024f, + 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000019f, 0.000021f, 0.000022f, 0.000024f, 0.000027f, 0.000035f, 0.000041f, 0.000034f, + 0.000041f, 0.000052f, 0.000051f, 0.000051f, 0.000058f, 0.000070f, 0.000074f, 0.000103f, 0.000119f, 0.000169f, 0.000277f, 0.000510f, + 0.001495f, 0.008766f, 0.583008f, 0.590332f, 0.591797f, 0.591797f, 0.592285f, 0.592285f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000003f, 0.000005f, 0.000006f, 0.000008f, 0.000009f, 0.000010f, 0.000010f, + 0.000012f, 0.000012f, 0.000013f, 0.000014f, 0.000015f, 0.000015f, 0.000015f, 0.000015f, 0.000014f, 0.000013f, 0.000013f, 0.000012f, + 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000014f, 0.000011f, 0.000015f, 0.000017f, 0.000017f, 0.000021f, 0.000020f, + 0.000026f, 0.000026f, 0.000042f, 0.000069f, 0.000178f, 0.001302f, 0.544434f, 0.553711f, 0.554688f, 0.554688f, 0.556152f, 0.556641f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000002f, 0.000003f, 0.000003f, + 0.000003f, 0.000003f, 0.000003f, 0.000002f, 0.000002f, 0.000001f, 0.000003f, 0.000003f, 0.000004f, 0.000014f, 0.506836f, 0.515137f, + 0.516113f, 0.516602f, 0.517090f, 0.517578f, + }, + { + 0.089539f, 0.244873f, 0.368164f, 0.464355f, 0.539551f, 0.599121f, 0.648438f, 0.688477f, 0.721680f, 0.749512f, 0.772461f, 0.793945f, + 0.811523f, 0.826172f, 0.841309f, 0.854004f, 0.863770f, 0.874512f, 0.883301f, 0.891602f, 0.898438f, 0.906250f, 0.912109f, 0.917969f, + 0.922852f, 0.928223f, 0.932617f, 0.937012f, 0.940918f, 0.944336f, 0.948242f, 0.951660f, 0.954590f, 0.957520f, 0.960449f, 0.962891f, + 0.965820f, 0.967773f, 0.970215f, 0.972656f, 0.974609f, 0.976074f, 0.978516f, 0.979492f, 0.981934f, 0.983398f, 0.984863f, 0.986328f, + 0.987793f, 0.988770f, 0.990234f, 0.991699f, 0.993164f, 0.994141f, 0.995117f, 0.996582f, 0.997559f, 0.998535f, 0.999023f, 0.998535f, + 0.997559f, 0.997070f, 0.996582f, 0.995605f, 0.045563f, 0.143921f, 0.242798f, 0.334717f, 0.417969f, 0.489258f, 0.550293f, 0.602051f, + 0.646484f, 0.683594f, 0.715820f, 0.743652f, 0.767090f, 0.788086f, 0.805664f, 0.822266f, 0.836426f, 0.849609f, 0.861328f, 0.870117f, + 0.879883f, 0.889160f, 0.896973f, 0.903320f, 0.909668f, 0.916016f, 0.921875f, 0.926758f, 0.931641f, 0.936523f, 0.940430f, 0.943848f, + 0.947266f, 0.951172f, 0.954102f, 0.957520f, 0.960449f, 0.962891f, 0.965820f, 0.968262f, 0.970215f, 0.973145f, 0.974121f, 0.976074f, + 0.979004f, 0.980469f, 0.982422f, 0.983887f, 0.985352f, 0.986816f, 0.988281f, 0.989746f, 0.991211f, 0.992188f, 0.994141f, 0.995117f, + 0.996094f, 0.997070f, 0.998535f, 0.997559f, 0.997070f, 0.996582f, 0.996094f, 0.995117f, 0.026855f, 0.089233f, 0.159790f, 0.234619f, + 0.308838f, 0.381348f, 0.447754f, 0.507812f, 0.561035f, 0.606934f, 0.646484f, 0.683105f, 0.712402f, 0.740234f, 0.763184f, 0.784668f, + 0.802246f, 0.819336f, 0.833984f, 0.846680f, 0.857910f, 0.868652f, 0.878418f, 0.886719f, 0.895508f, 0.903320f, 0.909668f, 0.915527f, + 0.920410f, 0.926270f, 0.931152f, 0.935547f, 0.940430f, 0.943848f, 0.947754f, 0.951172f, 0.954590f, 0.958008f, 0.960449f, 0.963379f, + 0.966309f, 0.968750f, 0.971191f, 0.973145f, 0.975586f, 0.977051f, 0.979004f, 0.981445f, 0.982910f, 0.983887f, 0.985840f, 0.987305f, + 0.988770f, 0.990723f, 0.992188f, 0.993164f, 0.994629f, 0.996094f, 0.998047f, 0.997070f, 0.996582f, 0.996094f, 0.995605f, 0.995117f, + 0.017746f, 0.058746f, 0.108276f, 0.163818f, 0.224365f, 0.288086f, 0.351562f, 0.413086f, 0.470947f, 0.522949f, 0.569824f, 0.612793f, + 0.650879f, 0.684570f, 0.713867f, 0.739258f, 0.762695f, 0.783203f, 0.800781f, 0.817871f, 0.833008f, 0.845215f, 0.857422f, 0.868164f, + 0.877441f, 0.886230f, 0.894043f, 0.902832f, 0.908691f, 0.915039f, 0.921387f, 0.925781f, 0.930664f, 0.936035f, 0.939941f, 0.944336f, + 0.948242f, 0.951660f, 0.955078f, 0.957520f, 0.961426f, 0.964355f, 0.967285f, 0.968750f, 0.971680f, 0.974121f, 0.975586f, 0.978027f, + 0.979980f, 0.981934f, 0.983887f, 0.985352f, 0.987305f, 0.988770f, 0.989746f, 0.991211f, 0.992676f, 0.993652f, 0.997070f, 0.996582f, + 0.996582f, 0.996094f, 0.995117f, 0.994629f, 0.012337f, 0.041229f, 0.075928f, 0.117065f, 0.163208f, 0.214478f, 0.270020f, 0.327148f, + 0.383301f, 0.437500f, 0.490234f, 0.536621f, 0.581543f, 0.621094f, 0.656250f, 0.688477f, 0.716797f, 0.741699f, 0.763672f, 0.784668f, + 0.802246f, 0.818359f, 0.832520f, 0.845703f, 0.857422f, 0.868164f, 0.877930f, 0.886230f, 0.895020f, 0.902344f, 0.909668f, 0.915039f, + 0.921875f, 0.926758f, 0.931641f, 0.937012f, 0.940430f, 0.946289f, 0.949219f, 0.952637f, 0.956055f, 0.958984f, 0.961914f, 0.964844f, + 0.967773f, 0.970215f, 0.972656f, 0.974609f, 0.976562f, 0.979004f, 0.980957f, 0.982910f, 0.984863f, 0.986816f, 0.987793f, 0.989746f, + 0.990723f, 0.992676f, 0.996582f, 0.996094f, 0.995605f, 0.995117f, 0.994629f, 0.994141f, 0.009315f, 0.030411f, 0.055756f, 0.085632f, + 0.121094f, 0.160889f, 0.206055f, 0.254150f, 0.305664f, 0.357422f, 0.408447f, 0.459717f, 0.506836f, 0.551270f, 0.592773f, 0.629395f, + 0.662598f, 0.692871f, 0.719727f, 0.745117f, 0.767090f, 0.786133f, 0.804688f, 0.819336f, 0.834473f, 0.847168f, 0.858398f, 0.869629f, + 0.879395f, 0.888672f, 0.895020f, 0.903320f, 0.910156f, 0.916016f, 0.922363f, 0.928223f, 0.933105f, 0.937012f, 0.941406f, 0.946289f, + 0.950195f, 0.954102f, 0.957031f, 0.960449f, 0.963379f, 0.965820f, 0.969238f, 0.971191f, 0.974121f, 0.976074f, 0.978027f, 0.979980f, + 0.982422f, 0.984375f, 0.985840f, 0.987793f, 0.989258f, 0.990723f, 0.995605f, 0.995605f, 0.995117f, 0.994629f, 0.994629f, 0.993652f, + 0.006634f, 0.022736f, 0.041962f, 0.064026f, 0.090759f, 0.122192f, 0.157593f, 0.197510f, 0.240356f, 0.287354f, 0.335693f, 0.384766f, + 0.432373f, 0.479736f, 0.523438f, 0.565430f, 0.604004f, 0.639160f, 0.670898f, 0.699219f, 0.726562f, 0.749023f, 0.770508f, 0.790527f, + 0.806641f, 0.822754f, 0.836426f, 0.848633f, 0.859863f, 0.871582f, 0.881348f, 0.889160f, 0.897949f, 0.905273f, 0.912598f, 0.918945f, + 0.924316f, 0.929199f, 0.935059f, 0.938965f, 0.943848f, 0.947266f, 0.951660f, 0.955078f, 0.958496f, 0.961914f, 0.964844f, 0.967773f, + 0.970703f, 0.973145f, 0.975098f, 0.977539f, 0.979492f, 0.981445f, 0.983887f, 0.985352f, 0.987305f, 0.989258f, 0.995117f, 0.994629f, + 0.994141f, 0.994141f, 0.993652f, 0.993164f, 0.005428f, 0.017807f, 0.032166f, 0.049652f, 0.070007f, 0.093811f, 0.121765f, 0.153564f, + 0.189087f, 0.228516f, 0.270752f, 0.316162f, 0.362061f, 0.408936f, 0.453857f, 0.498779f, 0.540527f, 0.579590f, 0.615723f, 0.649902f, + 0.679688f, 0.707520f, 0.732422f, 0.755371f, 0.775391f, 0.794922f, 0.811035f, 0.826172f, 0.839844f, 0.852051f, 0.864258f, 0.875000f, + 0.883301f, 0.892578f, 0.899902f, 0.907715f, 0.914062f, 0.920410f, 0.926270f, 0.931641f, 0.936035f, 0.940918f, 0.945312f, 0.949219f, + 0.954102f, 0.957031f, 0.960938f, 0.963379f, 0.966797f, 0.969238f, 0.972168f, 0.974609f, 0.977051f, 0.979492f, 0.980957f, 0.983398f, + 0.985352f, 0.987305f, 0.994141f, 0.994141f, 0.994141f, 0.993652f, 0.993164f, 0.992676f, 0.004223f, 0.014046f, 0.025452f, 0.039062f, + 0.055115f, 0.073608f, 0.095642f, 0.120239f, 0.149292f, 0.182251f, 0.217529f, 0.257080f, 0.298828f, 0.342773f, 0.387207f, 0.431152f, + 0.474609f, 0.516602f, 0.556641f, 0.593750f, 0.628418f, 0.660156f, 0.689453f, 0.715820f, 0.740723f, 0.762207f, 0.782227f, 0.799805f, + 0.816406f, 0.830566f, 0.844727f, 0.855469f, 0.867188f, 0.877441f, 0.886230f, 0.895020f, 0.903809f, 0.910645f, 0.917480f, 0.923340f, + 0.928711f, 0.934570f, 0.939453f, 0.943848f, 0.948242f, 0.952148f, 0.956055f, 0.959473f, 0.961914f, 0.965820f, 0.968750f, 0.971680f, + 0.974121f, 0.975586f, 0.979004f, 0.980957f, 0.983398f, 0.985352f, 0.993652f, 0.993652f, 0.993164f, 0.993164f, 0.992676f, 0.991699f, + 0.003532f, 0.011536f, 0.020645f, 0.031342f, 0.044098f, 0.058624f, 0.075989f, 0.096252f, 0.119141f, 0.145386f, 0.175049f, 0.208130f, + 0.244385f, 0.283203f, 0.324463f, 0.367432f, 0.410400f, 0.453369f, 0.495361f, 0.534668f, 0.572266f, 0.607910f, 0.641602f, 0.672852f, + 0.700195f, 0.725098f, 0.748047f, 0.769531f, 0.789062f, 0.806152f, 0.821777f, 0.835938f, 0.848633f, 0.860352f, 0.872070f, 0.881836f, + 0.890625f, 0.898926f, 0.906738f, 0.913086f, 0.919922f, 0.925781f, 0.931641f, 0.936523f, 0.941406f, 0.946289f, 0.950684f, 0.954590f, + 0.958008f, 0.961426f, 0.964844f, 0.968262f, 0.970703f, 0.973633f, 0.976074f, 0.978516f, 0.980469f, 0.982910f, 0.992676f, 0.992676f, + 0.992188f, 0.992188f, 0.991699f, 0.990723f, 0.002850f, 0.009483f, 0.016647f, 0.025833f, 0.035889f, 0.047424f, 0.061646f, 0.076660f, + 0.095642f, 0.117065f, 0.141113f, 0.168457f, 0.198975f, 0.233032f, 0.269775f, 0.308838f, 0.349854f, 0.391357f, 0.432861f, 0.474121f, + 0.515625f, 0.552734f, 0.589355f, 0.622559f, 0.654785f, 0.683594f, 0.710938f, 0.735352f, 0.757812f, 0.777344f, 0.795898f, 0.812988f, + 0.827637f, 0.842285f, 0.854492f, 0.866211f, 0.876953f, 0.886719f, 0.895508f, 0.902832f, 0.911133f, 0.917969f, 0.924316f, 0.929688f, + 0.935059f, 0.940430f, 0.945312f, 0.949219f, 0.953125f, 0.958008f, 0.961426f, 0.964844f, 0.967285f, 0.970703f, 0.973633f, 0.975586f, + 0.978516f, 0.981445f, 0.991699f, 0.992188f, 0.991699f, 0.991211f, 0.991211f, 0.990723f, 0.002628f, 0.007713f, 0.014069f, 0.021484f, + 0.029709f, 0.038910f, 0.050201f, 0.063171f, 0.078186f, 0.094849f, 0.114563f, 0.137329f, 0.162720f, 0.190918f, 0.222656f, 0.257568f, + 0.293945f, 0.332764f, 0.372803f, 0.414551f, 0.455078f, 0.495361f, 0.533691f, 0.571289f, 0.606445f, 0.639160f, 0.668457f, 0.697754f, + 0.723633f, 0.746094f, 0.767090f, 0.787598f, 0.804199f, 0.820801f, 0.834473f, 0.848633f, 0.860352f, 0.872559f, 0.882324f, 0.891602f, + 0.899902f, 0.907715f, 0.915039f, 0.921387f, 0.927734f, 0.934082f, 0.938965f, 0.944824f, 0.948730f, 0.953125f, 0.956543f, 0.960938f, + 0.963867f, 0.967285f, 0.970215f, 0.973145f, 0.976074f, 0.978516f, 0.990234f, 0.990723f, 0.990723f, 0.991211f, 0.990234f, 0.990234f, + 0.002131f, 0.006535f, 0.012016f, 0.017670f, 0.024780f, 0.032837f, 0.041199f, 0.051819f, 0.063904f, 0.077759f, 0.093689f, 0.112610f, + 0.133057f, 0.156860f, 0.183472f, 0.213257f, 0.245605f, 0.281006f, 0.318115f, 0.357422f, 0.397217f, 0.437500f, 0.478271f, 0.516602f, + 0.554688f, 0.589844f, 0.623535f, 0.654785f, 0.684082f, 0.710938f, 0.734375f, 0.757812f, 0.777832f, 0.795898f, 0.813477f, 0.828613f, + 0.843262f, 0.855957f, 0.867676f, 0.878906f, 0.888184f, 0.897461f, 0.905273f, 0.912598f, 0.919922f, 0.926758f, 0.932129f, 0.937988f, + 0.942871f, 0.947754f, 0.951660f, 0.955566f, 0.960449f, 0.964355f, 0.967285f, 0.970215f, 0.973145f, 0.976074f, 0.989746f, 0.990234f, + 0.990234f, 0.990234f, 0.989746f, 0.988770f, 0.001566f, 0.005798f, 0.010231f, 0.015259f, 0.020920f, 0.027176f, 0.034607f, 0.043335f, + 0.052887f, 0.064392f, 0.077576f, 0.092712f, 0.109802f, 0.129639f, 0.151611f, 0.176758f, 0.204346f, 0.235474f, 0.269043f, 0.304688f, + 0.342529f, 0.381836f, 0.421143f, 0.460449f, 0.500488f, 0.538086f, 0.574219f, 0.608887f, 0.640625f, 0.670898f, 0.699219f, 0.725098f, + 0.748535f, 0.769043f, 0.788574f, 0.807129f, 0.823242f, 0.837402f, 0.850586f, 0.863281f, 0.874512f, 0.885254f, 0.894043f, 0.902832f, + 0.910645f, 0.917969f, 0.924805f, 0.931152f, 0.936523f, 0.941895f, 0.947266f, 0.951172f, 0.955566f, 0.960449f, 0.963867f, 0.966797f, + 0.970703f, 0.973145f, 0.988281f, 0.989258f, 0.989258f, 0.989258f, 0.988770f, 0.988281f, 0.001427f, 0.004749f, 0.008934f, 0.012833f, + 0.017670f, 0.023483f, 0.029114f, 0.036438f, 0.044556f, 0.054047f, 0.064453f, 0.077148f, 0.091309f, 0.107544f, 0.125854f, 0.146729f, + 0.170776f, 0.197266f, 0.226440f, 0.257568f, 0.292236f, 0.329346f, 0.367188f, 0.405762f, 0.445557f, 0.484619f, 0.522949f, 0.559570f, + 0.595215f, 0.627441f, 0.659180f, 0.687012f, 0.714355f, 0.739258f, 0.761719f, 0.781738f, 0.800781f, 0.817383f, 0.833984f, 0.847168f, + 0.859375f, 0.872070f, 0.882324f, 0.891602f, 0.900879f, 0.909668f, 0.916504f, 0.923828f, 0.930176f, 0.936523f, 0.941895f, 0.946777f, + 0.951172f, 0.956055f, 0.960449f, 0.963867f, 0.967285f, 0.970703f, 0.987305f, 0.988770f, 0.988281f, 0.987793f, 0.987793f, 0.987793f, + 0.001357f, 0.004501f, 0.007557f, 0.011284f, 0.015236f, 0.019791f, 0.025101f, 0.030838f, 0.037628f, 0.045532f, 0.054596f, 0.064636f, + 0.076355f, 0.089905f, 0.105042f, 0.122498f, 0.142334f, 0.164307f, 0.189697f, 0.217896f, 0.248413f, 0.281494f, 0.316406f, 0.354004f, + 0.391846f, 0.430664f, 0.469971f, 0.508301f, 0.545898f, 0.582031f, 0.615723f, 0.647461f, 0.677734f, 0.704590f, 0.731445f, 0.754395f, + 0.775391f, 0.794922f, 0.811523f, 0.829102f, 0.842773f, 0.856934f, 0.868652f, 0.880371f, 0.891113f, 0.899414f, 0.908203f, 0.915527f, + 0.922852f, 0.930176f, 0.936035f, 0.941406f, 0.947266f, 0.951660f, 0.957031f, 0.960449f, 0.963867f, 0.968262f, 0.986328f, 0.987305f, + 0.987793f, 0.987305f, 0.987305f, 0.986816f, 0.001239f, 0.003864f, 0.006699f, 0.009621f, 0.013008f, 0.017059f, 0.021805f, 0.026703f, + 0.032562f, 0.039185f, 0.045807f, 0.054352f, 0.064514f, 0.075439f, 0.088257f, 0.102478f, 0.119263f, 0.138306f, 0.159546f, 0.183228f, + 0.209961f, 0.239258f, 0.271484f, 0.305176f, 0.341797f, 0.379639f, 0.417480f, 0.456787f, 0.495605f, 0.532227f, 0.570801f, 0.604980f, + 0.637207f, 0.666992f, 0.696289f, 0.722656f, 0.746582f, 0.768555f, 0.789062f, 0.808105f, 0.824219f, 0.839844f, 0.854492f, 0.865723f, + 0.878418f, 0.888672f, 0.897461f, 0.906738f, 0.915039f, 0.922363f, 0.929199f, 0.935547f, 0.941895f, 0.946289f, 0.952148f, 0.956543f, + 0.960449f, 0.964844f, 0.985352f, 0.986816f, 0.986816f, 0.986328f, 0.986328f, 0.985840f, 0.001151f, 0.003429f, 0.005753f, 0.008400f, + 0.011391f, 0.014877f, 0.018494f, 0.022858f, 0.028046f, 0.033112f, 0.039642f, 0.046661f, 0.054565f, 0.064026f, 0.074280f, 0.086243f, + 0.100403f, 0.116150f, 0.133789f, 0.154053f, 0.176636f, 0.202393f, 0.230957f, 0.261719f, 0.295166f, 0.330322f, 0.367432f, 0.405518f, + 0.445312f, 0.483398f, 0.520996f, 0.558105f, 0.594238f, 0.626465f, 0.659668f, 0.688477f, 0.714844f, 0.740723f, 0.763672f, 0.784180f, + 0.804199f, 0.821289f, 0.837402f, 0.852051f, 0.864258f, 0.876465f, 0.886719f, 0.897949f, 0.906250f, 0.915039f, 0.922363f, 0.929199f, + 0.935547f, 0.941406f, 0.946777f, 0.952637f, 0.958008f, 0.961914f, 0.983887f, 0.985840f, 0.985352f, 0.985352f, 0.984863f, 0.984863f, + 0.001000f, 0.002768f, 0.005127f, 0.007515f, 0.010155f, 0.013283f, 0.016205f, 0.019714f, 0.023987f, 0.028854f, 0.033905f, 0.040161f, + 0.046814f, 0.054199f, 0.063110f, 0.073303f, 0.084839f, 0.098145f, 0.112854f, 0.129883f, 0.149292f, 0.171387f, 0.195435f, 0.222778f, + 0.252686f, 0.285400f, 0.320312f, 0.356689f, 0.394531f, 0.433105f, 0.471924f, 0.510742f, 0.547852f, 0.584473f, 0.617676f, 0.650879f, + 0.680664f, 0.708984f, 0.734375f, 0.759277f, 0.780762f, 0.799805f, 0.817383f, 0.834473f, 0.849121f, 0.862793f, 0.875488f, 0.886719f, + 0.896484f, 0.906250f, 0.915039f, 0.923828f, 0.930176f, 0.936035f, 0.942871f, 0.948242f, 0.953613f, 0.958008f, 0.982910f, 0.983887f, + 0.984375f, 0.983887f, 0.984375f, 0.983398f, 0.000799f, 0.002705f, 0.004459f, 0.006573f, 0.008842f, 0.011375f, 0.014099f, 0.017487f, + 0.020798f, 0.024963f, 0.029465f, 0.034637f, 0.039703f, 0.046478f, 0.054047f, 0.062256f, 0.072388f, 0.082947f, 0.095764f, 0.110229f, + 0.126099f, 0.144775f, 0.165771f, 0.189697f, 0.216187f, 0.244995f, 0.276123f, 0.310303f, 0.346191f, 0.384521f, 0.422607f, 0.461670f, + 0.500000f, 0.538574f, 0.575195f, 0.609863f, 0.643555f, 0.673828f, 0.702637f, 0.730469f, 0.754395f, 0.777344f, 0.797363f, 0.815430f, + 0.833008f, 0.848633f, 0.861328f, 0.875000f, 0.886719f, 0.896973f, 0.906738f, 0.915039f, 0.923340f, 0.930176f, 0.936523f, 0.943848f, + 0.948730f, 0.954102f, 0.981445f, 0.983398f, 0.982910f, 0.983398f, 0.982910f, 0.982910f, 0.000774f, 0.002554f, 0.003899f, 0.005875f, + 0.007759f, 0.009949f, 0.012733f, 0.015060f, 0.018280f, 0.021667f, 0.025574f, 0.029678f, 0.034698f, 0.040405f, 0.046570f, 0.053650f, + 0.061462f, 0.071106f, 0.081360f, 0.093323f, 0.107300f, 0.122864f, 0.140747f, 0.160522f, 0.183960f, 0.209229f, 0.237305f, 0.268799f, + 0.302002f, 0.337402f, 0.374023f, 0.413330f, 0.451904f, 0.490967f, 0.529785f, 0.567383f, 0.603027f, 0.636719f, 0.668457f, 0.698242f, + 0.725586f, 0.750977f, 0.773926f, 0.793945f, 0.813965f, 0.831543f, 0.847656f, 0.861816f, 0.874512f, 0.886719f, 0.897461f, 0.906738f, + 0.915527f, 0.923828f, 0.931641f, 0.937988f, 0.944824f, 0.949707f, 0.979980f, 0.981934f, 0.981934f, 0.981934f, 0.981934f, 0.981445f, + 0.000657f, 0.001934f, 0.003330f, 0.005280f, 0.006748f, 0.009079f, 0.010994f, 0.013763f, 0.015945f, 0.019150f, 0.022003f, 0.026001f, + 0.030350f, 0.034790f, 0.040253f, 0.045898f, 0.052795f, 0.060852f, 0.069641f, 0.079346f, 0.091187f, 0.104492f, 0.119751f, 0.136963f, + 0.156372f, 0.178345f, 0.203247f, 0.230957f, 0.260742f, 0.294189f, 0.328613f, 0.365723f, 0.403564f, 0.443115f, 0.482910f, 0.521484f, + 0.559570f, 0.596680f, 0.630859f, 0.664062f, 0.694336f, 0.722168f, 0.747559f, 0.771484f, 0.793457f, 0.813477f, 0.830078f, 0.846191f, + 0.861816f, 0.874023f, 0.887207f, 0.898438f, 0.908691f, 0.916992f, 0.925293f, 0.933594f, 0.939941f, 0.946777f, 0.978516f, 0.980469f, + 0.980469f, 0.980469f, 0.980469f, 0.980469f, 0.000818f, 0.001935f, 0.003246f, 0.004658f, 0.006229f, 0.007912f, 0.010017f, 0.012093f, + 0.014259f, 0.016586f, 0.019653f, 0.022659f, 0.026413f, 0.030289f, 0.034790f, 0.039917f, 0.045441f, 0.052338f, 0.059479f, 0.068115f, + 0.077759f, 0.089050f, 0.102051f, 0.116272f, 0.133179f, 0.152344f, 0.173340f, 0.197876f, 0.224243f, 0.254150f, 0.286621f, 0.321533f, + 0.357666f, 0.396729f, 0.436279f, 0.475830f, 0.514648f, 0.553711f, 0.590332f, 0.626465f, 0.659180f, 0.689941f, 0.719238f, 0.746094f, + 0.770020f, 0.792480f, 0.812500f, 0.830566f, 0.846680f, 0.862305f, 0.875977f, 0.888184f, 0.899414f, 0.910156f, 0.918945f, 0.927246f, + 0.935059f, 0.941895f, 0.977051f, 0.979004f, 0.979492f, 0.979004f, 0.979492f, 0.979004f, 0.000583f, 0.001696f, 0.003044f, 0.004276f, + 0.005394f, 0.007111f, 0.009048f, 0.010727f, 0.012802f, 0.014549f, 0.017319f, 0.019943f, 0.023132f, 0.026459f, 0.030212f, 0.034576f, + 0.039612f, 0.045105f, 0.051422f, 0.058594f, 0.066833f, 0.076416f, 0.087341f, 0.099792f, 0.113647f, 0.130005f, 0.147827f, 0.168945f, + 0.192261f, 0.218750f, 0.247803f, 0.280029f, 0.314209f, 0.351074f, 0.389404f, 0.429199f, 0.468750f, 0.508301f, 0.547852f, 0.585938f, + 0.622070f, 0.655762f, 0.687988f, 0.718262f, 0.744629f, 0.769531f, 0.792480f, 0.812500f, 0.832520f, 0.848633f, 0.863770f, 0.877441f, + 0.890137f, 0.901367f, 0.912109f, 0.921387f, 0.929199f, 0.937500f, 0.975586f, 0.978027f, 0.978027f, 0.977539f, 0.977539f, 0.977051f, + 0.000463f, 0.001634f, 0.002899f, 0.003574f, 0.004932f, 0.006233f, 0.007866f, 0.009644f, 0.011055f, 0.012894f, 0.015518f, 0.017792f, + 0.020279f, 0.023178f, 0.026657f, 0.030136f, 0.034271f, 0.039062f, 0.044586f, 0.050446f, 0.057739f, 0.065613f, 0.074646f, 0.084900f, + 0.097107f, 0.111023f, 0.126099f, 0.143921f, 0.164673f, 0.187500f, 0.213257f, 0.242065f, 0.273926f, 0.308594f, 0.344971f, 0.383301f, + 0.423340f, 0.463623f, 0.503906f, 0.543945f, 0.582520f, 0.619629f, 0.653809f, 0.686523f, 0.717285f, 0.744629f, 0.770020f, 0.792969f, + 0.814453f, 0.833496f, 0.850098f, 0.866211f, 0.879395f, 0.893066f, 0.904297f, 0.914551f, 0.923828f, 0.932129f, 0.973145f, 0.976074f, + 0.976562f, 0.976074f, 0.976074f, 0.976074f, 0.000472f, 0.001289f, 0.002508f, 0.003481f, 0.004459f, 0.005894f, 0.007042f, 0.008232f, + 0.009972f, 0.011719f, 0.013435f, 0.015884f, 0.017899f, 0.020386f, 0.023422f, 0.026428f, 0.030411f, 0.034180f, 0.038757f, 0.043854f, + 0.049652f, 0.056549f, 0.064270f, 0.073303f, 0.083252f, 0.095093f, 0.107910f, 0.123169f, 0.141113f, 0.160645f, 0.183472f, 0.208618f, + 0.237305f, 0.268799f, 0.302734f, 0.339600f, 0.377930f, 0.418457f, 0.459473f, 0.500000f, 0.540527f, 0.579102f, 0.617188f, 0.652832f, + 0.685547f, 0.716309f, 0.745117f, 0.771484f, 0.794922f, 0.815918f, 0.834961f, 0.853027f, 0.868652f, 0.882324f, 0.895996f, 0.907227f, + 0.916992f, 0.927246f, 0.972168f, 0.974121f, 0.975098f, 0.973633f, 0.974609f, 0.973633f, 0.000238f, 0.001453f, 0.002047f, 0.002985f, + 0.004227f, 0.005272f, 0.006096f, 0.007309f, 0.008957f, 0.010437f, 0.012184f, 0.014214f, 0.015793f, 0.018082f, 0.020538f, 0.023270f, + 0.026505f, 0.029648f, 0.033813f, 0.038300f, 0.043457f, 0.049042f, 0.055298f, 0.062744f, 0.070984f, 0.081299f, 0.092590f, 0.105591f, + 0.120361f, 0.137695f, 0.156982f, 0.179443f, 0.204346f, 0.232788f, 0.263672f, 0.297363f, 0.334229f, 0.373047f, 0.414307f, 0.455322f, + 0.497314f, 0.538086f, 0.578613f, 0.616211f, 0.653320f, 0.686523f, 0.718262f, 0.747559f, 0.773438f, 0.797363f, 0.818848f, 0.838867f, + 0.856934f, 0.871582f, 0.885742f, 0.898926f, 0.910645f, 0.920410f, 0.970215f, 0.971680f, 0.972656f, 0.972656f, 0.972168f, 0.972168f, + 0.000376f, 0.001075f, 0.002052f, 0.002823f, 0.003603f, 0.004509f, 0.005619f, 0.007008f, 0.008064f, 0.009132f, 0.010849f, 0.012314f, + 0.013817f, 0.015945f, 0.018188f, 0.020676f, 0.022995f, 0.026230f, 0.029587f, 0.033234f, 0.037598f, 0.042328f, 0.048004f, 0.054230f, + 0.061188f, 0.069824f, 0.079468f, 0.090454f, 0.103271f, 0.117493f, 0.134644f, 0.153931f, 0.175293f, 0.200806f, 0.228149f, 0.259277f, + 0.293945f, 0.330566f, 0.370117f, 0.410889f, 0.453369f, 0.495605f, 0.537109f, 0.578125f, 0.616699f, 0.653809f, 0.689453f, 0.721191f, + 0.750000f, 0.776855f, 0.800293f, 0.822754f, 0.841309f, 0.859863f, 0.876465f, 0.890137f, 0.902832f, 0.914062f, 0.967773f, 0.970703f, + 0.970703f, 0.970703f, 0.970703f, 0.970703f, 0.000237f, 0.000972f, 0.001674f, 0.002413f, 0.003336f, 0.003956f, 0.005093f, 0.006039f, + 0.007069f, 0.008202f, 0.009613f, 0.011017f, 0.012520f, 0.014282f, 0.016068f, 0.017853f, 0.020508f, 0.023117f, 0.025986f, 0.029160f, + 0.032898f, 0.036865f, 0.041565f, 0.046997f, 0.052887f, 0.060089f, 0.068176f, 0.077515f, 0.088257f, 0.100586f, 0.114929f, 0.131592f, + 0.150635f, 0.172241f, 0.196411f, 0.224731f, 0.255859f, 0.290039f, 0.327393f, 0.367188f, 0.409180f, 0.451172f, 0.493896f, 0.536621f, + 0.578613f, 0.618164f, 0.655762f, 0.691406f, 0.724121f, 0.753906f, 0.781738f, 0.805176f, 0.827637f, 0.847656f, 0.864746f, 0.880859f, + 0.895508f, 0.907715f, 0.965332f, 0.968262f, 0.968750f, 0.969238f, 0.967773f, 0.967773f, 0.000450f, 0.001033f, 0.001554f, 0.002131f, + 0.002939f, 0.003662f, 0.004551f, 0.005722f, 0.006405f, 0.007542f, 0.008484f, 0.009750f, 0.011017f, 0.012596f, 0.014046f, 0.015854f, + 0.017975f, 0.020264f, 0.022736f, 0.025497f, 0.028671f, 0.031952f, 0.036011f, 0.040741f, 0.045746f, 0.051910f, 0.058868f, 0.066772f, + 0.075867f, 0.086304f, 0.098328f, 0.112244f, 0.128784f, 0.147217f, 0.168945f, 0.193848f, 0.221558f, 0.252441f, 0.287109f, 0.324951f, + 0.365234f, 0.407715f, 0.450684f, 0.494629f, 0.539062f, 0.580566f, 0.621094f, 0.659668f, 0.695801f, 0.729004f, 0.758789f, 0.786133f, + 0.810547f, 0.833008f, 0.852539f, 0.870117f, 0.886719f, 0.900879f, 0.962891f, 0.966309f, 0.966309f, 0.966797f, 0.966797f, 0.966309f, + 0.000304f, 0.001050f, 0.001257f, 0.002295f, 0.002689f, 0.003885f, 0.004284f, 0.004726f, 0.005547f, 0.006721f, 0.007595f, 0.008667f, + 0.009811f, 0.011330f, 0.012642f, 0.014130f, 0.016098f, 0.017975f, 0.019867f, 0.022247f, 0.024811f, 0.028030f, 0.031403f, 0.035461f, + 0.039642f, 0.044800f, 0.050720f, 0.057495f, 0.065002f, 0.073914f, 0.084290f, 0.095947f, 0.109985f, 0.126343f, 0.144409f, 0.166138f, + 0.190918f, 0.218750f, 0.250244f, 0.285400f, 0.323730f, 0.364258f, 0.407471f, 0.452148f, 0.496338f, 0.540527f, 0.584473f, 0.625977f, + 0.665039f, 0.701172f, 0.735352f, 0.765137f, 0.792480f, 0.817383f, 0.840332f, 0.859863f, 0.876953f, 0.893066f, 0.959961f, 0.963379f, + 0.963867f, 0.964355f, 0.963867f, 0.963867f, 0.000228f, 0.000682f, 0.001293f, 0.001717f, 0.002352f, 0.003160f, 0.003626f, 0.004360f, + 0.005348f, 0.005871f, 0.006870f, 0.007660f, 0.008957f, 0.010002f, 0.011299f, 0.012375f, 0.014099f, 0.015900f, 0.017670f, 0.019363f, + 0.022034f, 0.024216f, 0.027420f, 0.030930f, 0.034454f, 0.038910f, 0.044006f, 0.049530f, 0.055878f, 0.063477f, 0.072083f, 0.082275f, + 0.094177f, 0.107666f, 0.123840f, 0.142090f, 0.163452f, 0.188477f, 0.216919f, 0.248047f, 0.283447f, 0.322754f, 0.364990f, 0.408447f, + 0.453613f, 0.500000f, 0.544922f, 0.589355f, 0.631348f, 0.671387f, 0.708008f, 0.742188f, 0.773438f, 0.800781f, 0.824219f, 0.846680f, + 0.866699f, 0.884277f, 0.958008f, 0.960938f, 0.961426f, 0.962402f, 0.961914f, 0.960938f, 0.000239f, 0.000731f, 0.001204f, 0.001637f, + 0.002144f, 0.002913f, 0.003521f, 0.003828f, 0.004517f, 0.005291f, 0.006203f, 0.006954f, 0.007740f, 0.008911f, 0.010239f, 0.011017f, + 0.012413f, 0.013863f, 0.015396f, 0.017181f, 0.019196f, 0.021439f, 0.024078f, 0.026993f, 0.030182f, 0.033752f, 0.038055f, 0.042664f, + 0.048004f, 0.054657f, 0.061920f, 0.070312f, 0.080688f, 0.092041f, 0.105774f, 0.121094f, 0.140015f, 0.161255f, 0.186523f, 0.214966f, + 0.246948f, 0.283203f, 0.322998f, 0.365967f, 0.410400f, 0.457275f, 0.503906f, 0.550781f, 0.596191f, 0.638672f, 0.678711f, 0.716797f, + 0.750488f, 0.781738f, 0.809082f, 0.833496f, 0.855469f, 0.874512f, 0.954590f, 0.958008f, 0.958984f, 0.958984f, 0.958984f, 0.958984f, + 0.000226f, 0.000663f, 0.001073f, 0.001420f, 0.002163f, 0.002567f, 0.003052f, 0.003433f, 0.004181f, 0.004734f, 0.005516f, 0.006424f, + 0.007050f, 0.008003f, 0.008659f, 0.009827f, 0.011086f, 0.012398f, 0.013649f, 0.015266f, 0.016891f, 0.018921f, 0.021118f, 0.023560f, + 0.026505f, 0.029556f, 0.032715f, 0.036865f, 0.041077f, 0.046570f, 0.053314f, 0.060150f, 0.068787f, 0.078552f, 0.090027f, 0.103638f, + 0.119690f, 0.138184f, 0.159546f, 0.184692f, 0.213745f, 0.245972f, 0.283203f, 0.324219f, 0.367920f, 0.414062f, 0.461914f, 0.509766f, + 0.557129f, 0.604492f, 0.647461f, 0.688965f, 0.727051f, 0.761230f, 0.791504f, 0.819824f, 0.844238f, 0.865234f, 0.951660f, 0.955566f, + 0.955566f, 0.956055f, 0.955078f, 0.956543f, 0.000156f, 0.000587f, 0.001056f, 0.001499f, 0.001647f, 0.002380f, 0.002594f, 0.003469f, + 0.003777f, 0.004112f, 0.004925f, 0.005699f, 0.006180f, 0.007019f, 0.007957f, 0.008942f, 0.009560f, 0.010727f, 0.011963f, 0.013123f, + 0.014885f, 0.016556f, 0.018494f, 0.020355f, 0.022766f, 0.025330f, 0.028320f, 0.031830f, 0.035736f, 0.040161f, 0.045532f, 0.052032f, + 0.059113f, 0.066833f, 0.076782f, 0.088501f, 0.101868f, 0.117310f, 0.136108f, 0.157959f, 0.183105f, 0.212769f, 0.247070f, 0.284424f, + 0.326660f, 0.371338f, 0.419189f, 0.468994f, 0.518066f, 0.567383f, 0.613770f, 0.658691f, 0.700684f, 0.738770f, 0.771973f, 0.803223f, + 0.829590f, 0.854492f, 0.947266f, 0.952637f, 0.952637f, 0.952637f, 0.953125f, 0.952637f, 0.000155f, 0.000358f, 0.000859f, 0.001402f, + 0.001830f, 0.002092f, 0.002499f, 0.002672f, 0.003410f, 0.003763f, 0.004375f, 0.005077f, 0.005535f, 0.006554f, 0.007004f, 0.007874f, + 0.008537f, 0.009529f, 0.010742f, 0.011749f, 0.013016f, 0.014427f, 0.015945f, 0.017929f, 0.019775f, 0.022018f, 0.024460f, 0.027618f, + 0.030640f, 0.034668f, 0.039154f, 0.044250f, 0.050293f, 0.057068f, 0.065491f, 0.074951f, 0.086487f, 0.099670f, 0.115906f, 0.134277f, + 0.156860f, 0.182495f, 0.213135f, 0.248047f, 0.286621f, 0.329834f, 0.376709f, 0.426025f, 0.476562f, 0.527832f, 0.577637f, 0.626465f, + 0.671387f, 0.713379f, 0.752441f, 0.784668f, 0.815430f, 0.841797f, 0.944336f, 0.948242f, 0.949219f, 0.949219f, 0.949219f, 0.949707f, + 0.000233f, 0.000639f, 0.000930f, 0.001277f, 0.001579f, 0.001916f, 0.002041f, 0.002625f, 0.003035f, 0.003571f, 0.004124f, 0.004375f, + 0.004978f, 0.005379f, 0.006348f, 0.006886f, 0.007526f, 0.008430f, 0.009216f, 0.010262f, 0.011436f, 0.012779f, 0.014160f, 0.015549f, + 0.017120f, 0.019089f, 0.021164f, 0.023621f, 0.026352f, 0.029724f, 0.033447f, 0.037842f, 0.042603f, 0.048737f, 0.055573f, 0.063721f, + 0.073364f, 0.084778f, 0.098206f, 0.114197f, 0.133423f, 0.155762f, 0.182739f, 0.213623f, 0.249512f, 0.289795f, 0.335205f, 0.383789f, + 0.434814f, 0.487305f, 0.540039f, 0.591797f, 0.640137f, 0.686035f, 0.727539f, 0.765137f, 0.800293f, 0.830078f, 0.940430f, 0.944336f, + 0.945312f, 0.946289f, 0.945801f, 0.945312f, 0.000217f, 0.000519f, 0.000848f, 0.001180f, 0.001366f, 0.001589f, 0.001986f, 0.002354f, + 0.002987f, 0.003170f, 0.003576f, 0.003901f, 0.004440f, 0.004738f, 0.005543f, 0.006058f, 0.006508f, 0.007511f, 0.008163f, 0.009132f, + 0.010078f, 0.011246f, 0.012390f, 0.013412f, 0.014938f, 0.016632f, 0.018433f, 0.020676f, 0.022995f, 0.025726f, 0.028702f, 0.032227f, + 0.036377f, 0.041992f, 0.047394f, 0.053986f, 0.062195f, 0.071716f, 0.082825f, 0.096802f, 0.112732f, 0.132202f, 0.155273f, 0.182861f, + 0.215210f, 0.252441f, 0.294678f, 0.341553f, 0.392090f, 0.445557f, 0.499512f, 0.553711f, 0.606445f, 0.656250f, 0.703125f, 0.745605f, + 0.782715f, 0.816895f, 0.935547f, 0.939941f, 0.941406f, 0.941406f, 0.941406f, 0.940918f, 0.000242f, 0.000678f, 0.000781f, 0.000928f, + 0.001200f, 0.001592f, 0.001694f, 0.002096f, 0.002703f, 0.002903f, 0.003170f, 0.003531f, 0.003918f, 0.004433f, 0.004955f, 0.005390f, + 0.005939f, 0.006454f, 0.007298f, 0.007782f, 0.008759f, 0.009567f, 0.010559f, 0.011650f, 0.013046f, 0.014420f, 0.015793f, 0.017715f, + 0.019699f, 0.021774f, 0.024460f, 0.027481f, 0.031082f, 0.035065f, 0.039917f, 0.045715f, 0.052246f, 0.060486f, 0.070129f, 0.081482f, + 0.095093f, 0.111755f, 0.131714f, 0.155273f, 0.183838f, 0.217285f, 0.256348f, 0.300781f, 0.350342f, 0.403076f, 0.458252f, 0.514160f, + 0.570312f, 0.624512f, 0.675781f, 0.722168f, 0.763672f, 0.800293f, 0.930664f, 0.935547f, 0.937500f, 0.937012f, 0.937500f, 0.937012f, + 0.000239f, 0.000297f, 0.000667f, 0.000785f, 0.001044f, 0.001269f, 0.001569f, 0.001950f, 0.002224f, 0.002419f, 0.002810f, 0.003063f, + 0.003626f, 0.003895f, 0.004261f, 0.004749f, 0.005066f, 0.005726f, 0.006260f, 0.007019f, 0.007771f, 0.008369f, 0.008919f, 0.009941f, + 0.011101f, 0.012375f, 0.013519f, 0.015190f, 0.016891f, 0.018631f, 0.021011f, 0.023590f, 0.026581f, 0.029892f, 0.033875f, 0.038757f, + 0.044281f, 0.051147f, 0.058746f, 0.068481f, 0.079834f, 0.094116f, 0.110779f, 0.131348f, 0.155884f, 0.185669f, 0.220825f, 0.261963f, + 0.308594f, 0.360352f, 0.416260f, 0.473877f, 0.532715f, 0.589844f, 0.645508f, 0.696289f, 0.743652f, 0.784668f, 0.925781f, 0.930664f, + 0.932129f, 0.932129f, 0.932129f, 0.932129f, 0.000226f, 0.000351f, 0.000434f, 0.000624f, 0.000887f, 0.001040f, 0.001246f, 0.001665f, + 0.001856f, 0.002384f, 0.002420f, 0.002842f, 0.002874f, 0.003471f, 0.003735f, 0.004078f, 0.004639f, 0.004910f, 0.005531f, 0.006065f, + 0.006664f, 0.007370f, 0.007690f, 0.008690f, 0.009544f, 0.010536f, 0.011795f, 0.012833f, 0.014183f, 0.015900f, 0.017899f, 0.019684f, + 0.022430f, 0.025253f, 0.028412f, 0.032410f, 0.037201f, 0.042633f, 0.049316f, 0.057159f, 0.066772f, 0.078186f, 0.092590f, 0.110107f, + 0.131348f, 0.156982f, 0.188232f, 0.225342f, 0.269043f, 0.318604f, 0.373535f, 0.431641f, 0.492188f, 0.554199f, 0.613281f, 0.668945f, + 0.720703f, 0.766602f, 0.919922f, 0.925781f, 0.926758f, 0.926758f, 0.927246f, 0.926758f, 0.000000f, 0.000340f, 0.000458f, 0.000715f, + 0.000823f, 0.000895f, 0.001165f, 0.001518f, 0.001636f, 0.001876f, 0.002190f, 0.002472f, 0.002640f, 0.002964f, 0.003340f, 0.003527f, + 0.004005f, 0.004227f, 0.004803f, 0.005260f, 0.005878f, 0.006042f, 0.006805f, 0.007500f, 0.008469f, 0.009132f, 0.009949f, 0.011009f, + 0.012077f, 0.013687f, 0.014938f, 0.016785f, 0.018997f, 0.021194f, 0.023895f, 0.027283f, 0.030945f, 0.035583f, 0.040955f, 0.047760f, + 0.055573f, 0.065247f, 0.077209f, 0.091736f, 0.109619f, 0.131470f, 0.159058f, 0.192017f, 0.231812f, 0.278076f, 0.331543f, 0.389404f, + 0.450928f, 0.513672f, 0.577637f, 0.638672f, 0.695801f, 0.746582f, 0.914062f, 0.919922f, 0.920898f, 0.921387f, 0.921387f, 0.921387f, + 0.000146f, 0.000319f, 0.000443f, 0.000458f, 0.000704f, 0.000894f, 0.001199f, 0.001324f, 0.001549f, 0.001592f, 0.002081f, 0.002092f, + 0.002237f, 0.002604f, 0.002815f, 0.003159f, 0.003510f, 0.003937f, 0.004147f, 0.004425f, 0.004814f, 0.005318f, 0.005878f, 0.006413f, + 0.006924f, 0.007782f, 0.008408f, 0.009239f, 0.010414f, 0.011505f, 0.012642f, 0.014015f, 0.015884f, 0.017563f, 0.019852f, 0.022598f, + 0.025650f, 0.029663f, 0.033875f, 0.039307f, 0.045898f, 0.053955f, 0.063782f, 0.075928f, 0.090820f, 0.109497f, 0.132690f, 0.161621f, + 0.196777f, 0.239624f, 0.290039f, 0.346436f, 0.408203f, 0.473633f, 0.540527f, 0.605957f, 0.667969f, 0.725586f, 0.907715f, 0.914062f, + 0.914062f, 0.915039f, 0.915039f, 0.915039f, 0.000121f, 0.000251f, 0.000506f, 0.000532f, 0.000665f, 0.000830f, 0.001190f, 0.001164f, + 0.001290f, 0.001413f, 0.001755f, 0.001900f, 0.002157f, 0.002319f, 0.002422f, 0.002853f, 0.003042f, 0.003254f, 0.003529f, 0.003725f, + 0.004288f, 0.004585f, 0.005043f, 0.005539f, 0.005970f, 0.006386f, 0.007126f, 0.007812f, 0.008652f, 0.009598f, 0.010651f, 0.011803f, + 0.013130f, 0.014702f, 0.016510f, 0.018814f, 0.021011f, 0.024368f, 0.028122f, 0.032379f, 0.037506f, 0.044128f, 0.052277f, 0.062042f, + 0.075073f, 0.090088f, 0.110107f, 0.134766f, 0.165405f, 0.203613f, 0.249268f, 0.303955f, 0.365234f, 0.431396f, 0.501465f, 0.571777f, + 0.638672f, 0.702148f, 0.900879f, 0.906738f, 0.907227f, 0.908203f, 0.907227f, 0.908203f, 0.000241f, 0.000122f, 0.000417f, 0.000505f, + 0.000741f, 0.000782f, 0.000916f, 0.001145f, 0.001189f, 0.001289f, 0.001331f, 0.001565f, 0.001779f, 0.002020f, 0.002171f, 0.002228f, + 0.002623f, 0.002752f, 0.002949f, 0.003157f, 0.003515f, 0.003847f, 0.004082f, 0.004429f, 0.004990f, 0.005405f, 0.006008f, 0.006603f, + 0.007103f, 0.007889f, 0.008789f, 0.009766f, 0.010605f, 0.012177f, 0.013672f, 0.015305f, 0.017487f, 0.019913f, 0.022781f, 0.026245f, + 0.030670f, 0.035980f, 0.042389f, 0.050812f, 0.060883f, 0.073792f, 0.090088f, 0.111145f, 0.138062f, 0.171143f, 0.212524f, 0.262695f, + 0.322266f, 0.388184f, 0.460205f, 0.533203f, 0.606445f, 0.676758f, 0.893066f, 0.898926f, 0.899414f, 0.899414f, 0.900879f, 0.900391f, + 0.000000f, 0.000114f, 0.000227f, 0.000407f, 0.000532f, 0.000732f, 0.000714f, 0.000922f, 0.000993f, 0.001072f, 0.001190f, 0.001412f, + 0.001569f, 0.001726f, 0.001959f, 0.002071f, 0.002159f, 0.002350f, 0.002565f, 0.002729f, 0.003090f, 0.003248f, 0.003702f, 0.003761f, + 0.004192f, 0.004585f, 0.004925f, 0.005272f, 0.005966f, 0.006405f, 0.007275f, 0.007965f, 0.008850f, 0.009872f, 0.011017f, 0.012383f, + 0.014275f, 0.015900f, 0.018463f, 0.021194f, 0.024673f, 0.028870f, 0.034271f, 0.040955f, 0.048981f, 0.059723f, 0.073059f, 0.090149f, + 0.112549f, 0.141357f, 0.178467f, 0.223755f, 0.280029f, 0.345215f, 0.417969f, 0.494385f, 0.572266f, 0.648438f, 0.884277f, 0.890137f, + 0.891602f, 0.891602f, 0.893066f, 0.892090f, 0.000000f, 0.000219f, 0.000211f, 0.000333f, 0.000559f, 0.000609f, 0.000788f, 0.000805f, + 0.000869f, 0.000903f, 0.001101f, 0.001166f, 0.001302f, 0.001399f, 0.001456f, 0.001668f, 0.001853f, 0.001999f, 0.002102f, 0.002256f, + 0.002447f, 0.002728f, 0.002943f, 0.003178f, 0.003515f, 0.003836f, 0.004074f, 0.004475f, 0.004745f, 0.005325f, 0.005970f, 0.006569f, + 0.007248f, 0.008102f, 0.008888f, 0.010132f, 0.011169f, 0.012947f, 0.014763f, 0.016891f, 0.019760f, 0.023087f, 0.027176f, 0.032562f, + 0.038940f, 0.047516f, 0.058167f, 0.072754f, 0.090698f, 0.114929f, 0.146851f, 0.187744f, 0.239258f, 0.301514f, 0.373291f, 0.452637f, + 0.535645f, 0.617676f, 0.874512f, 0.880859f, 0.882324f, 0.883301f, 0.883301f, 0.882324f, 0.000204f, 0.000207f, 0.000204f, 0.000322f, + 0.000435f, 0.000480f, 0.000556f, 0.000615f, 0.000747f, 0.000782f, 0.000844f, 0.001006f, 0.001159f, 0.001191f, 0.001231f, 0.001450f, + 0.001585f, 0.001633f, 0.001790f, 0.001919f, 0.002117f, 0.002298f, 0.002432f, 0.002651f, 0.002939f, 0.003172f, 0.003399f, 0.003614f, + 0.003944f, 0.004421f, 0.004704f, 0.005203f, 0.005886f, 0.006454f, 0.007160f, 0.008049f, 0.009041f, 0.010201f, 0.011627f, 0.013237f, + 0.015404f, 0.018097f, 0.021469f, 0.025284f, 0.030884f, 0.036987f, 0.045990f, 0.056915f, 0.072083f, 0.092163f, 0.119141f, 0.154419f, + 0.200928f, 0.259277f, 0.328857f, 0.409424f, 0.495605f, 0.584473f, 0.864258f, 0.871094f, 0.872070f, 0.873047f, 0.872559f, 0.873047f, + 0.000000f, 0.000044f, 0.000176f, 0.000290f, 0.000410f, 0.000390f, 0.000513f, 0.000546f, 0.000647f, 0.000680f, 0.000827f, 0.000858f, + 0.000958f, 0.001131f, 0.001102f, 0.001223f, 0.001367f, 0.001401f, 0.001525f, 0.001610f, 0.001826f, 0.001821f, 0.002039f, 0.002253f, + 0.002459f, 0.002617f, 0.002708f, 0.003036f, 0.003279f, 0.003431f, 0.003805f, 0.004219f, 0.004471f, 0.004929f, 0.005569f, 0.006310f, + 0.007107f, 0.007988f, 0.009003f, 0.010384f, 0.011856f, 0.014015f, 0.016418f, 0.019669f, 0.023666f, 0.028809f, 0.035583f, 0.044159f, + 0.056458f, 0.072571f, 0.094604f, 0.124329f, 0.164917f, 0.218018f, 0.284912f, 0.364746f, 0.454102f, 0.549316f, 0.853027f, 0.859863f, + 0.861328f, 0.861816f, 0.861816f, 0.861816f, 0.000000f, 0.000069f, 0.000120f, 0.000345f, 0.000371f, 0.000398f, 0.000452f, 0.000396f, + 0.000498f, 0.000530f, 0.000596f, 0.000648f, 0.000781f, 0.000921f, 0.000995f, 0.001007f, 0.001101f, 0.001146f, 0.001282f, 0.001278f, + 0.001471f, 0.001554f, 0.001710f, 0.001811f, 0.001995f, 0.001986f, 0.002314f, 0.002399f, 0.002499f, 0.002903f, 0.002975f, 0.003305f, + 0.003605f, 0.004086f, 0.004425f, 0.005081f, 0.005402f, 0.006035f, 0.006889f, 0.007755f, 0.009041f, 0.010422f, 0.012672f, 0.014885f, + 0.017746f, 0.021530f, 0.026733f, 0.033691f, 0.043060f, 0.055847f, 0.073181f, 0.097473f, 0.132324f, 0.179077f, 0.241821f, 0.320068f, + 0.410400f, 0.510742f, 0.839844f, 0.847656f, 0.849121f, 0.849609f, 0.849121f, 0.849609f, 0.000000f, 0.000000f, 0.000121f, 0.000243f, + 0.000321f, 0.000354f, 0.000341f, 0.000431f, 0.000423f, 0.000444f, 0.000473f, 0.000508f, 0.000595f, 0.000706f, 0.000737f, 0.000861f, + 0.000869f, 0.000926f, 0.001055f, 0.001104f, 0.001199f, 0.001306f, 0.001360f, 0.001433f, 0.001530f, 0.001555f, 0.001673f, 0.001942f, + 0.002138f, 0.002247f, 0.002562f, 0.002609f, 0.002911f, 0.003204f, 0.003466f, 0.003757f, 0.004192f, 0.004845f, 0.005482f, 0.006008f, + 0.006874f, 0.007904f, 0.009171f, 0.011124f, 0.013260f, 0.015839f, 0.019821f, 0.024872f, 0.031982f, 0.041534f, 0.055054f, 0.075012f, + 0.103516f, 0.143677f, 0.199951f, 0.273438f, 0.364502f, 0.469482f, 0.825684f, 0.834473f, 0.834961f, 0.835938f, 0.835938f, 0.835938f, + 0.000000f, 0.000000f, 0.000000f, 0.000120f, 0.000199f, 0.000272f, 0.000265f, 0.000363f, 0.000379f, 0.000388f, 0.000489f, 0.000500f, + 0.000488f, 0.000569f, 0.000604f, 0.000700f, 0.000683f, 0.000720f, 0.000784f, 0.000844f, 0.001009f, 0.001047f, 0.001108f, 0.001258f, + 0.001276f, 0.001388f, 0.001410f, 0.001565f, 0.001592f, 0.001814f, 0.001800f, 0.002167f, 0.002192f, 0.002556f, 0.002665f, 0.002905f, + 0.003195f, 0.003574f, 0.004028f, 0.004513f, 0.005127f, 0.005859f, 0.006847f, 0.008018f, 0.009491f, 0.011452f, 0.014099f, 0.017792f, + 0.022995f, 0.030258f, 0.040588f, 0.055878f, 0.078308f, 0.111450f, 0.160278f, 0.229248f, 0.318359f, 0.425781f, 0.810547f, 0.818359f, + 0.820312f, 0.821777f, 0.821777f, 0.820801f, 0.000000f, 0.000121f, 0.000120f, 0.000172f, 0.000195f, 0.000171f, 0.000208f, 0.000272f, + 0.000316f, 0.000333f, 0.000348f, 0.000355f, 0.000412f, 0.000410f, 0.000515f, 0.000485f, 0.000545f, 0.000656f, 0.000777f, 0.000659f, + 0.000705f, 0.000762f, 0.000874f, 0.000927f, 0.000959f, 0.000978f, 0.001045f, 0.001228f, 0.001294f, 0.001398f, 0.001443f, 0.001637f, + 0.001752f, 0.001925f, 0.002005f, 0.002230f, 0.002407f, 0.002670f, 0.002895f, 0.003267f, 0.003933f, 0.004280f, 0.005051f, 0.005772f, + 0.006718f, 0.008141f, 0.010117f, 0.012383f, 0.015930f, 0.020920f, 0.028671f, 0.039673f, 0.056702f, 0.083313f, 0.124695f, 0.185791f, + 0.270996f, 0.379639f, 0.793457f, 0.801270f, 0.803711f, 0.803711f, 0.804688f, 0.804688f, 0.000000f, 0.000121f, 0.000119f, 0.000144f, + 0.000149f, 0.000166f, 0.000173f, 0.000167f, 0.000214f, 0.000245f, 0.000334f, 0.000287f, 0.000303f, 0.000391f, 0.000401f, 0.000440f, + 0.000469f, 0.000493f, 0.000534f, 0.000513f, 0.000690f, 0.000682f, 0.000645f, 0.000712f, 0.000715f, 0.000747f, 0.000842f, 0.000849f, + 0.000967f, 0.000995f, 0.001178f, 0.001167f, 0.001273f, 0.001395f, 0.001586f, 0.001748f, 0.001796f, 0.001986f, 0.002132f, 0.002476f, + 0.002893f, 0.003294f, 0.003653f, 0.004086f, 0.004890f, 0.005821f, 0.006927f, 0.008553f, 0.010857f, 0.014137f, 0.019211f, 0.027084f, + 0.039642f, 0.059448f, 0.092468f, 0.144775f, 0.224487f, 0.332764f, 0.775391f, 0.784668f, 0.786133f, 0.786133f, 0.787109f, 0.786621f, + 0.000000f, 0.000000f, 0.000118f, 0.000116f, 0.000115f, 0.000113f, 0.000140f, 0.000140f, 0.000149f, 0.000220f, 0.000171f, 0.000255f, + 0.000274f, 0.000292f, 0.000318f, 0.000295f, 0.000346f, 0.000352f, 0.000380f, 0.000406f, 0.000401f, 0.000533f, 0.000490f, 0.000551f, + 0.000558f, 0.000648f, 0.000628f, 0.000723f, 0.000788f, 0.000749f, 0.000836f, 0.000941f, 0.000997f, 0.001065f, 0.001112f, 0.001207f, + 0.001328f, 0.001535f, 0.001621f, 0.001840f, 0.002022f, 0.002163f, 0.002522f, 0.002825f, 0.003391f, 0.003830f, 0.004616f, 0.005665f, + 0.007172f, 0.009247f, 0.012482f, 0.017532f, 0.025970f, 0.040161f, 0.064941f, 0.107422f, 0.178833f, 0.283447f, 0.754883f, 0.764648f, + 0.766113f, 0.767090f, 0.767578f, 0.767090f, 0.000000f, 0.000119f, 0.000116f, 0.000114f, 0.000112f, 0.000110f, 0.000109f, 0.000117f, + 0.000114f, 0.000117f, 0.000125f, 0.000193f, 0.000141f, 0.000196f, 0.000221f, 0.000235f, 0.000259f, 0.000278f, 0.000308f, 0.000316f, + 0.000323f, 0.000315f, 0.000329f, 0.000351f, 0.000388f, 0.000422f, 0.000465f, 0.000512f, 0.000571f, 0.000568f, 0.000588f, 0.000633f, + 0.000747f, 0.000751f, 0.000829f, 0.000958f, 0.000914f, 0.001104f, 0.001145f, 0.001255f, 0.001337f, 0.001499f, 0.001701f, 0.001966f, + 0.002275f, 0.002609f, 0.003119f, 0.003773f, 0.004658f, 0.005920f, 0.007935f, 0.010948f, 0.015900f, 0.025284f, 0.042511f, 0.075012f, + 0.135010f, 0.234619f, 0.733398f, 0.743164f, 0.744629f, 0.745117f, 0.745605f, 0.745605f, 0.000000f, 0.000116f, 0.000113f, 0.000111f, + 0.000108f, 0.000106f, 0.000104f, 0.000103f, 0.000098f, 0.000092f, 0.000099f, 0.000085f, 0.000098f, 0.000105f, 0.000163f, 0.000162f, + 0.000128f, 0.000193f, 0.000203f, 0.000214f, 0.000284f, 0.000239f, 0.000303f, 0.000268f, 0.000327f, 0.000326f, 0.000329f, 0.000330f, + 0.000407f, 0.000486f, 0.000406f, 0.000454f, 0.000465f, 0.000495f, 0.000535f, 0.000592f, 0.000648f, 0.000727f, 0.000753f, 0.000807f, + 0.000956f, 0.000992f, 0.001108f, 0.001294f, 0.001418f, 0.001703f, 0.001978f, 0.002390f, 0.002930f, 0.003643f, 0.004753f, 0.006519f, + 0.009499f, 0.014824f, 0.025497f, 0.048065f, 0.095154f, 0.185425f, 0.709961f, 0.719727f, 0.721191f, 0.721191f, 0.721680f, 0.721680f, + 0.000000f, 0.000113f, 0.000107f, 0.000106f, 0.000102f, 0.000100f, 0.000097f, 0.000096f, 0.000095f, 0.000092f, 0.000087f, 0.000083f, + 0.000078f, 0.000098f, 0.000077f, 0.000091f, 0.000114f, 0.000128f, 0.000114f, 0.000147f, 0.000154f, 0.000162f, 0.000186f, 0.000174f, + 0.000220f, 0.000233f, 0.000235f, 0.000245f, 0.000250f, 0.000253f, 0.000321f, 0.000296f, 0.000311f, 0.000354f, 0.000417f, 0.000419f, + 0.000438f, 0.000443f, 0.000495f, 0.000513f, 0.000585f, 0.000634f, 0.000705f, 0.000778f, 0.000912f, 0.001002f, 0.001163f, 0.001379f, + 0.001745f, 0.002092f, 0.002697f, 0.003721f, 0.005230f, 0.008194f, 0.013870f, 0.027359f, 0.061066f, 0.138062f, 0.685547f, 0.694336f, + 0.696777f, 0.696289f, 0.697754f, 0.697754f, 0.000000f, 0.000106f, 0.000102f, 0.000097f, 0.000093f, 0.000091f, 0.000089f, 0.000087f, + 0.000085f, 0.000084f, 0.000082f, 0.000080f, 0.000076f, 0.000072f, 0.000069f, 0.000074f, 0.000076f, 0.000059f, 0.000075f, 0.000062f, + 0.000085f, 0.000091f, 0.000103f, 0.000111f, 0.000121f, 0.000135f, 0.000128f, 0.000159f, 0.000171f, 0.000160f, 0.000178f, 0.000193f, + 0.000196f, 0.000202f, 0.000220f, 0.000230f, 0.000273f, 0.000289f, 0.000312f, 0.000330f, 0.000335f, 0.000397f, 0.000408f, 0.000463f, + 0.000517f, 0.000577f, 0.000691f, 0.000771f, 0.000919f, 0.001150f, 0.001436f, 0.001955f, 0.002737f, 0.004185f, 0.007103f, 0.013863f, + 0.033661f, 0.093628f, 0.657227f, 0.667480f, 0.668945f, 0.669434f, 0.670898f, 0.669922f, 0.000108f, 0.000093f, 0.000087f, 0.000082f, + 0.000079f, 0.000078f, 0.000075f, 0.000073f, 0.000071f, 0.000070f, 0.000069f, 0.000069f, 0.000067f, 0.000066f, 0.000064f, 0.000061f, + 0.000059f, 0.000056f, 0.000053f, 0.000051f, 0.000053f, 0.000049f, 0.000044f, 0.000047f, 0.000055f, 0.000058f, 0.000071f, 0.000077f, + 0.000093f, 0.000094f, 0.000103f, 0.000102f, 0.000110f, 0.000126f, 0.000130f, 0.000138f, 0.000143f, 0.000166f, 0.000166f, 0.000178f, + 0.000194f, 0.000217f, 0.000228f, 0.000231f, 0.000265f, 0.000330f, 0.000341f, 0.000411f, 0.000459f, 0.000549f, 0.000705f, 0.000867f, + 0.001228f, 0.001863f, 0.003143f, 0.006283f, 0.015594f, 0.054993f, 0.628418f, 0.638184f, 0.640137f, 0.640137f, 0.641602f, 0.641602f, + 0.000071f, 0.000058f, 0.000059f, 0.000058f, 0.000054f, 0.000054f, 0.000051f, 0.000053f, 0.000051f, 0.000052f, 0.000050f, 0.000050f, + 0.000051f, 0.000050f, 0.000049f, 0.000049f, 0.000049f, 0.000049f, 0.000047f, 0.000045f, 0.000043f, 0.000041f, 0.000039f, 0.000038f, + 0.000036f, 0.000034f, 0.000035f, 0.000037f, 0.000033f, 0.000034f, 0.000038f, 0.000047f, 0.000054f, 0.000061f, 0.000064f, 0.000068f, + 0.000069f, 0.000076f, 0.000083f, 0.000092f, 0.000098f, 0.000103f, 0.000112f, 0.000129f, 0.000113f, 0.000139f, 0.000152f, 0.000185f, + 0.000204f, 0.000238f, 0.000282f, 0.000365f, 0.000503f, 0.000685f, 0.001178f, 0.002274f, 0.006100f, 0.025162f, 0.597656f, 0.607910f, + 0.610840f, 0.611816f, 0.610352f, 0.611328f, 0.000000f, 0.000000f, 0.000004f, 0.000012f, 0.000014f, 0.000020f, 0.000022f, 0.000023f, + 0.000024f, 0.000022f, 0.000025f, 0.000027f, 0.000027f, 0.000026f, 0.000028f, 0.000029f, 0.000029f, 0.000029f, 0.000030f, 0.000030f, + 0.000030f, 0.000030f, 0.000030f, 0.000030f, 0.000029f, 0.000028f, 0.000027f, 0.000026f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, + 0.000020f, 0.000019f, 0.000018f, 0.000019f, 0.000023f, 0.000024f, 0.000027f, 0.000032f, 0.000038f, 0.000040f, 0.000041f, 0.000045f, + 0.000054f, 0.000052f, 0.000055f, 0.000060f, 0.000068f, 0.000089f, 0.000089f, 0.000115f, 0.000146f, 0.000198f, 0.000318f, 0.000586f, + 0.001614f, 0.008278f, 0.565918f, 0.576660f, 0.578125f, 0.579102f, 0.579590f, 0.580078f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, + 0.000003f, 0.000003f, 0.000005f, 0.000005f, 0.000006f, 0.000007f, 0.000009f, 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000012f, + 0.000013f, 0.000014f, 0.000014f, 0.000015f, 0.000014f, 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, + 0.000009f, 0.000009f, 0.000008f, 0.000010f, 0.000013f, 0.000013f, 0.000013f, 0.000017f, 0.000017f, 0.000022f, 0.000021f, 0.000023f, + 0.000031f, 0.000032f, 0.000049f, 0.000079f, 0.000204f, 0.001328f, 0.533203f, 0.543945f, 0.545410f, 0.546387f, 0.546875f, 0.546875f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000003f, + 0.000003f, 0.000003f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000016f, 0.499756f, 0.510254f, + 0.513184f, 0.513672f, 0.514160f, 0.514160f, + }, + { + 0.076172f, 0.209839f, 0.320312f, 0.408691f, 0.481689f, 0.541016f, 0.591309f, 0.633789f, 0.668945f, 0.699707f, 0.727051f, 0.749512f, + 0.770020f, 0.788086f, 0.803711f, 0.817871f, 0.832520f, 0.843750f, 0.854492f, 0.864258f, 0.873535f, 0.881836f, 0.889160f, 0.895996f, + 0.903320f, 0.909180f, 0.914551f, 0.920410f, 0.925781f, 0.929199f, 0.933594f, 0.938965f, 0.942383f, 0.946289f, 0.949219f, 0.953125f, + 0.955566f, 0.959473f, 0.961914f, 0.964355f, 0.967285f, 0.970215f, 0.971680f, 0.974609f, 0.976562f, 0.978516f, 0.980469f, 0.982422f, + 0.984375f, 0.986328f, 0.987793f, 0.989746f, 0.990723f, 0.992676f, 0.993652f, 0.995117f, 0.996582f, 0.998047f, 0.999023f, 0.997559f, + 0.996582f, 0.995605f, 0.994629f, 0.993652f, 0.043396f, 0.133301f, 0.221313f, 0.303223f, 0.377441f, 0.442871f, 0.500000f, 0.550781f, + 0.595215f, 0.632812f, 0.666992f, 0.696777f, 0.723145f, 0.745605f, 0.765137f, 0.783691f, 0.799805f, 0.815430f, 0.828613f, 0.839844f, + 0.851562f, 0.861328f, 0.871582f, 0.879395f, 0.887207f, 0.894531f, 0.901855f, 0.907227f, 0.914062f, 0.919434f, 0.924316f, 0.928711f, + 0.933594f, 0.937988f, 0.942383f, 0.945801f, 0.949219f, 0.953125f, 0.956055f, 0.959473f, 0.962402f, 0.964355f, 0.967773f, 0.970215f, + 0.972656f, 0.975098f, 0.977051f, 0.979492f, 0.980957f, 0.983398f, 0.985352f, 0.986816f, 0.988281f, 0.990234f, 0.991699f, 0.993652f, + 0.995117f, 0.996094f, 0.998047f, 0.997070f, 0.996094f, 0.995117f, 0.994141f, 0.993164f, 0.027832f, 0.088440f, 0.153198f, 0.221313f, + 0.288086f, 0.352051f, 0.411621f, 0.466797f, 0.515625f, 0.561523f, 0.601074f, 0.637207f, 0.667969f, 0.695312f, 0.721680f, 0.743652f, + 0.763184f, 0.781738f, 0.797852f, 0.812500f, 0.826172f, 0.838867f, 0.850098f, 0.859863f, 0.869141f, 0.877930f, 0.886230f, 0.893555f, + 0.900879f, 0.907227f, 0.912598f, 0.918457f, 0.922852f, 0.928711f, 0.934082f, 0.938477f, 0.942383f, 0.946289f, 0.950195f, 0.953125f, + 0.956543f, 0.959961f, 0.962402f, 0.965820f, 0.968262f, 0.970703f, 0.973145f, 0.975586f, 0.978027f, 0.979980f, 0.982422f, 0.984375f, + 0.985840f, 0.987793f, 0.989746f, 0.991211f, 0.993164f, 0.994141f, 0.997559f, 0.996582f, 0.995605f, 0.994629f, 0.993652f, 0.993164f, + 0.018921f, 0.061493f, 0.109497f, 0.161987f, 0.217041f, 0.273438f, 0.330811f, 0.384521f, 0.437500f, 0.486084f, 0.530273f, 0.570312f, + 0.607910f, 0.640137f, 0.670410f, 0.697266f, 0.722656f, 0.743652f, 0.763672f, 0.781250f, 0.797363f, 0.812012f, 0.825684f, 0.837891f, + 0.848633f, 0.859863f, 0.869141f, 0.878418f, 0.886719f, 0.893066f, 0.900879f, 0.906738f, 0.913574f, 0.919434f, 0.924316f, 0.930176f, + 0.934082f, 0.939453f, 0.942871f, 0.946777f, 0.950684f, 0.954590f, 0.958008f, 0.960449f, 0.963379f, 0.966797f, 0.969238f, 0.971680f, + 0.974121f, 0.977051f, 0.978516f, 0.980957f, 0.983398f, 0.985352f, 0.987305f, 0.989258f, 0.991211f, 0.992676f, 0.996094f, 0.995605f, + 0.994629f, 0.993652f, 0.993164f, 0.992188f, 0.013596f, 0.044495f, 0.080017f, 0.119873f, 0.164307f, 0.211670f, 0.261475f, 0.311523f, + 0.362793f, 0.410645f, 0.458008f, 0.501953f, 0.542969f, 0.580078f, 0.614746f, 0.645996f, 0.674805f, 0.701172f, 0.723633f, 0.745117f, + 0.765625f, 0.782227f, 0.798828f, 0.812988f, 0.826172f, 0.838867f, 0.849609f, 0.861328f, 0.870605f, 0.878906f, 0.887695f, 0.895020f, + 0.901855f, 0.907715f, 0.914551f, 0.920898f, 0.925781f, 0.930664f, 0.934570f, 0.940918f, 0.943848f, 0.947754f, 0.951660f, 0.955566f, + 0.958984f, 0.961914f, 0.964844f, 0.967773f, 0.970703f, 0.973145f, 0.975586f, 0.978027f, 0.979980f, 0.982422f, 0.984863f, 0.986328f, + 0.988770f, 0.990234f, 0.995117f, 0.995117f, 0.994141f, 0.993652f, 0.992676f, 0.991699f, 0.010414f, 0.033203f, 0.060364f, 0.090942f, + 0.125610f, 0.163818f, 0.206421f, 0.250488f, 0.295898f, 0.341797f, 0.388428f, 0.433350f, 0.475830f, 0.517090f, 0.555176f, 0.589844f, + 0.622559f, 0.652344f, 0.680176f, 0.704590f, 0.729004f, 0.748535f, 0.767578f, 0.784668f, 0.800293f, 0.814941f, 0.828125f, 0.839844f, + 0.852051f, 0.861816f, 0.871582f, 0.879883f, 0.888672f, 0.895996f, 0.903320f, 0.909180f, 0.916016f, 0.921387f, 0.927246f, 0.931641f, + 0.937012f, 0.940918f, 0.946289f, 0.950195f, 0.953125f, 0.957520f, 0.960449f, 0.963867f, 0.966309f, 0.969238f, 0.972168f, 0.975098f, + 0.976562f, 0.979492f, 0.981934f, 0.983887f, 0.985840f, 0.988281f, 0.994629f, 0.994141f, 0.993652f, 0.992676f, 0.991699f, 0.990723f, + 0.007889f, 0.025772f, 0.046539f, 0.070312f, 0.097168f, 0.128540f, 0.162354f, 0.200195f, 0.239868f, 0.281738f, 0.325195f, 0.368896f, + 0.411621f, 0.453125f, 0.493652f, 0.531738f, 0.566406f, 0.601074f, 0.631836f, 0.659668f, 0.687988f, 0.709961f, 0.732422f, 0.753418f, + 0.770996f, 0.788086f, 0.804199f, 0.818359f, 0.831543f, 0.843750f, 0.854492f, 0.864746f, 0.873535f, 0.882812f, 0.890137f, 0.898438f, + 0.905273f, 0.912598f, 0.917969f, 0.923828f, 0.929199f, 0.934570f, 0.938477f, 0.942871f, 0.948242f, 0.951660f, 0.955078f, 0.958496f, + 0.961914f, 0.965332f, 0.968262f, 0.971680f, 0.973633f, 0.976562f, 0.979492f, 0.981445f, 0.983398f, 0.985352f, 0.993164f, 0.993164f, + 0.992676f, 0.991699f, 0.991211f, 0.990234f, 0.006332f, 0.020325f, 0.036438f, 0.055573f, 0.077026f, 0.101562f, 0.129028f, 0.160278f, + 0.194458f, 0.230347f, 0.268555f, 0.309326f, 0.350830f, 0.391846f, 0.432373f, 0.472412f, 0.509277f, 0.545410f, 0.579102f, 0.611816f, + 0.640625f, 0.668945f, 0.693848f, 0.716797f, 0.739258f, 0.758789f, 0.775879f, 0.793945f, 0.807617f, 0.821777f, 0.834961f, 0.846680f, + 0.857422f, 0.867676f, 0.877441f, 0.885742f, 0.893555f, 0.900391f, 0.908203f, 0.915039f, 0.920898f, 0.926270f, 0.931152f, 0.937012f, + 0.940918f, 0.946289f, 0.949219f, 0.954102f, 0.958008f, 0.960938f, 0.964355f, 0.967773f, 0.970703f, 0.973145f, 0.975586f, 0.978516f, + 0.981445f, 0.983398f, 0.992188f, 0.992188f, 0.991699f, 0.990723f, 0.990723f, 0.989746f, 0.005226f, 0.016647f, 0.029556f, 0.044434f, + 0.061523f, 0.081543f, 0.103760f, 0.129150f, 0.157837f, 0.188477f, 0.221924f, 0.257812f, 0.295654f, 0.334473f, 0.374023f, 0.412842f, + 0.451904f, 0.489990f, 0.525391f, 0.560059f, 0.593262f, 0.623047f, 0.651855f, 0.678223f, 0.702148f, 0.725098f, 0.745605f, 0.764160f, + 0.781738f, 0.799316f, 0.812500f, 0.827148f, 0.838867f, 0.851074f, 0.861328f, 0.871582f, 0.880371f, 0.889648f, 0.896973f, 0.904297f, + 0.911621f, 0.917480f, 0.923340f, 0.929688f, 0.934570f, 0.939941f, 0.943848f, 0.948242f, 0.951660f, 0.957031f, 0.959473f, 0.963379f, + 0.966797f, 0.969727f, 0.972656f, 0.976074f, 0.979004f, 0.980957f, 0.991699f, 0.991211f, 0.990723f, 0.990234f, 0.989746f, 0.988770f, + 0.004108f, 0.013542f, 0.023819f, 0.036194f, 0.050262f, 0.066223f, 0.084717f, 0.104797f, 0.128174f, 0.153809f, 0.182861f, 0.213989f, + 0.247437f, 0.282471f, 0.319580f, 0.357422f, 0.395508f, 0.433350f, 0.470947f, 0.506348f, 0.542480f, 0.575684f, 0.605957f, 0.635254f, + 0.662109f, 0.687988f, 0.711426f, 0.732910f, 0.753418f, 0.771973f, 0.789062f, 0.804688f, 0.819336f, 0.831543f, 0.843750f, 0.855469f, + 0.866211f, 0.875488f, 0.884766f, 0.893066f, 0.901367f, 0.907715f, 0.914062f, 0.921387f, 0.927246f, 0.932129f, 0.937012f, 0.942383f, + 0.946777f, 0.951660f, 0.956055f, 0.959473f, 0.962891f, 0.966309f, 0.969238f, 0.972168f, 0.975098f, 0.978027f, 0.989746f, 0.990234f, + 0.990234f, 0.989258f, 0.989258f, 0.988281f, 0.003597f, 0.011330f, 0.020065f, 0.029938f, 0.041412f, 0.054504f, 0.068970f, 0.086182f, + 0.105469f, 0.126709f, 0.151123f, 0.177612f, 0.206909f, 0.237915f, 0.271484f, 0.305664f, 0.342529f, 0.378906f, 0.416748f, 0.453125f, + 0.489502f, 0.524414f, 0.558105f, 0.589844f, 0.619629f, 0.646973f, 0.673828f, 0.698242f, 0.721191f, 0.742676f, 0.761230f, 0.778809f, + 0.796387f, 0.810547f, 0.824707f, 0.837891f, 0.850098f, 0.861328f, 0.871094f, 0.881348f, 0.889648f, 0.896973f, 0.904785f, 0.912109f, + 0.919434f, 0.924316f, 0.931152f, 0.936523f, 0.941895f, 0.946289f, 0.951172f, 0.955078f, 0.959473f, 0.962402f, 0.965820f, 0.969238f, + 0.972656f, 0.975586f, 0.988770f, 0.989258f, 0.989258f, 0.988770f, 0.987793f, 0.987305f, 0.002836f, 0.009857f, 0.016693f, 0.025208f, + 0.034668f, 0.045288f, 0.057617f, 0.071106f, 0.087463f, 0.104858f, 0.125000f, 0.147461f, 0.172119f, 0.199829f, 0.229248f, 0.260742f, + 0.294434f, 0.329102f, 0.365479f, 0.400879f, 0.437012f, 0.472656f, 0.508301f, 0.541992f, 0.574219f, 0.604980f, 0.634766f, 0.660645f, + 0.686523f, 0.709473f, 0.731445f, 0.751953f, 0.770996f, 0.789062f, 0.804199f, 0.817871f, 0.832520f, 0.844727f, 0.856445f, 0.867188f, + 0.876953f, 0.886719f, 0.895020f, 0.902832f, 0.909668f, 0.916504f, 0.923340f, 0.929688f, 0.935547f, 0.939941f, 0.944824f, 0.949707f, + 0.954102f, 0.958496f, 0.961914f, 0.965820f, 0.969238f, 0.972656f, 0.987793f, 0.988281f, 0.988281f, 0.987793f, 0.986816f, 0.986328f, + 0.002541f, 0.008118f, 0.014244f, 0.021194f, 0.029480f, 0.037811f, 0.048584f, 0.060028f, 0.073242f, 0.088196f, 0.104370f, 0.123047f, + 0.144531f, 0.167114f, 0.193237f, 0.220947f, 0.250977f, 0.282227f, 0.316162f, 0.351074f, 0.386719f, 0.422119f, 0.457520f, 0.492432f, + 0.526367f, 0.559082f, 0.590332f, 0.621094f, 0.648438f, 0.674316f, 0.698730f, 0.721191f, 0.742188f, 0.762207f, 0.780762f, 0.797363f, + 0.812500f, 0.826172f, 0.840332f, 0.852051f, 0.863770f, 0.873535f, 0.883301f, 0.892090f, 0.900391f, 0.908203f, 0.915039f, 0.922363f, + 0.928711f, 0.933594f, 0.939453f, 0.944824f, 0.950195f, 0.953125f, 0.958008f, 0.962402f, 0.965332f, 0.969238f, 0.986816f, 0.987305f, + 0.986816f, 0.986328f, 0.985840f, 0.984863f, 0.002115f, 0.007030f, 0.012138f, 0.017944f, 0.024521f, 0.032318f, 0.040955f, 0.050476f, + 0.061676f, 0.073914f, 0.087769f, 0.103271f, 0.121033f, 0.140747f, 0.162598f, 0.187256f, 0.213379f, 0.242065f, 0.272705f, 0.305176f, + 0.338623f, 0.373047f, 0.408691f, 0.443848f, 0.478760f, 0.512695f, 0.545898f, 0.577637f, 0.607910f, 0.636719f, 0.663086f, 0.688965f, + 0.712402f, 0.734863f, 0.754395f, 0.774414f, 0.791016f, 0.806641f, 0.822266f, 0.835449f, 0.848145f, 0.859863f, 0.870605f, 0.880371f, + 0.890137f, 0.898438f, 0.906250f, 0.914551f, 0.921387f, 0.926758f, 0.933594f, 0.938965f, 0.944336f, 0.949219f, 0.954102f, 0.958984f, + 0.961914f, 0.965820f, 0.985840f, 0.986328f, 0.985840f, 0.985352f, 0.985352f, 0.984375f, 0.001999f, 0.006226f, 0.010384f, 0.015594f, + 0.021027f, 0.027435f, 0.034637f, 0.042969f, 0.052124f, 0.062469f, 0.074097f, 0.087646f, 0.102173f, 0.119141f, 0.137695f, 0.158203f, + 0.181396f, 0.206543f, 0.233643f, 0.263184f, 0.295166f, 0.327148f, 0.360596f, 0.395264f, 0.430420f, 0.464600f, 0.499023f, 0.532227f, + 0.564941f, 0.595703f, 0.625000f, 0.651855f, 0.679199f, 0.703613f, 0.726074f, 0.747559f, 0.766602f, 0.784668f, 0.801758f, 0.816895f, + 0.831055f, 0.843750f, 0.856934f, 0.867188f, 0.878418f, 0.887207f, 0.896484f, 0.904785f, 0.913086f, 0.919922f, 0.926270f, 0.932617f, + 0.938477f, 0.944336f, 0.949707f, 0.953613f, 0.958496f, 0.962891f, 0.983887f, 0.984863f, 0.984863f, 0.984375f, 0.983887f, 0.983398f, + 0.001891f, 0.004959f, 0.009300f, 0.013786f, 0.018433f, 0.023560f, 0.029892f, 0.037018f, 0.044586f, 0.053284f, 0.062805f, 0.074341f, + 0.086975f, 0.100586f, 0.116760f, 0.133789f, 0.154175f, 0.176025f, 0.200317f, 0.226318f, 0.254395f, 0.284424f, 0.316650f, 0.349365f, + 0.383301f, 0.418213f, 0.452393f, 0.487061f, 0.520508f, 0.553223f, 0.584473f, 0.613770f, 0.643066f, 0.668945f, 0.695312f, 0.718262f, + 0.740234f, 0.761230f, 0.778809f, 0.797363f, 0.812988f, 0.827148f, 0.840332f, 0.854004f, 0.865723f, 0.875977f, 0.886230f, 0.895020f, + 0.904297f, 0.912598f, 0.919922f, 0.926270f, 0.932617f, 0.938965f, 0.943359f, 0.949219f, 0.955078f, 0.958984f, 0.982422f, 0.983887f, + 0.983398f, 0.982910f, 0.982910f, 0.981934f, 0.001368f, 0.004715f, 0.008041f, 0.011948f, 0.016235f, 0.020889f, 0.025848f, 0.031921f, + 0.038391f, 0.045563f, 0.054108f, 0.063477f, 0.074036f, 0.085815f, 0.099304f, 0.114563f, 0.131104f, 0.150146f, 0.170654f, 0.193970f, + 0.219360f, 0.246338f, 0.275146f, 0.306396f, 0.338867f, 0.372559f, 0.406494f, 0.440918f, 0.474609f, 0.508789f, 0.541992f, 0.574219f, + 0.604492f, 0.634277f, 0.661133f, 0.687500f, 0.710938f, 0.733887f, 0.754883f, 0.774414f, 0.792480f, 0.809570f, 0.824707f, 0.838379f, + 0.852051f, 0.862793f, 0.874023f, 0.885254f, 0.895020f, 0.903320f, 0.912109f, 0.919434f, 0.926758f, 0.932617f, 0.939941f, 0.945312f, + 0.951172f, 0.955078f, 0.980957f, 0.982910f, 0.982422f, 0.982422f, 0.981445f, 0.981445f, 0.001393f, 0.004227f, 0.007011f, 0.010323f, + 0.014107f, 0.018234f, 0.022766f, 0.027649f, 0.032898f, 0.039581f, 0.046539f, 0.054230f, 0.063293f, 0.073608f, 0.085144f, 0.097961f, + 0.112305f, 0.127930f, 0.146362f, 0.166260f, 0.188599f, 0.212524f, 0.238647f, 0.266846f, 0.297363f, 0.328369f, 0.361816f, 0.395752f, + 0.429932f, 0.464844f, 0.498535f, 0.531250f, 0.564453f, 0.596191f, 0.625488f, 0.653320f, 0.680176f, 0.704590f, 0.728027f, 0.750977f, + 0.770020f, 0.788574f, 0.805176f, 0.821289f, 0.835449f, 0.849609f, 0.862793f, 0.874023f, 0.884277f, 0.894043f, 0.903320f, 0.911621f, + 0.919434f, 0.926758f, 0.933594f, 0.939453f, 0.945312f, 0.951172f, 0.979492f, 0.980957f, 0.980957f, 0.980957f, 0.980469f, 0.979980f, + 0.001163f, 0.003527f, 0.006229f, 0.009323f, 0.012199f, 0.015808f, 0.019928f, 0.024200f, 0.028870f, 0.033997f, 0.040161f, 0.046967f, + 0.054871f, 0.063477f, 0.073181f, 0.083618f, 0.096252f, 0.109863f, 0.125122f, 0.142334f, 0.161743f, 0.182739f, 0.206421f, 0.232300f, + 0.259277f, 0.288086f, 0.320068f, 0.352783f, 0.386475f, 0.420410f, 0.454590f, 0.489258f, 0.521973f, 0.555176f, 0.586914f, 0.617188f, + 0.646484f, 0.673828f, 0.699707f, 0.723633f, 0.746094f, 0.766113f, 0.785645f, 0.803223f, 0.819336f, 0.834961f, 0.848633f, 0.861328f, + 0.873535f, 0.884766f, 0.893555f, 0.903809f, 0.911621f, 0.920410f, 0.928223f, 0.934082f, 0.939941f, 0.946777f, 0.978027f, 0.979492f, + 0.979492f, 0.979004f, 0.979004f, 0.978516f, 0.000981f, 0.002987f, 0.005329f, 0.008186f, 0.010895f, 0.013832f, 0.017532f, 0.021149f, + 0.025253f, 0.029999f, 0.035034f, 0.040985f, 0.047485f, 0.054993f, 0.063049f, 0.072510f, 0.082581f, 0.094421f, 0.107727f, 0.122498f, + 0.138794f, 0.157471f, 0.178467f, 0.200562f, 0.225586f, 0.251953f, 0.281250f, 0.311279f, 0.343750f, 0.377197f, 0.411621f, 0.445557f, + 0.479736f, 0.513672f, 0.546875f, 0.579590f, 0.610352f, 0.640625f, 0.668457f, 0.694336f, 0.718750f, 0.742188f, 0.762695f, 0.782715f, + 0.801270f, 0.817871f, 0.833496f, 0.847168f, 0.860840f, 0.872559f, 0.884277f, 0.894531f, 0.904297f, 0.912598f, 0.920898f, 0.928711f, + 0.935547f, 0.942383f, 0.976074f, 0.978027f, 0.978516f, 0.978027f, 0.977539f, 0.977051f, 0.000880f, 0.002707f, 0.005089f, 0.007305f, + 0.010147f, 0.012596f, 0.015160f, 0.018616f, 0.022507f, 0.026230f, 0.030777f, 0.035767f, 0.041351f, 0.047455f, 0.054565f, 0.062256f, + 0.071289f, 0.081299f, 0.092346f, 0.105408f, 0.119812f, 0.135620f, 0.153320f, 0.173462f, 0.195068f, 0.219482f, 0.245361f, 0.273682f, + 0.303711f, 0.335938f, 0.368896f, 0.402588f, 0.437500f, 0.472168f, 0.505859f, 0.539551f, 0.573242f, 0.604492f, 0.634766f, 0.663086f, + 0.689453f, 0.714844f, 0.738770f, 0.760254f, 0.780762f, 0.799316f, 0.817383f, 0.833496f, 0.847168f, 0.860840f, 0.873535f, 0.884766f, + 0.895508f, 0.905273f, 0.914062f, 0.922363f, 0.930176f, 0.937012f, 0.974609f, 0.976074f, 0.976074f, 0.976562f, 0.976074f, 0.975586f, + 0.000851f, 0.002659f, 0.004692f, 0.006466f, 0.008545f, 0.011055f, 0.013649f, 0.016403f, 0.019714f, 0.023056f, 0.026962f, 0.031235f, + 0.035828f, 0.041656f, 0.047699f, 0.054077f, 0.061859f, 0.070496f, 0.080200f, 0.091125f, 0.103088f, 0.116882f, 0.132446f, 0.149780f, + 0.168701f, 0.190430f, 0.213379f, 0.239258f, 0.267334f, 0.296631f, 0.328369f, 0.360840f, 0.395020f, 0.429932f, 0.464355f, 0.499512f, + 0.533203f, 0.566406f, 0.599121f, 0.629883f, 0.658203f, 0.687012f, 0.712402f, 0.735840f, 0.758789f, 0.779297f, 0.798828f, 0.816406f, + 0.832520f, 0.847168f, 0.861328f, 0.874023f, 0.886230f, 0.896973f, 0.907227f, 0.915527f, 0.924805f, 0.931641f, 0.972168f, 0.975586f, + 0.975586f, 0.974609f, 0.974121f, 0.973633f, 0.000762f, 0.002214f, 0.004040f, 0.005859f, 0.007790f, 0.009689f, 0.012161f, 0.014786f, + 0.017441f, 0.020493f, 0.023956f, 0.027618f, 0.031860f, 0.036255f, 0.041595f, 0.047394f, 0.053894f, 0.061188f, 0.069214f, 0.078735f, + 0.089050f, 0.101135f, 0.114441f, 0.129150f, 0.145874f, 0.164673f, 0.185303f, 0.208862f, 0.233765f, 0.260742f, 0.290283f, 0.321045f, + 0.354248f, 0.388184f, 0.422607f, 0.457764f, 0.493652f, 0.526855f, 0.561523f, 0.594238f, 0.625977f, 0.655273f, 0.683594f, 0.710449f, + 0.734863f, 0.758301f, 0.779297f, 0.798828f, 0.817383f, 0.833984f, 0.848145f, 0.862793f, 0.875488f, 0.887207f, 0.899414f, 0.908691f, + 0.917969f, 0.926270f, 0.970215f, 0.972656f, 0.974121f, 0.973145f, 0.972656f, 0.972168f, 0.000732f, 0.001928f, 0.003513f, 0.005234f, + 0.007042f, 0.008629f, 0.010620f, 0.012985f, 0.015244f, 0.018158f, 0.020935f, 0.024475f, 0.027908f, 0.032013f, 0.036316f, 0.041290f, + 0.046661f, 0.053040f, 0.060089f, 0.068115f, 0.077087f, 0.087463f, 0.099121f, 0.111633f, 0.126221f, 0.142578f, 0.160767f, 0.181396f, + 0.203003f, 0.228149f, 0.255127f, 0.284180f, 0.315186f, 0.347900f, 0.381836f, 0.416748f, 0.451904f, 0.487549f, 0.522949f, 0.556641f, + 0.590332f, 0.623047f, 0.652832f, 0.682129f, 0.708984f, 0.733887f, 0.757324f, 0.779785f, 0.799316f, 0.818359f, 0.835449f, 0.850586f, + 0.865234f, 0.877441f, 0.890137f, 0.901367f, 0.912109f, 0.920410f, 0.968262f, 0.970703f, 0.971191f, 0.970703f, 0.971191f, 0.971191f, + 0.000524f, 0.001758f, 0.003185f, 0.004864f, 0.006081f, 0.007820f, 0.009705f, 0.011467f, 0.013634f, 0.016068f, 0.018707f, 0.021378f, + 0.024597f, 0.028030f, 0.032135f, 0.036224f, 0.041016f, 0.046692f, 0.052399f, 0.059265f, 0.067505f, 0.076050f, 0.085510f, 0.096558f, + 0.109253f, 0.123657f, 0.138794f, 0.157227f, 0.176880f, 0.198730f, 0.223267f, 0.250000f, 0.278809f, 0.309326f, 0.342041f, 0.375977f, + 0.410889f, 0.447021f, 0.483154f, 0.518555f, 0.554199f, 0.586914f, 0.620117f, 0.650879f, 0.681641f, 0.708496f, 0.734375f, 0.757324f, + 0.780762f, 0.801270f, 0.819336f, 0.837891f, 0.852539f, 0.867188f, 0.880371f, 0.893066f, 0.903809f, 0.914551f, 0.966309f, 0.968750f, + 0.969238f, 0.969727f, 0.968750f, 0.968750f, 0.000503f, 0.001896f, 0.002653f, 0.004128f, 0.005627f, 0.007004f, 0.008797f, 0.010361f, + 0.012230f, 0.014175f, 0.016647f, 0.019348f, 0.021454f, 0.024872f, 0.028290f, 0.031830f, 0.036163f, 0.040649f, 0.045715f, 0.051941f, + 0.058319f, 0.065979f, 0.074402f, 0.083618f, 0.094360f, 0.106812f, 0.120239f, 0.135742f, 0.153320f, 0.172974f, 0.194824f, 0.218506f, + 0.245117f, 0.273926f, 0.304688f, 0.336426f, 0.371094f, 0.406982f, 0.442627f, 0.479492f, 0.514648f, 0.550781f, 0.584961f, 0.618652f, + 0.650879f, 0.681152f, 0.709473f, 0.735352f, 0.760742f, 0.782715f, 0.803711f, 0.821777f, 0.838867f, 0.855957f, 0.870605f, 0.884277f, + 0.895996f, 0.906738f, 0.964355f, 0.966309f, 0.967285f, 0.966797f, 0.966309f, 0.966309f, 0.000636f, 0.001421f, 0.002768f, 0.003761f, + 0.004944f, 0.006462f, 0.007889f, 0.009262f, 0.010780f, 0.013000f, 0.014946f, 0.017029f, 0.019516f, 0.022049f, 0.024933f, 0.028091f, + 0.031616f, 0.035553f, 0.040161f, 0.045380f, 0.051239f, 0.057281f, 0.064270f, 0.072693f, 0.081970f, 0.092468f, 0.104736f, 0.117859f, + 0.132690f, 0.150391f, 0.169189f, 0.190796f, 0.214233f, 0.240601f, 0.268555f, 0.299561f, 0.332520f, 0.367188f, 0.402344f, 0.438965f, + 0.476074f, 0.512695f, 0.549805f, 0.584473f, 0.619141f, 0.651367f, 0.681152f, 0.709961f, 0.737305f, 0.762695f, 0.785156f, 0.806641f, + 0.826172f, 0.843262f, 0.859375f, 0.874023f, 0.888184f, 0.900391f, 0.961426f, 0.964355f, 0.965332f, 0.964844f, 0.964355f, 0.964844f, + 0.000295f, 0.001419f, 0.002342f, 0.003471f, 0.004539f, 0.005821f, 0.006882f, 0.008354f, 0.010155f, 0.011574f, 0.013283f, 0.015129f, + 0.017090f, 0.019333f, 0.022125f, 0.024643f, 0.028122f, 0.031586f, 0.035522f, 0.039825f, 0.044586f, 0.050110f, 0.056091f, 0.063354f, + 0.071045f, 0.080078f, 0.090637f, 0.102112f, 0.115479f, 0.130127f, 0.147217f, 0.165649f, 0.186768f, 0.210571f, 0.236694f, 0.265137f, + 0.295654f, 0.328857f, 0.363770f, 0.399902f, 0.436523f, 0.474365f, 0.511230f, 0.548828f, 0.584961f, 0.619141f, 0.652344f, 0.684082f, + 0.712891f, 0.741211f, 0.766113f, 0.789062f, 0.810547f, 0.830078f, 0.848633f, 0.864258f, 0.879395f, 0.892578f, 0.958496f, 0.962402f, + 0.962402f, 0.962402f, 0.961914f, 0.962402f, 0.000464f, 0.001313f, 0.002159f, 0.003134f, 0.004463f, 0.005001f, 0.006466f, 0.007595f, + 0.008842f, 0.010277f, 0.011971f, 0.013550f, 0.015434f, 0.017242f, 0.019348f, 0.021805f, 0.024734f, 0.027817f, 0.031174f, 0.034821f, + 0.039124f, 0.043823f, 0.049164f, 0.055237f, 0.062164f, 0.069336f, 0.078430f, 0.088501f, 0.099976f, 0.112854f, 0.127319f, 0.143555f, + 0.162354f, 0.183350f, 0.207031f, 0.233032f, 0.260986f, 0.291992f, 0.325195f, 0.361084f, 0.397217f, 0.435059f, 0.473389f, 0.510742f, + 0.549316f, 0.586426f, 0.620605f, 0.654785f, 0.686523f, 0.716797f, 0.744629f, 0.769043f, 0.793945f, 0.815918f, 0.834961f, 0.852539f, + 0.869141f, 0.884277f, 0.955078f, 0.959473f, 0.959473f, 0.959473f, 0.959961f, 0.959961f, 0.000541f, 0.001223f, 0.002172f, 0.002886f, + 0.003679f, 0.004681f, 0.005512f, 0.006683f, 0.008049f, 0.009346f, 0.010704f, 0.012024f, 0.013626f, 0.015213f, 0.017227f, 0.019516f, + 0.022079f, 0.024612f, 0.027313f, 0.030731f, 0.034180f, 0.038239f, 0.042969f, 0.048187f, 0.053864f, 0.060516f, 0.068298f, 0.076843f, + 0.086670f, 0.097473f, 0.110107f, 0.124268f, 0.140869f, 0.159302f, 0.180420f, 0.203613f, 0.229614f, 0.258057f, 0.289062f, 0.323486f, + 0.358398f, 0.395996f, 0.434082f, 0.472900f, 0.511719f, 0.550293f, 0.587402f, 0.624023f, 0.658203f, 0.690918f, 0.721191f, 0.749512f, + 0.774902f, 0.799316f, 0.821289f, 0.840820f, 0.859375f, 0.875488f, 0.952637f, 0.956543f, 0.957520f, 0.957520f, 0.957520f, 0.957031f, + 0.000252f, 0.001056f, 0.001923f, 0.002523f, 0.003414f, 0.003960f, 0.005146f, 0.006172f, 0.007130f, 0.008179f, 0.009567f, 0.010735f, + 0.012077f, 0.013878f, 0.015640f, 0.017456f, 0.019638f, 0.021622f, 0.024170f, 0.026978f, 0.030121f, 0.033630f, 0.037445f, 0.042053f, + 0.047119f, 0.052826f, 0.059174f, 0.066711f, 0.075012f, 0.084473f, 0.095276f, 0.107727f, 0.122070f, 0.138184f, 0.156250f, 0.177246f, + 0.200928f, 0.226929f, 0.255371f, 0.286865f, 0.321289f, 0.356934f, 0.395264f, 0.434326f, 0.473877f, 0.514160f, 0.553711f, 0.591797f, + 0.628418f, 0.663574f, 0.696777f, 0.728027f, 0.755859f, 0.782715f, 0.806152f, 0.829102f, 0.847656f, 0.867188f, 0.949707f, 0.954102f, + 0.954590f, 0.954590f, 0.954102f, 0.954590f, 0.000365f, 0.000963f, 0.001581f, 0.002337f, 0.002996f, 0.003952f, 0.004608f, 0.005459f, + 0.006489f, 0.007351f, 0.008484f, 0.009544f, 0.011108f, 0.012413f, 0.013901f, 0.015388f, 0.017181f, 0.019012f, 0.021439f, 0.023727f, + 0.026520f, 0.029449f, 0.032898f, 0.036835f, 0.041046f, 0.045868f, 0.051575f, 0.058075f, 0.064758f, 0.073120f, 0.082520f, 0.093079f, + 0.105652f, 0.119385f, 0.135620f, 0.153687f, 0.174683f, 0.198364f, 0.224365f, 0.253662f, 0.285400f, 0.320557f, 0.357178f, 0.395752f, + 0.435791f, 0.476318f, 0.516602f, 0.557129f, 0.596191f, 0.633789f, 0.669434f, 0.703613f, 0.734375f, 0.763672f, 0.790039f, 0.812988f, + 0.836914f, 0.855957f, 0.946289f, 0.949707f, 0.951172f, 0.951172f, 0.951172f, 0.951172f, 0.000404f, 0.001028f, 0.001410f, 0.002098f, + 0.002657f, 0.003445f, 0.004391f, 0.005039f, 0.005665f, 0.006569f, 0.007549f, 0.008614f, 0.009743f, 0.011108f, 0.012390f, 0.013611f, + 0.015396f, 0.017044f, 0.018921f, 0.020874f, 0.023453f, 0.025833f, 0.028809f, 0.032501f, 0.036011f, 0.040161f, 0.044952f, 0.050018f, + 0.056091f, 0.063477f, 0.071533f, 0.080200f, 0.091064f, 0.103027f, 0.117065f, 0.133057f, 0.151489f, 0.171997f, 0.196045f, 0.222290f, + 0.251709f, 0.284424f, 0.319824f, 0.357422f, 0.397217f, 0.438232f, 0.479492f, 0.521484f, 0.562500f, 0.602051f, 0.641113f, 0.677734f, + 0.711914f, 0.743164f, 0.772461f, 0.799316f, 0.822754f, 0.845215f, 0.942383f, 0.946777f, 0.947754f, 0.947754f, 0.948242f, 0.948242f, + 0.000406f, 0.000992f, 0.001447f, 0.001986f, 0.002499f, 0.003149f, 0.003769f, 0.004272f, 0.005016f, 0.005981f, 0.006924f, 0.007675f, + 0.008766f, 0.009727f, 0.010765f, 0.011986f, 0.013588f, 0.014915f, 0.016724f, 0.018478f, 0.020508f, 0.022873f, 0.025497f, 0.028336f, + 0.031525f, 0.034882f, 0.038818f, 0.043243f, 0.048615f, 0.054626f, 0.061707f, 0.069214f, 0.078430f, 0.089111f, 0.101013f, 0.115112f, + 0.130859f, 0.148926f, 0.170166f, 0.193604f, 0.220947f, 0.250732f, 0.283936f, 0.320068f, 0.358887f, 0.400391f, 0.442139f, 0.483887f, + 0.527344f, 0.569824f, 0.610352f, 0.649414f, 0.686523f, 0.722168f, 0.753906f, 0.782227f, 0.809570f, 0.833496f, 0.938477f, 0.942871f, + 0.944824f, 0.944336f, 0.943848f, 0.943848f, 0.000235f, 0.000984f, 0.001204f, 0.001706f, 0.002239f, 0.002998f, 0.003462f, 0.004093f, + 0.004372f, 0.005371f, 0.006149f, 0.006962f, 0.007736f, 0.008766f, 0.009804f, 0.010780f, 0.011887f, 0.013336f, 0.014618f, 0.016159f, + 0.018158f, 0.020050f, 0.022232f, 0.024597f, 0.027313f, 0.030334f, 0.033752f, 0.037872f, 0.042389f, 0.047516f, 0.053192f, 0.059937f, + 0.067749f, 0.076599f, 0.086975f, 0.098755f, 0.112610f, 0.128662f, 0.146973f, 0.168091f, 0.192383f, 0.220215f, 0.250732f, 0.284668f, + 0.322021f, 0.361572f, 0.403564f, 0.446777f, 0.490723f, 0.534668f, 0.577637f, 0.619629f, 0.660156f, 0.697754f, 0.731934f, 0.764648f, + 0.794922f, 0.820312f, 0.934082f, 0.939453f, 0.939941f, 0.941406f, 0.940430f, 0.940918f, 0.000237f, 0.000591f, 0.001098f, 0.001619f, + 0.002241f, 0.002636f, 0.003176f, 0.003521f, 0.004101f, 0.004631f, 0.005398f, 0.006378f, 0.007000f, 0.007767f, 0.008713f, 0.009758f, + 0.010475f, 0.011734f, 0.013016f, 0.014404f, 0.015762f, 0.017517f, 0.019440f, 0.021469f, 0.023651f, 0.026199f, 0.029495f, 0.033112f, + 0.036499f, 0.040955f, 0.045959f, 0.051849f, 0.058197f, 0.065552f, 0.074585f, 0.085022f, 0.096680f, 0.110535f, 0.126709f, 0.145264f, + 0.166626f, 0.191406f, 0.219482f, 0.250488f, 0.286133f, 0.323975f, 0.365723f, 0.408447f, 0.453125f, 0.498779f, 0.542969f, 0.588379f, + 0.631836f, 0.671387f, 0.709473f, 0.745117f, 0.777344f, 0.807617f, 0.930176f, 0.935059f, 0.936523f, 0.936523f, 0.936523f, 0.936035f, + 0.000242f, 0.000761f, 0.000943f, 0.001624f, 0.001858f, 0.002390f, 0.002638f, 0.003054f, 0.003805f, 0.004559f, 0.005035f, 0.005493f, + 0.006157f, 0.006878f, 0.007687f, 0.008530f, 0.009178f, 0.010406f, 0.011406f, 0.012520f, 0.014053f, 0.015579f, 0.017105f, 0.018661f, + 0.020737f, 0.022903f, 0.025650f, 0.028259f, 0.031433f, 0.035065f, 0.039581f, 0.044342f, 0.049988f, 0.056366f, 0.064026f, 0.072632f, + 0.082825f, 0.094666f, 0.108582f, 0.124634f, 0.143799f, 0.165405f, 0.190796f, 0.219360f, 0.251953f, 0.287842f, 0.328125f, 0.370605f, + 0.415283f, 0.461670f, 0.507812f, 0.555176f, 0.600586f, 0.645020f, 0.685547f, 0.724121f, 0.759277f, 0.792969f, 0.924805f, 0.931152f, + 0.931641f, 0.932129f, 0.932129f, 0.931641f, 0.000240f, 0.000685f, 0.000955f, 0.001395f, 0.001768f, 0.002157f, 0.002533f, 0.002970f, + 0.003223f, 0.003813f, 0.004601f, 0.004993f, 0.005428f, 0.005981f, 0.006878f, 0.007484f, 0.008110f, 0.009132f, 0.009964f, 0.011208f, + 0.012138f, 0.013374f, 0.015099f, 0.016190f, 0.018112f, 0.020187f, 0.022202f, 0.024780f, 0.027573f, 0.030411f, 0.034119f, 0.037964f, + 0.042755f, 0.048553f, 0.054474f, 0.061890f, 0.070984f, 0.080688f, 0.092590f, 0.106812f, 0.123291f, 0.142456f, 0.164551f, 0.190430f, + 0.220459f, 0.253418f, 0.291504f, 0.332520f, 0.376709f, 0.423340f, 0.471436f, 0.520508f, 0.567383f, 0.614746f, 0.660156f, 0.702148f, + 0.741211f, 0.776367f, 0.920410f, 0.925293f, 0.926270f, 0.926758f, 0.927246f, 0.926758f, 0.000244f, 0.000431f, 0.000799f, 0.001309f, + 0.001587f, 0.001945f, 0.002317f, 0.002514f, 0.003290f, 0.003548f, 0.004082f, 0.004349f, 0.004707f, 0.005348f, 0.006027f, 0.006565f, + 0.007141f, 0.008011f, 0.008850f, 0.009552f, 0.010757f, 0.011650f, 0.012794f, 0.014145f, 0.015778f, 0.017303f, 0.019028f, 0.021088f, + 0.023575f, 0.026169f, 0.029175f, 0.032562f, 0.036713f, 0.041382f, 0.046448f, 0.052948f, 0.060303f, 0.068787f, 0.079041f, 0.090942f, + 0.105103f, 0.121643f, 0.141113f, 0.164185f, 0.190308f, 0.221191f, 0.256836f, 0.295898f, 0.339355f, 0.385010f, 0.433838f, 0.484619f, + 0.534668f, 0.583496f, 0.631348f, 0.678223f, 0.719727f, 0.759766f, 0.913574f, 0.920410f, 0.921387f, 0.921875f, 0.921875f, 0.921387f, + 0.000243f, 0.000496f, 0.000847f, 0.001157f, 0.001426f, 0.001634f, 0.002020f, 0.002338f, 0.002607f, 0.003035f, 0.003502f, 0.003872f, + 0.004459f, 0.004726f, 0.005402f, 0.005779f, 0.006325f, 0.007095f, 0.007767f, 0.008568f, 0.009331f, 0.010086f, 0.011009f, 0.012314f, + 0.013611f, 0.015060f, 0.016312f, 0.018158f, 0.020401f, 0.022476f, 0.024979f, 0.027863f, 0.031036f, 0.034943f, 0.039581f, 0.044830f, + 0.050903f, 0.058289f, 0.066895f, 0.076782f, 0.088989f, 0.103210f, 0.120422f, 0.140259f, 0.164185f, 0.191772f, 0.223877f, 0.260742f, + 0.301758f, 0.347168f, 0.395508f, 0.446533f, 0.497803f, 0.551270f, 0.601562f, 0.651855f, 0.697754f, 0.741211f, 0.908203f, 0.915039f, + 0.916016f, 0.916016f, 0.916504f, 0.915527f, 0.000239f, 0.000345f, 0.000690f, 0.000913f, 0.001250f, 0.001343f, 0.001579f, 0.002050f, + 0.002331f, 0.002861f, 0.003048f, 0.003616f, 0.003696f, 0.004211f, 0.004723f, 0.005074f, 0.005657f, 0.006100f, 0.006893f, 0.007290f, + 0.008118f, 0.008659f, 0.009552f, 0.010704f, 0.011681f, 0.012764f, 0.014114f, 0.015533f, 0.017227f, 0.018982f, 0.021286f, 0.023560f, + 0.026489f, 0.029861f, 0.033417f, 0.037933f, 0.043121f, 0.049286f, 0.056519f, 0.065002f, 0.075073f, 0.087158f, 0.101624f, 0.118835f, + 0.139648f, 0.164185f, 0.193481f, 0.226929f, 0.265625f, 0.309570f, 0.356934f, 0.408203f, 0.461426f, 0.516113f, 0.569824f, 0.623047f, + 0.674316f, 0.720703f, 0.902344f, 0.908203f, 0.909668f, 0.910645f, 0.910645f, 0.911133f, 0.000000f, 0.000281f, 0.000560f, 0.000977f, + 0.001063f, 0.001171f, 0.001569f, 0.001903f, 0.002075f, 0.002413f, 0.002695f, 0.003004f, 0.003399f, 0.003553f, 0.003998f, 0.004333f, + 0.004971f, 0.005314f, 0.005806f, 0.006340f, 0.007015f, 0.007492f, 0.008377f, 0.009186f, 0.010094f, 0.010910f, 0.012199f, 0.013351f, + 0.014618f, 0.016266f, 0.018082f, 0.019852f, 0.022491f, 0.025085f, 0.028168f, 0.031799f, 0.036041f, 0.041107f, 0.047394f, 0.054321f, + 0.062866f, 0.073181f, 0.085327f, 0.100525f, 0.118408f, 0.139648f, 0.165527f, 0.196411f, 0.231812f, 0.273193f, 0.318848f, 0.369629f, + 0.423828f, 0.480225f, 0.536621f, 0.592773f, 0.647949f, 0.699707f, 0.894043f, 0.900879f, 0.903809f, 0.903320f, 0.903320f, 0.902832f, + 0.000232f, 0.000227f, 0.000555f, 0.000656f, 0.000937f, 0.000985f, 0.001351f, 0.001723f, 0.001925f, 0.002010f, 0.002445f, 0.002625f, + 0.002760f, 0.003220f, 0.003551f, 0.003870f, 0.004303f, 0.004826f, 0.005028f, 0.005451f, 0.005985f, 0.006523f, 0.007000f, 0.007744f, + 0.008499f, 0.009361f, 0.010109f, 0.011185f, 0.012413f, 0.013603f, 0.015121f, 0.016891f, 0.018753f, 0.020920f, 0.023407f, 0.026764f, + 0.030197f, 0.034302f, 0.039429f, 0.044891f, 0.052368f, 0.060822f, 0.071167f, 0.083557f, 0.098877f, 0.117493f, 0.139893f, 0.167725f, + 0.200195f, 0.238037f, 0.281982f, 0.331543f, 0.385010f, 0.442627f, 0.501465f, 0.561523f, 0.620605f, 0.675781f, 0.887207f, 0.894531f, + 0.895020f, 0.896484f, 0.896484f, 0.895996f, 0.000000f, 0.000332f, 0.000577f, 0.000723f, 0.000720f, 0.001210f, 0.001469f, 0.001456f, + 0.001546f, 0.001775f, 0.002159f, 0.002291f, 0.002659f, 0.002916f, 0.003046f, 0.003439f, 0.003752f, 0.003883f, 0.004375f, 0.004635f, + 0.005241f, 0.005638f, 0.006054f, 0.006630f, 0.007191f, 0.007744f, 0.008545f, 0.009178f, 0.010498f, 0.011536f, 0.012802f, 0.013931f, + 0.015808f, 0.017548f, 0.019379f, 0.022110f, 0.025040f, 0.028473f, 0.032471f, 0.037323f, 0.043152f, 0.050476f, 0.058807f, 0.069214f, + 0.082520f, 0.098145f, 0.116821f, 0.141602f, 0.170044f, 0.204834f, 0.245728f, 0.293213f, 0.346436f, 0.403564f, 0.464111f, 0.527832f, + 0.589844f, 0.650879f, 0.878418f, 0.886719f, 0.888184f, 0.887695f, 0.888672f, 0.888672f, 0.000243f, 0.000307f, 0.000526f, 0.000561f, + 0.000923f, 0.000980f, 0.001143f, 0.001386f, 0.001414f, 0.001683f, 0.001735f, 0.001972f, 0.002232f, 0.002481f, 0.002657f, 0.002754f, + 0.003193f, 0.003359f, 0.003603f, 0.003956f, 0.004368f, 0.004692f, 0.005119f, 0.005596f, 0.005955f, 0.006634f, 0.007256f, 0.007881f, + 0.008652f, 0.009552f, 0.010376f, 0.011719f, 0.012634f, 0.014595f, 0.016113f, 0.018219f, 0.020554f, 0.023254f, 0.026520f, 0.030502f, + 0.035553f, 0.041168f, 0.048065f, 0.057190f, 0.067261f, 0.080811f, 0.097107f, 0.117737f, 0.143066f, 0.173950f, 0.211182f, 0.256592f, + 0.307129f, 0.364502f, 0.427002f, 0.491943f, 0.557617f, 0.624023f, 0.869629f, 0.877930f, 0.879883f, 0.879883f, 0.879883f, 0.880371f, + 0.000000f, 0.000270f, 0.000342f, 0.000509f, 0.000668f, 0.000989f, 0.000945f, 0.001105f, 0.001230f, 0.001335f, 0.001492f, 0.001757f, + 0.001917f, 0.002140f, 0.002386f, 0.002501f, 0.002644f, 0.002884f, 0.003199f, 0.003441f, 0.003620f, 0.003891f, 0.004337f, 0.004631f, + 0.005119f, 0.005520f, 0.006100f, 0.006504f, 0.007301f, 0.007771f, 0.008751f, 0.009521f, 0.010658f, 0.011765f, 0.013145f, 0.014641f, + 0.016785f, 0.018829f, 0.021545f, 0.024719f, 0.028381f, 0.033203f, 0.038849f, 0.046112f, 0.055084f, 0.065552f, 0.079529f, 0.096985f, + 0.118530f, 0.145630f, 0.179321f, 0.220337f, 0.269287f, 0.325439f, 0.387207f, 0.454102f, 0.524414f, 0.595215f, 0.859863f, 0.868652f, + 0.870605f, 0.869629f, 0.870117f, 0.870605f, 0.000000f, 0.000230f, 0.000334f, 0.000416f, 0.000700f, 0.000726f, 0.000921f, 0.001008f, + 0.001065f, 0.001186f, 0.001365f, 0.001471f, 0.001627f, 0.001796f, 0.001843f, 0.002069f, 0.002266f, 0.002438f, 0.002596f, 0.002831f, + 0.003000f, 0.003298f, 0.003597f, 0.003887f, 0.004265f, 0.004581f, 0.004986f, 0.005505f, 0.005947f, 0.006454f, 0.007069f, 0.007801f, + 0.008621f, 0.009575f, 0.010612f, 0.011848f, 0.013321f, 0.015259f, 0.017410f, 0.019775f, 0.022934f, 0.026550f, 0.031464f, 0.036713f, + 0.043945f, 0.052887f, 0.064209f, 0.078735f, 0.096924f, 0.120361f, 0.149536f, 0.186768f, 0.232422f, 0.285889f, 0.347656f, 0.415527f, + 0.488281f, 0.563965f, 0.849121f, 0.857910f, 0.859375f, 0.860840f, 0.860840f, 0.860352f, 0.000233f, 0.000225f, 0.000219f, 0.000431f, + 0.000579f, 0.000648f, 0.000671f, 0.000744f, 0.000946f, 0.000994f, 0.001091f, 0.001307f, 0.001364f, 0.001490f, 0.001561f, 0.001712f, + 0.001892f, 0.001999f, 0.002190f, 0.002369f, 0.002512f, 0.002733f, 0.003014f, 0.003145f, 0.003553f, 0.003822f, 0.004135f, 0.004326f, + 0.004799f, 0.005344f, 0.005718f, 0.006378f, 0.007008f, 0.007721f, 0.008400f, 0.009537f, 0.010597f, 0.011917f, 0.013542f, 0.015579f, + 0.018051f, 0.020889f, 0.024765f, 0.029236f, 0.034668f, 0.041779f, 0.051056f, 0.062439f, 0.077576f, 0.097595f, 0.122864f, 0.155273f, + 0.196655f, 0.247437f, 0.307617f, 0.375977f, 0.450684f, 0.531250f, 0.837891f, 0.847168f, 0.848633f, 0.849609f, 0.849121f, 0.849609f, + 0.000202f, 0.000180f, 0.000206f, 0.000339f, 0.000479f, 0.000536f, 0.000687f, 0.000739f, 0.000771f, 0.000849f, 0.001051f, 0.001060f, + 0.001154f, 0.001219f, 0.001389f, 0.001505f, 0.001469f, 0.001729f, 0.001858f, 0.001980f, 0.002209f, 0.002243f, 0.002483f, 0.002695f, + 0.002951f, 0.003149f, 0.003374f, 0.003654f, 0.004002f, 0.004154f, 0.004539f, 0.005032f, 0.005428f, 0.005989f, 0.006760f, 0.007549f, + 0.008423f, 0.009499f, 0.010620f, 0.012016f, 0.013992f, 0.016434f, 0.019135f, 0.022583f, 0.026840f, 0.032501f, 0.039551f, 0.048828f, + 0.061066f, 0.077393f, 0.098755f, 0.127075f, 0.163208f, 0.209717f, 0.267578f, 0.334961f, 0.411133f, 0.494629f, 0.825684f, 0.834473f, + 0.836426f, 0.837402f, 0.837402f, 0.837402f, 0.000000f, 0.000185f, 0.000184f, 0.000404f, 0.000408f, 0.000454f, 0.000480f, 0.000506f, + 0.000660f, 0.000694f, 0.000742f, 0.000801f, 0.000989f, 0.001111f, 0.001167f, 0.001250f, 0.001311f, 0.001424f, 0.001541f, 0.001574f, + 0.001712f, 0.001930f, 0.001982f, 0.002201f, 0.002375f, 0.002439f, 0.002792f, 0.002905f, 0.003065f, 0.003412f, 0.003653f, 0.003952f, + 0.004463f, 0.004723f, 0.005230f, 0.005936f, 0.006386f, 0.007092f, 0.008240f, 0.009247f, 0.010765f, 0.012344f, 0.014420f, 0.017090f, + 0.020493f, 0.024551f, 0.030014f, 0.037689f, 0.047302f, 0.060028f, 0.077820f, 0.100830f, 0.132812f, 0.174561f, 0.228516f, 0.294434f, + 0.371582f, 0.457031f, 0.812012f, 0.820801f, 0.823730f, 0.824219f, 0.824707f, 0.824219f, 0.000000f, 0.000053f, 0.000206f, 0.000360f, + 0.000379f, 0.000391f, 0.000379f, 0.000478f, 0.000549f, 0.000589f, 0.000626f, 0.000674f, 0.000762f, 0.000832f, 0.000894f, 0.001050f, + 0.001111f, 0.001155f, 0.001286f, 0.001345f, 0.001449f, 0.001564f, 0.001666f, 0.001750f, 0.001856f, 0.001925f, 0.002056f, 0.002359f, + 0.002542f, 0.002728f, 0.003042f, 0.003164f, 0.003460f, 0.003786f, 0.004116f, 0.004578f, 0.005116f, 0.005688f, 0.006508f, 0.007229f, + 0.008125f, 0.009232f, 0.010796f, 0.012741f, 0.015137f, 0.018158f, 0.022186f, 0.028030f, 0.035248f, 0.045593f, 0.059052f, 0.078308f, + 0.105042f, 0.141602f, 0.190308f, 0.252930f, 0.329102f, 0.417969f, 0.797852f, 0.807129f, 0.810059f, 0.810547f, 0.811035f, 0.810547f, + 0.000000f, 0.000000f, 0.000082f, 0.000195f, 0.000309f, 0.000336f, 0.000324f, 0.000414f, 0.000439f, 0.000460f, 0.000599f, 0.000643f, + 0.000637f, 0.000690f, 0.000733f, 0.000834f, 0.000821f, 0.000922f, 0.000989f, 0.001067f, 0.001207f, 0.001293f, 0.001327f, 0.001476f, + 0.001581f, 0.001663f, 0.001725f, 0.001906f, 0.001934f, 0.002180f, 0.002258f, 0.002602f, 0.002701f, 0.003019f, 0.003229f, 0.003502f, + 0.003847f, 0.004261f, 0.004795f, 0.005318f, 0.006130f, 0.007008f, 0.008118f, 0.009277f, 0.011024f, 0.013229f, 0.016205f, 0.020203f, + 0.025620f, 0.033020f, 0.043854f, 0.059021f, 0.080383f, 0.111206f, 0.154419f, 0.212646f, 0.287354f, 0.378418f, 0.781250f, 0.792480f, + 0.793457f, 0.795410f, 0.795898f, 0.794922f, 0.000000f, 0.000121f, 0.000120f, 0.000198f, 0.000275f, 0.000249f, 0.000290f, 0.000360f, + 0.000375f, 0.000379f, 0.000391f, 0.000438f, 0.000505f, 0.000534f, 0.000669f, 0.000629f, 0.000659f, 0.000754f, 0.000890f, 0.000833f, + 0.000849f, 0.000975f, 0.001029f, 0.001117f, 0.001193f, 0.001203f, 0.001269f, 0.001424f, 0.001594f, 0.001675f, 0.001737f, 0.001957f, + 0.002094f, 0.002319f, 0.002342f, 0.002609f, 0.002928f, 0.003248f, 0.003523f, 0.003967f, 0.004547f, 0.005138f, 0.005871f, 0.006760f, + 0.007912f, 0.009430f, 0.011528f, 0.014236f, 0.017899f, 0.023346f, 0.031235f, 0.042694f, 0.059235f, 0.084229f, 0.120972f, 0.173950f, + 0.245239f, 0.334473f, 0.764160f, 0.775391f, 0.777344f, 0.778809f, 0.777832f, 0.778809f, 0.000000f, 0.000121f, 0.000119f, 0.000182f, + 0.000177f, 0.000179f, 0.000262f, 0.000239f, 0.000309f, 0.000322f, 0.000404f, 0.000370f, 0.000361f, 0.000430f, 0.000458f, 0.000540f, + 0.000589f, 0.000615f, 0.000648f, 0.000632f, 0.000777f, 0.000782f, 0.000798f, 0.000871f, 0.000857f, 0.000925f, 0.001000f, 0.001045f, + 0.001191f, 0.001223f, 0.001426f, 0.001419f, 0.001512f, 0.001635f, 0.001884f, 0.002092f, 0.002100f, 0.002293f, 0.002577f, 0.003012f, + 0.003258f, 0.003761f, 0.004253f, 0.004814f, 0.005619f, 0.006676f, 0.008064f, 0.009750f, 0.012268f, 0.015854f, 0.021255f, 0.029282f, + 0.041687f, 0.061005f, 0.091370f, 0.136230f, 0.202759f, 0.291504f, 0.746582f, 0.757324f, 0.759277f, 0.760254f, 0.760254f, 0.760254f, + 0.000000f, 0.000000f, 0.000117f, 0.000126f, 0.000113f, 0.000146f, 0.000158f, 0.000155f, 0.000189f, 0.000288f, 0.000254f, 0.000336f, + 0.000347f, 0.000353f, 0.000370f, 0.000355f, 0.000390f, 0.000417f, 0.000456f, 0.000480f, 0.000525f, 0.000587f, 0.000596f, 0.000620f, + 0.000676f, 0.000740f, 0.000758f, 0.000852f, 0.000907f, 0.000947f, 0.001057f, 0.001122f, 0.001170f, 0.001293f, 0.001316f, 0.001437f, + 0.001531f, 0.001813f, 0.001952f, 0.002090f, 0.002346f, 0.002560f, 0.002974f, 0.003334f, 0.003899f, 0.004547f, 0.005360f, 0.006516f, + 0.008179f, 0.010468f, 0.013947f, 0.019241f, 0.027832f, 0.041443f, 0.064941f, 0.102600f, 0.162231f, 0.247437f, 0.726074f, 0.737793f, + 0.739258f, 0.740723f, 0.741211f, 0.741211f, 0.000000f, 0.000118f, 0.000115f, 0.000113f, 0.000110f, 0.000126f, 0.000121f, 0.000139f, + 0.000147f, 0.000160f, 0.000161f, 0.000233f, 0.000199f, 0.000266f, 0.000286f, 0.000297f, 0.000329f, 0.000313f, 0.000347f, 0.000358f, + 0.000364f, 0.000394f, 0.000435f, 0.000446f, 0.000489f, 0.000506f, 0.000546f, 0.000625f, 0.000648f, 0.000674f, 0.000723f, 0.000782f, + 0.000865f, 0.000918f, 0.000979f, 0.001104f, 0.001100f, 0.001196f, 0.001352f, 0.001488f, 0.001586f, 0.001749f, 0.001955f, 0.002275f, + 0.002644f, 0.003054f, 0.003563f, 0.004322f, 0.005314f, 0.006786f, 0.008980f, 0.012115f, 0.017319f, 0.026520f, 0.043121f, 0.072693f, + 0.123535f, 0.203613f, 0.705566f, 0.716797f, 0.719238f, 0.719727f, 0.720703f, 0.721191f, 0.000000f, 0.000000f, 0.000112f, 0.000109f, + 0.000106f, 0.000104f, 0.000102f, 0.000096f, 0.000091f, 0.000113f, 0.000147f, 0.000129f, 0.000155f, 0.000134f, 0.000196f, 0.000205f, + 0.000181f, 0.000239f, 0.000297f, 0.000255f, 0.000317f, 0.000273f, 0.000335f, 0.000299f, 0.000379f, 0.000385f, 0.000398f, 0.000402f, + 0.000473f, 0.000552f, 0.000489f, 0.000543f, 0.000557f, 0.000606f, 0.000662f, 0.000698f, 0.000747f, 0.000810f, 0.000902f, 0.000961f, + 0.001063f, 0.001166f, 0.001312f, 0.001523f, 0.001662f, 0.001908f, 0.002298f, 0.002758f, 0.003365f, 0.004135f, 0.005394f, 0.007290f, + 0.010490f, 0.015991f, 0.026215f, 0.047180f, 0.087646f, 0.160645f, 0.682617f, 0.695801f, 0.697266f, 0.697266f, 0.697266f, 0.698730f, + 0.000000f, 0.000112f, 0.000106f, 0.000104f, 0.000100f, 0.000098f, 0.000095f, 0.000094f, 0.000090f, 0.000085f, 0.000080f, 0.000081f, + 0.000085f, 0.000123f, 0.000123f, 0.000138f, 0.000151f, 0.000158f, 0.000147f, 0.000171f, 0.000183f, 0.000192f, 0.000242f, 0.000215f, + 0.000253f, 0.000256f, 0.000269f, 0.000278f, 0.000293f, 0.000315f, 0.000377f, 0.000357f, 0.000357f, 0.000423f, 0.000479f, 0.000493f, + 0.000489f, 0.000535f, 0.000579f, 0.000628f, 0.000683f, 0.000731f, 0.000833f, 0.000935f, 0.001068f, 0.001200f, 0.001347f, 0.001581f, + 0.001995f, 0.002419f, 0.003109f, 0.004147f, 0.005829f, 0.008919f, 0.014641f, 0.027405f, 0.056885f, 0.119385f, 0.658691f, 0.669922f, + 0.673828f, 0.673828f, 0.675293f, 0.675293f, 0.000000f, 0.000105f, 0.000101f, 0.000096f, 0.000092f, 0.000089f, 0.000087f, 0.000085f, + 0.000083f, 0.000081f, 0.000077f, 0.000073f, 0.000070f, 0.000066f, 0.000080f, 0.000084f, 0.000089f, 0.000068f, 0.000101f, 0.000094f, + 0.000116f, 0.000118f, 0.000125f, 0.000129f, 0.000150f, 0.000168f, 0.000153f, 0.000192f, 0.000195f, 0.000185f, 0.000200f, 0.000217f, + 0.000226f, 0.000247f, 0.000257f, 0.000262f, 0.000319f, 0.000334f, 0.000347f, 0.000376f, 0.000395f, 0.000447f, 0.000504f, 0.000544f, + 0.000590f, 0.000670f, 0.000789f, 0.000887f, 0.001069f, 0.001345f, 0.001670f, 0.002167f, 0.003065f, 0.004562f, 0.007660f, 0.014290f, + 0.032135f, 0.081299f, 0.632812f, 0.645996f, 0.648926f, 0.649414f, 0.648926f, 0.649902f, 0.000109f, 0.000094f, 0.000087f, 0.000082f, + 0.000078f, 0.000076f, 0.000074f, 0.000071f, 0.000069f, 0.000068f, 0.000067f, 0.000066f, 0.000064f, 0.000061f, 0.000058f, 0.000055f, + 0.000053f, 0.000050f, 0.000051f, 0.000046f, 0.000059f, 0.000056f, 0.000057f, 0.000068f, 0.000078f, 0.000088f, 0.000096f, 0.000096f, + 0.000105f, 0.000107f, 0.000128f, 0.000121f, 0.000133f, 0.000141f, 0.000156f, 0.000151f, 0.000160f, 0.000200f, 0.000209f, 0.000198f, + 0.000222f, 0.000242f, 0.000258f, 0.000275f, 0.000314f, 0.000352f, 0.000410f, 0.000468f, 0.000537f, 0.000639f, 0.000799f, 0.001002f, + 0.001390f, 0.002092f, 0.003466f, 0.006653f, 0.015305f, 0.048004f, 0.606934f, 0.618652f, 0.622559f, 0.623047f, 0.623535f, 0.624023f, + 0.000084f, 0.000067f, 0.000064f, 0.000062f, 0.000057f, 0.000056f, 0.000053f, 0.000054f, 0.000051f, 0.000052f, 0.000050f, 0.000050f, + 0.000050f, 0.000049f, 0.000048f, 0.000047f, 0.000046f, 0.000044f, 0.000042f, 0.000040f, 0.000039f, 0.000037f, 0.000035f, 0.000036f, + 0.000037f, 0.000031f, 0.000040f, 0.000041f, 0.000042f, 0.000051f, 0.000058f, 0.000063f, 0.000067f, 0.000069f, 0.000072f, 0.000079f, + 0.000085f, 0.000092f, 0.000093f, 0.000101f, 0.000107f, 0.000123f, 0.000125f, 0.000139f, 0.000147f, 0.000154f, 0.000181f, 0.000204f, + 0.000229f, 0.000270f, 0.000327f, 0.000425f, 0.000559f, 0.000772f, 0.001265f, 0.002462f, 0.006191f, 0.022415f, 0.578613f, 0.592285f, + 0.595215f, 0.596191f, 0.596191f, 0.597656f, 0.000008f, 0.000022f, 0.000022f, 0.000024f, 0.000024f, 0.000027f, 0.000028f, 0.000028f, + 0.000028f, 0.000026f, 0.000028f, 0.000029f, 0.000029f, 0.000028f, 0.000029f, 0.000029f, 0.000029f, 0.000029f, 0.000030f, 0.000030f, + 0.000030f, 0.000029f, 0.000028f, 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000019f, + 0.000021f, 0.000020f, 0.000022f, 0.000026f, 0.000028f, 0.000033f, 0.000037f, 0.000036f, 0.000039f, 0.000045f, 0.000051f, 0.000046f, + 0.000056f, 0.000059f, 0.000061f, 0.000071f, 0.000084f, 0.000098f, 0.000110f, 0.000133f, 0.000169f, 0.000223f, 0.000356f, 0.000648f, + 0.001702f, 0.007713f, 0.550293f, 0.564453f, 0.566895f, 0.567871f, 0.568359f, 0.568848f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000003f, 0.000004f, 0.000006f, + 0.000007f, 0.000007f, 0.000008f, 0.000008f, 0.000009f, 0.000010f, 0.000011f, 0.000011f, 0.000012f, 0.000012f, 0.000013f, 0.000013f, + 0.000013f, 0.000014f, 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, + 0.000008f, 0.000008f, 0.000009f, 0.000011f, 0.000014f, 0.000017f, 0.000015f, 0.000018f, 0.000021f, 0.000022f, 0.000023f, 0.000026f, + 0.000035f, 0.000040f, 0.000056f, 0.000089f, 0.000225f, 0.001332f, 0.520996f, 0.535156f, 0.538086f, 0.540039f, 0.540039f, 0.540039f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000003f, 0.000003f, + 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000017f, 0.491211f, 0.506348f, + 0.508789f, 0.510254f, 0.510254f, 0.510742f, + }, + { + 0.064758f, 0.179688f, 0.277344f, 0.358398f, 0.427002f, 0.485107f, 0.535156f, 0.578613f, 0.615234f, 0.647949f, 0.677734f, 0.703125f, + 0.725586f, 0.745605f, 0.763672f, 0.780273f, 0.795410f, 0.810059f, 0.821777f, 0.833496f, 0.843750f, 0.854004f, 0.862793f, 0.871582f, + 0.879883f, 0.886719f, 0.894043f, 0.900879f, 0.906250f, 0.912109f, 0.917969f, 0.922852f, 0.927246f, 0.932129f, 0.936523f, 0.940918f, + 0.944824f, 0.948242f, 0.951660f, 0.955078f, 0.958496f, 0.961426f, 0.964844f, 0.967773f, 0.970215f, 0.973145f, 0.975586f, 0.977539f, + 0.979980f, 0.982422f, 0.984863f, 0.986328f, 0.988770f, 0.990234f, 0.992676f, 0.993652f, 0.995605f, 0.997559f, 0.998535f, 0.996582f, + 0.995117f, 0.993652f, 0.992188f, 0.990723f, 0.040344f, 0.121460f, 0.199341f, 0.272949f, 0.339600f, 0.401123f, 0.455078f, 0.501953f, + 0.546875f, 0.583984f, 0.618164f, 0.648926f, 0.676270f, 0.700195f, 0.723145f, 0.743164f, 0.761230f, 0.776855f, 0.793457f, 0.806641f, + 0.819336f, 0.831543f, 0.842285f, 0.852051f, 0.861328f, 0.869629f, 0.877930f, 0.886230f, 0.892578f, 0.899902f, 0.905273f, 0.911621f, + 0.917480f, 0.922852f, 0.927246f, 0.932129f, 0.936035f, 0.940430f, 0.945312f, 0.949219f, 0.952148f, 0.956055f, 0.958984f, 0.961914f, + 0.965332f, 0.967773f, 0.970703f, 0.973633f, 0.976074f, 0.978516f, 0.980957f, 0.983398f, 0.985840f, 0.987305f, 0.989258f, 0.991699f, + 0.993652f, 0.995117f, 0.997070f, 0.995605f, 0.994141f, 0.993164f, 0.991699f, 0.990234f, 0.027191f, 0.084961f, 0.145630f, 0.206177f, + 0.266113f, 0.323242f, 0.377930f, 0.428711f, 0.474609f, 0.517090f, 0.554688f, 0.591309f, 0.621582f, 0.650391f, 0.676758f, 0.700684f, + 0.723145f, 0.741699f, 0.760254f, 0.776855f, 0.791504f, 0.805664f, 0.818359f, 0.830566f, 0.841309f, 0.851074f, 0.861816f, 0.870117f, + 0.878418f, 0.885254f, 0.892090f, 0.899414f, 0.906250f, 0.912598f, 0.916992f, 0.922363f, 0.928223f, 0.932617f, 0.937500f, 0.941895f, + 0.945801f, 0.949219f, 0.953613f, 0.957031f, 0.960449f, 0.963379f, 0.966797f, 0.969727f, 0.971680f, 0.974609f, 0.977539f, 0.979980f, + 0.981934f, 0.984375f, 0.986328f, 0.989258f, 0.991211f, 0.992676f, 0.996094f, 0.994629f, 0.993652f, 0.992188f, 0.990723f, 0.989746f, + 0.019577f, 0.061340f, 0.108337f, 0.156860f, 0.207153f, 0.258789f, 0.310059f, 0.358887f, 0.405762f, 0.450928f, 0.491211f, 0.530273f, + 0.565430f, 0.597656f, 0.627441f, 0.654297f, 0.680176f, 0.702637f, 0.724121f, 0.743164f, 0.760742f, 0.776855f, 0.791992f, 0.806152f, + 0.817871f, 0.830078f, 0.841797f, 0.852539f, 0.861816f, 0.870117f, 0.878906f, 0.886230f, 0.893066f, 0.900391f, 0.906738f, 0.912598f, + 0.918457f, 0.923340f, 0.928223f, 0.933594f, 0.938477f, 0.942871f, 0.946777f, 0.950684f, 0.954590f, 0.958496f, 0.960938f, 0.964844f, + 0.967773f, 0.970703f, 0.973633f, 0.976074f, 0.979004f, 0.981445f, 0.983398f, 0.985840f, 0.987793f, 0.990234f, 0.995117f, 0.993652f, + 0.992676f, 0.991699f, 0.990234f, 0.989258f, 0.014397f, 0.046295f, 0.081543f, 0.120728f, 0.162842f, 0.206177f, 0.250977f, 0.296143f, + 0.342041f, 0.385986f, 0.427979f, 0.468262f, 0.506348f, 0.542480f, 0.575195f, 0.605469f, 0.633789f, 0.660156f, 0.684570f, 0.706543f, + 0.727539f, 0.745117f, 0.763184f, 0.778809f, 0.793945f, 0.807617f, 0.820312f, 0.833008f, 0.842773f, 0.852539f, 0.862305f, 0.872070f, + 0.879395f, 0.887207f, 0.894531f, 0.900879f, 0.907227f, 0.914551f, 0.919922f, 0.925293f, 0.930176f, 0.935547f, 0.938965f, 0.943359f, + 0.948730f, 0.952637f, 0.956055f, 0.959473f, 0.962891f, 0.966309f, 0.969238f, 0.972656f, 0.975098f, 0.977539f, 0.980957f, 0.982910f, + 0.984863f, 0.987793f, 0.994141f, 0.993164f, 0.991699f, 0.990723f, 0.989746f, 0.988281f, 0.010925f, 0.035828f, 0.063660f, 0.094360f, + 0.128174f, 0.164551f, 0.203247f, 0.244385f, 0.285645f, 0.326416f, 0.367432f, 0.409424f, 0.447998f, 0.484131f, 0.520508f, 0.553711f, + 0.584473f, 0.614258f, 0.641113f, 0.666016f, 0.689453f, 0.710938f, 0.730469f, 0.750488f, 0.766602f, 0.781250f, 0.796387f, 0.809570f, + 0.822266f, 0.833496f, 0.844727f, 0.854980f, 0.864258f, 0.873047f, 0.881348f, 0.889648f, 0.895996f, 0.903809f, 0.910156f, 0.916504f, + 0.921387f, 0.926758f, 0.932129f, 0.937500f, 0.941895f, 0.946777f, 0.950684f, 0.954102f, 0.958008f, 0.960938f, 0.965332f, 0.968262f, + 0.971680f, 0.975098f, 0.977539f, 0.979492f, 0.982422f, 0.984863f, 0.992676f, 0.991699f, 0.990723f, 0.989746f, 0.988770f, 0.987793f, + 0.008698f, 0.028244f, 0.049866f, 0.074463f, 0.102295f, 0.132935f, 0.165161f, 0.200073f, 0.236206f, 0.275391f, 0.313477f, 0.352051f, + 0.391113f, 0.428955f, 0.465088f, 0.500977f, 0.534180f, 0.565430f, 0.593750f, 0.622559f, 0.648438f, 0.671875f, 0.694824f, 0.715820f, + 0.734863f, 0.753906f, 0.771484f, 0.784668f, 0.799805f, 0.813477f, 0.825195f, 0.836914f, 0.847656f, 0.857910f, 0.866699f, 0.875488f, + 0.884766f, 0.892090f, 0.898438f, 0.906250f, 0.913086f, 0.918457f, 0.923828f, 0.929688f, 0.935059f, 0.939941f, 0.944336f, 0.948730f, + 0.952637f, 0.956055f, 0.959961f, 0.963379f, 0.967285f, 0.970703f, 0.973633f, 0.976074f, 0.979492f, 0.982422f, 0.991211f, 0.990723f, + 0.990234f, 0.988770f, 0.987793f, 0.986328f, 0.007210f, 0.022797f, 0.040039f, 0.060181f, 0.082153f, 0.107300f, 0.134155f, 0.164673f, + 0.196167f, 0.229492f, 0.265381f, 0.301025f, 0.338379f, 0.374756f, 0.411133f, 0.446533f, 0.481201f, 0.515625f, 0.546387f, 0.576660f, + 0.605957f, 0.631348f, 0.656738f, 0.681152f, 0.702148f, 0.722168f, 0.741699f, 0.758789f, 0.775391f, 0.791016f, 0.803711f, 0.817383f, + 0.829102f, 0.840820f, 0.851562f, 0.860840f, 0.871094f, 0.879395f, 0.887695f, 0.895020f, 0.901855f, 0.909180f, 0.915527f, 0.921387f, + 0.927734f, 0.932129f, 0.937500f, 0.941895f, 0.947266f, 0.950684f, 0.955078f, 0.958984f, 0.962891f, 0.966797f, 0.969727f, 0.973145f, + 0.976562f, 0.979004f, 0.990234f, 0.989746f, 0.988770f, 0.987793f, 0.986816f, 0.985840f, 0.005863f, 0.018936f, 0.032898f, 0.049377f, + 0.067261f, 0.088257f, 0.110535f, 0.135254f, 0.162231f, 0.191895f, 0.223389f, 0.255371f, 0.290039f, 0.324707f, 0.359863f, 0.395996f, + 0.429932f, 0.464355f, 0.497314f, 0.529297f, 0.559570f, 0.587891f, 0.616699f, 0.642090f, 0.665527f, 0.688965f, 0.709961f, 0.729492f, + 0.747559f, 0.765625f, 0.780762f, 0.794922f, 0.809082f, 0.822754f, 0.833984f, 0.844727f, 0.855957f, 0.864746f, 0.875000f, 0.883789f, + 0.891113f, 0.898926f, 0.906250f, 0.912598f, 0.918457f, 0.925293f, 0.930664f, 0.935059f, 0.940918f, 0.945312f, 0.950195f, 0.954590f, + 0.958496f, 0.962402f, 0.965820f, 0.969238f, 0.972656f, 0.976074f, 0.988770f, 0.988770f, 0.987793f, 0.986816f, 0.985840f, 0.984863f, + 0.004925f, 0.015518f, 0.027451f, 0.041199f, 0.055786f, 0.072998f, 0.091492f, 0.112427f, 0.135254f, 0.160767f, 0.187500f, 0.216919f, + 0.247314f, 0.280273f, 0.313477f, 0.346680f, 0.381592f, 0.415283f, 0.448730f, 0.481201f, 0.513184f, 0.543945f, 0.573242f, 0.601562f, + 0.627441f, 0.652344f, 0.675293f, 0.697754f, 0.718262f, 0.737793f, 0.754883f, 0.771973f, 0.787109f, 0.800781f, 0.815430f, 0.828125f, + 0.839844f, 0.851074f, 0.860840f, 0.870117f, 0.879883f, 0.887695f, 0.896484f, 0.902832f, 0.911133f, 0.916992f, 0.922852f, 0.928711f, + 0.934082f, 0.939941f, 0.944336f, 0.948730f, 0.954102f, 0.958008f, 0.961426f, 0.965332f, 0.969238f, 0.972168f, 0.987305f, 0.987305f, + 0.986816f, 0.985840f, 0.984863f, 0.983887f, 0.004139f, 0.012955f, 0.022781f, 0.034088f, 0.046997f, 0.061005f, 0.076538f, 0.094360f, + 0.113464f, 0.134888f, 0.158203f, 0.183716f, 0.210693f, 0.239990f, 0.270264f, 0.302734f, 0.334961f, 0.367676f, 0.400635f, 0.434082f, + 0.467041f, 0.497803f, 0.528809f, 0.558105f, 0.586426f, 0.614258f, 0.638672f, 0.663574f, 0.686035f, 0.707520f, 0.728027f, 0.745605f, + 0.762695f, 0.779297f, 0.794434f, 0.808594f, 0.821777f, 0.834473f, 0.845215f, 0.855957f, 0.866699f, 0.876465f, 0.884766f, 0.892090f, + 0.900391f, 0.908203f, 0.915039f, 0.920898f, 0.927246f, 0.932617f, 0.937988f, 0.943848f, 0.948730f, 0.952637f, 0.957520f, 0.961426f, + 0.965820f, 0.968750f, 0.985840f, 0.985840f, 0.985840f, 0.984375f, 0.983887f, 0.982910f, 0.003492f, 0.011307f, 0.019608f, 0.028793f, + 0.039246f, 0.051544f, 0.064392f, 0.078796f, 0.095337f, 0.113953f, 0.134033f, 0.155396f, 0.179688f, 0.205200f, 0.232300f, 0.261475f, + 0.291748f, 0.323730f, 0.355225f, 0.387939f, 0.420410f, 0.452637f, 0.483887f, 0.514648f, 0.544922f, 0.573730f, 0.601074f, 0.626953f, + 0.651367f, 0.675293f, 0.697266f, 0.717285f, 0.736816f, 0.755371f, 0.771973f, 0.786621f, 0.803223f, 0.815430f, 0.828613f, 0.840820f, + 0.851562f, 0.863281f, 0.873047f, 0.880859f, 0.890625f, 0.898438f, 0.905762f, 0.913086f, 0.919434f, 0.925781f, 0.931641f, 0.937500f, + 0.942871f, 0.947754f, 0.952637f, 0.957520f, 0.960938f, 0.965820f, 0.984375f, 0.984863f, 0.984375f, 0.983398f, 0.982422f, 0.981445f, + 0.002977f, 0.009415f, 0.016708f, 0.024811f, 0.033356f, 0.043457f, 0.054535f, 0.067017f, 0.080322f, 0.096130f, 0.113708f, 0.132080f, + 0.152710f, 0.175415f, 0.199829f, 0.226440f, 0.253662f, 0.282959f, 0.313232f, 0.343750f, 0.375000f, 0.406982f, 0.439453f, 0.471191f, + 0.501465f, 0.531738f, 0.560547f, 0.587891f, 0.615234f, 0.640625f, 0.664062f, 0.687500f, 0.708496f, 0.728516f, 0.747559f, 0.765137f, + 0.781738f, 0.795898f, 0.811523f, 0.824707f, 0.836426f, 0.847656f, 0.858887f, 0.869141f, 0.878906f, 0.887695f, 0.895996f, 0.904297f, + 0.911133f, 0.917969f, 0.925293f, 0.931152f, 0.937012f, 0.942383f, 0.947266f, 0.953125f, 0.957031f, 0.961426f, 0.982910f, 0.983398f, + 0.982910f, 0.982422f, 0.981445f, 0.980957f, 0.002743f, 0.008568f, 0.014305f, 0.021378f, 0.028732f, 0.037201f, 0.046387f, 0.057068f, + 0.068848f, 0.082336f, 0.096924f, 0.113159f, 0.130859f, 0.150146f, 0.171509f, 0.194824f, 0.219482f, 0.246338f, 0.273926f, 0.302734f, + 0.333496f, 0.364502f, 0.395752f, 0.426758f, 0.458252f, 0.489990f, 0.519531f, 0.548340f, 0.576660f, 0.604004f, 0.630859f, 0.654297f, + 0.678223f, 0.700684f, 0.720215f, 0.740234f, 0.758301f, 0.775391f, 0.790527f, 0.805176f, 0.818848f, 0.833008f, 0.844238f, 0.855469f, + 0.866699f, 0.876953f, 0.886230f, 0.894043f, 0.902832f, 0.910645f, 0.917480f, 0.924316f, 0.930664f, 0.937012f, 0.941895f, 0.947266f, + 0.952148f, 0.957031f, 0.981445f, 0.982422f, 0.981445f, 0.980957f, 0.980469f, 0.979004f, 0.002504f, 0.007004f, 0.012634f, 0.018555f, + 0.024933f, 0.032654f, 0.040283f, 0.048920f, 0.059357f, 0.070007f, 0.082642f, 0.096741f, 0.112122f, 0.128906f, 0.147339f, 0.167603f, + 0.189697f, 0.213257f, 0.238770f, 0.265869f, 0.293701f, 0.323242f, 0.354004f, 0.384766f, 0.415283f, 0.447021f, 0.478516f, 0.507812f, + 0.536621f, 0.565918f, 0.593750f, 0.620605f, 0.645508f, 0.668945f, 0.692383f, 0.712891f, 0.733398f, 0.751465f, 0.769531f, 0.785156f, + 0.801270f, 0.814941f, 0.828125f, 0.841797f, 0.853516f, 0.864746f, 0.874512f, 0.883789f, 0.893555f, 0.900879f, 0.910156f, 0.917480f, + 0.923340f, 0.930664f, 0.936523f, 0.942383f, 0.947754f, 0.952637f, 0.979492f, 0.980469f, 0.980469f, 0.979492f, 0.978516f, 0.978027f, + 0.002039f, 0.006287f, 0.010864f, 0.016129f, 0.021637f, 0.027786f, 0.034485f, 0.042450f, 0.051331f, 0.060760f, 0.071594f, 0.082886f, + 0.096313f, 0.110840f, 0.126587f, 0.145020f, 0.164185f, 0.185181f, 0.207520f, 0.232300f, 0.258301f, 0.285889f, 0.314941f, 0.344238f, + 0.374268f, 0.405029f, 0.436035f, 0.466797f, 0.498291f, 0.527344f, 0.555664f, 0.583984f, 0.611328f, 0.636230f, 0.661133f, 0.684082f, + 0.705566f, 0.726562f, 0.745605f, 0.764648f, 0.781250f, 0.797852f, 0.812500f, 0.825195f, 0.838867f, 0.851074f, 0.862305f, 0.873535f, + 0.883301f, 0.892578f, 0.901367f, 0.908203f, 0.916992f, 0.923828f, 0.931152f, 0.937012f, 0.942383f, 0.947266f, 0.978027f, 0.978516f, + 0.979004f, 0.978027f, 0.977051f, 0.977051f, 0.001762f, 0.005489f, 0.009804f, 0.013931f, 0.019028f, 0.024445f, 0.030518f, 0.036865f, + 0.044189f, 0.052460f, 0.061432f, 0.071960f, 0.083008f, 0.095642f, 0.109558f, 0.124756f, 0.141602f, 0.160156f, 0.180664f, 0.202148f, + 0.225952f, 0.250977f, 0.278076f, 0.305664f, 0.334961f, 0.364990f, 0.394775f, 0.425537f, 0.456543f, 0.487061f, 0.517090f, 0.546387f, + 0.575195f, 0.602539f, 0.627930f, 0.653809f, 0.676758f, 0.699707f, 0.721191f, 0.740723f, 0.759766f, 0.777832f, 0.793945f, 0.809082f, + 0.823242f, 0.836426f, 0.849609f, 0.861328f, 0.872070f, 0.881836f, 0.892578f, 0.900391f, 0.908691f, 0.916992f, 0.924316f, 0.931152f, + 0.937500f, 0.943359f, 0.976074f, 0.977051f, 0.977051f, 0.976562f, 0.976074f, 0.975098f, 0.001675f, 0.005020f, 0.008400f, 0.012253f, + 0.016724f, 0.021469f, 0.026428f, 0.032104f, 0.039062f, 0.045563f, 0.053741f, 0.062103f, 0.072205f, 0.082947f, 0.094666f, 0.107727f, + 0.122681f, 0.139038f, 0.156250f, 0.176514f, 0.197388f, 0.220581f, 0.244629f, 0.270752f, 0.297607f, 0.326172f, 0.355957f, 0.386475f, + 0.416748f, 0.447754f, 0.478027f, 0.507812f, 0.538086f, 0.566406f, 0.594727f, 0.621582f, 0.647461f, 0.671387f, 0.694336f, 0.716797f, + 0.737305f, 0.755859f, 0.773438f, 0.791016f, 0.807129f, 0.820801f, 0.834961f, 0.848145f, 0.860352f, 0.871582f, 0.881836f, 0.891602f, + 0.901367f, 0.909180f, 0.917480f, 0.925293f, 0.932129f, 0.938965f, 0.974609f, 0.975586f, 0.976074f, 0.974609f, 0.974121f, 0.973633f, + 0.001437f, 0.004513f, 0.007427f, 0.010994f, 0.014526f, 0.018829f, 0.023331f, 0.028229f, 0.034058f, 0.040192f, 0.046844f, 0.054321f, + 0.062683f, 0.071716f, 0.082397f, 0.093933f, 0.106567f, 0.120728f, 0.136230f, 0.153320f, 0.172485f, 0.192627f, 0.214233f, 0.237915f, + 0.263672f, 0.290527f, 0.318115f, 0.347412f, 0.377197f, 0.408203f, 0.438477f, 0.469482f, 0.499512f, 0.529785f, 0.558594f, 0.586914f, + 0.614258f, 0.641602f, 0.665527f, 0.689941f, 0.711914f, 0.732422f, 0.752930f, 0.771484f, 0.789062f, 0.805664f, 0.819824f, 0.833984f, + 0.847656f, 0.860840f, 0.871094f, 0.881836f, 0.891602f, 0.902344f, 0.910156f, 0.918457f, 0.926270f, 0.932617f, 0.972168f, 0.973633f, + 0.973633f, 0.973145f, 0.973145f, 0.971680f, 0.001390f, 0.003952f, 0.006779f, 0.009941f, 0.013062f, 0.017029f, 0.020905f, 0.024994f, + 0.029877f, 0.035187f, 0.041077f, 0.047119f, 0.055145f, 0.062500f, 0.071594f, 0.081543f, 0.092712f, 0.104736f, 0.118530f, 0.133179f, + 0.150024f, 0.168091f, 0.187378f, 0.209717f, 0.232178f, 0.256836f, 0.283447f, 0.311279f, 0.339844f, 0.369873f, 0.399658f, 0.429932f, + 0.461426f, 0.492188f, 0.521973f, 0.551758f, 0.580566f, 0.608887f, 0.635254f, 0.660645f, 0.685059f, 0.708008f, 0.729492f, 0.750488f, + 0.769043f, 0.786621f, 0.802734f, 0.818848f, 0.832520f, 0.846680f, 0.860352f, 0.871582f, 0.882324f, 0.892578f, 0.902832f, 0.911133f, + 0.919922f, 0.926758f, 0.970703f, 0.971680f, 0.971680f, 0.971680f, 0.971680f, 0.969238f, 0.001328f, 0.003641f, 0.006138f, 0.008690f, + 0.011444f, 0.014786f, 0.018311f, 0.022125f, 0.026337f, 0.031403f, 0.036011f, 0.041809f, 0.047943f, 0.054901f, 0.062622f, 0.071106f, + 0.081299f, 0.091614f, 0.103455f, 0.116333f, 0.130493f, 0.146484f, 0.164307f, 0.183228f, 0.204224f, 0.226685f, 0.251221f, 0.277100f, + 0.303711f, 0.332764f, 0.361572f, 0.391846f, 0.422852f, 0.454102f, 0.485352f, 0.515625f, 0.545410f, 0.574707f, 0.603027f, 0.630371f, + 0.656250f, 0.681641f, 0.705078f, 0.726562f, 0.747070f, 0.767578f, 0.784668f, 0.803223f, 0.818848f, 0.833008f, 0.847656f, 0.860352f, + 0.872559f, 0.883301f, 0.894043f, 0.903809f, 0.913574f, 0.921387f, 0.967773f, 0.970215f, 0.970215f, 0.968750f, 0.969238f, 0.968750f, + 0.001053f, 0.002905f, 0.005432f, 0.007912f, 0.010658f, 0.012901f, 0.016464f, 0.019363f, 0.023376f, 0.027237f, 0.031799f, 0.036346f, + 0.042145f, 0.048248f, 0.054871f, 0.062256f, 0.070618f, 0.079834f, 0.089844f, 0.101440f, 0.113831f, 0.128174f, 0.143433f, 0.160156f, + 0.179077f, 0.199707f, 0.222046f, 0.245483f, 0.271240f, 0.297363f, 0.325684f, 0.355469f, 0.385254f, 0.416016f, 0.447754f, 0.479004f, + 0.508789f, 0.539551f, 0.570312f, 0.598145f, 0.626465f, 0.652344f, 0.678223f, 0.702148f, 0.725098f, 0.746094f, 0.765625f, 0.785645f, + 0.803223f, 0.819336f, 0.834961f, 0.848145f, 0.861328f, 0.873535f, 0.884766f, 0.895508f, 0.905762f, 0.915527f, 0.965332f, 0.967773f, + 0.968262f, 0.967773f, 0.967285f, 0.966309f, 0.001106f, 0.002684f, 0.004913f, 0.006733f, 0.009300f, 0.011955f, 0.014435f, 0.017700f, + 0.020477f, 0.024124f, 0.028091f, 0.032532f, 0.037231f, 0.042511f, 0.048309f, 0.054596f, 0.061798f, 0.069885f, 0.078857f, 0.089050f, + 0.099915f, 0.112183f, 0.125488f, 0.140503f, 0.157104f, 0.175293f, 0.195068f, 0.216309f, 0.240356f, 0.265381f, 0.291748f, 0.319580f, + 0.348633f, 0.379150f, 0.410156f, 0.441406f, 0.472900f, 0.503418f, 0.534668f, 0.565430f, 0.594727f, 0.622070f, 0.649902f, 0.676270f, + 0.700195f, 0.723633f, 0.746094f, 0.766602f, 0.786133f, 0.802734f, 0.819824f, 0.835449f, 0.849609f, 0.863281f, 0.875977f, 0.887695f, + 0.898438f, 0.908203f, 0.962891f, 0.965820f, 0.966309f, 0.965332f, 0.964844f, 0.964355f, 0.000782f, 0.002707f, 0.004574f, 0.006184f, + 0.008286f, 0.010681f, 0.012878f, 0.015640f, 0.018478f, 0.021912f, 0.025208f, 0.028976f, 0.032867f, 0.037598f, 0.042938f, 0.048370f, + 0.054443f, 0.061432f, 0.069214f, 0.077515f, 0.087402f, 0.098145f, 0.109497f, 0.122803f, 0.137329f, 0.153564f, 0.171509f, 0.190918f, + 0.212158f, 0.235352f, 0.259766f, 0.286133f, 0.314209f, 0.343262f, 0.373535f, 0.404297f, 0.436279f, 0.467773f, 0.499512f, 0.530273f, + 0.561523f, 0.590820f, 0.620117f, 0.647461f, 0.674316f, 0.699219f, 0.722656f, 0.745605f, 0.766602f, 0.785645f, 0.804688f, 0.821777f, + 0.836426f, 0.852051f, 0.865234f, 0.878418f, 0.890625f, 0.901855f, 0.959961f, 0.962891f, 0.963867f, 0.963379f, 0.962402f, 0.962402f, + 0.000787f, 0.002195f, 0.004250f, 0.005775f, 0.007774f, 0.009445f, 0.011795f, 0.013725f, 0.016678f, 0.019531f, 0.022018f, 0.025665f, + 0.029495f, 0.033142f, 0.037598f, 0.042664f, 0.048248f, 0.053772f, 0.060699f, 0.067993f, 0.076416f, 0.085815f, 0.095764f, 0.107422f, + 0.120239f, 0.134277f, 0.150269f, 0.167358f, 0.186646f, 0.207764f, 0.230347f, 0.255127f, 0.281250f, 0.308838f, 0.337891f, 0.368408f, + 0.399414f, 0.431396f, 0.463135f, 0.495605f, 0.526855f, 0.558594f, 0.588379f, 0.618652f, 0.646973f, 0.673828f, 0.699707f, 0.723633f, + 0.746094f, 0.767090f, 0.788086f, 0.806641f, 0.823730f, 0.840332f, 0.854980f, 0.869141f, 0.881836f, 0.893555f, 0.957520f, 0.960938f, + 0.960938f, 0.961426f, 0.960449f, 0.959961f, 0.000765f, 0.002207f, 0.003666f, 0.005177f, 0.006973f, 0.008301f, 0.010704f, 0.012794f, + 0.015015f, 0.017303f, 0.020309f, 0.022568f, 0.026123f, 0.029587f, 0.033325f, 0.037659f, 0.042206f, 0.047516f, 0.053223f, 0.059814f, + 0.067017f, 0.075195f, 0.083801f, 0.094055f, 0.105042f, 0.117737f, 0.131470f, 0.146851f, 0.163940f, 0.182739f, 0.203369f, 0.225952f, + 0.250244f, 0.276367f, 0.304199f, 0.333008f, 0.364258f, 0.395264f, 0.427002f, 0.459961f, 0.491699f, 0.524414f, 0.555664f, 0.586914f, + 0.617676f, 0.645996f, 0.673340f, 0.699707f, 0.724121f, 0.748047f, 0.770020f, 0.790039f, 0.809082f, 0.827148f, 0.842773f, 0.858398f, + 0.873047f, 0.885742f, 0.954102f, 0.958008f, 0.958496f, 0.958496f, 0.958496f, 0.957520f, 0.000586f, 0.001937f, 0.003107f, 0.004745f, + 0.006168f, 0.007610f, 0.009590f, 0.011345f, 0.013321f, 0.015587f, 0.017593f, 0.020294f, 0.023346f, 0.026154f, 0.029205f, 0.033234f, + 0.037415f, 0.041962f, 0.046906f, 0.052673f, 0.058533f, 0.065796f, 0.073669f, 0.082642f, 0.092346f, 0.103027f, 0.115234f, 0.128784f, + 0.143799f, 0.160889f, 0.179199f, 0.199585f, 0.221802f, 0.246094f, 0.271973f, 0.299805f, 0.329102f, 0.359863f, 0.391357f, 0.423340f, + 0.456299f, 0.490234f, 0.522949f, 0.555176f, 0.586426f, 0.617188f, 0.645996f, 0.675293f, 0.701660f, 0.726074f, 0.750488f, 0.773926f, + 0.793945f, 0.812988f, 0.831543f, 0.847656f, 0.862793f, 0.877441f, 0.951660f, 0.955078f, 0.955566f, 0.955566f, 0.955078f, 0.954590f, + 0.000678f, 0.001864f, 0.003138f, 0.004333f, 0.005707f, 0.006893f, 0.008224f, 0.009850f, 0.012215f, 0.013954f, 0.015747f, 0.018219f, + 0.020584f, 0.023148f, 0.026047f, 0.029434f, 0.033020f, 0.037018f, 0.041626f, 0.046509f, 0.051910f, 0.058105f, 0.064636f, 0.072510f, + 0.080750f, 0.090149f, 0.100891f, 0.112549f, 0.126343f, 0.141113f, 0.157593f, 0.175537f, 0.195801f, 0.218018f, 0.242554f, 0.268311f, + 0.295898f, 0.325195f, 0.355713f, 0.388184f, 0.421143f, 0.454834f, 0.488281f, 0.522949f, 0.554199f, 0.587402f, 0.618164f, 0.648438f, + 0.676758f, 0.704102f, 0.730957f, 0.754395f, 0.776855f, 0.798340f, 0.817871f, 0.836426f, 0.852051f, 0.868164f, 0.948242f, 0.952637f, + 0.953125f, 0.952637f, 0.952148f, 0.951660f, 0.000470f, 0.001578f, 0.002934f, 0.003838f, 0.005032f, 0.006310f, 0.007725f, 0.008972f, + 0.010826f, 0.012657f, 0.014359f, 0.015991f, 0.018402f, 0.020721f, 0.023102f, 0.026230f, 0.029495f, 0.032867f, 0.036743f, 0.040680f, + 0.045654f, 0.050812f, 0.056763f, 0.063477f, 0.071045f, 0.078918f, 0.088440f, 0.098938f, 0.110657f, 0.123535f, 0.138062f, 0.154175f, + 0.172363f, 0.192627f, 0.214478f, 0.238770f, 0.264404f, 0.292236f, 0.322266f, 0.353271f, 0.385742f, 0.419189f, 0.453857f, 0.487549f, + 0.521484f, 0.555664f, 0.588867f, 0.621094f, 0.651367f, 0.680176f, 0.708008f, 0.733887f, 0.759766f, 0.780762f, 0.802734f, 0.821289f, + 0.840820f, 0.858398f, 0.943848f, 0.949219f, 0.949707f, 0.949707f, 0.949707f, 0.949219f, 0.000485f, 0.001689f, 0.002386f, 0.003698f, + 0.004547f, 0.005936f, 0.006851f, 0.008217f, 0.009834f, 0.011055f, 0.012810f, 0.014473f, 0.016449f, 0.018509f, 0.020950f, 0.023209f, + 0.025940f, 0.029114f, 0.032410f, 0.036133f, 0.040161f, 0.044861f, 0.050018f, 0.055664f, 0.061859f, 0.069153f, 0.077515f, 0.086365f, + 0.096680f, 0.108093f, 0.120605f, 0.135132f, 0.151489f, 0.169556f, 0.189209f, 0.211426f, 0.235352f, 0.261475f, 0.289307f, 0.319580f, + 0.351074f, 0.384521f, 0.418701f, 0.452881f, 0.487549f, 0.522461f, 0.556641f, 0.591309f, 0.623535f, 0.653809f, 0.684570f, 0.712891f, + 0.739258f, 0.764160f, 0.787109f, 0.809570f, 0.829102f, 0.847168f, 0.940918f, 0.945801f, 0.946289f, 0.946777f, 0.946777f, 0.945312f, + 0.000620f, 0.001351f, 0.002413f, 0.003273f, 0.004307f, 0.004971f, 0.006138f, 0.007542f, 0.008835f, 0.009972f, 0.011581f, 0.013069f, + 0.014717f, 0.016495f, 0.018738f, 0.020691f, 0.023315f, 0.025879f, 0.028793f, 0.031860f, 0.035309f, 0.039246f, 0.043762f, 0.048950f, + 0.054474f, 0.060669f, 0.067932f, 0.075378f, 0.084351f, 0.094055f, 0.105774f, 0.118469f, 0.132690f, 0.148315f, 0.166504f, 0.186401f, + 0.208130f, 0.232544f, 0.258789f, 0.287109f, 0.317627f, 0.349854f, 0.383057f, 0.417725f, 0.453125f, 0.488770f, 0.523926f, 0.559082f, + 0.594238f, 0.627441f, 0.659180f, 0.689941f, 0.719238f, 0.745117f, 0.770508f, 0.794434f, 0.815430f, 0.836914f, 0.936523f, 0.941895f, + 0.942871f, 0.942871f, 0.942871f, 0.942383f, 0.000404f, 0.001095f, 0.002087f, 0.002983f, 0.003986f, 0.004673f, 0.005844f, 0.006878f, + 0.007740f, 0.008873f, 0.010323f, 0.011757f, 0.013176f, 0.014915f, 0.016586f, 0.018585f, 0.020523f, 0.022720f, 0.025391f, 0.028244f, + 0.031219f, 0.034821f, 0.038788f, 0.042908f, 0.047943f, 0.053040f, 0.058960f, 0.066162f, 0.073547f, 0.082397f, 0.092285f, 0.102844f, + 0.115234f, 0.129883f, 0.146118f, 0.163452f, 0.183350f, 0.205688f, 0.229614f, 0.256592f, 0.285156f, 0.316162f, 0.348633f, 0.383057f, + 0.418457f, 0.454590f, 0.490967f, 0.526855f, 0.563477f, 0.598633f, 0.632812f, 0.665527f, 0.696777f, 0.726074f, 0.752930f, 0.779297f, + 0.803223f, 0.825684f, 0.933105f, 0.938477f, 0.938477f, 0.938965f, 0.938477f, 0.938477f, 0.000415f, 0.000864f, 0.001907f, 0.002775f, + 0.003519f, 0.004204f, 0.005352f, 0.006237f, 0.007019f, 0.008064f, 0.009239f, 0.010483f, 0.011742f, 0.013130f, 0.014877f, 0.016571f, + 0.018494f, 0.020126f, 0.022537f, 0.024826f, 0.027649f, 0.030701f, 0.033875f, 0.037964f, 0.042114f, 0.046356f, 0.051605f, 0.057587f, + 0.064209f, 0.071777f, 0.080261f, 0.089722f, 0.100952f, 0.113220f, 0.127075f, 0.143066f, 0.160767f, 0.180664f, 0.202759f, 0.227417f, + 0.254395f, 0.284180f, 0.315674f, 0.348633f, 0.383789f, 0.420166f, 0.457275f, 0.494385f, 0.531250f, 0.569336f, 0.605469f, 0.639160f, + 0.672363f, 0.705078f, 0.735352f, 0.762207f, 0.788574f, 0.811523f, 0.928711f, 0.934082f, 0.934570f, 0.935059f, 0.935059f, 0.935059f, + 0.000236f, 0.001136f, 0.001664f, 0.002502f, 0.003187f, 0.004082f, 0.004631f, 0.005386f, 0.006275f, 0.007385f, 0.008217f, 0.009453f, + 0.010567f, 0.011787f, 0.013115f, 0.014420f, 0.016083f, 0.017944f, 0.019867f, 0.022079f, 0.024414f, 0.026962f, 0.029755f, 0.033112f, + 0.036926f, 0.040771f, 0.045258f, 0.050232f, 0.056183f, 0.062500f, 0.069946f, 0.078430f, 0.087708f, 0.098389f, 0.110779f, 0.124634f, + 0.140259f, 0.158203f, 0.178223f, 0.200928f, 0.225708f, 0.253174f, 0.282715f, 0.315430f, 0.349365f, 0.385254f, 0.422363f, 0.460938f, + 0.499023f, 0.537109f, 0.574707f, 0.612305f, 0.646484f, 0.682129f, 0.713867f, 0.745117f, 0.772461f, 0.799316f, 0.923828f, 0.930176f, + 0.930664f, 0.931152f, 0.930664f, 0.930664f, 0.000229f, 0.000964f, 0.001582f, 0.002182f, 0.002838f, 0.003653f, 0.004341f, 0.004921f, + 0.005615f, 0.006626f, 0.007423f, 0.008545f, 0.009483f, 0.010666f, 0.011612f, 0.013000f, 0.014275f, 0.015900f, 0.017487f, 0.019333f, + 0.021484f, 0.023773f, 0.026276f, 0.028992f, 0.032135f, 0.035492f, 0.039398f, 0.044037f, 0.049072f, 0.054443f, 0.061035f, 0.067871f, + 0.076111f, 0.085632f, 0.096252f, 0.108154f, 0.122253f, 0.138306f, 0.156006f, 0.175903f, 0.199219f, 0.224243f, 0.251953f, 0.282715f, + 0.315918f, 0.350830f, 0.387451f, 0.425781f, 0.465332f, 0.504395f, 0.544434f, 0.583008f, 0.620117f, 0.657715f, 0.692383f, 0.725098f, + 0.755371f, 0.783691f, 0.919434f, 0.925781f, 0.926270f, 0.926758f, 0.926758f, 0.925781f, 0.000410f, 0.000856f, 0.001542f, 0.001844f, + 0.002565f, 0.003380f, 0.003971f, 0.004246f, 0.005047f, 0.005863f, 0.006653f, 0.007744f, 0.008568f, 0.009407f, 0.010529f, 0.011482f, + 0.012657f, 0.013924f, 0.015602f, 0.017105f, 0.018997f, 0.020859f, 0.022980f, 0.025192f, 0.028030f, 0.031036f, 0.034515f, 0.038300f, + 0.042236f, 0.047180f, 0.052795f, 0.059113f, 0.065857f, 0.074097f, 0.083374f, 0.094360f, 0.105896f, 0.119873f, 0.135620f, 0.154175f, + 0.174072f, 0.197632f, 0.223267f, 0.251465f, 0.283447f, 0.317139f, 0.353760f, 0.391113f, 0.431152f, 0.470703f, 0.512207f, 0.552734f, + 0.592285f, 0.631348f, 0.669434f, 0.704590f, 0.737793f, 0.768555f, 0.913574f, 0.919922f, 0.920898f, 0.920898f, 0.921387f, 0.921387f, + 0.000214f, 0.000619f, 0.001172f, 0.001941f, 0.002228f, 0.002960f, 0.003490f, 0.003994f, 0.004761f, 0.005180f, 0.005806f, 0.006622f, + 0.007565f, 0.008301f, 0.009262f, 0.010170f, 0.011208f, 0.012482f, 0.013855f, 0.015060f, 0.016739f, 0.018311f, 0.020248f, 0.022034f, + 0.024597f, 0.027084f, 0.030045f, 0.033051f, 0.036743f, 0.041016f, 0.045807f, 0.050964f, 0.056946f, 0.063904f, 0.071899f, 0.080994f, + 0.091675f, 0.103699f, 0.117920f, 0.133667f, 0.151978f, 0.172729f, 0.196533f, 0.222534f, 0.252197f, 0.284424f, 0.319580f, 0.356689f, + 0.396973f, 0.437500f, 0.479492f, 0.521484f, 0.562500f, 0.604004f, 0.644043f, 0.682129f, 0.718262f, 0.751465f, 0.907715f, 0.915039f, + 0.916016f, 0.916504f, 0.916504f, 0.916504f, 0.000405f, 0.000760f, 0.001116f, 0.001688f, 0.002180f, 0.002670f, 0.003313f, 0.003569f, + 0.003979f, 0.004543f, 0.005466f, 0.005985f, 0.006699f, 0.007359f, 0.008102f, 0.009094f, 0.009949f, 0.011055f, 0.012047f, 0.013412f, + 0.014488f, 0.016068f, 0.017532f, 0.019348f, 0.021210f, 0.023834f, 0.025986f, 0.028854f, 0.031891f, 0.035339f, 0.039490f, 0.043976f, + 0.049347f, 0.055084f, 0.061951f, 0.069763f, 0.078918f, 0.089478f, 0.101379f, 0.115479f, 0.131592f, 0.150024f, 0.171387f, 0.195068f, + 0.222900f, 0.252686f, 0.286621f, 0.323242f, 0.362061f, 0.402588f, 0.445312f, 0.488770f, 0.532715f, 0.575684f, 0.618652f, 0.659180f, + 0.698242f, 0.734375f, 0.901367f, 0.909180f, 0.911133f, 0.910645f, 0.911133f, 0.910645f, 0.000218f, 0.000539f, 0.001187f, 0.001617f, + 0.001987f, 0.002316f, 0.002666f, 0.003176f, 0.003841f, 0.004425f, 0.004917f, 0.005402f, 0.005768f, 0.006462f, 0.007233f, 0.008018f, + 0.008575f, 0.009758f, 0.010582f, 0.011520f, 0.012756f, 0.013832f, 0.015312f, 0.016968f, 0.018509f, 0.020279f, 0.022644f, 0.024857f, + 0.027740f, 0.030472f, 0.033783f, 0.037567f, 0.042175f, 0.047150f, 0.052979f, 0.059601f, 0.067505f, 0.076538f, 0.087158f, 0.099243f, + 0.113281f, 0.129272f, 0.148315f, 0.170532f, 0.194702f, 0.223267f, 0.254639f, 0.289795f, 0.327393f, 0.368408f, 0.410889f, 0.455322f, + 0.499756f, 0.544434f, 0.590332f, 0.633789f, 0.676270f, 0.716309f, 0.895508f, 0.902344f, 0.903809f, 0.905762f, 0.903809f, 0.904297f, + 0.000184f, 0.000612f, 0.001122f, 0.001464f, 0.001848f, 0.002150f, 0.002514f, 0.002651f, 0.003391f, 0.003666f, 0.004368f, 0.004677f, + 0.005219f, 0.005882f, 0.006531f, 0.007019f, 0.007675f, 0.008530f, 0.009224f, 0.010269f, 0.011017f, 0.012146f, 0.013321f, 0.014626f, + 0.016098f, 0.017639f, 0.019440f, 0.021317f, 0.023773f, 0.026123f, 0.029144f, 0.032410f, 0.036072f, 0.040314f, 0.045013f, 0.051086f, + 0.057587f, 0.065308f, 0.074402f, 0.084961f, 0.097107f, 0.111267f, 0.127930f, 0.147217f, 0.169556f, 0.195312f, 0.224365f, 0.257568f, + 0.294189f, 0.333496f, 0.375977f, 0.420166f, 0.467041f, 0.514160f, 0.561035f, 0.607422f, 0.652344f, 0.695312f, 0.888672f, 0.896484f, + 0.897461f, 0.897461f, 0.897949f, 0.897949f, 0.000159f, 0.000537f, 0.000830f, 0.001206f, 0.001578f, 0.001760f, 0.002050f, 0.002504f, + 0.002951f, 0.003397f, 0.003674f, 0.004238f, 0.004520f, 0.005245f, 0.005692f, 0.006138f, 0.006748f, 0.007240f, 0.008087f, 0.008728f, + 0.009636f, 0.010437f, 0.011543f, 0.012611f, 0.013763f, 0.015266f, 0.016617f, 0.018433f, 0.020248f, 0.022354f, 0.024887f, 0.027390f, + 0.030716f, 0.034454f, 0.038422f, 0.043365f, 0.048950f, 0.055511f, 0.062988f, 0.072021f, 0.082336f, 0.094727f, 0.109375f, 0.125977f, + 0.145874f, 0.169556f, 0.195679f, 0.226929f, 0.260986f, 0.299805f, 0.341309f, 0.385498f, 0.432129f, 0.480957f, 0.529297f, 0.579102f, + 0.627441f, 0.673828f, 0.881348f, 0.889160f, 0.890625f, 0.891113f, 0.891602f, 0.891113f, 0.000204f, 0.000566f, 0.000741f, 0.001033f, + 0.001378f, 0.001599f, 0.001961f, 0.002354f, 0.002609f, 0.002974f, 0.003300f, 0.003609f, 0.004101f, 0.004463f, 0.004906f, 0.005337f, + 0.006020f, 0.006290f, 0.007023f, 0.007656f, 0.008301f, 0.009140f, 0.009918f, 0.010933f, 0.011940f, 0.013107f, 0.014252f, 0.015656f, + 0.017136f, 0.019058f, 0.021057f, 0.023209f, 0.025940f, 0.029190f, 0.032715f, 0.036591f, 0.041138f, 0.046661f, 0.053253f, 0.060944f, + 0.069702f, 0.080444f, 0.092651f, 0.107788f, 0.124695f, 0.145630f, 0.169189f, 0.197632f, 0.229736f, 0.266113f, 0.306396f, 0.350586f, + 0.397217f, 0.447021f, 0.497803f, 0.549805f, 0.600586f, 0.650391f, 0.872559f, 0.881836f, 0.882812f, 0.883301f, 0.884277f, 0.884277f, + 0.000240f, 0.000349f, 0.000795f, 0.000892f, 0.001151f, 0.001377f, 0.001773f, 0.001984f, 0.002415f, 0.002602f, 0.002932f, 0.003168f, + 0.003483f, 0.003906f, 0.004257f, 0.004681f, 0.005173f, 0.005596f, 0.006119f, 0.006550f, 0.007126f, 0.007759f, 0.008522f, 0.009270f, + 0.010086f, 0.011108f, 0.012138f, 0.013199f, 0.014549f, 0.015884f, 0.017776f, 0.019623f, 0.022003f, 0.024384f, 0.027237f, 0.030624f, + 0.034515f, 0.039215f, 0.044342f, 0.050873f, 0.058411f, 0.067017f, 0.078003f, 0.090332f, 0.105530f, 0.123718f, 0.144775f, 0.170410f, + 0.200195f, 0.234131f, 0.272461f, 0.315674f, 0.362305f, 0.412354f, 0.465332f, 0.518555f, 0.572754f, 0.626465f, 0.863770f, 0.873047f, + 0.875488f, 0.875488f, 0.875977f, 0.875977f, 0.000102f, 0.000298f, 0.000604f, 0.000950f, 0.001089f, 0.001472f, 0.001760f, 0.001823f, + 0.001903f, 0.002325f, 0.002611f, 0.002775f, 0.003185f, 0.003405f, 0.003674f, 0.004005f, 0.004406f, 0.004814f, 0.005203f, 0.005665f, + 0.006062f, 0.006702f, 0.007317f, 0.007881f, 0.008560f, 0.009239f, 0.010193f, 0.010994f, 0.012161f, 0.013588f, 0.015068f, 0.016479f, + 0.018250f, 0.020386f, 0.022781f, 0.025665f, 0.028809f, 0.032501f, 0.037048f, 0.042297f, 0.048553f, 0.055908f, 0.065491f, 0.075378f, + 0.088501f, 0.104248f, 0.122742f, 0.145874f, 0.171997f, 0.203247f, 0.239990f, 0.281250f, 0.326904f, 0.376953f, 0.430176f, 0.486328f, + 0.542480f, 0.600586f, 0.855469f, 0.864746f, 0.866211f, 0.867188f, 0.867188f, 0.867188f, 0.000000f, 0.000357f, 0.000576f, 0.000692f, + 0.001013f, 0.001069f, 0.001383f, 0.001702f, 0.001789f, 0.002102f, 0.002182f, 0.002377f, 0.002686f, 0.002985f, 0.003347f, 0.003359f, + 0.003782f, 0.004036f, 0.004436f, 0.004749f, 0.005169f, 0.005672f, 0.006145f, 0.006649f, 0.007187f, 0.007828f, 0.008644f, 0.009529f, + 0.010269f, 0.011200f, 0.012337f, 0.013596f, 0.015038f, 0.017044f, 0.018784f, 0.021011f, 0.023727f, 0.026871f, 0.030457f, 0.034637f, + 0.039978f, 0.046478f, 0.053436f, 0.062622f, 0.073730f, 0.086792f, 0.102661f, 0.122437f, 0.146240f, 0.174561f, 0.208252f, 0.247437f, + 0.291748f, 0.341064f, 0.395020f, 0.451904f, 0.511230f, 0.571777f, 0.844238f, 0.854980f, 0.857422f, 0.858887f, 0.857910f, 0.857910f, + 0.000101f, 0.000326f, 0.000535f, 0.000683f, 0.000848f, 0.001161f, 0.001184f, 0.001284f, 0.001576f, 0.001701f, 0.001839f, 0.002167f, + 0.002321f, 0.002584f, 0.002645f, 0.002941f, 0.003141f, 0.003538f, 0.003817f, 0.004112f, 0.004395f, 0.004646f, 0.005165f, 0.005531f, + 0.006096f, 0.006496f, 0.007217f, 0.007767f, 0.008629f, 0.009163f, 0.010239f, 0.011276f, 0.012611f, 0.013779f, 0.015213f, 0.017120f, + 0.019379f, 0.021606f, 0.024994f, 0.028351f, 0.032379f, 0.037201f, 0.043640f, 0.050903f, 0.060120f, 0.071045f, 0.084900f, 0.101868f, + 0.122559f, 0.147827f, 0.178223f, 0.214722f, 0.257080f, 0.305664f, 0.358887f, 0.416992f, 0.478027f, 0.542969f, 0.834473f, 0.845215f, + 0.847656f, 0.847656f, 0.847656f, 0.848633f, 0.000092f, 0.000316f, 0.000410f, 0.000556f, 0.000808f, 0.000918f, 0.001094f, 0.001287f, + 0.001309f, 0.001411f, 0.001671f, 0.001780f, 0.001909f, 0.002092f, 0.002274f, 0.002523f, 0.002733f, 0.002974f, 0.003101f, 0.003401f, + 0.003677f, 0.003956f, 0.004311f, 0.004551f, 0.004940f, 0.005444f, 0.005768f, 0.006451f, 0.006977f, 0.007568f, 0.008270f, 0.009201f, + 0.010170f, 0.011230f, 0.012566f, 0.013939f, 0.015503f, 0.017761f, 0.020111f, 0.022873f, 0.025940f, 0.029938f, 0.035217f, 0.040985f, + 0.048431f, 0.057770f, 0.069092f, 0.083618f, 0.100891f, 0.123047f, 0.150146f, 0.183838f, 0.223633f, 0.269531f, 0.322510f, 0.381348f, + 0.444824f, 0.511719f, 0.823730f, 0.834473f, 0.835938f, 0.836914f, 0.836914f, 0.837402f, 0.000240f, 0.000273f, 0.000326f, 0.000564f, + 0.000682f, 0.000807f, 0.000854f, 0.000949f, 0.001139f, 0.001238f, 0.001404f, 0.001548f, 0.001637f, 0.001840f, 0.001893f, 0.002077f, + 0.002321f, 0.002434f, 0.002642f, 0.002821f, 0.003044f, 0.003271f, 0.003649f, 0.003763f, 0.004208f, 0.004448f, 0.004986f, 0.005169f, + 0.005657f, 0.006279f, 0.006680f, 0.007442f, 0.008194f, 0.008881f, 0.009895f, 0.010918f, 0.012138f, 0.013924f, 0.015915f, 0.018112f, + 0.020645f, 0.023743f, 0.027817f, 0.032745f, 0.038361f, 0.045990f, 0.055481f, 0.066895f, 0.082031f, 0.100769f, 0.124573f, 0.154541f, + 0.190796f, 0.235107f, 0.286133f, 0.344238f, 0.408936f, 0.478271f, 0.810547f, 0.822266f, 0.824707f, 0.825195f, 0.825684f, 0.825684f, + 0.000115f, 0.000222f, 0.000252f, 0.000524f, 0.000574f, 0.000673f, 0.000869f, 0.000928f, 0.000963f, 0.001022f, 0.001246f, 0.001292f, + 0.001404f, 0.001477f, 0.001652f, 0.001811f, 0.001822f, 0.002058f, 0.002237f, 0.002371f, 0.002588f, 0.002645f, 0.003019f, 0.003080f, + 0.003506f, 0.003689f, 0.003904f, 0.004383f, 0.004707f, 0.005020f, 0.005386f, 0.006023f, 0.006451f, 0.007038f, 0.007809f, 0.008911f, + 0.009949f, 0.011200f, 0.012222f, 0.014137f, 0.016068f, 0.018692f, 0.021683f, 0.025314f, 0.029861f, 0.035889f, 0.043335f, 0.052582f, + 0.065186f, 0.080627f, 0.101501f, 0.127441f, 0.159912f, 0.200806f, 0.250000f, 0.307129f, 0.371582f, 0.444580f, 0.798340f, 0.809570f, + 0.811523f, 0.812988f, 0.812988f, 0.812988f, 0.000000f, 0.000211f, 0.000204f, 0.000474f, 0.000555f, 0.000583f, 0.000600f, 0.000593f, + 0.000812f, 0.000865f, 0.000941f, 0.001013f, 0.001162f, 0.001348f, 0.001418f, 0.001465f, 0.001616f, 0.001722f, 0.001856f, 0.001888f, + 0.002048f, 0.002321f, 0.002396f, 0.002632f, 0.002821f, 0.002974f, 0.003265f, 0.003477f, 0.003632f, 0.004051f, 0.004299f, 0.004700f, + 0.005238f, 0.005592f, 0.006199f, 0.006756f, 0.007614f, 0.008324f, 0.009727f, 0.010811f, 0.012337f, 0.014168f, 0.016434f, 0.019257f, + 0.022858f, 0.027451f, 0.033295f, 0.040619f, 0.050690f, 0.063416f, 0.080261f, 0.102295f, 0.131104f, 0.168335f, 0.214355f, 0.270508f, + 0.334717f, 0.408936f, 0.783691f, 0.795898f, 0.798340f, 0.799316f, 0.800293f, 0.800293f, 0.000174f, 0.000090f, 0.000281f, 0.000397f, + 0.000401f, 0.000450f, 0.000488f, 0.000640f, 0.000674f, 0.000713f, 0.000753f, 0.000845f, 0.000872f, 0.001020f, 0.001115f, 0.001264f, + 0.001327f, 0.001373f, 0.001520f, 0.001616f, 0.001767f, 0.001875f, 0.001968f, 0.002090f, 0.002232f, 0.002333f, 0.002472f, 0.002802f, + 0.002926f, 0.003189f, 0.003569f, 0.003752f, 0.004009f, 0.004513f, 0.004860f, 0.005375f, 0.005997f, 0.006561f, 0.007378f, 0.008347f, + 0.009384f, 0.010612f, 0.012466f, 0.014526f, 0.017075f, 0.020447f, 0.024887f, 0.030533f, 0.038300f, 0.048584f, 0.062042f, 0.080383f, + 0.104736f, 0.137329f, 0.180176f, 0.232544f, 0.296875f, 0.371338f, 0.769043f, 0.781250f, 0.784180f, 0.784668f, 0.786133f, 0.786133f, + 0.000025f, 0.000135f, 0.000154f, 0.000260f, 0.000353f, 0.000364f, 0.000380f, 0.000520f, 0.000548f, 0.000587f, 0.000712f, 0.000735f, + 0.000772f, 0.000822f, 0.000886f, 0.001004f, 0.000946f, 0.001115f, 0.001177f, 0.001266f, 0.001454f, 0.001527f, 0.001575f, 0.001680f, + 0.001883f, 0.001961f, 0.002043f, 0.002193f, 0.002281f, 0.002520f, 0.002712f, 0.003021f, 0.003147f, 0.003561f, 0.003786f, 0.004116f, + 0.004570f, 0.005058f, 0.005634f, 0.006165f, 0.007095f, 0.008049f, 0.009201f, 0.010674f, 0.012550f, 0.014854f, 0.018051f, 0.022385f, + 0.027908f, 0.035522f, 0.046295f, 0.061035f, 0.081238f, 0.109131f, 0.146729f, 0.197021f, 0.258301f, 0.333008f, 0.752441f, 0.766113f, + 0.768555f, 0.769531f, 0.770020f, 0.769531f, 0.000000f, 0.000121f, 0.000209f, 0.000291f, 0.000337f, 0.000307f, 0.000324f, 0.000415f, + 0.000426f, 0.000453f, 0.000491f, 0.000573f, 0.000644f, 0.000650f, 0.000781f, 0.000746f, 0.000830f, 0.000803f, 0.000997f, 0.001017f, + 0.001020f, 0.001158f, 0.001241f, 0.001317f, 0.001375f, 0.001432f, 0.001524f, 0.001656f, 0.001858f, 0.001955f, 0.002050f, 0.002274f, + 0.002460f, 0.002724f, 0.002831f, 0.003050f, 0.003441f, 0.003790f, 0.004162f, 0.004623f, 0.005219f, 0.005951f, 0.006721f, 0.007729f, + 0.008926f, 0.010620f, 0.013000f, 0.015686f, 0.019852f, 0.025436f, 0.033295f, 0.044617f, 0.060608f, 0.083313f, 0.116211f, 0.161499f, + 0.220093f, 0.293945f, 0.734863f, 0.749512f, 0.752441f, 0.752930f, 0.753906f, 0.753906f, 0.000000f, 0.000121f, 0.000118f, 0.000246f, + 0.000233f, 0.000252f, 0.000338f, 0.000282f, 0.000353f, 0.000355f, 0.000448f, 0.000435f, 0.000464f, 0.000530f, 0.000578f, 0.000649f, + 0.000677f, 0.000710f, 0.000749f, 0.000792f, 0.000881f, 0.000903f, 0.000967f, 0.001049f, 0.001041f, 0.001100f, 0.001176f, 0.001254f, + 0.001402f, 0.001451f, 0.001697f, 0.001674f, 0.001804f, 0.001914f, 0.002195f, 0.002451f, 0.002474f, 0.002758f, 0.003029f, 0.003483f, + 0.003824f, 0.004272f, 0.004833f, 0.005573f, 0.006477f, 0.007629f, 0.009041f, 0.010918f, 0.013573f, 0.017319f, 0.022842f, 0.031036f, + 0.043030f, 0.061096f, 0.088440f, 0.127563f, 0.182861f, 0.254395f, 0.717285f, 0.731934f, 0.734863f, 0.735352f, 0.735840f, 0.736328f, + 0.000000f, 0.000000f, 0.000117f, 0.000163f, 0.000109f, 0.000208f, 0.000212f, 0.000208f, 0.000270f, 0.000356f, 0.000324f, 0.000377f, + 0.000391f, 0.000420f, 0.000449f, 0.000440f, 0.000484f, 0.000504f, 0.000534f, 0.000561f, 0.000639f, 0.000667f, 0.000715f, 0.000722f, + 0.000799f, 0.000845f, 0.000939f, 0.000945f, 0.001053f, 0.001149f, 0.001252f, 0.001310f, 0.001392f, 0.001507f, 0.001526f, 0.001710f, + 0.001773f, 0.002111f, 0.002300f, 0.002443f, 0.002661f, 0.002996f, 0.003376f, 0.003880f, 0.004482f, 0.005150f, 0.006115f, 0.007401f, + 0.009132f, 0.011696f, 0.015076f, 0.020416f, 0.029236f, 0.042389f, 0.063782f, 0.096802f, 0.146362f, 0.215576f, 0.698242f, 0.712891f, + 0.715332f, 0.716797f, 0.717285f, 0.717285f, 0.000000f, 0.000118f, 0.000115f, 0.000133f, 0.000144f, 0.000147f, 0.000162f, 0.000150f, + 0.000194f, 0.000215f, 0.000228f, 0.000299f, 0.000271f, 0.000313f, 0.000328f, 0.000358f, 0.000378f, 0.000360f, 0.000407f, 0.000438f, + 0.000441f, 0.000488f, 0.000515f, 0.000544f, 0.000576f, 0.000617f, 0.000659f, 0.000715f, 0.000741f, 0.000773f, 0.000850f, 0.000921f, + 0.000979f, 0.001066f, 0.001128f, 0.001292f, 0.001279f, 0.001400f, 0.001572f, 0.001668f, 0.001869f, 0.002029f, 0.002295f, 0.002607f, + 0.002985f, 0.003464f, 0.004066f, 0.004913f, 0.006023f, 0.007519f, 0.009827f, 0.013016f, 0.018524f, 0.027481f, 0.042847f, 0.068970f, + 0.111938f, 0.176392f, 0.675781f, 0.692871f, 0.695801f, 0.696777f, 0.698242f, 0.697754f, 0.000000f, 0.000000f, 0.000111f, 0.000108f, + 0.000104f, 0.000102f, 0.000118f, 0.000120f, 0.000134f, 0.000128f, 0.000188f, 0.000154f, 0.000197f, 0.000188f, 0.000245f, 0.000256f, + 0.000233f, 0.000266f, 0.000345f, 0.000281f, 0.000355f, 0.000322f, 0.000392f, 0.000358f, 0.000437f, 0.000425f, 0.000458f, 0.000477f, + 0.000564f, 0.000636f, 0.000578f, 0.000607f, 0.000668f, 0.000719f, 0.000769f, 0.000832f, 0.000880f, 0.000953f, 0.001060f, 0.001116f, + 0.001226f, 0.001363f, 0.001486f, 0.001760f, 0.001944f, 0.002216f, 0.002605f, 0.003107f, 0.003778f, 0.004715f, 0.005989f, 0.007942f, + 0.011292f, 0.016632f, 0.026550f, 0.045532f, 0.079956f, 0.138550f, 0.655762f, 0.671875f, 0.674805f, 0.675293f, 0.675781f, 0.678223f, + 0.000000f, 0.000112f, 0.000105f, 0.000102f, 0.000098f, 0.000095f, 0.000093f, 0.000088f, 0.000089f, 0.000085f, 0.000095f, 0.000126f, + 0.000109f, 0.000154f, 0.000153f, 0.000162f, 0.000176f, 0.000190f, 0.000202f, 0.000204f, 0.000212f, 0.000214f, 0.000266f, 0.000239f, + 0.000279f, 0.000293f, 0.000329f, 0.000329f, 0.000339f, 0.000365f, 0.000437f, 0.000424f, 0.000429f, 0.000474f, 0.000525f, 0.000596f, + 0.000572f, 0.000612f, 0.000666f, 0.000723f, 0.000791f, 0.000850f, 0.000977f, 0.001066f, 0.001225f, 0.001351f, 0.001555f, 0.001837f, + 0.002279f, 0.002760f, 0.003445f, 0.004612f, 0.006386f, 0.009438f, 0.015221f, 0.027008f, 0.052551f, 0.102966f, 0.633789f, 0.649414f, + 0.652832f, 0.653809f, 0.655273f, 0.655273f, 0.000000f, 0.000105f, 0.000099f, 0.000094f, 0.000090f, 0.000087f, 0.000084f, 0.000082f, + 0.000079f, 0.000075f, 0.000071f, 0.000068f, 0.000064f, 0.000072f, 0.000096f, 0.000105f, 0.000112f, 0.000088f, 0.000123f, 0.000129f, + 0.000132f, 0.000140f, 0.000147f, 0.000170f, 0.000188f, 0.000192f, 0.000171f, 0.000210f, 0.000217f, 0.000223f, 0.000237f, 0.000251f, + 0.000258f, 0.000294f, 0.000298f, 0.000316f, 0.000350f, 0.000382f, 0.000400f, 0.000437f, 0.000479f, 0.000514f, 0.000576f, 0.000620f, + 0.000688f, 0.000782f, 0.000916f, 0.001026f, 0.001219f, 0.001502f, 0.001892f, 0.002424f, 0.003359f, 0.004974f, 0.008118f, 0.014343f, + 0.030075f, 0.070068f, 0.610352f, 0.626953f, 0.629883f, 0.631348f, 0.632324f, 0.632324f, 0.000110f, 0.000094f, 0.000087f, 0.000081f, + 0.000077f, 0.000075f, 0.000072f, 0.000069f, 0.000067f, 0.000066f, 0.000064f, 0.000062f, 0.000058f, 0.000056f, 0.000053f, 0.000051f, + 0.000054f, 0.000047f, 0.000057f, 0.000055f, 0.000075f, 0.000078f, 0.000086f, 0.000093f, 0.000093f, 0.000102f, 0.000112f, 0.000113f, + 0.000130f, 0.000128f, 0.000142f, 0.000145f, 0.000156f, 0.000153f, 0.000180f, 0.000178f, 0.000183f, 0.000223f, 0.000230f, 0.000240f, + 0.000265f, 0.000276f, 0.000300f, 0.000332f, 0.000357f, 0.000411f, 0.000449f, 0.000540f, 0.000615f, 0.000741f, 0.000916f, 0.001144f, + 0.001566f, 0.002310f, 0.003731f, 0.006905f, 0.014793f, 0.041779f, 0.585938f, 0.603027f, 0.605957f, 0.608398f, 0.608398f, 0.609375f, + 0.000090f, 0.000071f, 0.000066f, 0.000062f, 0.000058f, 0.000056f, 0.000053f, 0.000053f, 0.000051f, 0.000051f, 0.000049f, 0.000048f, + 0.000048f, 0.000047f, 0.000045f, 0.000043f, 0.000042f, 0.000040f, 0.000038f, 0.000036f, 0.000036f, 0.000033f, 0.000034f, 0.000040f, + 0.000040f, 0.000040f, 0.000048f, 0.000053f, 0.000060f, 0.000064f, 0.000067f, 0.000070f, 0.000075f, 0.000081f, 0.000085f, 0.000090f, + 0.000091f, 0.000103f, 0.000106f, 0.000120f, 0.000134f, 0.000138f, 0.000142f, 0.000156f, 0.000174f, 0.000180f, 0.000212f, 0.000239f, + 0.000253f, 0.000310f, 0.000377f, 0.000479f, 0.000627f, 0.000875f, 0.001396f, 0.002623f, 0.006184f, 0.019897f, 0.560547f, 0.578125f, + 0.581543f, 0.583008f, 0.583984f, 0.583984f, 0.000038f, 0.000035f, 0.000031f, 0.000031f, 0.000030f, 0.000031f, 0.000031f, 0.000030f, + 0.000030f, 0.000028f, 0.000029f, 0.000030f, 0.000029f, 0.000028f, 0.000029f, 0.000029f, 0.000029f, 0.000029f, 0.000029f, 0.000028f, + 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000019f, 0.000021f, 0.000019f, 0.000022f, + 0.000023f, 0.000027f, 0.000031f, 0.000035f, 0.000037f, 0.000039f, 0.000039f, 0.000043f, 0.000049f, 0.000052f, 0.000056f, 0.000050f, + 0.000068f, 0.000062f, 0.000070f, 0.000087f, 0.000094f, 0.000107f, 0.000122f, 0.000140f, 0.000191f, 0.000247f, 0.000388f, 0.000710f, + 0.001781f, 0.007076f, 0.535156f, 0.553223f, 0.556152f, 0.558105f, 0.559082f, 0.559082f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000003f, 0.000005f, 0.000006f, 0.000007f, 0.000007f, 0.000009f, + 0.000009f, 0.000009f, 0.000010f, 0.000010f, 0.000011f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000013f, 0.000013f, 0.000013f, + 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000009f, + 0.000009f, 0.000010f, 0.000011f, 0.000015f, 0.000017f, 0.000016f, 0.000018f, 0.000021f, 0.000020f, 0.000024f, 0.000024f, 0.000032f, + 0.000035f, 0.000045f, 0.000065f, 0.000105f, 0.000246f, 0.001313f, 0.508789f, 0.527344f, 0.530762f, 0.531738f, 0.532715f, 0.533691f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000002f, 0.000002f, 0.000002f, + 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000005f, 0.000018f, 0.481934f, 0.500977f, + 0.504883f, 0.505859f, 0.507324f, 0.507812f, + }, + { + 0.053833f, 0.152832f, 0.239014f, 0.313477f, 0.377686f, 0.433838f, 0.481689f, 0.524414f, 0.562988f, 0.596680f, 0.626953f, 0.654785f, + 0.678711f, 0.700684f, 0.720703f, 0.739746f, 0.755859f, 0.771973f, 0.787109f, 0.798828f, 0.812012f, 0.823730f, 0.833984f, 0.844238f, + 0.853027f, 0.862793f, 0.870605f, 0.878418f, 0.885254f, 0.892090f, 0.898926f, 0.904297f, 0.910645f, 0.916504f, 0.921875f, 0.926270f, + 0.931641f, 0.936035f, 0.939941f, 0.944336f, 0.948242f, 0.952148f, 0.955566f, 0.959961f, 0.962402f, 0.966309f, 0.969238f, 0.972168f, + 0.975098f, 0.978027f, 0.980957f, 0.983398f, 0.985840f, 0.988281f, 0.990723f, 0.992676f, 0.995117f, 0.996582f, 0.998047f, 0.995117f, + 0.993164f, 0.990723f, 0.988770f, 0.986816f, 0.036804f, 0.109497f, 0.178589f, 0.244751f, 0.305908f, 0.361084f, 0.411621f, 0.457275f, + 0.498535f, 0.536133f, 0.569824f, 0.601562f, 0.629883f, 0.655273f, 0.679688f, 0.700195f, 0.720215f, 0.737793f, 0.755859f, 0.770508f, + 0.785645f, 0.798340f, 0.811035f, 0.822754f, 0.833008f, 0.843750f, 0.852539f, 0.861328f, 0.869629f, 0.877441f, 0.885742f, 0.892578f, + 0.898926f, 0.905273f, 0.911133f, 0.916504f, 0.921875f, 0.926758f, 0.931641f, 0.936523f, 0.940430f, 0.945312f, 0.949219f, 0.953613f, + 0.956543f, 0.960449f, 0.963867f, 0.967285f, 0.970703f, 0.973633f, 0.976562f, 0.979004f, 0.981934f, 0.984375f, 0.986816f, 0.989746f, + 0.992188f, 0.994141f, 0.996582f, 0.994141f, 0.992188f, 0.990234f, 0.988281f, 0.986328f, 0.025787f, 0.080383f, 0.136230f, 0.191650f, + 0.245239f, 0.297119f, 0.345947f, 0.392822f, 0.436035f, 0.476807f, 0.513184f, 0.547363f, 0.578125f, 0.607910f, 0.634766f, 0.658203f, + 0.681152f, 0.702637f, 0.721191f, 0.738770f, 0.755371f, 0.770508f, 0.784668f, 0.798828f, 0.810547f, 0.821777f, 0.833984f, 0.843262f, + 0.852539f, 0.861816f, 0.869629f, 0.877930f, 0.885254f, 0.893555f, 0.898926f, 0.906250f, 0.911621f, 0.917969f, 0.923340f, 0.928223f, + 0.933105f, 0.937500f, 0.941406f, 0.946289f, 0.950195f, 0.954102f, 0.958496f, 0.961914f, 0.965820f, 0.968750f, 0.971680f, 0.975098f, + 0.978027f, 0.980469f, 0.983887f, 0.985840f, 0.988770f, 0.991211f, 0.995117f, 0.993164f, 0.991211f, 0.989258f, 0.987305f, 0.985352f, + 0.019455f, 0.060944f, 0.104553f, 0.150513f, 0.196411f, 0.243164f, 0.289062f, 0.333740f, 0.376709f, 0.417725f, 0.454346f, 0.491211f, + 0.524414f, 0.556641f, 0.585938f, 0.613770f, 0.639160f, 0.662598f, 0.682617f, 0.703613f, 0.723633f, 0.740723f, 0.756836f, 0.771973f, + 0.787109f, 0.798828f, 0.812012f, 0.823242f, 0.833984f, 0.844238f, 0.853516f, 0.863281f, 0.871094f, 0.879395f, 0.886719f, 0.893555f, + 0.899902f, 0.907227f, 0.913086f, 0.918945f, 0.924805f, 0.928711f, 0.934082f, 0.938965f, 0.943848f, 0.947754f, 0.952637f, 0.955566f, + 0.959961f, 0.963867f, 0.966797f, 0.970215f, 0.973633f, 0.977051f, 0.979004f, 0.982422f, 0.985840f, 0.987793f, 0.993652f, 0.991699f, + 0.989746f, 0.988281f, 0.986328f, 0.984375f, 0.015221f, 0.047363f, 0.082092f, 0.119202f, 0.159058f, 0.199219f, 0.239380f, 0.280762f, + 0.321533f, 0.362061f, 0.400146f, 0.436768f, 0.472900f, 0.504883f, 0.536621f, 0.566406f, 0.594238f, 0.621094f, 0.645508f, 0.667969f, + 0.688477f, 0.707520f, 0.726562f, 0.742676f, 0.759277f, 0.773926f, 0.787598f, 0.800781f, 0.812988f, 0.825195f, 0.835938f, 0.846191f, + 0.856445f, 0.865234f, 0.872559f, 0.880859f, 0.888672f, 0.895020f, 0.902832f, 0.908203f, 0.914551f, 0.919922f, 0.926758f, 0.931152f, + 0.937012f, 0.941406f, 0.945312f, 0.949707f, 0.954102f, 0.958496f, 0.962402f, 0.965820f, 0.969238f, 0.972168f, 0.976074f, 0.978516f, + 0.981934f, 0.984863f, 0.992188f, 0.990723f, 0.988770f, 0.987305f, 0.985352f, 0.983887f, 0.011658f, 0.037170f, 0.065430f, 0.096008f, + 0.128784f, 0.162842f, 0.198975f, 0.235596f, 0.273926f, 0.310791f, 0.348145f, 0.385010f, 0.420410f, 0.454834f, 0.488037f, 0.519043f, + 0.548828f, 0.577148f, 0.603516f, 0.627441f, 0.650879f, 0.672363f, 0.693848f, 0.712402f, 0.729980f, 0.748535f, 0.762207f, 0.778809f, + 0.791504f, 0.804199f, 0.815918f, 0.827637f, 0.838867f, 0.848145f, 0.857910f, 0.866211f, 0.875977f, 0.883301f, 0.891602f, 0.898438f, + 0.905273f, 0.911133f, 0.917480f, 0.923340f, 0.928711f, 0.933594f, 0.938477f, 0.942871f, 0.948242f, 0.952637f, 0.956543f, 0.960449f, + 0.964355f, 0.968262f, 0.971191f, 0.974609f, 0.978027f, 0.980957f, 0.990723f, 0.989258f, 0.987793f, 0.985840f, 0.984375f, 0.983398f, + 0.009758f, 0.030121f, 0.052490f, 0.077576f, 0.104309f, 0.134277f, 0.164917f, 0.197510f, 0.231812f, 0.266113f, 0.301025f, 0.336426f, + 0.372070f, 0.405762f, 0.438721f, 0.471436f, 0.502441f, 0.531738f, 0.560059f, 0.587402f, 0.612793f, 0.634766f, 0.658691f, 0.679199f, + 0.699219f, 0.718262f, 0.735352f, 0.751953f, 0.767090f, 0.780762f, 0.794922f, 0.808105f, 0.820801f, 0.831055f, 0.842285f, 0.851562f, + 0.861328f, 0.870117f, 0.878906f, 0.886719f, 0.893555f, 0.900879f, 0.907715f, 0.913574f, 0.919434f, 0.926270f, 0.932129f, 0.936523f, + 0.941895f, 0.945801f, 0.951172f, 0.955078f, 0.959473f, 0.963867f, 0.966797f, 0.970703f, 0.974121f, 0.977539f, 0.989746f, 0.988281f, + 0.986328f, 0.984863f, 0.983398f, 0.982422f, 0.007744f, 0.024567f, 0.043365f, 0.063782f, 0.086487f, 0.111389f, 0.137451f, 0.166260f, + 0.195435f, 0.226929f, 0.259033f, 0.291748f, 0.324951f, 0.358398f, 0.391113f, 0.424316f, 0.456299f, 0.486328f, 0.516113f, 0.543945f, + 0.571289f, 0.597656f, 0.621094f, 0.644531f, 0.666504f, 0.686523f, 0.705078f, 0.724121f, 0.741211f, 0.757324f, 0.773438f, 0.786621f, + 0.801270f, 0.812988f, 0.823730f, 0.835938f, 0.846191f, 0.855957f, 0.865723f, 0.873047f, 0.882324f, 0.889648f, 0.897949f, 0.905762f, + 0.911133f, 0.917969f, 0.923828f, 0.929199f, 0.934082f, 0.940430f, 0.944824f, 0.949707f, 0.954102f, 0.958008f, 0.962891f, 0.966309f, + 0.970215f, 0.974121f, 0.987793f, 0.986816f, 0.985352f, 0.983887f, 0.981934f, 0.980469f, 0.006672f, 0.020828f, 0.035950f, 0.053345f, + 0.071594f, 0.092834f, 0.114624f, 0.139282f, 0.165649f, 0.192627f, 0.222290f, 0.252197f, 0.283203f, 0.314941f, 0.346680f, 0.377930f, + 0.409668f, 0.441650f, 0.471680f, 0.500977f, 0.529297f, 0.557129f, 0.583008f, 0.607422f, 0.630859f, 0.654297f, 0.674805f, 0.694824f, + 0.713867f, 0.731445f, 0.748535f, 0.763672f, 0.778320f, 0.791992f, 0.805664f, 0.817871f, 0.829590f, 0.840332f, 0.850098f, 0.860352f, + 0.869141f, 0.878906f, 0.886719f, 0.894043f, 0.901855f, 0.909180f, 0.915527f, 0.920898f, 0.927246f, 0.933105f, 0.938477f, 0.943848f, + 0.948730f, 0.953125f, 0.957520f, 0.961914f, 0.965820f, 0.970215f, 0.985840f, 0.985352f, 0.983887f, 0.981934f, 0.980957f, 0.979492f, + 0.005592f, 0.017181f, 0.030457f, 0.044739f, 0.060638f, 0.077454f, 0.097046f, 0.117981f, 0.140625f, 0.164673f, 0.190552f, 0.217896f, + 0.246582f, 0.275635f, 0.305176f, 0.336426f, 0.366943f, 0.397949f, 0.428711f, 0.457764f, 0.487061f, 0.515137f, 0.542480f, 0.568848f, + 0.593750f, 0.619141f, 0.641602f, 0.662598f, 0.683594f, 0.703613f, 0.721191f, 0.738281f, 0.755859f, 0.770996f, 0.784180f, 0.799316f, + 0.811035f, 0.823730f, 0.833984f, 0.845703f, 0.855957f, 0.865234f, 0.875000f, 0.883301f, 0.891602f, 0.898926f, 0.906738f, 0.912598f, + 0.919922f, 0.926270f, 0.931152f, 0.937988f, 0.942871f, 0.948242f, 0.952148f, 0.957520f, 0.961914f, 0.966309f, 0.984375f, 0.983398f, + 0.982422f, 0.981445f, 0.979492f, 0.978027f, 0.004829f, 0.014816f, 0.025711f, 0.037964f, 0.051300f, 0.065796f, 0.082458f, 0.100037f, + 0.120178f, 0.141357f, 0.163330f, 0.187622f, 0.213013f, 0.240601f, 0.268311f, 0.296387f, 0.325928f, 0.356445f, 0.385742f, 0.415771f, + 0.445557f, 0.474121f, 0.501465f, 0.530762f, 0.556152f, 0.581543f, 0.606445f, 0.630859f, 0.651855f, 0.672852f, 0.693359f, 0.712402f, + 0.730469f, 0.746582f, 0.762695f, 0.777832f, 0.791992f, 0.806152f, 0.818359f, 0.830566f, 0.840820f, 0.852051f, 0.862305f, 0.871094f, + 0.880371f, 0.888184f, 0.896484f, 0.904297f, 0.910645f, 0.917969f, 0.924316f, 0.931152f, 0.936035f, 0.942383f, 0.947266f, 0.951660f, + 0.957031f, 0.960938f, 0.982422f, 0.982422f, 0.981445f, 0.979492f, 0.978516f, 0.977051f, 0.004040f, 0.012436f, 0.022064f, 0.032440f, + 0.044006f, 0.056549f, 0.070068f, 0.085999f, 0.102539f, 0.120239f, 0.140625f, 0.161621f, 0.184448f, 0.208496f, 0.234253f, 0.260742f, + 0.288086f, 0.316406f, 0.345215f, 0.374512f, 0.404297f, 0.433350f, 0.462402f, 0.490234f, 0.518066f, 0.543945f, 0.570312f, 0.594727f, + 0.618652f, 0.642090f, 0.663086f, 0.683594f, 0.703613f, 0.721680f, 0.739258f, 0.755859f, 0.772461f, 0.786621f, 0.798828f, 0.812500f, + 0.825195f, 0.836914f, 0.848633f, 0.858887f, 0.869141f, 0.877441f, 0.886230f, 0.894531f, 0.902832f, 0.909668f, 0.916992f, 0.923340f, + 0.929688f, 0.935547f, 0.941406f, 0.947266f, 0.951660f, 0.957031f, 0.980469f, 0.980469f, 0.979492f, 0.978516f, 0.977051f, 0.976074f, + 0.003536f, 0.010872f, 0.018829f, 0.027893f, 0.037872f, 0.048492f, 0.060883f, 0.073425f, 0.088074f, 0.103638f, 0.120789f, 0.139038f, + 0.159912f, 0.181274f, 0.204102f, 0.227905f, 0.253906f, 0.280518f, 0.307861f, 0.335938f, 0.364746f, 0.393311f, 0.421631f, 0.451416f, + 0.479004f, 0.505859f, 0.533203f, 0.560059f, 0.584473f, 0.608398f, 0.631836f, 0.653320f, 0.674805f, 0.695801f, 0.714355f, 0.731934f, + 0.749512f, 0.765137f, 0.781250f, 0.794434f, 0.808594f, 0.821289f, 0.833496f, 0.844238f, 0.855469f, 0.866211f, 0.875000f, 0.883789f, + 0.892578f, 0.901855f, 0.908691f, 0.915527f, 0.922852f, 0.929199f, 0.935059f, 0.941406f, 0.947266f, 0.951172f, 0.978516f, 0.979004f, + 0.978027f, 0.977051f, 0.975586f, 0.974121f, 0.002989f, 0.009476f, 0.016785f, 0.024246f, 0.032745f, 0.041809f, 0.052246f, 0.063782f, + 0.076111f, 0.089722f, 0.104675f, 0.120605f, 0.138306f, 0.157959f, 0.178101f, 0.200073f, 0.223145f, 0.247192f, 0.273193f, 0.300293f, + 0.327148f, 0.354736f, 0.383545f, 0.411621f, 0.439941f, 0.468018f, 0.495605f, 0.522949f, 0.548828f, 0.574219f, 0.598145f, 0.622559f, + 0.645508f, 0.666016f, 0.687500f, 0.706543f, 0.725586f, 0.743164f, 0.759766f, 0.775391f, 0.791016f, 0.803711f, 0.817871f, 0.829590f, + 0.841797f, 0.852539f, 0.863281f, 0.873047f, 0.882812f, 0.891113f, 0.900391f, 0.906738f, 0.915039f, 0.922852f, 0.929688f, 0.936035f, + 0.941895f, 0.946777f, 0.976074f, 0.977051f, 0.976074f, 0.975586f, 0.974121f, 0.972656f, 0.002846f, 0.008568f, 0.014557f, 0.021484f, + 0.028442f, 0.036377f, 0.045074f, 0.055054f, 0.066101f, 0.077759f, 0.090759f, 0.104797f, 0.120483f, 0.136719f, 0.155029f, 0.175171f, + 0.196045f, 0.218262f, 0.241943f, 0.266357f, 0.292480f, 0.319336f, 0.345703f, 0.373535f, 0.402100f, 0.429932f, 0.457764f, 0.484863f, + 0.512207f, 0.539062f, 0.564941f, 0.589844f, 0.613281f, 0.636719f, 0.659180f, 0.680664f, 0.700684f, 0.718750f, 0.736816f, 0.754883f, + 0.770508f, 0.785645f, 0.799805f, 0.813965f, 0.826172f, 0.838867f, 0.850586f, 0.861328f, 0.871582f, 0.881836f, 0.890625f, 0.898926f, + 0.906738f, 0.915039f, 0.922363f, 0.928711f, 0.936035f, 0.941895f, 0.974609f, 0.975098f, 0.974609f, 0.973633f, 0.972656f, 0.971191f, + 0.002285f, 0.007290f, 0.012634f, 0.018280f, 0.024918f, 0.032074f, 0.039673f, 0.048157f, 0.057220f, 0.067810f, 0.078735f, 0.091248f, + 0.104370f, 0.119873f, 0.135742f, 0.152344f, 0.171631f, 0.191650f, 0.213501f, 0.236206f, 0.260010f, 0.285156f, 0.310547f, 0.338135f, + 0.364746f, 0.392578f, 0.420410f, 0.448242f, 0.476562f, 0.502441f, 0.529785f, 0.555664f, 0.581543f, 0.605469f, 0.629395f, 0.652344f, + 0.673340f, 0.693848f, 0.713867f, 0.732910f, 0.750000f, 0.767090f, 0.782715f, 0.797852f, 0.811035f, 0.825195f, 0.836914f, 0.848633f, + 0.860840f, 0.870605f, 0.880371f, 0.890137f, 0.898926f, 0.907227f, 0.915527f, 0.923340f, 0.929688f, 0.936523f, 0.972168f, 0.973145f, + 0.972656f, 0.972168f, 0.970703f, 0.969727f, 0.002064f, 0.006584f, 0.011154f, 0.016266f, 0.022263f, 0.028397f, 0.034973f, 0.042145f, + 0.050232f, 0.059235f, 0.069031f, 0.079346f, 0.091736f, 0.104553f, 0.118652f, 0.133789f, 0.150635f, 0.168457f, 0.188110f, 0.208984f, + 0.230225f, 0.253906f, 0.278076f, 0.303955f, 0.329346f, 0.356689f, 0.384033f, 0.411865f, 0.439941f, 0.467285f, 0.493896f, 0.520996f, + 0.547363f, 0.573730f, 0.597168f, 0.622559f, 0.645508f, 0.667969f, 0.688965f, 0.709473f, 0.728027f, 0.746094f, 0.762695f, 0.778809f, + 0.794922f, 0.809082f, 0.822754f, 0.834961f, 0.847168f, 0.858887f, 0.870117f, 0.880371f, 0.889648f, 0.898926f, 0.907227f, 0.915039f, + 0.923828f, 0.930176f, 0.970215f, 0.971680f, 0.970215f, 0.970215f, 0.968750f, 0.968262f, 0.001935f, 0.005634f, 0.010078f, 0.014389f, + 0.019669f, 0.024658f, 0.030716f, 0.037201f, 0.044098f, 0.051941f, 0.060333f, 0.070129f, 0.080383f, 0.091370f, 0.103638f, 0.116943f, + 0.131714f, 0.148193f, 0.165161f, 0.183838f, 0.203979f, 0.225220f, 0.247803f, 0.271240f, 0.296631f, 0.322510f, 0.349121f, 0.376221f, + 0.403076f, 0.431152f, 0.458984f, 0.485596f, 0.513672f, 0.540039f, 0.564941f, 0.590820f, 0.616211f, 0.638672f, 0.662109f, 0.683105f, + 0.704102f, 0.723633f, 0.741699f, 0.759766f, 0.776855f, 0.792480f, 0.807617f, 0.821777f, 0.833496f, 0.847168f, 0.858887f, 0.870117f, + 0.880859f, 0.889648f, 0.899414f, 0.908203f, 0.916992f, 0.924316f, 0.967285f, 0.968262f, 0.968750f, 0.968262f, 0.967285f, 0.966309f, + 0.001805f, 0.005119f, 0.009079f, 0.013023f, 0.017487f, 0.022278f, 0.027130f, 0.032684f, 0.038666f, 0.045959f, 0.052826f, 0.061401f, + 0.070801f, 0.080139f, 0.090698f, 0.102844f, 0.115845f, 0.130005f, 0.145264f, 0.162476f, 0.180176f, 0.199951f, 0.220459f, 0.242188f, + 0.265869f, 0.290283f, 0.315430f, 0.341309f, 0.368652f, 0.395752f, 0.423584f, 0.451416f, 0.479248f, 0.505859f, 0.532227f, 0.559082f, + 0.584961f, 0.609863f, 0.634277f, 0.656738f, 0.678711f, 0.700195f, 0.720703f, 0.738281f, 0.757324f, 0.774414f, 0.790527f, 0.805664f, + 0.820312f, 0.834473f, 0.846680f, 0.858887f, 0.869629f, 0.880859f, 0.890625f, 0.899902f, 0.909668f, 0.917969f, 0.964844f, 0.966797f, + 0.967285f, 0.965820f, 0.964844f, 0.963867f, 0.001437f, 0.004662f, 0.007919f, 0.011681f, 0.015404f, 0.019272f, 0.024261f, 0.029205f, + 0.034515f, 0.040619f, 0.046967f, 0.054138f, 0.061737f, 0.070496f, 0.080200f, 0.090271f, 0.101807f, 0.114136f, 0.127686f, 0.143188f, + 0.159058f, 0.176514f, 0.195190f, 0.215454f, 0.237305f, 0.260010f, 0.283936f, 0.309326f, 0.334717f, 0.361328f, 0.389160f, 0.416260f, + 0.444336f, 0.471436f, 0.499512f, 0.525879f, 0.552734f, 0.579590f, 0.604004f, 0.628906f, 0.651855f, 0.674805f, 0.696777f, 0.717773f, + 0.737305f, 0.755859f, 0.772949f, 0.789551f, 0.805664f, 0.819336f, 0.833984f, 0.847168f, 0.859375f, 0.871094f, 0.881836f, 0.892090f, + 0.902344f, 0.910156f, 0.962402f, 0.964355f, 0.964355f, 0.963867f, 0.962891f, 0.961914f, 0.001264f, 0.004036f, 0.007088f, 0.010170f, + 0.013672f, 0.017365f, 0.021423f, 0.025955f, 0.030533f, 0.035614f, 0.041321f, 0.047791f, 0.054626f, 0.062195f, 0.070679f, 0.080017f, + 0.089600f, 0.100769f, 0.112854f, 0.125977f, 0.139893f, 0.156128f, 0.172852f, 0.191650f, 0.211060f, 0.232056f, 0.254883f, 0.278076f, + 0.302979f, 0.328125f, 0.355225f, 0.381836f, 0.409912f, 0.437256f, 0.464844f, 0.492676f, 0.520508f, 0.547852f, 0.573242f, 0.599609f, + 0.625000f, 0.649414f, 0.672363f, 0.694336f, 0.714844f, 0.734863f, 0.753418f, 0.771484f, 0.788574f, 0.804688f, 0.820312f, 0.833496f, + 0.847656f, 0.859863f, 0.873047f, 0.883301f, 0.894043f, 0.903809f, 0.959961f, 0.961914f, 0.962402f, 0.960938f, 0.960449f, 0.959961f, + 0.001297f, 0.003721f, 0.006397f, 0.009308f, 0.012260f, 0.015808f, 0.019302f, 0.023010f, 0.027267f, 0.032013f, 0.037109f, 0.042419f, + 0.048523f, 0.054962f, 0.061920f, 0.070435f, 0.079407f, 0.088318f, 0.099121f, 0.111084f, 0.124023f, 0.137695f, 0.152832f, 0.169434f, + 0.187378f, 0.206421f, 0.227783f, 0.249268f, 0.272461f, 0.297363f, 0.322754f, 0.348389f, 0.376221f, 0.403809f, 0.431396f, 0.459229f, + 0.487305f, 0.515137f, 0.542480f, 0.569336f, 0.595215f, 0.621094f, 0.645996f, 0.669434f, 0.691406f, 0.712891f, 0.733887f, 0.753418f, + 0.770996f, 0.789062f, 0.805176f, 0.820801f, 0.835449f, 0.849121f, 0.861328f, 0.874512f, 0.885742f, 0.895508f, 0.956543f, 0.959473f, + 0.958984f, 0.958984f, 0.958008f, 0.957031f, 0.001267f, 0.003481f, 0.005955f, 0.008568f, 0.011185f, 0.014030f, 0.017151f, 0.020294f, + 0.024246f, 0.028427f, 0.032654f, 0.037476f, 0.042603f, 0.048523f, 0.054871f, 0.062408f, 0.070129f, 0.078552f, 0.087769f, 0.097534f, + 0.109192f, 0.121399f, 0.135010f, 0.150513f, 0.165894f, 0.183960f, 0.202881f, 0.222656f, 0.244385f, 0.267334f, 0.291260f, 0.317139f, + 0.343506f, 0.370605f, 0.397949f, 0.426025f, 0.454346f, 0.482666f, 0.511230f, 0.538086f, 0.565918f, 0.592285f, 0.618164f, 0.642578f, + 0.667480f, 0.690918f, 0.711914f, 0.732910f, 0.752930f, 0.771484f, 0.790039f, 0.806641f, 0.821777f, 0.837402f, 0.850586f, 0.864746f, + 0.875977f, 0.887695f, 0.953613f, 0.956543f, 0.957031f, 0.956055f, 0.956055f, 0.955078f, 0.001068f, 0.003025f, 0.005283f, 0.007442f, + 0.009857f, 0.012665f, 0.015930f, 0.018570f, 0.021820f, 0.025314f, 0.028931f, 0.033325f, 0.038147f, 0.042908f, 0.049011f, 0.055176f, + 0.061859f, 0.069397f, 0.077637f, 0.086792f, 0.096252f, 0.107117f, 0.119385f, 0.132690f, 0.147095f, 0.162720f, 0.180054f, 0.198486f, + 0.218384f, 0.239990f, 0.262207f, 0.287109f, 0.311523f, 0.337891f, 0.364990f, 0.392822f, 0.420654f, 0.449219f, 0.478027f, 0.505859f, + 0.535156f, 0.562012f, 0.588867f, 0.615723f, 0.641602f, 0.666016f, 0.688965f, 0.711914f, 0.732910f, 0.753906f, 0.773438f, 0.791016f, + 0.808594f, 0.823730f, 0.839355f, 0.854004f, 0.867188f, 0.879883f, 0.950195f, 0.954102f, 0.954102f, 0.953125f, 0.952637f, 0.952148f, + 0.000884f, 0.003082f, 0.004631f, 0.006931f, 0.008942f, 0.011513f, 0.013779f, 0.016663f, 0.019806f, 0.022934f, 0.026215f, 0.029999f, + 0.033813f, 0.038544f, 0.043365f, 0.048615f, 0.054352f, 0.061005f, 0.068420f, 0.076477f, 0.085022f, 0.095032f, 0.105469f, 0.117432f, + 0.130127f, 0.143799f, 0.159790f, 0.176270f, 0.194580f, 0.214478f, 0.235229f, 0.257568f, 0.281982f, 0.306641f, 0.332764f, 0.359863f, + 0.388184f, 0.416016f, 0.445557f, 0.474854f, 0.502441f, 0.531738f, 0.559570f, 0.586914f, 0.614258f, 0.640625f, 0.665039f, 0.689453f, + 0.712891f, 0.734863f, 0.755371f, 0.774902f, 0.793945f, 0.810547f, 0.827637f, 0.842773f, 0.857910f, 0.871094f, 0.946777f, 0.950684f, + 0.951172f, 0.950684f, 0.949707f, 0.949707f, 0.000848f, 0.002630f, 0.004330f, 0.006386f, 0.008148f, 0.010437f, 0.012436f, 0.014977f, + 0.017731f, 0.020645f, 0.023529f, 0.026413f, 0.030289f, 0.034302f, 0.038391f, 0.043365f, 0.048737f, 0.054413f, 0.060455f, 0.067383f, + 0.075134f, 0.083801f, 0.093262f, 0.103821f, 0.114746f, 0.127441f, 0.140991f, 0.156372f, 0.172729f, 0.190918f, 0.210449f, 0.231201f, + 0.253662f, 0.277344f, 0.302734f, 0.328857f, 0.355225f, 0.384033f, 0.413086f, 0.440918f, 0.471191f, 0.500488f, 0.529785f, 0.558594f, + 0.586426f, 0.613770f, 0.640137f, 0.666016f, 0.689453f, 0.714355f, 0.736328f, 0.757812f, 0.777832f, 0.796875f, 0.813965f, 0.831543f, + 0.847168f, 0.860840f, 0.943848f, 0.948242f, 0.947754f, 0.948242f, 0.946777f, 0.946777f, 0.000747f, 0.002462f, 0.004192f, 0.005573f, + 0.007454f, 0.009430f, 0.011253f, 0.013588f, 0.015762f, 0.018112f, 0.020859f, 0.023758f, 0.027084f, 0.030426f, 0.034332f, 0.038635f, + 0.042999f, 0.048340f, 0.053772f, 0.060028f, 0.066589f, 0.074402f, 0.082764f, 0.091553f, 0.101685f, 0.112854f, 0.125122f, 0.138184f, + 0.153320f, 0.169556f, 0.187500f, 0.206543f, 0.227539f, 0.249512f, 0.273193f, 0.298340f, 0.324463f, 0.351562f, 0.379883f, 0.409424f, + 0.438477f, 0.468750f, 0.498047f, 0.527832f, 0.556641f, 0.585449f, 0.614258f, 0.641113f, 0.666992f, 0.692383f, 0.716309f, 0.738281f, + 0.760742f, 0.780273f, 0.799805f, 0.818848f, 0.834473f, 0.851074f, 0.939941f, 0.944824f, 0.944336f, 0.944336f, 0.944336f, 0.943359f, + 0.000670f, 0.002079f, 0.003538f, 0.005146f, 0.006508f, 0.008247f, 0.010223f, 0.012260f, 0.014153f, 0.016479f, 0.018677f, 0.021515f, + 0.024323f, 0.027313f, 0.030518f, 0.034302f, 0.038422f, 0.042725f, 0.047760f, 0.053101f, 0.059113f, 0.065613f, 0.072937f, 0.080444f, + 0.089722f, 0.099426f, 0.110596f, 0.122314f, 0.135742f, 0.150513f, 0.166260f, 0.183716f, 0.202759f, 0.223633f, 0.245728f, 0.269287f, + 0.294189f, 0.320557f, 0.348633f, 0.376709f, 0.406494f, 0.436523f, 0.467285f, 0.497070f, 0.528320f, 0.557129f, 0.586426f, 0.614746f, + 0.642090f, 0.668945f, 0.694824f, 0.718750f, 0.742676f, 0.764648f, 0.786133f, 0.805176f, 0.823242f, 0.840820f, 0.936035f, 0.940918f, + 0.941406f, 0.941406f, 0.940430f, 0.939941f, 0.000645f, 0.001963f, 0.003384f, 0.004719f, 0.006042f, 0.007614f, 0.009384f, 0.011192f, + 0.012665f, 0.015083f, 0.016861f, 0.019165f, 0.021393f, 0.024445f, 0.027451f, 0.030716f, 0.034149f, 0.038116f, 0.042389f, 0.047028f, + 0.052277f, 0.058014f, 0.064270f, 0.071289f, 0.079041f, 0.087830f, 0.097351f, 0.108337f, 0.119995f, 0.132812f, 0.147217f, 0.163452f, + 0.180420f, 0.199585f, 0.219849f, 0.242065f, 0.265625f, 0.291260f, 0.318115f, 0.345703f, 0.375000f, 0.404541f, 0.434326f, 0.465820f, + 0.496582f, 0.526855f, 0.557617f, 0.587402f, 0.616699f, 0.645508f, 0.672363f, 0.698242f, 0.723145f, 0.747559f, 0.770020f, 0.791504f, + 0.810059f, 0.828613f, 0.931641f, 0.937012f, 0.937500f, 0.937500f, 0.937012f, 0.936523f, 0.000692f, 0.001705f, 0.003000f, 0.004238f, + 0.005798f, 0.006805f, 0.008659f, 0.009933f, 0.011681f, 0.013191f, 0.015259f, 0.017166f, 0.019379f, 0.021729f, 0.024796f, 0.027328f, + 0.030380f, 0.033661f, 0.037598f, 0.041718f, 0.046539f, 0.051270f, 0.056946f, 0.062988f, 0.069885f, 0.077271f, 0.085999f, 0.095398f, + 0.105652f, 0.117859f, 0.129883f, 0.144409f, 0.159912f, 0.177002f, 0.196045f, 0.216553f, 0.239014f, 0.262451f, 0.288086f, 0.314941f, + 0.343262f, 0.372314f, 0.403076f, 0.433594f, 0.465332f, 0.496826f, 0.527832f, 0.559082f, 0.589355f, 0.619629f, 0.648926f, 0.676758f, + 0.703125f, 0.728516f, 0.752930f, 0.775391f, 0.797363f, 0.817871f, 0.927246f, 0.933105f, 0.934082f, 0.933594f, 0.933594f, 0.933105f, + 0.000460f, 0.001622f, 0.002705f, 0.003983f, 0.004925f, 0.006363f, 0.007652f, 0.008965f, 0.010521f, 0.011963f, 0.013664f, 0.015480f, + 0.017258f, 0.019440f, 0.021912f, 0.024338f, 0.027084f, 0.030212f, 0.033356f, 0.037018f, 0.040833f, 0.045380f, 0.050110f, 0.055573f, + 0.061829f, 0.068359f, 0.075928f, 0.083984f, 0.093140f, 0.103333f, 0.115112f, 0.127441f, 0.141602f, 0.156982f, 0.174316f, 0.192871f, + 0.213257f, 0.235596f, 0.259766f, 0.285400f, 0.312256f, 0.341797f, 0.371094f, 0.402100f, 0.434082f, 0.465332f, 0.497314f, 0.529297f, + 0.562012f, 0.592773f, 0.623535f, 0.652832f, 0.681641f, 0.709473f, 0.735352f, 0.759766f, 0.783203f, 0.803711f, 0.922363f, 0.929199f, + 0.929688f, 0.929199f, 0.929688f, 0.928711f, 0.000341f, 0.001686f, 0.002537f, 0.003769f, 0.004745f, 0.005764f, 0.007034f, 0.008286f, + 0.009369f, 0.010742f, 0.012161f, 0.013931f, 0.015671f, 0.017563f, 0.019440f, 0.021851f, 0.024231f, 0.026672f, 0.029556f, 0.032776f, + 0.036255f, 0.040283f, 0.044464f, 0.049194f, 0.054413f, 0.060059f, 0.066589f, 0.074036f, 0.081909f, 0.091187f, 0.100769f, 0.112000f, + 0.124512f, 0.139038f, 0.154297f, 0.171265f, 0.189819f, 0.210571f, 0.232788f, 0.257324f, 0.283203f, 0.311035f, 0.339844f, 0.370850f, + 0.402100f, 0.433838f, 0.466797f, 0.499268f, 0.532227f, 0.565430f, 0.598145f, 0.628418f, 0.659180f, 0.687988f, 0.715820f, 0.742188f, + 0.767090f, 0.791504f, 0.917969f, 0.924805f, 0.925293f, 0.925293f, 0.924805f, 0.924805f, 0.000405f, 0.001282f, 0.002298f, 0.003269f, + 0.004448f, 0.005043f, 0.006294f, 0.007233f, 0.008606f, 0.009727f, 0.010849f, 0.012421f, 0.013885f, 0.015465f, 0.017426f, 0.019394f, + 0.021667f, 0.023819f, 0.026154f, 0.029175f, 0.032227f, 0.035706f, 0.039062f, 0.043427f, 0.047913f, 0.052856f, 0.058502f, 0.064880f, + 0.071960f, 0.079895f, 0.088867f, 0.098633f, 0.109619f, 0.122192f, 0.135742f, 0.151489f, 0.168457f, 0.187134f, 0.207764f, 0.230835f, + 0.254883f, 0.281494f, 0.310059f, 0.339355f, 0.370361f, 0.402588f, 0.435547f, 0.468994f, 0.502930f, 0.537109f, 0.569824f, 0.602051f, + 0.634766f, 0.665527f, 0.695801f, 0.724121f, 0.750488f, 0.776855f, 0.912598f, 0.919434f, 0.920410f, 0.920410f, 0.919922f, 0.920410f, + 0.000529f, 0.001217f, 0.002171f, 0.003035f, 0.003790f, 0.004784f, 0.005711f, 0.006756f, 0.007782f, 0.008987f, 0.009773f, 0.011185f, + 0.012650f, 0.013771f, 0.015656f, 0.017181f, 0.018890f, 0.021057f, 0.023239f, 0.025848f, 0.028488f, 0.031525f, 0.034607f, 0.038147f, + 0.042023f, 0.046539f, 0.051605f, 0.056793f, 0.063049f, 0.069946f, 0.078064f, 0.086548f, 0.096313f, 0.107117f, 0.119446f, 0.133301f, + 0.148560f, 0.165405f, 0.184570f, 0.205811f, 0.228394f, 0.253174f, 0.280029f, 0.308594f, 0.339111f, 0.370605f, 0.404053f, 0.437988f, + 0.471680f, 0.506348f, 0.541504f, 0.576172f, 0.609375f, 0.642578f, 0.674316f, 0.705078f, 0.734375f, 0.761719f, 0.907227f, 0.914062f, + 0.915527f, 0.915527f, 0.916016f, 0.915039f, 0.000402f, 0.001247f, 0.001841f, 0.002651f, 0.003414f, 0.004200f, 0.005337f, 0.005821f, + 0.006733f, 0.008041f, 0.008942f, 0.010201f, 0.011261f, 0.012749f, 0.013893f, 0.015472f, 0.016663f, 0.018829f, 0.020615f, 0.022873f, + 0.025299f, 0.027893f, 0.030533f, 0.033600f, 0.037140f, 0.040924f, 0.044983f, 0.049927f, 0.055359f, 0.061340f, 0.068176f, 0.075500f, + 0.084106f, 0.093933f, 0.104370f, 0.116638f, 0.130249f, 0.145996f, 0.162842f, 0.181885f, 0.203735f, 0.226562f, 0.251465f, 0.279297f, + 0.308594f, 0.339355f, 0.373047f, 0.406982f, 0.440918f, 0.477051f, 0.511719f, 0.548340f, 0.583496f, 0.618164f, 0.652344f, 0.684570f, + 0.715332f, 0.745605f, 0.901855f, 0.909180f, 0.910156f, 0.910645f, 0.910156f, 0.910156f, 0.000371f, 0.001090f, 0.001752f, 0.002409f, + 0.003042f, 0.003963f, 0.004898f, 0.005295f, 0.006077f, 0.006992f, 0.008102f, 0.009338f, 0.010101f, 0.011078f, 0.012375f, 0.013718f, + 0.015099f, 0.016403f, 0.018402f, 0.020203f, 0.022354f, 0.024475f, 0.026825f, 0.029388f, 0.032623f, 0.035522f, 0.039429f, 0.043762f, + 0.048462f, 0.053558f, 0.059265f, 0.065552f, 0.073120f, 0.081787f, 0.091431f, 0.102112f, 0.114136f, 0.127930f, 0.143066f, 0.160767f, + 0.179810f, 0.200928f, 0.224854f, 0.250732f, 0.279053f, 0.308838f, 0.340820f, 0.374756f, 0.410156f, 0.446045f, 0.482666f, 0.520020f, + 0.556152f, 0.593262f, 0.628906f, 0.663574f, 0.695801f, 0.728027f, 0.895508f, 0.903809f, 0.904297f, 0.904297f, 0.904297f, 0.904785f, + 0.000425f, 0.000937f, 0.001529f, 0.002129f, 0.002674f, 0.003696f, 0.004257f, 0.004990f, 0.005726f, 0.006161f, 0.007118f, 0.007919f, + 0.009109f, 0.009941f, 0.011055f, 0.011993f, 0.013191f, 0.014832f, 0.016281f, 0.017868f, 0.019562f, 0.021362f, 0.023514f, 0.025909f, + 0.028549f, 0.031189f, 0.034637f, 0.037994f, 0.042145f, 0.046570f, 0.051453f, 0.057129f, 0.063965f, 0.070984f, 0.079285f, 0.088806f, + 0.099426f, 0.111267f, 0.125366f, 0.140747f, 0.158203f, 0.178101f, 0.199585f, 0.223755f, 0.250732f, 0.279297f, 0.310059f, 0.343994f, + 0.377686f, 0.414307f, 0.451904f, 0.489258f, 0.527832f, 0.565918f, 0.603027f, 0.640137f, 0.675781f, 0.710449f, 0.888672f, 0.897461f, + 0.899902f, 0.900391f, 0.899414f, 0.899414f, 0.000317f, 0.000823f, 0.001386f, 0.002108f, 0.002684f, 0.003239f, 0.003883f, 0.004303f, + 0.004730f, 0.005569f, 0.006626f, 0.007214f, 0.008003f, 0.008865f, 0.009590f, 0.010948f, 0.011856f, 0.012871f, 0.014381f, 0.015640f, + 0.017075f, 0.018799f, 0.020569f, 0.022537f, 0.024704f, 0.027405f, 0.030090f, 0.033142f, 0.036346f, 0.040436f, 0.044830f, 0.049835f, + 0.055450f, 0.061584f, 0.068665f, 0.076904f, 0.086060f, 0.096741f, 0.109192f, 0.122559f, 0.138428f, 0.155762f, 0.176270f, 0.198242f, + 0.223145f, 0.250244f, 0.280518f, 0.312500f, 0.346680f, 0.382324f, 0.420410f, 0.458740f, 0.498779f, 0.538086f, 0.577637f, 0.616211f, + 0.654297f, 0.690918f, 0.881348f, 0.890625f, 0.892578f, 0.893066f, 0.893066f, 0.892578f, 0.000385f, 0.000766f, 0.001544f, 0.001925f, + 0.002359f, 0.002947f, 0.003176f, 0.003691f, 0.004288f, 0.005215f, 0.005917f, 0.006214f, 0.007019f, 0.007843f, 0.008469f, 0.009598f, + 0.010345f, 0.011559f, 0.012497f, 0.013634f, 0.014992f, 0.016373f, 0.017853f, 0.019608f, 0.021515f, 0.023788f, 0.026260f, 0.028931f, + 0.031860f, 0.034912f, 0.038635f, 0.042633f, 0.047638f, 0.053070f, 0.059540f, 0.066284f, 0.074524f, 0.083679f, 0.094177f, 0.106445f, + 0.120361f, 0.135620f, 0.154053f, 0.174072f, 0.197144f, 0.222900f, 0.251221f, 0.281982f, 0.315430f, 0.351318f, 0.388672f, 0.427734f, + 0.468506f, 0.508301f, 0.549805f, 0.591309f, 0.631348f, 0.670410f, 0.874512f, 0.884766f, 0.885742f, 0.886230f, 0.886230f, 0.886230f, + 0.000230f, 0.000832f, 0.001281f, 0.001865f, 0.002207f, 0.002605f, 0.003212f, 0.003284f, 0.004124f, 0.004597f, 0.005222f, 0.005703f, + 0.006260f, 0.007095f, 0.007790f, 0.008377f, 0.009010f, 0.010078f, 0.011009f, 0.011925f, 0.013153f, 0.014282f, 0.015610f, 0.017151f, + 0.018951f, 0.020416f, 0.022583f, 0.024826f, 0.027328f, 0.030136f, 0.033508f, 0.036835f, 0.040985f, 0.045410f, 0.050812f, 0.056854f, + 0.063965f, 0.071777f, 0.081177f, 0.091858f, 0.103699f, 0.117615f, 0.133423f, 0.152588f, 0.172974f, 0.196777f, 0.222900f, 0.252686f, + 0.284912f, 0.319824f, 0.356934f, 0.395996f, 0.436768f, 0.478516f, 0.521484f, 0.564453f, 0.607422f, 0.649414f, 0.866699f, 0.876953f, + 0.877930f, 0.879395f, 0.879883f, 0.878418f, 0.000228f, 0.000734f, 0.000993f, 0.001416f, 0.001935f, 0.002293f, 0.002541f, 0.003174f, + 0.003508f, 0.004040f, 0.004337f, 0.005039f, 0.005505f, 0.006054f, 0.006840f, 0.007366f, 0.008041f, 0.008644f, 0.009544f, 0.010460f, + 0.011238f, 0.012329f, 0.013542f, 0.014755f, 0.016083f, 0.017624f, 0.019424f, 0.021408f, 0.023422f, 0.025803f, 0.028366f, 0.031311f, + 0.034912f, 0.039124f, 0.043304f, 0.048492f, 0.054291f, 0.061188f, 0.069397f, 0.078552f, 0.089233f, 0.101074f, 0.115540f, 0.131226f, + 0.150757f, 0.172119f, 0.196533f, 0.224243f, 0.254883f, 0.288574f, 0.324707f, 0.364014f, 0.405029f, 0.447510f, 0.491699f, 0.536133f, + 0.581543f, 0.627441f, 0.858398f, 0.869141f, 0.870605f, 0.871582f, 0.871094f, 0.871582f, 0.000118f, 0.000713f, 0.000985f, 0.001328f, + 0.001612f, 0.001999f, 0.002399f, 0.002913f, 0.003139f, 0.003567f, 0.004055f, 0.004406f, 0.004986f, 0.005226f, 0.005856f, 0.006332f, + 0.007042f, 0.007553f, 0.008286f, 0.009064f, 0.009834f, 0.010696f, 0.011658f, 0.012726f, 0.013817f, 0.015289f, 0.016693f, 0.018265f, + 0.019699f, 0.021835f, 0.024307f, 0.026642f, 0.029770f, 0.033234f, 0.037048f, 0.041351f, 0.046478f, 0.052032f, 0.058960f, 0.066589f, + 0.075745f, 0.086182f, 0.099121f, 0.113037f, 0.129517f, 0.149048f, 0.171387f, 0.196899f, 0.225464f, 0.257812f, 0.293457f, 0.331787f, + 0.373291f, 0.416748f, 0.460938f, 0.507812f, 0.554688f, 0.602051f, 0.849609f, 0.859863f, 0.862793f, 0.863281f, 0.862793f, 0.862793f, + 0.000211f, 0.000522f, 0.000877f, 0.001204f, 0.001507f, 0.001724f, 0.002062f, 0.002426f, 0.002867f, 0.003157f, 0.003443f, 0.003752f, + 0.004192f, 0.004753f, 0.005154f, 0.005428f, 0.006065f, 0.006546f, 0.007210f, 0.007725f, 0.008530f, 0.009247f, 0.010025f, 0.010887f, + 0.011909f, 0.012970f, 0.014069f, 0.015335f, 0.017105f, 0.018433f, 0.020554f, 0.022552f, 0.025116f, 0.027802f, 0.031158f, 0.034485f, + 0.038971f, 0.044037f, 0.049469f, 0.055847f, 0.063843f, 0.072815f, 0.083618f, 0.095947f, 0.110840f, 0.128174f, 0.147949f, 0.171387f, + 0.198242f, 0.228271f, 0.262207f, 0.299805f, 0.340332f, 0.384277f, 0.430176f, 0.477295f, 0.527344f, 0.577637f, 0.839844f, 0.851074f, + 0.853516f, 0.854492f, 0.854980f, 0.854980f, 0.000218f, 0.000479f, 0.000706f, 0.001109f, 0.001245f, 0.001763f, 0.001800f, 0.002211f, + 0.002377f, 0.002783f, 0.003103f, 0.003223f, 0.003782f, 0.004089f, 0.004326f, 0.004711f, 0.005306f, 0.005569f, 0.006199f, 0.006653f, + 0.007168f, 0.007919f, 0.008560f, 0.009254f, 0.009979f, 0.010872f, 0.012054f, 0.012810f, 0.014221f, 0.015793f, 0.017181f, 0.018967f, + 0.021088f, 0.023361f, 0.026001f, 0.028915f, 0.032257f, 0.036469f, 0.040924f, 0.046875f, 0.053375f, 0.061218f, 0.070435f, 0.080811f, + 0.093628f, 0.108704f, 0.126709f, 0.147461f, 0.172241f, 0.199951f, 0.232788f, 0.268799f, 0.308594f, 0.351562f, 0.397705f, 0.447266f, + 0.498291f, 0.550293f, 0.830078f, 0.841797f, 0.843750f, 0.845215f, 0.845215f, 0.845703f, 0.000139f, 0.000379f, 0.000704f, 0.000896f, + 0.001095f, 0.001392f, 0.001649f, 0.002058f, 0.002235f, 0.002483f, 0.002621f, 0.002878f, 0.003214f, 0.003580f, 0.003820f, 0.004055f, + 0.004498f, 0.004791f, 0.005173f, 0.005692f, 0.006145f, 0.006691f, 0.007175f, 0.007874f, 0.008499f, 0.009239f, 0.010117f, 0.011032f, + 0.011864f, 0.012901f, 0.014282f, 0.015701f, 0.017242f, 0.019516f, 0.021469f, 0.024002f, 0.026749f, 0.029953f, 0.034027f, 0.038727f, + 0.044250f, 0.050568f, 0.058136f, 0.067139f, 0.078247f, 0.091614f, 0.106689f, 0.125366f, 0.147339f, 0.172974f, 0.202881f, 0.237671f, + 0.275879f, 0.318359f, 0.365234f, 0.415283f, 0.468018f, 0.521973f, 0.819336f, 0.832031f, 0.834473f, 0.834961f, 0.835449f, 0.835938f, + 0.000115f, 0.000396f, 0.000688f, 0.000885f, 0.000917f, 0.001393f, 0.001478f, 0.001590f, 0.001944f, 0.002123f, 0.002291f, 0.002644f, + 0.002666f, 0.003023f, 0.003197f, 0.003546f, 0.003714f, 0.004246f, 0.004551f, 0.004837f, 0.005108f, 0.005577f, 0.006054f, 0.006504f, + 0.007023f, 0.007633f, 0.008362f, 0.009148f, 0.009926f, 0.010742f, 0.011917f, 0.013062f, 0.014351f, 0.015991f, 0.017639f, 0.019455f, + 0.021729f, 0.024689f, 0.027740f, 0.031708f, 0.036102f, 0.041260f, 0.047882f, 0.055450f, 0.064392f, 0.075500f, 0.088928f, 0.104797f, + 0.124756f, 0.147949f, 0.175415f, 0.207275f, 0.244507f, 0.286133f, 0.332520f, 0.381836f, 0.436279f, 0.492432f, 0.808105f, 0.821289f, + 0.822754f, 0.824707f, 0.825195f, 0.824219f, 0.000209f, 0.000435f, 0.000493f, 0.000669f, 0.001040f, 0.001076f, 0.001254f, 0.001398f, + 0.001603f, 0.001697f, 0.001987f, 0.002140f, 0.002268f, 0.002472f, 0.002769f, 0.002991f, 0.003302f, 0.003572f, 0.003685f, 0.004002f, + 0.004337f, 0.004654f, 0.005062f, 0.005379f, 0.005871f, 0.006363f, 0.006733f, 0.007416f, 0.008102f, 0.008812f, 0.009727f, 0.010689f, + 0.011566f, 0.013145f, 0.014053f, 0.015762f, 0.017899f, 0.020096f, 0.022552f, 0.025528f, 0.028992f, 0.033325f, 0.038635f, 0.044952f, + 0.052582f, 0.061554f, 0.072998f, 0.086670f, 0.103577f, 0.124329f, 0.148804f, 0.178467f, 0.213501f, 0.253174f, 0.298828f, 0.348877f, + 0.403076f, 0.461914f, 0.795898f, 0.809570f, 0.812012f, 0.813477f, 0.813477f, 0.814453f, 0.000243f, 0.000322f, 0.000466f, 0.000710f, + 0.000863f, 0.000942f, 0.001051f, 0.001182f, 0.001369f, 0.001451f, 0.001716f, 0.001851f, 0.001968f, 0.002192f, 0.002323f, 0.002470f, + 0.002773f, 0.002850f, 0.003056f, 0.003399f, 0.003624f, 0.003832f, 0.004192f, 0.004467f, 0.004955f, 0.005276f, 0.005772f, 0.006084f, + 0.006672f, 0.007191f, 0.007828f, 0.008720f, 0.009575f, 0.010292f, 0.011505f, 0.012535f, 0.014114f, 0.016006f, 0.017838f, 0.020462f, + 0.023193f, 0.026489f, 0.030807f, 0.035858f, 0.041840f, 0.049652f, 0.059174f, 0.070435f, 0.084839f, 0.102783f, 0.124146f, 0.151489f, + 0.183472f, 0.221802f, 0.265137f, 0.315186f, 0.369629f, 0.430664f, 0.782715f, 0.796875f, 0.799805f, 0.800293f, 0.801758f, 0.801758f, + 0.000119f, 0.000369f, 0.000340f, 0.000595f, 0.000667f, 0.000841f, 0.001010f, 0.001086f, 0.001179f, 0.001225f, 0.001494f, 0.001555f, + 0.001654f, 0.001754f, 0.001965f, 0.002142f, 0.002197f, 0.002432f, 0.002619f, 0.002811f, 0.003021f, 0.003139f, 0.003567f, 0.003708f, + 0.004066f, 0.004360f, 0.004612f, 0.005123f, 0.005489f, 0.005878f, 0.006306f, 0.006824f, 0.007576f, 0.008286f, 0.008949f, 0.010155f, + 0.011322f, 0.012756f, 0.014046f, 0.015976f, 0.018250f, 0.020874f, 0.024094f, 0.027878f, 0.032867f, 0.039154f, 0.046509f, 0.055908f, + 0.068054f, 0.082886f, 0.102356f, 0.125732f, 0.155029f, 0.190674f, 0.232422f, 0.281006f, 0.335693f, 0.397949f, 0.770020f, 0.783691f, + 0.786621f, 0.787598f, 0.788086f, 0.789551f, 0.000000f, 0.000220f, 0.000275f, 0.000562f, 0.000618f, 0.000683f, 0.000733f, 0.000761f, + 0.000966f, 0.001022f, 0.001184f, 0.001237f, 0.001382f, 0.001552f, 0.001688f, 0.001724f, 0.001918f, 0.002024f, 0.002115f, 0.002243f, + 0.002403f, 0.002718f, 0.002840f, 0.003052f, 0.003330f, 0.003508f, 0.003860f, 0.004097f, 0.004314f, 0.004719f, 0.005074f, 0.005535f, + 0.006058f, 0.006584f, 0.007168f, 0.007874f, 0.008759f, 0.009651f, 0.011086f, 0.012459f, 0.013992f, 0.015945f, 0.018433f, 0.021408f, + 0.025192f, 0.029861f, 0.035950f, 0.043396f, 0.053406f, 0.065735f, 0.082031f, 0.102234f, 0.128052f, 0.160645f, 0.200073f, 0.247192f, + 0.301025f, 0.363281f, 0.755371f, 0.770996f, 0.772949f, 0.773926f, 0.775879f, 0.775879f, 0.000216f, 0.000102f, 0.000381f, 0.000487f, + 0.000429f, 0.000552f, 0.000579f, 0.000788f, 0.000804f, 0.000854f, 0.000937f, 0.000996f, 0.001078f, 0.001218f, 0.001315f, 0.001499f, + 0.001532f, 0.001642f, 0.001805f, 0.001825f, 0.002077f, 0.002178f, 0.002312f, 0.002396f, 0.002575f, 0.002735f, 0.002947f, 0.003317f, + 0.003428f, 0.003721f, 0.004185f, 0.004379f, 0.004704f, 0.005253f, 0.005650f, 0.006145f, 0.006870f, 0.007515f, 0.008415f, 0.009430f, + 0.010612f, 0.012093f, 0.013954f, 0.016052f, 0.018967f, 0.022476f, 0.027115f, 0.032898f, 0.040649f, 0.050690f, 0.063599f, 0.080811f, + 0.103210f, 0.132202f, 0.168823f, 0.213501f, 0.266602f, 0.329102f, 0.740234f, 0.756348f, 0.758789f, 0.760254f, 0.761230f, 0.761230f, + 0.000179f, 0.000181f, 0.000180f, 0.000289f, 0.000413f, 0.000458f, 0.000497f, 0.000620f, 0.000646f, 0.000688f, 0.000830f, 0.000868f, + 0.000904f, 0.000981f, 0.001024f, 0.001178f, 0.001146f, 0.001302f, 0.001382f, 0.001523f, 0.001679f, 0.001737f, 0.001824f, 0.001959f, + 0.002195f, 0.002283f, 0.002438f, 0.002579f, 0.002703f, 0.002939f, 0.003181f, 0.003454f, 0.003677f, 0.004051f, 0.004395f, 0.004738f, + 0.005283f, 0.005783f, 0.006420f, 0.007095f, 0.007988f, 0.009094f, 0.010384f, 0.011955f, 0.013939f, 0.016434f, 0.019836f, 0.024292f, + 0.030029f, 0.037659f, 0.048065f, 0.061890f, 0.080811f, 0.105774f, 0.138672f, 0.180542f, 0.231934f, 0.293213f, 0.724121f, 0.740234f, + 0.744141f, 0.745117f, 0.745605f, 0.746094f, 0.000000f, 0.000056f, 0.000263f, 0.000339f, 0.000369f, 0.000357f, 0.000376f, 0.000508f, + 0.000519f, 0.000558f, 0.000581f, 0.000678f, 0.000767f, 0.000775f, 0.000905f, 0.000849f, 0.000992f, 0.000942f, 0.001192f, 0.001169f, + 0.001204f, 0.001375f, 0.001439f, 0.001532f, 0.001634f, 0.001676f, 0.001799f, 0.001904f, 0.002165f, 0.002262f, 0.002377f, 0.002611f, + 0.002836f, 0.003103f, 0.003321f, 0.003550f, 0.004005f, 0.004356f, 0.004772f, 0.005295f, 0.005962f, 0.006756f, 0.007690f, 0.008690f, + 0.010078f, 0.011871f, 0.014252f, 0.017242f, 0.021393f, 0.027100f, 0.034851f, 0.046051f, 0.060455f, 0.081848f, 0.110474f, 0.148682f, + 0.197632f, 0.257568f, 0.706543f, 0.724121f, 0.727539f, 0.729492f, 0.729980f, 0.729492f, 0.000000f, 0.000130f, 0.000174f, 0.000312f, + 0.000290f, 0.000293f, 0.000372f, 0.000319f, 0.000397f, 0.000433f, 0.000550f, 0.000552f, 0.000564f, 0.000593f, 0.000638f, 0.000758f, + 0.000784f, 0.000797f, 0.000842f, 0.000937f, 0.001011f, 0.001068f, 0.001125f, 0.001231f, 0.001228f, 0.001288f, 0.001409f, 0.001465f, + 0.001644f, 0.001697f, 0.001965f, 0.001924f, 0.002136f, 0.002270f, 0.002436f, 0.002697f, 0.002916f, 0.003202f, 0.003492f, 0.003929f, + 0.004391f, 0.004887f, 0.005516f, 0.006233f, 0.007240f, 0.008461f, 0.010094f, 0.012070f, 0.014854f, 0.018585f, 0.024338f, 0.032379f, + 0.043884f, 0.060516f, 0.084656f, 0.118469f, 0.164185f, 0.222168f, 0.689941f, 0.708008f, 0.710449f, 0.711914f, 0.712891f, 0.712402f, + 0.000000f, 0.000000f, 0.000122f, 0.000226f, 0.000145f, 0.000282f, 0.000255f, 0.000247f, 0.000323f, 0.000389f, 0.000379f, 0.000435f, + 0.000461f, 0.000509f, 0.000535f, 0.000517f, 0.000557f, 0.000604f, 0.000649f, 0.000690f, 0.000757f, 0.000773f, 0.000836f, 0.000865f, + 0.000924f, 0.000957f, 0.001095f, 0.001104f, 0.001243f, 0.001361f, 0.001458f, 0.001486f, 0.001619f, 0.001745f, 0.001791f, 0.001993f, + 0.002100f, 0.002321f, 0.002539f, 0.002771f, 0.003084f, 0.003412f, 0.003866f, 0.004368f, 0.005062f, 0.005821f, 0.006882f, 0.008278f, + 0.010071f, 0.012756f, 0.016327f, 0.021774f, 0.029785f, 0.042206f, 0.061462f, 0.090149f, 0.131348f, 0.187378f, 0.669434f, 0.688965f, + 0.692383f, 0.694824f, 0.695801f, 0.695312f, 0.000000f, 0.000118f, 0.000113f, 0.000158f, 0.000158f, 0.000176f, 0.000224f, 0.000202f, + 0.000251f, 0.000260f, 0.000280f, 0.000332f, 0.000316f, 0.000365f, 0.000389f, 0.000419f, 0.000454f, 0.000435f, 0.000476f, 0.000494f, + 0.000516f, 0.000576f, 0.000609f, 0.000656f, 0.000678f, 0.000712f, 0.000792f, 0.000800f, 0.000852f, 0.000919f, 0.000961f, 0.001070f, + 0.001120f, 0.001238f, 0.001300f, 0.001480f, 0.001459f, 0.001634f, 0.001798f, 0.001947f, 0.002111f, 0.002377f, 0.002615f, 0.002966f, + 0.003410f, 0.003933f, 0.004585f, 0.005489f, 0.006706f, 0.008148f, 0.010757f, 0.013962f, 0.019257f, 0.027771f, 0.041931f, 0.065125f, + 0.101135f, 0.152832f, 0.650391f, 0.670898f, 0.674316f, 0.675293f, 0.675781f, 0.677246f, 0.000000f, 0.000000f, 0.000109f, 0.000106f, + 0.000121f, 0.000117f, 0.000130f, 0.000151f, 0.000161f, 0.000174f, 0.000234f, 0.000197f, 0.000205f, 0.000236f, 0.000272f, 0.000296f, + 0.000267f, 0.000296f, 0.000397f, 0.000344f, 0.000413f, 0.000395f, 0.000433f, 0.000434f, 0.000504f, 0.000488f, 0.000532f, 0.000550f, + 0.000602f, 0.000711f, 0.000675f, 0.000704f, 0.000752f, 0.000817f, 0.000896f, 0.000955f, 0.001009f, 0.001091f, 0.001223f, 0.001271f, + 0.001415f, 0.001560f, 0.001721f, 0.001989f, 0.002214f, 0.002508f, 0.002930f, 0.003504f, 0.004208f, 0.005169f, 0.006603f, 0.008606f, + 0.011864f, 0.017090f, 0.026367f, 0.043396f, 0.072571f, 0.119751f, 0.630859f, 0.650879f, 0.653809f, 0.656250f, 0.657227f, 0.657227f, + 0.000000f, 0.000111f, 0.000104f, 0.000100f, 0.000096f, 0.000094f, 0.000105f, 0.000096f, 0.000101f, 0.000115f, 0.000119f, 0.000155f, + 0.000129f, 0.000180f, 0.000186f, 0.000199f, 0.000208f, 0.000214f, 0.000232f, 0.000230f, 0.000237f, 0.000247f, 0.000303f, 0.000276f, + 0.000324f, 0.000332f, 0.000381f, 0.000371f, 0.000393f, 0.000428f, 0.000490f, 0.000468f, 0.000512f, 0.000540f, 0.000598f, 0.000670f, + 0.000673f, 0.000711f, 0.000767f, 0.000842f, 0.000894f, 0.000985f, 0.001120f, 0.001200f, 0.001416f, 0.001544f, 0.001768f, 0.002052f, + 0.002510f, 0.003044f, 0.003796f, 0.005016f, 0.006870f, 0.009918f, 0.015335f, 0.026077f, 0.048004f, 0.088745f, 0.610352f, 0.630859f, + 0.634277f, 0.636230f, 0.637207f, 0.638184f, 0.000000f, 0.000104f, 0.000098f, 0.000092f, 0.000087f, 0.000084f, 0.000081f, 0.000078f, + 0.000074f, 0.000070f, 0.000073f, 0.000075f, 0.000081f, 0.000081f, 0.000119f, 0.000124f, 0.000129f, 0.000115f, 0.000142f, 0.000169f, + 0.000155f, 0.000169f, 0.000172f, 0.000196f, 0.000209f, 0.000211f, 0.000203f, 0.000238f, 0.000245f, 0.000260f, 0.000282f, 0.000281f, + 0.000297f, 0.000333f, 0.000343f, 0.000374f, 0.000398f, 0.000428f, 0.000473f, 0.000494f, 0.000534f, 0.000591f, 0.000643f, 0.000708f, + 0.000790f, 0.000893f, 0.001040f, 0.001169f, 0.001381f, 0.001676f, 0.002123f, 0.002686f, 0.003658f, 0.005329f, 0.008347f, 0.014244f, + 0.027954f, 0.060638f, 0.587891f, 0.609375f, 0.613281f, 0.614746f, 0.616699f, 0.616211f, 0.000110f, 0.000094f, 0.000085f, 0.000079f, + 0.000075f, 0.000072f, 0.000069f, 0.000067f, 0.000065f, 0.000063f, 0.000059f, 0.000059f, 0.000054f, 0.000051f, 0.000055f, 0.000051f, + 0.000066f, 0.000066f, 0.000078f, 0.000074f, 0.000089f, 0.000091f, 0.000102f, 0.000109f, 0.000114f, 0.000126f, 0.000133f, 0.000130f, + 0.000141f, 0.000141f, 0.000156f, 0.000172f, 0.000180f, 0.000179f, 0.000206f, 0.000199f, 0.000214f, 0.000254f, 0.000247f, 0.000282f, + 0.000300f, 0.000324f, 0.000349f, 0.000374f, 0.000413f, 0.000459f, 0.000513f, 0.000619f, 0.000711f, 0.000823f, 0.001030f, 0.001269f, + 0.001724f, 0.002487f, 0.003948f, 0.007015f, 0.014122f, 0.036346f, 0.565430f, 0.586426f, 0.592285f, 0.592773f, 0.594238f, 0.594727f, + 0.000092f, 0.000073f, 0.000067f, 0.000062f, 0.000057f, 0.000055f, 0.000052f, 0.000052f, 0.000049f, 0.000049f, 0.000047f, 0.000046f, + 0.000046f, 0.000043f, 0.000041f, 0.000039f, 0.000038f, 0.000036f, 0.000039f, 0.000036f, 0.000039f, 0.000037f, 0.000039f, 0.000047f, + 0.000051f, 0.000057f, 0.000059f, 0.000060f, 0.000067f, 0.000071f, 0.000078f, 0.000085f, 0.000087f, 0.000091f, 0.000098f, 0.000095f, + 0.000102f, 0.000122f, 0.000122f, 0.000137f, 0.000143f, 0.000145f, 0.000168f, 0.000171f, 0.000197f, 0.000209f, 0.000234f, 0.000264f, + 0.000295f, 0.000349f, 0.000418f, 0.000520f, 0.000678f, 0.000958f, 0.001512f, 0.002745f, 0.006092f, 0.017456f, 0.542969f, 0.565430f, + 0.568848f, 0.569824f, 0.572266f, 0.572266f, 0.000052f, 0.000042f, 0.000037f, 0.000035f, 0.000033f, 0.000033f, 0.000032f, 0.000031f, + 0.000031f, 0.000029f, 0.000030f, 0.000030f, 0.000029f, 0.000028f, 0.000028f, 0.000028f, 0.000028f, 0.000028f, 0.000027f, 0.000026f, + 0.000024f, 0.000023f, 0.000022f, 0.000022f, 0.000021f, 0.000020f, 0.000019f, 0.000022f, 0.000020f, 0.000023f, 0.000024f, 0.000026f, + 0.000028f, 0.000035f, 0.000037f, 0.000038f, 0.000039f, 0.000043f, 0.000048f, 0.000050f, 0.000053f, 0.000055f, 0.000062f, 0.000059f, + 0.000072f, 0.000070f, 0.000087f, 0.000099f, 0.000100f, 0.000119f, 0.000142f, 0.000162f, 0.000217f, 0.000283f, 0.000425f, 0.000760f, + 0.001818f, 0.006405f, 0.519043f, 0.541504f, 0.546387f, 0.548828f, 0.549316f, 0.550781f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000004f, 0.000004f, 0.000006f, 0.000006f, 0.000008f, 0.000009f, 0.000009f, 0.000009f, 0.000010f, + 0.000010f, 0.000010f, 0.000011f, 0.000011f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000013f, 0.000012f, 0.000012f, + 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000008f, 0.000011f, + 0.000011f, 0.000012f, 0.000015f, 0.000016f, 0.000016f, 0.000018f, 0.000018f, 0.000020f, 0.000022f, 0.000024f, 0.000028f, 0.000035f, + 0.000036f, 0.000052f, 0.000071f, 0.000117f, 0.000260f, 0.001269f, 0.495605f, 0.518555f, 0.523926f, 0.525879f, 0.526855f, 0.527344f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, + 0.000002f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000005f, 0.000021f, 0.473145f, 0.495605f, + 0.500000f, 0.502441f, 0.503418f, 0.503906f, + }, + { + 0.045868f, 0.130493f, 0.205322f, 0.272705f, 0.331787f, 0.384521f, 0.431885f, 0.473389f, 0.511719f, 0.545898f, 0.576660f, 0.605469f, + 0.631348f, 0.654785f, 0.676758f, 0.696289f, 0.714355f, 0.732422f, 0.749023f, 0.763184f, 0.777832f, 0.790527f, 0.802734f, 0.813477f, + 0.824219f, 0.834961f, 0.844238f, 0.853027f, 0.862305f, 0.869629f, 0.877441f, 0.884277f, 0.892090f, 0.898926f, 0.904297f, 0.910645f, + 0.916992f, 0.921875f, 0.926758f, 0.931641f, 0.937012f, 0.941406f, 0.945801f, 0.950195f, 0.954102f, 0.958496f, 0.962402f, 0.966309f, + 0.969238f, 0.973145f, 0.976074f, 0.979492f, 0.982422f, 0.985352f, 0.988281f, 0.991211f, 0.993652f, 0.996094f, 0.997070f, 0.993164f, + 0.990234f, 0.987305f, 0.984375f, 0.981445f, 0.033447f, 0.097717f, 0.160400f, 0.219238f, 0.273438f, 0.323486f, 0.371582f, 0.414062f, + 0.454834f, 0.491211f, 0.524414f, 0.555176f, 0.583984f, 0.610840f, 0.635254f, 0.658203f, 0.678223f, 0.697754f, 0.716309f, 0.732422f, + 0.749023f, 0.763184f, 0.776855f, 0.790527f, 0.802734f, 0.812988f, 0.824707f, 0.834473f, 0.844238f, 0.853516f, 0.862305f, 0.870117f, + 0.877930f, 0.884766f, 0.892090f, 0.897949f, 0.905762f, 0.910645f, 0.917480f, 0.923340f, 0.927734f, 0.933105f, 0.937988f, 0.942871f, + 0.947266f, 0.951172f, 0.955566f, 0.960449f, 0.963379f, 0.967285f, 0.970703f, 0.974609f, 0.978027f, 0.981445f, 0.984863f, 0.986816f, + 0.989746f, 0.993164f, 0.995605f, 0.992188f, 0.988770f, 0.986328f, 0.983398f, 0.980957f, 0.024796f, 0.075195f, 0.126221f, 0.176025f, + 0.224976f, 0.271729f, 0.317383f, 0.359375f, 0.399902f, 0.437744f, 0.472656f, 0.505371f, 0.536133f, 0.565430f, 0.591797f, 0.615723f, + 0.639648f, 0.660156f, 0.681152f, 0.699219f, 0.718262f, 0.734375f, 0.749512f, 0.764648f, 0.777832f, 0.791016f, 0.802734f, 0.813965f, + 0.825195f, 0.835449f, 0.844727f, 0.854004f, 0.862305f, 0.871094f, 0.878418f, 0.886230f, 0.893555f, 0.900391f, 0.906738f, 0.912598f, + 0.917969f, 0.923828f, 0.929688f, 0.935059f, 0.939941f, 0.943848f, 0.949219f, 0.953613f, 0.958008f, 0.961914f, 0.965332f, 0.969238f, + 0.972656f, 0.976074f, 0.979492f, 0.982910f, 0.986328f, 0.989258f, 0.993652f, 0.990723f, 0.987793f, 0.985352f, 0.982910f, 0.979980f, + 0.019119f, 0.058624f, 0.100220f, 0.142578f, 0.185303f, 0.227417f, 0.269287f, 0.310059f, 0.348877f, 0.385254f, 0.421875f, 0.455566f, + 0.489014f, 0.518555f, 0.546875f, 0.574707f, 0.598633f, 0.624023f, 0.645508f, 0.666016f, 0.684082f, 0.702637f, 0.720703f, 0.736816f, + 0.751465f, 0.766113f, 0.779785f, 0.792969f, 0.804199f, 0.815918f, 0.826660f, 0.836426f, 0.846191f, 0.855957f, 0.864746f, 0.872559f, + 0.880371f, 0.888184f, 0.895508f, 0.902344f, 0.908691f, 0.914062f, 0.919922f, 0.925293f, 0.932129f, 0.936035f, 0.941895f, 0.946289f, + 0.951172f, 0.955566f, 0.959473f, 0.963867f, 0.967773f, 0.970703f, 0.975586f, 0.978516f, 0.981934f, 0.985352f, 0.991699f, 0.988770f, + 0.986328f, 0.983887f, 0.981445f, 0.979004f, 0.015175f, 0.046997f, 0.080688f, 0.116028f, 0.152466f, 0.189819f, 0.227417f, 0.264404f, + 0.301758f, 0.338623f, 0.374268f, 0.407471f, 0.439941f, 0.471924f, 0.501465f, 0.529785f, 0.556641f, 0.582031f, 0.606445f, 0.629395f, + 0.649902f, 0.670898f, 0.688965f, 0.708496f, 0.725098f, 0.740723f, 0.755371f, 0.769531f, 0.782715f, 0.795410f, 0.807129f, 0.818848f, + 0.829590f, 0.839844f, 0.849121f, 0.857910f, 0.866699f, 0.875488f, 0.882812f, 0.890625f, 0.897461f, 0.904297f, 0.910645f, 0.916992f, + 0.922363f, 0.928223f, 0.933594f, 0.938477f, 0.944824f, 0.949707f, 0.953613f, 0.958008f, 0.962402f, 0.966309f, 0.970703f, 0.974121f, + 0.977539f, 0.981934f, 0.990234f, 0.987793f, 0.984863f, 0.982910f, 0.980469f, 0.978516f, 0.012215f, 0.038452f, 0.066101f, 0.095825f, + 0.126831f, 0.159180f, 0.192749f, 0.226685f, 0.260986f, 0.294922f, 0.328857f, 0.363037f, 0.394531f, 0.426270f, 0.457520f, 0.486572f, + 0.514648f, 0.541016f, 0.567871f, 0.590820f, 0.614746f, 0.636230f, 0.657227f, 0.676270f, 0.694336f, 0.711914f, 0.729492f, 0.744141f, + 0.759277f, 0.773438f, 0.786621f, 0.798340f, 0.811523f, 0.822266f, 0.833496f, 0.842773f, 0.851562f, 0.861816f, 0.869629f, 0.878418f, + 0.885742f, 0.893066f, 0.900879f, 0.907715f, 0.913574f, 0.919922f, 0.925781f, 0.932129f, 0.937012f, 0.942871f, 0.946777f, 0.951660f, + 0.957031f, 0.960938f, 0.965332f, 0.969727f, 0.973633f, 0.977051f, 0.988281f, 0.986328f, 0.983887f, 0.981445f, 0.979492f, 0.976562f, + 0.009903f, 0.031525f, 0.054626f, 0.078979f, 0.105408f, 0.133789f, 0.162720f, 0.192993f, 0.224976f, 0.256592f, 0.288330f, 0.320312f, + 0.352295f, 0.383545f, 0.414062f, 0.443848f, 0.473389f, 0.500488f, 0.526367f, 0.553223f, 0.577637f, 0.600586f, 0.622070f, 0.644043f, + 0.664551f, 0.683105f, 0.701660f, 0.718262f, 0.734375f, 0.750000f, 0.764648f, 0.778320f, 0.791016f, 0.802734f, 0.815430f, 0.826172f, + 0.836426f, 0.845703f, 0.855957f, 0.864258f, 0.874023f, 0.881348f, 0.889648f, 0.896973f, 0.904297f, 0.911621f, 0.917480f, 0.922852f, + 0.929199f, 0.935059f, 0.939941f, 0.944824f, 0.950195f, 0.954590f, 0.959961f, 0.964355f, 0.968262f, 0.972656f, 0.986328f, 0.984375f, + 0.981934f, 0.979980f, 0.978027f, 0.975586f, 0.008385f, 0.026154f, 0.045319f, 0.066467f, 0.089111f, 0.113220f, 0.138916f, 0.165405f, + 0.192871f, 0.222290f, 0.252197f, 0.281494f, 0.311279f, 0.342285f, 0.372314f, 0.402832f, 0.431641f, 0.459473f, 0.486572f, 0.513672f, + 0.539062f, 0.562988f, 0.587402f, 0.609863f, 0.631348f, 0.652344f, 0.671875f, 0.689941f, 0.708008f, 0.724609f, 0.740234f, 0.755371f, + 0.768066f, 0.783203f, 0.795410f, 0.808105f, 0.819336f, 0.830078f, 0.840332f, 0.851074f, 0.860352f, 0.869141f, 0.877930f, 0.885742f, + 0.893555f, 0.900879f, 0.907715f, 0.915039f, 0.920410f, 0.926758f, 0.933105f, 0.938965f, 0.944336f, 0.949707f, 0.953613f, 0.958984f, + 0.962891f, 0.967285f, 0.984375f, 0.982910f, 0.980957f, 0.978516f, 0.976562f, 0.974609f, 0.006992f, 0.022324f, 0.038544f, 0.056396f, + 0.075317f, 0.095947f, 0.117981f, 0.141968f, 0.166504f, 0.192627f, 0.219238f, 0.246704f, 0.275879f, 0.304443f, 0.333252f, 0.362305f, + 0.390869f, 0.419678f, 0.447266f, 0.474121f, 0.500977f, 0.525879f, 0.551270f, 0.574219f, 0.597656f, 0.620117f, 0.641602f, 0.661133f, + 0.680664f, 0.698242f, 0.715332f, 0.731934f, 0.746582f, 0.761230f, 0.775391f, 0.789551f, 0.802246f, 0.813477f, 0.825195f, 0.835938f, + 0.846191f, 0.855957f, 0.865723f, 0.873535f, 0.882324f, 0.890625f, 0.898438f, 0.905762f, 0.912598f, 0.918945f, 0.925781f, 0.931641f, + 0.937012f, 0.943848f, 0.948730f, 0.954102f, 0.957520f, 0.963379f, 0.981934f, 0.980957f, 0.979004f, 0.977051f, 0.975098f, 0.973145f, + 0.006260f, 0.018387f, 0.032684f, 0.047821f, 0.064636f, 0.082153f, 0.101318f, 0.122009f, 0.143921f, 0.166870f, 0.191406f, 0.216187f, + 0.243164f, 0.269287f, 0.297119f, 0.324951f, 0.352783f, 0.380859f, 0.408691f, 0.435547f, 0.462402f, 0.489258f, 0.514160f, 0.540039f, + 0.563965f, 0.585938f, 0.608398f, 0.629395f, 0.649414f, 0.669434f, 0.689453f, 0.705566f, 0.722656f, 0.739258f, 0.753418f, 0.769043f, + 0.783203f, 0.795898f, 0.807617f, 0.819824f, 0.830566f, 0.842285f, 0.852051f, 0.862305f, 0.871094f, 0.878906f, 0.888184f, 0.895996f, + 0.902832f, 0.910645f, 0.917480f, 0.924316f, 0.930176f, 0.936523f, 0.942383f, 0.946777f, 0.953613f, 0.958496f, 0.979980f, 0.979004f, + 0.977539f, 0.975586f, 0.973633f, 0.972168f, 0.005268f, 0.016418f, 0.028091f, 0.041107f, 0.055420f, 0.070435f, 0.087341f, 0.105347f, + 0.124512f, 0.144531f, 0.166260f, 0.189453f, 0.213989f, 0.238037f, 0.263184f, 0.290039f, 0.317139f, 0.344238f, 0.370850f, 0.398438f, + 0.425293f, 0.451660f, 0.477539f, 0.503418f, 0.528320f, 0.551270f, 0.576172f, 0.598145f, 0.619629f, 0.640137f, 0.659668f, 0.680176f, + 0.697754f, 0.714844f, 0.731934f, 0.748047f, 0.762695f, 0.776367f, 0.790039f, 0.803223f, 0.814453f, 0.827148f, 0.837891f, 0.847656f, + 0.858398f, 0.868164f, 0.876953f, 0.885742f, 0.893066f, 0.901855f, 0.908691f, 0.916504f, 0.922852f, 0.929199f, 0.935059f, 0.941895f, + 0.947754f, 0.953125f, 0.978027f, 0.977539f, 0.975586f, 0.973633f, 0.971680f, 0.969727f, 0.004372f, 0.013802f, 0.024185f, 0.036011f, + 0.047729f, 0.060944f, 0.075684f, 0.090820f, 0.107788f, 0.125488f, 0.144653f, 0.165771f, 0.187012f, 0.210205f, 0.233643f, 0.258545f, + 0.283447f, 0.309326f, 0.335449f, 0.362305f, 0.388672f, 0.415771f, 0.441650f, 0.468018f, 0.492920f, 0.518066f, 0.542480f, 0.564941f, + 0.587891f, 0.609863f, 0.630859f, 0.651855f, 0.670898f, 0.689453f, 0.707520f, 0.724609f, 0.740723f, 0.755859f, 0.770996f, 0.785156f, + 0.799316f, 0.809570f, 0.822754f, 0.834473f, 0.845215f, 0.855469f, 0.865723f, 0.874023f, 0.883301f, 0.892090f, 0.899902f, 0.907715f, + 0.915039f, 0.922363f, 0.928711f, 0.935059f, 0.941406f, 0.947266f, 0.975586f, 0.975098f, 0.973633f, 0.971680f, 0.969727f, 0.968262f, + 0.003809f, 0.012253f, 0.021240f, 0.030884f, 0.041473f, 0.052887f, 0.065308f, 0.079224f, 0.094177f, 0.109558f, 0.126709f, 0.145142f, + 0.163940f, 0.184814f, 0.207397f, 0.229736f, 0.252686f, 0.276855f, 0.302246f, 0.327881f, 0.353271f, 0.380127f, 0.405762f, 0.432129f, + 0.457520f, 0.482422f, 0.507324f, 0.531250f, 0.556152f, 0.578125f, 0.600586f, 0.622559f, 0.642578f, 0.662109f, 0.681641f, 0.700195f, + 0.716797f, 0.734375f, 0.750000f, 0.766113f, 0.779297f, 0.793457f, 0.807129f, 0.819336f, 0.830078f, 0.842285f, 0.853027f, 0.862793f, + 0.872559f, 0.881348f, 0.890625f, 0.899414f, 0.907227f, 0.914551f, 0.920898f, 0.928223f, 0.935059f, 0.941406f, 0.973633f, 0.973145f, + 0.971680f, 0.970215f, 0.968262f, 0.966797f, 0.003462f, 0.010796f, 0.018646f, 0.026962f, 0.036377f, 0.046173f, 0.057190f, 0.068665f, + 0.081726f, 0.095520f, 0.110962f, 0.127563f, 0.144897f, 0.162476f, 0.182373f, 0.202881f, 0.225342f, 0.248291f, 0.271729f, 0.294922f, + 0.320312f, 0.345459f, 0.370850f, 0.397217f, 0.422607f, 0.447998f, 0.473145f, 0.498291f, 0.522461f, 0.546875f, 0.569824f, 0.591797f, + 0.614258f, 0.635742f, 0.655273f, 0.674805f, 0.693359f, 0.711426f, 0.729492f, 0.745605f, 0.760742f, 0.775391f, 0.789551f, 0.803223f, + 0.816406f, 0.828125f, 0.839844f, 0.850586f, 0.861328f, 0.871094f, 0.880371f, 0.889648f, 0.898438f, 0.906250f, 0.915039f, 0.921875f, + 0.928223f, 0.935547f, 0.970703f, 0.970215f, 0.970215f, 0.967773f, 0.966309f, 0.965332f, 0.002872f, 0.009338f, 0.016174f, 0.024231f, + 0.031525f, 0.040558f, 0.050140f, 0.060455f, 0.071472f, 0.084167f, 0.097168f, 0.111450f, 0.127197f, 0.143433f, 0.160889f, 0.179565f, + 0.199463f, 0.220825f, 0.242554f, 0.265625f, 0.288818f, 0.312744f, 0.338135f, 0.362793f, 0.387939f, 0.414307f, 0.439453f, 0.464355f, + 0.489014f, 0.514648f, 0.537598f, 0.561523f, 0.583984f, 0.606445f, 0.627930f, 0.648926f, 0.667480f, 0.687988f, 0.705566f, 0.723633f, + 0.740234f, 0.756348f, 0.771484f, 0.786621f, 0.799805f, 0.812012f, 0.825195f, 0.836426f, 0.849121f, 0.859375f, 0.870605f, 0.879883f, + 0.888672f, 0.897461f, 0.905762f, 0.915039f, 0.921387f, 0.928711f, 0.967773f, 0.969238f, 0.966797f, 0.966797f, 0.964355f, 0.963379f, + 0.002750f, 0.008202f, 0.014519f, 0.021301f, 0.028183f, 0.035828f, 0.044342f, 0.053375f, 0.063354f, 0.074219f, 0.085876f, 0.098083f, + 0.111938f, 0.126343f, 0.142212f, 0.158936f, 0.177124f, 0.196411f, 0.216553f, 0.237427f, 0.260010f, 0.282715f, 0.306641f, 0.330811f, + 0.355957f, 0.381104f, 0.405518f, 0.431152f, 0.456543f, 0.480957f, 0.504883f, 0.529785f, 0.553223f, 0.577148f, 0.599121f, 0.620605f, + 0.642090f, 0.662598f, 0.682617f, 0.701172f, 0.718750f, 0.735352f, 0.751953f, 0.768066f, 0.783691f, 0.796875f, 0.810547f, 0.822754f, + 0.835938f, 0.847656f, 0.858398f, 0.869141f, 0.879395f, 0.888672f, 0.897949f, 0.906250f, 0.914551f, 0.922363f, 0.965820f, 0.966797f, + 0.965820f, 0.963867f, 0.963379f, 0.961426f, 0.002264f, 0.007446f, 0.012741f, 0.018494f, 0.024536f, 0.031769f, 0.039154f, 0.047424f, + 0.056122f, 0.065308f, 0.075623f, 0.087219f, 0.098755f, 0.111328f, 0.125854f, 0.140869f, 0.157349f, 0.174805f, 0.193115f, 0.212402f, + 0.233643f, 0.254883f, 0.276855f, 0.300293f, 0.324463f, 0.348389f, 0.374023f, 0.398193f, 0.423340f, 0.448242f, 0.473877f, 0.498291f, + 0.521973f, 0.545898f, 0.569824f, 0.592773f, 0.614258f, 0.635742f, 0.657227f, 0.676270f, 0.695801f, 0.714844f, 0.731445f, 0.749512f, + 0.765137f, 0.779785f, 0.793945f, 0.808594f, 0.821777f, 0.833496f, 0.846191f, 0.858398f, 0.868652f, 0.879395f, 0.888672f, 0.897949f, + 0.906738f, 0.916016f, 0.962402f, 0.963867f, 0.962891f, 0.961914f, 0.960938f, 0.958984f, 0.002377f, 0.006668f, 0.011467f, 0.016693f, + 0.021820f, 0.028091f, 0.034485f, 0.041748f, 0.049347f, 0.057678f, 0.066589f, 0.076538f, 0.086975f, 0.098816f, 0.111816f, 0.125366f, + 0.139404f, 0.155151f, 0.171875f, 0.190186f, 0.208496f, 0.228760f, 0.250244f, 0.271973f, 0.294189f, 0.317871f, 0.341797f, 0.365479f, + 0.391357f, 0.415771f, 0.440430f, 0.466797f, 0.491699f, 0.515625f, 0.539551f, 0.563477f, 0.585938f, 0.608887f, 0.630371f, 0.651855f, + 0.672363f, 0.692383f, 0.710449f, 0.729492f, 0.745605f, 0.762695f, 0.778320f, 0.792480f, 0.807129f, 0.820801f, 0.833984f, 0.846680f, + 0.857910f, 0.869141f, 0.879395f, 0.889648f, 0.899414f, 0.907715f, 0.959473f, 0.961426f, 0.960449f, 0.959961f, 0.958496f, 0.957031f, + 0.002062f, 0.006180f, 0.010201f, 0.015053f, 0.019531f, 0.025116f, 0.030960f, 0.037292f, 0.043915f, 0.051117f, 0.059570f, 0.067749f, + 0.076843f, 0.087708f, 0.099060f, 0.110352f, 0.123413f, 0.138062f, 0.153198f, 0.169067f, 0.186768f, 0.204956f, 0.224487f, 0.244873f, + 0.265625f, 0.288330f, 0.311768f, 0.335205f, 0.359863f, 0.384521f, 0.409668f, 0.434082f, 0.459717f, 0.483887f, 0.508789f, 0.533203f, + 0.557617f, 0.580566f, 0.603516f, 0.626465f, 0.646484f, 0.667969f, 0.687500f, 0.708008f, 0.726074f, 0.744141f, 0.760742f, 0.776367f, + 0.791504f, 0.806641f, 0.820312f, 0.833496f, 0.846191f, 0.858398f, 0.869629f, 0.879883f, 0.890625f, 0.900879f, 0.956543f, 0.958496f, + 0.958008f, 0.956543f, 0.955566f, 0.954102f, 0.001774f, 0.005459f, 0.009155f, 0.013290f, 0.017807f, 0.022537f, 0.027527f, 0.033081f, + 0.038818f, 0.045380f, 0.052643f, 0.060516f, 0.068420f, 0.077942f, 0.087952f, 0.098572f, 0.109863f, 0.122925f, 0.136230f, 0.150146f, + 0.166382f, 0.183105f, 0.201172f, 0.219482f, 0.240112f, 0.261230f, 0.283203f, 0.305664f, 0.329590f, 0.353027f, 0.377930f, 0.402344f, + 0.427490f, 0.453369f, 0.478516f, 0.502930f, 0.527832f, 0.552246f, 0.575684f, 0.598145f, 0.621094f, 0.643555f, 0.664551f, 0.685547f, + 0.704590f, 0.723633f, 0.742188f, 0.759277f, 0.775879f, 0.791016f, 0.806152f, 0.820801f, 0.833496f, 0.847168f, 0.859375f, 0.870605f, + 0.881348f, 0.893066f, 0.953125f, 0.956055f, 0.955566f, 0.954102f, 0.953125f, 0.951660f, 0.001655f, 0.004757f, 0.008308f, 0.011993f, + 0.015808f, 0.020187f, 0.024780f, 0.029434f, 0.034851f, 0.040741f, 0.046997f, 0.053650f, 0.061096f, 0.069397f, 0.078064f, 0.087280f, + 0.097351f, 0.108887f, 0.121033f, 0.134277f, 0.148560f, 0.163330f, 0.180054f, 0.197144f, 0.215332f, 0.235718f, 0.255859f, 0.277588f, + 0.300049f, 0.323730f, 0.347656f, 0.371826f, 0.396729f, 0.422607f, 0.447021f, 0.472168f, 0.497803f, 0.521973f, 0.547363f, 0.571289f, + 0.594238f, 0.618164f, 0.640137f, 0.662109f, 0.682617f, 0.702637f, 0.722168f, 0.739746f, 0.758301f, 0.774902f, 0.790527f, 0.806641f, + 0.820801f, 0.834961f, 0.848633f, 0.860352f, 0.872559f, 0.883789f, 0.949707f, 0.953125f, 0.952148f, 0.951172f, 0.950684f, 0.948730f, + 0.001418f, 0.004456f, 0.007584f, 0.010803f, 0.014450f, 0.018005f, 0.022186f, 0.026398f, 0.031342f, 0.036224f, 0.041687f, 0.048126f, + 0.054382f, 0.061676f, 0.069641f, 0.077759f, 0.086914f, 0.097168f, 0.107910f, 0.119263f, 0.132446f, 0.145752f, 0.161011f, 0.176758f, + 0.193726f, 0.211914f, 0.231201f, 0.251709f, 0.272705f, 0.294922f, 0.318604f, 0.342041f, 0.366455f, 0.390869f, 0.416992f, 0.441895f, + 0.467285f, 0.493164f, 0.517578f, 0.541992f, 0.566895f, 0.590820f, 0.614746f, 0.637207f, 0.660156f, 0.681152f, 0.701172f, 0.720703f, + 0.739746f, 0.758301f, 0.775391f, 0.791992f, 0.807617f, 0.821289f, 0.836426f, 0.850586f, 0.863281f, 0.874512f, 0.946777f, 0.949707f, + 0.949707f, 0.948730f, 0.947266f, 0.946289f, 0.001213f, 0.003864f, 0.006721f, 0.009796f, 0.012932f, 0.016037f, 0.020218f, 0.024231f, + 0.028275f, 0.032379f, 0.037567f, 0.042603f, 0.048584f, 0.054993f, 0.061798f, 0.069519f, 0.077637f, 0.086182f, 0.095703f, 0.106323f, + 0.117676f, 0.130127f, 0.143555f, 0.158203f, 0.173462f, 0.189941f, 0.207886f, 0.226807f, 0.247192f, 0.267822f, 0.290527f, 0.312500f, + 0.336670f, 0.360352f, 0.385742f, 0.410889f, 0.437256f, 0.462646f, 0.488281f, 0.513184f, 0.539062f, 0.563477f, 0.588379f, 0.612305f, + 0.636230f, 0.657715f, 0.679199f, 0.700195f, 0.720703f, 0.740234f, 0.758301f, 0.775879f, 0.793945f, 0.809082f, 0.824219f, 0.838867f, + 0.852539f, 0.865234f, 0.942871f, 0.946777f, 0.946777f, 0.945312f, 0.944824f, 0.943359f, 0.001063f, 0.003754f, 0.005909f, 0.008789f, + 0.011780f, 0.014671f, 0.017792f, 0.021378f, 0.025238f, 0.029221f, 0.033417f, 0.038300f, 0.043488f, 0.048828f, 0.054779f, 0.061554f, + 0.068604f, 0.076721f, 0.085388f, 0.094482f, 0.104614f, 0.115845f, 0.128296f, 0.141113f, 0.155029f, 0.170044f, 0.186401f, 0.204224f, + 0.222778f, 0.242188f, 0.263916f, 0.285156f, 0.308350f, 0.331787f, 0.355957f, 0.381348f, 0.407227f, 0.432617f, 0.459229f, 0.484619f, + 0.509277f, 0.536133f, 0.560547f, 0.585938f, 0.609863f, 0.633301f, 0.657715f, 0.678711f, 0.699707f, 0.721191f, 0.740723f, 0.759277f, + 0.777344f, 0.794922f, 0.811035f, 0.826660f, 0.841797f, 0.855469f, 0.939453f, 0.943359f, 0.943359f, 0.942871f, 0.941895f, 0.940918f, + 0.001175f, 0.003069f, 0.005558f, 0.007912f, 0.010712f, 0.013199f, 0.016235f, 0.019547f, 0.022659f, 0.026138f, 0.030151f, 0.034424f, + 0.038940f, 0.044067f, 0.049255f, 0.054993f, 0.061493f, 0.068359f, 0.075928f, 0.084290f, 0.093262f, 0.103760f, 0.114319f, 0.126099f, + 0.138550f, 0.152466f, 0.167114f, 0.183472f, 0.200439f, 0.219238f, 0.239014f, 0.259277f, 0.281250f, 0.303711f, 0.327148f, 0.351807f, + 0.376709f, 0.402344f, 0.428955f, 0.453857f, 0.480713f, 0.507324f, 0.533203f, 0.558594f, 0.583984f, 0.609375f, 0.633301f, 0.656738f, + 0.678711f, 0.700195f, 0.722168f, 0.742188f, 0.761719f, 0.780273f, 0.797852f, 0.813477f, 0.830078f, 0.845703f, 0.935547f, 0.939453f, + 0.939453f, 0.938965f, 0.937988f, 0.937012f, 0.001089f, 0.002945f, 0.005066f, 0.007225f, 0.009575f, 0.012016f, 0.014656f, 0.017288f, + 0.020142f, 0.023712f, 0.026764f, 0.030640f, 0.034637f, 0.039490f, 0.043854f, 0.048706f, 0.054688f, 0.060913f, 0.067871f, 0.075256f, + 0.083191f, 0.092163f, 0.101868f, 0.111938f, 0.123657f, 0.136108f, 0.149658f, 0.164185f, 0.179932f, 0.196777f, 0.215454f, 0.234375f, + 0.255371f, 0.276611f, 0.299805f, 0.323486f, 0.347656f, 0.373047f, 0.398682f, 0.425293f, 0.451172f, 0.477783f, 0.504883f, 0.530762f, + 0.557617f, 0.583008f, 0.607910f, 0.632812f, 0.657227f, 0.680664f, 0.702637f, 0.724121f, 0.743652f, 0.764160f, 0.783691f, 0.800781f, + 0.818848f, 0.833984f, 0.930664f, 0.936035f, 0.936035f, 0.935547f, 0.934570f, 0.933594f, 0.000847f, 0.002800f, 0.004562f, 0.006786f, + 0.008804f, 0.011017f, 0.013145f, 0.015640f, 0.018509f, 0.021255f, 0.024277f, 0.027603f, 0.030991f, 0.035248f, 0.039642f, 0.043854f, + 0.048798f, 0.054504f, 0.060516f, 0.067017f, 0.073914f, 0.082092f, 0.090515f, 0.099854f, 0.109863f, 0.121521f, 0.133545f, 0.146851f, + 0.161133f, 0.176514f, 0.192993f, 0.211426f, 0.230957f, 0.251465f, 0.272705f, 0.295410f, 0.319092f, 0.343994f, 0.369385f, 0.395020f, + 0.421631f, 0.448242f, 0.475342f, 0.501953f, 0.529785f, 0.556152f, 0.582031f, 0.608887f, 0.633789f, 0.658203f, 0.681152f, 0.704590f, + 0.726074f, 0.748535f, 0.768555f, 0.787109f, 0.804199f, 0.822754f, 0.926758f, 0.931641f, 0.932129f, 0.931641f, 0.931152f, 0.930176f, + 0.001035f, 0.002598f, 0.004147f, 0.006062f, 0.007942f, 0.009933f, 0.012405f, 0.014565f, 0.016174f, 0.019135f, 0.021988f, 0.024811f, + 0.028259f, 0.031616f, 0.035065f, 0.039429f, 0.043884f, 0.048615f, 0.053833f, 0.059723f, 0.065796f, 0.072693f, 0.080383f, 0.088745f, + 0.098206f, 0.107727f, 0.119080f, 0.130981f, 0.143677f, 0.157959f, 0.173218f, 0.189941f, 0.207642f, 0.226929f, 0.247437f, 0.269043f, + 0.291748f, 0.315674f, 0.340576f, 0.366211f, 0.392578f, 0.419434f, 0.446533f, 0.473877f, 0.502441f, 0.528320f, 0.556152f, 0.583008f, + 0.609375f, 0.635254f, 0.660156f, 0.684082f, 0.706543f, 0.729980f, 0.751953f, 0.771973f, 0.792480f, 0.810547f, 0.922363f, 0.927734f, + 0.928223f, 0.928223f, 0.927246f, 0.926758f, 0.000775f, 0.002325f, 0.003843f, 0.005573f, 0.007397f, 0.009163f, 0.010857f, 0.012939f, + 0.015312f, 0.017273f, 0.019684f, 0.022537f, 0.025070f, 0.028183f, 0.031616f, 0.035461f, 0.038940f, 0.043671f, 0.048096f, 0.053131f, + 0.058411f, 0.064941f, 0.071777f, 0.078857f, 0.086731f, 0.096130f, 0.105835f, 0.116760f, 0.128296f, 0.140747f, 0.154907f, 0.170410f, + 0.186646f, 0.204834f, 0.223633f, 0.243896f, 0.265625f, 0.288330f, 0.312012f, 0.337402f, 0.363037f, 0.389648f, 0.417480f, 0.444824f, + 0.473633f, 0.500000f, 0.529297f, 0.556641f, 0.583984f, 0.610840f, 0.638184f, 0.662598f, 0.687988f, 0.711914f, 0.734375f, 0.755859f, + 0.777832f, 0.798828f, 0.916992f, 0.922852f, 0.923828f, 0.923828f, 0.923340f, 0.922363f, 0.000617f, 0.002234f, 0.003510f, 0.005035f, + 0.006397f, 0.008156f, 0.010033f, 0.011665f, 0.013481f, 0.015717f, 0.017700f, 0.020004f, 0.022766f, 0.025391f, 0.028214f, 0.031586f, + 0.035217f, 0.038757f, 0.042999f, 0.047668f, 0.052368f, 0.057434f, 0.063538f, 0.070190f, 0.077698f, 0.085449f, 0.094299f, 0.103394f, + 0.113953f, 0.125610f, 0.137817f, 0.151855f, 0.167236f, 0.183228f, 0.200806f, 0.219971f, 0.240479f, 0.262451f, 0.285645f, 0.309570f, + 0.334961f, 0.360596f, 0.387939f, 0.416016f, 0.444092f, 0.473145f, 0.501465f, 0.529785f, 0.558105f, 0.585938f, 0.614258f, 0.640137f, + 0.666992f, 0.692383f, 0.716797f, 0.739746f, 0.763184f, 0.784180f, 0.912109f, 0.918457f, 0.919434f, 0.919434f, 0.918457f, 0.917969f, + 0.000665f, 0.002039f, 0.003386f, 0.004520f, 0.005989f, 0.007511f, 0.009262f, 0.010902f, 0.012314f, 0.014320f, 0.015869f, 0.018127f, + 0.020248f, 0.022476f, 0.025284f, 0.028122f, 0.030991f, 0.034668f, 0.038239f, 0.042206f, 0.046539f, 0.051361f, 0.056610f, 0.062347f, + 0.068604f, 0.075623f, 0.083313f, 0.092041f, 0.101379f, 0.111572f, 0.122986f, 0.135132f, 0.148926f, 0.164062f, 0.180054f, 0.197510f, + 0.216797f, 0.237183f, 0.259521f, 0.282227f, 0.307129f, 0.332764f, 0.358887f, 0.386475f, 0.415527f, 0.443604f, 0.473389f, 0.501465f, + 0.530762f, 0.560059f, 0.588867f, 0.617676f, 0.645020f, 0.671387f, 0.698242f, 0.722656f, 0.746094f, 0.770020f, 0.906738f, 0.913574f, + 0.915039f, 0.914551f, 0.914062f, 0.914062f, 0.000661f, 0.001754f, 0.002831f, 0.004066f, 0.005333f, 0.006668f, 0.008286f, 0.009773f, + 0.011124f, 0.012794f, 0.014320f, 0.016357f, 0.018036f, 0.020386f, 0.022766f, 0.025192f, 0.027924f, 0.030807f, 0.034027f, 0.037628f, + 0.041321f, 0.045349f, 0.050262f, 0.055328f, 0.060699f, 0.066833f, 0.073669f, 0.081360f, 0.089600f, 0.099060f, 0.108826f, 0.119995f, + 0.132324f, 0.145874f, 0.160889f, 0.176880f, 0.194702f, 0.213379f, 0.234497f, 0.256104f, 0.280029f, 0.304688f, 0.330811f, 0.358154f, + 0.385986f, 0.415039f, 0.444092f, 0.474609f, 0.503418f, 0.534180f, 0.563965f, 0.592773f, 0.621094f, 0.650391f, 0.678223f, 0.704590f, + 0.730469f, 0.754883f, 0.901855f, 0.908691f, 0.910156f, 0.909668f, 0.909668f, 0.908691f, 0.000653f, 0.001667f, 0.002666f, 0.003887f, + 0.004986f, 0.006359f, 0.007202f, 0.008751f, 0.010300f, 0.011757f, 0.012939f, 0.014595f, 0.016281f, 0.018234f, 0.020142f, 0.022415f, + 0.025101f, 0.027466f, 0.030182f, 0.033539f, 0.036865f, 0.040680f, 0.044342f, 0.048798f, 0.053619f, 0.059479f, 0.065491f, 0.071716f, + 0.079285f, 0.087341f, 0.096497f, 0.106445f, 0.117615f, 0.129395f, 0.142822f, 0.157959f, 0.174194f, 0.192139f, 0.210938f, 0.231567f, + 0.253906f, 0.277832f, 0.302979f, 0.329590f, 0.357422f, 0.385986f, 0.415283f, 0.446045f, 0.475830f, 0.506348f, 0.537109f, 0.567871f, + 0.599121f, 0.628418f, 0.657227f, 0.685547f, 0.712891f, 0.739746f, 0.895508f, 0.902344f, 0.904297f, 0.904785f, 0.904297f, 0.904297f, + 0.000372f, 0.001397f, 0.002384f, 0.003529f, 0.004509f, 0.005505f, 0.007015f, 0.008026f, 0.009201f, 0.010292f, 0.011536f, 0.013130f, + 0.014915f, 0.016266f, 0.018387f, 0.020218f, 0.022034f, 0.024399f, 0.026901f, 0.029617f, 0.032623f, 0.035950f, 0.039032f, 0.043030f, + 0.047577f, 0.052612f, 0.057556f, 0.063477f, 0.070007f, 0.077209f, 0.085083f, 0.094177f, 0.103821f, 0.114563f, 0.126709f, 0.140015f, + 0.154785f, 0.171143f, 0.188477f, 0.208252f, 0.229004f, 0.251709f, 0.275879f, 0.302002f, 0.328613f, 0.356445f, 0.385986f, 0.416504f, + 0.447510f, 0.478760f, 0.510254f, 0.542480f, 0.573730f, 0.604980f, 0.635742f, 0.665527f, 0.694336f, 0.722656f, 0.887695f, 0.897949f, + 0.898926f, 0.899414f, 0.897949f, 0.898438f, 0.000661f, 0.001222f, 0.002275f, 0.003313f, 0.004181f, 0.005119f, 0.006275f, 0.007126f, + 0.007988f, 0.009354f, 0.010300f, 0.012062f, 0.013313f, 0.014786f, 0.016251f, 0.018021f, 0.019516f, 0.021896f, 0.024017f, 0.026428f, + 0.029022f, 0.031799f, 0.034698f, 0.038422f, 0.042236f, 0.046265f, 0.050598f, 0.055786f, 0.061493f, 0.067871f, 0.074951f, 0.082458f, + 0.091187f, 0.101135f, 0.111694f, 0.123779f, 0.137207f, 0.151978f, 0.167969f, 0.186157f, 0.205688f, 0.226929f, 0.249756f, 0.274658f, + 0.301025f, 0.328613f, 0.357178f, 0.387207f, 0.418457f, 0.450195f, 0.482422f, 0.516113f, 0.548340f, 0.580566f, 0.612305f, 0.644043f, + 0.674805f, 0.705566f, 0.882812f, 0.890625f, 0.892578f, 0.893066f, 0.892578f, 0.893066f, 0.000379f, 0.001211f, 0.002066f, 0.003040f, + 0.003834f, 0.004616f, 0.005608f, 0.006550f, 0.007347f, 0.008408f, 0.009529f, 0.010452f, 0.011940f, 0.013039f, 0.014313f, 0.015961f, + 0.017746f, 0.019180f, 0.021210f, 0.023239f, 0.025482f, 0.028030f, 0.030640f, 0.033661f, 0.036987f, 0.040466f, 0.044617f, 0.048828f, + 0.053894f, 0.059235f, 0.065674f, 0.072632f, 0.079956f, 0.089050f, 0.098267f, 0.109009f, 0.120789f, 0.134521f, 0.148926f, 0.165405f, + 0.183228f, 0.202881f, 0.224731f, 0.248779f, 0.273193f, 0.300049f, 0.329346f, 0.358887f, 0.390381f, 0.421387f, 0.454590f, 0.488770f, + 0.521484f, 0.555176f, 0.588379f, 0.621582f, 0.654785f, 0.686523f, 0.875488f, 0.885254f, 0.886719f, 0.886230f, 0.886719f, 0.886230f, + 0.000282f, 0.001126f, 0.002010f, 0.002661f, 0.003340f, 0.004269f, 0.005192f, 0.005711f, 0.006638f, 0.007278f, 0.008377f, 0.009483f, + 0.010567f, 0.011742f, 0.012871f, 0.014061f, 0.015480f, 0.017242f, 0.018799f, 0.020584f, 0.022461f, 0.024490f, 0.027100f, 0.029434f, + 0.032532f, 0.035706f, 0.038971f, 0.042969f, 0.047241f, 0.052094f, 0.057373f, 0.063232f, 0.070007f, 0.077637f, 0.086243f, 0.095764f, + 0.106323f, 0.118164f, 0.131470f, 0.146118f, 0.162720f, 0.181030f, 0.200928f, 0.223022f, 0.247070f, 0.272705f, 0.300537f, 0.330322f, + 0.360107f, 0.393066f, 0.426270f, 0.459473f, 0.494629f, 0.529297f, 0.564453f, 0.598633f, 0.633789f, 0.666504f, 0.868652f, 0.878418f, + 0.879395f, 0.880371f, 0.879883f, 0.879395f, 0.000340f, 0.000963f, 0.001826f, 0.002459f, 0.003307f, 0.003847f, 0.004719f, 0.004936f, + 0.005802f, 0.006695f, 0.007748f, 0.008522f, 0.009506f, 0.010376f, 0.011383f, 0.012787f, 0.013901f, 0.015182f, 0.016663f, 0.018051f, + 0.019821f, 0.021759f, 0.023590f, 0.025818f, 0.028519f, 0.030975f, 0.034210f, 0.037811f, 0.040802f, 0.045349f, 0.050201f, 0.055298f, + 0.061310f, 0.067688f, 0.074768f, 0.083557f, 0.092590f, 0.103149f, 0.115479f, 0.128906f, 0.142944f, 0.160278f, 0.178345f, 0.198975f, + 0.221802f, 0.246094f, 0.272949f, 0.301514f, 0.331543f, 0.363525f, 0.396729f, 0.430908f, 0.466553f, 0.501953f, 0.538086f, 0.574707f, + 0.610840f, 0.646973f, 0.860352f, 0.870605f, 0.873047f, 0.873047f, 0.873535f, 0.872559f, 0.000225f, 0.001021f, 0.001653f, 0.002302f, + 0.002827f, 0.003448f, 0.003937f, 0.004486f, 0.004986f, 0.006252f, 0.007000f, 0.007416f, 0.008224f, 0.009300f, 0.009972f, 0.011322f, + 0.012115f, 0.013428f, 0.014557f, 0.015991f, 0.017532f, 0.018982f, 0.020706f, 0.022781f, 0.024567f, 0.027161f, 0.029770f, 0.032623f, + 0.035828f, 0.039551f, 0.043030f, 0.047852f, 0.052795f, 0.058716f, 0.065125f, 0.072266f, 0.080566f, 0.089661f, 0.100403f, 0.112854f, + 0.125732f, 0.140991f, 0.157349f, 0.176514f, 0.197510f, 0.220581f, 0.245850f, 0.273438f, 0.302979f, 0.334717f, 0.367676f, 0.401855f, + 0.437256f, 0.474609f, 0.512695f, 0.549316f, 0.588379f, 0.625000f, 0.853027f, 0.863281f, 0.866211f, 0.866211f, 0.866699f, 0.866211f, + 0.000324f, 0.000845f, 0.001534f, 0.002172f, 0.002474f, 0.003115f, 0.003824f, 0.003937f, 0.004848f, 0.005417f, 0.006222f, 0.006760f, + 0.007446f, 0.008186f, 0.009102f, 0.009888f, 0.010620f, 0.011551f, 0.012878f, 0.013954f, 0.015106f, 0.016495f, 0.018143f, 0.019669f, + 0.021713f, 0.023468f, 0.025818f, 0.028183f, 0.031021f, 0.033783f, 0.037445f, 0.041534f, 0.045532f, 0.050598f, 0.056152f, 0.062500f, + 0.069580f, 0.077698f, 0.086914f, 0.097717f, 0.108948f, 0.123047f, 0.138184f, 0.155273f, 0.174438f, 0.196167f, 0.219604f, 0.246094f, + 0.274902f, 0.305420f, 0.338379f, 0.372314f, 0.408936f, 0.445801f, 0.484131f, 0.523438f, 0.562988f, 0.604492f, 0.843262f, 0.856445f, + 0.857422f, 0.857910f, 0.858398f, 0.858398f, 0.000331f, 0.000944f, 0.001288f, 0.001833f, 0.002388f, 0.002769f, 0.003216f, 0.003664f, + 0.004276f, 0.004822f, 0.005173f, 0.005951f, 0.006531f, 0.007156f, 0.007896f, 0.008438f, 0.009430f, 0.010117f, 0.011208f, 0.012253f, + 0.012970f, 0.014297f, 0.015572f, 0.017059f, 0.018692f, 0.020264f, 0.022125f, 0.024323f, 0.026474f, 0.029343f, 0.032288f, 0.035461f, + 0.039062f, 0.043335f, 0.047821f, 0.053558f, 0.059509f, 0.067078f, 0.074341f, 0.083862f, 0.094360f, 0.106323f, 0.120117f, 0.135254f, + 0.153442f, 0.172852f, 0.195190f, 0.220337f, 0.246948f, 0.276611f, 0.308594f, 0.343262f, 0.379150f, 0.416992f, 0.455811f, 0.496582f, + 0.537598f, 0.579590f, 0.834473f, 0.847656f, 0.850098f, 0.850098f, 0.849609f, 0.850098f, 0.000316f, 0.000824f, 0.001088f, 0.001693f, + 0.002062f, 0.002403f, 0.003027f, 0.003460f, 0.003712f, 0.004166f, 0.004765f, 0.005138f, 0.005871f, 0.006218f, 0.006924f, 0.007431f, + 0.008255f, 0.008850f, 0.009781f, 0.010590f, 0.011391f, 0.012367f, 0.013474f, 0.014709f, 0.015823f, 0.017685f, 0.018982f, 0.020844f, + 0.022629f, 0.025070f, 0.027496f, 0.030380f, 0.033447f, 0.037140f, 0.041168f, 0.045654f, 0.050720f, 0.057251f, 0.063965f, 0.071777f, + 0.080811f, 0.091248f, 0.103638f, 0.117126f, 0.133179f, 0.151001f, 0.171631f, 0.194580f, 0.220337f, 0.248413f, 0.279785f, 0.313965f, + 0.349365f, 0.386963f, 0.426514f, 0.468262f, 0.510742f, 0.555176f, 0.825684f, 0.838379f, 0.839844f, 0.841309f, 0.841309f, 0.841309f, + 0.000210f, 0.000717f, 0.001084f, 0.001454f, 0.001882f, 0.002096f, 0.002468f, 0.002996f, 0.003395f, 0.003632f, 0.004066f, 0.004467f, + 0.005020f, 0.005569f, 0.005917f, 0.006474f, 0.006958f, 0.007576f, 0.008453f, 0.009140f, 0.010002f, 0.010689f, 0.011520f, 0.012596f, + 0.013695f, 0.014938f, 0.016220f, 0.017593f, 0.019424f, 0.020996f, 0.023331f, 0.025696f, 0.028427f, 0.031067f, 0.034668f, 0.038422f, + 0.042908f, 0.048096f, 0.054016f, 0.060699f, 0.068909f, 0.077515f, 0.088501f, 0.100464f, 0.114624f, 0.130615f, 0.149048f, 0.170654f, + 0.194214f, 0.222046f, 0.251465f, 0.283936f, 0.319580f, 0.357422f, 0.397461f, 0.440186f, 0.484375f, 0.528320f, 0.814941f, 0.828613f, + 0.830078f, 0.832031f, 0.831543f, 0.833008f, 0.000234f, 0.000576f, 0.000939f, 0.001362f, 0.001481f, 0.001999f, 0.002228f, 0.002714f, + 0.002846f, 0.003218f, 0.003555f, 0.003933f, 0.004356f, 0.004787f, 0.005169f, 0.005604f, 0.006145f, 0.006554f, 0.007275f, 0.007675f, + 0.008293f, 0.009201f, 0.009979f, 0.010651f, 0.011497f, 0.012527f, 0.013893f, 0.014771f, 0.016373f, 0.017975f, 0.019455f, 0.021683f, + 0.023895f, 0.026077f, 0.029114f, 0.032257f, 0.036072f, 0.040405f, 0.045197f, 0.050903f, 0.057770f, 0.065613f, 0.074524f, 0.085388f, + 0.097656f, 0.111694f, 0.128540f, 0.147949f, 0.170166f, 0.195435f, 0.223389f, 0.255127f, 0.289551f, 0.327393f, 0.367432f, 0.410400f, + 0.455078f, 0.502441f, 0.804199f, 0.818848f, 0.821289f, 0.822266f, 0.822754f, 0.822266f, 0.000213f, 0.000506f, 0.000756f, 0.001184f, + 0.001396f, 0.001697f, 0.002010f, 0.002474f, 0.002569f, 0.002918f, 0.003090f, 0.003496f, 0.003855f, 0.004139f, 0.004478f, 0.004852f, + 0.005253f, 0.005665f, 0.006100f, 0.006638f, 0.007080f, 0.007744f, 0.008293f, 0.009132f, 0.009750f, 0.010658f, 0.011536f, 0.012413f, + 0.013779f, 0.014908f, 0.016510f, 0.017990f, 0.019623f, 0.021637f, 0.024109f, 0.026718f, 0.029922f, 0.033539f, 0.037567f, 0.042572f, + 0.048279f, 0.054413f, 0.062042f, 0.071472f, 0.081909f, 0.094604f, 0.109436f, 0.127075f, 0.146484f, 0.170044f, 0.196533f, 0.226929f, + 0.260254f, 0.296875f, 0.337402f, 0.380615f, 0.426025f, 0.475342f, 0.792969f, 0.807617f, 0.811035f, 0.811523f, 0.812012f, 0.813477f, + 0.000119f, 0.000422f, 0.000883f, 0.001027f, 0.001189f, 0.001604f, 0.001783f, 0.001913f, 0.002228f, 0.002522f, 0.002645f, 0.003086f, + 0.003199f, 0.003534f, 0.003790f, 0.004105f, 0.004421f, 0.004902f, 0.005283f, 0.005589f, 0.006039f, 0.006401f, 0.007088f, 0.007519f, + 0.008217f, 0.008812f, 0.009712f, 0.010460f, 0.011337f, 0.012413f, 0.013596f, 0.014687f, 0.016159f, 0.018051f, 0.019913f, 0.022018f, + 0.024551f, 0.027359f, 0.030792f, 0.035065f, 0.039703f, 0.044983f, 0.051392f, 0.059204f, 0.068176f, 0.079102f, 0.092041f, 0.106873f, + 0.125000f, 0.145874f, 0.170532f, 0.198975f, 0.230835f, 0.267090f, 0.306641f, 0.349854f, 0.395508f, 0.445801f, 0.780762f, 0.796875f, + 0.799805f, 0.801270f, 0.801270f, 0.801270f, 0.000227f, 0.000521f, 0.000698f, 0.000817f, 0.001236f, 0.001359f, 0.001540f, 0.001619f, + 0.001940f, 0.002089f, 0.002430f, 0.002552f, 0.002655f, 0.002932f, 0.003241f, 0.003532f, 0.003841f, 0.004120f, 0.004292f, 0.004761f, + 0.005051f, 0.005459f, 0.005886f, 0.006290f, 0.006821f, 0.007320f, 0.007889f, 0.008652f, 0.009399f, 0.010063f, 0.010887f, 0.012215f, + 0.013206f, 0.014648f, 0.016037f, 0.017853f, 0.019958f, 0.022491f, 0.024994f, 0.028091f, 0.032135f, 0.036530f, 0.041809f, 0.048096f, + 0.055908f, 0.064941f, 0.076050f, 0.089050f, 0.104980f, 0.123596f, 0.146118f, 0.172363f, 0.203003f, 0.237183f, 0.276123f, 0.318359f, + 0.365479f, 0.416504f, 0.768555f, 0.784668f, 0.788086f, 0.789551f, 0.790039f, 0.790039f, 0.000000f, 0.000448f, 0.000566f, 0.000688f, + 0.000985f, 0.001144f, 0.001305f, 0.001437f, 0.001622f, 0.001731f, 0.001989f, 0.002174f, 0.002338f, 0.002552f, 0.002739f, 0.002924f, + 0.003239f, 0.003405f, 0.003628f, 0.003933f, 0.004200f, 0.004463f, 0.004948f, 0.005245f, 0.005615f, 0.006138f, 0.006699f, 0.006989f, + 0.007793f, 0.008247f, 0.008980f, 0.009918f, 0.010857f, 0.011795f, 0.013016f, 0.014244f, 0.015930f, 0.017868f, 0.019882f, 0.022659f, + 0.025543f, 0.029160f, 0.033417f, 0.038635f, 0.044983f, 0.052338f, 0.061859f, 0.072693f, 0.086487f, 0.102966f, 0.122864f, 0.146973f, + 0.175049f, 0.207764f, 0.245605f, 0.287842f, 0.334229f, 0.385986f, 0.755371f, 0.771973f, 0.775879f, 0.777344f, 0.777832f, 0.778809f, + 0.000000f, 0.000303f, 0.000512f, 0.000752f, 0.000828f, 0.001036f, 0.001184f, 0.001292f, 0.001281f, 0.001460f, 0.001717f, 0.001843f, + 0.001955f, 0.002060f, 0.002317f, 0.002476f, 0.002542f, 0.002869f, 0.003088f, 0.003313f, 0.003559f, 0.003693f, 0.004082f, 0.004318f, + 0.004696f, 0.005070f, 0.005245f, 0.005741f, 0.006126f, 0.006771f, 0.007298f, 0.007828f, 0.008583f, 0.009338f, 0.010246f, 0.011528f, + 0.012794f, 0.014160f, 0.015717f, 0.017853f, 0.019958f, 0.022995f, 0.026291f, 0.030533f, 0.035553f, 0.041565f, 0.048981f, 0.058350f, + 0.069824f, 0.083801f, 0.101685f, 0.122437f, 0.148438f, 0.178833f, 0.215454f, 0.256104f, 0.302490f, 0.354736f, 0.741699f, 0.758789f, + 0.762695f, 0.763672f, 0.764648f, 0.765625f, 0.000097f, 0.000306f, 0.000370f, 0.000618f, 0.000713f, 0.000810f, 0.000953f, 0.000920f, + 0.001167f, 0.001238f, 0.001406f, 0.001483f, 0.001540f, 0.001794f, 0.001970f, 0.002028f, 0.002264f, 0.002354f, 0.002459f, 0.002636f, + 0.002827f, 0.003096f, 0.003342f, 0.003544f, 0.003881f, 0.003948f, 0.004459f, 0.004742f, 0.005005f, 0.005394f, 0.005867f, 0.006374f, + 0.006901f, 0.007507f, 0.008202f, 0.008881f, 0.010017f, 0.010986f, 0.012451f, 0.013809f, 0.015511f, 0.017776f, 0.020325f, 0.023453f, + 0.027390f, 0.032349f, 0.038330f, 0.045624f, 0.055359f, 0.067078f, 0.082275f, 0.101013f, 0.123657f, 0.151611f, 0.185791f, 0.225342f, + 0.270752f, 0.322754f, 0.727051f, 0.746094f, 0.749512f, 0.750977f, 0.751953f, 0.751953f, 0.000228f, 0.000211f, 0.000504f, 0.000443f, + 0.000523f, 0.000672f, 0.000703f, 0.000902f, 0.000975f, 0.001010f, 0.001122f, 0.001178f, 0.001257f, 0.001424f, 0.001575f, 0.001631f, + 0.001789f, 0.001910f, 0.002090f, 0.002144f, 0.002411f, 0.002520f, 0.002703f, 0.002827f, 0.003010f, 0.003195f, 0.003403f, 0.003750f, + 0.003960f, 0.004276f, 0.004780f, 0.005005f, 0.005432f, 0.005981f, 0.006428f, 0.007015f, 0.007812f, 0.008537f, 0.009415f, 0.010658f, + 0.011963f, 0.013443f, 0.015396f, 0.017731f, 0.020782f, 0.024414f, 0.029083f, 0.034912f, 0.042572f, 0.052216f, 0.064392f, 0.080017f, + 0.100220f, 0.126099f, 0.157227f, 0.194946f, 0.239136f, 0.290283f, 0.712402f, 0.731445f, 0.734863f, 0.736816f, 0.737305f, 0.737793f, + 0.000211f, 0.000198f, 0.000195f, 0.000413f, 0.000517f, 0.000531f, 0.000586f, 0.000736f, 0.000769f, 0.000809f, 0.000970f, 0.001007f, + 0.001067f, 0.001134f, 0.001211f, 0.001348f, 0.001341f, 0.001534f, 0.001617f, 0.001734f, 0.001942f, 0.002010f, 0.002110f, 0.002268f, + 0.002523f, 0.002607f, 0.002829f, 0.003004f, 0.003113f, 0.003403f, 0.003681f, 0.003990f, 0.004257f, 0.004601f, 0.005039f, 0.005444f, + 0.005993f, 0.006561f, 0.007278f, 0.008026f, 0.009041f, 0.010124f, 0.011513f, 0.013222f, 0.015320f, 0.017914f, 0.021408f, 0.025833f, + 0.031433f, 0.039429f, 0.049255f, 0.062286f, 0.079102f, 0.101135f, 0.130005f, 0.164917f, 0.207764f, 0.258057f, 0.696289f, 0.716309f, + 0.720215f, 0.722168f, 0.722656f, 0.723145f, 0.000000f, 0.000080f, 0.000286f, 0.000374f, 0.000434f, 0.000457f, 0.000460f, 0.000568f, + 0.000610f, 0.000669f, 0.000715f, 0.000773f, 0.000877f, 0.000918f, 0.001030f, 0.000998f, 0.001148f, 0.001134f, 0.001305f, 0.001369f, + 0.001410f, 0.001534f, 0.001688f, 0.001780f, 0.001899f, 0.001963f, 0.002081f, 0.002199f, 0.002470f, 0.002563f, 0.002758f, 0.003006f, + 0.003273f, 0.003531f, 0.003817f, 0.004093f, 0.004532f, 0.004993f, 0.005463f, 0.006027f, 0.006657f, 0.007492f, 0.008537f, 0.009689f, + 0.011246f, 0.012985f, 0.015518f, 0.018539f, 0.022827f, 0.028534f, 0.036072f, 0.046234f, 0.060028f, 0.078918f, 0.103943f, 0.136353f, + 0.176514f, 0.225952f, 0.679199f, 0.699707f, 0.703613f, 0.706055f, 0.706543f, 0.708008f, 0.000089f, 0.000176f, 0.000232f, 0.000342f, + 0.000317f, 0.000319f, 0.000420f, 0.000382f, 0.000494f, 0.000515f, 0.000612f, 0.000650f, 0.000671f, 0.000701f, 0.000732f, 0.000859f, + 0.000888f, 0.000923f, 0.001002f, 0.001048f, 0.001170f, 0.001234f, 0.001292f, 0.001426f, 0.001414f, 0.001476f, 0.001622f, 0.001723f, + 0.001892f, 0.001976f, 0.002237f, 0.002239f, 0.002476f, 0.002645f, 0.002817f, 0.003092f, 0.003355f, 0.003626f, 0.003979f, 0.004459f, + 0.004948f, 0.005527f, 0.006256f, 0.007027f, 0.008026f, 0.009270f, 0.010918f, 0.013184f, 0.016098f, 0.019913f, 0.025253f, 0.033112f, + 0.043762f, 0.059113f, 0.079956f, 0.109009f, 0.146729f, 0.193726f, 0.660645f, 0.682129f, 0.688477f, 0.690430f, 0.689941f, 0.690918f, + 0.000000f, 0.000063f, 0.000194f, 0.000281f, 0.000187f, 0.000325f, 0.000278f, 0.000272f, 0.000386f, 0.000466f, 0.000462f, 0.000510f, + 0.000519f, 0.000587f, 0.000613f, 0.000603f, 0.000671f, 0.000709f, 0.000744f, 0.000808f, 0.000858f, 0.000913f, 0.000963f, 0.000999f, + 0.001062f, 0.001106f, 0.001262f, 0.001266f, 0.001431f, 0.001562f, 0.001672f, 0.001693f, 0.001810f, 0.001976f, 0.002090f, 0.002289f, + 0.002422f, 0.002666f, 0.002916f, 0.003166f, 0.003513f, 0.003862f, 0.004318f, 0.004936f, 0.005646f, 0.006493f, 0.007626f, 0.009048f, + 0.010826f, 0.013519f, 0.017166f, 0.022476f, 0.030258f, 0.041687f, 0.058807f, 0.083435f, 0.117737f, 0.162598f, 0.644043f, 0.666504f, + 0.670410f, 0.673340f, 0.674316f, 0.675293f, 0.000000f, 0.000117f, 0.000112f, 0.000178f, 0.000216f, 0.000222f, 0.000271f, 0.000229f, + 0.000280f, 0.000283f, 0.000326f, 0.000376f, 0.000376f, 0.000443f, 0.000456f, 0.000470f, 0.000499f, 0.000507f, 0.000547f, 0.000566f, + 0.000613f, 0.000667f, 0.000692f, 0.000749f, 0.000773f, 0.000803f, 0.000917f, 0.000924f, 0.000997f, 0.001055f, 0.001096f, 0.001236f, + 0.001261f, 0.001376f, 0.001466f, 0.001693f, 0.001695f, 0.001826f, 0.002077f, 0.002226f, 0.002411f, 0.002686f, 0.002985f, 0.003368f, + 0.003801f, 0.004353f, 0.005131f, 0.005974f, 0.007370f, 0.008842f, 0.011345f, 0.014717f, 0.019699f, 0.027893f, 0.040619f, 0.060730f, + 0.090454f, 0.132080f, 0.625488f, 0.649414f, 0.653809f, 0.655273f, 0.656250f, 0.658203f, 0.000000f, 0.000000f, 0.000108f, 0.000121f, + 0.000136f, 0.000154f, 0.000158f, 0.000191f, 0.000203f, 0.000213f, 0.000270f, 0.000223f, 0.000232f, 0.000270f, 0.000296f, 0.000342f, + 0.000324f, 0.000352f, 0.000453f, 0.000407f, 0.000450f, 0.000459f, 0.000486f, 0.000524f, 0.000545f, 0.000565f, 0.000630f, 0.000620f, + 0.000678f, 0.000803f, 0.000763f, 0.000813f, 0.000860f, 0.000937f, 0.001035f, 0.001101f, 0.001141f, 0.001254f, 0.001399f, 0.001449f, + 0.001616f, 0.001779f, 0.001942f, 0.002220f, 0.002493f, 0.002808f, 0.003258f, 0.003895f, 0.004623f, 0.005714f, 0.007111f, 0.009178f, + 0.012367f, 0.017319f, 0.025879f, 0.040741f, 0.065552f, 0.103577f, 0.606934f, 0.630371f, 0.635254f, 0.637695f, 0.638672f, 0.639648f, + 0.000000f, 0.000109f, 0.000102f, 0.000098f, 0.000105f, 0.000110f, 0.000113f, 0.000122f, 0.000117f, 0.000132f, 0.000147f, 0.000189f, + 0.000163f, 0.000212f, 0.000213f, 0.000222f, 0.000224f, 0.000233f, 0.000258f, 0.000262f, 0.000274f, 0.000305f, 0.000340f, 0.000329f, + 0.000358f, 0.000376f, 0.000445f, 0.000418f, 0.000447f, 0.000478f, 0.000546f, 0.000530f, 0.000594f, 0.000626f, 0.000679f, 0.000745f, + 0.000763f, 0.000804f, 0.000869f, 0.000952f, 0.001025f, 0.001119f, 0.001254f, 0.001359f, 0.001584f, 0.001728f, 0.001993f, 0.002295f, + 0.002790f, 0.003298f, 0.004135f, 0.005363f, 0.007267f, 0.010277f, 0.015350f, 0.024994f, 0.043518f, 0.076599f, 0.585938f, 0.611816f, + 0.616211f, 0.619141f, 0.619629f, 0.620605f, 0.000000f, 0.000102f, 0.000095f, 0.000090f, 0.000085f, 0.000081f, 0.000078f, 0.000073f, + 0.000075f, 0.000079f, 0.000087f, 0.000092f, 0.000095f, 0.000094f, 0.000133f, 0.000143f, 0.000152f, 0.000155f, 0.000161f, 0.000195f, + 0.000174f, 0.000183f, 0.000188f, 0.000216f, 0.000233f, 0.000241f, 0.000241f, 0.000257f, 0.000269f, 0.000302f, 0.000325f, 0.000321f, + 0.000350f, 0.000363f, 0.000405f, 0.000426f, 0.000456f, 0.000486f, 0.000539f, 0.000560f, 0.000614f, 0.000671f, 0.000722f, 0.000811f, + 0.000891f, 0.000989f, 0.001162f, 0.001312f, 0.001545f, 0.001863f, 0.002340f, 0.002920f, 0.003963f, 0.005615f, 0.008499f, 0.013931f, + 0.025833f, 0.052094f, 0.566406f, 0.591797f, 0.597168f, 0.599609f, 0.601074f, 0.601562f, 0.000110f, 0.000092f, 0.000084f, 0.000077f, + 0.000073f, 0.000070f, 0.000067f, 0.000064f, 0.000061f, 0.000058f, 0.000055f, 0.000064f, 0.000051f, 0.000054f, 0.000071f, 0.000059f, + 0.000082f, 0.000081f, 0.000090f, 0.000087f, 0.000099f, 0.000103f, 0.000127f, 0.000131f, 0.000135f, 0.000139f, 0.000142f, 0.000143f, + 0.000156f, 0.000162f, 0.000173f, 0.000194f, 0.000206f, 0.000201f, 0.000233f, 0.000225f, 0.000246f, 0.000294f, 0.000279f, 0.000313f, + 0.000333f, 0.000356f, 0.000395f, 0.000432f, 0.000459f, 0.000511f, 0.000577f, 0.000664f, 0.000770f, 0.000916f, 0.001114f, 0.001400f, + 0.001881f, 0.002665f, 0.004093f, 0.006966f, 0.013290f, 0.031525f, 0.545410f, 0.571777f, 0.577637f, 0.579102f, 0.580566f, 0.581055f, + 0.000093f, 0.000073f, 0.000066f, 0.000061f, 0.000056f, 0.000054f, 0.000051f, 0.000050f, 0.000048f, 0.000047f, 0.000045f, 0.000044f, + 0.000042f, 0.000040f, 0.000038f, 0.000036f, 0.000039f, 0.000033f, 0.000041f, 0.000040f, 0.000046f, 0.000048f, 0.000051f, 0.000057f, + 0.000060f, 0.000066f, 0.000062f, 0.000067f, 0.000080f, 0.000085f, 0.000088f, 0.000092f, 0.000092f, 0.000097f, 0.000109f, 0.000109f, + 0.000117f, 0.000132f, 0.000134f, 0.000147f, 0.000154f, 0.000156f, 0.000188f, 0.000197f, 0.000219f, 0.000234f, 0.000266f, 0.000286f, + 0.000335f, 0.000397f, 0.000472f, 0.000566f, 0.000751f, 0.001039f, 0.001626f, 0.002834f, 0.005909f, 0.015411f, 0.524414f, 0.551270f, + 0.557129f, 0.559570f, 0.561035f, 0.561523f, 0.000060f, 0.000046f, 0.000039f, 0.000037f, 0.000034f, 0.000034f, 0.000032f, 0.000032f, + 0.000031f, 0.000029f, 0.000029f, 0.000029f, 0.000028f, 0.000028f, 0.000028f, 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, + 0.000022f, 0.000021f, 0.000020f, 0.000021f, 0.000020f, 0.000018f, 0.000018f, 0.000023f, 0.000024f, 0.000028f, 0.000032f, 0.000033f, + 0.000032f, 0.000038f, 0.000039f, 0.000043f, 0.000046f, 0.000050f, 0.000052f, 0.000053f, 0.000057f, 0.000067f, 0.000073f, 0.000068f, + 0.000076f, 0.000083f, 0.000097f, 0.000110f, 0.000116f, 0.000127f, 0.000157f, 0.000185f, 0.000246f, 0.000319f, 0.000466f, 0.000810f, + 0.001841f, 0.005795f, 0.503418f, 0.531250f, 0.536621f, 0.539062f, 0.540039f, 0.540527f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000004f, 0.000005f, 0.000005f, 0.000008f, 0.000008f, 0.000009f, 0.000009f, 0.000010f, 0.000010f, 0.000010f, 0.000010f, 0.000011f, + 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, + 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000009f, 0.000009f, 0.000010f, 0.000012f, + 0.000013f, 0.000014f, 0.000015f, 0.000017f, 0.000020f, 0.000021f, 0.000018f, 0.000023f, 0.000023f, 0.000025f, 0.000030f, 0.000038f, + 0.000043f, 0.000059f, 0.000079f, 0.000131f, 0.000279f, 0.001210f, 0.481934f, 0.510254f, 0.516113f, 0.518555f, 0.520020f, 0.520508f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, + 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, + 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000006f, 0.000022f, 0.460449f, 0.489258f, + 0.495850f, 0.498291f, 0.499512f, 0.500000f, + }, + { + 0.038544f, 0.111450f, 0.177368f, 0.237061f, 0.290771f, 0.339600f, 0.384277f, 0.425293f, 0.462402f, 0.497070f, 0.527344f, 0.556152f, + 0.583496f, 0.607910f, 0.630859f, 0.652344f, 0.672852f, 0.690918f, 0.708496f, 0.724609f, 0.740723f, 0.754883f, 0.768066f, 0.780273f, + 0.792480f, 0.803711f, 0.815430f, 0.825684f, 0.835449f, 0.844727f, 0.853516f, 0.861816f, 0.870117f, 0.877930f, 0.885254f, 0.892578f, + 0.899414f, 0.905762f, 0.912109f, 0.918945f, 0.923828f, 0.928711f, 0.934082f, 0.939941f, 0.944824f, 0.949707f, 0.953613f, 0.958496f, + 0.962402f, 0.967285f, 0.971191f, 0.974609f, 0.979004f, 0.982422f, 0.985352f, 0.989258f, 0.992188f, 0.996094f, 0.996094f, 0.990723f, + 0.986328f, 0.982422f, 0.978516f, 0.975098f, 0.029068f, 0.087219f, 0.142578f, 0.195190f, 0.244629f, 0.291016f, 0.334717f, 0.375000f, + 0.412842f, 0.446533f, 0.481201f, 0.511230f, 0.539062f, 0.565918f, 0.590820f, 0.614258f, 0.636719f, 0.656250f, 0.675293f, 0.693359f, + 0.710449f, 0.726562f, 0.741699f, 0.755371f, 0.769043f, 0.781738f, 0.793457f, 0.805176f, 0.815918f, 0.826660f, 0.835938f, 0.845703f, + 0.854980f, 0.862793f, 0.871582f, 0.879395f, 0.885742f, 0.894531f, 0.900879f, 0.907227f, 0.913086f, 0.919434f, 0.925293f, 0.931152f, + 0.936523f, 0.941406f, 0.946777f, 0.951172f, 0.956055f, 0.960449f, 0.964355f, 0.968750f, 0.972656f, 0.976562f, 0.980469f, 0.984375f, + 0.987793f, 0.991211f, 0.994141f, 0.989258f, 0.984863f, 0.981445f, 0.977539f, 0.974121f, 0.023346f, 0.069641f, 0.115601f, 0.160767f, + 0.205078f, 0.248047f, 0.289062f, 0.328125f, 0.365723f, 0.401367f, 0.435059f, 0.466309f, 0.495361f, 0.523926f, 0.550781f, 0.574707f, + 0.597168f, 0.620117f, 0.641113f, 0.660156f, 0.679688f, 0.696777f, 0.713379f, 0.728516f, 0.743652f, 0.757324f, 0.770996f, 0.784180f, + 0.795410f, 0.806641f, 0.817383f, 0.828125f, 0.837891f, 0.847168f, 0.855957f, 0.864258f, 0.873047f, 0.880859f, 0.888672f, 0.895996f, + 0.902832f, 0.909668f, 0.915039f, 0.921875f, 0.927246f, 0.934082f, 0.937988f, 0.943848f, 0.948242f, 0.953613f, 0.958496f, 0.962402f, + 0.967285f, 0.971191f, 0.975098f, 0.979492f, 0.983398f, 0.985840f, 0.992188f, 0.987305f, 0.983398f, 0.979980f, 0.977051f, 0.973633f, + 0.018600f, 0.056366f, 0.094299f, 0.133545f, 0.172729f, 0.211670f, 0.249756f, 0.285889f, 0.322021f, 0.356934f, 0.390869f, 0.421875f, + 0.452148f, 0.481201f, 0.509277f, 0.535156f, 0.560059f, 0.583496f, 0.605957f, 0.626465f, 0.647949f, 0.665527f, 0.684570f, 0.700684f, + 0.717285f, 0.731934f, 0.746582f, 0.760254f, 0.773926f, 0.786621f, 0.799316f, 0.809082f, 0.820312f, 0.830566f, 0.840332f, 0.850098f, + 0.858887f, 0.867188f, 0.875000f, 0.883789f, 0.890625f, 0.898926f, 0.904297f, 0.912109f, 0.916992f, 0.924316f, 0.930176f, 0.935547f, + 0.941406f, 0.945801f, 0.951172f, 0.956055f, 0.960938f, 0.964844f, 0.969727f, 0.974609f, 0.978516f, 0.981934f, 0.989746f, 0.985840f, + 0.981934f, 0.978516f, 0.975586f, 0.972168f, 0.015068f, 0.046143f, 0.077881f, 0.111816f, 0.145264f, 0.179688f, 0.214600f, 0.249023f, + 0.282715f, 0.316406f, 0.348389f, 0.380615f, 0.411133f, 0.440430f, 0.468018f, 0.494873f, 0.520508f, 0.546387f, 0.568848f, 0.591309f, + 0.613281f, 0.634277f, 0.653809f, 0.670898f, 0.688477f, 0.706055f, 0.721191f, 0.736328f, 0.751465f, 0.764648f, 0.776855f, 0.789551f, + 0.801270f, 0.812500f, 0.823730f, 0.833496f, 0.843262f, 0.853027f, 0.861328f, 0.869629f, 0.878418f, 0.885742f, 0.893555f, 0.900391f, + 0.908203f, 0.914551f, 0.921387f, 0.927246f, 0.932617f, 0.938965f, 0.943848f, 0.949219f, 0.953613f, 0.959473f, 0.963867f, 0.968262f, + 0.972656f, 0.977051f, 0.987305f, 0.983887f, 0.980957f, 0.977051f, 0.974121f, 0.970703f, 0.012444f, 0.037933f, 0.065613f, 0.093811f, + 0.123474f, 0.153809f, 0.185059f, 0.215820f, 0.247559f, 0.279297f, 0.310547f, 0.341309f, 0.370361f, 0.399658f, 0.428467f, 0.457031f, + 0.482910f, 0.507812f, 0.533203f, 0.556152f, 0.579590f, 0.600098f, 0.621094f, 0.641113f, 0.659668f, 0.676270f, 0.695312f, 0.710449f, + 0.726074f, 0.740723f, 0.756348f, 0.769043f, 0.780762f, 0.794434f, 0.805176f, 0.816895f, 0.827637f, 0.837891f, 0.847168f, 0.855957f, + 0.865723f, 0.873535f, 0.882324f, 0.889648f, 0.897949f, 0.904297f, 0.911133f, 0.917480f, 0.924316f, 0.930176f, 0.936523f, 0.941895f, + 0.947266f, 0.952637f, 0.958008f, 0.962891f, 0.967285f, 0.971680f, 0.984863f, 0.981934f, 0.978516f, 0.975586f, 0.972656f, 0.969238f, + 0.010353f, 0.032043f, 0.055359f, 0.079529f, 0.104980f, 0.131836f, 0.159424f, 0.187866f, 0.216431f, 0.245239f, 0.275146f, 0.304199f, + 0.333496f, 0.362061f, 0.390869f, 0.417969f, 0.445068f, 0.471191f, 0.496582f, 0.520508f, 0.543457f, 0.566895f, 0.588867f, 0.608398f, + 0.628906f, 0.648438f, 0.666992f, 0.684570f, 0.701660f, 0.716797f, 0.732422f, 0.746582f, 0.760254f, 0.773438f, 0.786133f, 0.798340f, + 0.810547f, 0.821777f, 0.832520f, 0.842773f, 0.851074f, 0.860352f, 0.869629f, 0.878906f, 0.886230f, 0.894043f, 0.901855f, 0.908691f, + 0.915527f, 0.922363f, 0.928223f, 0.935059f, 0.939941f, 0.945312f, 0.950684f, 0.956055f, 0.962402f, 0.966797f, 0.982910f, 0.979980f, + 0.977051f, 0.973633f, 0.970703f, 0.968262f, 0.008598f, 0.027328f, 0.046417f, 0.067871f, 0.089905f, 0.113220f, 0.137695f, 0.163330f, + 0.189087f, 0.216064f, 0.243164f, 0.270752f, 0.298340f, 0.326416f, 0.354004f, 0.381348f, 0.407715f, 0.434082f, 0.460205f, 0.484863f, + 0.508789f, 0.532227f, 0.555176f, 0.577637f, 0.598145f, 0.618652f, 0.637695f, 0.657227f, 0.674805f, 0.691406f, 0.708008f, 0.723633f, + 0.738770f, 0.751953f, 0.766113f, 0.779785f, 0.791992f, 0.804199f, 0.815918f, 0.825684f, 0.836914f, 0.846680f, 0.856934f, 0.866211f, + 0.874512f, 0.882324f, 0.890625f, 0.898438f, 0.905273f, 0.913086f, 0.919922f, 0.926758f, 0.933105f, 0.938477f, 0.944824f, 0.951172f, + 0.955566f, 0.960938f, 0.980469f, 0.978027f, 0.974609f, 0.972168f, 0.969238f, 0.966797f, 0.007561f, 0.023315f, 0.040344f, 0.058228f, + 0.077148f, 0.097534f, 0.119995f, 0.142212f, 0.165649f, 0.190063f, 0.214722f, 0.240601f, 0.266846f, 0.293457f, 0.319824f, 0.346924f, + 0.372314f, 0.398438f, 0.424561f, 0.449463f, 0.474609f, 0.498535f, 0.521973f, 0.544434f, 0.566895f, 0.587402f, 0.608398f, 0.628418f, + 0.645996f, 0.665039f, 0.683105f, 0.699219f, 0.716309f, 0.731445f, 0.745117f, 0.760254f, 0.772949f, 0.786133f, 0.799316f, 0.809570f, + 0.820801f, 0.832031f, 0.843262f, 0.852051f, 0.861816f, 0.871094f, 0.880371f, 0.887695f, 0.895996f, 0.904297f, 0.911133f, 0.917969f, + 0.924805f, 0.931641f, 0.937012f, 0.943848f, 0.949707f, 0.954590f, 0.978027f, 0.976074f, 0.973145f, 0.970215f, 0.967773f, 0.965332f, + 0.006416f, 0.020065f, 0.034943f, 0.050537f, 0.067078f, 0.084900f, 0.104065f, 0.123962f, 0.145264f, 0.166748f, 0.189575f, 0.213501f, + 0.237305f, 0.262451f, 0.288574f, 0.313477f, 0.338623f, 0.364502f, 0.389893f, 0.414551f, 0.440186f, 0.464600f, 0.487549f, 0.510742f, + 0.534668f, 0.556641f, 0.578613f, 0.598145f, 0.618652f, 0.637207f, 0.655273f, 0.674805f, 0.690430f, 0.707031f, 0.724121f, 0.739258f, + 0.752930f, 0.767090f, 0.779785f, 0.792969f, 0.805176f, 0.816895f, 0.827637f, 0.838379f, 0.849121f, 0.858398f, 0.868652f, 0.876465f, + 0.885742f, 0.894043f, 0.901855f, 0.909180f, 0.916992f, 0.923828f, 0.930176f, 0.937012f, 0.943359f, 0.949707f, 0.975586f, 0.973633f, + 0.971191f, 0.968262f, 0.965820f, 0.963379f, 0.005802f, 0.017502f, 0.030045f, 0.043823f, 0.058014f, 0.074280f, 0.090759f, 0.108459f, + 0.127197f, 0.146484f, 0.167725f, 0.189087f, 0.211304f, 0.234497f, 0.258301f, 0.282471f, 0.307373f, 0.331299f, 0.356689f, 0.381104f, + 0.405762f, 0.430420f, 0.455078f, 0.478516f, 0.502441f, 0.524414f, 0.545898f, 0.568359f, 0.588867f, 0.608887f, 0.628906f, 0.646973f, + 0.665527f, 0.684082f, 0.701172f, 0.715820f, 0.731934f, 0.746582f, 0.760742f, 0.774414f, 0.787598f, 0.800781f, 0.812500f, 0.823730f, + 0.834961f, 0.845703f, 0.855469f, 0.865234f, 0.874512f, 0.883789f, 0.892090f, 0.899902f, 0.908203f, 0.916016f, 0.922852f, 0.930176f, + 0.936523f, 0.942871f, 0.972656f, 0.971191f, 0.968750f, 0.966309f, 0.963867f, 0.961426f, 0.004734f, 0.014984f, 0.026169f, 0.038177f, + 0.051208f, 0.065186f, 0.079468f, 0.095276f, 0.111633f, 0.129639f, 0.148071f, 0.167969f, 0.188599f, 0.208984f, 0.231689f, 0.254639f, + 0.277832f, 0.301025f, 0.325439f, 0.349854f, 0.373779f, 0.397705f, 0.422607f, 0.446045f, 0.469727f, 0.492676f, 0.514648f, 0.537598f, + 0.559570f, 0.580078f, 0.600586f, 0.620117f, 0.639648f, 0.658203f, 0.676758f, 0.692871f, 0.708984f, 0.725586f, 0.740723f, 0.755859f, + 0.769531f, 0.783691f, 0.796875f, 0.808594f, 0.820801f, 0.832520f, 0.842285f, 0.852539f, 0.862793f, 0.872070f, 0.881836f, 0.890137f, + 0.898926f, 0.906738f, 0.915039f, 0.922363f, 0.929199f, 0.936523f, 0.969727f, 0.968750f, 0.966797f, 0.964355f, 0.961914f, 0.959473f, + 0.004055f, 0.013588f, 0.023132f, 0.033722f, 0.044891f, 0.057343f, 0.069763f, 0.083923f, 0.098389f, 0.114441f, 0.131226f, 0.148682f, + 0.167603f, 0.186768f, 0.207031f, 0.228516f, 0.250732f, 0.272949f, 0.295410f, 0.318604f, 0.342285f, 0.365967f, 0.390381f, 0.413574f, + 0.437744f, 0.460938f, 0.484131f, 0.506348f, 0.528320f, 0.550781f, 0.572266f, 0.592773f, 0.613281f, 0.632812f, 0.651367f, 0.669922f, + 0.687500f, 0.704102f, 0.720215f, 0.735840f, 0.751465f, 0.764160f, 0.778809f, 0.792480f, 0.803711f, 0.816895f, 0.829102f, 0.840332f, + 0.850586f, 0.860352f, 0.870605f, 0.880371f, 0.889648f, 0.897949f, 0.905762f, 0.914551f, 0.922363f, 0.929199f, 0.967285f, 0.966797f, + 0.964844f, 0.961426f, 0.959473f, 0.958008f, 0.003611f, 0.011971f, 0.020401f, 0.030029f, 0.039185f, 0.050415f, 0.061737f, 0.074341f, + 0.086975f, 0.101074f, 0.115845f, 0.131958f, 0.148682f, 0.166626f, 0.185059f, 0.205200f, 0.224854f, 0.245483f, 0.267334f, 0.290771f, + 0.312988f, 0.335449f, 0.359619f, 0.382080f, 0.406250f, 0.429443f, 0.452881f, 0.475830f, 0.498779f, 0.520996f, 0.542480f, 0.563477f, + 0.584473f, 0.604980f, 0.625977f, 0.643555f, 0.663086f, 0.681152f, 0.698242f, 0.714355f, 0.729980f, 0.746582f, 0.760742f, 0.774902f, + 0.788086f, 0.801758f, 0.814941f, 0.826660f, 0.838867f, 0.848633f, 0.859863f, 0.869141f, 0.879395f, 0.889160f, 0.897949f, 0.906250f, + 0.914551f, 0.922363f, 0.963867f, 0.964355f, 0.961914f, 0.959961f, 0.957520f, 0.955078f, 0.003393f, 0.010361f, 0.018494f, 0.026337f, + 0.035187f, 0.044556f, 0.054596f, 0.065186f, 0.077515f, 0.089783f, 0.102783f, 0.117249f, 0.132446f, 0.148071f, 0.165649f, 0.183838f, + 0.202026f, 0.221313f, 0.241943f, 0.262939f, 0.285156f, 0.307129f, 0.329102f, 0.352539f, 0.375977f, 0.398438f, 0.421875f, 0.445312f, + 0.468750f, 0.490723f, 0.512695f, 0.534668f, 0.556641f, 0.577637f, 0.598633f, 0.619141f, 0.637695f, 0.656738f, 0.674805f, 0.692383f, + 0.709473f, 0.726074f, 0.742188f, 0.756836f, 0.771973f, 0.786133f, 0.799316f, 0.812012f, 0.824707f, 0.835938f, 0.848145f, 0.858887f, + 0.868164f, 0.878906f, 0.888184f, 0.897949f, 0.906250f, 0.914551f, 0.960938f, 0.960938f, 0.959473f, 0.957520f, 0.955078f, 0.953125f, + 0.003084f, 0.009521f, 0.016144f, 0.023346f, 0.031204f, 0.039520f, 0.048523f, 0.057953f, 0.068359f, 0.079895f, 0.091309f, 0.104126f, + 0.117920f, 0.132324f, 0.147949f, 0.164062f, 0.181396f, 0.199219f, 0.218872f, 0.238403f, 0.258545f, 0.279541f, 0.301758f, 0.323486f, + 0.346191f, 0.368408f, 0.391846f, 0.414795f, 0.437256f, 0.460693f, 0.483643f, 0.505371f, 0.527832f, 0.550293f, 0.571289f, 0.591797f, + 0.612305f, 0.632324f, 0.651855f, 0.670898f, 0.687500f, 0.705566f, 0.722168f, 0.737793f, 0.753418f, 0.768555f, 0.783691f, 0.796875f, + 0.811035f, 0.823242f, 0.834473f, 0.846191f, 0.857422f, 0.868652f, 0.878418f, 0.887695f, 0.897949f, 0.906250f, 0.958008f, 0.958008f, + 0.957031f, 0.954590f, 0.952637f, 0.950684f, 0.002666f, 0.008293f, 0.014297f, 0.021225f, 0.027847f, 0.035156f, 0.043274f, 0.051666f, + 0.060791f, 0.070801f, 0.081543f, 0.092407f, 0.104858f, 0.118530f, 0.131836f, 0.146606f, 0.162598f, 0.179443f, 0.196777f, 0.215210f, + 0.234375f, 0.254150f, 0.274414f, 0.295898f, 0.317871f, 0.340088f, 0.362549f, 0.385010f, 0.407959f, 0.430664f, 0.454590f, 0.476562f, + 0.499268f, 0.521484f, 0.543945f, 0.564941f, 0.585938f, 0.606934f, 0.626465f, 0.646484f, 0.665527f, 0.683594f, 0.701660f, 0.717773f, + 0.735352f, 0.751465f, 0.766113f, 0.781738f, 0.794922f, 0.808105f, 0.821289f, 0.833496f, 0.846191f, 0.857910f, 0.868164f, 0.878906f, + 0.889160f, 0.899414f, 0.954102f, 0.955566f, 0.953613f, 0.952148f, 0.950195f, 0.948730f, 0.002396f, 0.007427f, 0.012978f, 0.018646f, + 0.025024f, 0.031403f, 0.038788f, 0.046112f, 0.054260f, 0.063354f, 0.072693f, 0.082886f, 0.093689f, 0.105469f, 0.118164f, 0.130859f, + 0.145996f, 0.161011f, 0.177124f, 0.193359f, 0.211670f, 0.230225f, 0.249634f, 0.270020f, 0.290771f, 0.311768f, 0.333740f, 0.356201f, + 0.378906f, 0.401855f, 0.424561f, 0.447754f, 0.470215f, 0.493408f, 0.515137f, 0.537109f, 0.559570f, 0.580078f, 0.601074f, 0.621582f, + 0.642090f, 0.661621f, 0.679688f, 0.697754f, 0.715820f, 0.732422f, 0.749512f, 0.765137f, 0.779785f, 0.794434f, 0.808594f, 0.821289f, + 0.833496f, 0.846191f, 0.857910f, 0.869141f, 0.879883f, 0.889648f, 0.950195f, 0.952637f, 0.950684f, 0.948730f, 0.947266f, 0.945801f, + 0.002029f, 0.006672f, 0.011658f, 0.016937f, 0.022476f, 0.028305f, 0.034332f, 0.041351f, 0.048584f, 0.056671f, 0.064697f, 0.073853f, + 0.083923f, 0.094482f, 0.105225f, 0.117798f, 0.130615f, 0.144287f, 0.159302f, 0.174683f, 0.190430f, 0.208740f, 0.226318f, 0.245483f, + 0.264893f, 0.285400f, 0.307129f, 0.328369f, 0.350342f, 0.372803f, 0.395264f, 0.418701f, 0.441650f, 0.462891f, 0.486816f, 0.509277f, + 0.532227f, 0.553711f, 0.575684f, 0.596680f, 0.617676f, 0.638672f, 0.657715f, 0.676758f, 0.695312f, 0.712402f, 0.729492f, 0.746582f, + 0.762695f, 0.778320f, 0.793457f, 0.807129f, 0.820801f, 0.833984f, 0.846191f, 0.858887f, 0.869629f, 0.881836f, 0.947266f, 0.949219f, + 0.947754f, 0.946289f, 0.944824f, 0.942871f, 0.002142f, 0.006401f, 0.010841f, 0.015251f, 0.019760f, 0.025055f, 0.031113f, 0.037201f, + 0.043671f, 0.050598f, 0.057892f, 0.066101f, 0.075012f, 0.084351f, 0.093994f, 0.105164f, 0.117432f, 0.129517f, 0.142822f, 0.157104f, + 0.172119f, 0.188110f, 0.204956f, 0.223145f, 0.241577f, 0.260498f, 0.280762f, 0.301758f, 0.322998f, 0.345215f, 0.366943f, 0.389893f, + 0.412842f, 0.435791f, 0.458008f, 0.482178f, 0.504395f, 0.526855f, 0.548828f, 0.571289f, 0.592285f, 0.612793f, 0.634277f, 0.654297f, + 0.673340f, 0.692383f, 0.710938f, 0.729004f, 0.745117f, 0.762207f, 0.777832f, 0.792480f, 0.807129f, 0.821289f, 0.834961f, 0.847168f, + 0.859863f, 0.871582f, 0.943359f, 0.946289f, 0.944824f, 0.943359f, 0.941895f, 0.940430f, 0.001760f, 0.005562f, 0.009621f, 0.013710f, + 0.018417f, 0.022736f, 0.027939f, 0.033264f, 0.039185f, 0.045166f, 0.052460f, 0.059143f, 0.067261f, 0.075745f, 0.084106f, 0.094177f, + 0.104980f, 0.116455f, 0.128174f, 0.141113f, 0.155151f, 0.169922f, 0.184937f, 0.201660f, 0.219238f, 0.237549f, 0.256348f, 0.276367f, + 0.296875f, 0.317871f, 0.339844f, 0.361572f, 0.383789f, 0.407227f, 0.430908f, 0.453857f, 0.476807f, 0.498779f, 0.521973f, 0.543945f, + 0.567383f, 0.589355f, 0.609863f, 0.631348f, 0.651855f, 0.671875f, 0.690918f, 0.709961f, 0.727539f, 0.744141f, 0.761719f, 0.777344f, + 0.793457f, 0.808594f, 0.823242f, 0.835449f, 0.848633f, 0.861328f, 0.938965f, 0.941895f, 0.941406f, 0.940430f, 0.938477f, 0.937012f, + 0.001594f, 0.005283f, 0.008789f, 0.012383f, 0.016342f, 0.020523f, 0.025284f, 0.029968f, 0.035217f, 0.040741f, 0.046417f, 0.052948f, + 0.060120f, 0.067566f, 0.076294f, 0.084534f, 0.093750f, 0.104614f, 0.115173f, 0.126831f, 0.139160f, 0.152832f, 0.166748f, 0.181885f, + 0.198853f, 0.215698f, 0.233521f, 0.252197f, 0.271973f, 0.291992f, 0.313477f, 0.334717f, 0.357178f, 0.379395f, 0.401855f, 0.425537f, + 0.448242f, 0.471924f, 0.495361f, 0.517578f, 0.541016f, 0.562988f, 0.585938f, 0.607422f, 0.627930f, 0.649414f, 0.670410f, 0.688965f, + 0.708496f, 0.727539f, 0.744629f, 0.761719f, 0.778809f, 0.794922f, 0.809082f, 0.824219f, 0.838379f, 0.851074f, 0.935059f, 0.938965f, + 0.937988f, 0.937012f, 0.936035f, 0.933594f, 0.001564f, 0.004665f, 0.007973f, 0.011276f, 0.014908f, 0.018600f, 0.022675f, 0.027176f, + 0.031464f, 0.036621f, 0.042023f, 0.047974f, 0.054108f, 0.060822f, 0.068237f, 0.075684f, 0.084229f, 0.093567f, 0.103210f, 0.113892f, + 0.125000f, 0.137329f, 0.150269f, 0.164307f, 0.179810f, 0.194946f, 0.212158f, 0.229248f, 0.247925f, 0.267578f, 0.287842f, 0.308350f, + 0.330322f, 0.352051f, 0.374756f, 0.397461f, 0.420654f, 0.444092f, 0.466797f, 0.490723f, 0.514160f, 0.537109f, 0.560059f, 0.582031f, + 0.604980f, 0.626953f, 0.648926f, 0.668457f, 0.688477f, 0.708008f, 0.727539f, 0.745117f, 0.763672f, 0.779297f, 0.795410f, 0.811523f, + 0.826660f, 0.840332f, 0.930664f, 0.934570f, 0.934082f, 0.933594f, 0.932129f, 0.930664f, 0.001424f, 0.004261f, 0.007122f, 0.010239f, + 0.013374f, 0.016693f, 0.020401f, 0.024368f, 0.028595f, 0.033325f, 0.037964f, 0.043152f, 0.048340f, 0.054962f, 0.060730f, 0.067749f, + 0.075684f, 0.083862f, 0.092041f, 0.102051f, 0.112305f, 0.123657f, 0.135376f, 0.148071f, 0.161987f, 0.176270f, 0.192139f, 0.208252f, + 0.226196f, 0.244141f, 0.263672f, 0.283447f, 0.304199f, 0.325195f, 0.346924f, 0.370605f, 0.392822f, 0.416260f, 0.439209f, 0.463623f, + 0.486084f, 0.511230f, 0.534180f, 0.558105f, 0.580566f, 0.603516f, 0.625000f, 0.647461f, 0.668457f, 0.688965f, 0.708496f, 0.727539f, + 0.746582f, 0.764160f, 0.781738f, 0.798340f, 0.813477f, 0.829590f, 0.926758f, 0.931152f, 0.930664f, 0.929199f, 0.928223f, 0.927246f, + 0.001294f, 0.004196f, 0.006538f, 0.009346f, 0.012306f, 0.015335f, 0.018845f, 0.022003f, 0.025558f, 0.029816f, 0.034149f, 0.038605f, + 0.043915f, 0.049042f, 0.054810f, 0.061188f, 0.067993f, 0.075256f, 0.083130f, 0.091553f, 0.100769f, 0.110779f, 0.121643f, 0.133057f, + 0.145630f, 0.159058f, 0.173218f, 0.188721f, 0.204590f, 0.222290f, 0.240234f, 0.259277f, 0.279053f, 0.299561f, 0.321533f, 0.343506f, + 0.365723f, 0.389404f, 0.412354f, 0.436035f, 0.459961f, 0.484131f, 0.508301f, 0.532227f, 0.555176f, 0.579102f, 0.601562f, 0.624512f, + 0.646484f, 0.668457f, 0.688965f, 0.709473f, 0.729004f, 0.748047f, 0.766602f, 0.784668f, 0.800293f, 0.817383f, 0.921875f, 0.926270f, + 0.926270f, 0.925781f, 0.924316f, 0.923340f, 0.001081f, 0.003603f, 0.006027f, 0.008575f, 0.010979f, 0.013847f, 0.016937f, 0.020020f, + 0.023315f, 0.026917f, 0.030930f, 0.035156f, 0.039429f, 0.044098f, 0.049622f, 0.054779f, 0.060791f, 0.067566f, 0.074341f, 0.082336f, + 0.090515f, 0.099548f, 0.109070f, 0.119263f, 0.130981f, 0.143188f, 0.156250f, 0.170288f, 0.185303f, 0.201294f, 0.218262f, 0.236450f, + 0.255615f, 0.275391f, 0.295654f, 0.316895f, 0.339111f, 0.362061f, 0.385498f, 0.408936f, 0.432861f, 0.457275f, 0.481689f, 0.505371f, + 0.529785f, 0.553711f, 0.577637f, 0.601074f, 0.624023f, 0.646484f, 0.669434f, 0.689941f, 0.711426f, 0.731445f, 0.750977f, 0.770020f, + 0.787598f, 0.804688f, 0.916992f, 0.922363f, 0.922363f, 0.921875f, 0.920898f, 0.918945f, 0.001064f, 0.003231f, 0.005322f, 0.007710f, + 0.010323f, 0.012489f, 0.015244f, 0.018051f, 0.020798f, 0.024338f, 0.027893f, 0.031738f, 0.035553f, 0.039795f, 0.044495f, 0.049133f, + 0.054657f, 0.060608f, 0.066895f, 0.073792f, 0.081421f, 0.089050f, 0.097717f, 0.106934f, 0.117554f, 0.128540f, 0.140503f, 0.153442f, + 0.167236f, 0.182129f, 0.197998f, 0.214966f, 0.232422f, 0.251465f, 0.271240f, 0.291992f, 0.313232f, 0.335693f, 0.358643f, 0.382080f, + 0.406006f, 0.430176f, 0.454590f, 0.479004f, 0.503906f, 0.528320f, 0.552734f, 0.577637f, 0.601562f, 0.625000f, 0.648438f, 0.670898f, + 0.691895f, 0.713867f, 0.733887f, 0.754883f, 0.774414f, 0.791992f, 0.912109f, 0.917969f, 0.918457f, 0.916992f, 0.916016f, 0.915039f, + 0.000998f, 0.003012f, 0.005123f, 0.007114f, 0.009438f, 0.011360f, 0.013763f, 0.016510f, 0.018951f, 0.022171f, 0.025101f, 0.028305f, + 0.031830f, 0.035736f, 0.039795f, 0.044067f, 0.048950f, 0.053864f, 0.059601f, 0.066345f, 0.072815f, 0.079956f, 0.087402f, 0.096375f, + 0.105835f, 0.115479f, 0.126343f, 0.138184f, 0.150635f, 0.164062f, 0.178711f, 0.194214f, 0.210815f, 0.229004f, 0.247314f, 0.267090f, + 0.288330f, 0.309570f, 0.332275f, 0.355469f, 0.378418f, 0.402832f, 0.427490f, 0.452637f, 0.477783f, 0.501953f, 0.527832f, 0.552734f, + 0.577637f, 0.602051f, 0.626465f, 0.649902f, 0.672852f, 0.695312f, 0.717773f, 0.737793f, 0.758789f, 0.778809f, 0.906250f, 0.913086f, + 0.913574f, 0.912598f, 0.911621f, 0.910645f, 0.001059f, 0.002985f, 0.004475f, 0.006496f, 0.008545f, 0.010300f, 0.012581f, 0.014969f, + 0.017471f, 0.019852f, 0.022507f, 0.025864f, 0.028824f, 0.032135f, 0.036041f, 0.039795f, 0.043884f, 0.048706f, 0.053680f, 0.059113f, + 0.064819f, 0.071472f, 0.078491f, 0.086365f, 0.094360f, 0.103577f, 0.113403f, 0.124023f, 0.135620f, 0.147705f, 0.160889f, 0.175537f, + 0.191284f, 0.207764f, 0.225464f, 0.244263f, 0.264160f, 0.284912f, 0.306641f, 0.329102f, 0.352295f, 0.376465f, 0.400635f, 0.426025f, + 0.451416f, 0.476562f, 0.502930f, 0.527344f, 0.553711f, 0.579102f, 0.603027f, 0.627930f, 0.652344f, 0.675781f, 0.700195f, 0.722168f, + 0.742676f, 0.764648f, 0.901367f, 0.907715f, 0.908691f, 0.908203f, 0.907227f, 0.906250f, 0.000988f, 0.002577f, 0.004124f, 0.006042f, + 0.007603f, 0.009506f, 0.011299f, 0.013680f, 0.015778f, 0.017883f, 0.020554f, 0.023102f, 0.025940f, 0.028946f, 0.031891f, 0.035431f, + 0.039825f, 0.043671f, 0.048157f, 0.053009f, 0.058075f, 0.063782f, 0.069885f, 0.077087f, 0.084839f, 0.092712f, 0.101379f, 0.110779f, + 0.121155f, 0.132446f, 0.144775f, 0.157837f, 0.172363f, 0.187744f, 0.204590f, 0.222290f, 0.240601f, 0.260254f, 0.281494f, 0.303223f, + 0.325439f, 0.349609f, 0.373535f, 0.399170f, 0.424561f, 0.450439f, 0.475586f, 0.501953f, 0.528320f, 0.554688f, 0.580566f, 0.605957f, + 0.630859f, 0.656250f, 0.680176f, 0.704102f, 0.727051f, 0.749512f, 0.895508f, 0.902344f, 0.903320f, 0.902832f, 0.901855f, 0.901855f, + 0.000842f, 0.002253f, 0.003597f, 0.005352f, 0.007195f, 0.008804f, 0.010460f, 0.012100f, 0.014130f, 0.016281f, 0.018341f, 0.021057f, + 0.023193f, 0.025742f, 0.029022f, 0.031830f, 0.035278f, 0.039246f, 0.042999f, 0.047211f, 0.052032f, 0.056946f, 0.062744f, 0.068848f, + 0.075195f, 0.082642f, 0.090332f, 0.099060f, 0.108215f, 0.118469f, 0.129517f, 0.141724f, 0.154907f, 0.169434f, 0.184448f, 0.201172f, + 0.218506f, 0.237427f, 0.257324f, 0.278320f, 0.300293f, 0.323242f, 0.347412f, 0.372070f, 0.397217f, 0.423340f, 0.449707f, 0.476807f, + 0.502930f, 0.529785f, 0.556641f, 0.582520f, 0.609863f, 0.635254f, 0.660645f, 0.686035f, 0.710938f, 0.733887f, 0.889648f, 0.897461f, + 0.898926f, 0.896973f, 0.896973f, 0.896484f, 0.000660f, 0.002014f, 0.003531f, 0.004951f, 0.006424f, 0.007935f, 0.009392f, 0.011322f, + 0.012924f, 0.014824f, 0.016754f, 0.018906f, 0.020935f, 0.023376f, 0.026245f, 0.028809f, 0.031860f, 0.034821f, 0.038330f, 0.042236f, + 0.046387f, 0.050812f, 0.056061f, 0.061279f, 0.066956f, 0.073547f, 0.080566f, 0.088074f, 0.096802f, 0.106079f, 0.116089f, 0.127075f, + 0.138672f, 0.151855f, 0.165649f, 0.180908f, 0.197754f, 0.215332f, 0.234375f, 0.254150f, 0.275391f, 0.298096f, 0.321533f, 0.344971f, + 0.370361f, 0.396973f, 0.422852f, 0.449219f, 0.477295f, 0.504395f, 0.532227f, 0.558594f, 0.586914f, 0.614258f, 0.640625f, 0.666016f, + 0.692871f, 0.718262f, 0.882812f, 0.891602f, 0.892578f, 0.892090f, 0.892090f, 0.890625f, 0.000623f, 0.002073f, 0.003298f, 0.004292f, + 0.005589f, 0.007401f, 0.008377f, 0.010315f, 0.011871f, 0.013596f, 0.015213f, 0.016632f, 0.018829f, 0.020920f, 0.023239f, 0.025726f, + 0.028381f, 0.031250f, 0.034241f, 0.037781f, 0.041473f, 0.045349f, 0.049469f, 0.054199f, 0.059448f, 0.065186f, 0.071716f, 0.078613f, + 0.085999f, 0.093872f, 0.103516f, 0.112976f, 0.123840f, 0.135620f, 0.148804f, 0.162720f, 0.178223f, 0.194824f, 0.212280f, 0.231079f, + 0.251953f, 0.273193f, 0.295410f, 0.319580f, 0.343994f, 0.370117f, 0.396729f, 0.422852f, 0.450684f, 0.478516f, 0.507324f, 0.534668f, + 0.562988f, 0.591797f, 0.619629f, 0.646484f, 0.674316f, 0.700195f, 0.875488f, 0.885254f, 0.886719f, 0.886719f, 0.885742f, 0.885254f, + 0.000583f, 0.001746f, 0.002840f, 0.004143f, 0.005234f, 0.006516f, 0.007835f, 0.009460f, 0.010788f, 0.012062f, 0.013428f, 0.015053f, + 0.017349f, 0.018753f, 0.021271f, 0.023163f, 0.025284f, 0.027924f, 0.030655f, 0.033478f, 0.036957f, 0.040527f, 0.044037f, 0.048309f, + 0.053223f, 0.058319f, 0.063660f, 0.069763f, 0.076172f, 0.083679f, 0.091431f, 0.100647f, 0.110229f, 0.120667f, 0.132690f, 0.145386f, + 0.159668f, 0.174805f, 0.191284f, 0.208984f, 0.228516f, 0.248535f, 0.270996f, 0.293701f, 0.317383f, 0.342529f, 0.369629f, 0.396240f, + 0.424072f, 0.452148f, 0.480957f, 0.509277f, 0.539551f, 0.567871f, 0.596680f, 0.625977f, 0.654785f, 0.682129f, 0.868652f, 0.878906f, + 0.880371f, 0.879883f, 0.879883f, 0.879395f, 0.000535f, 0.001538f, 0.002930f, 0.003725f, 0.004986f, 0.005920f, 0.006973f, 0.008247f, + 0.009575f, 0.010841f, 0.012115f, 0.013550f, 0.015343f, 0.016983f, 0.018814f, 0.020523f, 0.022568f, 0.024887f, 0.027206f, 0.029907f, + 0.032959f, 0.035828f, 0.039185f, 0.042877f, 0.046967f, 0.051605f, 0.056213f, 0.061432f, 0.067749f, 0.073730f, 0.081238f, 0.089111f, + 0.097656f, 0.107300f, 0.118042f, 0.129883f, 0.142334f, 0.156250f, 0.171875f, 0.187866f, 0.206665f, 0.225708f, 0.246704f, 0.268799f, + 0.291992f, 0.316650f, 0.342529f, 0.369629f, 0.397217f, 0.425537f, 0.454590f, 0.484131f, 0.513672f, 0.544434f, 0.574219f, 0.604492f, + 0.633789f, 0.664062f, 0.861328f, 0.871582f, 0.873535f, 0.874512f, 0.873047f, 0.872559f, 0.000581f, 0.001668f, 0.002563f, 0.003471f, + 0.004494f, 0.005562f, 0.006580f, 0.007782f, 0.008690f, 0.009766f, 0.011261f, 0.012314f, 0.013901f, 0.014969f, 0.016479f, 0.018265f, + 0.020294f, 0.022156f, 0.024353f, 0.026505f, 0.029053f, 0.031799f, 0.034607f, 0.037964f, 0.041382f, 0.045471f, 0.049591f, 0.054047f, + 0.059326f, 0.065186f, 0.071411f, 0.078735f, 0.086304f, 0.094971f, 0.104126f, 0.114807f, 0.126587f, 0.138916f, 0.153564f, 0.169067f, + 0.185669f, 0.203613f, 0.223389f, 0.244629f, 0.266602f, 0.291260f, 0.316406f, 0.342773f, 0.370361f, 0.398926f, 0.427734f, 0.458008f, + 0.488770f, 0.520020f, 0.550293f, 0.582031f, 0.613281f, 0.645020f, 0.854004f, 0.865234f, 0.866699f, 0.867188f, 0.866699f, 0.866699f, + 0.000571f, 0.001365f, 0.002483f, 0.003033f, 0.004120f, 0.005054f, 0.005981f, 0.006737f, 0.007603f, 0.008675f, 0.009789f, 0.011078f, + 0.012413f, 0.013626f, 0.014908f, 0.016174f, 0.017792f, 0.019699f, 0.021591f, 0.023499f, 0.025635f, 0.028000f, 0.030533f, 0.033417f, + 0.036499f, 0.039948f, 0.043762f, 0.047943f, 0.052460f, 0.057465f, 0.062622f, 0.068848f, 0.076111f, 0.083557f, 0.092102f, 0.101562f, + 0.111816f, 0.123230f, 0.135864f, 0.150024f, 0.165771f, 0.182373f, 0.200806f, 0.221191f, 0.242920f, 0.265869f, 0.290283f, 0.316406f, + 0.343262f, 0.371582f, 0.400879f, 0.431396f, 0.463623f, 0.494629f, 0.526367f, 0.558105f, 0.591309f, 0.624023f, 0.845215f, 0.856934f, + 0.859375f, 0.859375f, 0.859863f, 0.860352f, 0.000411f, 0.001296f, 0.002012f, 0.002808f, 0.003754f, 0.004543f, 0.005215f, 0.006012f, + 0.006725f, 0.007851f, 0.008888f, 0.009979f, 0.010994f, 0.012009f, 0.013062f, 0.014549f, 0.016113f, 0.017441f, 0.019073f, 0.020767f, + 0.022598f, 0.024689f, 0.026764f, 0.029358f, 0.032043f, 0.034760f, 0.038391f, 0.041779f, 0.045380f, 0.050110f, 0.055054f, 0.060394f, + 0.066650f, 0.073120f, 0.080688f, 0.089233f, 0.098450f, 0.108582f, 0.120178f, 0.133057f, 0.146973f, 0.162354f, 0.179565f, 0.198364f, + 0.218750f, 0.240967f, 0.264648f, 0.290039f, 0.316650f, 0.344971f, 0.374023f, 0.404541f, 0.435791f, 0.467773f, 0.500977f, 0.535156f, + 0.569336f, 0.601562f, 0.836914f, 0.850098f, 0.852051f, 0.852539f, 0.852539f, 0.852051f, 0.000408f, 0.001071f, 0.001857f, 0.002573f, + 0.003338f, 0.004078f, 0.004692f, 0.005379f, 0.006046f, 0.007275f, 0.007957f, 0.008606f, 0.009598f, 0.010864f, 0.011658f, 0.013084f, + 0.013977f, 0.015366f, 0.016724f, 0.018402f, 0.019669f, 0.021759f, 0.023697f, 0.025726f, 0.027954f, 0.030640f, 0.033356f, 0.036530f, + 0.039948f, 0.043701f, 0.047791f, 0.052704f, 0.057770f, 0.063782f, 0.070129f, 0.077881f, 0.085999f, 0.095337f, 0.105591f, 0.116882f, + 0.130005f, 0.143921f, 0.159302f, 0.177246f, 0.196411f, 0.217163f, 0.239746f, 0.263916f, 0.290039f, 0.317871f, 0.346924f, 0.377441f, + 0.408936f, 0.442139f, 0.476074f, 0.509766f, 0.545410f, 0.580078f, 0.828613f, 0.841309f, 0.843262f, 0.844238f, 0.843750f, 0.844238f, + 0.000322f, 0.001009f, 0.001674f, 0.002262f, 0.002949f, 0.003633f, 0.004250f, 0.004780f, 0.005478f, 0.006256f, 0.007248f, 0.007919f, + 0.008720f, 0.009552f, 0.010277f, 0.011391f, 0.012291f, 0.013466f, 0.014786f, 0.015976f, 0.017288f, 0.019043f, 0.020477f, 0.022385f, + 0.024292f, 0.026276f, 0.029175f, 0.031769f, 0.034546f, 0.037842f, 0.041626f, 0.045868f, 0.050293f, 0.055084f, 0.060669f, 0.067688f, + 0.074585f, 0.083008f, 0.092102f, 0.102234f, 0.113525f, 0.126587f, 0.140869f, 0.156860f, 0.174805f, 0.194214f, 0.215698f, 0.239014f, + 0.264404f, 0.291016f, 0.320068f, 0.350098f, 0.382080f, 0.414551f, 0.449463f, 0.485107f, 0.520996f, 0.557617f, 0.818848f, 0.833496f, + 0.836426f, 0.836914f, 0.836426f, 0.835938f, 0.000483f, 0.000841f, 0.001632f, 0.002142f, 0.002678f, 0.003359f, 0.003830f, 0.004333f, + 0.005077f, 0.005527f, 0.006104f, 0.006908f, 0.007675f, 0.008392f, 0.009216f, 0.009789f, 0.010880f, 0.011719f, 0.012817f, 0.013809f, + 0.015068f, 0.016357f, 0.017883f, 0.019485f, 0.021271f, 0.022995f, 0.025162f, 0.027359f, 0.029755f, 0.032806f, 0.036133f, 0.039459f, + 0.043091f, 0.047821f, 0.052368f, 0.058258f, 0.064514f, 0.071472f, 0.079224f, 0.088623f, 0.098694f, 0.109924f, 0.123230f, 0.137817f, + 0.154053f, 0.172363f, 0.192261f, 0.214478f, 0.238647f, 0.265137f, 0.292725f, 0.322998f, 0.354492f, 0.387695f, 0.422363f, 0.458740f, + 0.495605f, 0.533691f, 0.809570f, 0.824219f, 0.826660f, 0.827148f, 0.828125f, 0.827148f, 0.000240f, 0.000906f, 0.001379f, 0.001807f, + 0.002495f, 0.002916f, 0.003490f, 0.004139f, 0.004471f, 0.004898f, 0.005638f, 0.005978f, 0.006874f, 0.007313f, 0.007957f, 0.008698f, + 0.009560f, 0.010178f, 0.011345f, 0.012177f, 0.012985f, 0.014214f, 0.015274f, 0.016708f, 0.017929f, 0.019882f, 0.021393f, 0.023560f, + 0.025406f, 0.028137f, 0.030472f, 0.033752f, 0.036896f, 0.040619f, 0.044952f, 0.049622f, 0.055298f, 0.061249f, 0.068420f, 0.075928f, + 0.084900f, 0.095398f, 0.107300f, 0.119934f, 0.134766f, 0.151733f, 0.170410f, 0.191284f, 0.213867f, 0.238647f, 0.265869f, 0.295654f, + 0.326660f, 0.359863f, 0.394775f, 0.432129f, 0.469482f, 0.508789f, 0.798340f, 0.814941f, 0.817871f, 0.818359f, 0.818848f, 0.818848f, + 0.000376f, 0.000870f, 0.001291f, 0.001619f, 0.002251f, 0.002520f, 0.003016f, 0.003502f, 0.004036f, 0.004299f, 0.004723f, 0.005234f, + 0.005840f, 0.006512f, 0.006908f, 0.007595f, 0.008003f, 0.008797f, 0.009773f, 0.010536f, 0.011284f, 0.012161f, 0.013237f, 0.014465f, + 0.015579f, 0.016968f, 0.018402f, 0.019882f, 0.021759f, 0.023621f, 0.026138f, 0.028488f, 0.031738f, 0.034668f, 0.038239f, 0.042389f, + 0.046783f, 0.052094f, 0.058319f, 0.064941f, 0.072815f, 0.081726f, 0.092102f, 0.103516f, 0.117188f, 0.132202f, 0.149048f, 0.168091f, + 0.189941f, 0.213745f, 0.239990f, 0.268311f, 0.299316f, 0.332275f, 0.367188f, 0.403076f, 0.442871f, 0.483398f, 0.788086f, 0.805176f, + 0.808105f, 0.808594f, 0.809082f, 0.809082f, 0.000386f, 0.000765f, 0.000998f, 0.001537f, 0.001833f, 0.002407f, 0.002529f, 0.003113f, + 0.003334f, 0.003841f, 0.004192f, 0.004585f, 0.005096f, 0.005543f, 0.006073f, 0.006405f, 0.007118f, 0.007641f, 0.008278f, 0.008957f, + 0.009651f, 0.010498f, 0.011307f, 0.012184f, 0.013199f, 0.014343f, 0.015671f, 0.016678f, 0.018585f, 0.019852f, 0.021881f, 0.023987f, + 0.026398f, 0.029099f, 0.032227f, 0.035339f, 0.039246f, 0.043915f, 0.048859f, 0.054688f, 0.061554f, 0.069519f, 0.078247f, 0.088379f, + 0.100037f, 0.113770f, 0.129272f, 0.146606f, 0.166626f, 0.189575f, 0.214111f, 0.241577f, 0.271973f, 0.304199f, 0.339844f, 0.375977f, + 0.415527f, 0.457275f, 0.776855f, 0.794434f, 0.797363f, 0.797852f, 0.798828f, 0.799316f, 0.000232f, 0.000636f, 0.000996f, 0.001201f, + 0.001721f, 0.002029f, 0.002340f, 0.002802f, 0.003012f, 0.003462f, 0.003693f, 0.004059f, 0.004295f, 0.004822f, 0.005077f, 0.005623f, + 0.006126f, 0.006653f, 0.007027f, 0.007561f, 0.008049f, 0.008904f, 0.009399f, 0.010300f, 0.011200f, 0.012115f, 0.013092f, 0.014221f, + 0.015671f, 0.016891f, 0.018433f, 0.020294f, 0.022064f, 0.024277f, 0.026688f, 0.029678f, 0.032654f, 0.036499f, 0.040955f, 0.045715f, + 0.051514f, 0.058014f, 0.065674f, 0.074707f, 0.084717f, 0.096802f, 0.111023f, 0.126709f, 0.144775f, 0.165771f, 0.189209f, 0.215820f, + 0.244385f, 0.275879f, 0.310547f, 0.348145f, 0.387695f, 0.429932f, 0.765137f, 0.783203f, 0.787109f, 0.788574f, 0.788574f, 0.789551f, + 0.000171f, 0.000518f, 0.001106f, 0.001242f, 0.001475f, 0.001939f, 0.002092f, 0.002254f, 0.002607f, 0.002930f, 0.003084f, 0.003382f, + 0.003674f, 0.004040f, 0.004395f, 0.004780f, 0.005157f, 0.005653f, 0.006088f, 0.006355f, 0.006870f, 0.007420f, 0.008057f, 0.008667f, + 0.009361f, 0.010040f, 0.011101f, 0.011803f, 0.012711f, 0.013962f, 0.015343f, 0.016586f, 0.018036f, 0.020142f, 0.022079f, 0.024399f, + 0.027023f, 0.030075f, 0.033569f, 0.037750f, 0.042603f, 0.048096f, 0.054718f, 0.062134f, 0.071045f, 0.081299f, 0.093445f, 0.107605f, + 0.124268f, 0.142944f, 0.165405f, 0.189941f, 0.218262f, 0.249268f, 0.282227f, 0.319336f, 0.359375f, 0.402832f, 0.752930f, 0.771973f, + 0.775879f, 0.776855f, 0.777832f, 0.777832f, 0.000204f, 0.000608f, 0.000865f, 0.001011f, 0.001362f, 0.001632f, 0.001817f, 0.001930f, + 0.002274f, 0.002491f, 0.002796f, 0.002932f, 0.003139f, 0.003429f, 0.003736f, 0.004055f, 0.004448f, 0.004829f, 0.004971f, 0.005497f, + 0.005859f, 0.006298f, 0.006741f, 0.007080f, 0.007687f, 0.008308f, 0.009087f, 0.009880f, 0.010735f, 0.011528f, 0.012375f, 0.013664f, + 0.014862f, 0.016464f, 0.017868f, 0.019852f, 0.022156f, 0.024490f, 0.027435f, 0.030853f, 0.034637f, 0.039154f, 0.044495f, 0.050964f, + 0.058441f, 0.067383f, 0.077759f, 0.090332f, 0.104797f, 0.121826f, 0.142334f, 0.164795f, 0.191528f, 0.221313f, 0.254150f, 0.290771f, + 0.330078f, 0.374268f, 0.740234f, 0.759277f, 0.763672f, 0.766113f, 0.766602f, 0.766113f, 0.000150f, 0.000514f, 0.000666f, 0.000865f, + 0.001163f, 0.001389f, 0.001540f, 0.001672f, 0.001940f, 0.002110f, 0.002302f, 0.002419f, 0.002745f, 0.002974f, 0.003120f, 0.003366f, + 0.003695f, 0.003815f, 0.004173f, 0.004574f, 0.004879f, 0.005165f, 0.005646f, 0.006058f, 0.006481f, 0.006969f, 0.007626f, 0.007881f, + 0.008751f, 0.009445f, 0.010231f, 0.011246f, 0.012222f, 0.013268f, 0.014641f, 0.015976f, 0.017792f, 0.019867f, 0.021912f, 0.024704f, + 0.027786f, 0.031494f, 0.036011f, 0.041229f, 0.047363f, 0.054962f, 0.063904f, 0.074463f, 0.087036f, 0.102295f, 0.120483f, 0.141113f, + 0.166260f, 0.194214f, 0.226196f, 0.261719f, 0.301514f, 0.345459f, 0.727051f, 0.747070f, 0.751953f, 0.753418f, 0.754395f, 0.754883f, + 0.000103f, 0.000251f, 0.000628f, 0.000912f, 0.000978f, 0.001191f, 0.001365f, 0.001507f, 0.001513f, 0.001757f, 0.001980f, 0.002121f, + 0.002316f, 0.002373f, 0.002645f, 0.002909f, 0.003012f, 0.003305f, 0.003538f, 0.003775f, 0.004070f, 0.004246f, 0.004642f, 0.004986f, + 0.005394f, 0.005802f, 0.006031f, 0.006565f, 0.006969f, 0.007618f, 0.008293f, 0.008980f, 0.009766f, 0.010612f, 0.011528f, 0.012802f, + 0.014198f, 0.015671f, 0.017517f, 0.019592f, 0.021957f, 0.024918f, 0.028442f, 0.032562f, 0.037567f, 0.043762f, 0.051025f, 0.059753f, + 0.071045f, 0.084412f, 0.099792f, 0.119385f, 0.141846f, 0.167969f, 0.199341f, 0.233521f, 0.272461f, 0.315674f, 0.712891f, 0.733887f, + 0.738770f, 0.740234f, 0.741211f, 0.741699f, 0.000185f, 0.000434f, 0.000489f, 0.000732f, 0.000874f, 0.000968f, 0.001122f, 0.001124f, + 0.001371f, 0.001423f, 0.001639f, 0.001693f, 0.001805f, 0.002094f, 0.002241f, 0.002356f, 0.002567f, 0.002691f, 0.002871f, 0.003063f, + 0.003195f, 0.003582f, 0.003790f, 0.004089f, 0.004372f, 0.004536f, 0.005085f, 0.005314f, 0.005699f, 0.006153f, 0.006672f, 0.007202f, + 0.007805f, 0.008522f, 0.009216f, 0.010071f, 0.011086f, 0.012184f, 0.013596f, 0.015297f, 0.017014f, 0.019363f, 0.021988f, 0.025299f, + 0.029282f, 0.033936f, 0.040070f, 0.047028f, 0.056519f, 0.067932f, 0.080872f, 0.098083f, 0.118469f, 0.143188f, 0.171753f, 0.205200f, + 0.243286f, 0.286133f, 0.698730f, 0.721680f, 0.725098f, 0.727051f, 0.728027f, 0.728516f, 0.000116f, 0.000267f, 0.000565f, 0.000505f, + 0.000648f, 0.000772f, 0.000813f, 0.001031f, 0.001107f, 0.001184f, 0.001335f, 0.001391f, 0.001451f, 0.001633f, 0.001798f, 0.001874f, + 0.002090f, 0.002192f, 0.002392f, 0.002464f, 0.002707f, 0.002895f, 0.003044f, 0.003206f, 0.003468f, 0.003666f, 0.003887f, 0.004261f, + 0.004524f, 0.004898f, 0.005379f, 0.005711f, 0.006130f, 0.006721f, 0.007267f, 0.007912f, 0.008659f, 0.009575f, 0.010475f, 0.011749f, + 0.013252f, 0.014717f, 0.016815f, 0.019302f, 0.022369f, 0.025955f, 0.030502f, 0.036285f, 0.043579f, 0.052795f, 0.064453f, 0.078735f, + 0.096497f, 0.118591f, 0.145508f, 0.177368f, 0.213989f, 0.256592f, 0.683105f, 0.707031f, 0.710938f, 0.713379f, 0.714844f, 0.714844f, + 0.000223f, 0.000239f, 0.000286f, 0.000476f, 0.000580f, 0.000647f, 0.000715f, 0.000843f, 0.000914f, 0.000950f, 0.001090f, 0.001163f, + 0.001259f, 0.001328f, 0.001392f, 0.001560f, 0.001549f, 0.001775f, 0.001868f, 0.001999f, 0.002199f, 0.002235f, 0.002436f, 0.002575f, + 0.002842f, 0.002892f, 0.003111f, 0.003401f, 0.003563f, 0.003887f, 0.004196f, 0.004505f, 0.004791f, 0.005142f, 0.005684f, 0.006153f, + 0.006710f, 0.007378f, 0.008064f, 0.008881f, 0.009979f, 0.011177f, 0.012779f, 0.014435f, 0.016647f, 0.019150f, 0.022583f, 0.027252f, + 0.033051f, 0.040039f, 0.049561f, 0.061340f, 0.076843f, 0.096313f, 0.120544f, 0.150513f, 0.185547f, 0.227173f, 0.668457f, 0.692383f, + 0.696289f, 0.698242f, 0.699219f, 0.701172f, 0.000000f, 0.000109f, 0.000315f, 0.000449f, 0.000511f, 0.000507f, 0.000538f, 0.000653f, + 0.000724f, 0.000749f, 0.000830f, 0.000893f, 0.001007f, 0.001079f, 0.001189f, 0.001163f, 0.001335f, 0.001307f, 0.001502f, 0.001575f, + 0.001627f, 0.001778f, 0.001933f, 0.002029f, 0.002155f, 0.002254f, 0.002401f, 0.002535f, 0.002829f, 0.002943f, 0.003143f, 0.003422f, + 0.003710f, 0.003990f, 0.004318f, 0.004627f, 0.005108f, 0.005585f, 0.006142f, 0.006641f, 0.007378f, 0.008354f, 0.009430f, 0.010628f, + 0.012123f, 0.014015f, 0.016541f, 0.019836f, 0.023849f, 0.029312f, 0.036774f, 0.046356f, 0.058868f, 0.075562f, 0.097107f, 0.124634f, + 0.157837f, 0.197754f, 0.653320f, 0.677734f, 0.682129f, 0.684082f, 0.685547f, 0.684570f, 0.000166f, 0.000195f, 0.000256f, 0.000372f, + 0.000386f, 0.000415f, 0.000515f, 0.000432f, 0.000579f, 0.000606f, 0.000706f, 0.000745f, 0.000764f, 0.000837f, 0.000853f, 0.000993f, + 0.001034f, 0.001066f, 0.001156f, 0.001203f, 0.001339f, 0.001418f, 0.001470f, 0.001612f, 0.001614f, 0.001707f, 0.001850f, 0.001986f, + 0.002151f, 0.002254f, 0.002499f, 0.002560f, 0.002794f, 0.003000f, 0.003212f, 0.003510f, 0.003761f, 0.004086f, 0.004475f, 0.004967f, + 0.005428f, 0.006134f, 0.006840f, 0.007786f, 0.008858f, 0.010033f, 0.011909f, 0.014137f, 0.016907f, 0.020767f, 0.025894f, 0.033386f, + 0.043274f, 0.056854f, 0.075439f, 0.099548f, 0.130737f, 0.169434f, 0.634277f, 0.661133f, 0.667480f, 0.668945f, 0.669922f, 0.670898f, + 0.000115f, 0.000119f, 0.000230f, 0.000304f, 0.000221f, 0.000380f, 0.000322f, 0.000351f, 0.000453f, 0.000527f, 0.000535f, 0.000558f, + 0.000595f, 0.000675f, 0.000707f, 0.000670f, 0.000776f, 0.000812f, 0.000839f, 0.000911f, 0.000974f, 0.001033f, 0.001082f, 0.001154f, + 0.001209f, 0.001268f, 0.001416f, 0.001432f, 0.001607f, 0.001775f, 0.001877f, 0.001911f, 0.002041f, 0.002207f, 0.002380f, 0.002563f, + 0.002741f, 0.002956f, 0.003281f, 0.003513f, 0.003902f, 0.004353f, 0.004803f, 0.005405f, 0.006256f, 0.007072f, 0.008263f, 0.009659f, + 0.011627f, 0.014221f, 0.017792f, 0.022919f, 0.030075f, 0.040497f, 0.055878f, 0.076721f, 0.104980f, 0.141357f, 0.618652f, 0.644531f, + 0.650391f, 0.652832f, 0.653320f, 0.654785f, 0.000000f, 0.000122f, 0.000142f, 0.000227f, 0.000248f, 0.000246f, 0.000296f, 0.000254f, + 0.000308f, 0.000329f, 0.000387f, 0.000437f, 0.000443f, 0.000504f, 0.000515f, 0.000535f, 0.000566f, 0.000592f, 0.000618f, 0.000641f, + 0.000706f, 0.000746f, 0.000787f, 0.000839f, 0.000878f, 0.000920f, 0.001043f, 0.001041f, 0.001136f, 0.001199f, 0.001258f, 0.001393f, + 0.001428f, 0.001549f, 0.001632f, 0.001856f, 0.001945f, 0.002079f, 0.002310f, 0.002489f, 0.002708f, 0.002996f, 0.003315f, 0.003759f, + 0.004177f, 0.004803f, 0.005619f, 0.006527f, 0.007793f, 0.009468f, 0.011917f, 0.015152f, 0.019897f, 0.027298f, 0.038910f, 0.055908f, + 0.080811f, 0.114563f, 0.600586f, 0.628906f, 0.634277f, 0.636719f, 0.637207f, 0.638672f, 0.000000f, 0.000000f, 0.000106f, 0.000137f, + 0.000172f, 0.000211f, 0.000189f, 0.000226f, 0.000230f, 0.000248f, 0.000293f, 0.000251f, 0.000264f, 0.000321f, 0.000343f, 0.000399f, + 0.000368f, 0.000401f, 0.000499f, 0.000479f, 0.000498f, 0.000526f, 0.000550f, 0.000595f, 0.000631f, 0.000645f, 0.000726f, 0.000717f, + 0.000786f, 0.000902f, 0.000865f, 0.000916f, 0.000989f, 0.001059f, 0.001165f, 0.001246f, 0.001279f, 0.001408f, 0.001566f, 0.001628f, + 0.001808f, 0.001991f, 0.002165f, 0.002466f, 0.002766f, 0.003084f, 0.003534f, 0.004250f, 0.005016f, 0.006130f, 0.007584f, 0.009605f, + 0.012718f, 0.017395f, 0.025131f, 0.038269f, 0.058899f, 0.089661f, 0.582031f, 0.611328f, 0.616699f, 0.620117f, 0.621094f, 0.622559f, + 0.000000f, 0.000108f, 0.000104f, 0.000095f, 0.000117f, 0.000117f, 0.000122f, 0.000143f, 0.000147f, 0.000164f, 0.000174f, 0.000216f, + 0.000191f, 0.000227f, 0.000241f, 0.000250f, 0.000257f, 0.000271f, 0.000301f, 0.000298f, 0.000317f, 0.000344f, 0.000370f, 0.000392f, + 0.000404f, 0.000427f, 0.000491f, 0.000491f, 0.000519f, 0.000535f, 0.000611f, 0.000601f, 0.000668f, 0.000698f, 0.000767f, 0.000838f, + 0.000865f, 0.000895f, 0.000993f, 0.001066f, 0.001161f, 0.001242f, 0.001415f, 0.001521f, 0.001743f, 0.001901f, 0.002209f, 0.002523f, + 0.003038f, 0.003601f, 0.004478f, 0.005699f, 0.007545f, 0.010437f, 0.015175f, 0.023682f, 0.039429f, 0.066406f, 0.563477f, 0.593262f, + 0.598633f, 0.602051f, 0.602539f, 0.603516f, 0.000000f, 0.000101f, 0.000093f, 0.000087f, 0.000082f, 0.000078f, 0.000084f, 0.000087f, + 0.000093f, 0.000094f, 0.000099f, 0.000104f, 0.000114f, 0.000123f, 0.000158f, 0.000163f, 0.000166f, 0.000178f, 0.000177f, 0.000214f, + 0.000191f, 0.000208f, 0.000212f, 0.000247f, 0.000268f, 0.000263f, 0.000272f, 0.000287f, 0.000310f, 0.000336f, 0.000353f, 0.000368f, + 0.000396f, 0.000408f, 0.000453f, 0.000476f, 0.000511f, 0.000540f, 0.000615f, 0.000635f, 0.000682f, 0.000751f, 0.000812f, 0.000908f, + 0.000987f, 0.001116f, 0.001278f, 0.001431f, 0.001702f, 0.002047f, 0.002512f, 0.003126f, 0.004181f, 0.005817f, 0.008553f, 0.013489f, + 0.023697f, 0.045288f, 0.544922f, 0.575684f, 0.581543f, 0.584473f, 0.585938f, 0.587402f, 0.000109f, 0.000091f, 0.000081f, 0.000075f, + 0.000070f, 0.000067f, 0.000064f, 0.000061f, 0.000057f, 0.000054f, 0.000058f, 0.000075f, 0.000062f, 0.000064f, 0.000085f, 0.000068f, + 0.000092f, 0.000094f, 0.000103f, 0.000110f, 0.000113f, 0.000119f, 0.000141f, 0.000141f, 0.000148f, 0.000152f, 0.000159f, 0.000164f, + 0.000175f, 0.000188f, 0.000184f, 0.000218f, 0.000233f, 0.000223f, 0.000253f, 0.000265f, 0.000282f, 0.000321f, 0.000322f, 0.000351f, + 0.000371f, 0.000405f, 0.000443f, 0.000478f, 0.000515f, 0.000571f, 0.000652f, 0.000733f, 0.000856f, 0.001011f, 0.001227f, 0.001531f, + 0.002029f, 0.002817f, 0.004215f, 0.006874f, 0.012390f, 0.027405f, 0.525879f, 0.557129f, 0.563477f, 0.566895f, 0.568848f, 0.569824f, + 0.000094f, 0.000073f, 0.000065f, 0.000060f, 0.000055f, 0.000052f, 0.000049f, 0.000048f, 0.000046f, 0.000045f, 0.000042f, 0.000040f, + 0.000040f, 0.000037f, 0.000035f, 0.000035f, 0.000042f, 0.000036f, 0.000049f, 0.000051f, 0.000055f, 0.000056f, 0.000059f, 0.000062f, + 0.000064f, 0.000078f, 0.000071f, 0.000079f, 0.000088f, 0.000091f, 0.000093f, 0.000099f, 0.000103f, 0.000110f, 0.000125f, 0.000123f, + 0.000127f, 0.000151f, 0.000151f, 0.000161f, 0.000169f, 0.000179f, 0.000204f, 0.000219f, 0.000240f, 0.000267f, 0.000294f, 0.000321f, + 0.000378f, 0.000438f, 0.000524f, 0.000628f, 0.000818f, 0.001125f, 0.001693f, 0.002888f, 0.005638f, 0.013580f, 0.505859f, 0.539062f, + 0.544922f, 0.548340f, 0.550293f, 0.550781f, 0.000064f, 0.000048f, 0.000041f, 0.000037f, 0.000035f, 0.000034f, 0.000032f, 0.000031f, + 0.000030f, 0.000029f, 0.000028f, 0.000028f, 0.000027f, 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, + 0.000020f, 0.000019f, 0.000019f, 0.000023f, 0.000021f, 0.000022f, 0.000026f, 0.000029f, 0.000032f, 0.000031f, 0.000036f, 0.000037f, + 0.000036f, 0.000044f, 0.000046f, 0.000048f, 0.000052f, 0.000054f, 0.000056f, 0.000061f, 0.000070f, 0.000073f, 0.000076f, 0.000081f, + 0.000082f, 0.000095f, 0.000105f, 0.000120f, 0.000126f, 0.000143f, 0.000173f, 0.000203f, 0.000267f, 0.000346f, 0.000505f, 0.000853f, + 0.001829f, 0.005222f, 0.487061f, 0.519531f, 0.527344f, 0.529785f, 0.531738f, 0.532715f, 0.000000f, 0.000002f, 0.000003f, 0.000004f, + 0.000008f, 0.000008f, 0.000008f, 0.000010f, 0.000009f, 0.000010f, 0.000010f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, + 0.000012f, 0.000011f, 0.000012f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, + 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000007f, 0.000008f, 0.000009f, 0.000010f, 0.000012f, 0.000012f, 0.000015f, + 0.000013f, 0.000015f, 0.000018f, 0.000020f, 0.000021f, 0.000022f, 0.000022f, 0.000024f, 0.000026f, 0.000027f, 0.000034f, 0.000043f, + 0.000049f, 0.000065f, 0.000089f, 0.000138f, 0.000293f, 0.001143f, 0.466553f, 0.500488f, 0.508301f, 0.510742f, 0.512207f, 0.513672f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, + 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000006f, 0.000023f, 0.446777f, 0.482178f, + 0.489746f, 0.492676f, 0.494629f, 0.496094f, + }, + { + 0.032318f, 0.095032f, 0.152344f, 0.205322f, 0.254883f, 0.299316f, 0.342041f, 0.380859f, 0.416504f, 0.449707f, 0.481201f, 0.508789f, + 0.537109f, 0.562012f, 0.584961f, 0.608398f, 0.628418f, 0.648926f, 0.666504f, 0.684570f, 0.701172f, 0.716797f, 0.731934f, 0.746094f, + 0.759766f, 0.770996f, 0.784668f, 0.795898f, 0.806641f, 0.817871f, 0.827637f, 0.837402f, 0.846680f, 0.855469f, 0.863770f, 0.872559f, + 0.879883f, 0.887695f, 0.895508f, 0.901367f, 0.909180f, 0.915527f, 0.921387f, 0.927734f, 0.934082f, 0.939453f, 0.944824f, 0.950684f, + 0.955566f, 0.960449f, 0.965332f, 0.969238f, 0.974121f, 0.978516f, 0.982910f, 0.986816f, 0.990723f, 0.994629f, 0.994629f, 0.987793f, + 0.981934f, 0.976562f, 0.971680f, 0.966797f, 0.025833f, 0.076965f, 0.125854f, 0.173096f, 0.217896f, 0.259766f, 0.299561f, 0.338135f, + 0.372559f, 0.407471f, 0.437500f, 0.468262f, 0.496582f, 0.522949f, 0.547852f, 0.571289f, 0.593750f, 0.614746f, 0.633789f, 0.652832f, + 0.671387f, 0.687988f, 0.705078f, 0.719727f, 0.734863f, 0.749023f, 0.761719f, 0.774414f, 0.786621f, 0.797363f, 0.808594f, 0.818848f, + 0.829590f, 0.838867f, 0.848633f, 0.858398f, 0.865723f, 0.874512f, 0.881836f, 0.890137f, 0.897949f, 0.904297f, 0.910645f, 0.917480f, + 0.923828f, 0.929688f, 0.935547f, 0.941895f, 0.947266f, 0.952637f, 0.957520f, 0.962402f, 0.967285f, 0.971680f, 0.976562f, 0.980957f, + 0.984863f, 0.989258f, 0.992676f, 0.985840f, 0.979980f, 0.975098f, 0.970703f, 0.966309f, 0.020828f, 0.063049f, 0.104797f, 0.146606f, + 0.187134f, 0.225464f, 0.263916f, 0.299072f, 0.333252f, 0.366943f, 0.398438f, 0.429199f, 0.457031f, 0.484131f, 0.509766f, 0.534668f, + 0.559082f, 0.579590f, 0.600586f, 0.622070f, 0.640625f, 0.659180f, 0.676758f, 0.692383f, 0.708984f, 0.722656f, 0.737793f, 0.751465f, + 0.764648f, 0.776367f, 0.789062f, 0.801270f, 0.811523f, 0.821289f, 0.832031f, 0.841309f, 0.850586f, 0.860352f, 0.868652f, 0.876953f, + 0.884766f, 0.892090f, 0.899902f, 0.906738f, 0.913086f, 0.920410f, 0.927246f, 0.933105f, 0.938477f, 0.944336f, 0.950195f, 0.955078f, + 0.959961f, 0.965332f, 0.970215f, 0.975098f, 0.979492f, 0.983887f, 0.989746f, 0.983398f, 0.978516f, 0.973633f, 0.969238f, 0.964844f, + 0.017273f, 0.052429f, 0.088745f, 0.124207f, 0.160034f, 0.195068f, 0.230103f, 0.263916f, 0.297119f, 0.329102f, 0.360596f, 0.390625f, + 0.418945f, 0.446289f, 0.472656f, 0.498535f, 0.521973f, 0.545898f, 0.567871f, 0.588867f, 0.609375f, 0.629395f, 0.646973f, 0.664551f, + 0.681641f, 0.698242f, 0.712402f, 0.727539f, 0.741699f, 0.755371f, 0.768555f, 0.780762f, 0.792480f, 0.803711f, 0.814941f, 0.825195f, + 0.834961f, 0.844727f, 0.854004f, 0.863281f, 0.871094f, 0.879883f, 0.887695f, 0.895508f, 0.902832f, 0.909668f, 0.916504f, 0.923828f, + 0.929688f, 0.936035f, 0.941895f, 0.947754f, 0.952637f, 0.958496f, 0.963379f, 0.968750f, 0.973633f, 0.978027f, 0.986816f, 0.980957f, + 0.976562f, 0.972168f, 0.967285f, 0.963379f, 0.014076f, 0.043915f, 0.074951f, 0.106140f, 0.137573f, 0.169189f, 0.201416f, 0.233154f, + 0.264648f, 0.295166f, 0.324707f, 0.354248f, 0.381836f, 0.410156f, 0.436279f, 0.462891f, 0.487793f, 0.510742f, 0.534180f, 0.556152f, + 0.576660f, 0.598145f, 0.616211f, 0.636719f, 0.653320f, 0.670410f, 0.687500f, 0.703125f, 0.718262f, 0.733398f, 0.746582f, 0.760742f, + 0.772949f, 0.785156f, 0.796875f, 0.808105f, 0.818848f, 0.829590f, 0.838867f, 0.848145f, 0.857910f, 0.867188f, 0.875977f, 0.883301f, + 0.891602f, 0.899414f, 0.906738f, 0.913086f, 0.919922f, 0.926270f, 0.932617f, 0.938477f, 0.944824f, 0.951660f, 0.957520f, 0.961914f, + 0.967285f, 0.972168f, 0.984863f, 0.979004f, 0.974609f, 0.970215f, 0.966309f, 0.961914f, 0.012077f, 0.037445f, 0.063660f, 0.090881f, + 0.118774f, 0.147827f, 0.176636f, 0.206055f, 0.234253f, 0.262939f, 0.291504f, 0.320312f, 0.347168f, 0.374756f, 0.401367f, 0.427734f, + 0.451904f, 0.477051f, 0.500488f, 0.523438f, 0.545898f, 0.566406f, 0.587402f, 0.605957f, 0.624512f, 0.643555f, 0.662109f, 0.676758f, + 0.693848f, 0.708984f, 0.724609f, 0.738770f, 0.751465f, 0.765137f, 0.777344f, 0.790039f, 0.800781f, 0.812500f, 0.823242f, 0.833984f, + 0.842773f, 0.853027f, 0.861816f, 0.871094f, 0.879395f, 0.887695f, 0.895508f, 0.903320f, 0.910156f, 0.917969f, 0.924316f, 0.931152f, + 0.937988f, 0.943848f, 0.949219f, 0.955566f, 0.960449f, 0.966309f, 0.981445f, 0.977051f, 0.972168f, 0.968262f, 0.964355f, 0.960938f, + 0.010445f, 0.032562f, 0.054657f, 0.078613f, 0.103333f, 0.128540f, 0.153564f, 0.181274f, 0.207520f, 0.234619f, 0.261475f, 0.288818f, + 0.315674f, 0.342041f, 0.368408f, 0.394287f, 0.418945f, 0.443604f, 0.467773f, 0.490479f, 0.512695f, 0.534180f, 0.555664f, 0.575684f, + 0.596191f, 0.616211f, 0.633301f, 0.651855f, 0.668457f, 0.685547f, 0.701172f, 0.714844f, 0.729492f, 0.743652f, 0.758301f, 0.770996f, + 0.783203f, 0.794922f, 0.806641f, 0.817383f, 0.827637f, 0.838867f, 0.847656f, 0.857422f, 0.866699f, 0.875000f, 0.884277f, 0.892578f, + 0.900391f, 0.907227f, 0.914551f, 0.922363f, 0.929199f, 0.935059f, 0.941895f, 0.948242f, 0.953125f, 0.959473f, 0.978516f, 0.974609f, + 0.970215f, 0.966309f, 0.962402f, 0.958984f, 0.009117f, 0.027466f, 0.047424f, 0.067871f, 0.089783f, 0.112244f, 0.135376f, 0.159668f, + 0.184082f, 0.209106f, 0.233887f, 0.259277f, 0.285400f, 0.311523f, 0.336182f, 0.360840f, 0.385986f, 0.410889f, 0.435059f, 0.458252f, + 0.480713f, 0.503418f, 0.524902f, 0.546387f, 0.566895f, 0.586426f, 0.605469f, 0.624512f, 0.642578f, 0.659668f, 0.676758f, 0.692383f, + 0.708008f, 0.722168f, 0.736816f, 0.749512f, 0.763184f, 0.776855f, 0.789062f, 0.800781f, 0.812012f, 0.823730f, 0.833496f, 0.843750f, + 0.854004f, 0.863281f, 0.872559f, 0.880371f, 0.889648f, 0.896973f, 0.905762f, 0.912598f, 0.919922f, 0.927734f, 0.934082f, 0.940918f, + 0.946289f, 0.952637f, 0.976074f, 0.972168f, 0.967773f, 0.963867f, 0.960938f, 0.957031f, 0.007561f, 0.024231f, 0.041077f, 0.059631f, + 0.078369f, 0.098145f, 0.119507f, 0.140747f, 0.163208f, 0.185913f, 0.209839f, 0.233154f, 0.257324f, 0.281494f, 0.305908f, 0.330566f, + 0.354736f, 0.378906f, 0.402588f, 0.425781f, 0.449219f, 0.471924f, 0.494385f, 0.516602f, 0.536621f, 0.557617f, 0.576660f, 0.596680f, + 0.616211f, 0.632812f, 0.650879f, 0.668457f, 0.684082f, 0.700684f, 0.715332f, 0.729492f, 0.744141f, 0.757812f, 0.771973f, 0.783691f, + 0.796387f, 0.807129f, 0.818359f, 0.829590f, 0.840820f, 0.850098f, 0.859375f, 0.868652f, 0.877930f, 0.886719f, 0.894531f, 0.903320f, + 0.910645f, 0.918945f, 0.925781f, 0.932617f, 0.939453f, 0.945801f, 0.972656f, 0.969727f, 0.965820f, 0.961914f, 0.958496f, 0.955078f, + 0.006832f, 0.020676f, 0.036224f, 0.051758f, 0.069214f, 0.086609f, 0.105225f, 0.124146f, 0.144653f, 0.165527f, 0.186646f, 0.209106f, + 0.232178f, 0.254883f, 0.277588f, 0.301758f, 0.325195f, 0.348633f, 0.371826f, 0.395264f, 0.418213f, 0.440674f, 0.463135f, 0.485596f, + 0.506348f, 0.527832f, 0.548340f, 0.567871f, 0.587891f, 0.606934f, 0.625977f, 0.642578f, 0.660645f, 0.677734f, 0.692871f, 0.708008f, + 0.723633f, 0.737793f, 0.752441f, 0.765137f, 0.778320f, 0.791504f, 0.802734f, 0.814453f, 0.825684f, 0.835449f, 0.847168f, 0.856934f, + 0.866699f, 0.875488f, 0.884766f, 0.893066f, 0.901367f, 0.910156f, 0.917480f, 0.924805f, 0.932129f, 0.938965f, 0.970215f, 0.966797f, + 0.963379f, 0.959961f, 0.956543f, 0.953125f, 0.006050f, 0.018585f, 0.031860f, 0.045807f, 0.060883f, 0.076538f, 0.093323f, 0.109985f, + 0.128174f, 0.147949f, 0.167480f, 0.186768f, 0.208496f, 0.230591f, 0.252441f, 0.274170f, 0.297363f, 0.319824f, 0.342773f, 0.365723f, + 0.388672f, 0.411133f, 0.433350f, 0.455811f, 0.477295f, 0.498291f, 0.519531f, 0.539551f, 0.560059f, 0.580566f, 0.599121f, 0.617676f, + 0.635254f, 0.653320f, 0.669434f, 0.686523f, 0.702148f, 0.717773f, 0.732422f, 0.747070f, 0.760742f, 0.773926f, 0.786621f, 0.798340f, + 0.811035f, 0.822754f, 0.833008f, 0.843750f, 0.854004f, 0.863770f, 0.873047f, 0.882812f, 0.891602f, 0.900879f, 0.908691f, 0.916504f, + 0.924316f, 0.931152f, 0.966309f, 0.964355f, 0.961426f, 0.957520f, 0.954102f, 0.951172f, 0.005352f, 0.016388f, 0.027985f, 0.040222f, + 0.053436f, 0.067261f, 0.082520f, 0.098022f, 0.114319f, 0.131836f, 0.150146f, 0.167969f, 0.187744f, 0.208008f, 0.228271f, 0.249634f, + 0.270996f, 0.292969f, 0.314697f, 0.337158f, 0.359375f, 0.380859f, 0.403809f, 0.426025f, 0.447510f, 0.469482f, 0.490967f, 0.511719f, + 0.532227f, 0.552734f, 0.571777f, 0.591309f, 0.609375f, 0.628418f, 0.645508f, 0.663086f, 0.680664f, 0.696289f, 0.711426f, 0.727051f, + 0.741699f, 0.755859f, 0.768555f, 0.782227f, 0.795410f, 0.807617f, 0.818359f, 0.830078f, 0.841309f, 0.851074f, 0.861816f, 0.871582f, + 0.880859f, 0.890625f, 0.898438f, 0.907715f, 0.915527f, 0.923828f, 0.962402f, 0.961914f, 0.958496f, 0.955078f, 0.951172f, 0.948730f, + 0.004700f, 0.014397f, 0.025208f, 0.035675f, 0.047485f, 0.060120f, 0.073242f, 0.087097f, 0.102173f, 0.117249f, 0.133789f, 0.150513f, + 0.168823f, 0.186890f, 0.206665f, 0.225830f, 0.246216f, 0.267334f, 0.288574f, 0.309814f, 0.331299f, 0.353271f, 0.375244f, 0.396729f, + 0.418701f, 0.440674f, 0.461182f, 0.483398f, 0.504883f, 0.524902f, 0.544434f, 0.564941f, 0.584473f, 0.603027f, 0.621582f, 0.639648f, + 0.656738f, 0.673828f, 0.690430f, 0.705566f, 0.721680f, 0.736816f, 0.750977f, 0.764648f, 0.778809f, 0.791016f, 0.804688f, 0.815918f, + 0.826660f, 0.838867f, 0.850098f, 0.860840f, 0.870605f, 0.879883f, 0.889648f, 0.898438f, 0.907227f, 0.915527f, 0.959961f, 0.958496f, + 0.955078f, 0.952148f, 0.949219f, 0.946777f, 0.004238f, 0.013138f, 0.022202f, 0.031769f, 0.042358f, 0.053040f, 0.065613f, 0.077637f, + 0.090759f, 0.104980f, 0.119995f, 0.135498f, 0.151855f, 0.167725f, 0.186646f, 0.205078f, 0.224121f, 0.243042f, 0.263672f, 0.283936f, + 0.305176f, 0.326416f, 0.347168f, 0.369629f, 0.390625f, 0.411865f, 0.433350f, 0.454590f, 0.475830f, 0.497314f, 0.517578f, 0.537109f, + 0.557617f, 0.577637f, 0.596191f, 0.615723f, 0.632812f, 0.651367f, 0.668945f, 0.685059f, 0.701172f, 0.716797f, 0.732422f, 0.747559f, + 0.761230f, 0.775391f, 0.788574f, 0.800781f, 0.813965f, 0.824707f, 0.837402f, 0.848145f, 0.859375f, 0.869141f, 0.879395f, 0.889160f, + 0.897949f, 0.906250f, 0.956055f, 0.955566f, 0.952148f, 0.950195f, 0.947266f, 0.943848f, 0.003944f, 0.011490f, 0.019943f, 0.028748f, + 0.037964f, 0.047485f, 0.058014f, 0.069702f, 0.081360f, 0.093994f, 0.107361f, 0.121277f, 0.136353f, 0.151978f, 0.167480f, 0.185669f, + 0.202637f, 0.222168f, 0.240601f, 0.259766f, 0.279541f, 0.300293f, 0.321533f, 0.342285f, 0.362549f, 0.384033f, 0.405762f, 0.427002f, + 0.447998f, 0.469238f, 0.490479f, 0.510742f, 0.532227f, 0.551758f, 0.570312f, 0.589844f, 0.609375f, 0.628418f, 0.645508f, 0.662598f, + 0.680664f, 0.696777f, 0.712402f, 0.728516f, 0.744141f, 0.757812f, 0.771973f, 0.785156f, 0.798828f, 0.811523f, 0.824707f, 0.835449f, + 0.847168f, 0.858887f, 0.869141f, 0.878906f, 0.888672f, 0.897949f, 0.952148f, 0.952148f, 0.949219f, 0.946777f, 0.944336f, 0.941406f, + 0.003448f, 0.010574f, 0.017807f, 0.025558f, 0.033875f, 0.042633f, 0.052307f, 0.062134f, 0.073059f, 0.084045f, 0.096375f, 0.109192f, + 0.122803f, 0.136475f, 0.151367f, 0.167603f, 0.183960f, 0.201416f, 0.218506f, 0.237427f, 0.256104f, 0.275635f, 0.295410f, 0.315918f, + 0.336426f, 0.357178f, 0.378906f, 0.399414f, 0.421143f, 0.442139f, 0.462891f, 0.484375f, 0.504883f, 0.524902f, 0.544922f, 0.564941f, + 0.583984f, 0.603516f, 0.622070f, 0.640625f, 0.658691f, 0.675781f, 0.692871f, 0.709473f, 0.725098f, 0.740234f, 0.754883f, 0.769531f, + 0.783203f, 0.796875f, 0.809570f, 0.823242f, 0.834473f, 0.846191f, 0.857422f, 0.868164f, 0.878906f, 0.889160f, 0.948730f, 0.948242f, + 0.946289f, 0.944336f, 0.940918f, 0.938477f, 0.003017f, 0.009422f, 0.015900f, 0.023041f, 0.030380f, 0.038574f, 0.047150f, 0.055969f, + 0.065735f, 0.075684f, 0.086426f, 0.098267f, 0.110535f, 0.123047f, 0.136841f, 0.151489f, 0.166138f, 0.182495f, 0.198975f, 0.216553f, + 0.233765f, 0.252930f, 0.271484f, 0.291016f, 0.310547f, 0.331299f, 0.351562f, 0.372559f, 0.393555f, 0.415039f, 0.435059f, 0.457275f, + 0.477539f, 0.498047f, 0.519043f, 0.538574f, 0.559570f, 0.579102f, 0.598633f, 0.617188f, 0.635742f, 0.654297f, 0.672363f, 0.688965f, + 0.706055f, 0.721191f, 0.737793f, 0.752930f, 0.768066f, 0.782227f, 0.795898f, 0.809082f, 0.821289f, 0.833496f, 0.846191f, 0.857422f, + 0.869141f, 0.879883f, 0.944824f, 0.945312f, 0.942871f, 0.940918f, 0.938477f, 0.936035f, 0.002802f, 0.008575f, 0.014763f, 0.020844f, + 0.027557f, 0.034576f, 0.042084f, 0.050476f, 0.058990f, 0.067993f, 0.077942f, 0.087952f, 0.098999f, 0.111267f, 0.122803f, 0.136719f, + 0.150269f, 0.165527f, 0.180542f, 0.196533f, 0.213257f, 0.230591f, 0.248779f, 0.267334f, 0.286865f, 0.306152f, 0.325928f, 0.346436f, + 0.367188f, 0.387695f, 0.409424f, 0.429199f, 0.450195f, 0.471680f, 0.492920f, 0.513184f, 0.534180f, 0.553711f, 0.573730f, 0.593750f, + 0.612793f, 0.631836f, 0.649414f, 0.668457f, 0.685059f, 0.703125f, 0.719238f, 0.735352f, 0.750000f, 0.766113f, 0.781738f, 0.794434f, + 0.808105f, 0.821777f, 0.833984f, 0.846191f, 0.858398f, 0.870117f, 0.940918f, 0.941895f, 0.939941f, 0.937500f, 0.935059f, 0.932617f, + 0.002573f, 0.007603f, 0.013100f, 0.018799f, 0.024719f, 0.031372f, 0.038147f, 0.045105f, 0.052795f, 0.061127f, 0.069519f, 0.079529f, + 0.089355f, 0.099976f, 0.111084f, 0.123718f, 0.136353f, 0.148926f, 0.163574f, 0.178345f, 0.194214f, 0.210083f, 0.227783f, 0.245361f, + 0.263672f, 0.282471f, 0.301758f, 0.321533f, 0.341797f, 0.361816f, 0.383057f, 0.403320f, 0.424316f, 0.445557f, 0.466797f, 0.487061f, + 0.507812f, 0.528809f, 0.549805f, 0.569336f, 0.589844f, 0.608887f, 0.627930f, 0.646973f, 0.665527f, 0.682129f, 0.700195f, 0.717773f, + 0.732910f, 0.749512f, 0.765137f, 0.779785f, 0.794434f, 0.808105f, 0.821777f, 0.834473f, 0.847168f, 0.859375f, 0.936523f, 0.937988f, + 0.936035f, 0.933594f, 0.932129f, 0.929688f, 0.002409f, 0.007107f, 0.011833f, 0.017075f, 0.022278f, 0.028351f, 0.034088f, 0.040558f, + 0.047943f, 0.055389f, 0.063232f, 0.072021f, 0.080322f, 0.090454f, 0.100220f, 0.111389f, 0.122986f, 0.135010f, 0.148438f, 0.162109f, + 0.176270f, 0.191772f, 0.207642f, 0.224121f, 0.241699f, 0.259277f, 0.278076f, 0.297363f, 0.316650f, 0.336670f, 0.356934f, 0.377686f, + 0.397949f, 0.418701f, 0.439941f, 0.461914f, 0.482178f, 0.502930f, 0.524414f, 0.544922f, 0.565918f, 0.585938f, 0.605957f, 0.625000f, + 0.643066f, 0.662109f, 0.680176f, 0.698730f, 0.715820f, 0.731934f, 0.748047f, 0.764648f, 0.780273f, 0.794434f, 0.808594f, 0.821777f, + 0.836914f, 0.848145f, 0.932129f, 0.934082f, 0.932617f, 0.930176f, 0.928711f, 0.926270f, 0.002066f, 0.006329f, 0.010986f, 0.015541f, + 0.020294f, 0.025452f, 0.030975f, 0.037201f, 0.043152f, 0.049835f, 0.056824f, 0.064331f, 0.072998f, 0.081177f, 0.090637f, 0.100525f, + 0.110718f, 0.122131f, 0.134033f, 0.146851f, 0.159912f, 0.173584f, 0.189331f, 0.204468f, 0.221191f, 0.237671f, 0.255615f, 0.273682f, + 0.292969f, 0.312012f, 0.331543f, 0.352295f, 0.372314f, 0.393311f, 0.413818f, 0.435547f, 0.456055f, 0.477539f, 0.499023f, 0.520508f, + 0.540039f, 0.561523f, 0.581543f, 0.602051f, 0.622070f, 0.641113f, 0.659668f, 0.678223f, 0.697266f, 0.714844f, 0.731445f, 0.748535f, + 0.765137f, 0.778809f, 0.794922f, 0.810059f, 0.824219f, 0.837402f, 0.926758f, 0.930176f, 0.928711f, 0.926758f, 0.924805f, 0.922852f, + 0.001840f, 0.005703f, 0.009918f, 0.014099f, 0.018311f, 0.023026f, 0.028000f, 0.033508f, 0.038971f, 0.045044f, 0.051880f, 0.058289f, + 0.065796f, 0.073425f, 0.081482f, 0.090698f, 0.100464f, 0.110413f, 0.121216f, 0.132812f, 0.145142f, 0.158203f, 0.171997f, 0.186401f, + 0.201538f, 0.217651f, 0.234497f, 0.251465f, 0.269287f, 0.288330f, 0.307129f, 0.327148f, 0.346924f, 0.367920f, 0.388428f, 0.409668f, + 0.430420f, 0.451416f, 0.474121f, 0.494873f, 0.516113f, 0.537598f, 0.558105f, 0.579102f, 0.598633f, 0.619629f, 0.639160f, 0.657715f, + 0.677734f, 0.695801f, 0.713867f, 0.731934f, 0.748047f, 0.764160f, 0.781738f, 0.796875f, 0.810547f, 0.826172f, 0.922363f, 0.925781f, + 0.924805f, 0.922852f, 0.921387f, 0.919434f, 0.001621f, 0.005188f, 0.008888f, 0.012939f, 0.016724f, 0.021271f, 0.025772f, 0.029984f, + 0.035553f, 0.040741f, 0.046417f, 0.052490f, 0.059265f, 0.066528f, 0.074097f, 0.081482f, 0.090271f, 0.100220f, 0.109741f, 0.120178f, + 0.131226f, 0.143188f, 0.156006f, 0.169189f, 0.183716f, 0.198486f, 0.214233f, 0.230713f, 0.247925f, 0.265381f, 0.284424f, 0.303711f, + 0.322754f, 0.342773f, 0.363525f, 0.384277f, 0.405518f, 0.427002f, 0.447754f, 0.469727f, 0.491455f, 0.512207f, 0.534180f, 0.554688f, + 0.576172f, 0.597168f, 0.617188f, 0.636719f, 0.657227f, 0.677734f, 0.695312f, 0.713379f, 0.731934f, 0.749512f, 0.766113f, 0.782715f, + 0.798340f, 0.813477f, 0.917480f, 0.920898f, 0.920410f, 0.919922f, 0.916992f, 0.915039f, 0.001581f, 0.004616f, 0.008049f, 0.011917f, + 0.015556f, 0.019547f, 0.023270f, 0.027908f, 0.031860f, 0.036652f, 0.041992f, 0.047577f, 0.053528f, 0.060150f, 0.066772f, 0.073914f, + 0.082153f, 0.090088f, 0.099304f, 0.108887f, 0.118835f, 0.129517f, 0.141357f, 0.154297f, 0.166992f, 0.180908f, 0.195557f, 0.210815f, + 0.227173f, 0.244141f, 0.261963f, 0.279785f, 0.299072f, 0.318359f, 0.338379f, 0.358887f, 0.380127f, 0.401123f, 0.422607f, 0.443848f, + 0.466309f, 0.487793f, 0.509277f, 0.530762f, 0.553223f, 0.573730f, 0.594727f, 0.616699f, 0.636719f, 0.656250f, 0.676270f, 0.695801f, + 0.713867f, 0.733398f, 0.750488f, 0.767090f, 0.784180f, 0.801270f, 0.912598f, 0.916992f, 0.916504f, 0.914551f, 0.913086f, 0.911133f, + 0.001476f, 0.004410f, 0.007374f, 0.010620f, 0.013931f, 0.017258f, 0.021057f, 0.024979f, 0.029144f, 0.033478f, 0.037872f, 0.042969f, + 0.048737f, 0.053986f, 0.060150f, 0.066895f, 0.074036f, 0.081665f, 0.089417f, 0.098083f, 0.107361f, 0.117371f, 0.127930f, 0.139648f, + 0.151489f, 0.164062f, 0.178589f, 0.192627f, 0.208130f, 0.223755f, 0.240601f, 0.258057f, 0.275879f, 0.295654f, 0.314697f, 0.334961f, + 0.354980f, 0.375977f, 0.396729f, 0.418945f, 0.440430f, 0.462402f, 0.484619f, 0.506348f, 0.528809f, 0.550781f, 0.572266f, 0.593750f, + 0.615234f, 0.637207f, 0.656738f, 0.676758f, 0.696289f, 0.716309f, 0.734863f, 0.752930f, 0.770508f, 0.788574f, 0.906738f, 0.911621f, + 0.912109f, 0.910156f, 0.908691f, 0.907227f, 0.001204f, 0.003998f, 0.006786f, 0.009850f, 0.012642f, 0.015762f, 0.019226f, 0.022751f, + 0.026749f, 0.030502f, 0.034698f, 0.038940f, 0.044006f, 0.048615f, 0.054352f, 0.060608f, 0.066711f, 0.073059f, 0.080505f, 0.088318f, + 0.097290f, 0.105835f, 0.115845f, 0.126343f, 0.137085f, 0.148804f, 0.161377f, 0.175049f, 0.189331f, 0.204346f, 0.219604f, 0.236816f, + 0.253662f, 0.272217f, 0.291260f, 0.310547f, 0.330811f, 0.350830f, 0.372314f, 0.393799f, 0.415771f, 0.437500f, 0.459717f, 0.481934f, + 0.504883f, 0.527344f, 0.549316f, 0.571777f, 0.593750f, 0.615723f, 0.636230f, 0.657715f, 0.678223f, 0.697754f, 0.718262f, 0.737793f, + 0.756348f, 0.774902f, 0.900879f, 0.907227f, 0.906738f, 0.905762f, 0.904297f, 0.902832f, 0.001290f, 0.003807f, 0.006207f, 0.008652f, + 0.011368f, 0.014618f, 0.017792f, 0.020813f, 0.023849f, 0.027588f, 0.031036f, 0.035400f, 0.039917f, 0.044250f, 0.049408f, 0.054321f, + 0.059937f, 0.065918f, 0.072937f, 0.079773f, 0.087463f, 0.095703f, 0.104553f, 0.113892f, 0.124146f, 0.134888f, 0.146606f, 0.159058f, + 0.171753f, 0.185913f, 0.201416f, 0.216309f, 0.232910f, 0.250000f, 0.268555f, 0.287354f, 0.306885f, 0.326904f, 0.347412f, 0.369141f, + 0.390381f, 0.412842f, 0.434570f, 0.457764f, 0.479736f, 0.502930f, 0.525879f, 0.547852f, 0.570801f, 0.592773f, 0.615723f, 0.637207f, + 0.659180f, 0.680176f, 0.700684f, 0.720703f, 0.740234f, 0.759766f, 0.895996f, 0.901855f, 0.901855f, 0.900879f, 0.899414f, 0.897949f, + 0.001030f, 0.003561f, 0.005718f, 0.008301f, 0.010582f, 0.013283f, 0.015839f, 0.018753f, 0.022156f, 0.025314f, 0.028427f, 0.032318f, + 0.035889f, 0.040039f, 0.044434f, 0.048737f, 0.054077f, 0.059723f, 0.065613f, 0.072083f, 0.079224f, 0.086426f, 0.094238f, 0.102966f, + 0.111938f, 0.122253f, 0.132568f, 0.143555f, 0.155884f, 0.168945f, 0.182861f, 0.197510f, 0.213379f, 0.229492f, 0.246948f, 0.264648f, + 0.283203f, 0.303467f, 0.322998f, 0.343994f, 0.365479f, 0.387451f, 0.409912f, 0.432129f, 0.455078f, 0.478760f, 0.501465f, 0.523926f, + 0.547852f, 0.570801f, 0.593750f, 0.616211f, 0.639160f, 0.661133f, 0.682617f, 0.703613f, 0.725098f, 0.745117f, 0.888672f, 0.896484f, + 0.896973f, 0.895020f, 0.895508f, 0.893555f, 0.001051f, 0.002956f, 0.005398f, 0.007523f, 0.009613f, 0.012024f, 0.014725f, 0.017059f, + 0.019714f, 0.022537f, 0.025681f, 0.029236f, 0.032715f, 0.036102f, 0.040100f, 0.043945f, 0.048859f, 0.053772f, 0.058838f, 0.064880f, + 0.070862f, 0.077576f, 0.084839f, 0.092712f, 0.101013f, 0.110229f, 0.119446f, 0.130005f, 0.141113f, 0.153198f, 0.166016f, 0.179565f, + 0.193970f, 0.209351f, 0.225830f, 0.242920f, 0.261230f, 0.280273f, 0.299316f, 0.320068f, 0.341309f, 0.363037f, 0.384521f, 0.407227f, + 0.429443f, 0.453369f, 0.477051f, 0.500977f, 0.524414f, 0.547852f, 0.571777f, 0.595215f, 0.619141f, 0.641602f, 0.664062f, 0.686035f, + 0.707520f, 0.729004f, 0.882812f, 0.891602f, 0.891113f, 0.890625f, 0.889160f, 0.888184f, 0.000934f, 0.002998f, 0.004883f, 0.006859f, + 0.009102f, 0.010925f, 0.012871f, 0.015656f, 0.017853f, 0.020767f, 0.023422f, 0.026413f, 0.029251f, 0.032593f, 0.036011f, 0.039825f, + 0.044495f, 0.048645f, 0.053284f, 0.058258f, 0.063782f, 0.069885f, 0.076111f, 0.083313f, 0.090881f, 0.099060f, 0.107788f, 0.117126f, + 0.127075f, 0.138428f, 0.150391f, 0.162720f, 0.176270f, 0.190796f, 0.206177f, 0.222290f, 0.239624f, 0.257568f, 0.276367f, 0.296387f, + 0.316895f, 0.338623f, 0.360352f, 0.382812f, 0.404785f, 0.428467f, 0.452148f, 0.476562f, 0.500488f, 0.524902f, 0.548828f, 0.572754f, + 0.597168f, 0.621094f, 0.644531f, 0.667480f, 0.689941f, 0.712402f, 0.875977f, 0.883789f, 0.884766f, 0.884766f, 0.883301f, 0.883789f, + 0.001108f, 0.002474f, 0.004707f, 0.006248f, 0.007744f, 0.009888f, 0.011787f, 0.014244f, 0.016205f, 0.018631f, 0.021286f, 0.023758f, + 0.026535f, 0.029510f, 0.032654f, 0.035919f, 0.039825f, 0.043762f, 0.047852f, 0.052368f, 0.057373f, 0.062561f, 0.068604f, 0.074707f, + 0.081360f, 0.088623f, 0.096802f, 0.105103f, 0.114624f, 0.124573f, 0.135498f, 0.147217f, 0.159424f, 0.172729f, 0.187378f, 0.202881f, + 0.219116f, 0.235962f, 0.254639f, 0.273438f, 0.293945f, 0.314453f, 0.335449f, 0.358154f, 0.380371f, 0.403564f, 0.428223f, 0.452148f, + 0.476074f, 0.500977f, 0.525879f, 0.550293f, 0.575195f, 0.599609f, 0.625000f, 0.649414f, 0.672852f, 0.695801f, 0.870117f, 0.879395f, + 0.879883f, 0.879395f, 0.878906f, 0.877441f, 0.000877f, 0.002495f, 0.003918f, 0.005669f, 0.007484f, 0.009148f, 0.010895f, 0.012634f, + 0.014717f, 0.017014f, 0.019302f, 0.021347f, 0.023849f, 0.026443f, 0.029388f, 0.032532f, 0.035492f, 0.039185f, 0.042816f, 0.046906f, + 0.051453f, 0.056122f, 0.061310f, 0.066895f, 0.072937f, 0.079590f, 0.086548f, 0.094360f, 0.103027f, 0.111938f, 0.121643f, 0.132568f, + 0.144043f, 0.156006f, 0.169434f, 0.184204f, 0.199341f, 0.215698f, 0.233032f, 0.251221f, 0.269531f, 0.290039f, 0.311768f, 0.333740f, + 0.355957f, 0.379395f, 0.402344f, 0.426758f, 0.451172f, 0.476562f, 0.501465f, 0.526855f, 0.552246f, 0.578613f, 0.603516f, 0.629395f, + 0.653809f, 0.679199f, 0.863281f, 0.872559f, 0.874023f, 0.873535f, 0.872559f, 0.871094f, 0.000779f, 0.002241f, 0.003813f, 0.005371f, + 0.006763f, 0.008186f, 0.009827f, 0.011574f, 0.013260f, 0.015274f, 0.017303f, 0.019119f, 0.021362f, 0.023972f, 0.026505f, 0.029144f, + 0.031860f, 0.035126f, 0.038422f, 0.041809f, 0.045929f, 0.050323f, 0.054840f, 0.059631f, 0.065002f, 0.070984f, 0.077759f, 0.084656f, + 0.091736f, 0.100037f, 0.109436f, 0.118835f, 0.129272f, 0.140625f, 0.152832f, 0.166138f, 0.180786f, 0.195679f, 0.211914f, 0.229736f, + 0.247803f, 0.267822f, 0.287598f, 0.309326f, 0.331055f, 0.354492f, 0.377686f, 0.401855f, 0.426270f, 0.451660f, 0.477051f, 0.503418f, + 0.529785f, 0.555664f, 0.583008f, 0.608887f, 0.635254f, 0.661133f, 0.855957f, 0.865234f, 0.866699f, 0.867188f, 0.866211f, 0.865723f, + 0.000778f, 0.002155f, 0.003584f, 0.004871f, 0.006149f, 0.007519f, 0.008858f, 0.010498f, 0.012100f, 0.013977f, 0.015511f, 0.017303f, + 0.019363f, 0.021515f, 0.023880f, 0.026230f, 0.028564f, 0.031555f, 0.034241f, 0.037476f, 0.041138f, 0.044983f, 0.048859f, 0.053436f, + 0.058014f, 0.063232f, 0.069214f, 0.075195f, 0.081848f, 0.089417f, 0.097168f, 0.106201f, 0.115479f, 0.126343f, 0.137695f, 0.149658f, + 0.162476f, 0.177002f, 0.192993f, 0.209473f, 0.226440f, 0.245239f, 0.264404f, 0.285156f, 0.306885f, 0.330078f, 0.353271f, 0.376465f, + 0.402100f, 0.426758f, 0.453857f, 0.479492f, 0.505859f, 0.532715f, 0.560547f, 0.587402f, 0.614258f, 0.640137f, 0.847168f, 0.858398f, + 0.860352f, 0.859863f, 0.859863f, 0.858887f, 0.000673f, 0.002026f, 0.003120f, 0.004242f, 0.005390f, 0.006874f, 0.008087f, 0.009346f, + 0.011192f, 0.012642f, 0.013855f, 0.015511f, 0.017502f, 0.019394f, 0.021301f, 0.023331f, 0.025681f, 0.028137f, 0.030792f, 0.033295f, + 0.036804f, 0.039917f, 0.043488f, 0.047363f, 0.051880f, 0.056580f, 0.061646f, 0.066956f, 0.072998f, 0.079407f, 0.086609f, 0.094971f, + 0.103027f, 0.112793f, 0.122742f, 0.134399f, 0.146118f, 0.159058f, 0.173828f, 0.188599f, 0.205444f, 0.223633f, 0.241943f, 0.262451f, + 0.283203f, 0.304932f, 0.328369f, 0.352051f, 0.376953f, 0.402100f, 0.428467f, 0.454834f, 0.481934f, 0.509766f, 0.537598f, 0.566406f, + 0.594238f, 0.622559f, 0.838867f, 0.852051f, 0.853516f, 0.853027f, 0.853027f, 0.852051f, 0.000419f, 0.001721f, 0.003044f, 0.003881f, + 0.005161f, 0.006329f, 0.007500f, 0.009117f, 0.009941f, 0.011147f, 0.013023f, 0.014053f, 0.015869f, 0.017181f, 0.018906f, 0.020889f, + 0.023026f, 0.025085f, 0.027435f, 0.029724f, 0.032440f, 0.035492f, 0.038605f, 0.042175f, 0.045898f, 0.049988f, 0.054504f, 0.059143f, + 0.064697f, 0.070435f, 0.076721f, 0.083984f, 0.091675f, 0.100037f, 0.109009f, 0.119629f, 0.130737f, 0.143066f, 0.156250f, 0.170654f, + 0.186157f, 0.202393f, 0.220825f, 0.239990f, 0.259521f, 0.281250f, 0.303467f, 0.327148f, 0.351318f, 0.376953f, 0.402832f, 0.430664f, + 0.458252f, 0.485596f, 0.514648f, 0.543457f, 0.572754f, 0.602051f, 0.830566f, 0.844238f, 0.845703f, 0.845703f, 0.845703f, 0.845215f, + 0.000503f, 0.001644f, 0.002455f, 0.003765f, 0.004906f, 0.005901f, 0.006805f, 0.007744f, 0.008789f, 0.009972f, 0.011314f, 0.012688f, + 0.014160f, 0.015480f, 0.016953f, 0.018555f, 0.020325f, 0.022232f, 0.024338f, 0.026535f, 0.028717f, 0.031403f, 0.034119f, 0.037384f, + 0.040680f, 0.044128f, 0.047943f, 0.052551f, 0.057098f, 0.062134f, 0.067871f, 0.074158f, 0.081543f, 0.088684f, 0.097107f, 0.106262f, + 0.116028f, 0.127563f, 0.139404f, 0.152344f, 0.167358f, 0.182739f, 0.199951f, 0.217773f, 0.237427f, 0.257812f, 0.279541f, 0.303223f, + 0.327148f, 0.351807f, 0.377441f, 0.405518f, 0.433105f, 0.460449f, 0.491211f, 0.520020f, 0.550293f, 0.581543f, 0.821777f, 0.835938f, + 0.837891f, 0.838867f, 0.838867f, 0.837891f, 0.000649f, 0.001432f, 0.002455f, 0.003469f, 0.004162f, 0.005192f, 0.006046f, 0.007053f, + 0.007919f, 0.009148f, 0.010185f, 0.011490f, 0.012558f, 0.013748f, 0.015083f, 0.016663f, 0.018341f, 0.019897f, 0.021561f, 0.023376f, + 0.025513f, 0.027725f, 0.030075f, 0.032745f, 0.035583f, 0.038544f, 0.041901f, 0.045898f, 0.049896f, 0.054443f, 0.059784f, 0.065186f, + 0.071228f, 0.078247f, 0.085632f, 0.093872f, 0.103088f, 0.113098f, 0.123840f, 0.135986f, 0.148682f, 0.163696f, 0.179321f, 0.196533f, + 0.214722f, 0.234985f, 0.256104f, 0.278320f, 0.302246f, 0.326660f, 0.352783f, 0.379395f, 0.406738f, 0.436279f, 0.465820f, 0.496338f, + 0.527344f, 0.559082f, 0.813477f, 0.827148f, 0.829590f, 0.830566f, 0.830566f, 0.829590f, 0.000427f, 0.001431f, 0.002077f, 0.002947f, + 0.004009f, 0.004860f, 0.005501f, 0.006416f, 0.007008f, 0.008171f, 0.009155f, 0.010063f, 0.011154f, 0.012474f, 0.013336f, 0.014793f, + 0.016006f, 0.017471f, 0.019119f, 0.020630f, 0.022079f, 0.024078f, 0.026505f, 0.028687f, 0.031128f, 0.033813f, 0.036804f, 0.040283f, + 0.043732f, 0.047882f, 0.052094f, 0.057281f, 0.062500f, 0.068726f, 0.075012f, 0.082581f, 0.090393f, 0.099487f, 0.109375f, 0.120728f, + 0.131958f, 0.145508f, 0.160278f, 0.176025f, 0.193848f, 0.212891f, 0.232788f, 0.253906f, 0.277344f, 0.302002f, 0.327637f, 0.354248f, + 0.382080f, 0.411621f, 0.441162f, 0.472656f, 0.504395f, 0.536621f, 0.803223f, 0.818359f, 0.821777f, 0.821777f, 0.822266f, 0.821777f, + 0.000574f, 0.001416f, 0.001961f, 0.002621f, 0.003527f, 0.004250f, 0.004894f, 0.005653f, 0.006340f, 0.007263f, 0.008255f, 0.008965f, + 0.009819f, 0.010857f, 0.011864f, 0.012917f, 0.014114f, 0.015358f, 0.016678f, 0.018005f, 0.019669f, 0.021347f, 0.023239f, 0.025070f, + 0.027267f, 0.029434f, 0.032318f, 0.035156f, 0.038269f, 0.041534f, 0.045624f, 0.049469f, 0.054321f, 0.059479f, 0.065369f, 0.071655f, + 0.078857f, 0.086853f, 0.095886f, 0.105652f, 0.116943f, 0.128662f, 0.142090f, 0.156860f, 0.173096f, 0.190918f, 0.210327f, 0.231201f, + 0.253418f, 0.277100f, 0.302490f, 0.328369f, 0.356445f, 0.385254f, 0.415771f, 0.446533f, 0.479736f, 0.513184f, 0.794434f, 0.810547f, + 0.812500f, 0.813477f, 0.812988f, 0.813477f, 0.000417f, 0.001152f, 0.002066f, 0.002480f, 0.003115f, 0.003778f, 0.004543f, 0.005001f, + 0.005936f, 0.006420f, 0.007130f, 0.007881f, 0.008789f, 0.009666f, 0.010605f, 0.011276f, 0.012352f, 0.013367f, 0.014626f, 0.015732f, + 0.017090f, 0.018509f, 0.020096f, 0.021759f, 0.023895f, 0.025681f, 0.027740f, 0.030121f, 0.032776f, 0.036011f, 0.039276f, 0.042694f, + 0.046906f, 0.051575f, 0.056488f, 0.061951f, 0.068481f, 0.075684f, 0.083191f, 0.092102f, 0.101990f, 0.112915f, 0.125122f, 0.138672f, + 0.153564f, 0.170410f, 0.188477f, 0.208008f, 0.229980f, 0.252441f, 0.276855f, 0.303711f, 0.331055f, 0.360596f, 0.391357f, 0.422607f, + 0.456299f, 0.490234f, 0.783203f, 0.799805f, 0.803223f, 0.804688f, 0.804199f, 0.805176f, 0.000422f, 0.000885f, 0.001743f, 0.002075f, + 0.002930f, 0.003460f, 0.004105f, 0.004696f, 0.005257f, 0.005753f, 0.006550f, 0.006916f, 0.007805f, 0.008308f, 0.009109f, 0.010056f, + 0.010918f, 0.011627f, 0.012787f, 0.013725f, 0.014732f, 0.016113f, 0.017319f, 0.018906f, 0.020264f, 0.022324f, 0.023911f, 0.026230f, + 0.028183f, 0.030884f, 0.033661f, 0.036865f, 0.040314f, 0.044189f, 0.048615f, 0.053284f, 0.058838f, 0.065491f, 0.072205f, 0.079651f, + 0.088379f, 0.098389f, 0.109314f, 0.121765f, 0.135010f, 0.150513f, 0.167358f, 0.186035f, 0.206543f, 0.228516f, 0.252197f, 0.278320f, + 0.305176f, 0.333496f, 0.364746f, 0.396973f, 0.430176f, 0.465820f, 0.772949f, 0.790527f, 0.794434f, 0.794922f, 0.795410f, 0.794922f, + 0.000211f, 0.000970f, 0.001484f, 0.002035f, 0.002586f, 0.003040f, 0.003540f, 0.004086f, 0.004696f, 0.005016f, 0.005508f, 0.006100f, + 0.006763f, 0.007401f, 0.008011f, 0.008675f, 0.009247f, 0.010071f, 0.011009f, 0.011940f, 0.012802f, 0.013870f, 0.014771f, 0.016281f, + 0.017487f, 0.018890f, 0.020584f, 0.022171f, 0.024200f, 0.026505f, 0.028870f, 0.031372f, 0.034363f, 0.037659f, 0.041412f, 0.045685f, + 0.050262f, 0.055664f, 0.061768f, 0.068359f, 0.076172f, 0.084717f, 0.094666f, 0.105835f, 0.117798f, 0.131958f, 0.147095f, 0.164795f, + 0.184326f, 0.204956f, 0.228271f, 0.253174f, 0.279785f, 0.307861f, 0.338379f, 0.370361f, 0.404785f, 0.440430f, 0.761230f, 0.780273f, + 0.783691f, 0.785645f, 0.786133f, 0.785156f, 0.000281f, 0.000954f, 0.001275f, 0.001745f, 0.002159f, 0.002810f, 0.003002f, 0.003622f, + 0.003918f, 0.004471f, 0.004776f, 0.005352f, 0.005852f, 0.006298f, 0.006989f, 0.007339f, 0.008087f, 0.008698f, 0.009499f, 0.010208f, + 0.010986f, 0.011871f, 0.012802f, 0.013809f, 0.014923f, 0.016129f, 0.017624f, 0.018753f, 0.020645f, 0.022156f, 0.024399f, 0.026382f, + 0.029037f, 0.031769f, 0.034851f, 0.038513f, 0.042542f, 0.047180f, 0.052063f, 0.058136f, 0.064819f, 0.072205f, 0.080933f, 0.090698f, + 0.101685f, 0.114441f, 0.128784f, 0.144287f, 0.162476f, 0.182617f, 0.203979f, 0.228149f, 0.253906f, 0.282227f, 0.312744f, 0.344482f, + 0.378418f, 0.415039f, 0.749023f, 0.770020f, 0.773438f, 0.774902f, 0.775391f, 0.776367f, 0.000200f, 0.000790f, 0.001209f, 0.001475f, + 0.002022f, 0.002375f, 0.002754f, 0.003136f, 0.003532f, 0.003851f, 0.004253f, 0.004719f, 0.004864f, 0.005455f, 0.005749f, 0.006435f, + 0.007053f, 0.007557f, 0.007988f, 0.008614f, 0.009216f, 0.010101f, 0.010712f, 0.011604f, 0.012596f, 0.013588f, 0.014877f, 0.016052f, + 0.017334f, 0.018753f, 0.020401f, 0.022415f, 0.024338f, 0.026642f, 0.029282f, 0.032196f, 0.035461f, 0.039215f, 0.043854f, 0.048706f, + 0.054413f, 0.060913f, 0.068237f, 0.076965f, 0.086792f, 0.097961f, 0.110657f, 0.125488f, 0.141846f, 0.160278f, 0.180542f, 0.203857f, + 0.229004f, 0.256348f, 0.286133f, 0.317627f, 0.351807f, 0.388184f, 0.737305f, 0.757812f, 0.762695f, 0.763672f, 0.764160f, 0.764648f, + 0.000214f, 0.000700f, 0.001134f, 0.001480f, 0.001724f, 0.002056f, 0.002468f, 0.002672f, 0.003069f, 0.003412f, 0.003618f, 0.003883f, + 0.004265f, 0.004627f, 0.004971f, 0.005508f, 0.005817f, 0.006397f, 0.006866f, 0.007244f, 0.007812f, 0.008446f, 0.009003f, 0.009872f, + 0.010544f, 0.011345f, 0.012375f, 0.013321f, 0.014275f, 0.015587f, 0.017075f, 0.018372f, 0.020050f, 0.022186f, 0.024246f, 0.026596f, + 0.029388f, 0.032562f, 0.036285f, 0.040344f, 0.045197f, 0.050568f, 0.056946f, 0.064514f, 0.072876f, 0.082886f, 0.093933f, 0.107056f, + 0.122070f, 0.139404f, 0.158325f, 0.180176f, 0.204590f, 0.231201f, 0.260010f, 0.290771f, 0.325195f, 0.361816f, 0.726074f, 0.747070f, + 0.751465f, 0.753418f, 0.753906f, 0.754395f, 0.000187f, 0.000637f, 0.001095f, 0.001133f, 0.001488f, 0.001872f, 0.002007f, 0.002253f, + 0.002590f, 0.002880f, 0.003010f, 0.003420f, 0.003593f, 0.003914f, 0.004322f, 0.004650f, 0.005051f, 0.005424f, 0.005733f, 0.006134f, + 0.006683f, 0.007183f, 0.007671f, 0.008072f, 0.008720f, 0.009483f, 0.010201f, 0.011070f, 0.011871f, 0.012863f, 0.013924f, 0.015167f, + 0.016434f, 0.018143f, 0.019669f, 0.021851f, 0.024109f, 0.026749f, 0.029587f, 0.033020f, 0.037109f, 0.041718f, 0.047119f, 0.053192f, + 0.060516f, 0.068848f, 0.078857f, 0.090149f, 0.104004f, 0.119202f, 0.136841f, 0.157471f, 0.180420f, 0.205322f, 0.234009f, 0.264648f, + 0.297852f, 0.335449f, 0.711914f, 0.735352f, 0.740234f, 0.741211f, 0.742676f, 0.742676f, 0.000201f, 0.000676f, 0.000884f, 0.001044f, + 0.001369f, 0.001633f, 0.001786f, 0.002001f, 0.002237f, 0.002460f, 0.002680f, 0.002777f, 0.003117f, 0.003408f, 0.003632f, 0.003910f, + 0.004211f, 0.004375f, 0.004772f, 0.005226f, 0.005520f, 0.005909f, 0.006302f, 0.006882f, 0.007385f, 0.007858f, 0.008553f, 0.008919f, + 0.009827f, 0.010582f, 0.011398f, 0.012520f, 0.013611f, 0.014725f, 0.016190f, 0.017593f, 0.019424f, 0.021622f, 0.023941f, 0.026703f, + 0.029938f, 0.033539f, 0.038055f, 0.043243f, 0.049408f, 0.056519f, 0.065002f, 0.074951f, 0.086548f, 0.100403f, 0.116394f, 0.135132f, + 0.156860f, 0.181030f, 0.208252f, 0.238281f, 0.271240f, 0.307861f, 0.698730f, 0.722656f, 0.727539f, 0.729980f, 0.730957f, 0.730469f, + 0.000185f, 0.000371f, 0.000784f, 0.001028f, 0.001153f, 0.001304f, 0.001567f, 0.001792f, 0.001790f, 0.002028f, 0.002283f, 0.002424f, + 0.002640f, 0.002764f, 0.003044f, 0.003313f, 0.003445f, 0.003748f, 0.004044f, 0.004337f, 0.004677f, 0.004879f, 0.005207f, 0.005661f, + 0.006027f, 0.006481f, 0.006870f, 0.007454f, 0.007874f, 0.008583f, 0.009239f, 0.009880f, 0.010849f, 0.011871f, 0.012833f, 0.014153f, + 0.015656f, 0.017151f, 0.018967f, 0.021118f, 0.023621f, 0.026703f, 0.030197f, 0.034576f, 0.039368f, 0.045441f, 0.052460f, 0.061157f, + 0.070862f, 0.083069f, 0.097290f, 0.114441f, 0.134155f, 0.157104f, 0.182983f, 0.212158f, 0.244507f, 0.281250f, 0.684570f, 0.710449f, + 0.715332f, 0.717285f, 0.717773f, 0.718750f, 0.000109f, 0.000455f, 0.000558f, 0.000757f, 0.000986f, 0.001166f, 0.001298f, 0.001310f, + 0.001566f, 0.001614f, 0.001852f, 0.001933f, 0.002062f, 0.002327f, 0.002571f, 0.002699f, 0.002909f, 0.003057f, 0.003254f, 0.003496f, + 0.003643f, 0.004066f, 0.004295f, 0.004665f, 0.004822f, 0.005161f, 0.005722f, 0.006008f, 0.006424f, 0.006897f, 0.007435f, 0.008049f, + 0.008789f, 0.009529f, 0.010284f, 0.011177f, 0.012321f, 0.013466f, 0.014885f, 0.016586f, 0.018417f, 0.020844f, 0.023575f, 0.026810f, + 0.030655f, 0.035400f, 0.041412f, 0.048462f, 0.056976f, 0.067322f, 0.079712f, 0.094543f, 0.112610f, 0.133789f, 0.158691f, 0.186279f, + 0.217896f, 0.253418f, 0.670898f, 0.696777f, 0.702148f, 0.704590f, 0.705078f, 0.705566f, 0.000000f, 0.000317f, 0.000556f, 0.000619f, + 0.000759f, 0.000889f, 0.001012f, 0.001163f, 0.001282f, 0.001353f, 0.001531f, 0.001621f, 0.001681f, 0.001862f, 0.001976f, 0.002140f, + 0.002392f, 0.002502f, 0.002745f, 0.002838f, 0.003019f, 0.003311f, 0.003477f, 0.003639f, 0.003889f, 0.004166f, 0.004429f, 0.004784f, + 0.005119f, 0.005547f, 0.006042f, 0.006317f, 0.006901f, 0.007442f, 0.008110f, 0.008751f, 0.009583f, 0.010590f, 0.011566f, 0.012894f, + 0.014404f, 0.015930f, 0.018158f, 0.020569f, 0.023697f, 0.027374f, 0.031830f, 0.037567f, 0.044434f, 0.053009f, 0.063599f, 0.076538f, + 0.092346f, 0.111511f, 0.134521f, 0.161133f, 0.191772f, 0.227173f, 0.654297f, 0.684082f, 0.687988f, 0.690918f, 0.691895f, 0.691895f, + 0.000000f, 0.000275f, 0.000368f, 0.000572f, 0.000683f, 0.000731f, 0.000877f, 0.000979f, 0.001039f, 0.001091f, 0.001234f, 0.001332f, + 0.001447f, 0.001547f, 0.001601f, 0.001760f, 0.001790f, 0.002007f, 0.002119f, 0.002245f, 0.002493f, 0.002565f, 0.002747f, 0.002920f, + 0.003168f, 0.003235f, 0.003551f, 0.003830f, 0.004040f, 0.004368f, 0.004658f, 0.005001f, 0.005337f, 0.005798f, 0.006287f, 0.006794f, + 0.007488f, 0.008087f, 0.008865f, 0.009773f, 0.010963f, 0.012199f, 0.013649f, 0.015610f, 0.017822f, 0.020493f, 0.023849f, 0.028320f, + 0.033752f, 0.040466f, 0.049377f, 0.060028f, 0.073853f, 0.090698f, 0.111572f, 0.136841f, 0.166016f, 0.199341f, 0.640137f, 0.667969f, + 0.675781f, 0.676758f, 0.678223f, 0.678223f, 0.000017f, 0.000193f, 0.000383f, 0.000487f, 0.000586f, 0.000597f, 0.000618f, 0.000733f, + 0.000826f, 0.000863f, 0.000902f, 0.001037f, 0.001121f, 0.001244f, 0.001342f, 0.001329f, 0.001514f, 0.001506f, 0.001719f, 0.001793f, + 0.001851f, 0.002016f, 0.002182f, 0.002281f, 0.002432f, 0.002554f, 0.002708f, 0.002859f, 0.003168f, 0.003344f, 0.003563f, 0.003845f, + 0.004158f, 0.004478f, 0.004852f, 0.005154f, 0.005714f, 0.006207f, 0.006752f, 0.007370f, 0.008186f, 0.009155f, 0.010193f, 0.011490f, + 0.013016f, 0.015144f, 0.017517f, 0.020752f, 0.024811f, 0.029922f, 0.036835f, 0.045593f, 0.056946f, 0.071533f, 0.090576f, 0.113159f, + 0.140991f, 0.173340f, 0.624023f, 0.653809f, 0.660156f, 0.663574f, 0.664551f, 0.664062f, 0.000194f, 0.000227f, 0.000316f, 0.000451f, + 0.000449f, 0.000482f, 0.000610f, 0.000511f, 0.000654f, 0.000673f, 0.000804f, 0.000844f, 0.000880f, 0.000955f, 0.000961f, 0.001127f, + 0.001169f, 0.001210f, 0.001318f, 0.001330f, 0.001507f, 0.001592f, 0.001657f, 0.001771f, 0.001839f, 0.001953f, 0.002083f, 0.002214f, + 0.002399f, 0.002518f, 0.002815f, 0.002882f, 0.003132f, 0.003361f, 0.003605f, 0.003925f, 0.004177f, 0.004528f, 0.004963f, 0.005527f, + 0.006027f, 0.006783f, 0.007381f, 0.008469f, 0.009644f, 0.010849f, 0.012772f, 0.014748f, 0.017578f, 0.021332f, 0.026367f, 0.033142f, + 0.042389f, 0.054413f, 0.070129f, 0.091064f, 0.116943f, 0.147339f, 0.608887f, 0.640137f, 0.645996f, 0.647461f, 0.650391f, 0.651367f, + 0.000166f, 0.000146f, 0.000248f, 0.000320f, 0.000288f, 0.000446f, 0.000375f, 0.000407f, 0.000468f, 0.000514f, 0.000629f, 0.000638f, + 0.000681f, 0.000773f, 0.000806f, 0.000766f, 0.000883f, 0.000927f, 0.000959f, 0.001036f, 0.001097f, 0.001172f, 0.001224f, 0.001297f, + 0.001392f, 0.001425f, 0.001592f, 0.001631f, 0.001793f, 0.001965f, 0.002089f, 0.002157f, 0.002321f, 0.002495f, 0.002680f, 0.002874f, + 0.003054f, 0.003305f, 0.003632f, 0.003902f, 0.004314f, 0.004753f, 0.005306f, 0.005901f, 0.006828f, 0.007645f, 0.008896f, 0.010323f, + 0.012283f, 0.014816f, 0.018234f, 0.023010f, 0.029678f, 0.039276f, 0.052307f, 0.070190f, 0.093811f, 0.123474f, 0.591797f, 0.623535f, + 0.631348f, 0.633301f, 0.634766f, 0.635254f, 0.000000f, 0.000154f, 0.000184f, 0.000257f, 0.000265f, 0.000266f, 0.000323f, 0.000291f, + 0.000369f, 0.000384f, 0.000450f, 0.000472f, 0.000505f, 0.000572f, 0.000577f, 0.000604f, 0.000636f, 0.000675f, 0.000699f, 0.000736f, + 0.000787f, 0.000840f, 0.000890f, 0.000945f, 0.000988f, 0.001039f, 0.001165f, 0.001165f, 0.001266f, 0.001318f, 0.001410f, 0.001550f, + 0.001618f, 0.001743f, 0.001866f, 0.001997f, 0.002151f, 0.002319f, 0.002562f, 0.002779f, 0.002975f, 0.003298f, 0.003674f, 0.004131f, + 0.004604f, 0.005268f, 0.006065f, 0.007027f, 0.008316f, 0.009949f, 0.012390f, 0.015526f, 0.019852f, 0.026733f, 0.036682f, 0.051666f, + 0.072449f, 0.099792f, 0.574707f, 0.608398f, 0.614746f, 0.618164f, 0.619629f, 0.621094f, 0.000000f, 0.000008f, 0.000146f, 0.000181f, + 0.000203f, 0.000243f, 0.000206f, 0.000250f, 0.000257f, 0.000283f, 0.000335f, 0.000293f, 0.000304f, 0.000368f, 0.000373f, 0.000435f, + 0.000418f, 0.000468f, 0.000539f, 0.000540f, 0.000564f, 0.000598f, 0.000628f, 0.000657f, 0.000716f, 0.000724f, 0.000797f, 0.000807f, + 0.000883f, 0.001002f, 0.000974f, 0.001037f, 0.001104f, 0.001196f, 0.001316f, 0.001394f, 0.001445f, 0.001574f, 0.001746f, 0.001829f, + 0.002005f, 0.002222f, 0.002401f, 0.002699f, 0.003057f, 0.003372f, 0.003874f, 0.004505f, 0.005360f, 0.006500f, 0.007927f, 0.009972f, + 0.012878f, 0.017258f, 0.024155f, 0.035339f, 0.052795f, 0.077637f, 0.558105f, 0.592285f, 0.600586f, 0.602539f, 0.604004f, 0.605469f, + 0.000000f, 0.000107f, 0.000122f, 0.000093f, 0.000133f, 0.000142f, 0.000149f, 0.000174f, 0.000174f, 0.000184f, 0.000190f, 0.000234f, + 0.000214f, 0.000250f, 0.000273f, 0.000286f, 0.000292f, 0.000302f, 0.000329f, 0.000336f, 0.000366f, 0.000391f, 0.000408f, 0.000444f, + 0.000452f, 0.000495f, 0.000531f, 0.000559f, 0.000578f, 0.000611f, 0.000659f, 0.000675f, 0.000757f, 0.000771f, 0.000854f, 0.000906f, + 0.000957f, 0.001004f, 0.001102f, 0.001187f, 0.001267f, 0.001394f, 0.001546f, 0.001683f, 0.001922f, 0.002094f, 0.002420f, 0.002754f, + 0.003254f, 0.003878f, 0.004757f, 0.005997f, 0.007812f, 0.010544f, 0.014786f, 0.022324f, 0.035522f, 0.057465f, 0.541504f, 0.576172f, + 0.583984f, 0.585938f, 0.588379f, 0.590332f, 0.000000f, 0.000099f, 0.000091f, 0.000084f, 0.000084f, 0.000086f, 0.000089f, 0.000101f, + 0.000105f, 0.000109f, 0.000122f, 0.000124f, 0.000132f, 0.000146f, 0.000171f, 0.000172f, 0.000176f, 0.000198f, 0.000197f, 0.000239f, + 0.000218f, 0.000235f, 0.000240f, 0.000281f, 0.000309f, 0.000301f, 0.000312f, 0.000321f, 0.000347f, 0.000370f, 0.000387f, 0.000419f, + 0.000444f, 0.000458f, 0.000513f, 0.000536f, 0.000570f, 0.000607f, 0.000688f, 0.000703f, 0.000754f, 0.000834f, 0.000890f, 0.000997f, + 0.001100f, 0.001238f, 0.001410f, 0.001584f, 0.001859f, 0.002207f, 0.002665f, 0.003323f, 0.004353f, 0.005947f, 0.008492f, 0.012909f, + 0.021606f, 0.039368f, 0.522461f, 0.559082f, 0.566406f, 0.569824f, 0.572266f, 0.572754f, 0.000108f, 0.000089f, 0.000079f, 0.000072f, + 0.000068f, 0.000065f, 0.000061f, 0.000057f, 0.000061f, 0.000062f, 0.000063f, 0.000086f, 0.000070f, 0.000071f, 0.000095f, 0.000080f, + 0.000107f, 0.000113f, 0.000115f, 0.000124f, 0.000121f, 0.000130f, 0.000151f, 0.000154f, 0.000164f, 0.000170f, 0.000176f, 0.000189f, + 0.000193f, 0.000215f, 0.000211f, 0.000242f, 0.000252f, 0.000260f, 0.000280f, 0.000293f, 0.000312f, 0.000350f, 0.000359f, 0.000389f, + 0.000410f, 0.000452f, 0.000481f, 0.000535f, 0.000578f, 0.000643f, 0.000718f, 0.000812f, 0.000939f, 0.001107f, 0.001329f, 0.001644f, + 0.002155f, 0.002930f, 0.004284f, 0.006706f, 0.011452f, 0.023895f, 0.504395f, 0.542480f, 0.550293f, 0.553711f, 0.555664f, 0.557129f, + 0.000093f, 0.000072f, 0.000063f, 0.000058f, 0.000053f, 0.000050f, 0.000047f, 0.000046f, 0.000044f, 0.000042f, 0.000039f, 0.000037f, + 0.000042f, 0.000035f, 0.000036f, 0.000037f, 0.000051f, 0.000046f, 0.000057f, 0.000058f, 0.000061f, 0.000062f, 0.000066f, 0.000069f, + 0.000072f, 0.000087f, 0.000077f, 0.000088f, 0.000093f, 0.000099f, 0.000103f, 0.000109f, 0.000115f, 0.000122f, 0.000139f, 0.000134f, + 0.000142f, 0.000170f, 0.000175f, 0.000179f, 0.000192f, 0.000203f, 0.000228f, 0.000245f, 0.000265f, 0.000291f, 0.000326f, 0.000360f, + 0.000420f, 0.000481f, 0.000574f, 0.000686f, 0.000887f, 0.001203f, 0.001759f, 0.002892f, 0.005318f, 0.011955f, 0.487305f, 0.524902f, + 0.534180f, 0.538086f, 0.539551f, 0.540527f, 0.000066f, 0.000049f, 0.000041f, 0.000037f, 0.000034f, 0.000033f, 0.000032f, 0.000030f, + 0.000029f, 0.000028f, 0.000028f, 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000022f, 0.000023f, + 0.000019f, 0.000018f, 0.000019f, 0.000024f, 0.000026f, 0.000029f, 0.000032f, 0.000032f, 0.000036f, 0.000034f, 0.000040f, 0.000041f, + 0.000043f, 0.000049f, 0.000049f, 0.000050f, 0.000056f, 0.000059f, 0.000067f, 0.000067f, 0.000074f, 0.000078f, 0.000082f, 0.000092f, + 0.000094f, 0.000103f, 0.000120f, 0.000130f, 0.000141f, 0.000163f, 0.000191f, 0.000230f, 0.000286f, 0.000374f, 0.000543f, 0.000890f, + 0.001802f, 0.004650f, 0.468994f, 0.507812f, 0.516602f, 0.520508f, 0.522461f, 0.523926f, 0.000007f, 0.000008f, 0.000008f, 0.000008f, + 0.000011f, 0.000010f, 0.000010f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000012f, + 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, + 0.000008f, 0.000008f, 0.000009f, 0.000009f, 0.000009f, 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000014f, 0.000013f, 0.000016f, + 0.000015f, 0.000018f, 0.000020f, 0.000021f, 0.000022f, 0.000025f, 0.000024f, 0.000025f, 0.000030f, 0.000031f, 0.000040f, 0.000046f, + 0.000052f, 0.000071f, 0.000099f, 0.000147f, 0.000306f, 0.001072f, 0.450439f, 0.491211f, 0.499756f, 0.503418f, 0.505859f, 0.507324f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, + 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000007f, 0.000024f, 0.432129f, 0.474121f, + 0.482666f, 0.486572f, 0.489014f, 0.490234f, + }, + { + 0.027573f, 0.080750f, 0.130981f, 0.177734f, 0.222290f, 0.263672f, 0.302002f, 0.338623f, 0.373291f, 0.405029f, 0.435791f, 0.464111f, + 0.490967f, 0.516602f, 0.540039f, 0.563477f, 0.584961f, 0.605469f, 0.625000f, 0.644043f, 0.660645f, 0.677246f, 0.693848f, 0.708496f, + 0.724121f, 0.738281f, 0.751465f, 0.764648f, 0.776855f, 0.789062f, 0.799805f, 0.810547f, 0.821289f, 0.831055f, 0.840820f, 0.850098f, + 0.859863f, 0.867676f, 0.876953f, 0.884277f, 0.892578f, 0.900391f, 0.907227f, 0.914551f, 0.921875f, 0.928223f, 0.934082f, 0.940430f, + 0.946777f, 0.952637f, 0.957520f, 0.964355f, 0.968262f, 0.974121f, 0.979004f, 0.983887f, 0.989258f, 0.994141f, 0.993164f, 0.983398f, + 0.976074f, 0.969238f, 0.962891f, 0.957031f, 0.022873f, 0.067871f, 0.111511f, 0.153809f, 0.193359f, 0.232788f, 0.268799f, 0.303223f, + 0.337402f, 0.368652f, 0.399414f, 0.427734f, 0.455078f, 0.481201f, 0.506348f, 0.529785f, 0.552246f, 0.573242f, 0.593750f, 0.613281f, + 0.632324f, 0.650391f, 0.667480f, 0.683105f, 0.698730f, 0.713867f, 0.728516f, 0.741211f, 0.755371f, 0.767578f, 0.779785f, 0.791504f, + 0.803223f, 0.813477f, 0.823242f, 0.834473f, 0.843750f, 0.853027f, 0.861816f, 0.870605f, 0.878906f, 0.887695f, 0.895996f, 0.901855f, + 0.910645f, 0.917480f, 0.923828f, 0.930176f, 0.937012f, 0.943359f, 0.949707f, 0.955078f, 0.960938f, 0.966797f, 0.972656f, 0.977051f, + 0.982422f, 0.987305f, 0.989746f, 0.981445f, 0.973633f, 0.967773f, 0.961426f, 0.956055f, 0.019089f, 0.057007f, 0.095215f, 0.132202f, + 0.168823f, 0.204712f, 0.238281f, 0.272217f, 0.304688f, 0.334717f, 0.364502f, 0.392822f, 0.420898f, 0.446533f, 0.471924f, 0.495850f, + 0.518555f, 0.541992f, 0.562988f, 0.582520f, 0.602539f, 0.621094f, 0.639160f, 0.655762f, 0.672852f, 0.687988f, 0.703613f, 0.718262f, + 0.732422f, 0.746094f, 0.758789f, 0.771484f, 0.783203f, 0.795898f, 0.807129f, 0.817383f, 0.827637f, 0.837402f, 0.846680f, 0.856445f, + 0.865234f, 0.874023f, 0.882324f, 0.890137f, 0.898438f, 0.905273f, 0.913574f, 0.920410f, 0.927246f, 0.934082f, 0.940918f, 0.946777f, + 0.953125f, 0.958496f, 0.964844f, 0.969727f, 0.975586f, 0.980957f, 0.986816f, 0.979004f, 0.971680f, 0.965332f, 0.959961f, 0.954590f, + 0.016327f, 0.048676f, 0.081787f, 0.114807f, 0.147705f, 0.180176f, 0.211426f, 0.243652f, 0.273438f, 0.303223f, 0.332031f, 0.360107f, + 0.386963f, 0.412598f, 0.438477f, 0.462891f, 0.487305f, 0.510254f, 0.530762f, 0.552246f, 0.572754f, 0.590820f, 0.610352f, 0.629883f, + 0.647461f, 0.662598f, 0.679688f, 0.693848f, 0.709961f, 0.723633f, 0.737305f, 0.750977f, 0.763672f, 0.776367f, 0.788086f, 0.799316f, + 0.810059f, 0.820801f, 0.832031f, 0.841309f, 0.851074f, 0.860352f, 0.868652f, 0.877930f, 0.886230f, 0.894531f, 0.902832f, 0.910156f, + 0.916504f, 0.924316f, 0.930664f, 0.937500f, 0.943848f, 0.950684f, 0.957031f, 0.962891f, 0.968262f, 0.974121f, 0.983887f, 0.976074f, + 0.969727f, 0.963867f, 0.958496f, 0.953125f, 0.013573f, 0.041901f, 0.070801f, 0.100098f, 0.129517f, 0.159058f, 0.187866f, 0.217041f, + 0.246216f, 0.274414f, 0.302002f, 0.328857f, 0.354980f, 0.381592f, 0.406738f, 0.431641f, 0.455322f, 0.478271f, 0.500000f, 0.521484f, + 0.541992f, 0.563477f, 0.583008f, 0.600098f, 0.619141f, 0.636719f, 0.653320f, 0.671387f, 0.684570f, 0.699707f, 0.715332f, 0.729492f, + 0.743164f, 0.755371f, 0.768555f, 0.780762f, 0.792480f, 0.804199f, 0.814453f, 0.824707f, 0.835449f, 0.845215f, 0.854980f, 0.864746f, + 0.874023f, 0.882812f, 0.890137f, 0.898438f, 0.905762f, 0.914062f, 0.921387f, 0.928223f, 0.935059f, 0.941406f, 0.948242f, 0.955078f, + 0.961426f, 0.966797f, 0.980957f, 0.973633f, 0.967773f, 0.961914f, 0.956543f, 0.951660f, 0.011681f, 0.036316f, 0.061584f, 0.087524f, + 0.113342f, 0.140259f, 0.167358f, 0.194214f, 0.220947f, 0.247437f, 0.273926f, 0.300537f, 0.325684f, 0.351074f, 0.375732f, 0.400146f, + 0.423828f, 0.446533f, 0.469482f, 0.491943f, 0.512695f, 0.532715f, 0.553223f, 0.573242f, 0.592285f, 0.609863f, 0.627930f, 0.644531f, + 0.660156f, 0.676758f, 0.691406f, 0.706055f, 0.720215f, 0.734863f, 0.749023f, 0.762207f, 0.774414f, 0.786133f, 0.797852f, 0.809082f, + 0.820801f, 0.831055f, 0.840332f, 0.850098f, 0.859863f, 0.869629f, 0.878418f, 0.886719f, 0.895508f, 0.903809f, 0.910645f, 0.918945f, + 0.925781f, 0.932617f, 0.939453f, 0.947754f, 0.953613f, 0.958984f, 0.977539f, 0.970703f, 0.964844f, 0.959473f, 0.954102f, 0.949707f, + 0.010330f, 0.031525f, 0.053406f, 0.076538f, 0.100159f, 0.124084f, 0.148193f, 0.173096f, 0.197998f, 0.223267f, 0.247681f, 0.273193f, + 0.297607f, 0.322021f, 0.346924f, 0.370117f, 0.394043f, 0.417236f, 0.439697f, 0.462158f, 0.483887f, 0.504883f, 0.524902f, 0.545410f, + 0.563477f, 0.583008f, 0.602539f, 0.618652f, 0.636230f, 0.652344f, 0.669922f, 0.685059f, 0.699219f, 0.714355f, 0.729004f, 0.741211f, + 0.755371f, 0.767578f, 0.780762f, 0.792480f, 0.803711f, 0.815918f, 0.825195f, 0.836914f, 0.846191f, 0.855957f, 0.864746f, 0.874512f, + 0.883301f, 0.891602f, 0.900391f, 0.908203f, 0.916016f, 0.923828f, 0.931152f, 0.937988f, 0.945801f, 0.952148f, 0.974121f, 0.967773f, + 0.962891f, 0.957520f, 0.952637f, 0.947754f, 0.009186f, 0.027359f, 0.047302f, 0.067505f, 0.088806f, 0.109924f, 0.132202f, 0.154907f, + 0.177246f, 0.201050f, 0.224121f, 0.247925f, 0.271240f, 0.295410f, 0.318359f, 0.341797f, 0.365234f, 0.387939f, 0.410156f, 0.432861f, + 0.454590f, 0.475586f, 0.495850f, 0.517090f, 0.536621f, 0.556152f, 0.575195f, 0.592773f, 0.609863f, 0.628418f, 0.645020f, 0.661133f, + 0.677246f, 0.692383f, 0.707520f, 0.721191f, 0.735352f, 0.748047f, 0.762207f, 0.774414f, 0.786621f, 0.798828f, 0.810547f, 0.820801f, + 0.831543f, 0.842285f, 0.852539f, 0.862305f, 0.871094f, 0.880859f, 0.889648f, 0.898438f, 0.906738f, 0.914551f, 0.921875f, 0.929199f, + 0.936035f, 0.944824f, 0.971191f, 0.965332f, 0.959473f, 0.955078f, 0.950195f, 0.945801f, 0.008041f, 0.024384f, 0.041321f, 0.059631f, + 0.078003f, 0.097656f, 0.117554f, 0.138428f, 0.159912f, 0.181152f, 0.203003f, 0.224976f, 0.247070f, 0.269531f, 0.292480f, 0.314697f, + 0.337891f, 0.360352f, 0.382324f, 0.403809f, 0.426025f, 0.447998f, 0.468018f, 0.488770f, 0.508301f, 0.528320f, 0.547852f, 0.567383f, + 0.585449f, 0.603516f, 0.620605f, 0.637695f, 0.654297f, 0.670410f, 0.686523f, 0.700195f, 0.715820f, 0.729980f, 0.743164f, 0.756836f, + 0.769531f, 0.782715f, 0.794434f, 0.805664f, 0.816895f, 0.827637f, 0.838379f, 0.848633f, 0.859375f, 0.868164f, 0.877930f, 0.887695f, + 0.895996f, 0.905273f, 0.912598f, 0.920898f, 0.928711f, 0.936035f, 0.966797f, 0.962402f, 0.957031f, 0.952637f, 0.947754f, 0.943848f, + 0.007095f, 0.021515f, 0.036926f, 0.052704f, 0.069641f, 0.087463f, 0.105347f, 0.123413f, 0.143188f, 0.163452f, 0.183105f, 0.204102f, + 0.225220f, 0.246704f, 0.268066f, 0.290283f, 0.311768f, 0.333740f, 0.355225f, 0.376465f, 0.397949f, 0.419434f, 0.440430f, 0.461670f, + 0.481445f, 0.500977f, 0.520020f, 0.540527f, 0.559570f, 0.578125f, 0.595703f, 0.613770f, 0.630371f, 0.646973f, 0.663086f, 0.678223f, + 0.694336f, 0.709473f, 0.723145f, 0.736328f, 0.750000f, 0.764648f, 0.777344f, 0.790039f, 0.801270f, 0.812988f, 0.824707f, 0.834961f, + 0.846191f, 0.856934f, 0.865723f, 0.875977f, 0.884766f, 0.894531f, 0.903320f, 0.911621f, 0.919922f, 0.927734f, 0.962891f, 0.959473f, + 0.954102f, 0.949219f, 0.945312f, 0.941406f, 0.006138f, 0.019150f, 0.033051f, 0.047089f, 0.061829f, 0.077515f, 0.094299f, 0.111084f, + 0.128174f, 0.146729f, 0.165771f, 0.185059f, 0.205200f, 0.224731f, 0.245361f, 0.265625f, 0.286865f, 0.307861f, 0.328857f, 0.350098f, + 0.370605f, 0.392090f, 0.413086f, 0.433594f, 0.454346f, 0.474609f, 0.493896f, 0.513672f, 0.532227f, 0.552734f, 0.569824f, 0.588867f, + 0.605957f, 0.623047f, 0.640625f, 0.656738f, 0.672852f, 0.688477f, 0.703613f, 0.717773f, 0.732910f, 0.746582f, 0.759766f, 0.772461f, + 0.786621f, 0.798340f, 0.810059f, 0.820312f, 0.832520f, 0.842773f, 0.853516f, 0.863770f, 0.873535f, 0.883789f, 0.892578f, 0.901367f, + 0.910645f, 0.919434f, 0.958984f, 0.955566f, 0.951172f, 0.946777f, 0.942871f, 0.938965f, 0.005424f, 0.017059f, 0.029541f, 0.042023f, + 0.055389f, 0.069397f, 0.083984f, 0.099670f, 0.115601f, 0.132324f, 0.149292f, 0.167114f, 0.185547f, 0.204468f, 0.224121f, 0.243896f, + 0.262939f, 0.283691f, 0.304443f, 0.323486f, 0.345459f, 0.365479f, 0.386230f, 0.407471f, 0.426758f, 0.448486f, 0.467529f, 0.487061f, + 0.506348f, 0.526367f, 0.545410f, 0.563965f, 0.581543f, 0.600098f, 0.617676f, 0.634277f, 0.650391f, 0.666016f, 0.682617f, 0.697754f, + 0.712891f, 0.727539f, 0.741211f, 0.755859f, 0.769043f, 0.782227f, 0.793945f, 0.806152f, 0.818848f, 0.830566f, 0.840332f, 0.851074f, + 0.861328f, 0.872070f, 0.881836f, 0.892090f, 0.900879f, 0.910645f, 0.955566f, 0.952637f, 0.948730f, 0.943359f, 0.939941f, 0.935547f, + 0.004833f, 0.015442f, 0.026169f, 0.037689f, 0.049683f, 0.062164f, 0.075806f, 0.089539f, 0.103760f, 0.119263f, 0.134888f, 0.151978f, + 0.168335f, 0.186646f, 0.204102f, 0.223022f, 0.242065f, 0.260986f, 0.280518f, 0.300537f, 0.320801f, 0.340820f, 0.360107f, 0.381104f, + 0.401367f, 0.421387f, 0.441650f, 0.460449f, 0.480957f, 0.500000f, 0.519531f, 0.538574f, 0.557129f, 0.575684f, 0.593262f, 0.610840f, + 0.628906f, 0.645508f, 0.662109f, 0.677246f, 0.692871f, 0.708008f, 0.723145f, 0.738281f, 0.751465f, 0.766113f, 0.778320f, 0.791504f, + 0.802246f, 0.816406f, 0.827637f, 0.838867f, 0.850098f, 0.860352f, 0.871582f, 0.881348f, 0.890137f, 0.899902f, 0.951660f, 0.948730f, + 0.944824f, 0.940918f, 0.937012f, 0.933594f, 0.004269f, 0.013809f, 0.023911f, 0.033569f, 0.044342f, 0.056213f, 0.068054f, 0.080811f, + 0.093933f, 0.107910f, 0.122131f, 0.137451f, 0.152710f, 0.169434f, 0.185791f, 0.203979f, 0.221436f, 0.239990f, 0.257812f, 0.277344f, + 0.296631f, 0.316162f, 0.335693f, 0.355713f, 0.375244f, 0.395996f, 0.416016f, 0.436035f, 0.455078f, 0.474365f, 0.494629f, 0.513184f, + 0.532715f, 0.550781f, 0.569336f, 0.586914f, 0.604980f, 0.622559f, 0.639648f, 0.655762f, 0.672363f, 0.688477f, 0.704102f, 0.718750f, + 0.733887f, 0.747559f, 0.761230f, 0.775391f, 0.788574f, 0.800781f, 0.814453f, 0.825684f, 0.837402f, 0.848633f, 0.859375f, 0.870605f, + 0.880371f, 0.891113f, 0.947754f, 0.945312f, 0.941895f, 0.937988f, 0.934082f, 0.931152f, 0.004028f, 0.012581f, 0.021133f, 0.030396f, + 0.039948f, 0.050323f, 0.061523f, 0.072815f, 0.084961f, 0.096985f, 0.110535f, 0.124756f, 0.138916f, 0.153687f, 0.169800f, 0.185669f, + 0.202881f, 0.219116f, 0.237305f, 0.255615f, 0.273926f, 0.293213f, 0.311768f, 0.331055f, 0.351074f, 0.370605f, 0.390381f, 0.409668f, + 0.429688f, 0.449707f, 0.468994f, 0.487549f, 0.506836f, 0.526367f, 0.545898f, 0.562988f, 0.581543f, 0.599121f, 0.616699f, 0.634766f, + 0.651367f, 0.667480f, 0.683594f, 0.699707f, 0.714844f, 0.730957f, 0.744141f, 0.758789f, 0.772949f, 0.785645f, 0.799316f, 0.812500f, + 0.823730f, 0.836914f, 0.847168f, 0.859375f, 0.869629f, 0.880371f, 0.942383f, 0.941406f, 0.937500f, 0.934570f, 0.931152f, 0.927734f, + 0.003613f, 0.011391f, 0.018875f, 0.027679f, 0.036133f, 0.045624f, 0.055420f, 0.065491f, 0.076416f, 0.088135f, 0.099487f, 0.112427f, + 0.126099f, 0.139771f, 0.154419f, 0.169556f, 0.184814f, 0.201050f, 0.218262f, 0.234985f, 0.252441f, 0.271484f, 0.289062f, 0.308594f, + 0.326660f, 0.346924f, 0.365234f, 0.384521f, 0.404541f, 0.424072f, 0.443359f, 0.463135f, 0.482422f, 0.501953f, 0.521484f, 0.539551f, + 0.558594f, 0.576660f, 0.595215f, 0.612793f, 0.629883f, 0.647949f, 0.663574f, 0.679688f, 0.695801f, 0.711426f, 0.727539f, 0.741699f, + 0.757324f, 0.770996f, 0.785156f, 0.798828f, 0.811035f, 0.823730f, 0.835449f, 0.848145f, 0.858887f, 0.870605f, 0.937988f, 0.937988f, + 0.934570f, 0.931152f, 0.927734f, 0.924805f, 0.003248f, 0.010185f, 0.017395f, 0.025055f, 0.032928f, 0.041321f, 0.049957f, 0.059265f, + 0.069092f, 0.079407f, 0.090820f, 0.101746f, 0.113770f, 0.126953f, 0.140381f, 0.154053f, 0.168701f, 0.184082f, 0.199951f, 0.216431f, + 0.232788f, 0.250000f, 0.267578f, 0.285645f, 0.303955f, 0.322998f, 0.341553f, 0.361084f, 0.379150f, 0.399414f, 0.418701f, 0.437988f, + 0.457275f, 0.477051f, 0.496094f, 0.515137f, 0.534180f, 0.553223f, 0.571289f, 0.589844f, 0.606934f, 0.625488f, 0.643066f, 0.659668f, + 0.676758f, 0.692871f, 0.708984f, 0.725098f, 0.740234f, 0.753906f, 0.769043f, 0.782227f, 0.796387f, 0.810059f, 0.822266f, 0.834961f, + 0.847168f, 0.859375f, 0.933594f, 0.933594f, 0.931152f, 0.927246f, 0.923828f, 0.921387f, 0.002914f, 0.009361f, 0.015793f, 0.022659f, + 0.029938f, 0.037354f, 0.045593f, 0.053406f, 0.062988f, 0.072083f, 0.081665f, 0.092712f, 0.103943f, 0.114990f, 0.128174f, 0.140503f, + 0.153809f, 0.167725f, 0.182251f, 0.198242f, 0.213623f, 0.230225f, 0.246826f, 0.263672f, 0.281494f, 0.300049f, 0.318604f, 0.337158f, + 0.356201f, 0.374756f, 0.394531f, 0.413574f, 0.433105f, 0.451904f, 0.471680f, 0.491211f, 0.509766f, 0.529297f, 0.547852f, 0.566895f, + 0.584961f, 0.603516f, 0.621094f, 0.638672f, 0.656738f, 0.673340f, 0.689453f, 0.706543f, 0.722656f, 0.737793f, 0.752930f, 0.767578f, + 0.781250f, 0.796875f, 0.809082f, 0.823242f, 0.835449f, 0.847656f, 0.929199f, 0.929199f, 0.927246f, 0.923828f, 0.920898f, 0.917969f, + 0.002766f, 0.008736f, 0.014442f, 0.020691f, 0.027054f, 0.033905f, 0.040924f, 0.048645f, 0.056976f, 0.065674f, 0.074951f, 0.084229f, + 0.094116f, 0.105225f, 0.116333f, 0.127563f, 0.139771f, 0.153564f, 0.166626f, 0.181030f, 0.196411f, 0.211182f, 0.227417f, 0.243896f, + 0.260742f, 0.277588f, 0.295898f, 0.314209f, 0.332031f, 0.351562f, 0.370117f, 0.389404f, 0.408203f, 0.428223f, 0.447266f, 0.467041f, + 0.486084f, 0.505859f, 0.524414f, 0.543945f, 0.562012f, 0.581543f, 0.600098f, 0.617676f, 0.636230f, 0.654297f, 0.670898f, 0.687500f, + 0.704102f, 0.720703f, 0.736816f, 0.751465f, 0.766113f, 0.781738f, 0.796387f, 0.809082f, 0.823242f, 0.835938f, 0.923828f, 0.925781f, + 0.922852f, 0.920410f, 0.916992f, 0.914551f, 0.002483f, 0.007599f, 0.013161f, 0.018555f, 0.024551f, 0.030670f, 0.037476f, 0.044464f, + 0.051636f, 0.059174f, 0.067688f, 0.075928f, 0.085693f, 0.095093f, 0.105591f, 0.116394f, 0.127441f, 0.139648f, 0.152344f, 0.165527f, + 0.179565f, 0.193970f, 0.208862f, 0.224487f, 0.240356f, 0.256836f, 0.274658f, 0.291748f, 0.310059f, 0.328369f, 0.346680f, 0.365234f, + 0.384521f, 0.404297f, 0.423340f, 0.442139f, 0.462646f, 0.481445f, 0.500977f, 0.520020f, 0.540039f, 0.559082f, 0.577148f, 0.596191f, + 0.614746f, 0.632812f, 0.651367f, 0.669434f, 0.685059f, 0.702637f, 0.718750f, 0.734375f, 0.750488f, 0.766113f, 0.780762f, 0.795410f, + 0.811035f, 0.823730f, 0.919434f, 0.920898f, 0.918457f, 0.916016f, 0.913086f, 0.910645f, 0.002457f, 0.007114f, 0.011757f, 0.016708f, + 0.022125f, 0.027786f, 0.033752f, 0.040375f, 0.046661f, 0.053864f, 0.061584f, 0.069336f, 0.077515f, 0.086365f, 0.095947f, 0.105896f, + 0.116638f, 0.127075f, 0.138916f, 0.151245f, 0.164062f, 0.177490f, 0.191528f, 0.206177f, 0.221802f, 0.237427f, 0.253906f, 0.270508f, + 0.287842f, 0.305664f, 0.323730f, 0.342285f, 0.361572f, 0.379639f, 0.399170f, 0.418457f, 0.438965f, 0.458252f, 0.477295f, 0.497559f, + 0.516113f, 0.536133f, 0.554688f, 0.574707f, 0.593750f, 0.612305f, 0.630859f, 0.648926f, 0.666504f, 0.684082f, 0.701660f, 0.717773f, + 0.734863f, 0.751465f, 0.766602f, 0.781738f, 0.797852f, 0.812012f, 0.913086f, 0.916016f, 0.913574f, 0.911621f, 0.909180f, 0.906250f, + 0.002132f, 0.006493f, 0.010750f, 0.015717f, 0.020569f, 0.025604f, 0.030823f, 0.036682f, 0.043060f, 0.049286f, 0.055786f, 0.062988f, + 0.070557f, 0.078918f, 0.086914f, 0.096191f, 0.105530f, 0.116028f, 0.126953f, 0.138306f, 0.149902f, 0.162231f, 0.175537f, 0.189453f, + 0.203491f, 0.218628f, 0.234131f, 0.250000f, 0.266602f, 0.284180f, 0.301514f, 0.319580f, 0.338135f, 0.356689f, 0.375977f, 0.395020f, + 0.413818f, 0.434082f, 0.452881f, 0.473145f, 0.492920f, 0.512207f, 0.532227f, 0.552246f, 0.570801f, 0.591309f, 0.609375f, 0.629395f, + 0.646973f, 0.665527f, 0.683105f, 0.700684f, 0.717773f, 0.734863f, 0.751465f, 0.767578f, 0.782715f, 0.799316f, 0.908203f, 0.911133f, + 0.909180f, 0.907227f, 0.904785f, 0.902832f, 0.001891f, 0.006008f, 0.010025f, 0.014122f, 0.018616f, 0.023239f, 0.028442f, 0.033691f, + 0.038757f, 0.044556f, 0.050964f, 0.057465f, 0.064087f, 0.071167f, 0.079224f, 0.087463f, 0.096008f, 0.105591f, 0.115356f, 0.125488f, + 0.136597f, 0.148193f, 0.160278f, 0.173218f, 0.186768f, 0.200684f, 0.215332f, 0.231323f, 0.246338f, 0.262939f, 0.279785f, 0.297607f, + 0.314941f, 0.333984f, 0.353271f, 0.371094f, 0.391357f, 0.409668f, 0.430420f, 0.448975f, 0.469482f, 0.489746f, 0.509277f, 0.528809f, + 0.549316f, 0.568848f, 0.588379f, 0.607910f, 0.626953f, 0.645996f, 0.664062f, 0.683105f, 0.700684f, 0.718262f, 0.735840f, 0.751953f, + 0.768555f, 0.785645f, 0.902344f, 0.906250f, 0.904785f, 0.902832f, 0.900391f, 0.898438f, 0.001732f, 0.005573f, 0.009193f, 0.012932f, + 0.017075f, 0.021286f, 0.025406f, 0.030289f, 0.035675f, 0.040344f, 0.046326f, 0.052032f, 0.058411f, 0.064575f, 0.072205f, 0.079834f, + 0.087708f, 0.095947f, 0.104797f, 0.114380f, 0.124451f, 0.134888f, 0.146606f, 0.158691f, 0.170776f, 0.184082f, 0.197510f, 0.212524f, + 0.227417f, 0.243164f, 0.259521f, 0.276367f, 0.293457f, 0.311768f, 0.329590f, 0.348633f, 0.367188f, 0.386230f, 0.406006f, 0.425781f, + 0.446533f, 0.465332f, 0.486084f, 0.505859f, 0.526367f, 0.545898f, 0.567383f, 0.585938f, 0.605957f, 0.625977f, 0.645508f, 0.664551f, + 0.683105f, 0.701172f, 0.718750f, 0.736816f, 0.754395f, 0.770508f, 0.896484f, 0.900879f, 0.900391f, 0.897949f, 0.895996f, 0.894043f, + 0.001713f, 0.004684f, 0.008339f, 0.011818f, 0.015450f, 0.019409f, 0.023605f, 0.027832f, 0.032349f, 0.036865f, 0.041809f, 0.047302f, + 0.052673f, 0.058838f, 0.065613f, 0.072083f, 0.079407f, 0.087280f, 0.095337f, 0.104126f, 0.113037f, 0.122986f, 0.133667f, 0.144897f, + 0.156250f, 0.168579f, 0.181396f, 0.195068f, 0.208984f, 0.224243f, 0.239624f, 0.255859f, 0.272461f, 0.289551f, 0.307617f, 0.326172f, + 0.344482f, 0.363770f, 0.383301f, 0.402588f, 0.422607f, 0.443115f, 0.463135f, 0.483154f, 0.503418f, 0.523926f, 0.544434f, 0.564941f, + 0.584473f, 0.604980f, 0.624512f, 0.645508f, 0.664551f, 0.683594f, 0.701660f, 0.721191f, 0.738281f, 0.755859f, 0.889648f, 0.895996f, + 0.895020f, 0.893066f, 0.891602f, 0.889160f, 0.001545f, 0.004745f, 0.007710f, 0.010979f, 0.014450f, 0.017807f, 0.021469f, 0.025238f, + 0.029282f, 0.033661f, 0.038177f, 0.043182f, 0.048157f, 0.053436f, 0.059326f, 0.065674f, 0.072205f, 0.078857f, 0.086548f, 0.094604f, + 0.102905f, 0.111816f, 0.121521f, 0.131592f, 0.142334f, 0.153442f, 0.165894f, 0.178345f, 0.192139f, 0.205933f, 0.220703f, 0.236084f, + 0.251709f, 0.268555f, 0.285645f, 0.303467f, 0.321777f, 0.340332f, 0.359619f, 0.379150f, 0.398682f, 0.419189f, 0.440430f, 0.460449f, + 0.480957f, 0.501465f, 0.521973f, 0.543457f, 0.563477f, 0.584961f, 0.604492f, 0.625488f, 0.645508f, 0.665039f, 0.684082f, 0.704102f, + 0.723145f, 0.741211f, 0.885254f, 0.890137f, 0.889160f, 0.887695f, 0.886719f, 0.884277f, 0.001487f, 0.004356f, 0.006828f, 0.010162f, + 0.012993f, 0.016022f, 0.019333f, 0.023087f, 0.026886f, 0.030518f, 0.034668f, 0.039062f, 0.043671f, 0.048370f, 0.053741f, 0.059326f, + 0.065308f, 0.071655f, 0.078125f, 0.085693f, 0.093323f, 0.101807f, 0.110657f, 0.119507f, 0.129517f, 0.140137f, 0.151367f, 0.163330f, + 0.175781f, 0.188843f, 0.202759f, 0.217163f, 0.232666f, 0.248413f, 0.264893f, 0.282227f, 0.299805f, 0.318115f, 0.336914f, 0.356445f, + 0.375488f, 0.395996f, 0.416504f, 0.436279f, 0.457520f, 0.479004f, 0.499023f, 0.520508f, 0.541504f, 0.562988f, 0.583984f, 0.604492f, + 0.625488f, 0.646973f, 0.666504f, 0.687012f, 0.706055f, 0.725098f, 0.877441f, 0.885254f, 0.884766f, 0.882324f, 0.881836f, 0.880371f, + 0.001443f, 0.003807f, 0.006336f, 0.009171f, 0.011909f, 0.015007f, 0.018097f, 0.020905f, 0.024384f, 0.027893f, 0.031555f, 0.035370f, + 0.039581f, 0.044128f, 0.048889f, 0.053894f, 0.059174f, 0.065125f, 0.070984f, 0.077698f, 0.084656f, 0.091919f, 0.100037f, 0.108093f, + 0.117493f, 0.127563f, 0.137817f, 0.148438f, 0.159912f, 0.172485f, 0.185547f, 0.199585f, 0.213867f, 0.229248f, 0.244995f, 0.261230f, + 0.278564f, 0.296387f, 0.314697f, 0.333252f, 0.353271f, 0.372314f, 0.393311f, 0.413330f, 0.433594f, 0.455078f, 0.476318f, 0.497314f, + 0.519531f, 0.540527f, 0.562500f, 0.583496f, 0.605469f, 0.626953f, 0.648438f, 0.669434f, 0.689941f, 0.709961f, 0.870605f, 0.878906f, + 0.878418f, 0.877441f, 0.875488f, 0.873535f, 0.001302f, 0.003712f, 0.005859f, 0.008286f, 0.010910f, 0.013779f, 0.016235f, 0.019135f, + 0.021912f, 0.025345f, 0.029022f, 0.032166f, 0.036011f, 0.040131f, 0.044128f, 0.048492f, 0.053528f, 0.058533f, 0.064209f, 0.070129f, + 0.076355f, 0.083191f, 0.090149f, 0.098328f, 0.106628f, 0.115662f, 0.124817f, 0.134766f, 0.145630f, 0.157104f, 0.169678f, 0.182495f, + 0.195801f, 0.210205f, 0.225342f, 0.241455f, 0.257812f, 0.274902f, 0.292725f, 0.311035f, 0.330322f, 0.349365f, 0.369873f, 0.390137f, + 0.411133f, 0.432373f, 0.453369f, 0.474609f, 0.496826f, 0.519043f, 0.541504f, 0.563477f, 0.585449f, 0.606445f, 0.629395f, 0.650391f, + 0.672363f, 0.693848f, 0.863281f, 0.872070f, 0.872070f, 0.871582f, 0.869629f, 0.868164f, 0.001170f, 0.003151f, 0.005295f, 0.007812f, + 0.010132f, 0.012466f, 0.015076f, 0.017517f, 0.019943f, 0.023178f, 0.026443f, 0.029312f, 0.032471f, 0.036041f, 0.039978f, 0.044037f, + 0.048828f, 0.053070f, 0.057983f, 0.063232f, 0.068909f, 0.075378f, 0.081909f, 0.088745f, 0.096375f, 0.104309f, 0.113281f, 0.122437f, + 0.132202f, 0.142944f, 0.154419f, 0.166138f, 0.178955f, 0.192505f, 0.206421f, 0.221558f, 0.237183f, 0.253906f, 0.270996f, 0.289062f, + 0.308105f, 0.326904f, 0.346924f, 0.366455f, 0.387695f, 0.408936f, 0.430176f, 0.451416f, 0.474365f, 0.496582f, 0.518066f, 0.541016f, + 0.563965f, 0.585938f, 0.608887f, 0.630859f, 0.654297f, 0.675781f, 0.856934f, 0.865234f, 0.866211f, 0.864746f, 0.863281f, 0.862793f, + 0.001049f, 0.003254f, 0.005234f, 0.007263f, 0.009270f, 0.011307f, 0.013596f, 0.015869f, 0.018555f, 0.020844f, 0.023972f, 0.026566f, + 0.029739f, 0.033020f, 0.036316f, 0.039856f, 0.044159f, 0.048096f, 0.052277f, 0.057281f, 0.062439f, 0.067871f, 0.073792f, 0.079956f, + 0.087158f, 0.094055f, 0.102234f, 0.110535f, 0.119934f, 0.129517f, 0.140259f, 0.151245f, 0.162842f, 0.175537f, 0.189209f, 0.203369f, + 0.218262f, 0.233643f, 0.250488f, 0.268066f, 0.285645f, 0.304443f, 0.324219f, 0.343750f, 0.364014f, 0.385254f, 0.406494f, 0.428223f, + 0.450928f, 0.472656f, 0.495605f, 0.519043f, 0.541504f, 0.565918f, 0.588379f, 0.612305f, 0.635742f, 0.659180f, 0.850098f, 0.859863f, + 0.859863f, 0.858398f, 0.857910f, 0.856934f, 0.000914f, 0.002861f, 0.004742f, 0.006569f, 0.008415f, 0.010521f, 0.012596f, 0.014648f, + 0.016708f, 0.019089f, 0.021515f, 0.023865f, 0.026688f, 0.029572f, 0.032928f, 0.036377f, 0.039337f, 0.043365f, 0.047333f, 0.051544f, + 0.056305f, 0.061066f, 0.066406f, 0.071960f, 0.078247f, 0.084961f, 0.092163f, 0.099426f, 0.108215f, 0.116943f, 0.126831f, 0.136719f, + 0.148193f, 0.159302f, 0.171875f, 0.185669f, 0.199585f, 0.214478f, 0.230469f, 0.247070f, 0.264160f, 0.282471f, 0.301270f, 0.321045f, + 0.341553f, 0.362061f, 0.383545f, 0.404785f, 0.427734f, 0.449951f, 0.473389f, 0.496582f, 0.520020f, 0.543457f, 0.568359f, 0.592285f, + 0.615723f, 0.639648f, 0.840820f, 0.851074f, 0.853027f, 0.853027f, 0.852051f, 0.850586f, 0.000679f, 0.002518f, 0.004173f, 0.006149f, + 0.008064f, 0.009369f, 0.011551f, 0.013222f, 0.015175f, 0.017212f, 0.019592f, 0.021835f, 0.024048f, 0.026932f, 0.029846f, 0.032623f, + 0.035675f, 0.038940f, 0.042542f, 0.046295f, 0.050354f, 0.055054f, 0.059601f, 0.064880f, 0.070190f, 0.076233f, 0.082703f, 0.089661f, + 0.097229f, 0.105103f, 0.113831f, 0.123474f, 0.133423f, 0.144409f, 0.156006f, 0.168335f, 0.182495f, 0.196411f, 0.211304f, 0.227295f, + 0.243530f, 0.260986f, 0.279053f, 0.298828f, 0.318359f, 0.339111f, 0.360107f, 0.381348f, 0.403809f, 0.427490f, 0.449463f, 0.473633f, + 0.497803f, 0.521484f, 0.546875f, 0.570801f, 0.595703f, 0.620605f, 0.833008f, 0.845215f, 0.845703f, 0.845703f, 0.845215f, 0.843750f, + 0.000719f, 0.002470f, 0.003975f, 0.005337f, 0.007275f, 0.008713f, 0.010376f, 0.012032f, 0.013580f, 0.015793f, 0.017609f, 0.019501f, + 0.021530f, 0.024277f, 0.026657f, 0.029312f, 0.031982f, 0.035187f, 0.038086f, 0.041565f, 0.045288f, 0.049103f, 0.053436f, 0.058136f, + 0.062927f, 0.068054f, 0.073853f, 0.080383f, 0.087341f, 0.094666f, 0.102173f, 0.111084f, 0.120300f, 0.130859f, 0.141235f, 0.152954f, + 0.164429f, 0.178223f, 0.192749f, 0.207642f, 0.223145f, 0.239868f, 0.258301f, 0.276611f, 0.295654f, 0.316162f, 0.337402f, 0.358643f, + 0.380859f, 0.403320f, 0.427002f, 0.450684f, 0.474609f, 0.499756f, 0.523926f, 0.550781f, 0.575195f, 0.600586f, 0.824707f, 0.836914f, + 0.838379f, 0.838867f, 0.837402f, 0.837402f, 0.000683f, 0.002361f, 0.003649f, 0.005116f, 0.006416f, 0.008202f, 0.009460f, 0.010941f, + 0.012817f, 0.014099f, 0.015839f, 0.017593f, 0.019867f, 0.021988f, 0.023926f, 0.026276f, 0.028824f, 0.031311f, 0.034363f, 0.036957f, + 0.040375f, 0.043823f, 0.047546f, 0.051758f, 0.056183f, 0.061249f, 0.066162f, 0.071777f, 0.077942f, 0.084534f, 0.091553f, 0.099487f, + 0.107910f, 0.116882f, 0.127075f, 0.137451f, 0.148804f, 0.161499f, 0.174805f, 0.188721f, 0.203735f, 0.220093f, 0.237427f, 0.254639f, + 0.273926f, 0.293457f, 0.313965f, 0.334961f, 0.357666f, 0.379883f, 0.403076f, 0.427002f, 0.451660f, 0.476807f, 0.501953f, 0.527344f, + 0.553711f, 0.581055f, 0.815918f, 0.829102f, 0.831055f, 0.831055f, 0.831055f, 0.830566f, 0.000607f, 0.001863f, 0.003416f, 0.004528f, + 0.005943f, 0.007191f, 0.008781f, 0.009964f, 0.011337f, 0.012939f, 0.014458f, 0.015808f, 0.018051f, 0.019394f, 0.021332f, 0.023529f, + 0.025803f, 0.028168f, 0.030502f, 0.033020f, 0.036072f, 0.039032f, 0.042419f, 0.046082f, 0.049927f, 0.054321f, 0.058411f, 0.063538f, + 0.069336f, 0.075684f, 0.081787f, 0.088562f, 0.096436f, 0.104553f, 0.113281f, 0.123596f, 0.133667f, 0.145386f, 0.157471f, 0.171021f, + 0.185547f, 0.200562f, 0.216553f, 0.234619f, 0.251709f, 0.271240f, 0.291504f, 0.312012f, 0.333496f, 0.355957f, 0.379395f, 0.403076f, + 0.428223f, 0.453857f, 0.479492f, 0.506348f, 0.532715f, 0.560059f, 0.805664f, 0.820801f, 0.823730f, 0.822754f, 0.822754f, 0.822266f, + 0.000593f, 0.001862f, 0.002966f, 0.004341f, 0.005600f, 0.006516f, 0.007626f, 0.008995f, 0.010223f, 0.011292f, 0.012848f, 0.014427f, + 0.016098f, 0.017532f, 0.019165f, 0.021027f, 0.022842f, 0.024918f, 0.027115f, 0.029739f, 0.032013f, 0.034637f, 0.037506f, 0.040955f, + 0.044220f, 0.048065f, 0.051941f, 0.056305f, 0.061768f, 0.066528f, 0.072327f, 0.078979f, 0.085571f, 0.092834f, 0.101135f, 0.110229f, + 0.119690f, 0.130127f, 0.141602f, 0.153564f, 0.167114f, 0.181763f, 0.196899f, 0.213623f, 0.230957f, 0.249268f, 0.268555f, 0.289062f, + 0.310059f, 0.333252f, 0.355957f, 0.379883f, 0.404541f, 0.430176f, 0.456055f, 0.483887f, 0.510254f, 0.539062f, 0.797852f, 0.812988f, + 0.814941f, 0.815430f, 0.815918f, 0.814453f, 0.000556f, 0.001811f, 0.002998f, 0.003815f, 0.004658f, 0.005905f, 0.007099f, 0.008232f, + 0.009239f, 0.010483f, 0.011559f, 0.013016f, 0.014305f, 0.015671f, 0.017090f, 0.018646f, 0.020370f, 0.022369f, 0.024124f, 0.026062f, + 0.028458f, 0.030624f, 0.033264f, 0.036041f, 0.039307f, 0.042053f, 0.045807f, 0.049530f, 0.054016f, 0.058441f, 0.063904f, 0.069641f, + 0.075745f, 0.082520f, 0.089539f, 0.097717f, 0.106750f, 0.116150f, 0.126587f, 0.137817f, 0.150024f, 0.163452f, 0.177490f, 0.193359f, + 0.209717f, 0.227539f, 0.246704f, 0.266602f, 0.287598f, 0.309326f, 0.332520f, 0.355713f, 0.380371f, 0.406494f, 0.432861f, 0.459961f, + 0.488525f, 0.517090f, 0.787598f, 0.804199f, 0.806641f, 0.807617f, 0.807617f, 0.807129f, 0.000507f, 0.001697f, 0.002468f, 0.003351f, + 0.004425f, 0.005486f, 0.006325f, 0.007412f, 0.008156f, 0.009270f, 0.010239f, 0.011497f, 0.012520f, 0.013954f, 0.015182f, 0.016617f, + 0.018036f, 0.019714f, 0.021362f, 0.022934f, 0.024704f, 0.026886f, 0.029419f, 0.031525f, 0.034302f, 0.037292f, 0.040558f, 0.043701f, + 0.047577f, 0.051849f, 0.056183f, 0.061249f, 0.066467f, 0.072876f, 0.078918f, 0.086548f, 0.094116f, 0.102844f, 0.112427f, 0.122620f, + 0.133667f, 0.146362f, 0.159668f, 0.174438f, 0.190063f, 0.207153f, 0.225098f, 0.244263f, 0.264648f, 0.286377f, 0.308350f, 0.332275f, + 0.357178f, 0.382080f, 0.408936f, 0.436035f, 0.465820f, 0.495361f, 0.776855f, 0.794922f, 0.797852f, 0.799316f, 0.798828f, 0.798340f, + 0.000366f, 0.001644f, 0.002289f, 0.003046f, 0.004082f, 0.005032f, 0.005550f, 0.006599f, 0.007389f, 0.008369f, 0.009201f, 0.010315f, + 0.011276f, 0.012405f, 0.013466f, 0.014587f, 0.015991f, 0.017303f, 0.018692f, 0.020081f, 0.021851f, 0.023865f, 0.025726f, 0.027771f, + 0.030136f, 0.032532f, 0.035309f, 0.038422f, 0.041626f, 0.045044f, 0.048767f, 0.053375f, 0.057861f, 0.063477f, 0.069031f, 0.075684f, + 0.082336f, 0.090515f, 0.099182f, 0.107849f, 0.118958f, 0.130005f, 0.142212f, 0.156128f, 0.170898f, 0.186890f, 0.203857f, 0.222534f, + 0.241821f, 0.263428f, 0.285156f, 0.308105f, 0.332275f, 0.359131f, 0.385010f, 0.413086f, 0.441895f, 0.472168f, 0.767090f, 0.785645f, + 0.789062f, 0.789551f, 0.790527f, 0.789551f, 0.000340f, 0.001434f, 0.002129f, 0.002827f, 0.003696f, 0.004463f, 0.005112f, 0.005730f, + 0.006836f, 0.007465f, 0.008217f, 0.008972f, 0.009972f, 0.010887f, 0.011948f, 0.012794f, 0.013947f, 0.015030f, 0.016266f, 0.017670f, + 0.019165f, 0.020813f, 0.022415f, 0.024216f, 0.026047f, 0.028336f, 0.030594f, 0.033142f, 0.035858f, 0.039154f, 0.042328f, 0.046265f, + 0.050537f, 0.055237f, 0.059998f, 0.065918f, 0.072083f, 0.078918f, 0.086243f, 0.094788f, 0.104309f, 0.114807f, 0.125854f, 0.138672f, + 0.152222f, 0.166992f, 0.183716f, 0.200928f, 0.220459f, 0.240112f, 0.261719f, 0.284668f, 0.308838f, 0.333740f, 0.360840f, 0.388672f, + 0.418213f, 0.448730f, 0.756348f, 0.775391f, 0.779297f, 0.780273f, 0.781250f, 0.780273f, 0.000511f, 0.001174f, 0.002163f, 0.002554f, + 0.003391f, 0.003990f, 0.004547f, 0.005211f, 0.005993f, 0.006653f, 0.007462f, 0.007942f, 0.008781f, 0.009476f, 0.010323f, 0.011444f, + 0.012207f, 0.013062f, 0.014336f, 0.015427f, 0.016464f, 0.017929f, 0.019287f, 0.021164f, 0.022461f, 0.024567f, 0.026474f, 0.028885f, + 0.031067f, 0.033630f, 0.036835f, 0.040070f, 0.043488f, 0.047394f, 0.051910f, 0.056732f, 0.062378f, 0.068481f, 0.075073f, 0.082764f, + 0.090881f, 0.100403f, 0.110779f, 0.122009f, 0.134399f, 0.148560f, 0.163940f, 0.180298f, 0.198120f, 0.218140f, 0.239014f, 0.260986f, + 0.285645f, 0.310059f, 0.336182f, 0.364502f, 0.393311f, 0.424316f, 0.744629f, 0.765137f, 0.769531f, 0.770508f, 0.771484f, 0.771484f, + 0.000374f, 0.000983f, 0.001696f, 0.002279f, 0.002924f, 0.003571f, 0.004139f, 0.004742f, 0.005390f, 0.005817f, 0.006371f, 0.006981f, + 0.007648f, 0.008354f, 0.009041f, 0.009727f, 0.010536f, 0.011375f, 0.012398f, 0.013535f, 0.014389f, 0.015541f, 0.016602f, 0.018112f, + 0.019516f, 0.020996f, 0.022644f, 0.024582f, 0.026627f, 0.028748f, 0.031586f, 0.034210f, 0.037415f, 0.040588f, 0.044464f, 0.048676f, + 0.053192f, 0.058472f, 0.064880f, 0.070984f, 0.078674f, 0.086914f, 0.096191f, 0.106445f, 0.117859f, 0.130859f, 0.144775f, 0.160522f, + 0.177490f, 0.196411f, 0.215942f, 0.237793f, 0.261475f, 0.285645f, 0.312012f, 0.339111f, 0.368652f, 0.400391f, 0.733887f, 0.755371f, + 0.759766f, 0.760742f, 0.761719f, 0.761719f, 0.000298f, 0.000924f, 0.001542f, 0.002125f, 0.002439f, 0.003153f, 0.003502f, 0.004196f, + 0.004585f, 0.005039f, 0.005531f, 0.006054f, 0.006531f, 0.007217f, 0.007935f, 0.008362f, 0.009171f, 0.009773f, 0.010704f, 0.011505f, + 0.012207f, 0.013321f, 0.014381f, 0.015556f, 0.016586f, 0.017792f, 0.019608f, 0.020844f, 0.022583f, 0.024536f, 0.026566f, 0.028885f, + 0.031494f, 0.034332f, 0.037689f, 0.041260f, 0.045258f, 0.049927f, 0.054901f, 0.060699f, 0.067322f, 0.074768f, 0.082764f, 0.091675f, + 0.102173f, 0.113831f, 0.126831f, 0.141113f, 0.157104f, 0.175049f, 0.194580f, 0.215210f, 0.237305f, 0.261475f, 0.287598f, 0.314697f, + 0.344482f, 0.375977f, 0.721680f, 0.744629f, 0.749512f, 0.751465f, 0.751465f, 0.751465f, 0.000275f, 0.001002f, 0.001335f, 0.001704f, + 0.002264f, 0.002790f, 0.003202f, 0.003555f, 0.004017f, 0.004368f, 0.004894f, 0.005318f, 0.005592f, 0.006241f, 0.006611f, 0.007317f, + 0.007851f, 0.008560f, 0.009071f, 0.009758f, 0.010429f, 0.011375f, 0.011986f, 0.013130f, 0.013916f, 0.015205f, 0.016403f, 0.017624f, + 0.019119f, 0.020660f, 0.022278f, 0.024582f, 0.026474f, 0.029007f, 0.031738f, 0.034668f, 0.038025f, 0.041962f, 0.046417f, 0.051270f, + 0.056915f, 0.063110f, 0.070312f, 0.078369f, 0.087769f, 0.098145f, 0.109863f, 0.123352f, 0.137451f, 0.154785f, 0.172363f, 0.192261f, + 0.214233f, 0.237793f, 0.262939f, 0.289795f, 0.319336f, 0.351074f, 0.708984f, 0.733398f, 0.738281f, 0.740234f, 0.741211f, 0.740723f, + 0.000334f, 0.000805f, 0.001231f, 0.001640f, 0.002033f, 0.002277f, 0.002871f, 0.003115f, 0.003481f, 0.003895f, 0.004147f, 0.004379f, + 0.004841f, 0.005306f, 0.005653f, 0.006241f, 0.006630f, 0.007217f, 0.007721f, 0.008133f, 0.008842f, 0.009529f, 0.010010f, 0.011017f, + 0.011780f, 0.012733f, 0.013626f, 0.014824f, 0.015656f, 0.017212f, 0.018829f, 0.020248f, 0.021973f, 0.023926f, 0.026306f, 0.028900f, + 0.031616f, 0.034973f, 0.038605f, 0.042816f, 0.047424f, 0.052765f, 0.059021f, 0.066162f, 0.074219f, 0.083435f, 0.093994f, 0.105835f, + 0.119385f, 0.134277f, 0.151611f, 0.170532f, 0.191284f, 0.214233f, 0.239014f, 0.265381f, 0.293701f, 0.325684f, 0.696289f, 0.722168f, + 0.727051f, 0.729004f, 0.729980f, 0.729980f, 0.000215f, 0.000635f, 0.001184f, 0.001348f, 0.001758f, 0.002171f, 0.002249f, 0.002596f, + 0.003004f, 0.003325f, 0.003487f, 0.003906f, 0.004108f, 0.004494f, 0.004955f, 0.005241f, 0.005726f, 0.006134f, 0.006485f, 0.006916f, + 0.007496f, 0.008072f, 0.008629f, 0.009071f, 0.009857f, 0.010651f, 0.011375f, 0.012283f, 0.013283f, 0.014320f, 0.015350f, 0.016739f, + 0.017975f, 0.019852f, 0.021454f, 0.023712f, 0.025925f, 0.028717f, 0.031769f, 0.035217f, 0.038910f, 0.043396f, 0.048767f, 0.054901f, + 0.061707f, 0.069824f, 0.078613f, 0.089783f, 0.101685f, 0.115479f, 0.131104f, 0.149292f, 0.168823f, 0.190674f, 0.214844f, 0.241211f, + 0.269775f, 0.299561f, 0.683594f, 0.709961f, 0.715332f, 0.717773f, 0.718262f, 0.718750f, 0.000199f, 0.000826f, 0.001047f, 0.001288f, + 0.001600f, 0.001857f, 0.002014f, 0.002329f, 0.002535f, 0.002785f, 0.003027f, 0.003210f, 0.003580f, 0.003788f, 0.004025f, 0.004444f, + 0.004791f, 0.004974f, 0.005417f, 0.005909f, 0.006248f, 0.006672f, 0.007118f, 0.007664f, 0.008232f, 0.008759f, 0.009598f, 0.009964f, + 0.010956f, 0.011650f, 0.012665f, 0.013702f, 0.014832f, 0.016144f, 0.017654f, 0.019211f, 0.021118f, 0.023102f, 0.025681f, 0.028320f, + 0.031708f, 0.035370f, 0.039673f, 0.044739f, 0.050812f, 0.057800f, 0.065796f, 0.074768f, 0.085510f, 0.097961f, 0.112000f, 0.128662f, + 0.147217f, 0.168213f, 0.190796f, 0.216309f, 0.244751f, 0.274902f, 0.669922f, 0.698730f, 0.703613f, 0.705566f, 0.707031f, 0.707031f, + 0.000212f, 0.000458f, 0.000959f, 0.001192f, 0.001321f, 0.001500f, 0.001823f, 0.002064f, 0.002073f, 0.002293f, 0.002512f, 0.002768f, + 0.002981f, 0.003138f, 0.003431f, 0.003765f, 0.003918f, 0.004238f, 0.004482f, 0.004814f, 0.005245f, 0.005531f, 0.005871f, 0.006214f, + 0.006660f, 0.007236f, 0.007664f, 0.008331f, 0.008812f, 0.009628f, 0.010277f, 0.010979f, 0.012016f, 0.012978f, 0.014084f, 0.015495f, + 0.016937f, 0.018494f, 0.020386f, 0.022659f, 0.025208f, 0.028183f, 0.031860f, 0.036072f, 0.040894f, 0.046326f, 0.053009f, 0.061127f, + 0.070374f, 0.081238f, 0.094238f, 0.109314f, 0.126343f, 0.145874f, 0.167847f, 0.192505f, 0.219604f, 0.249634f, 0.656738f, 0.686035f, + 0.690430f, 0.694336f, 0.694336f, 0.696777f, 0.000151f, 0.000529f, 0.000692f, 0.000883f, 0.001153f, 0.001337f, 0.001380f, 0.001520f, + 0.001753f, 0.001886f, 0.002077f, 0.002243f, 0.002386f, 0.002556f, 0.002832f, 0.003029f, 0.003277f, 0.003447f, 0.003683f, 0.003952f, + 0.004135f, 0.004578f, 0.004833f, 0.005222f, 0.005417f, 0.005810f, 0.006355f, 0.006718f, 0.007076f, 0.007652f, 0.008293f, 0.008980f, + 0.009674f, 0.010422f, 0.011276f, 0.012283f, 0.013443f, 0.014664f, 0.016113f, 0.017853f, 0.019897f, 0.022156f, 0.024826f, 0.028275f, + 0.032135f, 0.036865f, 0.042389f, 0.049011f, 0.056732f, 0.066223f, 0.077576f, 0.090820f, 0.106384f, 0.124512f, 0.145264f, 0.169067f, + 0.195190f, 0.224976f, 0.642578f, 0.671387f, 0.679688f, 0.682617f, 0.682617f, 0.683594f, 0.000127f, 0.000376f, 0.000600f, 0.000721f, + 0.000901f, 0.001066f, 0.001180f, 0.001332f, 0.001455f, 0.001549f, 0.001709f, 0.001831f, 0.001947f, 0.002150f, 0.002245f, 0.002443f, + 0.002682f, 0.002844f, 0.002989f, 0.003201f, 0.003403f, 0.003683f, 0.003883f, 0.004097f, 0.004372f, 0.004665f, 0.004963f, 0.005348f, + 0.005711f, 0.006165f, 0.006672f, 0.007004f, 0.007610f, 0.008278f, 0.008873f, 0.009636f, 0.010475f, 0.011475f, 0.012634f, 0.014053f, + 0.015404f, 0.017242f, 0.019104f, 0.021774f, 0.024750f, 0.028458f, 0.032745f, 0.038391f, 0.044861f, 0.052795f, 0.062103f, 0.073914f, + 0.087830f, 0.104553f, 0.123718f, 0.145996f, 0.171509f, 0.200439f, 0.627930f, 0.658691f, 0.666504f, 0.668945f, 0.671387f, 0.671387f, + 0.000013f, 0.000374f, 0.000443f, 0.000688f, 0.000819f, 0.000844f, 0.001004f, 0.001132f, 0.001216f, 0.001259f, 0.001405f, 0.001523f, + 0.001566f, 0.001753f, 0.001842f, 0.001997f, 0.002022f, 0.002287f, 0.002377f, 0.002541f, 0.002787f, 0.002878f, 0.003096f, 0.003283f, + 0.003551f, 0.003651f, 0.003971f, 0.004272f, 0.004524f, 0.004887f, 0.005196f, 0.005527f, 0.005939f, 0.006386f, 0.006977f, 0.007526f, + 0.008148f, 0.008835f, 0.009689f, 0.010689f, 0.011810f, 0.013000f, 0.014641f, 0.016388f, 0.018799f, 0.021469f, 0.024734f, 0.029022f, + 0.034210f, 0.040588f, 0.048401f, 0.058319f, 0.070435f, 0.085205f, 0.102905f, 0.123901f, 0.147827f, 0.175903f, 0.612793f, 0.645508f, + 0.653320f, 0.656250f, 0.657227f, 0.657227f, 0.000113f, 0.000234f, 0.000465f, 0.000547f, 0.000646f, 0.000684f, 0.000711f, 0.000832f, + 0.000963f, 0.000999f, 0.001042f, 0.001183f, 0.001279f, 0.001402f, 0.001494f, 0.001513f, 0.001688f, 0.001716f, 0.001919f, 0.001993f, + 0.002081f, 0.002253f, 0.002441f, 0.002575f, 0.002714f, 0.002876f, 0.003050f, 0.003214f, 0.003531f, 0.003714f, 0.003956f, 0.004276f, + 0.004604f, 0.004967f, 0.005386f, 0.005718f, 0.006283f, 0.006790f, 0.007290f, 0.008133f, 0.008957f, 0.009987f, 0.010956f, 0.012375f, + 0.013916f, 0.015991f, 0.018311f, 0.021347f, 0.025253f, 0.030289f, 0.036560f, 0.044586f, 0.054779f, 0.067749f, 0.083252f, 0.102722f, + 0.125732f, 0.152100f, 0.597168f, 0.631836f, 0.639160f, 0.643555f, 0.643066f, 0.645508f, 0.000207f, 0.000175f, 0.000364f, 0.000507f, + 0.000496f, 0.000569f, 0.000683f, 0.000584f, 0.000737f, 0.000764f, 0.000885f, 0.000964f, 0.000999f, 0.001076f, 0.001085f, 0.001272f, + 0.001327f, 0.001354f, 0.001491f, 0.001494f, 0.001677f, 0.001781f, 0.001862f, 0.001976f, 0.002079f, 0.002190f, 0.002338f, 0.002481f, + 0.002691f, 0.002811f, 0.003117f, 0.003214f, 0.003422f, 0.003706f, 0.003990f, 0.004314f, 0.004608f, 0.004982f, 0.005379f, 0.006027f, + 0.006580f, 0.007351f, 0.008049f, 0.009041f, 0.010323f, 0.011551f, 0.013428f, 0.015419f, 0.018219f, 0.021713f, 0.026550f, 0.032715f, + 0.040833f, 0.051605f, 0.065552f, 0.082458f, 0.104004f, 0.129395f, 0.582031f, 0.618652f, 0.625488f, 0.627930f, 0.630859f, 0.631348f, + 0.000189f, 0.000160f, 0.000272f, 0.000387f, 0.000335f, 0.000486f, 0.000424f, 0.000469f, 0.000551f, 0.000589f, 0.000700f, 0.000727f, + 0.000772f, 0.000859f, 0.000891f, 0.000872f, 0.001000f, 0.001048f, 0.001076f, 0.001172f, 0.001224f, 0.001311f, 0.001376f, 0.001450f, + 0.001554f, 0.001591f, 0.001760f, 0.001838f, 0.001999f, 0.002180f, 0.002333f, 0.002388f, 0.002584f, 0.002777f, 0.002907f, 0.003162f, + 0.003368f, 0.003677f, 0.003979f, 0.004303f, 0.004715f, 0.005188f, 0.005787f, 0.006378f, 0.007313f, 0.008194f, 0.009407f, 0.010887f, + 0.012779f, 0.015198f, 0.018494f, 0.022888f, 0.029037f, 0.037659f, 0.048920f, 0.064270f, 0.083740f, 0.107300f, 0.565918f, 0.603516f, + 0.611328f, 0.614746f, 0.617188f, 0.618164f, 0.000000f, 0.000170f, 0.000207f, 0.000274f, 0.000292f, 0.000309f, 0.000381f, 0.000326f, + 0.000418f, 0.000439f, 0.000519f, 0.000519f, 0.000560f, 0.000574f, 0.000652f, 0.000678f, 0.000717f, 0.000756f, 0.000782f, 0.000820f, + 0.000893f, 0.000937f, 0.000991f, 0.001063f, 0.001112f, 0.001174f, 0.001284f, 0.001302f, 0.001408f, 0.001460f, 0.001586f, 0.001711f, + 0.001826f, 0.001959f, 0.002058f, 0.002207f, 0.002388f, 0.002565f, 0.002836f, 0.003046f, 0.003284f, 0.003567f, 0.004009f, 0.004463f, + 0.005001f, 0.005661f, 0.006451f, 0.007473f, 0.008751f, 0.010368f, 0.012611f, 0.015587f, 0.019730f, 0.025787f, 0.034729f, 0.047272f, + 0.064392f, 0.087097f, 0.550293f, 0.587891f, 0.596680f, 0.600586f, 0.602539f, 0.603516f, 0.000000f, 0.000057f, 0.000175f, 0.000210f, + 0.000221f, 0.000261f, 0.000224f, 0.000285f, 0.000296f, 0.000329f, 0.000374f, 0.000329f, 0.000344f, 0.000416f, 0.000421f, 0.000479f, + 0.000455f, 0.000530f, 0.000552f, 0.000598f, 0.000640f, 0.000670f, 0.000695f, 0.000740f, 0.000798f, 0.000806f, 0.000883f, 0.000908f, + 0.000983f, 0.001094f, 0.001083f, 0.001169f, 0.001242f, 0.001340f, 0.001440f, 0.001536f, 0.001601f, 0.001752f, 0.001893f, 0.002029f, + 0.002218f, 0.002424f, 0.002651f, 0.002934f, 0.003294f, 0.003681f, 0.004200f, 0.004833f, 0.005688f, 0.006863f, 0.008202f, 0.010178f, + 0.012955f, 0.016846f, 0.023163f, 0.032745f, 0.047150f, 0.067383f, 0.534180f, 0.574219f, 0.582031f, 0.584961f, 0.586914f, 0.589844f, + 0.000000f, 0.000105f, 0.000145f, 0.000101f, 0.000161f, 0.000163f, 0.000165f, 0.000193f, 0.000190f, 0.000202f, 0.000205f, 0.000260f, + 0.000251f, 0.000281f, 0.000305f, 0.000316f, 0.000323f, 0.000346f, 0.000364f, 0.000383f, 0.000413f, 0.000436f, 0.000461f, 0.000486f, + 0.000515f, 0.000564f, 0.000594f, 0.000616f, 0.000639f, 0.000677f, 0.000729f, 0.000748f, 0.000842f, 0.000861f, 0.000943f, 0.000970f, + 0.001054f, 0.001120f, 0.001219f, 0.001310f, 0.001398f, 0.001534f, 0.001709f, 0.001852f, 0.002096f, 0.002291f, 0.002594f, 0.002987f, + 0.003481f, 0.004128f, 0.004997f, 0.006218f, 0.007950f, 0.010445f, 0.014313f, 0.020874f, 0.032166f, 0.049866f, 0.517578f, 0.558105f, + 0.567383f, 0.570801f, 0.573730f, 0.574707f, 0.000000f, 0.000097f, 0.000089f, 0.000082f, 0.000092f, 0.000096f, 0.000092f, 0.000118f, + 0.000126f, 0.000130f, 0.000138f, 0.000138f, 0.000143f, 0.000163f, 0.000181f, 0.000187f, 0.000195f, 0.000228f, 0.000221f, 0.000261f, + 0.000243f, 0.000254f, 0.000274f, 0.000299f, 0.000334f, 0.000332f, 0.000345f, 0.000362f, 0.000394f, 0.000410f, 0.000433f, 0.000463f, + 0.000497f, 0.000510f, 0.000562f, 0.000594f, 0.000636f, 0.000670f, 0.000731f, 0.000777f, 0.000832f, 0.000927f, 0.000991f, 0.001101f, + 0.001210f, 0.001350f, 0.001513f, 0.001720f, 0.001999f, 0.002373f, 0.002815f, 0.003498f, 0.004478f, 0.006001f, 0.008347f, 0.012299f, + 0.019669f, 0.034210f, 0.501465f, 0.542969f, 0.552246f, 0.556641f, 0.559082f, 0.559570f, 0.000107f, 0.000087f, 0.000077f, 0.000070f, + 0.000065f, 0.000066f, 0.000059f, 0.000064f, 0.000065f, 0.000071f, 0.000070f, 0.000095f, 0.000081f, 0.000085f, 0.000110f, 0.000097f, + 0.000117f, 0.000126f, 0.000127f, 0.000133f, 0.000132f, 0.000141f, 0.000169f, 0.000173f, 0.000185f, 0.000183f, 0.000192f, 0.000215f, + 0.000216f, 0.000235f, 0.000236f, 0.000265f, 0.000278f, 0.000290f, 0.000313f, 0.000317f, 0.000347f, 0.000365f, 0.000400f, 0.000422f, + 0.000457f, 0.000494f, 0.000535f, 0.000586f, 0.000639f, 0.000700f, 0.000786f, 0.000888f, 0.001019f, 0.001207f, 0.001435f, 0.001746f, + 0.002258f, 0.003019f, 0.004299f, 0.006523f, 0.010612f, 0.020859f, 0.484619f, 0.527344f, 0.536621f, 0.541504f, 0.542969f, 0.544922f, + 0.000092f, 0.000070f, 0.000062f, 0.000056f, 0.000051f, 0.000048f, 0.000045f, 0.000044f, 0.000041f, 0.000039f, 0.000038f, 0.000037f, + 0.000047f, 0.000039f, 0.000041f, 0.000041f, 0.000058f, 0.000053f, 0.000062f, 0.000064f, 0.000068f, 0.000072f, 0.000076f, 0.000076f, + 0.000078f, 0.000092f, 0.000085f, 0.000101f, 0.000104f, 0.000110f, 0.000115f, 0.000118f, 0.000127f, 0.000133f, 0.000152f, 0.000150f, + 0.000163f, 0.000190f, 0.000190f, 0.000202f, 0.000213f, 0.000225f, 0.000249f, 0.000268f, 0.000296f, 0.000321f, 0.000354f, 0.000402f, + 0.000458f, 0.000520f, 0.000618f, 0.000744f, 0.000950f, 0.001263f, 0.001822f, 0.002865f, 0.005028f, 0.010544f, 0.468018f, 0.511230f, + 0.521484f, 0.524902f, 0.529297f, 0.529785f, 0.000067f, 0.000049f, 0.000041f, 0.000037f, 0.000034f, 0.000032f, 0.000031f, 0.000029f, + 0.000028f, 0.000027f, 0.000027f, 0.000026f, 0.000025f, 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000020f, 0.000023f, 0.000024f, + 0.000021f, 0.000022f, 0.000025f, 0.000029f, 0.000030f, 0.000034f, 0.000036f, 0.000034f, 0.000039f, 0.000038f, 0.000045f, 0.000045f, + 0.000048f, 0.000051f, 0.000053f, 0.000055f, 0.000063f, 0.000070f, 0.000073f, 0.000073f, 0.000080f, 0.000084f, 0.000089f, 0.000102f, + 0.000107f, 0.000115f, 0.000128f, 0.000145f, 0.000156f, 0.000178f, 0.000213f, 0.000253f, 0.000311f, 0.000400f, 0.000572f, 0.000916f, + 0.001751f, 0.004158f, 0.450439f, 0.496338f, 0.505859f, 0.510742f, 0.513184f, 0.514648f, 0.000016f, 0.000013f, 0.000011f, 0.000010f, + 0.000012f, 0.000012f, 0.000011f, 0.000012f, 0.000011f, 0.000012f, 0.000011f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, + 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, + 0.000008f, 0.000009f, 0.000009f, 0.000009f, 0.000009f, 0.000011f, 0.000012f, 0.000012f, 0.000015f, 0.000014f, 0.000014f, 0.000017f, + 0.000018f, 0.000020f, 0.000020f, 0.000022f, 0.000026f, 0.000027f, 0.000028f, 0.000027f, 0.000033f, 0.000036f, 0.000044f, 0.000051f, + 0.000057f, 0.000078f, 0.000103f, 0.000159f, 0.000315f, 0.000997f, 0.433350f, 0.479980f, 0.490234f, 0.495605f, 0.498291f, 0.499512f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, + 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000004f, 0.000007f, 0.000025f, 0.416016f, 0.464111f, + 0.474854f, 0.479248f, 0.481934f, 0.484375f, + }, + { + 0.023209f, 0.069336f, 0.113037f, 0.154663f, 0.193726f, 0.231812f, 0.267578f, 0.301758f, 0.333740f, 0.364258f, 0.393555f, 0.421631f, + 0.447510f, 0.473145f, 0.497070f, 0.520020f, 0.541992f, 0.562988f, 0.583008f, 0.602539f, 0.620605f, 0.638184f, 0.655762f, 0.671387f, + 0.687500f, 0.702637f, 0.716309f, 0.729980f, 0.744141f, 0.757812f, 0.769531f, 0.782227f, 0.793945f, 0.804688f, 0.815918f, 0.826172f, + 0.836426f, 0.846191f, 0.855957f, 0.865234f, 0.874023f, 0.882812f, 0.891113f, 0.898926f, 0.907227f, 0.915039f, 0.922852f, 0.929688f, + 0.937012f, 0.943848f, 0.950684f, 0.956543f, 0.963379f, 0.969238f, 0.976074f, 0.981445f, 0.986816f, 0.992676f, 0.991211f, 0.978516f, + 0.968750f, 0.960449f, 0.952637f, 0.945312f, 0.019730f, 0.059631f, 0.098206f, 0.135864f, 0.172119f, 0.206421f, 0.239624f, 0.272461f, + 0.304932f, 0.333984f, 0.362549f, 0.389648f, 0.416016f, 0.441406f, 0.466309f, 0.489502f, 0.511230f, 0.533203f, 0.554199f, 0.573242f, + 0.593262f, 0.611816f, 0.629395f, 0.645508f, 0.662598f, 0.678711f, 0.693359f, 0.708496f, 0.722168f, 0.735840f, 0.750000f, 0.762207f, + 0.773926f, 0.786133f, 0.796875f, 0.808594f, 0.818848f, 0.829590f, 0.839355f, 0.850098f, 0.859863f, 0.868652f, 0.877441f, 0.886230f, + 0.895020f, 0.903809f, 0.911133f, 0.918457f, 0.925781f, 0.933105f, 0.940430f, 0.946777f, 0.954590f, 0.960938f, 0.966797f, 0.973145f, + 0.979004f, 0.984863f, 0.987793f, 0.976074f, 0.966797f, 0.958496f, 0.951172f, 0.943848f, 0.017151f, 0.051636f, 0.085510f, 0.119202f, + 0.152466f, 0.184814f, 0.216187f, 0.246582f, 0.276855f, 0.305664f, 0.332764f, 0.360107f, 0.385986f, 0.411621f, 0.435791f, 0.459473f, + 0.481445f, 0.502441f, 0.524414f, 0.546387f, 0.565430f, 0.583496f, 0.602051f, 0.619629f, 0.636719f, 0.653320f, 0.669434f, 0.684082f, + 0.699707f, 0.713867f, 0.728027f, 0.741211f, 0.754883f, 0.767090f, 0.779297f, 0.791016f, 0.802734f, 0.813965f, 0.824219f, 0.833984f, + 0.843750f, 0.854492f, 0.863281f, 0.873535f, 0.882324f, 0.890137f, 0.898926f, 0.906738f, 0.915039f, 0.922852f, 0.930176f, 0.937012f, + 0.944336f, 0.951172f, 0.958008f, 0.964844f, 0.970703f, 0.977051f, 0.983887f, 0.972656f, 0.964355f, 0.956543f, 0.949219f, 0.942383f, + 0.014885f, 0.044678f, 0.075195f, 0.104919f, 0.135254f, 0.165649f, 0.194702f, 0.223633f, 0.251221f, 0.279053f, 0.305420f, 0.331543f, + 0.357422f, 0.382568f, 0.406982f, 0.430420f, 0.453369f, 0.475586f, 0.496582f, 0.517090f, 0.536133f, 0.556641f, 0.575684f, 0.592773f, + 0.611328f, 0.628418f, 0.643555f, 0.661621f, 0.676270f, 0.691406f, 0.705566f, 0.720215f, 0.733887f, 0.746582f, 0.759766f, 0.772949f, + 0.784668f, 0.795898f, 0.807129f, 0.818359f, 0.828125f, 0.838867f, 0.848633f, 0.858887f, 0.867676f, 0.877441f, 0.886230f, 0.894531f, + 0.903320f, 0.911621f, 0.919434f, 0.927734f, 0.934570f, 0.940918f, 0.948730f, 0.956543f, 0.962402f, 0.969238f, 0.979980f, 0.970215f, + 0.961914f, 0.954102f, 0.947266f, 0.940918f, 0.013046f, 0.038940f, 0.066162f, 0.093323f, 0.120544f, 0.147583f, 0.174683f, 0.201538f, + 0.228516f, 0.254639f, 0.280518f, 0.304932f, 0.330566f, 0.354492f, 0.379395f, 0.402100f, 0.424561f, 0.446533f, 0.467529f, 0.488525f, + 0.509277f, 0.529297f, 0.547852f, 0.566895f, 0.585449f, 0.602539f, 0.620605f, 0.636230f, 0.653809f, 0.667480f, 0.684570f, 0.698242f, + 0.712891f, 0.726562f, 0.739746f, 0.753418f, 0.765625f, 0.777344f, 0.789551f, 0.801270f, 0.812500f, 0.823730f, 0.833984f, 0.844238f, + 0.854004f, 0.863770f, 0.874023f, 0.882324f, 0.891113f, 0.899902f, 0.908203f, 0.916504f, 0.924805f, 0.932129f, 0.939453f, 0.947266f, + 0.954102f, 0.960938f, 0.976562f, 0.967285f, 0.958984f, 0.951660f, 0.944824f, 0.938965f, 0.011696f, 0.034698f, 0.058807f, 0.083130f, + 0.107727f, 0.132324f, 0.156982f, 0.182251f, 0.207153f, 0.232178f, 0.256836f, 0.280762f, 0.304688f, 0.328369f, 0.352295f, 0.375244f, + 0.397461f, 0.419434f, 0.440430f, 0.461914f, 0.482178f, 0.501953f, 0.522461f, 0.540527f, 0.559570f, 0.577148f, 0.595703f, 0.613281f, + 0.628418f, 0.644531f, 0.661621f, 0.676270f, 0.691406f, 0.705078f, 0.719727f, 0.733887f, 0.746094f, 0.759766f, 0.771973f, 0.784180f, + 0.795898f, 0.807617f, 0.818359f, 0.829102f, 0.839844f, 0.850098f, 0.859375f, 0.869629f, 0.878906f, 0.887695f, 0.896484f, 0.905273f, + 0.914062f, 0.921875f, 0.929688f, 0.937988f, 0.944824f, 0.952637f, 0.973145f, 0.963379f, 0.956055f, 0.949219f, 0.942871f, 0.937012f, + 0.010094f, 0.030975f, 0.052063f, 0.073975f, 0.096069f, 0.118713f, 0.141479f, 0.164551f, 0.187866f, 0.211182f, 0.234985f, 0.258057f, + 0.280518f, 0.303467f, 0.326172f, 0.348145f, 0.370117f, 0.392822f, 0.413574f, 0.434814f, 0.455322f, 0.476074f, 0.495361f, 0.515137f, + 0.533203f, 0.551758f, 0.569824f, 0.586426f, 0.604492f, 0.621582f, 0.637695f, 0.654297f, 0.668945f, 0.683594f, 0.699219f, 0.712402f, + 0.728516f, 0.741699f, 0.753906f, 0.767090f, 0.778320f, 0.790527f, 0.802246f, 0.813965f, 0.824219f, 0.835449f, 0.846680f, 0.855957f, + 0.865723f, 0.875488f, 0.884766f, 0.894043f, 0.902832f, 0.911133f, 0.919434f, 0.927734f, 0.935547f, 0.943359f, 0.968750f, 0.960449f, + 0.953125f, 0.946289f, 0.940430f, 0.934570f, 0.008797f, 0.027466f, 0.045959f, 0.066223f, 0.086304f, 0.106506f, 0.127441f, 0.149170f, + 0.170532f, 0.192261f, 0.213867f, 0.236206f, 0.258057f, 0.280273f, 0.301758f, 0.323486f, 0.344727f, 0.367188f, 0.388184f, 0.408447f, + 0.429443f, 0.450439f, 0.469727f, 0.489014f, 0.508301f, 0.526855f, 0.545410f, 0.562500f, 0.581055f, 0.597656f, 0.613770f, 0.630859f, + 0.647461f, 0.663574f, 0.677734f, 0.693359f, 0.707031f, 0.720703f, 0.735352f, 0.748047f, 0.760254f, 0.772461f, 0.785156f, 0.797363f, + 0.810059f, 0.819824f, 0.831543f, 0.842285f, 0.852051f, 0.862793f, 0.873047f, 0.882324f, 0.891113f, 0.899902f, 0.909180f, 0.917969f, + 0.925781f, 0.934082f, 0.964355f, 0.957031f, 0.949707f, 0.943359f, 0.937988f, 0.932129f, 0.007927f, 0.024414f, 0.041077f, 0.059204f, + 0.077148f, 0.095581f, 0.115479f, 0.134644f, 0.154785f, 0.175293f, 0.196045f, 0.216553f, 0.236694f, 0.258057f, 0.278809f, 0.300049f, + 0.321289f, 0.342529f, 0.363281f, 0.383545f, 0.403564f, 0.424072f, 0.444092f, 0.463135f, 0.483154f, 0.501953f, 0.519531f, 0.539062f, + 0.555664f, 0.574707f, 0.591309f, 0.608398f, 0.624512f, 0.640137f, 0.655762f, 0.671875f, 0.686523f, 0.701172f, 0.715820f, 0.729004f, + 0.742676f, 0.755859f, 0.769043f, 0.781738f, 0.792969f, 0.805176f, 0.816895f, 0.827637f, 0.838867f, 0.849121f, 0.859375f, 0.870117f, + 0.879395f, 0.889160f, 0.898926f, 0.906738f, 0.916504f, 0.924805f, 0.960938f, 0.953125f, 0.947266f, 0.940430f, 0.935547f, 0.929688f, + 0.007080f, 0.022247f, 0.037445f, 0.053070f, 0.069336f, 0.086975f, 0.103577f, 0.121948f, 0.140503f, 0.158936f, 0.178833f, 0.198242f, + 0.217651f, 0.237793f, 0.257812f, 0.278076f, 0.297607f, 0.318604f, 0.338623f, 0.358643f, 0.378662f, 0.399170f, 0.418213f, 0.438721f, + 0.457520f, 0.477051f, 0.495361f, 0.513672f, 0.531250f, 0.549316f, 0.567383f, 0.583984f, 0.601562f, 0.617676f, 0.634277f, 0.650391f, + 0.666016f, 0.680176f, 0.695801f, 0.710449f, 0.723633f, 0.737305f, 0.750977f, 0.764648f, 0.776367f, 0.789551f, 0.802246f, 0.813477f, + 0.824219f, 0.835938f, 0.846680f, 0.857422f, 0.867188f, 0.876953f, 0.887207f, 0.895996f, 0.905762f, 0.915527f, 0.955566f, 0.949707f, + 0.943359f, 0.937988f, 0.932129f, 0.927246f, 0.006363f, 0.019516f, 0.033691f, 0.047577f, 0.062469f, 0.078186f, 0.093933f, 0.110657f, + 0.127563f, 0.144653f, 0.162598f, 0.181152f, 0.199707f, 0.218384f, 0.237427f, 0.257324f, 0.276367f, 0.295166f, 0.315674f, 0.335205f, + 0.355225f, 0.374756f, 0.393799f, 0.413574f, 0.432617f, 0.451904f, 0.470459f, 0.489258f, 0.508301f, 0.525879f, 0.543945f, 0.560059f, + 0.578613f, 0.595703f, 0.612793f, 0.628418f, 0.644531f, 0.659668f, 0.675293f, 0.689941f, 0.704590f, 0.719238f, 0.732910f, 0.747070f, + 0.759766f, 0.773438f, 0.785156f, 0.797852f, 0.809570f, 0.821289f, 0.833008f, 0.843750f, 0.854980f, 0.865723f, 0.875977f, 0.886230f, + 0.895508f, 0.904785f, 0.951660f, 0.945801f, 0.939941f, 0.934570f, 0.929199f, 0.924805f, 0.005985f, 0.017776f, 0.030212f, 0.043030f, + 0.056488f, 0.070190f, 0.085205f, 0.100342f, 0.115723f, 0.132446f, 0.148438f, 0.165771f, 0.183228f, 0.200684f, 0.218994f, 0.237183f, + 0.255859f, 0.274170f, 0.292725f, 0.313477f, 0.331299f, 0.351318f, 0.369873f, 0.389160f, 0.408936f, 0.426758f, 0.446533f, 0.464844f, + 0.483154f, 0.501465f, 0.519531f, 0.537598f, 0.555664f, 0.572754f, 0.589844f, 0.605957f, 0.622070f, 0.639648f, 0.654297f, 0.670898f, + 0.685059f, 0.700195f, 0.714844f, 0.728516f, 0.742188f, 0.754883f, 0.769043f, 0.781738f, 0.795410f, 0.808105f, 0.818359f, 0.830566f, + 0.841797f, 0.853027f, 0.863770f, 0.874023f, 0.884766f, 0.893555f, 0.947266f, 0.942383f, 0.936523f, 0.930664f, 0.926270f, 0.921387f, + 0.005173f, 0.016083f, 0.027359f, 0.038849f, 0.051056f, 0.063843f, 0.077026f, 0.091064f, 0.105591f, 0.120422f, 0.135498f, 0.150879f, + 0.167480f, 0.184326f, 0.201172f, 0.218384f, 0.236084f, 0.254395f, 0.272949f, 0.291260f, 0.309570f, 0.328125f, 0.346680f, 0.365967f, + 0.384766f, 0.403320f, 0.422119f, 0.440918f, 0.458984f, 0.477783f, 0.496094f, 0.513672f, 0.531738f, 0.548828f, 0.566406f, 0.583984f, + 0.600098f, 0.617188f, 0.632812f, 0.649902f, 0.665527f, 0.681152f, 0.694824f, 0.709473f, 0.724121f, 0.738770f, 0.752441f, 0.765137f, + 0.778809f, 0.791992f, 0.803711f, 0.815918f, 0.828125f, 0.839844f, 0.851562f, 0.862793f, 0.873535f, 0.883789f, 0.941895f, 0.938477f, + 0.933105f, 0.927246f, 0.922363f, 0.918457f, 0.004791f, 0.014610f, 0.024475f, 0.035126f, 0.046478f, 0.057922f, 0.069885f, 0.083008f, + 0.096069f, 0.109253f, 0.123840f, 0.137939f, 0.153076f, 0.168701f, 0.185059f, 0.200928f, 0.218262f, 0.234985f, 0.252686f, 0.270264f, + 0.288086f, 0.306396f, 0.324951f, 0.343018f, 0.362305f, 0.379883f, 0.398926f, 0.417236f, 0.435547f, 0.454346f, 0.472656f, 0.491211f, + 0.508301f, 0.526855f, 0.543457f, 0.561523f, 0.578125f, 0.595215f, 0.612305f, 0.628418f, 0.644043f, 0.660645f, 0.675781f, 0.691406f, + 0.706055f, 0.720215f, 0.735840f, 0.749023f, 0.762695f, 0.776855f, 0.789551f, 0.800781f, 0.814941f, 0.826172f, 0.838867f, 0.851074f, + 0.862305f, 0.872070f, 0.937500f, 0.933594f, 0.929199f, 0.923828f, 0.919434f, 0.915527f, 0.004387f, 0.013268f, 0.022385f, 0.031860f, + 0.041962f, 0.052612f, 0.063171f, 0.075073f, 0.086792f, 0.099854f, 0.113037f, 0.125977f, 0.140381f, 0.154663f, 0.169678f, 0.184814f, + 0.200562f, 0.217773f, 0.234131f, 0.250732f, 0.268066f, 0.284912f, 0.303223f, 0.321289f, 0.339355f, 0.357666f, 0.375488f, 0.394043f, + 0.411865f, 0.430664f, 0.448730f, 0.467041f, 0.485352f, 0.503418f, 0.520508f, 0.539062f, 0.556152f, 0.573242f, 0.590820f, 0.606934f, + 0.624512f, 0.640625f, 0.655762f, 0.672363f, 0.687500f, 0.702148f, 0.718750f, 0.731934f, 0.746582f, 0.759766f, 0.772949f, 0.787109f, + 0.800781f, 0.813477f, 0.825195f, 0.838379f, 0.850098f, 0.861816f, 0.932617f, 0.929688f, 0.925293f, 0.919922f, 0.915527f, 0.912109f, + 0.003941f, 0.011986f, 0.020630f, 0.029144f, 0.038544f, 0.048035f, 0.058075f, 0.068542f, 0.079590f, 0.090942f, 0.102661f, 0.115295f, + 0.128296f, 0.141602f, 0.155518f, 0.170654f, 0.185425f, 0.200684f, 0.216309f, 0.231812f, 0.249146f, 0.265137f, 0.282471f, 0.299072f, + 0.317139f, 0.334717f, 0.352783f, 0.371338f, 0.388916f, 0.406982f, 0.425537f, 0.443848f, 0.461914f, 0.479980f, 0.498291f, 0.515625f, + 0.533203f, 0.550293f, 0.568359f, 0.585449f, 0.603027f, 0.618652f, 0.635742f, 0.652344f, 0.668457f, 0.684082f, 0.699219f, 0.713867f, + 0.729004f, 0.743652f, 0.757812f, 0.771484f, 0.785645f, 0.798828f, 0.812012f, 0.824219f, 0.836914f, 0.850098f, 0.927246f, 0.925293f, + 0.920410f, 0.916504f, 0.912598f, 0.908203f, 0.003790f, 0.011009f, 0.018829f, 0.026779f, 0.035339f, 0.043762f, 0.053223f, 0.062408f, + 0.072693f, 0.082947f, 0.093689f, 0.105469f, 0.117554f, 0.130005f, 0.142822f, 0.156494f, 0.170166f, 0.184448f, 0.198975f, 0.213745f, + 0.230469f, 0.246460f, 0.262939f, 0.279541f, 0.296143f, 0.313721f, 0.331299f, 0.348633f, 0.367188f, 0.384521f, 0.402344f, 0.420410f, + 0.438965f, 0.457275f, 0.475830f, 0.493164f, 0.510742f, 0.528809f, 0.546387f, 0.564453f, 0.581055f, 0.598145f, 0.615234f, 0.631836f, + 0.647461f, 0.665527f, 0.680664f, 0.696289f, 0.711914f, 0.728027f, 0.741211f, 0.756836f, 0.770508f, 0.783691f, 0.798340f, 0.811523f, + 0.824219f, 0.837402f, 0.921387f, 0.920410f, 0.916504f, 0.913086f, 0.908691f, 0.904785f, 0.003479f, 0.009949f, 0.016937f, 0.024445f, + 0.031708f, 0.039948f, 0.048218f, 0.056793f, 0.066223f, 0.075928f, 0.085632f, 0.096313f, 0.107178f, 0.118958f, 0.130493f, 0.143311f, + 0.156494f, 0.170044f, 0.183960f, 0.197876f, 0.213501f, 0.228027f, 0.244019f, 0.260010f, 0.276611f, 0.293213f, 0.309814f, 0.327393f, + 0.344482f, 0.363037f, 0.379883f, 0.398438f, 0.416504f, 0.434082f, 0.451904f, 0.470215f, 0.488525f, 0.505859f, 0.523926f, 0.541504f, + 0.559570f, 0.577637f, 0.594238f, 0.611328f, 0.628418f, 0.645020f, 0.661133f, 0.677246f, 0.693848f, 0.709961f, 0.725586f, 0.739746f, + 0.755371f, 0.769531f, 0.783203f, 0.797852f, 0.810547f, 0.824707f, 0.916016f, 0.915527f, 0.912109f, 0.908691f, 0.904785f, 0.900879f, + 0.003014f, 0.008842f, 0.015640f, 0.022018f, 0.028885f, 0.036163f, 0.044250f, 0.051819f, 0.059967f, 0.069031f, 0.078247f, 0.088135f, + 0.098267f, 0.108337f, 0.119751f, 0.131470f, 0.143433f, 0.156006f, 0.169189f, 0.183105f, 0.196655f, 0.211304f, 0.226196f, 0.241211f, + 0.257080f, 0.273438f, 0.289307f, 0.306396f, 0.323975f, 0.340576f, 0.358398f, 0.375732f, 0.393799f, 0.411133f, 0.429688f, 0.447998f, + 0.466064f, 0.483887f, 0.501465f, 0.519531f, 0.537598f, 0.555664f, 0.573242f, 0.590820f, 0.607910f, 0.625000f, 0.642578f, 0.658203f, + 0.675293f, 0.691406f, 0.707520f, 0.724121f, 0.738770f, 0.753418f, 0.769531f, 0.783203f, 0.797363f, 0.811523f, 0.910156f, 0.910645f, + 0.907715f, 0.904785f, 0.900879f, 0.896973f, 0.002861f, 0.008591f, 0.014000f, 0.020203f, 0.026962f, 0.033203f, 0.040161f, 0.047485f, + 0.055237f, 0.062988f, 0.071594f, 0.080750f, 0.089905f, 0.099854f, 0.109741f, 0.120056f, 0.131592f, 0.143311f, 0.155640f, 0.167969f, + 0.181763f, 0.195190f, 0.209229f, 0.223877f, 0.238647f, 0.254150f, 0.269531f, 0.285889f, 0.302979f, 0.319824f, 0.336426f, 0.354004f, + 0.372070f, 0.389893f, 0.406982f, 0.424805f, 0.443359f, 0.461182f, 0.479492f, 0.498047f, 0.515625f, 0.533691f, 0.551270f, 0.569336f, + 0.587402f, 0.604492f, 0.622070f, 0.639160f, 0.656738f, 0.673828f, 0.689941f, 0.705566f, 0.722168f, 0.737793f, 0.753418f, 0.768066f, + 0.783203f, 0.798340f, 0.904297f, 0.905762f, 0.902832f, 0.899414f, 0.895996f, 0.893066f, 0.002535f, 0.007812f, 0.013252f, 0.018738f, + 0.024384f, 0.030548f, 0.036774f, 0.043427f, 0.050476f, 0.057556f, 0.065491f, 0.073425f, 0.082458f, 0.091370f, 0.100525f, 0.110413f, + 0.120605f, 0.131592f, 0.142822f, 0.154663f, 0.166870f, 0.180176f, 0.193237f, 0.207031f, 0.221191f, 0.236084f, 0.250732f, 0.266602f, + 0.282959f, 0.299072f, 0.315430f, 0.332520f, 0.350342f, 0.367676f, 0.385010f, 0.403076f, 0.421631f, 0.439209f, 0.457520f, 0.475342f, + 0.494141f, 0.512695f, 0.530273f, 0.547852f, 0.565918f, 0.584473f, 0.602051f, 0.619629f, 0.637207f, 0.655273f, 0.671387f, 0.688965f, + 0.706055f, 0.721191f, 0.737305f, 0.752930f, 0.769531f, 0.784668f, 0.898438f, 0.900879f, 0.897949f, 0.894531f, 0.891602f, 0.888672f, + 0.002411f, 0.007103f, 0.012161f, 0.017105f, 0.022385f, 0.027985f, 0.033203f, 0.039581f, 0.045532f, 0.052521f, 0.059814f, 0.067261f, + 0.074768f, 0.083313f, 0.092041f, 0.101013f, 0.110291f, 0.120361f, 0.130615f, 0.141724f, 0.153076f, 0.165283f, 0.177612f, 0.190918f, + 0.204346f, 0.218506f, 0.233154f, 0.247559f, 0.263428f, 0.279053f, 0.295166f, 0.312256f, 0.328857f, 0.345947f, 0.363281f, 0.381348f, + 0.398926f, 0.417236f, 0.435547f, 0.453369f, 0.471191f, 0.489502f, 0.508301f, 0.525879f, 0.545410f, 0.563477f, 0.581055f, 0.600098f, + 0.617676f, 0.635254f, 0.653809f, 0.670410f, 0.687500f, 0.705078f, 0.720703f, 0.736816f, 0.753418f, 0.769531f, 0.892090f, 0.895020f, + 0.892578f, 0.889648f, 0.887207f, 0.884277f, 0.002344f, 0.006565f, 0.011322f, 0.015686f, 0.020630f, 0.025574f, 0.030807f, 0.035980f, + 0.042084f, 0.048279f, 0.054352f, 0.061432f, 0.068848f, 0.076172f, 0.083618f, 0.092590f, 0.101135f, 0.109619f, 0.120178f, 0.130249f, + 0.140991f, 0.151978f, 0.163696f, 0.175781f, 0.188721f, 0.202026f, 0.215820f, 0.230103f, 0.244873f, 0.259766f, 0.275635f, 0.291504f, + 0.307617f, 0.324219f, 0.342041f, 0.358887f, 0.376709f, 0.394775f, 0.412354f, 0.431152f, 0.448975f, 0.468018f, 0.486328f, 0.504883f, + 0.523438f, 0.541992f, 0.560547f, 0.579102f, 0.597656f, 0.615234f, 0.633789f, 0.651855f, 0.669434f, 0.687500f, 0.704590f, 0.721680f, + 0.738770f, 0.755859f, 0.886719f, 0.889648f, 0.887695f, 0.884766f, 0.882812f, 0.879883f, 0.002003f, 0.006268f, 0.009987f, 0.014198f, + 0.018875f, 0.023605f, 0.028259f, 0.033203f, 0.038513f, 0.044495f, 0.049866f, 0.056152f, 0.062500f, 0.069458f, 0.076660f, 0.084473f, + 0.092163f, 0.100586f, 0.109741f, 0.119324f, 0.128662f, 0.139526f, 0.150146f, 0.161499f, 0.173706f, 0.185791f, 0.199341f, 0.212891f, + 0.227051f, 0.241455f, 0.256592f, 0.271729f, 0.288330f, 0.304199f, 0.321045f, 0.337891f, 0.355469f, 0.373291f, 0.391113f, 0.408936f, + 0.426758f, 0.446289f, 0.464600f, 0.483643f, 0.500977f, 0.520996f, 0.539551f, 0.558594f, 0.577148f, 0.595703f, 0.614746f, 0.632324f, + 0.650879f, 0.669434f, 0.687012f, 0.704590f, 0.722656f, 0.740234f, 0.880371f, 0.883301f, 0.881836f, 0.879883f, 0.877441f, 0.875000f, + 0.001739f, 0.005779f, 0.009598f, 0.013245f, 0.017334f, 0.021637f, 0.025955f, 0.030121f, 0.035217f, 0.040131f, 0.045990f, 0.051453f, + 0.056915f, 0.063354f, 0.070007f, 0.076965f, 0.084351f, 0.091980f, 0.100281f, 0.108826f, 0.117981f, 0.127441f, 0.137939f, 0.148315f, + 0.160034f, 0.171753f, 0.183594f, 0.196167f, 0.209961f, 0.223511f, 0.238037f, 0.252930f, 0.268066f, 0.284180f, 0.300537f, 0.317139f, + 0.333740f, 0.351074f, 0.368896f, 0.386719f, 0.405273f, 0.423584f, 0.442871f, 0.460938f, 0.479736f, 0.499512f, 0.517578f, 0.537109f, + 0.555664f, 0.575195f, 0.594238f, 0.613770f, 0.632324f, 0.650879f, 0.669922f, 0.687988f, 0.706055f, 0.724121f, 0.873047f, 0.876953f, + 0.875488f, 0.874023f, 0.872559f, 0.869141f, 0.001648f, 0.005039f, 0.008675f, 0.012161f, 0.015823f, 0.019760f, 0.023865f, 0.028015f, + 0.032318f, 0.036865f, 0.041504f, 0.046906f, 0.051758f, 0.057922f, 0.064087f, 0.070435f, 0.077209f, 0.084290f, 0.091736f, 0.099243f, + 0.108215f, 0.117004f, 0.126343f, 0.135620f, 0.146484f, 0.157349f, 0.168823f, 0.180908f, 0.193848f, 0.206909f, 0.220459f, 0.234619f, + 0.249634f, 0.264404f, 0.280273f, 0.296631f, 0.313232f, 0.329834f, 0.347412f, 0.365479f, 0.383545f, 0.401855f, 0.420166f, 0.438721f, + 0.458252f, 0.477783f, 0.496826f, 0.516602f, 0.535156f, 0.554199f, 0.574219f, 0.593750f, 0.612305f, 0.631836f, 0.651367f, 0.670410f, + 0.689453f, 0.708984f, 0.865234f, 0.872070f, 0.870605f, 0.868652f, 0.866699f, 0.863770f, 0.001492f, 0.004704f, 0.007973f, 0.011124f, + 0.014603f, 0.017792f, 0.021652f, 0.025314f, 0.029526f, 0.033722f, 0.038147f, 0.042694f, 0.047668f, 0.052673f, 0.057983f, 0.064209f, + 0.070068f, 0.076233f, 0.083313f, 0.090942f, 0.098572f, 0.106750f, 0.115295f, 0.124512f, 0.134277f, 0.144287f, 0.154663f, 0.166504f, + 0.178345f, 0.190063f, 0.203247f, 0.217041f, 0.231079f, 0.245850f, 0.260986f, 0.276611f, 0.293213f, 0.309570f, 0.326172f, 0.343994f, + 0.361816f, 0.379395f, 0.397949f, 0.417480f, 0.436523f, 0.455322f, 0.474854f, 0.493896f, 0.514160f, 0.533691f, 0.553711f, 0.573730f, + 0.593262f, 0.612793f, 0.632812f, 0.651855f, 0.672363f, 0.690918f, 0.857910f, 0.865723f, 0.864746f, 0.863281f, 0.860352f, 0.858887f, + 0.001657f, 0.004684f, 0.007290f, 0.010201f, 0.013657f, 0.016541f, 0.019989f, 0.023636f, 0.026932f, 0.030548f, 0.034576f, 0.039154f, + 0.043793f, 0.048126f, 0.053162f, 0.058319f, 0.063721f, 0.069885f, 0.076355f, 0.082947f, 0.089844f, 0.097046f, 0.105286f, 0.113281f, + 0.122559f, 0.131348f, 0.141357f, 0.152100f, 0.163330f, 0.175415f, 0.187256f, 0.199951f, 0.213501f, 0.227051f, 0.241943f, 0.257324f, + 0.273193f, 0.288818f, 0.305420f, 0.322754f, 0.340576f, 0.358643f, 0.375732f, 0.394775f, 0.414307f, 0.433105f, 0.453613f, 0.472168f, + 0.492188f, 0.512695f, 0.532715f, 0.552246f, 0.573242f, 0.593262f, 0.613770f, 0.632812f, 0.654785f, 0.673828f, 0.851074f, 0.859375f, + 0.858398f, 0.856934f, 0.855469f, 0.853027f, 0.001457f, 0.003944f, 0.006870f, 0.009392f, 0.012543f, 0.015190f, 0.018417f, 0.021576f, + 0.024811f, 0.028122f, 0.031708f, 0.035278f, 0.039398f, 0.043793f, 0.048218f, 0.052887f, 0.058044f, 0.063477f, 0.069397f, 0.075256f, + 0.081360f, 0.088318f, 0.095398f, 0.103210f, 0.111084f, 0.120361f, 0.129150f, 0.139038f, 0.149292f, 0.160645f, 0.172241f, 0.183716f, + 0.196533f, 0.209595f, 0.224121f, 0.238647f, 0.253174f, 0.268799f, 0.286133f, 0.302490f, 0.319092f, 0.337158f, 0.355225f, 0.373535f, + 0.392090f, 0.411133f, 0.430908f, 0.450928f, 0.470947f, 0.490967f, 0.511719f, 0.531250f, 0.551758f, 0.573730f, 0.594238f, 0.614746f, + 0.636230f, 0.656738f, 0.842773f, 0.852051f, 0.851562f, 0.851074f, 0.848633f, 0.846680f, 0.001404f, 0.003891f, 0.006233f, 0.008751f, + 0.011353f, 0.014175f, 0.017075f, 0.019592f, 0.022842f, 0.025772f, 0.028839f, 0.032410f, 0.036011f, 0.039764f, 0.043671f, 0.048126f, + 0.052704f, 0.057373f, 0.062561f, 0.067688f, 0.074158f, 0.080200f, 0.086853f, 0.093445f, 0.101379f, 0.109192f, 0.117432f, 0.126709f, + 0.136353f, 0.146484f, 0.157227f, 0.168823f, 0.180542f, 0.193115f, 0.206299f, 0.219727f, 0.234375f, 0.249756f, 0.265869f, 0.281738f, + 0.298096f, 0.315674f, 0.333252f, 0.352051f, 0.370850f, 0.389160f, 0.409180f, 0.428955f, 0.448730f, 0.469971f, 0.489502f, 0.510742f, + 0.531738f, 0.552246f, 0.574707f, 0.595215f, 0.617676f, 0.639160f, 0.835449f, 0.845215f, 0.845215f, 0.844238f, 0.843262f, 0.840332f, + 0.001275f, 0.003536f, 0.005600f, 0.007881f, 0.010628f, 0.012878f, 0.015610f, 0.018097f, 0.020996f, 0.023376f, 0.026443f, 0.029556f, + 0.032867f, 0.036163f, 0.039581f, 0.043915f, 0.047943f, 0.052216f, 0.056763f, 0.061981f, 0.067322f, 0.072449f, 0.078796f, 0.084717f, + 0.091919f, 0.098999f, 0.106995f, 0.115417f, 0.124084f, 0.133667f, 0.143433f, 0.154297f, 0.165161f, 0.177124f, 0.189697f, 0.202759f, + 0.216309f, 0.230713f, 0.245728f, 0.261719f, 0.278320f, 0.295410f, 0.312256f, 0.330566f, 0.349365f, 0.367676f, 0.386719f, 0.406494f, + 0.427246f, 0.447266f, 0.468506f, 0.489746f, 0.510742f, 0.532227f, 0.553711f, 0.575684f, 0.597656f, 0.619141f, 0.826172f, 0.837402f, + 0.837891f, 0.837402f, 0.835449f, 0.833984f, 0.001134f, 0.003105f, 0.005337f, 0.007462f, 0.009628f, 0.011833f, 0.014137f, 0.016113f, + 0.018875f, 0.021484f, 0.024063f, 0.026581f, 0.029709f, 0.032623f, 0.036194f, 0.039703f, 0.043335f, 0.047058f, 0.051422f, 0.055908f, + 0.060608f, 0.065491f, 0.071167f, 0.076843f, 0.083313f, 0.089661f, 0.097168f, 0.104492f, 0.112122f, 0.121155f, 0.130615f, 0.140137f, + 0.150757f, 0.161499f, 0.173462f, 0.185547f, 0.199341f, 0.212524f, 0.227051f, 0.242310f, 0.258057f, 0.274414f, 0.291016f, 0.309082f, + 0.327148f, 0.345459f, 0.364990f, 0.384521f, 0.404297f, 0.425781f, 0.445801f, 0.467285f, 0.489258f, 0.510254f, 0.533203f, 0.555664f, + 0.578125f, 0.601074f, 0.817871f, 0.830078f, 0.831055f, 0.830078f, 0.829102f, 0.828125f, 0.001101f, 0.003019f, 0.004818f, 0.006725f, + 0.008781f, 0.010864f, 0.013069f, 0.014801f, 0.017151f, 0.019531f, 0.021973f, 0.024429f, 0.026917f, 0.030121f, 0.033112f, 0.036041f, + 0.039337f, 0.042542f, 0.046509f, 0.050537f, 0.054596f, 0.058990f, 0.064209f, 0.069519f, 0.075134f, 0.080994f, 0.087158f, 0.094177f, + 0.102051f, 0.109741f, 0.117981f, 0.127319f, 0.136963f, 0.147095f, 0.158081f, 0.169434f, 0.182251f, 0.195557f, 0.208984f, 0.223267f, + 0.238281f, 0.254639f, 0.270996f, 0.288330f, 0.305908f, 0.324219f, 0.343018f, 0.362549f, 0.382324f, 0.402832f, 0.424805f, 0.445312f, + 0.467529f, 0.489258f, 0.511230f, 0.535645f, 0.558594f, 0.582031f, 0.809082f, 0.822266f, 0.824219f, 0.823242f, 0.821777f, 0.820801f, + 0.000987f, 0.002644f, 0.004562f, 0.006344f, 0.008133f, 0.009918f, 0.011696f, 0.013527f, 0.015572f, 0.017746f, 0.019714f, 0.021942f, + 0.024155f, 0.027069f, 0.029678f, 0.032288f, 0.035156f, 0.038574f, 0.041779f, 0.045319f, 0.049225f, 0.053284f, 0.057678f, 0.062225f, + 0.067505f, 0.072571f, 0.078613f, 0.084961f, 0.092041f, 0.098938f, 0.106506f, 0.115112f, 0.123779f, 0.133667f, 0.143311f, 0.154541f, + 0.165894f, 0.178345f, 0.191406f, 0.205200f, 0.219238f, 0.234985f, 0.250977f, 0.267578f, 0.284912f, 0.302734f, 0.321289f, 0.340332f, + 0.360352f, 0.380615f, 0.401611f, 0.423340f, 0.445312f, 0.467529f, 0.490967f, 0.514160f, 0.537598f, 0.561035f, 0.800293f, 0.814453f, + 0.815918f, 0.815918f, 0.814941f, 0.813965f, 0.000932f, 0.002567f, 0.004009f, 0.005722f, 0.007538f, 0.008812f, 0.010864f, 0.012413f, + 0.014290f, 0.015991f, 0.018051f, 0.019836f, 0.022247f, 0.024506f, 0.026520f, 0.029175f, 0.031769f, 0.034332f, 0.037689f, 0.040466f, + 0.043945f, 0.047607f, 0.051605f, 0.055817f, 0.060486f, 0.065125f, 0.070557f, 0.076111f, 0.081909f, 0.088806f, 0.095886f, 0.103210f, + 0.111755f, 0.120422f, 0.130249f, 0.140137f, 0.150513f, 0.162109f, 0.174561f, 0.187256f, 0.200928f, 0.215698f, 0.231323f, 0.246582f, + 0.264160f, 0.281982f, 0.299561f, 0.319092f, 0.338623f, 0.358643f, 0.379883f, 0.400879f, 0.423096f, 0.445557f, 0.468750f, 0.492188f, + 0.516113f, 0.541504f, 0.791016f, 0.805664f, 0.808105f, 0.808594f, 0.807129f, 0.806641f, 0.000871f, 0.002337f, 0.003727f, 0.005474f, + 0.006641f, 0.008377f, 0.009567f, 0.011154f, 0.012848f, 0.014610f, 0.016235f, 0.017960f, 0.019958f, 0.021729f, 0.023926f, 0.026154f, + 0.028351f, 0.030975f, 0.033722f, 0.036407f, 0.039459f, 0.042694f, 0.046082f, 0.049896f, 0.053833f, 0.058167f, 0.062744f, 0.067932f, + 0.073608f, 0.079468f, 0.085632f, 0.092651f, 0.100098f, 0.108521f, 0.116699f, 0.126099f, 0.136108f, 0.146606f, 0.157959f, 0.170410f, + 0.183594f, 0.197510f, 0.212280f, 0.227295f, 0.243652f, 0.260986f, 0.278564f, 0.297607f, 0.316406f, 0.336426f, 0.357178f, 0.378662f, + 0.400146f, 0.422852f, 0.446045f, 0.470215f, 0.494873f, 0.520020f, 0.781250f, 0.796875f, 0.800293f, 0.800781f, 0.799805f, 0.799316f, + 0.000782f, 0.002131f, 0.003649f, 0.004715f, 0.006054f, 0.007458f, 0.008759f, 0.010269f, 0.011711f, 0.012970f, 0.014664f, 0.016327f, + 0.017914f, 0.019699f, 0.021423f, 0.023499f, 0.025391f, 0.027374f, 0.029999f, 0.032501f, 0.035156f, 0.037872f, 0.040710f, 0.044403f, + 0.047791f, 0.051880f, 0.055969f, 0.060364f, 0.065247f, 0.070496f, 0.076172f, 0.082825f, 0.089294f, 0.096497f, 0.104431f, 0.112854f, + 0.122375f, 0.132202f, 0.142700f, 0.153931f, 0.166260f, 0.179565f, 0.193481f, 0.208008f, 0.223877f, 0.240479f, 0.257568f, 0.275879f, + 0.294922f, 0.314453f, 0.334961f, 0.355957f, 0.377686f, 0.400391f, 0.423828f, 0.448730f, 0.472900f, 0.498535f, 0.771484f, 0.789062f, + 0.791504f, 0.792480f, 0.791016f, 0.791016f, 0.000742f, 0.001822f, 0.003183f, 0.004444f, 0.005600f, 0.006550f, 0.008087f, 0.009247f, + 0.010559f, 0.011650f, 0.013184f, 0.014565f, 0.016083f, 0.017548f, 0.019119f, 0.020737f, 0.022644f, 0.024597f, 0.026627f, 0.028809f, + 0.031281f, 0.033539f, 0.036469f, 0.039429f, 0.042480f, 0.045654f, 0.049561f, 0.053406f, 0.057739f, 0.062469f, 0.067749f, 0.073364f, + 0.079773f, 0.086121f, 0.093262f, 0.100647f, 0.109253f, 0.118042f, 0.128174f, 0.138550f, 0.150024f, 0.162231f, 0.175171f, 0.189087f, + 0.204468f, 0.220215f, 0.236938f, 0.254639f, 0.273438f, 0.292236f, 0.312012f, 0.333252f, 0.355957f, 0.377686f, 0.401367f, 0.425781f, + 0.451416f, 0.476318f, 0.761230f, 0.779785f, 0.782227f, 0.782715f, 0.782715f, 0.782715f, 0.000632f, 0.001970f, 0.003042f, 0.004025f, + 0.005173f, 0.006435f, 0.007343f, 0.008522f, 0.009369f, 0.010475f, 0.011726f, 0.012962f, 0.014145f, 0.015411f, 0.016922f, 0.018478f, + 0.020111f, 0.021835f, 0.023682f, 0.025253f, 0.027466f, 0.029678f, 0.032196f, 0.034607f, 0.037415f, 0.040497f, 0.043610f, 0.047089f, + 0.051178f, 0.055573f, 0.059845f, 0.064758f, 0.070068f, 0.076111f, 0.082275f, 0.089417f, 0.096863f, 0.105286f, 0.114441f, 0.123535f, + 0.134399f, 0.145508f, 0.157959f, 0.171387f, 0.185425f, 0.200806f, 0.216919f, 0.233521f, 0.251953f, 0.270508f, 0.290527f, 0.310791f, + 0.332275f, 0.355469f, 0.378418f, 0.403564f, 0.428223f, 0.455322f, 0.750977f, 0.770996f, 0.774414f, 0.774414f, 0.774902f, 0.773926f, + 0.000517f, 0.001554f, 0.002741f, 0.003695f, 0.004669f, 0.005417f, 0.006466f, 0.007545f, 0.008453f, 0.009499f, 0.010468f, 0.011490f, + 0.012718f, 0.013985f, 0.014977f, 0.016235f, 0.017868f, 0.019211f, 0.020630f, 0.022263f, 0.024078f, 0.026291f, 0.028275f, 0.030380f, + 0.032928f, 0.035675f, 0.038513f, 0.041656f, 0.044769f, 0.048523f, 0.052216f, 0.057007f, 0.061493f, 0.066711f, 0.072510f, 0.078735f, + 0.085327f, 0.093201f, 0.101135f, 0.109619f, 0.119690f, 0.130371f, 0.141602f, 0.154053f, 0.167480f, 0.181396f, 0.197021f, 0.213623f, + 0.230835f, 0.248901f, 0.268066f, 0.289062f, 0.310303f, 0.332520f, 0.355225f, 0.379639f, 0.405273f, 0.432373f, 0.740234f, 0.760742f, + 0.763672f, 0.765625f, 0.765625f, 0.765625f, 0.000588f, 0.001405f, 0.002306f, 0.003370f, 0.004375f, 0.005116f, 0.005817f, 0.006630f, + 0.007797f, 0.008507f, 0.009216f, 0.010254f, 0.011246f, 0.012154f, 0.013191f, 0.014366f, 0.015503f, 0.016785f, 0.018127f, 0.019562f, + 0.021072f, 0.022919f, 0.024643f, 0.026749f, 0.028564f, 0.031006f, 0.033203f, 0.036072f, 0.039032f, 0.042114f, 0.045654f, 0.049561f, + 0.053650f, 0.058380f, 0.063049f, 0.068848f, 0.075256f, 0.081543f, 0.088562f, 0.096924f, 0.105652f, 0.115173f, 0.125977f, 0.137207f, + 0.149902f, 0.163208f, 0.177979f, 0.193726f, 0.210205f, 0.228027f, 0.247070f, 0.266602f, 0.287842f, 0.309326f, 0.333008f, 0.356934f, + 0.382568f, 0.408691f, 0.729004f, 0.751953f, 0.755371f, 0.756348f, 0.757324f, 0.756348f, 0.000431f, 0.001562f, 0.002253f, 0.003088f, + 0.003944f, 0.004536f, 0.005066f, 0.006020f, 0.006840f, 0.007542f, 0.008347f, 0.008949f, 0.009827f, 0.010719f, 0.011696f, 0.012756f, + 0.013649f, 0.014679f, 0.015808f, 0.017288f, 0.018356f, 0.019913f, 0.021332f, 0.023148f, 0.024719f, 0.026840f, 0.029007f, 0.031250f, + 0.033661f, 0.036469f, 0.039490f, 0.042969f, 0.046326f, 0.050293f, 0.054901f, 0.059845f, 0.064941f, 0.071289f, 0.077454f, 0.084656f, + 0.092529f, 0.101562f, 0.111145f, 0.121460f, 0.132935f, 0.145386f, 0.159302f, 0.174438f, 0.190186f, 0.206909f, 0.225098f, 0.244751f, + 0.265381f, 0.287109f, 0.310059f, 0.333984f, 0.359131f, 0.386230f, 0.716797f, 0.740723f, 0.744629f, 0.746582f, 0.747070f, 0.747070f, + 0.000576f, 0.001266f, 0.002028f, 0.002766f, 0.003317f, 0.004051f, 0.004742f, 0.005459f, 0.006054f, 0.006641f, 0.007240f, 0.007919f, + 0.008644f, 0.009300f, 0.010170f, 0.010925f, 0.011795f, 0.012733f, 0.013855f, 0.014885f, 0.015900f, 0.017212f, 0.018326f, 0.019684f, + 0.021469f, 0.023178f, 0.024734f, 0.026794f, 0.028946f, 0.031204f, 0.033844f, 0.036682f, 0.039948f, 0.043335f, 0.047150f, 0.051422f, + 0.055969f, 0.061066f, 0.067139f, 0.073242f, 0.080444f, 0.088440f, 0.096985f, 0.106445f, 0.116943f, 0.128906f, 0.141479f, 0.154907f, + 0.170410f, 0.186523f, 0.204102f, 0.222900f, 0.243774f, 0.264160f, 0.286865f, 0.310791f, 0.336182f, 0.362793f, 0.705078f, 0.730469f, + 0.735352f, 0.736816f, 0.737793f, 0.736816f, 0.000307f, 0.001126f, 0.001758f, 0.002436f, 0.002911f, 0.003540f, 0.004047f, 0.004711f, + 0.005245f, 0.005749f, 0.006302f, 0.006844f, 0.007355f, 0.008095f, 0.008835f, 0.009438f, 0.010139f, 0.010941f, 0.011963f, 0.012878f, + 0.013519f, 0.014847f, 0.015945f, 0.017029f, 0.018250f, 0.019669f, 0.021362f, 0.022675f, 0.024750f, 0.026657f, 0.028854f, 0.031219f, + 0.033844f, 0.036804f, 0.040222f, 0.043793f, 0.047791f, 0.052185f, 0.057251f, 0.062866f, 0.069275f, 0.075867f, 0.083923f, 0.092407f, + 0.102295f, 0.112366f, 0.124207f, 0.137085f, 0.151489f, 0.167114f, 0.183838f, 0.202148f, 0.221558f, 0.242065f, 0.263916f, 0.287842f, + 0.312256f, 0.339111f, 0.693848f, 0.719727f, 0.724609f, 0.726074f, 0.727539f, 0.727051f, 0.000428f, 0.000939f, 0.001581f, 0.002033f, + 0.002665f, 0.003222f, 0.003660f, 0.004059f, 0.004475f, 0.004997f, 0.005554f, 0.006031f, 0.006371f, 0.007080f, 0.007511f, 0.008263f, + 0.008820f, 0.009552f, 0.010124f, 0.010948f, 0.011665f, 0.012550f, 0.013397f, 0.014526f, 0.015388f, 0.016754f, 0.017960f, 0.019257f, + 0.020844f, 0.022583f, 0.024246f, 0.026642f, 0.028656f, 0.031128f, 0.033783f, 0.036865f, 0.040253f, 0.044312f, 0.048523f, 0.053314f, + 0.058655f, 0.064880f, 0.071594f, 0.079102f, 0.087891f, 0.097107f, 0.108276f, 0.119751f, 0.133179f, 0.148071f, 0.163818f, 0.180908f, + 0.199951f, 0.219849f, 0.241699f, 0.264160f, 0.288818f, 0.315918f, 0.680176f, 0.708496f, 0.713867f, 0.716309f, 0.716797f, 0.717285f, + 0.000467f, 0.001054f, 0.001476f, 0.001825f, 0.002386f, 0.002644f, 0.003218f, 0.003553f, 0.003866f, 0.004433f, 0.004700f, 0.004948f, + 0.005505f, 0.006023f, 0.006405f, 0.006920f, 0.007484f, 0.008057f, 0.008598f, 0.009178f, 0.009857f, 0.010551f, 0.011169f, 0.012199f, + 0.013092f, 0.014084f, 0.015091f, 0.016205f, 0.017303f, 0.018845f, 0.020538f, 0.021957f, 0.023773f, 0.025833f, 0.028152f, 0.030716f, + 0.033661f, 0.036896f, 0.040405f, 0.044708f, 0.049286f, 0.054321f, 0.060333f, 0.067322f, 0.074890f, 0.083435f, 0.092651f, 0.103516f, + 0.115784f, 0.129028f, 0.144287f, 0.160278f, 0.178345f, 0.197632f, 0.218994f, 0.241089f, 0.265869f, 0.292725f, 0.667969f, 0.697266f, + 0.702637f, 0.704590f, 0.706055f, 0.707031f, 0.000348f, 0.000841f, 0.001292f, 0.001580f, 0.001961f, 0.002508f, 0.002630f, 0.002993f, + 0.003458f, 0.003738f, 0.003952f, 0.004425f, 0.004639f, 0.005070f, 0.005547f, 0.005840f, 0.006462f, 0.006844f, 0.007214f, 0.007698f, + 0.008339f, 0.008980f, 0.009560f, 0.010094f, 0.010941f, 0.011711f, 0.012550f, 0.013565f, 0.014404f, 0.015579f, 0.016754f, 0.018082f, + 0.019592f, 0.021439f, 0.023209f, 0.025375f, 0.027863f, 0.030411f, 0.033478f, 0.037018f, 0.040680f, 0.045105f, 0.050476f, 0.056183f, + 0.062805f, 0.070251f, 0.078613f, 0.088196f, 0.099060f, 0.111450f, 0.125122f, 0.140869f, 0.158203f, 0.176880f, 0.197266f, 0.218506f, + 0.242798f, 0.268555f, 0.655273f, 0.686035f, 0.691406f, 0.694336f, 0.695312f, 0.695801f, 0.000170f, 0.000976f, 0.001161f, 0.001441f, + 0.001846f, 0.002144f, 0.002367f, 0.002632f, 0.002892f, 0.003178f, 0.003435f, 0.003618f, 0.004021f, 0.004292f, 0.004562f, 0.005028f, + 0.005405f, 0.005623f, 0.006069f, 0.006577f, 0.006973f, 0.007431f, 0.007904f, 0.008484f, 0.009018f, 0.009659f, 0.010559f, 0.010994f, + 0.012009f, 0.012840f, 0.013901f, 0.014915f, 0.016129f, 0.017502f, 0.019089f, 0.020676f, 0.022568f, 0.024673f, 0.027252f, 0.029984f, + 0.033234f, 0.037079f, 0.041016f, 0.045868f, 0.051758f, 0.058014f, 0.065613f, 0.073853f, 0.083801f, 0.094727f, 0.107483f, 0.121826f, + 0.137573f, 0.156006f, 0.175049f, 0.196167f, 0.219482f, 0.245850f, 0.641113f, 0.673340f, 0.679688f, 0.681641f, 0.683594f, 0.684082f, + 0.000293f, 0.000601f, 0.001049f, 0.001358f, 0.001532f, 0.001719f, 0.001882f, 0.002298f, 0.002317f, 0.002628f, 0.002750f, 0.003143f, + 0.003363f, 0.003559f, 0.003866f, 0.004204f, 0.004383f, 0.004753f, 0.005028f, 0.005348f, 0.005863f, 0.006176f, 0.006569f, 0.006954f, + 0.007401f, 0.008057f, 0.008537f, 0.009178f, 0.009735f, 0.010521f, 0.011208f, 0.011978f, 0.013130f, 0.014099f, 0.015289f, 0.016739f, + 0.018219f, 0.019821f, 0.021713f, 0.024200f, 0.026749f, 0.029785f, 0.033386f, 0.036987f, 0.041840f, 0.047089f, 0.053253f, 0.060760f, + 0.069214f, 0.079224f, 0.090515f, 0.103638f, 0.118652f, 0.135376f, 0.154175f, 0.174561f, 0.196777f, 0.222534f, 0.628906f, 0.660645f, + 0.668457f, 0.670410f, 0.672852f, 0.673340f, 0.000258f, 0.000656f, 0.000811f, 0.001049f, 0.001288f, 0.001462f, 0.001599f, 0.001740f, + 0.002012f, 0.002171f, 0.002367f, 0.002535f, 0.002705f, 0.002880f, 0.003115f, 0.003429f, 0.003666f, 0.003897f, 0.004116f, 0.004398f, + 0.004635f, 0.005066f, 0.005341f, 0.005779f, 0.006042f, 0.006454f, 0.006954f, 0.007450f, 0.007835f, 0.008400f, 0.009132f, 0.009819f, + 0.010536f, 0.011307f, 0.012245f, 0.013229f, 0.014580f, 0.015900f, 0.017303f, 0.019119f, 0.021103f, 0.023468f, 0.026123f, 0.029495f, + 0.033112f, 0.037628f, 0.042938f, 0.048859f, 0.056152f, 0.064941f, 0.074829f, 0.086548f, 0.100281f, 0.115967f, 0.133545f, 0.153198f, + 0.175171f, 0.199341f, 0.613770f, 0.648926f, 0.655273f, 0.658691f, 0.660645f, 0.662598f, 0.000176f, 0.000474f, 0.000602f, 0.000854f, + 0.001030f, 0.001240f, 0.001349f, 0.001505f, 0.001580f, 0.001738f, 0.001957f, 0.002068f, 0.002230f, 0.002420f, 0.002556f, 0.002705f, + 0.002998f, 0.003178f, 0.003345f, 0.003567f, 0.003811f, 0.004105f, 0.004284f, 0.004593f, 0.004848f, 0.005173f, 0.005527f, 0.005939f, + 0.006306f, 0.006817f, 0.007366f, 0.007729f, 0.008339f, 0.008995f, 0.009644f, 0.010551f, 0.011360f, 0.012344f, 0.013710f, 0.015030f, + 0.016510f, 0.018143f, 0.020279f, 0.022751f, 0.025650f, 0.029144f, 0.033508f, 0.038452f, 0.044556f, 0.052032f, 0.060364f, 0.070923f, + 0.082642f, 0.097290f, 0.113525f, 0.132446f, 0.153442f, 0.176880f, 0.600586f, 0.636719f, 0.644531f, 0.647461f, 0.648926f, 0.649414f, + 0.000121f, 0.000426f, 0.000509f, 0.000778f, 0.000931f, 0.000992f, 0.001135f, 0.001303f, 0.001359f, 0.001410f, 0.001519f, 0.001722f, + 0.001751f, 0.001951f, 0.002060f, 0.002218f, 0.002287f, 0.002487f, 0.002670f, 0.002848f, 0.003061f, 0.003233f, 0.003452f, 0.003664f, + 0.003883f, 0.004078f, 0.004379f, 0.004692f, 0.004982f, 0.005329f, 0.005756f, 0.006081f, 0.006504f, 0.007019f, 0.007599f, 0.008217f, + 0.008850f, 0.009628f, 0.010437f, 0.011597f, 0.012650f, 0.013931f, 0.015480f, 0.017380f, 0.019577f, 0.022247f, 0.025513f, 0.029617f, + 0.034363f, 0.040314f, 0.047241f, 0.056274f, 0.066711f, 0.079773f, 0.094482f, 0.112488f, 0.132446f, 0.154907f, 0.585449f, 0.624023f, + 0.630371f, 0.634277f, 0.636230f, 0.637207f, 0.000161f, 0.000263f, 0.000526f, 0.000627f, 0.000723f, 0.000775f, 0.000856f, 0.000960f, + 0.001079f, 0.001158f, 0.001208f, 0.001272f, 0.001441f, 0.001557f, 0.001657f, 0.001702f, 0.001897f, 0.001918f, 0.002151f, 0.002232f, + 0.002337f, 0.002522f, 0.002720f, 0.002865f, 0.003029f, 0.003193f, 0.003387f, 0.003601f, 0.003887f, 0.004124f, 0.004356f, 0.004639f, + 0.005070f, 0.005466f, 0.005863f, 0.006298f, 0.006874f, 0.007290f, 0.007965f, 0.008774f, 0.009560f, 0.010666f, 0.011719f, 0.013077f, + 0.014679f, 0.016693f, 0.019058f, 0.021881f, 0.025528f, 0.030121f, 0.036011f, 0.043396f, 0.052460f, 0.063477f, 0.076721f, 0.093079f, + 0.112305f, 0.133667f, 0.572266f, 0.609375f, 0.618164f, 0.622070f, 0.623535f, 0.625488f, 0.000109f, 0.000212f, 0.000404f, 0.000578f, + 0.000567f, 0.000655f, 0.000763f, 0.000676f, 0.000824f, 0.000869f, 0.000971f, 0.001064f, 0.001132f, 0.001210f, 0.001212f, 0.001398f, + 0.001486f, 0.001525f, 0.001653f, 0.001676f, 0.001867f, 0.001953f, 0.002062f, 0.002199f, 0.002295f, 0.002443f, 0.002586f, 0.002766f, + 0.002979f, 0.003128f, 0.003429f, 0.003551f, 0.003763f, 0.004074f, 0.004349f, 0.004688f, 0.005032f, 0.005470f, 0.005894f, 0.006519f, + 0.007092f, 0.007896f, 0.008629f, 0.009659f, 0.010910f, 0.012215f, 0.013962f, 0.015991f, 0.018646f, 0.021881f, 0.026428f, 0.032074f, + 0.039276f, 0.048645f, 0.060455f, 0.075256f, 0.092773f, 0.113220f, 0.554688f, 0.596191f, 0.605957f, 0.608887f, 0.610352f, 0.612305f, + 0.000202f, 0.000186f, 0.000312f, 0.000433f, 0.000382f, 0.000543f, 0.000482f, 0.000546f, 0.000621f, 0.000666f, 0.000789f, 0.000802f, + 0.000859f, 0.000950f, 0.000970f, 0.000975f, 0.001113f, 0.001162f, 0.001207f, 0.001312f, 0.001362f, 0.001433f, 0.001541f, 0.001618f, + 0.001720f, 0.001791f, 0.001966f, 0.002035f, 0.002199f, 0.002413f, 0.002546f, 0.002626f, 0.002855f, 0.003063f, 0.003204f, 0.003448f, + 0.003693f, 0.003986f, 0.004364f, 0.004684f, 0.005127f, 0.005619f, 0.006271f, 0.006870f, 0.007748f, 0.008713f, 0.009911f, 0.011368f, + 0.013191f, 0.015518f, 0.018646f, 0.022644f, 0.028107f, 0.035645f, 0.045471f, 0.058502f, 0.074646f, 0.093994f, 0.541016f, 0.583008f, + 0.591797f, 0.596191f, 0.599121f, 0.600098f, 0.000000f, 0.000179f, 0.000242f, 0.000318f, 0.000341f, 0.000345f, 0.000432f, 0.000364f, + 0.000475f, 0.000483f, 0.000572f, 0.000576f, 0.000619f, 0.000640f, 0.000716f, 0.000737f, 0.000791f, 0.000845f, 0.000871f, 0.000907f, + 0.000998f, 0.001025f, 0.001107f, 0.001181f, 0.001244f, 0.001303f, 0.001391f, 0.001462f, 0.001549f, 0.001631f, 0.001756f, 0.001906f, + 0.001984f, 0.002161f, 0.002264f, 0.002419f, 0.002613f, 0.002825f, 0.003103f, 0.003321f, 0.003584f, 0.003893f, 0.004349f, 0.004799f, + 0.005383f, 0.006020f, 0.006836f, 0.007858f, 0.009117f, 0.010674f, 0.012825f, 0.015533f, 0.019363f, 0.024780f, 0.032593f, 0.043274f, + 0.057770f, 0.076111f, 0.525879f, 0.569336f, 0.578613f, 0.583008f, 0.585449f, 0.586426f, 0.000000f, 0.000088f, 0.000192f, 0.000227f, + 0.000230f, 0.000286f, 0.000255f, 0.000317f, 0.000321f, 0.000371f, 0.000401f, 0.000373f, 0.000391f, 0.000457f, 0.000474f, 0.000530f, + 0.000509f, 0.000585f, 0.000625f, 0.000664f, 0.000707f, 0.000746f, 0.000772f, 0.000817f, 0.000877f, 0.000887f, 0.000978f, 0.001007f, + 0.001069f, 0.001202f, 0.001192f, 0.001290f, 0.001356f, 0.001464f, 0.001583f, 0.001678f, 0.001771f, 0.001929f, 0.002050f, 0.002230f, + 0.002424f, 0.002651f, 0.002888f, 0.003176f, 0.003534f, 0.003967f, 0.004475f, 0.005154f, 0.005993f, 0.007118f, 0.008469f, 0.010338f, + 0.012794f, 0.016403f, 0.021957f, 0.030090f, 0.042419f, 0.059052f, 0.510254f, 0.554199f, 0.564453f, 0.570312f, 0.572754f, 0.573242f, + 0.000000f, 0.000126f, 0.000180f, 0.000121f, 0.000178f, 0.000176f, 0.000177f, 0.000212f, 0.000210f, 0.000228f, 0.000238f, 0.000291f, + 0.000280f, 0.000298f, 0.000336f, 0.000350f, 0.000369f, 0.000387f, 0.000395f, 0.000427f, 0.000460f, 0.000476f, 0.000515f, 0.000536f, + 0.000573f, 0.000619f, 0.000650f, 0.000670f, 0.000703f, 0.000746f, 0.000798f, 0.000836f, 0.000902f, 0.000949f, 0.001031f, 0.001062f, + 0.001162f, 0.001227f, 0.001349f, 0.001442f, 0.001533f, 0.001690f, 0.001865f, 0.001995f, 0.002228f, 0.002495f, 0.002800f, 0.003191f, + 0.003653f, 0.004349f, 0.005203f, 0.006393f, 0.008026f, 0.010307f, 0.013710f, 0.019379f, 0.028854f, 0.043457f, 0.494873f, 0.541016f, + 0.550781f, 0.555664f, 0.558105f, 0.559570f, 0.000000f, 0.000095f, 0.000086f, 0.000079f, 0.000105f, 0.000124f, 0.000111f, 0.000137f, + 0.000141f, 0.000142f, 0.000147f, 0.000151f, 0.000160f, 0.000181f, 0.000202f, 0.000207f, 0.000214f, 0.000248f, 0.000244f, 0.000282f, + 0.000273f, 0.000283f, 0.000306f, 0.000334f, 0.000367f, 0.000378f, 0.000376f, 0.000399f, 0.000437f, 0.000459f, 0.000474f, 0.000516f, + 0.000552f, 0.000567f, 0.000616f, 0.000649f, 0.000693f, 0.000743f, 0.000805f, 0.000851f, 0.000918f, 0.000999f, 0.001085f, 0.001195f, + 0.001309f, 0.001466f, 0.001644f, 0.001850f, 0.002151f, 0.002487f, 0.002974f, 0.003654f, 0.004574f, 0.006001f, 0.008156f, 0.011452f, + 0.017853f, 0.029739f, 0.478271f, 0.526367f, 0.537109f, 0.541504f, 0.544434f, 0.545898f, 0.000106f, 0.000085f, 0.000074f, 0.000067f, + 0.000066f, 0.000070f, 0.000069f, 0.000073f, 0.000073f, 0.000080f, 0.000084f, 0.000109f, 0.000093f, 0.000098f, 0.000119f, 0.000108f, + 0.000128f, 0.000135f, 0.000137f, 0.000149f, 0.000150f, 0.000157f, 0.000182f, 0.000185f, 0.000207f, 0.000206f, 0.000214f, 0.000234f, + 0.000237f, 0.000253f, 0.000267f, 0.000289f, 0.000306f, 0.000313f, 0.000344f, 0.000352f, 0.000384f, 0.000406f, 0.000445f, 0.000467f, + 0.000503f, 0.000543f, 0.000593f, 0.000634f, 0.000697f, 0.000764f, 0.000850f, 0.000963f, 0.001105f, 0.001298f, 0.001536f, 0.001856f, + 0.002333f, 0.003069f, 0.004299f, 0.006271f, 0.009789f, 0.018234f, 0.462402f, 0.511719f, 0.522949f, 0.527344f, 0.530762f, 0.532715f, + 0.000091f, 0.000069f, 0.000060f, 0.000054f, 0.000049f, 0.000046f, 0.000043f, 0.000041f, 0.000040f, 0.000044f, 0.000040f, 0.000040f, + 0.000054f, 0.000044f, 0.000045f, 0.000044f, 0.000062f, 0.000062f, 0.000069f, 0.000071f, 0.000074f, 0.000079f, 0.000081f, 0.000081f, + 0.000085f, 0.000099f, 0.000098f, 0.000115f, 0.000115f, 0.000119f, 0.000125f, 0.000130f, 0.000140f, 0.000144f, 0.000165f, 0.000172f, + 0.000178f, 0.000191f, 0.000205f, 0.000222f, 0.000234f, 0.000251f, 0.000276f, 0.000293f, 0.000327f, 0.000354f, 0.000392f, 0.000437f, + 0.000494f, 0.000562f, 0.000662f, 0.000800f, 0.001005f, 0.001315f, 0.001852f, 0.002825f, 0.004723f, 0.009285f, 0.446533f, 0.497803f, + 0.508301f, 0.514160f, 0.516602f, 0.519043f, 0.000067f, 0.000048f, 0.000040f, 0.000036f, 0.000033f, 0.000031f, 0.000030f, 0.000028f, + 0.000027f, 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000022f, 0.000021f, 0.000020f, 0.000019f, 0.000020f, 0.000024f, 0.000026f, + 0.000025f, 0.000027f, 0.000031f, 0.000032f, 0.000032f, 0.000037f, 0.000041f, 0.000038f, 0.000045f, 0.000042f, 0.000048f, 0.000049f, + 0.000053f, 0.000055f, 0.000059f, 0.000062f, 0.000071f, 0.000074f, 0.000077f, 0.000081f, 0.000086f, 0.000091f, 0.000098f, 0.000109f, + 0.000116f, 0.000125f, 0.000137f, 0.000158f, 0.000173f, 0.000193f, 0.000230f, 0.000273f, 0.000335f, 0.000425f, 0.000603f, 0.000935f, + 0.001694f, 0.003727f, 0.431396f, 0.481934f, 0.493652f, 0.499512f, 0.502930f, 0.504883f, 0.000021f, 0.000016f, 0.000013f, 0.000012f, + 0.000013f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, + 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000007f, + 0.000008f, 0.000009f, 0.000009f, 0.000010f, 0.000010f, 0.000013f, 0.000014f, 0.000013f, 0.000015f, 0.000016f, 0.000017f, 0.000019f, + 0.000019f, 0.000020f, 0.000023f, 0.000026f, 0.000027f, 0.000027f, 0.000032f, 0.000030f, 0.000036f, 0.000039f, 0.000050f, 0.000056f, + 0.000063f, 0.000082f, 0.000109f, 0.000168f, 0.000317f, 0.000922f, 0.415283f, 0.467773f, 0.479980f, 0.486328f, 0.489014f, 0.490723f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, + 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000005f, 0.000008f, 0.000026f, 0.398926f, 0.452881f, + 0.465576f, 0.471436f, 0.474854f, 0.477051f, + }, + { + 0.019653f, 0.058990f, 0.097473f, 0.134277f, 0.169189f, 0.203491f, 0.236450f, 0.267578f, 0.297852f, 0.326416f, 0.354004f, 0.380859f, + 0.406250f, 0.431641f, 0.455078f, 0.477539f, 0.500000f, 0.520996f, 0.541504f, 0.560547f, 0.580566f, 0.598633f, 0.615723f, 0.633301f, + 0.649902f, 0.666016f, 0.681641f, 0.695801f, 0.709961f, 0.724609f, 0.738770f, 0.751953f, 0.765137f, 0.775879f, 0.788574f, 0.799805f, + 0.812012f, 0.822754f, 0.833496f, 0.844238f, 0.854004f, 0.864258f, 0.874023f, 0.883301f, 0.891602f, 0.900391f, 0.909668f, 0.917969f, + 0.925781f, 0.934570f, 0.941895f, 0.949707f, 0.956543f, 0.963379f, 0.970703f, 0.977539f, 0.984863f, 0.991211f, 0.988770f, 0.972656f, + 0.960449f, 0.949707f, 0.940430f, 0.931641f, 0.017303f, 0.052399f, 0.086548f, 0.119446f, 0.153076f, 0.183594f, 0.214722f, 0.245117f, + 0.273193f, 0.301270f, 0.328613f, 0.354492f, 0.379883f, 0.404541f, 0.427979f, 0.450195f, 0.472656f, 0.494629f, 0.515137f, 0.534668f, + 0.554199f, 0.573242f, 0.591309f, 0.608887f, 0.625977f, 0.642578f, 0.658203f, 0.672852f, 0.688477f, 0.704102f, 0.717285f, 0.731445f, + 0.744629f, 0.756836f, 0.769531f, 0.782715f, 0.793945f, 0.805664f, 0.816406f, 0.828125f, 0.838379f, 0.849121f, 0.858887f, 0.868652f, + 0.877930f, 0.888184f, 0.896973f, 0.905762f, 0.915039f, 0.921875f, 0.930176f, 0.937988f, 0.946777f, 0.954102f, 0.960938f, 0.968750f, + 0.975586f, 0.982422f, 0.984375f, 0.969238f, 0.957520f, 0.947754f, 0.938477f, 0.930176f, 0.015221f, 0.045837f, 0.076843f, 0.107666f, + 0.136719f, 0.166504f, 0.196045f, 0.223999f, 0.250244f, 0.278320f, 0.303711f, 0.329346f, 0.353271f, 0.378906f, 0.401367f, 0.424316f, + 0.447266f, 0.468018f, 0.487793f, 0.508301f, 0.529297f, 0.547363f, 0.566406f, 0.583984f, 0.601562f, 0.618652f, 0.634766f, 0.650879f, + 0.666016f, 0.681641f, 0.695801f, 0.710449f, 0.724121f, 0.737305f, 0.750488f, 0.762695f, 0.775391f, 0.788086f, 0.799316f, 0.811035f, + 0.821777f, 0.833008f, 0.844238f, 0.854004f, 0.864258f, 0.874023f, 0.882812f, 0.892578f, 0.901367f, 0.910156f, 0.918457f, 0.926758f, + 0.936035f, 0.942871f, 0.950684f, 0.958496f, 0.965820f, 0.973145f, 0.980469f, 0.965820f, 0.955078f, 0.945312f, 0.936523f, 0.928223f, + 0.013420f, 0.041138f, 0.068359f, 0.096436f, 0.124023f, 0.150879f, 0.177246f, 0.204224f, 0.230103f, 0.255859f, 0.281494f, 0.305420f, + 0.329834f, 0.352783f, 0.376709f, 0.398682f, 0.420654f, 0.442627f, 0.462646f, 0.483887f, 0.502441f, 0.521484f, 0.540527f, 0.559082f, + 0.576172f, 0.595703f, 0.611328f, 0.627930f, 0.644043f, 0.659668f, 0.674316f, 0.688965f, 0.703613f, 0.717285f, 0.730957f, 0.744629f, + 0.756836f, 0.770020f, 0.781738f, 0.793945f, 0.805176f, 0.816895f, 0.828125f, 0.838379f, 0.849121f, 0.859375f, 0.869141f, 0.878418f, + 0.888184f, 0.897461f, 0.906738f, 0.915039f, 0.923828f, 0.932129f, 0.940430f, 0.947754f, 0.956543f, 0.963867f, 0.976074f, 0.962402f, + 0.951660f, 0.942383f, 0.934082f, 0.926758f, 0.012001f, 0.036591f, 0.061737f, 0.086670f, 0.112000f, 0.136719f, 0.161743f, 0.186768f, + 0.211792f, 0.235840f, 0.259521f, 0.283203f, 0.307129f, 0.329590f, 0.352295f, 0.374268f, 0.395996f, 0.416992f, 0.437744f, 0.457520f, + 0.477295f, 0.497314f, 0.515625f, 0.534180f, 0.553223f, 0.570312f, 0.588379f, 0.604492f, 0.621582f, 0.636719f, 0.653320f, 0.666992f, + 0.683105f, 0.697266f, 0.710449f, 0.724609f, 0.737793f, 0.750977f, 0.764160f, 0.775879f, 0.788086f, 0.799805f, 0.812012f, 0.823242f, + 0.833496f, 0.844238f, 0.854492f, 0.864746f, 0.875000f, 0.884277f, 0.894043f, 0.902832f, 0.911621f, 0.920898f, 0.929688f, 0.937500f, + 0.945801f, 0.953613f, 0.971191f, 0.958984f, 0.949219f, 0.939941f, 0.932129f, 0.924316f, 0.010612f, 0.032684f, 0.054810f, 0.077759f, + 0.100952f, 0.124023f, 0.146851f, 0.171021f, 0.193604f, 0.217163f, 0.239380f, 0.261963f, 0.284424f, 0.307129f, 0.328613f, 0.351318f, + 0.371826f, 0.392334f, 0.413574f, 0.432617f, 0.453613f, 0.472656f, 0.491943f, 0.510254f, 0.528320f, 0.546387f, 0.563965f, 0.580078f, + 0.598633f, 0.613770f, 0.629883f, 0.645996f, 0.661621f, 0.675293f, 0.688965f, 0.705078f, 0.718262f, 0.731934f, 0.745605f, 0.757812f, + 0.770996f, 0.782715f, 0.795410f, 0.807129f, 0.818359f, 0.829102f, 0.839844f, 0.851074f, 0.860840f, 0.871094f, 0.880859f, 0.891113f, + 0.900391f, 0.909668f, 0.917969f, 0.927246f, 0.935547f, 0.943848f, 0.966797f, 0.955566f, 0.945801f, 0.937012f, 0.929199f, 0.921875f, + 0.009483f, 0.029556f, 0.050140f, 0.070129f, 0.091797f, 0.112549f, 0.134155f, 0.156372f, 0.177368f, 0.198975f, 0.220825f, 0.243286f, + 0.263916f, 0.285645f, 0.306885f, 0.327393f, 0.348145f, 0.368896f, 0.389404f, 0.409424f, 0.429199f, 0.448730f, 0.467529f, 0.486572f, + 0.505371f, 0.522461f, 0.540039f, 0.558105f, 0.574219f, 0.591309f, 0.607422f, 0.623535f, 0.639648f, 0.654785f, 0.669922f, 0.685547f, + 0.698730f, 0.712891f, 0.726074f, 0.740234f, 0.752441f, 0.765625f, 0.778320f, 0.789551f, 0.802246f, 0.813477f, 0.825195f, 0.836426f, + 0.847168f, 0.856934f, 0.868164f, 0.877930f, 0.888184f, 0.897461f, 0.906738f, 0.915527f, 0.925293f, 0.935059f, 0.962402f, 0.951660f, + 0.942383f, 0.933594f, 0.926270f, 0.919434f, 0.008934f, 0.026581f, 0.044708f, 0.063354f, 0.082825f, 0.102844f, 0.122437f, 0.141968f, + 0.162720f, 0.183105f, 0.202515f, 0.224609f, 0.244995f, 0.265381f, 0.285645f, 0.306152f, 0.326416f, 0.346680f, 0.365967f, 0.385498f, + 0.406006f, 0.425293f, 0.444092f, 0.461914f, 0.480225f, 0.499268f, 0.517090f, 0.535156f, 0.552246f, 0.568359f, 0.585449f, 0.601562f, + 0.616699f, 0.633789f, 0.649414f, 0.663574f, 0.678711f, 0.693848f, 0.706543f, 0.721680f, 0.734375f, 0.746582f, 0.760742f, 0.773438f, + 0.786133f, 0.797852f, 0.809082f, 0.821777f, 0.832031f, 0.843262f, 0.854492f, 0.864746f, 0.875000f, 0.884766f, 0.895020f, 0.904785f, + 0.914062f, 0.922852f, 0.957520f, 0.947266f, 0.938965f, 0.930664f, 0.923340f, 0.916992f, 0.007668f, 0.024017f, 0.040405f, 0.057831f, + 0.075195f, 0.093079f, 0.111694f, 0.130127f, 0.148926f, 0.168213f, 0.187500f, 0.206543f, 0.226440f, 0.246460f, 0.265869f, 0.285400f, + 0.305176f, 0.324707f, 0.344238f, 0.363281f, 0.383057f, 0.401123f, 0.420166f, 0.439941f, 0.457764f, 0.475586f, 0.493164f, 0.511719f, + 0.528809f, 0.545898f, 0.562988f, 0.579590f, 0.596191f, 0.612305f, 0.627441f, 0.643555f, 0.658203f, 0.672363f, 0.687988f, 0.702637f, + 0.715332f, 0.728516f, 0.742676f, 0.756348f, 0.768555f, 0.781250f, 0.794434f, 0.806152f, 0.818359f, 0.828613f, 0.840332f, 0.851074f, + 0.861816f, 0.872559f, 0.882812f, 0.892578f, 0.903320f, 0.912598f, 0.952637f, 0.943848f, 0.935059f, 0.927246f, 0.920410f, 0.914062f, + 0.007263f, 0.021530f, 0.037048f, 0.052429f, 0.068909f, 0.084961f, 0.102112f, 0.119568f, 0.136475f, 0.154541f, 0.172852f, 0.191528f, + 0.209717f, 0.228638f, 0.246948f, 0.265869f, 0.284912f, 0.304199f, 0.322510f, 0.341309f, 0.360596f, 0.379639f, 0.397461f, 0.416504f, + 0.434570f, 0.452881f, 0.470947f, 0.489014f, 0.505859f, 0.523438f, 0.541016f, 0.557129f, 0.574219f, 0.590332f, 0.606445f, 0.622070f, + 0.637695f, 0.653809f, 0.667969f, 0.682129f, 0.697754f, 0.711426f, 0.724609f, 0.737793f, 0.750977f, 0.765625f, 0.777832f, 0.790039f, + 0.801270f, 0.813477f, 0.825684f, 0.837402f, 0.848145f, 0.859375f, 0.870117f, 0.880859f, 0.891602f, 0.900391f, 0.947754f, 0.938965f, + 0.931152f, 0.923828f, 0.917480f, 0.911133f, 0.006401f, 0.019730f, 0.033813f, 0.047729f, 0.062561f, 0.077515f, 0.093140f, 0.108948f, + 0.125366f, 0.141968f, 0.159058f, 0.175781f, 0.193726f, 0.212036f, 0.229980f, 0.247681f, 0.265869f, 0.284424f, 0.302734f, 0.320557f, + 0.339111f, 0.357910f, 0.376221f, 0.394287f, 0.412109f, 0.429688f, 0.448486f, 0.466064f, 0.483398f, 0.500977f, 0.517090f, 0.535156f, + 0.552246f, 0.568359f, 0.583984f, 0.600586f, 0.616699f, 0.632324f, 0.647949f, 0.662598f, 0.677246f, 0.692383f, 0.706543f, 0.719727f, + 0.734375f, 0.747070f, 0.761230f, 0.773926f, 0.786621f, 0.797852f, 0.811523f, 0.823242f, 0.834961f, 0.846680f, 0.857422f, 0.868652f, + 0.879395f, 0.890137f, 0.942383f, 0.934082f, 0.927246f, 0.919922f, 0.913574f, 0.908203f, 0.005836f, 0.018158f, 0.030746f, 0.043335f, + 0.057007f, 0.070801f, 0.085754f, 0.099548f, 0.115112f, 0.130127f, 0.146362f, 0.162354f, 0.178711f, 0.195801f, 0.212769f, 0.230103f, + 0.247925f, 0.264893f, 0.283203f, 0.300293f, 0.318604f, 0.336426f, 0.354492f, 0.372314f, 0.390137f, 0.408203f, 0.425537f, 0.443848f, + 0.461182f, 0.478271f, 0.496094f, 0.513184f, 0.529297f, 0.546387f, 0.563477f, 0.580566f, 0.595703f, 0.611816f, 0.626465f, 0.642090f, + 0.658691f, 0.671875f, 0.686523f, 0.702148f, 0.716797f, 0.729980f, 0.744629f, 0.757324f, 0.770020f, 0.783203f, 0.796875f, 0.808105f, + 0.820312f, 0.832520f, 0.844727f, 0.855957f, 0.867188f, 0.877930f, 0.937012f, 0.930176f, 0.922852f, 0.916504f, 0.910645f, 0.904785f, + 0.005486f, 0.016525f, 0.028030f, 0.039612f, 0.052185f, 0.064636f, 0.077576f, 0.091553f, 0.105347f, 0.119568f, 0.134521f, 0.149536f, + 0.164917f, 0.180664f, 0.197388f, 0.213623f, 0.230347f, 0.246826f, 0.264160f, 0.280518f, 0.298584f, 0.315674f, 0.334229f, 0.350830f, + 0.369141f, 0.386963f, 0.404053f, 0.422119f, 0.438477f, 0.456299f, 0.474121f, 0.491211f, 0.507812f, 0.524902f, 0.541504f, 0.557617f, + 0.574707f, 0.590820f, 0.606934f, 0.622559f, 0.637207f, 0.652832f, 0.668945f, 0.683105f, 0.698730f, 0.711914f, 0.726074f, 0.740723f, + 0.753906f, 0.766602f, 0.780273f, 0.792969f, 0.805664f, 0.818848f, 0.830566f, 0.842285f, 0.854492f, 0.866211f, 0.931641f, 0.925781f, + 0.918945f, 0.913086f, 0.907227f, 0.900879f, 0.004810f, 0.014847f, 0.025604f, 0.036621f, 0.047577f, 0.059174f, 0.071472f, 0.084106f, + 0.096985f, 0.109863f, 0.124146f, 0.137939f, 0.152954f, 0.167358f, 0.182495f, 0.197754f, 0.213745f, 0.230103f, 0.246216f, 0.262939f, + 0.279297f, 0.296387f, 0.313477f, 0.329834f, 0.348145f, 0.365479f, 0.382080f, 0.399658f, 0.417480f, 0.434082f, 0.452148f, 0.469238f, + 0.486084f, 0.502441f, 0.520020f, 0.536621f, 0.552734f, 0.569336f, 0.585938f, 0.601562f, 0.617676f, 0.632812f, 0.648438f, 0.664062f, + 0.679688f, 0.693848f, 0.708008f, 0.722656f, 0.735840f, 0.750488f, 0.765137f, 0.777832f, 0.791016f, 0.803711f, 0.816895f, 0.829102f, + 0.841309f, 0.853027f, 0.925781f, 0.921387f, 0.914551f, 0.908203f, 0.903320f, 0.897461f, 0.004494f, 0.013809f, 0.023331f, 0.033264f, + 0.043549f, 0.053833f, 0.065369f, 0.076660f, 0.088684f, 0.100708f, 0.113464f, 0.127075f, 0.140381f, 0.154419f, 0.169067f, 0.183472f, + 0.198975f, 0.213623f, 0.229370f, 0.245117f, 0.261475f, 0.277832f, 0.294678f, 0.311523f, 0.327148f, 0.344727f, 0.362061f, 0.378418f, + 0.395996f, 0.413086f, 0.430176f, 0.447021f, 0.464111f, 0.481689f, 0.498047f, 0.514648f, 0.531738f, 0.547363f, 0.565430f, 0.582031f, + 0.597656f, 0.612793f, 0.628418f, 0.644043f, 0.660645f, 0.674805f, 0.689941f, 0.705078f, 0.718750f, 0.734375f, 0.747559f, 0.761719f, + 0.775391f, 0.788086f, 0.803223f, 0.814453f, 0.828125f, 0.840332f, 0.919434f, 0.916504f, 0.909668f, 0.904785f, 0.898926f, 0.894043f, + 0.004120f, 0.012512f, 0.021423f, 0.030655f, 0.039673f, 0.049500f, 0.059845f, 0.070374f, 0.081543f, 0.093323f, 0.104614f, 0.116577f, + 0.129395f, 0.142456f, 0.156250f, 0.169434f, 0.183594f, 0.198364f, 0.213257f, 0.228638f, 0.244141f, 0.259766f, 0.275635f, 0.291748f, + 0.308105f, 0.324707f, 0.341309f, 0.359131f, 0.375244f, 0.391846f, 0.408447f, 0.426025f, 0.442871f, 0.459473f, 0.477051f, 0.494141f, + 0.510254f, 0.527344f, 0.543457f, 0.560059f, 0.577148f, 0.592773f, 0.608887f, 0.625977f, 0.640625f, 0.656738f, 0.671875f, 0.686523f, + 0.702637f, 0.716797f, 0.731445f, 0.746582f, 0.759277f, 0.773926f, 0.787598f, 0.800293f, 0.814453f, 0.827148f, 0.914062f, 0.911133f, + 0.905273f, 0.899902f, 0.895508f, 0.890625f, 0.004120f, 0.011566f, 0.019180f, 0.027969f, 0.036255f, 0.045746f, 0.054901f, 0.064941f, + 0.074707f, 0.085327f, 0.096436f, 0.107239f, 0.119324f, 0.131470f, 0.144165f, 0.157104f, 0.169922f, 0.183594f, 0.198242f, 0.212769f, + 0.227295f, 0.242188f, 0.257568f, 0.273193f, 0.289307f, 0.305420f, 0.321289f, 0.337891f, 0.354492f, 0.371094f, 0.387451f, 0.405029f, + 0.421143f, 0.438477f, 0.455322f, 0.472656f, 0.488525f, 0.505859f, 0.521973f, 0.539551f, 0.555664f, 0.572754f, 0.588867f, 0.605469f, + 0.621582f, 0.637207f, 0.653320f, 0.668945f, 0.684570f, 0.698242f, 0.714844f, 0.729492f, 0.745117f, 0.758301f, 0.771973f, 0.787109f, + 0.800781f, 0.813477f, 0.907715f, 0.905762f, 0.900879f, 0.895508f, 0.890625f, 0.886719f, 0.003464f, 0.010536f, 0.018143f, 0.025604f, + 0.033600f, 0.041992f, 0.050659f, 0.059631f, 0.068481f, 0.078552f, 0.088196f, 0.099060f, 0.110107f, 0.121033f, 0.133057f, 0.145020f, + 0.157349f, 0.170166f, 0.183838f, 0.197632f, 0.210938f, 0.225464f, 0.241089f, 0.255371f, 0.270508f, 0.286377f, 0.302246f, 0.317871f, + 0.334229f, 0.349854f, 0.367188f, 0.383789f, 0.399414f, 0.417236f, 0.433838f, 0.450928f, 0.468018f, 0.484131f, 0.501465f, 0.519043f, + 0.535156f, 0.551758f, 0.568359f, 0.585449f, 0.601074f, 0.617676f, 0.634277f, 0.649902f, 0.666016f, 0.681152f, 0.695801f, 0.711914f, + 0.727539f, 0.741699f, 0.756836f, 0.770508f, 0.785645f, 0.800293f, 0.901855f, 0.900391f, 0.895996f, 0.891113f, 0.886230f, 0.881836f, + 0.003197f, 0.009903f, 0.016525f, 0.023849f, 0.030853f, 0.038605f, 0.046265f, 0.054657f, 0.063232f, 0.072266f, 0.081543f, 0.090881f, + 0.100769f, 0.112061f, 0.123047f, 0.134155f, 0.145752f, 0.157471f, 0.170166f, 0.182861f, 0.196289f, 0.210327f, 0.223755f, 0.238525f, + 0.253418f, 0.268066f, 0.283203f, 0.299316f, 0.314697f, 0.330811f, 0.346680f, 0.363281f, 0.379639f, 0.396484f, 0.412842f, 0.429443f, + 0.446289f, 0.462891f, 0.480225f, 0.497559f, 0.514648f, 0.531250f, 0.547852f, 0.564453f, 0.581055f, 0.598145f, 0.615234f, 0.631836f, + 0.646484f, 0.663086f, 0.679199f, 0.694824f, 0.710449f, 0.726074f, 0.740234f, 0.755859f, 0.770508f, 0.784668f, 0.895020f, 0.894531f, + 0.890625f, 0.886719f, 0.881836f, 0.877441f, 0.003071f, 0.009163f, 0.015602f, 0.021729f, 0.028412f, 0.035522f, 0.042755f, 0.050598f, + 0.057983f, 0.066284f, 0.075317f, 0.083862f, 0.092773f, 0.102905f, 0.113342f, 0.123840f, 0.134399f, 0.145752f, 0.157593f, 0.169556f, + 0.182129f, 0.194702f, 0.207886f, 0.222046f, 0.235840f, 0.250977f, 0.265137f, 0.280273f, 0.295898f, 0.311279f, 0.326660f, 0.342773f, + 0.359375f, 0.375732f, 0.392090f, 0.409180f, 0.425049f, 0.441895f, 0.459473f, 0.476318f, 0.493652f, 0.510742f, 0.527344f, 0.544434f, + 0.561035f, 0.578125f, 0.595215f, 0.611328f, 0.628418f, 0.645020f, 0.661133f, 0.677246f, 0.693359f, 0.708496f, 0.724609f, 0.740723f, + 0.755859f, 0.771484f, 0.889160f, 0.889160f, 0.885254f, 0.881348f, 0.876953f, 0.873047f, 0.002748f, 0.008171f, 0.014084f, 0.019638f, + 0.026108f, 0.032318f, 0.039154f, 0.045990f, 0.053619f, 0.061066f, 0.068665f, 0.076477f, 0.085632f, 0.094727f, 0.104187f, 0.113831f, + 0.123535f, 0.134888f, 0.145508f, 0.157104f, 0.168701f, 0.181030f, 0.193481f, 0.206665f, 0.220093f, 0.233398f, 0.248169f, 0.262695f, + 0.277344f, 0.292236f, 0.307617f, 0.322998f, 0.339355f, 0.355469f, 0.371582f, 0.388184f, 0.404541f, 0.420410f, 0.438477f, 0.455322f, + 0.472656f, 0.489014f, 0.506348f, 0.523926f, 0.541016f, 0.557617f, 0.575195f, 0.591309f, 0.608887f, 0.625977f, 0.643555f, 0.659180f, + 0.674805f, 0.691406f, 0.707520f, 0.724121f, 0.739746f, 0.755371f, 0.882812f, 0.883789f, 0.879883f, 0.875977f, 0.872559f, 0.868652f, + 0.002491f, 0.007809f, 0.012764f, 0.018448f, 0.024094f, 0.029861f, 0.036102f, 0.042572f, 0.049500f, 0.056091f, 0.063293f, 0.070984f, + 0.079285f, 0.087036f, 0.095825f, 0.104858f, 0.114441f, 0.124084f, 0.133789f, 0.144653f, 0.156250f, 0.167480f, 0.179199f, 0.191650f, + 0.204102f, 0.217896f, 0.231445f, 0.245239f, 0.259521f, 0.274170f, 0.289307f, 0.304199f, 0.319580f, 0.334961f, 0.351074f, 0.367676f, + 0.384277f, 0.400635f, 0.417480f, 0.434570f, 0.451660f, 0.468994f, 0.485352f, 0.502441f, 0.520508f, 0.537109f, 0.554688f, 0.571777f, + 0.588867f, 0.605957f, 0.623047f, 0.639648f, 0.656738f, 0.673828f, 0.690430f, 0.708008f, 0.723633f, 0.739746f, 0.874023f, 0.876953f, + 0.874023f, 0.871582f, 0.867188f, 0.862793f, 0.002279f, 0.007130f, 0.012291f, 0.016922f, 0.022171f, 0.027847f, 0.033325f, 0.039185f, + 0.045349f, 0.051849f, 0.058411f, 0.064880f, 0.072144f, 0.080017f, 0.087891f, 0.096313f, 0.105103f, 0.114197f, 0.123779f, 0.134155f, + 0.144043f, 0.155151f, 0.166016f, 0.177246f, 0.189697f, 0.202271f, 0.214722f, 0.228271f, 0.242310f, 0.256592f, 0.270752f, 0.285400f, + 0.300537f, 0.315674f, 0.331543f, 0.347656f, 0.363525f, 0.379639f, 0.396729f, 0.414307f, 0.430908f, 0.447754f, 0.465088f, 0.482178f, + 0.499512f, 0.517090f, 0.533203f, 0.552246f, 0.568848f, 0.586426f, 0.603516f, 0.621582f, 0.639648f, 0.656250f, 0.673828f, 0.690918f, + 0.707520f, 0.724121f, 0.867676f, 0.870605f, 0.868164f, 0.865723f, 0.861328f, 0.857910f, 0.002220f, 0.006565f, 0.011238f, 0.015961f, + 0.020401f, 0.025558f, 0.030853f, 0.036133f, 0.041199f, 0.047180f, 0.053436f, 0.059723f, 0.066162f, 0.073853f, 0.080688f, 0.088440f, + 0.096436f, 0.105042f, 0.114319f, 0.123047f, 0.132446f, 0.142822f, 0.153198f, 0.164062f, 0.175659f, 0.187378f, 0.199463f, 0.212402f, + 0.225464f, 0.239014f, 0.252686f, 0.266846f, 0.281494f, 0.296631f, 0.312500f, 0.328369f, 0.343750f, 0.359863f, 0.376221f, 0.393066f, + 0.409668f, 0.426514f, 0.444336f, 0.461670f, 0.478760f, 0.496826f, 0.513672f, 0.532227f, 0.549316f, 0.567383f, 0.584961f, 0.602051f, + 0.620605f, 0.637207f, 0.655273f, 0.672363f, 0.689941f, 0.708008f, 0.860840f, 0.864746f, 0.862793f, 0.859375f, 0.855957f, 0.853027f, + 0.002190f, 0.005993f, 0.010117f, 0.014420f, 0.018738f, 0.023361f, 0.028015f, 0.033142f, 0.037781f, 0.043732f, 0.048920f, 0.054840f, + 0.061218f, 0.067810f, 0.074219f, 0.081299f, 0.088562f, 0.096130f, 0.104614f, 0.113098f, 0.122253f, 0.131714f, 0.141113f, 0.151245f, + 0.162109f, 0.173462f, 0.184692f, 0.196899f, 0.209473f, 0.222534f, 0.236206f, 0.249634f, 0.263672f, 0.277588f, 0.293213f, 0.308350f, + 0.323975f, 0.339844f, 0.355957f, 0.372070f, 0.389404f, 0.405762f, 0.422852f, 0.439941f, 0.458008f, 0.475098f, 0.492920f, 0.510742f, + 0.528320f, 0.546875f, 0.564453f, 0.583496f, 0.601074f, 0.619141f, 0.636719f, 0.654785f, 0.672852f, 0.691406f, 0.852539f, 0.858398f, + 0.856445f, 0.853516f, 0.850586f, 0.847656f, 0.001787f, 0.005753f, 0.009300f, 0.013611f, 0.017410f, 0.021576f, 0.025665f, 0.030533f, + 0.035126f, 0.040039f, 0.044952f, 0.050446f, 0.055817f, 0.061890f, 0.068054f, 0.074707f, 0.081482f, 0.088501f, 0.095764f, 0.103943f, + 0.112183f, 0.120850f, 0.130249f, 0.139526f, 0.149658f, 0.160400f, 0.171021f, 0.182007f, 0.194336f, 0.206421f, 0.219360f, 0.232666f, + 0.245850f, 0.260010f, 0.274170f, 0.289307f, 0.304443f, 0.319580f, 0.335693f, 0.352295f, 0.369141f, 0.385498f, 0.402344f, 0.419189f, + 0.437012f, 0.454346f, 0.472412f, 0.490234f, 0.507812f, 0.525879f, 0.545410f, 0.562500f, 0.581055f, 0.600098f, 0.618164f, 0.636719f, + 0.655273f, 0.674316f, 0.845703f, 0.852051f, 0.849609f, 0.847168f, 0.845215f, 0.841309f, 0.001766f, 0.005241f, 0.008881f, 0.012024f, + 0.016129f, 0.020233f, 0.024124f, 0.027664f, 0.032135f, 0.036835f, 0.041321f, 0.046173f, 0.051392f, 0.056946f, 0.062225f, 0.068604f, + 0.074524f, 0.080933f, 0.088135f, 0.095398f, 0.103210f, 0.110779f, 0.119263f, 0.128296f, 0.137695f, 0.147217f, 0.157349f, 0.168091f, + 0.179688f, 0.191284f, 0.203613f, 0.215942f, 0.228882f, 0.242554f, 0.255859f, 0.270508f, 0.285400f, 0.300537f, 0.316406f, 0.331787f, + 0.348877f, 0.364746f, 0.382080f, 0.398682f, 0.415771f, 0.434082f, 0.451416f, 0.469482f, 0.487793f, 0.505859f, 0.524414f, 0.542969f, + 0.562012f, 0.580566f, 0.598145f, 0.618652f, 0.637695f, 0.657227f, 0.837891f, 0.844727f, 0.843750f, 0.841309f, 0.838379f, 0.836426f, + 0.001598f, 0.004887f, 0.008217f, 0.011497f, 0.014786f, 0.018326f, 0.021652f, 0.025513f, 0.029541f, 0.033813f, 0.038086f, 0.042236f, + 0.046844f, 0.052032f, 0.057251f, 0.062622f, 0.068237f, 0.074280f, 0.080505f, 0.086975f, 0.094116f, 0.101074f, 0.109314f, 0.117554f, + 0.126587f, 0.135254f, 0.144775f, 0.155029f, 0.165405f, 0.176392f, 0.187744f, 0.199829f, 0.212646f, 0.224976f, 0.238647f, 0.252441f, + 0.267090f, 0.281738f, 0.296631f, 0.312256f, 0.328369f, 0.344971f, 0.361328f, 0.377686f, 0.395264f, 0.412842f, 0.430908f, 0.448730f, + 0.467041f, 0.485596f, 0.503906f, 0.522461f, 0.541504f, 0.561523f, 0.580078f, 0.599121f, 0.618164f, 0.639648f, 0.828613f, 0.837891f, + 0.836914f, 0.834473f, 0.833008f, 0.830566f, 0.001709f, 0.004494f, 0.007416f, 0.010628f, 0.013680f, 0.016785f, 0.020203f, 0.023712f, + 0.027435f, 0.031006f, 0.034424f, 0.038635f, 0.043182f, 0.047668f, 0.052307f, 0.057159f, 0.062042f, 0.067749f, 0.073730f, 0.079956f, + 0.086182f, 0.092773f, 0.100159f, 0.107727f, 0.115479f, 0.123962f, 0.132935f, 0.142578f, 0.151978f, 0.162476f, 0.173340f, 0.184570f, + 0.196411f, 0.208740f, 0.221436f, 0.235229f, 0.248779f, 0.262939f, 0.277832f, 0.293213f, 0.308105f, 0.324219f, 0.341309f, 0.357178f, + 0.374756f, 0.391846f, 0.409424f, 0.427490f, 0.446533f, 0.464844f, 0.483643f, 0.501953f, 0.521484f, 0.541504f, 0.561035f, 0.579590f, + 0.599609f, 0.620605f, 0.821289f, 0.830566f, 0.830078f, 0.828125f, 0.825684f, 0.823242f, 0.001367f, 0.004105f, 0.007023f, 0.009552f, + 0.012611f, 0.015289f, 0.018341f, 0.021652f, 0.024857f, 0.027878f, 0.031769f, 0.035614f, 0.039276f, 0.043610f, 0.047333f, 0.052155f, + 0.056549f, 0.061401f, 0.066895f, 0.072449f, 0.078613f, 0.084778f, 0.091309f, 0.098083f, 0.105774f, 0.113281f, 0.121399f, 0.130371f, + 0.139648f, 0.148926f, 0.159546f, 0.169922f, 0.180908f, 0.192749f, 0.204834f, 0.217651f, 0.231567f, 0.244385f, 0.259277f, 0.273926f, + 0.289307f, 0.304688f, 0.320557f, 0.336914f, 0.354248f, 0.371338f, 0.388184f, 0.406982f, 0.424316f, 0.443115f, 0.462646f, 0.481445f, + 0.501465f, 0.520508f, 0.541016f, 0.559570f, 0.580078f, 0.601074f, 0.812988f, 0.823242f, 0.823242f, 0.821289f, 0.819824f, 0.817383f, + 0.001398f, 0.003883f, 0.006351f, 0.008911f, 0.011559f, 0.014343f, 0.017212f, 0.020035f, 0.022797f, 0.026062f, 0.028793f, 0.031891f, + 0.035858f, 0.039368f, 0.043213f, 0.047607f, 0.051483f, 0.056030f, 0.060883f, 0.065979f, 0.071350f, 0.076843f, 0.083130f, 0.089172f, + 0.096069f, 0.103333f, 0.111023f, 0.119019f, 0.127319f, 0.136719f, 0.145996f, 0.156128f, 0.166138f, 0.177368f, 0.189453f, 0.201416f, + 0.213745f, 0.227295f, 0.240601f, 0.255371f, 0.269287f, 0.285400f, 0.301270f, 0.317139f, 0.333740f, 0.350586f, 0.367920f, 0.385986f, + 0.404297f, 0.422852f, 0.442383f, 0.460938f, 0.479980f, 0.500488f, 0.520508f, 0.541016f, 0.560547f, 0.582520f, 0.803711f, 0.814941f, + 0.815430f, 0.814453f, 0.812500f, 0.810547f, 0.001259f, 0.003464f, 0.006332f, 0.008286f, 0.010384f, 0.013000f, 0.015587f, 0.018234f, + 0.021027f, 0.023422f, 0.026566f, 0.029480f, 0.032379f, 0.035919f, 0.039215f, 0.043060f, 0.046997f, 0.050995f, 0.055267f, 0.059998f, + 0.065002f, 0.069946f, 0.075317f, 0.081299f, 0.087280f, 0.094116f, 0.101135f, 0.108276f, 0.116150f, 0.124695f, 0.133545f, 0.142700f, + 0.152222f, 0.162720f, 0.173950f, 0.185303f, 0.197754f, 0.210205f, 0.223022f, 0.237061f, 0.250732f, 0.265869f, 0.281250f, 0.297119f, + 0.313477f, 0.330322f, 0.347656f, 0.364746f, 0.383301f, 0.401367f, 0.420898f, 0.440186f, 0.459229f, 0.479736f, 0.499512f, 0.520996f, + 0.541016f, 0.562988f, 0.794434f, 0.807129f, 0.807617f, 0.807129f, 0.805176f, 0.803711f, 0.001070f, 0.003237f, 0.005432f, 0.007359f, + 0.009857f, 0.012337f, 0.014191f, 0.016586f, 0.019257f, 0.021561f, 0.024094f, 0.026901f, 0.029724f, 0.032745f, 0.035675f, 0.039368f, + 0.042572f, 0.045990f, 0.050354f, 0.054535f, 0.058746f, 0.063232f, 0.068420f, 0.073608f, 0.079529f, 0.085266f, 0.091370f, 0.098083f, + 0.105835f, 0.113159f, 0.121094f, 0.129639f, 0.139038f, 0.148926f, 0.159058f, 0.169678f, 0.181274f, 0.193481f, 0.205811f, 0.219482f, + 0.233032f, 0.247192f, 0.262207f, 0.277100f, 0.293213f, 0.309814f, 0.326660f, 0.344238f, 0.361816f, 0.380615f, 0.398926f, 0.418945f, + 0.438477f, 0.458008f, 0.479004f, 0.499512f, 0.520996f, 0.543945f, 0.784668f, 0.798828f, 0.800293f, 0.799805f, 0.797852f, 0.796875f, + 0.001074f, 0.002916f, 0.004955f, 0.007149f, 0.009033f, 0.011055f, 0.013268f, 0.015495f, 0.017365f, 0.019485f, 0.022095f, 0.024002f, + 0.026688f, 0.029633f, 0.032593f, 0.035370f, 0.038361f, 0.041870f, 0.045319f, 0.049225f, 0.052948f, 0.057068f, 0.061676f, 0.066345f, + 0.071167f, 0.076782f, 0.082581f, 0.088867f, 0.095886f, 0.102539f, 0.109802f, 0.118042f, 0.126709f, 0.135132f, 0.144897f, 0.155151f, + 0.165771f, 0.177368f, 0.189209f, 0.201904f, 0.215210f, 0.229370f, 0.242798f, 0.258057f, 0.274170f, 0.290039f, 0.306885f, 0.323242f, + 0.341309f, 0.359375f, 0.378418f, 0.397461f, 0.416260f, 0.437500f, 0.457031f, 0.479004f, 0.501465f, 0.522461f, 0.775391f, 0.790527f, + 0.791992f, 0.791504f, 0.791016f, 0.789551f, 0.000837f, 0.002916f, 0.004738f, 0.006477f, 0.008575f, 0.010170f, 0.012161f, 0.014023f, + 0.015808f, 0.017792f, 0.020111f, 0.022064f, 0.024414f, 0.026794f, 0.029251f, 0.032074f, 0.034698f, 0.037598f, 0.040741f, 0.043915f, + 0.047577f, 0.051361f, 0.055389f, 0.059692f, 0.064209f, 0.068787f, 0.074585f, 0.079712f, 0.085632f, 0.092346f, 0.099487f, 0.106323f, + 0.114929f, 0.122925f, 0.131958f, 0.141235f, 0.151123f, 0.161865f, 0.172974f, 0.184937f, 0.197632f, 0.210693f, 0.224854f, 0.239136f, + 0.254395f, 0.269531f, 0.285889f, 0.302979f, 0.320557f, 0.338623f, 0.356689f, 0.375977f, 0.395752f, 0.415527f, 0.436523f, 0.458252f, + 0.479248f, 0.501465f, 0.765137f, 0.781738f, 0.783691f, 0.784180f, 0.783203f, 0.781250f, 0.000854f, 0.002817f, 0.004089f, 0.005684f, + 0.007675f, 0.009277f, 0.010864f, 0.012413f, 0.014427f, 0.016235f, 0.017838f, 0.019913f, 0.021805f, 0.023987f, 0.026276f, 0.028915f, + 0.030960f, 0.033875f, 0.036652f, 0.039551f, 0.042816f, 0.045837f, 0.049591f, 0.053589f, 0.057526f, 0.061829f, 0.066650f, 0.071655f, + 0.077393f, 0.083008f, 0.088989f, 0.096008f, 0.103210f, 0.110657f, 0.119141f, 0.127930f, 0.137085f, 0.146973f, 0.157593f, 0.169312f, + 0.181274f, 0.193481f, 0.207031f, 0.220581f, 0.235229f, 0.250732f, 0.266357f, 0.282227f, 0.299805f, 0.317627f, 0.335449f, 0.354736f, + 0.374268f, 0.394531f, 0.415527f, 0.436279f, 0.458252f, 0.481689f, 0.754883f, 0.773438f, 0.775391f, 0.775879f, 0.774902f, 0.773926f, + 0.000852f, 0.002520f, 0.003937f, 0.005527f, 0.006836f, 0.008408f, 0.009773f, 0.011620f, 0.013039f, 0.014687f, 0.016327f, 0.017944f, + 0.019760f, 0.021774f, 0.023697f, 0.025894f, 0.027969f, 0.030121f, 0.032501f, 0.035370f, 0.038208f, 0.041046f, 0.044098f, 0.047791f, + 0.051453f, 0.055176f, 0.059570f, 0.064026f, 0.068787f, 0.074158f, 0.079834f, 0.085938f, 0.092590f, 0.099304f, 0.106873f, 0.114990f, + 0.124023f, 0.133301f, 0.143066f, 0.153687f, 0.164551f, 0.176392f, 0.189209f, 0.202637f, 0.216553f, 0.231323f, 0.246704f, 0.262451f, + 0.279297f, 0.296387f, 0.314697f, 0.333496f, 0.353516f, 0.373047f, 0.394775f, 0.415039f, 0.437500f, 0.460449f, 0.745117f, 0.763672f, + 0.766602f, 0.767090f, 0.767090f, 0.765625f, 0.000762f, 0.002342f, 0.003563f, 0.004787f, 0.006447f, 0.007648f, 0.009193f, 0.010353f, + 0.012016f, 0.013138f, 0.014557f, 0.016312f, 0.017929f, 0.019470f, 0.021103f, 0.023056f, 0.024918f, 0.026886f, 0.029099f, 0.031586f, + 0.034058f, 0.036499f, 0.039307f, 0.042450f, 0.045685f, 0.049072f, 0.052826f, 0.056915f, 0.061096f, 0.065918f, 0.070984f, 0.076538f, + 0.082520f, 0.088928f, 0.095520f, 0.102905f, 0.111206f, 0.119629f, 0.128662f, 0.138184f, 0.148682f, 0.160156f, 0.171997f, 0.184937f, + 0.198364f, 0.212524f, 0.227173f, 0.243042f, 0.259277f, 0.276611f, 0.294189f, 0.312500f, 0.331055f, 0.350830f, 0.372070f, 0.392334f, + 0.415771f, 0.438232f, 0.734375f, 0.754395f, 0.758789f, 0.758789f, 0.758789f, 0.757812f, 0.000848f, 0.002024f, 0.003553f, 0.004646f, + 0.005726f, 0.007050f, 0.008362f, 0.009438f, 0.010536f, 0.011810f, 0.013123f, 0.014481f, 0.015778f, 0.017242f, 0.018753f, 0.020447f, + 0.022278f, 0.023819f, 0.025940f, 0.027771f, 0.029999f, 0.032410f, 0.034851f, 0.037354f, 0.040375f, 0.043610f, 0.046631f, 0.050354f, + 0.054108f, 0.058563f, 0.062805f, 0.067871f, 0.073242f, 0.078796f, 0.085083f, 0.091797f, 0.098816f, 0.106689f, 0.115540f, 0.124207f, + 0.134155f, 0.144409f, 0.155762f, 0.167725f, 0.180664f, 0.193848f, 0.208618f, 0.223389f, 0.239746f, 0.256104f, 0.273438f, 0.291260f, + 0.310059f, 0.330078f, 0.349854f, 0.370850f, 0.393555f, 0.416992f, 0.724121f, 0.744629f, 0.748535f, 0.750000f, 0.749512f, 0.749512f, + 0.000736f, 0.001780f, 0.002937f, 0.004314f, 0.005211f, 0.006214f, 0.007423f, 0.008537f, 0.009392f, 0.010773f, 0.011726f, 0.012970f, + 0.014183f, 0.015373f, 0.016724f, 0.017990f, 0.019730f, 0.021194f, 0.022644f, 0.024368f, 0.026443f, 0.028610f, 0.030685f, 0.032898f, + 0.035583f, 0.038300f, 0.041351f, 0.044556f, 0.047638f, 0.051422f, 0.055359f, 0.059875f, 0.064392f, 0.069580f, 0.075195f, 0.080872f, + 0.087646f, 0.094849f, 0.102173f, 0.110596f, 0.119690f, 0.129761f, 0.139893f, 0.151367f, 0.163452f, 0.176147f, 0.190063f, 0.204590f, + 0.219238f, 0.235718f, 0.252441f, 0.270264f, 0.289062f, 0.307861f, 0.328613f, 0.350098f, 0.372314f, 0.395020f, 0.712402f, 0.734863f, + 0.739746f, 0.740723f, 0.740723f, 0.740234f, 0.000589f, 0.001616f, 0.002674f, 0.003841f, 0.004940f, 0.005676f, 0.006554f, 0.007442f, + 0.008812f, 0.009537f, 0.010277f, 0.011528f, 0.012634f, 0.013527f, 0.014671f, 0.016037f, 0.017136f, 0.018631f, 0.019943f, 0.021530f, + 0.023071f, 0.025146f, 0.026825f, 0.029037f, 0.030853f, 0.033447f, 0.035736f, 0.038849f, 0.041656f, 0.044922f, 0.048462f, 0.052277f, + 0.056519f, 0.061127f, 0.065796f, 0.071411f, 0.077148f, 0.083435f, 0.090393f, 0.097900f, 0.106079f, 0.115356f, 0.125122f, 0.135132f, + 0.146729f, 0.158936f, 0.171509f, 0.185059f, 0.200439f, 0.215576f, 0.232056f, 0.249756f, 0.267822f, 0.286621f, 0.306885f, 0.328125f, + 0.349854f, 0.373291f, 0.701172f, 0.725586f, 0.729980f, 0.730957f, 0.731934f, 0.730957f, 0.000547f, 0.001666f, 0.002367f, 0.003559f, + 0.004238f, 0.005028f, 0.005852f, 0.006859f, 0.007755f, 0.008530f, 0.009163f, 0.010056f, 0.010956f, 0.011978f, 0.013062f, 0.014076f, + 0.015053f, 0.016251f, 0.017471f, 0.018921f, 0.020233f, 0.021774f, 0.023315f, 0.025162f, 0.026871f, 0.029007f, 0.031204f, 0.033661f, + 0.036102f, 0.039062f, 0.042053f, 0.045380f, 0.048859f, 0.053040f, 0.057343f, 0.062225f, 0.067261f, 0.073120f, 0.079407f, 0.086243f, + 0.093567f, 0.101868f, 0.110596f, 0.120239f, 0.130859f, 0.141968f, 0.154053f, 0.167358f, 0.181274f, 0.196045f, 0.212158f, 0.229248f, + 0.247192f, 0.265381f, 0.285400f, 0.305664f, 0.327637f, 0.350586f, 0.689453f, 0.715820f, 0.720215f, 0.722168f, 0.722168f, 0.722168f, + 0.000492f, 0.001634f, 0.002342f, 0.003111f, 0.003866f, 0.004574f, 0.005417f, 0.005928f, 0.006588f, 0.007393f, 0.008041f, 0.008873f, + 0.009689f, 0.010391f, 0.011375f, 0.012146f, 0.013100f, 0.014183f, 0.015274f, 0.016479f, 0.017456f, 0.018768f, 0.020157f, 0.021606f, + 0.023300f, 0.024933f, 0.026855f, 0.028885f, 0.031143f, 0.033417f, 0.036133f, 0.039032f, 0.042236f, 0.045776f, 0.049713f, 0.053680f, + 0.058228f, 0.063232f, 0.069092f, 0.074829f, 0.081482f, 0.089050f, 0.096924f, 0.105591f, 0.115417f, 0.126221f, 0.137329f, 0.149658f, + 0.162964f, 0.176880f, 0.192505f, 0.208740f, 0.226318f, 0.244873f, 0.263428f, 0.283936f, 0.306396f, 0.329346f, 0.676270f, 0.705078f, + 0.709961f, 0.711914f, 0.712891f, 0.711914f, 0.000506f, 0.001342f, 0.002157f, 0.002813f, 0.003353f, 0.004105f, 0.004658f, 0.005344f, + 0.005871f, 0.006538f, 0.007050f, 0.007751f, 0.008247f, 0.009109f, 0.009865f, 0.010559f, 0.011269f, 0.012169f, 0.013290f, 0.014191f, + 0.015015f, 0.016312f, 0.017395f, 0.018570f, 0.019989f, 0.021439f, 0.023102f, 0.024536f, 0.026535f, 0.028702f, 0.030899f, 0.033356f, + 0.035980f, 0.039093f, 0.042328f, 0.046051f, 0.049927f, 0.054199f, 0.059052f, 0.064575f, 0.070496f, 0.076782f, 0.084412f, 0.092285f, + 0.100708f, 0.110779f, 0.121399f, 0.132690f, 0.145508f, 0.158813f, 0.173584f, 0.189453f, 0.205688f, 0.223755f, 0.242554f, 0.263184f, + 0.284180f, 0.306641f, 0.664551f, 0.693848f, 0.699707f, 0.702148f, 0.702637f, 0.703125f, 0.000500f, 0.001122f, 0.001810f, 0.002363f, + 0.002987f, 0.003576f, 0.004158f, 0.004620f, 0.005032f, 0.005627f, 0.006161f, 0.006721f, 0.007179f, 0.007790f, 0.008385f, 0.009163f, + 0.009758f, 0.010536f, 0.011284f, 0.011986f, 0.012878f, 0.013710f, 0.014725f, 0.015823f, 0.016937f, 0.018326f, 0.019547f, 0.020874f, + 0.022522f, 0.024399f, 0.026077f, 0.028427f, 0.030609f, 0.032990f, 0.035736f, 0.038788f, 0.042236f, 0.045990f, 0.050354f, 0.054901f, + 0.059967f, 0.065918f, 0.072205f, 0.079468f, 0.087219f, 0.096252f, 0.105713f, 0.116272f, 0.128174f, 0.140747f, 0.154419f, 0.169556f, + 0.186279f, 0.203125f, 0.221313f, 0.240601f, 0.261719f, 0.284424f, 0.652344f, 0.683105f, 0.688965f, 0.691406f, 0.692383f, 0.693359f, + 0.000482f, 0.001184f, 0.001604f, 0.002171f, 0.002562f, 0.003029f, 0.003656f, 0.003941f, 0.004410f, 0.004948f, 0.005325f, 0.005577f, + 0.006157f, 0.006702f, 0.007172f, 0.007751f, 0.008331f, 0.008904f, 0.009514f, 0.010063f, 0.010925f, 0.011719f, 0.012306f, 0.013321f, + 0.014275f, 0.015465f, 0.016510f, 0.017593f, 0.018845f, 0.020401f, 0.022095f, 0.023682f, 0.025513f, 0.027679f, 0.029968f, 0.032593f, + 0.035461f, 0.038757f, 0.042175f, 0.046326f, 0.050873f, 0.055939f, 0.061462f, 0.067444f, 0.074402f, 0.082520f, 0.091125f, 0.100830f, + 0.111572f, 0.123413f, 0.136719f, 0.150513f, 0.165894f, 0.182251f, 0.200684f, 0.219727f, 0.240234f, 0.261963f, 0.640137f, 0.671387f, + 0.679199f, 0.680664f, 0.682617f, 0.683105f, 0.000501f, 0.000919f, 0.001424f, 0.001853f, 0.002266f, 0.002789f, 0.002998f, 0.003397f, + 0.003902f, 0.004192f, 0.004417f, 0.004974f, 0.005207f, 0.005676f, 0.006134f, 0.006527f, 0.007179f, 0.007465f, 0.008018f, 0.008537f, + 0.009178f, 0.009888f, 0.010544f, 0.011093f, 0.011986f, 0.012794f, 0.013664f, 0.014717f, 0.015747f, 0.016983f, 0.018127f, 0.019470f, + 0.021103f, 0.022919f, 0.024826f, 0.026962f, 0.029358f, 0.031769f, 0.035065f, 0.038239f, 0.042297f, 0.046570f, 0.051422f, 0.056671f, + 0.062805f, 0.069763f, 0.077698f, 0.086182f, 0.095825f, 0.106812f, 0.119080f, 0.132568f, 0.147217f, 0.162598f, 0.180176f, 0.198730f, + 0.218628f, 0.241211f, 0.627441f, 0.660156f, 0.668457f, 0.669922f, 0.672363f, 0.671875f, 0.000235f, 0.001120f, 0.001356f, 0.001651f, + 0.002117f, 0.002441f, 0.002678f, 0.002993f, 0.003244f, 0.003519f, 0.003876f, 0.004086f, 0.004505f, 0.004787f, 0.005085f, 0.005604f, + 0.005985f, 0.006271f, 0.006783f, 0.007145f, 0.007679f, 0.008217f, 0.008728f, 0.009277f, 0.009956f, 0.010605f, 0.011490f, 0.012062f, + 0.013084f, 0.013962f, 0.014984f, 0.016113f, 0.017395f, 0.018829f, 0.020416f, 0.022125f, 0.023972f, 0.025955f, 0.028625f, 0.031616f, + 0.034515f, 0.038147f, 0.042114f, 0.046783f, 0.052094f, 0.058075f, 0.065002f, 0.072510f, 0.081604f, 0.091125f, 0.102539f, 0.114807f, + 0.128662f, 0.143921f, 0.160034f, 0.178467f, 0.198364f, 0.218750f, 0.613281f, 0.648926f, 0.657227f, 0.659668f, 0.661621f, 0.661621f, + 0.000382f, 0.000704f, 0.001099f, 0.001557f, 0.001774f, 0.001976f, 0.002132f, 0.002575f, 0.002634f, 0.002916f, 0.003103f, 0.003494f, + 0.003754f, 0.003956f, 0.004269f, 0.004684f, 0.004902f, 0.005234f, 0.005569f, 0.005890f, 0.006416f, 0.006786f, 0.007160f, 0.007645f, + 0.008118f, 0.008781f, 0.009346f, 0.010025f, 0.010658f, 0.011475f, 0.012230f, 0.013016f, 0.014122f, 0.015251f, 0.016342f, 0.017807f, + 0.019424f, 0.021103f, 0.023026f, 0.025436f, 0.027817f, 0.030914f, 0.034210f, 0.037750f, 0.042450f, 0.047455f, 0.053101f, 0.059998f, + 0.067688f, 0.076660f, 0.086670f, 0.097961f, 0.110779f, 0.125366f, 0.140747f, 0.158081f, 0.176880f, 0.197632f, 0.600098f, 0.637207f, + 0.644531f, 0.647949f, 0.649414f, 0.651855f, 0.000182f, 0.000738f, 0.000942f, 0.001220f, 0.001469f, 0.001634f, 0.001820f, 0.002005f, + 0.002291f, 0.002441f, 0.002636f, 0.002832f, 0.003019f, 0.003242f, 0.003502f, 0.003824f, 0.004017f, 0.004333f, 0.004570f, 0.004883f, + 0.005173f, 0.005615f, 0.005909f, 0.006317f, 0.006649f, 0.007160f, 0.007656f, 0.008156f, 0.008583f, 0.009209f, 0.009857f, 0.010696f, + 0.011322f, 0.012367f, 0.013229f, 0.014259f, 0.015686f, 0.016815f, 0.018402f, 0.020126f, 0.022095f, 0.024414f, 0.027176f, 0.030273f, + 0.033722f, 0.038086f, 0.042969f, 0.048645f, 0.055237f, 0.063171f, 0.071960f, 0.082031f, 0.093994f, 0.107300f, 0.122131f, 0.138550f, + 0.156494f, 0.177002f, 0.586426f, 0.625488f, 0.633789f, 0.637207f, 0.638672f, 0.639648f, 0.000199f, 0.000534f, 0.000745f, 0.000995f, + 0.001190f, 0.001387f, 0.001516f, 0.001691f, 0.001790f, 0.001941f, 0.002214f, 0.002346f, 0.002449f, 0.002686f, 0.002832f, 0.003042f, + 0.003304f, 0.003531f, 0.003662f, 0.003952f, 0.004181f, 0.004517f, 0.004704f, 0.005074f, 0.005352f, 0.005718f, 0.006096f, 0.006481f, + 0.006947f, 0.007454f, 0.007988f, 0.008484f, 0.009140f, 0.009804f, 0.010475f, 0.011307f, 0.012299f, 0.013268f, 0.014511f, 0.015823f, + 0.017410f, 0.018936f, 0.021225f, 0.023621f, 0.026367f, 0.029770f, 0.033661f, 0.038452f, 0.044067f, 0.050812f, 0.058411f, 0.067444f, + 0.077942f, 0.090149f, 0.104187f, 0.119812f, 0.137085f, 0.156372f, 0.572754f, 0.613770f, 0.621582f, 0.625977f, 0.627441f, 0.628906f, + 0.000165f, 0.000486f, 0.000618f, 0.000880f, 0.001063f, 0.001140f, 0.001258f, 0.001464f, 0.001498f, 0.001561f, 0.001707f, 0.001899f, + 0.001976f, 0.002171f, 0.002285f, 0.002474f, 0.002571f, 0.002764f, 0.002968f, 0.003170f, 0.003389f, 0.003580f, 0.003822f, 0.004036f, + 0.004269f, 0.004505f, 0.004738f, 0.005157f, 0.005474f, 0.005821f, 0.006279f, 0.006649f, 0.007107f, 0.007610f, 0.008240f, 0.008835f, + 0.009598f, 0.010361f, 0.011276f, 0.012299f, 0.013466f, 0.014740f, 0.016251f, 0.018021f, 0.020294f, 0.022797f, 0.025833f, 0.029739f, + 0.034058f, 0.039612f, 0.046021f, 0.053833f, 0.063110f, 0.074158f, 0.086914f, 0.101562f, 0.118164f, 0.136841f, 0.558594f, 0.601074f, + 0.608887f, 0.613281f, 0.615234f, 0.617188f, 0.000096f, 0.000348f, 0.000585f, 0.000707f, 0.000837f, 0.000866f, 0.000972f, 0.001095f, + 0.001198f, 0.001309f, 0.001355f, 0.001417f, 0.001615f, 0.001740f, 0.001863f, 0.001880f, 0.002048f, 0.002159f, 0.002380f, 0.002487f, + 0.002613f, 0.002777f, 0.003000f, 0.003143f, 0.003353f, 0.003521f, 0.003748f, 0.003963f, 0.004265f, 0.004490f, 0.004776f, 0.005093f, + 0.005577f, 0.005966f, 0.006321f, 0.006828f, 0.007320f, 0.007904f, 0.008575f, 0.009392f, 0.010231f, 0.011276f, 0.012321f, 0.013832f, + 0.015343f, 0.017242f, 0.019501f, 0.022247f, 0.025696f, 0.029922f, 0.035187f, 0.041779f, 0.049683f, 0.059387f, 0.070801f, 0.084106f, + 0.100037f, 0.117798f, 0.544434f, 0.588867f, 0.597656f, 0.602539f, 0.604492f, 0.605469f, 0.000123f, 0.000248f, 0.000443f, 0.000625f, + 0.000663f, 0.000733f, 0.000843f, 0.000780f, 0.000921f, 0.000986f, 0.001081f, 0.001178f, 0.001254f, 0.001348f, 0.001364f, 0.001515f, + 0.001565f, 0.001705f, 0.001824f, 0.001870f, 0.002066f, 0.002155f, 0.002274f, 0.002422f, 0.002525f, 0.002695f, 0.002863f, 0.003038f, + 0.003271f, 0.003441f, 0.003736f, 0.003901f, 0.004112f, 0.004478f, 0.004719f, 0.005093f, 0.005482f, 0.005913f, 0.006413f, 0.007019f, + 0.007626f, 0.008408f, 0.009201f, 0.010201f, 0.011436f, 0.012749f, 0.014389f, 0.016373f, 0.018906f, 0.022034f, 0.025909f, 0.031082f, + 0.037628f, 0.045715f, 0.055939f, 0.068176f, 0.082764f, 0.099365f, 0.529785f, 0.574707f, 0.584961f, 0.589844f, 0.591797f, 0.593750f, + 0.000210f, 0.000212f, 0.000365f, 0.000494f, 0.000438f, 0.000597f, 0.000538f, 0.000623f, 0.000638f, 0.000736f, 0.000866f, 0.000882f, + 0.000954f, 0.001040f, 0.001070f, 0.001086f, 0.001220f, 0.001274f, 0.001341f, 0.001457f, 0.001513f, 0.001598f, 0.001697f, 0.001781f, + 0.001898f, 0.001970f, 0.002131f, 0.002241f, 0.002401f, 0.002645f, 0.002783f, 0.002892f, 0.003120f, 0.003347f, 0.003508f, 0.003757f, + 0.004032f, 0.004314f, 0.004688f, 0.005066f, 0.005520f, 0.006012f, 0.006702f, 0.007332f, 0.008171f, 0.009140f, 0.010399f, 0.011787f, + 0.013496f, 0.015732f, 0.018509f, 0.022278f, 0.027267f, 0.033813f, 0.042328f, 0.053070f, 0.066406f, 0.082825f, 0.516602f, 0.562500f, + 0.573242f, 0.577637f, 0.580078f, 0.581543f, 0.000000f, 0.000216f, 0.000281f, 0.000346f, 0.000374f, 0.000388f, 0.000491f, 0.000416f, + 0.000516f, 0.000535f, 0.000635f, 0.000625f, 0.000681f, 0.000719f, 0.000790f, 0.000813f, 0.000879f, 0.000926f, 0.000968f, 0.001004f, + 0.001097f, 0.001135f, 0.001229f, 0.001300f, 0.001361f, 0.001431f, 0.001541f, 0.001610f, 0.001711f, 0.001802f, 0.001922f, 0.002094f, + 0.002169f, 0.002346f, 0.002468f, 0.002644f, 0.002844f, 0.003094f, 0.003368f, 0.003586f, 0.003883f, 0.004223f, 0.004662f, 0.005093f, + 0.005680f, 0.006348f, 0.007206f, 0.008202f, 0.009392f, 0.010895f, 0.012939f, 0.015465f, 0.018906f, 0.023682f, 0.030502f, 0.039825f, + 0.051331f, 0.066528f, 0.500977f, 0.548828f, 0.560059f, 0.564453f, 0.567871f, 0.569336f, 0.000000f, 0.000106f, 0.000201f, 0.000252f, + 0.000251f, 0.000322f, 0.000281f, 0.000340f, 0.000359f, 0.000428f, 0.000443f, 0.000419f, 0.000444f, 0.000500f, 0.000524f, 0.000590f, + 0.000574f, 0.000650f, 0.000693f, 0.000732f, 0.000778f, 0.000821f, 0.000848f, 0.000900f, 0.000965f, 0.000982f, 0.001072f, 0.001109f, + 0.001169f, 0.001307f, 0.001301f, 0.001409f, 0.001483f, 0.001610f, 0.001734f, 0.001835f, 0.001940f, 0.002098f, 0.002241f, 0.002426f, + 0.002634f, 0.002865f, 0.003136f, 0.003431f, 0.003763f, 0.004211f, 0.004742f, 0.005417f, 0.006229f, 0.007298f, 0.008621f, 0.010330f, + 0.012650f, 0.015808f, 0.020569f, 0.027908f, 0.037994f, 0.051514f, 0.485840f, 0.536133f, 0.547363f, 0.551758f, 0.554688f, 0.557617f, + 0.000026f, 0.000156f, 0.000201f, 0.000136f, 0.000188f, 0.000187f, 0.000192f, 0.000240f, 0.000245f, 0.000254f, 0.000262f, 0.000311f, + 0.000309f, 0.000331f, 0.000374f, 0.000385f, 0.000411f, 0.000431f, 0.000443f, 0.000461f, 0.000507f, 0.000522f, 0.000562f, 0.000596f, + 0.000634f, 0.000684f, 0.000718f, 0.000735f, 0.000776f, 0.000815f, 0.000875f, 0.000927f, 0.000982f, 0.001053f, 0.001123f, 0.001162f, + 0.001271f, 0.001346f, 0.001473f, 0.001577f, 0.001670f, 0.001838f, 0.002005f, 0.002161f, 0.002405f, 0.002670f, 0.002993f, 0.003399f, + 0.003860f, 0.004528f, 0.005386f, 0.006523f, 0.008003f, 0.010063f, 0.013206f, 0.017990f, 0.026031f, 0.038086f, 0.471191f, 0.522949f, + 0.534668f, 0.540039f, 0.543457f, 0.544922f, 0.000000f, 0.000093f, 0.000084f, 0.000085f, 0.000124f, 0.000145f, 0.000122f, 0.000149f, + 0.000152f, 0.000152f, 0.000158f, 0.000167f, 0.000186f, 0.000209f, 0.000217f, 0.000225f, 0.000231f, 0.000272f, 0.000273f, 0.000301f, + 0.000303f, 0.000310f, 0.000338f, 0.000361f, 0.000387f, 0.000423f, 0.000413f, 0.000436f, 0.000478f, 0.000503f, 0.000525f, 0.000570f, + 0.000608f, 0.000626f, 0.000677f, 0.000706f, 0.000753f, 0.000813f, 0.000884f, 0.000929f, 0.001000f, 0.001094f, 0.001183f, 0.001302f, + 0.001412f, 0.001563f, 0.001769f, 0.001974f, 0.002277f, 0.002626f, 0.003124f, 0.003761f, 0.004665f, 0.005993f, 0.007935f, 0.010818f, + 0.016205f, 0.026138f, 0.456299f, 0.509277f, 0.520996f, 0.527344f, 0.530762f, 0.532715f, 0.000105f, 0.000083f, 0.000072f, 0.000065f, + 0.000071f, 0.000072f, 0.000077f, 0.000084f, 0.000088f, 0.000093f, 0.000095f, 0.000120f, 0.000100f, 0.000108f, 0.000126f, 0.000118f, + 0.000139f, 0.000149f, 0.000153f, 0.000165f, 0.000169f, 0.000172f, 0.000194f, 0.000203f, 0.000233f, 0.000225f, 0.000233f, 0.000253f, + 0.000266f, 0.000275f, 0.000299f, 0.000319f, 0.000338f, 0.000345f, 0.000374f, 0.000384f, 0.000415f, 0.000448f, 0.000483f, 0.000511f, + 0.000543f, 0.000585f, 0.000647f, 0.000692f, 0.000755f, 0.000827f, 0.000924f, 0.001041f, 0.001186f, 0.001372f, 0.001608f, 0.001953f, + 0.002411f, 0.003098f, 0.004238f, 0.005989f, 0.009003f, 0.016006f, 0.441406f, 0.495361f, 0.508301f, 0.514160f, 0.518066f, 0.520508f, + 0.000090f, 0.000067f, 0.000058f, 0.000052f, 0.000047f, 0.000044f, 0.000044f, 0.000040f, 0.000042f, 0.000049f, 0.000042f, 0.000045f, + 0.000059f, 0.000047f, 0.000050f, 0.000054f, 0.000071f, 0.000073f, 0.000075f, 0.000078f, 0.000079f, 0.000084f, 0.000087f, 0.000090f, + 0.000097f, 0.000109f, 0.000108f, 0.000124f, 0.000124f, 0.000131f, 0.000138f, 0.000143f, 0.000155f, 0.000164f, 0.000178f, 0.000182f, + 0.000192f, 0.000209f, 0.000225f, 0.000244f, 0.000259f, 0.000274f, 0.000303f, 0.000321f, 0.000357f, 0.000385f, 0.000429f, 0.000470f, + 0.000537f, 0.000608f, 0.000710f, 0.000852f, 0.001052f, 0.001371f, 0.001877f, 0.002762f, 0.004406f, 0.008202f, 0.426270f, 0.483154f, + 0.495605f, 0.500977f, 0.505371f, 0.507324f, 0.000067f, 0.000047f, 0.000039f, 0.000035f, 0.000032f, 0.000030f, 0.000029f, 0.000027f, + 0.000026f, 0.000025f, 0.000024f, 0.000023f, 0.000021f, 0.000020f, 0.000019f, 0.000021f, 0.000020f, 0.000024f, 0.000028f, 0.000030f, + 0.000029f, 0.000032f, 0.000035f, 0.000034f, 0.000036f, 0.000044f, 0.000046f, 0.000040f, 0.000048f, 0.000047f, 0.000051f, 0.000053f, + 0.000059f, 0.000059f, 0.000064f, 0.000066f, 0.000077f, 0.000079f, 0.000081f, 0.000091f, 0.000094f, 0.000100f, 0.000108f, 0.000119f, + 0.000129f, 0.000137f, 0.000148f, 0.000173f, 0.000191f, 0.000210f, 0.000249f, 0.000292f, 0.000357f, 0.000448f, 0.000629f, 0.000943f, + 0.001630f, 0.003332f, 0.411377f, 0.468506f, 0.482910f, 0.488770f, 0.492188f, 0.495117f, 0.000025f, 0.000018f, 0.000015f, 0.000013f, + 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, + 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000008f, 0.000008f, 0.000007f, + 0.000008f, 0.000010f, 0.000010f, 0.000010f, 0.000012f, 0.000014f, 0.000014f, 0.000014f, 0.000016f, 0.000018f, 0.000019f, 0.000021f, + 0.000020f, 0.000023f, 0.000025f, 0.000027f, 0.000027f, 0.000029f, 0.000035f, 0.000033f, 0.000040f, 0.000044f, 0.000052f, 0.000061f, + 0.000069f, 0.000087f, 0.000117f, 0.000174f, 0.000319f, 0.000847f, 0.395996f, 0.454834f, 0.468750f, 0.475586f, 0.479004f, 0.481689f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, + 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, + 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000004f, 0.000005f, 0.000009f, 0.000027f, 0.381348f, 0.441406f, + 0.455566f, 0.462891f, 0.466309f, 0.468994f, + }, + { + 0.016769f, 0.050629f, 0.083740f, 0.116638f, 0.148071f, 0.178955f, 0.208374f, 0.236938f, 0.265137f, 0.291992f, 0.317871f, 0.343994f, + 0.368164f, 0.391846f, 0.415527f, 0.437988f, 0.459717f, 0.480469f, 0.501465f, 0.520996f, 0.540527f, 0.559082f, 0.577637f, 0.594727f, + 0.612305f, 0.628418f, 0.644531f, 0.661133f, 0.676270f, 0.691406f, 0.705566f, 0.719727f, 0.734375f, 0.747070f, 0.760254f, 0.773438f, + 0.786133f, 0.798828f, 0.810059f, 0.821777f, 0.833008f, 0.843262f, 0.854492f, 0.865234f, 0.875488f, 0.885254f, 0.895508f, 0.904297f, + 0.913574f, 0.923340f, 0.932617f, 0.940918f, 0.949707f, 0.958008f, 0.966309f, 0.974609f, 0.981934f, 0.990234f, 0.985352f, 0.965332f, + 0.950195f, 0.937500f, 0.926270f, 0.915527f, 0.015083f, 0.045929f, 0.075806f, 0.105408f, 0.135254f, 0.163208f, 0.191772f, 0.219238f, + 0.245239f, 0.271973f, 0.297363f, 0.321045f, 0.345947f, 0.369141f, 0.391846f, 0.414062f, 0.435791f, 0.456787f, 0.477295f, 0.497314f, + 0.516113f, 0.535645f, 0.554199f, 0.571777f, 0.588867f, 0.606445f, 0.623047f, 0.639160f, 0.654785f, 0.669434f, 0.685059f, 0.699219f, + 0.713379f, 0.728027f, 0.741211f, 0.754883f, 0.767578f, 0.780273f, 0.792480f, 0.804688f, 0.815918f, 0.826660f, 0.838867f, 0.850098f, + 0.859863f, 0.871094f, 0.880859f, 0.891113f, 0.900879f, 0.909180f, 0.919434f, 0.929688f, 0.937500f, 0.946289f, 0.954590f, 0.963379f, + 0.971191f, 0.979004f, 0.980469f, 0.961426f, 0.947266f, 0.935059f, 0.924316f, 0.914062f, 0.013573f, 0.040955f, 0.068848f, 0.096313f, + 0.123169f, 0.150635f, 0.175537f, 0.202026f, 0.228271f, 0.251709f, 0.276367f, 0.300781f, 0.323730f, 0.347168f, 0.369385f, 0.390625f, + 0.412354f, 0.433594f, 0.454346f, 0.473145f, 0.491943f, 0.512207f, 0.529785f, 0.549316f, 0.566406f, 0.583008f, 0.600586f, 0.616211f, + 0.633301f, 0.648438f, 0.663574f, 0.679199f, 0.693359f, 0.708008f, 0.721680f, 0.735840f, 0.748535f, 0.762207f, 0.773926f, 0.786621f, + 0.798340f, 0.811035f, 0.822754f, 0.833984f, 0.845215f, 0.855957f, 0.865723f, 0.876465f, 0.886719f, 0.895508f, 0.906738f, 0.916016f, + 0.925293f, 0.934570f, 0.943848f, 0.952148f, 0.960449f, 0.969238f, 0.976074f, 0.958008f, 0.944336f, 0.932617f, 0.921875f, 0.912109f, + 0.012329f, 0.037201f, 0.062164f, 0.087646f, 0.112488f, 0.137451f, 0.161865f, 0.187134f, 0.210938f, 0.234253f, 0.258301f, 0.281006f, + 0.303467f, 0.325195f, 0.347656f, 0.368652f, 0.389648f, 0.410400f, 0.430664f, 0.450928f, 0.470215f, 0.488770f, 0.507812f, 0.525391f, + 0.543457f, 0.560059f, 0.579102f, 0.593750f, 0.611816f, 0.627441f, 0.643066f, 0.658203f, 0.672363f, 0.687500f, 0.702148f, 0.715820f, + 0.729004f, 0.742676f, 0.755371f, 0.768066f, 0.781738f, 0.792969f, 0.805176f, 0.816895f, 0.829102f, 0.839844f, 0.850586f, 0.861816f, + 0.872559f, 0.882812f, 0.893066f, 0.902832f, 0.912109f, 0.921875f, 0.930664f, 0.940430f, 0.948242f, 0.958008f, 0.970703f, 0.953613f, + 0.940430f, 0.929199f, 0.919434f, 0.910156f, 0.010979f, 0.033752f, 0.056763f, 0.080139f, 0.103516f, 0.126221f, 0.149414f, 0.172485f, + 0.195435f, 0.218262f, 0.240356f, 0.261719f, 0.284180f, 0.306396f, 0.326416f, 0.347900f, 0.368408f, 0.389160f, 0.408691f, 0.427979f, + 0.447754f, 0.467041f, 0.484863f, 0.502441f, 0.520996f, 0.538086f, 0.555664f, 0.573242f, 0.589355f, 0.604980f, 0.622559f, 0.637207f, + 0.652832f, 0.666992f, 0.680664f, 0.695801f, 0.710938f, 0.724121f, 0.737305f, 0.750977f, 0.763672f, 0.776855f, 0.789062f, 0.799805f, + 0.812012f, 0.824219f, 0.835449f, 0.846680f, 0.857910f, 0.868164f, 0.878418f, 0.889160f, 0.898926f, 0.909180f, 0.917969f, 0.928223f, + 0.937012f, 0.946777f, 0.965820f, 0.949707f, 0.937012f, 0.926270f, 0.916504f, 0.907715f, 0.009941f, 0.030746f, 0.051514f, 0.073181f, + 0.094116f, 0.116028f, 0.137817f, 0.158691f, 0.180664f, 0.202637f, 0.223511f, 0.244873f, 0.265869f, 0.285889f, 0.307129f, 0.327881f, + 0.347412f, 0.367188f, 0.387207f, 0.405762f, 0.425537f, 0.444092f, 0.462646f, 0.481201f, 0.499756f, 0.516602f, 0.533691f, 0.550781f, + 0.567383f, 0.583984f, 0.599609f, 0.616211f, 0.630859f, 0.647461f, 0.661621f, 0.676758f, 0.689453f, 0.704590f, 0.718750f, 0.731934f, + 0.745117f, 0.757812f, 0.770996f, 0.783691f, 0.796387f, 0.807617f, 0.819824f, 0.831543f, 0.842773f, 0.854004f, 0.864258f, 0.875488f, + 0.885742f, 0.895508f, 0.905762f, 0.915527f, 0.925781f, 0.934570f, 0.960449f, 0.945312f, 0.933594f, 0.922852f, 0.913574f, 0.905273f, + 0.009003f, 0.027756f, 0.046997f, 0.066711f, 0.085999f, 0.106506f, 0.127075f, 0.146973f, 0.166992f, 0.187500f, 0.207886f, 0.228149f, + 0.248169f, 0.268311f, 0.287842f, 0.307861f, 0.327393f, 0.347656f, 0.365967f, 0.385010f, 0.404541f, 0.422363f, 0.441162f, 0.458740f, + 0.477783f, 0.495117f, 0.512207f, 0.529297f, 0.546387f, 0.562012f, 0.578613f, 0.595215f, 0.610840f, 0.625977f, 0.641113f, 0.656738f, + 0.670410f, 0.685059f, 0.699707f, 0.714355f, 0.727051f, 0.741699f, 0.752441f, 0.767090f, 0.778809f, 0.791504f, 0.803711f, 0.815430f, + 0.827148f, 0.838867f, 0.850098f, 0.860840f, 0.872070f, 0.881836f, 0.893066f, 0.903809f, 0.913574f, 0.923828f, 0.955078f, 0.940918f, + 0.929199f, 0.919922f, 0.911133f, 0.902344f, 0.008469f, 0.025375f, 0.043121f, 0.060944f, 0.079468f, 0.097961f, 0.116394f, 0.135620f, + 0.154541f, 0.174072f, 0.193115f, 0.212280f, 0.231689f, 0.250732f, 0.270264f, 0.289307f, 0.307861f, 0.327148f, 0.345215f, 0.364990f, + 0.382812f, 0.401123f, 0.418945f, 0.437012f, 0.455811f, 0.472900f, 0.490234f, 0.507812f, 0.524414f, 0.541016f, 0.558105f, 0.573242f, + 0.590332f, 0.605469f, 0.620117f, 0.636230f, 0.651367f, 0.665039f, 0.679688f, 0.694336f, 0.708496f, 0.722168f, 0.735840f, 0.750000f, + 0.762695f, 0.774902f, 0.787598f, 0.798828f, 0.811523f, 0.823730f, 0.834473f, 0.846191f, 0.857910f, 0.868652f, 0.879883f, 0.891113f, + 0.900391f, 0.911133f, 0.949219f, 0.937012f, 0.925293f, 0.916016f, 0.907227f, 0.899414f, 0.007618f, 0.023178f, 0.039490f, 0.055542f, + 0.072937f, 0.090271f, 0.107605f, 0.125122f, 0.142944f, 0.160889f, 0.178955f, 0.197510f, 0.216553f, 0.234497f, 0.252686f, 0.271240f, + 0.289795f, 0.307861f, 0.326172f, 0.344238f, 0.362549f, 0.380859f, 0.398438f, 0.416504f, 0.433838f, 0.452393f, 0.468994f, 0.485840f, + 0.502930f, 0.519531f, 0.536133f, 0.553223f, 0.569336f, 0.584473f, 0.599609f, 0.615234f, 0.631348f, 0.646484f, 0.659668f, 0.675293f, + 0.689941f, 0.703125f, 0.716797f, 0.730957f, 0.744141f, 0.756836f, 0.771484f, 0.782227f, 0.795898f, 0.807617f, 0.819824f, 0.831543f, + 0.843750f, 0.854980f, 0.866211f, 0.877441f, 0.888672f, 0.898438f, 0.943359f, 0.931641f, 0.921387f, 0.912109f, 0.903809f, 0.896484f, + 0.007118f, 0.021255f, 0.035889f, 0.051514f, 0.066895f, 0.083191f, 0.098999f, 0.115540f, 0.132324f, 0.149292f, 0.166260f, 0.183716f, + 0.200928f, 0.218628f, 0.236084f, 0.253906f, 0.272217f, 0.289795f, 0.307617f, 0.325439f, 0.342529f, 0.360596f, 0.378906f, 0.395996f, + 0.413330f, 0.430908f, 0.447510f, 0.465332f, 0.481934f, 0.497803f, 0.514648f, 0.531738f, 0.547852f, 0.562988f, 0.579102f, 0.595215f, + 0.610840f, 0.625977f, 0.641113f, 0.655273f, 0.670410f, 0.685059f, 0.698730f, 0.712891f, 0.726074f, 0.739258f, 0.753418f, 0.766113f, + 0.779785f, 0.791992f, 0.803711f, 0.816406f, 0.829102f, 0.839844f, 0.852539f, 0.863770f, 0.874512f, 0.886719f, 0.937988f, 0.926758f, + 0.917480f, 0.908203f, 0.900391f, 0.893066f, 0.006481f, 0.019775f, 0.032928f, 0.047272f, 0.061371f, 0.076233f, 0.091064f, 0.107117f, + 0.122559f, 0.138062f, 0.154663f, 0.170532f, 0.187256f, 0.204346f, 0.220947f, 0.237915f, 0.254883f, 0.272217f, 0.289062f, 0.306641f, + 0.323730f, 0.341064f, 0.358643f, 0.375732f, 0.393555f, 0.410645f, 0.426758f, 0.444580f, 0.461182f, 0.477783f, 0.494141f, 0.510254f, + 0.526855f, 0.543457f, 0.559082f, 0.574219f, 0.590332f, 0.605957f, 0.621094f, 0.634766f, 0.650879f, 0.665039f, 0.679688f, 0.694824f, + 0.708008f, 0.722656f, 0.736816f, 0.749023f, 0.762695f, 0.775391f, 0.788086f, 0.801270f, 0.813965f, 0.826172f, 0.838379f, 0.849121f, + 0.861328f, 0.873535f, 0.932129f, 0.921875f, 0.912598f, 0.904297f, 0.896484f, 0.889160f, 0.005924f, 0.017899f, 0.030426f, 0.043427f, + 0.056824f, 0.070435f, 0.084106f, 0.098755f, 0.112976f, 0.128052f, 0.143311f, 0.158936f, 0.174072f, 0.189575f, 0.206421f, 0.222534f, + 0.238403f, 0.255615f, 0.271729f, 0.288818f, 0.305908f, 0.322021f, 0.339355f, 0.356445f, 0.373291f, 0.390137f, 0.407227f, 0.423584f, + 0.440430f, 0.457031f, 0.472900f, 0.489502f, 0.506836f, 0.521973f, 0.538574f, 0.554688f, 0.570312f, 0.585449f, 0.601074f, 0.616211f, + 0.631348f, 0.646484f, 0.661621f, 0.675781f, 0.690430f, 0.704590f, 0.717285f, 0.731934f, 0.746094f, 0.759277f, 0.771973f, 0.785156f, + 0.798340f, 0.810547f, 0.823242f, 0.835938f, 0.848145f, 0.860352f, 0.925781f, 0.916504f, 0.908203f, 0.900391f, 0.893066f, 0.886719f, + 0.005573f, 0.016693f, 0.028366f, 0.040192f, 0.052277f, 0.064880f, 0.078064f, 0.090698f, 0.105042f, 0.118591f, 0.133057f, 0.147461f, + 0.162231f, 0.177612f, 0.192383f, 0.207886f, 0.223633f, 0.239502f, 0.255615f, 0.272217f, 0.288330f, 0.304932f, 0.320312f, 0.337646f, + 0.354004f, 0.369873f, 0.386719f, 0.403320f, 0.419922f, 0.437012f, 0.453369f, 0.469482f, 0.485596f, 0.501465f, 0.517578f, 0.534180f, + 0.549316f, 0.565918f, 0.581055f, 0.595703f, 0.611328f, 0.626953f, 0.641602f, 0.657227f, 0.671387f, 0.686523f, 0.699707f, 0.714355f, + 0.729004f, 0.742676f, 0.756348f, 0.769043f, 0.782715f, 0.795410f, 0.809082f, 0.821289f, 0.833984f, 0.846680f, 0.919434f, 0.911133f, + 0.903320f, 0.895508f, 0.888672f, 0.882324f, 0.005016f, 0.015396f, 0.026169f, 0.037231f, 0.048126f, 0.059937f, 0.071716f, 0.084167f, + 0.096680f, 0.109558f, 0.123169f, 0.136719f, 0.150269f, 0.164917f, 0.179077f, 0.194580f, 0.208984f, 0.223877f, 0.239746f, 0.255127f, + 0.270996f, 0.286377f, 0.302490f, 0.319336f, 0.335205f, 0.351318f, 0.367432f, 0.383545f, 0.399902f, 0.415771f, 0.432373f, 0.448975f, + 0.465088f, 0.481934f, 0.497314f, 0.513672f, 0.529785f, 0.544434f, 0.561035f, 0.576660f, 0.592285f, 0.607422f, 0.622559f, 0.638184f, + 0.652344f, 0.667480f, 0.681641f, 0.696777f, 0.711426f, 0.725586f, 0.738770f, 0.753418f, 0.766602f, 0.779297f, 0.793945f, 0.807129f, + 0.819824f, 0.833008f, 0.913086f, 0.906738f, 0.898438f, 0.890625f, 0.884277f, 0.878418f, 0.004738f, 0.014053f, 0.024017f, 0.033752f, + 0.044495f, 0.055328f, 0.066467f, 0.078064f, 0.089661f, 0.102051f, 0.114258f, 0.126831f, 0.139771f, 0.153564f, 0.167114f, 0.181030f, + 0.195190f, 0.209839f, 0.224731f, 0.239136f, 0.253906f, 0.269531f, 0.285156f, 0.300293f, 0.317139f, 0.332520f, 0.348145f, 0.364990f, + 0.380859f, 0.396240f, 0.412109f, 0.428711f, 0.444336f, 0.460938f, 0.477295f, 0.492676f, 0.509277f, 0.524902f, 0.540527f, 0.556641f, + 0.572266f, 0.587402f, 0.604004f, 0.618164f, 0.633301f, 0.648438f, 0.664062f, 0.678223f, 0.693359f, 0.708008f, 0.722656f, 0.736328f, + 0.750000f, 0.764160f, 0.777832f, 0.791016f, 0.805176f, 0.817871f, 0.907227f, 0.900879f, 0.894043f, 0.886719f, 0.880371f, 0.874512f, + 0.004105f, 0.012741f, 0.022491f, 0.031769f, 0.041107f, 0.051208f, 0.061249f, 0.071777f, 0.083069f, 0.093811f, 0.105896f, 0.117554f, + 0.129761f, 0.142212f, 0.155273f, 0.168579f, 0.182251f, 0.196167f, 0.210449f, 0.223755f, 0.238525f, 0.253662f, 0.268799f, 0.283447f, + 0.298828f, 0.313965f, 0.329834f, 0.344971f, 0.361328f, 0.376953f, 0.393066f, 0.408691f, 0.424561f, 0.441406f, 0.457031f, 0.472656f, + 0.488770f, 0.504883f, 0.520996f, 0.536133f, 0.551758f, 0.567871f, 0.583496f, 0.599121f, 0.614258f, 0.629395f, 0.645996f, 0.660156f, + 0.675781f, 0.689453f, 0.704102f, 0.719727f, 0.733398f, 0.747559f, 0.761719f, 0.776367f, 0.789062f, 0.803223f, 0.899902f, 0.895020f, + 0.888184f, 0.881836f, 0.875488f, 0.870117f, 0.003925f, 0.011978f, 0.020538f, 0.028763f, 0.038269f, 0.047028f, 0.056732f, 0.066223f, + 0.076904f, 0.086731f, 0.097900f, 0.109314f, 0.120483f, 0.132324f, 0.144653f, 0.156982f, 0.169678f, 0.183228f, 0.196289f, 0.209961f, + 0.223633f, 0.237427f, 0.251953f, 0.266602f, 0.281982f, 0.296875f, 0.312012f, 0.326660f, 0.342041f, 0.357910f, 0.373779f, 0.389404f, + 0.404785f, 0.420166f, 0.436768f, 0.452637f, 0.468506f, 0.484863f, 0.500977f, 0.516602f, 0.531738f, 0.546875f, 0.563965f, 0.579102f, + 0.595215f, 0.610840f, 0.625977f, 0.641602f, 0.657227f, 0.671387f, 0.687500f, 0.702148f, 0.716309f, 0.731445f, 0.746094f, 0.760742f, + 0.774414f, 0.788086f, 0.893066f, 0.889648f, 0.882812f, 0.876953f, 0.870605f, 0.865723f, 0.003704f, 0.011169f, 0.019165f, 0.026550f, + 0.035339f, 0.043488f, 0.052277f, 0.061066f, 0.071045f, 0.080933f, 0.090576f, 0.101074f, 0.111877f, 0.122925f, 0.134277f, 0.146118f, + 0.157837f, 0.170288f, 0.183105f, 0.195557f, 0.209351f, 0.222900f, 0.236328f, 0.250732f, 0.264893f, 0.279297f, 0.294189f, 0.308838f, + 0.323975f, 0.339844f, 0.354736f, 0.370117f, 0.385986f, 0.401367f, 0.416504f, 0.432861f, 0.448486f, 0.463867f, 0.480469f, 0.497070f, + 0.511719f, 0.527832f, 0.544434f, 0.559570f, 0.575684f, 0.591797f, 0.606934f, 0.623047f, 0.638184f, 0.654297f, 0.668945f, 0.684570f, + 0.699219f, 0.714355f, 0.729492f, 0.744629f, 0.758789f, 0.773926f, 0.886230f, 0.883301f, 0.877441f, 0.871582f, 0.866211f, 0.860840f, + 0.003500f, 0.010292f, 0.017395f, 0.024963f, 0.032440f, 0.040344f, 0.048462f, 0.057098f, 0.065063f, 0.074646f, 0.083679f, 0.093445f, + 0.103882f, 0.114136f, 0.124451f, 0.135498f, 0.146606f, 0.158447f, 0.170410f, 0.182739f, 0.195435f, 0.208008f, 0.221558f, 0.234863f, + 0.248657f, 0.262695f, 0.276855f, 0.291748f, 0.306152f, 0.320801f, 0.335693f, 0.350830f, 0.365967f, 0.382080f, 0.396973f, 0.413330f, + 0.429199f, 0.444336f, 0.459473f, 0.476074f, 0.492188f, 0.507812f, 0.524414f, 0.540039f, 0.555664f, 0.571777f, 0.586914f, 0.604004f, + 0.619629f, 0.635742f, 0.650391f, 0.666504f, 0.682129f, 0.697754f, 0.712891f, 0.728027f, 0.743164f, 0.758301f, 0.878906f, 0.877441f, + 0.871582f, 0.866699f, 0.860840f, 0.856445f, 0.003084f, 0.009697f, 0.016403f, 0.022659f, 0.029892f, 0.037354f, 0.044281f, 0.052338f, + 0.060516f, 0.068970f, 0.077515f, 0.086243f, 0.096069f, 0.105713f, 0.115356f, 0.125610f, 0.136353f, 0.147339f, 0.158081f, 0.170410f, + 0.181396f, 0.194458f, 0.207275f, 0.219482f, 0.232910f, 0.246704f, 0.260010f, 0.274170f, 0.288330f, 0.302979f, 0.317383f, 0.332764f, + 0.347656f, 0.363037f, 0.378174f, 0.392578f, 0.408936f, 0.424316f, 0.440430f, 0.456299f, 0.472656f, 0.488525f, 0.503906f, 0.519531f, + 0.535645f, 0.552734f, 0.568359f, 0.584961f, 0.600586f, 0.616699f, 0.633301f, 0.648438f, 0.663574f, 0.679199f, 0.694824f, 0.710938f, + 0.726074f, 0.742188f, 0.872559f, 0.870605f, 0.865723f, 0.860840f, 0.855957f, 0.851074f, 0.002913f, 0.008781f, 0.014938f, 0.021759f, + 0.027878f, 0.034393f, 0.041412f, 0.048737f, 0.055969f, 0.063599f, 0.072021f, 0.080200f, 0.088928f, 0.097839f, 0.106934f, 0.116150f, + 0.126587f, 0.136353f, 0.147095f, 0.157715f, 0.169189f, 0.181519f, 0.193481f, 0.205933f, 0.217773f, 0.231323f, 0.244629f, 0.257812f, + 0.271240f, 0.285400f, 0.299561f, 0.314453f, 0.329590f, 0.343506f, 0.358887f, 0.373779f, 0.389648f, 0.405029f, 0.420410f, 0.437012f, + 0.452393f, 0.468262f, 0.484375f, 0.500000f, 0.516113f, 0.532227f, 0.548828f, 0.564941f, 0.581055f, 0.597168f, 0.612793f, 0.629883f, + 0.645508f, 0.662109f, 0.678223f, 0.694336f, 0.709473f, 0.726074f, 0.863770f, 0.864258f, 0.859863f, 0.854980f, 0.850586f, 0.846191f, + 0.002815f, 0.008194f, 0.013954f, 0.019653f, 0.025696f, 0.031982f, 0.038177f, 0.044830f, 0.051819f, 0.058502f, 0.066162f, 0.073792f, + 0.082031f, 0.090393f, 0.098999f, 0.107605f, 0.117493f, 0.126709f, 0.137207f, 0.146729f, 0.157593f, 0.168579f, 0.179810f, 0.191772f, + 0.203369f, 0.215820f, 0.228882f, 0.241455f, 0.254395f, 0.268311f, 0.282227f, 0.296631f, 0.310303f, 0.325439f, 0.339844f, 0.354736f, + 0.370361f, 0.385742f, 0.400879f, 0.416504f, 0.432617f, 0.448486f, 0.464355f, 0.479980f, 0.496094f, 0.513184f, 0.528809f, 0.545410f, + 0.561035f, 0.578613f, 0.594727f, 0.611328f, 0.626953f, 0.643555f, 0.660156f, 0.676270f, 0.693359f, 0.709473f, 0.856445f, 0.858398f, + 0.854492f, 0.849121f, 0.845215f, 0.841309f, 0.002583f, 0.007492f, 0.012878f, 0.018417f, 0.023941f, 0.029495f, 0.035339f, 0.041779f, + 0.047577f, 0.054047f, 0.061523f, 0.068787f, 0.075562f, 0.083313f, 0.091858f, 0.099792f, 0.108521f, 0.117615f, 0.126709f, 0.136108f, + 0.146851f, 0.156860f, 0.166992f, 0.178345f, 0.189819f, 0.202148f, 0.213623f, 0.225830f, 0.238892f, 0.252197f, 0.265137f, 0.278809f, + 0.292480f, 0.306885f, 0.321045f, 0.336914f, 0.350830f, 0.366943f, 0.381348f, 0.396240f, 0.412354f, 0.428223f, 0.444336f, 0.460449f, + 0.476318f, 0.493408f, 0.509277f, 0.525879f, 0.542480f, 0.559082f, 0.574707f, 0.591797f, 0.608398f, 0.625488f, 0.642090f, 0.659180f, + 0.675781f, 0.691406f, 0.848145f, 0.851562f, 0.848145f, 0.843750f, 0.838867f, 0.835449f, 0.002512f, 0.007374f, 0.012115f, 0.016983f, + 0.022064f, 0.027359f, 0.032715f, 0.038147f, 0.044373f, 0.050354f, 0.056641f, 0.063293f, 0.070190f, 0.077026f, 0.084717f, 0.092041f, + 0.100342f, 0.108398f, 0.117554f, 0.126221f, 0.135742f, 0.145142f, 0.155151f, 0.165771f, 0.176758f, 0.187988f, 0.199341f, 0.210815f, + 0.223389f, 0.236206f, 0.249023f, 0.261719f, 0.275879f, 0.289062f, 0.303467f, 0.317627f, 0.332520f, 0.347412f, 0.361816f, 0.377197f, + 0.393066f, 0.407959f, 0.424072f, 0.440186f, 0.457031f, 0.473145f, 0.489502f, 0.505859f, 0.522461f, 0.540039f, 0.555664f, 0.572754f, + 0.589844f, 0.606445f, 0.623535f, 0.640625f, 0.658203f, 0.675781f, 0.840820f, 0.843750f, 0.841309f, 0.836914f, 0.833984f, 0.830566f, + 0.002369f, 0.006668f, 0.011093f, 0.015778f, 0.020523f, 0.025223f, 0.030701f, 0.035339f, 0.040710f, 0.046600f, 0.051971f, 0.058075f, + 0.064819f, 0.071228f, 0.077942f, 0.085205f, 0.092224f, 0.100464f, 0.108398f, 0.116882f, 0.125610f, 0.134155f, 0.143555f, 0.153564f, + 0.164062f, 0.174316f, 0.185303f, 0.196899f, 0.208496f, 0.220093f, 0.232666f, 0.245239f, 0.258057f, 0.271729f, 0.285645f, 0.299561f, + 0.313721f, 0.328613f, 0.342773f, 0.358154f, 0.373535f, 0.388916f, 0.405518f, 0.419922f, 0.437012f, 0.453125f, 0.469238f, 0.486328f, + 0.502930f, 0.519531f, 0.536133f, 0.553223f, 0.571289f, 0.588379f, 0.605469f, 0.623047f, 0.640137f, 0.656250f, 0.833008f, 0.837402f, + 0.834473f, 0.831055f, 0.827637f, 0.824219f, 0.002188f, 0.006027f, 0.010582f, 0.014297f, 0.018921f, 0.023270f, 0.028183f, 0.032593f, + 0.037781f, 0.042999f, 0.048584f, 0.053650f, 0.059601f, 0.065369f, 0.071899f, 0.078369f, 0.085449f, 0.092407f, 0.099609f, 0.107788f, + 0.115601f, 0.124451f, 0.133301f, 0.142212f, 0.151978f, 0.161865f, 0.172363f, 0.182617f, 0.193970f, 0.205566f, 0.217407f, 0.229858f, + 0.241943f, 0.254639f, 0.268311f, 0.281494f, 0.295654f, 0.310059f, 0.324219f, 0.339600f, 0.353760f, 0.369629f, 0.385010f, 0.400879f, + 0.417725f, 0.433594f, 0.449219f, 0.465820f, 0.482910f, 0.499512f, 0.517090f, 0.534180f, 0.551270f, 0.568848f, 0.586426f, 0.604004f, + 0.622559f, 0.639160f, 0.824219f, 0.830078f, 0.827637f, 0.824707f, 0.821777f, 0.818359f, 0.002098f, 0.005634f, 0.009354f, 0.013557f, + 0.017685f, 0.021576f, 0.025604f, 0.030380f, 0.034943f, 0.039429f, 0.044281f, 0.049255f, 0.055023f, 0.060577f, 0.066101f, 0.072144f, + 0.078491f, 0.085083f, 0.091858f, 0.098999f, 0.106873f, 0.114502f, 0.122498f, 0.131592f, 0.140137f, 0.149536f, 0.159424f, 0.169556f, + 0.180054f, 0.191162f, 0.202026f, 0.213989f, 0.226318f, 0.239136f, 0.250977f, 0.264648f, 0.278320f, 0.291748f, 0.305908f, 0.320557f, + 0.334961f, 0.350342f, 0.365479f, 0.381592f, 0.397461f, 0.413818f, 0.429199f, 0.446289f, 0.462891f, 0.479736f, 0.496338f, 0.514160f, + 0.530762f, 0.548828f, 0.566406f, 0.584473f, 0.602539f, 0.621582f, 0.815918f, 0.823730f, 0.821289f, 0.817871f, 0.815430f, 0.812500f, + 0.001772f, 0.005249f, 0.008995f, 0.012260f, 0.016251f, 0.020020f, 0.024216f, 0.027603f, 0.032196f, 0.036377f, 0.041199f, 0.045410f, + 0.050110f, 0.055603f, 0.061005f, 0.066406f, 0.072327f, 0.077820f, 0.084290f, 0.090942f, 0.098083f, 0.105164f, 0.113037f, 0.120789f, + 0.129272f, 0.138062f, 0.147339f, 0.156982f, 0.166626f, 0.176758f, 0.187866f, 0.199097f, 0.210449f, 0.222412f, 0.234985f, 0.247559f, + 0.260742f, 0.273682f, 0.287598f, 0.302002f, 0.316650f, 0.331299f, 0.346191f, 0.362061f, 0.377686f, 0.393066f, 0.409668f, 0.426514f, + 0.443115f, 0.459717f, 0.476807f, 0.494629f, 0.511230f, 0.529785f, 0.547852f, 0.565430f, 0.583984f, 0.602539f, 0.806152f, 0.814453f, + 0.813965f, 0.811035f, 0.809082f, 0.806641f, 0.001631f, 0.005131f, 0.008186f, 0.011673f, 0.014938f, 0.018463f, 0.021957f, 0.025635f, + 0.029083f, 0.033325f, 0.037445f, 0.041840f, 0.046478f, 0.050751f, 0.055634f, 0.060760f, 0.065979f, 0.071472f, 0.077515f, 0.083801f, + 0.090027f, 0.096802f, 0.104065f, 0.110840f, 0.119080f, 0.127197f, 0.135498f, 0.144775f, 0.153931f, 0.163574f, 0.173462f, 0.184570f, + 0.195312f, 0.207153f, 0.218506f, 0.230591f, 0.243652f, 0.256348f, 0.270020f, 0.283691f, 0.297852f, 0.312744f, 0.326904f, 0.342529f, + 0.357910f, 0.373535f, 0.389404f, 0.406494f, 0.421875f, 0.439941f, 0.457275f, 0.474365f, 0.492432f, 0.509766f, 0.527832f, 0.546875f, + 0.564941f, 0.584473f, 0.797852f, 0.807129f, 0.807129f, 0.804199f, 0.801758f, 0.799316f, 0.001632f, 0.004704f, 0.007912f, 0.010788f, + 0.013870f, 0.017105f, 0.020187f, 0.023483f, 0.026932f, 0.030563f, 0.034332f, 0.038086f, 0.042694f, 0.046631f, 0.050995f, 0.055725f, + 0.060486f, 0.065674f, 0.070862f, 0.076721f, 0.082825f, 0.088623f, 0.094910f, 0.102112f, 0.109070f, 0.116516f, 0.124695f, 0.133057f, + 0.141968f, 0.151001f, 0.160522f, 0.170776f, 0.181030f, 0.191650f, 0.202881f, 0.214722f, 0.227417f, 0.239624f, 0.252686f, 0.265625f, + 0.279785f, 0.293213f, 0.308350f, 0.323242f, 0.338867f, 0.354248f, 0.370117f, 0.386475f, 0.403076f, 0.420410f, 0.437012f, 0.454102f, + 0.471924f, 0.490234f, 0.508789f, 0.526855f, 0.545410f, 0.564453f, 0.788086f, 0.799316f, 0.798828f, 0.797852f, 0.794434f, 0.791992f, + 0.001594f, 0.004177f, 0.007122f, 0.010201f, 0.012344f, 0.015839f, 0.018372f, 0.021683f, 0.024857f, 0.028534f, 0.031464f, 0.035034f, + 0.038879f, 0.042572f, 0.046295f, 0.051056f, 0.055389f, 0.059723f, 0.064697f, 0.069763f, 0.075073f, 0.080750f, 0.087219f, 0.093445f, + 0.099548f, 0.107056f, 0.114136f, 0.121887f, 0.130249f, 0.138794f, 0.147217f, 0.157104f, 0.166748f, 0.177124f, 0.187988f, 0.199097f, + 0.210693f, 0.222778f, 0.235352f, 0.248169f, 0.261719f, 0.275635f, 0.289062f, 0.303955f, 0.319336f, 0.334717f, 0.350098f, 0.365479f, + 0.382324f, 0.398926f, 0.416016f, 0.433594f, 0.451904f, 0.469238f, 0.487549f, 0.506348f, 0.525391f, 0.544922f, 0.779297f, 0.791504f, + 0.791504f, 0.789551f, 0.788086f, 0.786133f, 0.001365f, 0.004173f, 0.006222f, 0.008842f, 0.011703f, 0.014366f, 0.017242f, 0.020218f, + 0.022903f, 0.025787f, 0.028824f, 0.032227f, 0.035522f, 0.038818f, 0.042511f, 0.046326f, 0.050507f, 0.054657f, 0.058594f, 0.063660f, + 0.068359f, 0.073914f, 0.078918f, 0.085083f, 0.091125f, 0.097534f, 0.104126f, 0.111511f, 0.118896f, 0.126831f, 0.135742f, 0.144043f, + 0.153564f, 0.163330f, 0.173462f, 0.184082f, 0.195068f, 0.206787f, 0.218628f, 0.231079f, 0.243896f, 0.257080f, 0.270996f, 0.285645f, + 0.300049f, 0.314941f, 0.330322f, 0.346191f, 0.362305f, 0.379395f, 0.395508f, 0.412842f, 0.431641f, 0.448975f, 0.468262f, 0.487549f, + 0.505371f, 0.525391f, 0.769531f, 0.783691f, 0.783691f, 0.782715f, 0.781250f, 0.778809f, 0.001230f, 0.003925f, 0.006268f, 0.008659f, + 0.010796f, 0.013145f, 0.015617f, 0.018234f, 0.021133f, 0.023682f, 0.026215f, 0.029251f, 0.032349f, 0.035400f, 0.038696f, 0.042206f, + 0.045807f, 0.049377f, 0.053925f, 0.057953f, 0.062500f, 0.067078f, 0.071777f, 0.077271f, 0.082703f, 0.088806f, 0.094910f, 0.101379f, + 0.109192f, 0.115967f, 0.123779f, 0.131470f, 0.140259f, 0.149536f, 0.159302f, 0.169312f, 0.180054f, 0.190674f, 0.202515f, 0.214722f, + 0.226562f, 0.239624f, 0.253174f, 0.266602f, 0.281738f, 0.295898f, 0.311035f, 0.326904f, 0.342529f, 0.359131f, 0.375732f, 0.393066f, + 0.410400f, 0.428467f, 0.447510f, 0.466064f, 0.485596f, 0.504883f, 0.759277f, 0.774902f, 0.775879f, 0.774902f, 0.773438f, 0.771973f, + 0.001031f, 0.003601f, 0.005604f, 0.007858f, 0.009880f, 0.012146f, 0.014549f, 0.016998f, 0.019043f, 0.021362f, 0.024475f, 0.026566f, + 0.029358f, 0.032196f, 0.035248f, 0.038391f, 0.041656f, 0.045044f, 0.048553f, 0.052582f, 0.056213f, 0.060669f, 0.065186f, 0.070068f, + 0.074768f, 0.080322f, 0.086060f, 0.092102f, 0.098877f, 0.105408f, 0.112366f, 0.120239f, 0.128540f, 0.136597f, 0.145874f, 0.155396f, + 0.165283f, 0.175537f, 0.186401f, 0.198120f, 0.210083f, 0.222534f, 0.235229f, 0.248657f, 0.262451f, 0.277344f, 0.291504f, 0.307617f, + 0.322998f, 0.339111f, 0.354980f, 0.372559f, 0.390625f, 0.408936f, 0.426758f, 0.445312f, 0.466064f, 0.485840f, 0.749512f, 0.765137f, + 0.767578f, 0.767090f, 0.765137f, 0.764648f, 0.001161f, 0.003078f, 0.005310f, 0.007282f, 0.009201f, 0.011330f, 0.013214f, 0.015404f, + 0.017273f, 0.019409f, 0.021988f, 0.024078f, 0.026550f, 0.029358f, 0.032043f, 0.034454f, 0.037415f, 0.040710f, 0.043854f, 0.047272f, + 0.050659f, 0.054840f, 0.058777f, 0.063293f, 0.067566f, 0.072449f, 0.077759f, 0.083069f, 0.088928f, 0.095886f, 0.102478f, 0.109070f, + 0.116760f, 0.124390f, 0.132935f, 0.141479f, 0.151123f, 0.161011f, 0.171143f, 0.182007f, 0.193726f, 0.205688f, 0.218018f, 0.230835f, + 0.244507f, 0.258789f, 0.272949f, 0.287109f, 0.303467f, 0.319336f, 0.335449f, 0.352539f, 0.369873f, 0.387939f, 0.406250f, 0.425049f, + 0.444824f, 0.464844f, 0.739258f, 0.756348f, 0.758789f, 0.758789f, 0.757324f, 0.756836f, 0.001004f, 0.002939f, 0.005005f, 0.006779f, + 0.008453f, 0.010323f, 0.012177f, 0.013870f, 0.016052f, 0.018051f, 0.019638f, 0.022141f, 0.023956f, 0.026413f, 0.028870f, 0.031281f, + 0.033661f, 0.036591f, 0.039429f, 0.042542f, 0.045776f, 0.049011f, 0.053009f, 0.056885f, 0.061035f, 0.065186f, 0.069885f, 0.075134f, + 0.080505f, 0.085999f, 0.091858f, 0.098633f, 0.105591f, 0.112732f, 0.120667f, 0.128662f, 0.137573f, 0.146729f, 0.156372f, 0.166748f, + 0.177490f, 0.189331f, 0.201294f, 0.213501f, 0.226807f, 0.239746f, 0.254150f, 0.268555f, 0.283936f, 0.298828f, 0.316162f, 0.332275f, + 0.349609f, 0.367432f, 0.385498f, 0.404053f, 0.423828f, 0.443848f, 0.728516f, 0.747559f, 0.750488f, 0.750488f, 0.749512f, 0.748047f, + 0.000970f, 0.002523f, 0.004665f, 0.006203f, 0.007759f, 0.009491f, 0.011070f, 0.012802f, 0.014336f, 0.016266f, 0.017944f, 0.019852f, + 0.021805f, 0.023911f, 0.025818f, 0.028137f, 0.030579f, 0.032837f, 0.035248f, 0.038055f, 0.041046f, 0.044189f, 0.047333f, 0.050842f, + 0.054504f, 0.058502f, 0.062866f, 0.067383f, 0.071960f, 0.077393f, 0.082642f, 0.088928f, 0.095093f, 0.101685f, 0.108765f, 0.116272f, + 0.124451f, 0.133423f, 0.142212f, 0.152100f, 0.162354f, 0.172729f, 0.184692f, 0.196411f, 0.209106f, 0.221802f, 0.235718f, 0.250000f, + 0.265137f, 0.280029f, 0.296143f, 0.312012f, 0.329346f, 0.346924f, 0.364990f, 0.384277f, 0.403564f, 0.423340f, 0.718262f, 0.738770f, + 0.741211f, 0.742188f, 0.741211f, 0.740234f, 0.000785f, 0.002600f, 0.004028f, 0.005390f, 0.007275f, 0.008774f, 0.010124f, 0.011620f, + 0.013306f, 0.014427f, 0.015991f, 0.017838f, 0.019577f, 0.021469f, 0.023254f, 0.024902f, 0.027115f, 0.029190f, 0.031677f, 0.034088f, + 0.036682f, 0.039307f, 0.042175f, 0.045410f, 0.048553f, 0.052002f, 0.055908f, 0.060028f, 0.064270f, 0.068909f, 0.074097f, 0.079163f, + 0.085022f, 0.091309f, 0.097473f, 0.104797f, 0.112183f, 0.120239f, 0.128662f, 0.137451f, 0.146973f, 0.157471f, 0.168213f, 0.179810f, + 0.191650f, 0.204468f, 0.217529f, 0.231201f, 0.245605f, 0.260254f, 0.275879f, 0.292236f, 0.308838f, 0.326416f, 0.344238f, 0.363037f, + 0.382080f, 0.403076f, 0.707031f, 0.729980f, 0.732422f, 0.733398f, 0.733398f, 0.732910f, 0.000775f, 0.002190f, 0.003696f, 0.005081f, + 0.006397f, 0.007858f, 0.009239f, 0.010323f, 0.011803f, 0.012978f, 0.014328f, 0.015915f, 0.017349f, 0.019058f, 0.020630f, 0.022339f, + 0.024445f, 0.025909f, 0.028275f, 0.030151f, 0.032532f, 0.035065f, 0.037476f, 0.040283f, 0.042969f, 0.046448f, 0.049469f, 0.053314f, + 0.056976f, 0.061371f, 0.065613f, 0.070435f, 0.075623f, 0.081360f, 0.087341f, 0.093628f, 0.100220f, 0.107788f, 0.115845f, 0.123901f, + 0.133057f, 0.142456f, 0.152832f, 0.163574f, 0.174561f, 0.187012f, 0.199463f, 0.212646f, 0.226562f, 0.241455f, 0.256836f, 0.272705f, + 0.288818f, 0.305664f, 0.323486f, 0.341797f, 0.362305f, 0.382080f, 0.695312f, 0.719238f, 0.722656f, 0.724121f, 0.724121f, 0.723633f, + 0.000906f, 0.002022f, 0.003521f, 0.004963f, 0.005756f, 0.006847f, 0.008446f, 0.009392f, 0.010437f, 0.012039f, 0.012863f, 0.014343f, + 0.015457f, 0.016876f, 0.018295f, 0.019730f, 0.021484f, 0.023102f, 0.024689f, 0.026581f, 0.028717f, 0.030945f, 0.032928f, 0.035370f, + 0.037872f, 0.040894f, 0.043915f, 0.047028f, 0.050415f, 0.054169f, 0.058167f, 0.062286f, 0.067078f, 0.071960f, 0.077209f, 0.082947f, + 0.089417f, 0.096008f, 0.103271f, 0.110718f, 0.119324f, 0.128052f, 0.137817f, 0.147705f, 0.158691f, 0.169922f, 0.181519f, 0.195435f, + 0.208496f, 0.222534f, 0.237305f, 0.252441f, 0.268799f, 0.285645f, 0.302979f, 0.322266f, 0.340332f, 0.360840f, 0.683594f, 0.708984f, + 0.714355f, 0.715332f, 0.715820f, 0.715332f, 0.000700f, 0.002043f, 0.003139f, 0.004219f, 0.005417f, 0.006477f, 0.007442f, 0.008415f, + 0.009499f, 0.010475f, 0.011497f, 0.012619f, 0.013824f, 0.014969f, 0.016190f, 0.017639f, 0.018799f, 0.020386f, 0.021896f, 0.023560f, + 0.025131f, 0.027176f, 0.028900f, 0.031067f, 0.033295f, 0.035919f, 0.038239f, 0.041229f, 0.044373f, 0.047394f, 0.050934f, 0.054871f, + 0.058838f, 0.063293f, 0.068115f, 0.073303f, 0.078857f, 0.084839f, 0.091309f, 0.098328f, 0.106079f, 0.114136f, 0.123230f, 0.132690f, + 0.143066f, 0.153442f, 0.165161f, 0.177368f, 0.190186f, 0.203979f, 0.218262f, 0.232910f, 0.248901f, 0.265381f, 0.282227f, 0.301025f, + 0.319580f, 0.339355f, 0.672852f, 0.699707f, 0.704590f, 0.706055f, 0.706543f, 0.706055f, 0.000762f, 0.001804f, 0.002762f, 0.003914f, + 0.004791f, 0.005764f, 0.006542f, 0.007622f, 0.008606f, 0.009232f, 0.010178f, 0.011093f, 0.012108f, 0.013191f, 0.014412f, 0.015289f, + 0.016510f, 0.017731f, 0.019119f, 0.020615f, 0.022049f, 0.023483f, 0.025345f, 0.027100f, 0.028885f, 0.031067f, 0.033417f, 0.035797f, + 0.038422f, 0.041382f, 0.044495f, 0.047638f, 0.051178f, 0.055267f, 0.059387f, 0.064026f, 0.069092f, 0.074585f, 0.080566f, 0.087097f, + 0.093811f, 0.101624f, 0.109619f, 0.117798f, 0.127319f, 0.137817f, 0.148682f, 0.160278f, 0.172607f, 0.185669f, 0.199097f, 0.214233f, + 0.229492f, 0.245850f, 0.261963f, 0.280273f, 0.299316f, 0.319580f, 0.660645f, 0.689453f, 0.694824f, 0.696777f, 0.697266f, 0.697266f, + 0.000499f, 0.001527f, 0.002565f, 0.003622f, 0.004429f, 0.005138f, 0.005955f, 0.006691f, 0.007317f, 0.008156f, 0.008949f, 0.009903f, + 0.010635f, 0.011452f, 0.012512f, 0.013451f, 0.014503f, 0.015610f, 0.016632f, 0.017746f, 0.019073f, 0.020355f, 0.021957f, 0.023453f, + 0.025208f, 0.026932f, 0.028732f, 0.030945f, 0.033142f, 0.035614f, 0.038300f, 0.041199f, 0.044464f, 0.047760f, 0.051514f, 0.055573f, + 0.059998f, 0.064819f, 0.070312f, 0.075867f, 0.082275f, 0.088806f, 0.096436f, 0.104797f, 0.113342f, 0.122559f, 0.132568f, 0.143799f, + 0.155396f, 0.167725f, 0.181274f, 0.195068f, 0.209961f, 0.225708f, 0.242310f, 0.259766f, 0.277832f, 0.297363f, 0.648926f, 0.678711f, + 0.685059f, 0.687500f, 0.687500f, 0.687988f, 0.000653f, 0.001627f, 0.002562f, 0.003166f, 0.003872f, 0.004562f, 0.005287f, 0.005905f, + 0.006557f, 0.007309f, 0.007835f, 0.008621f, 0.009140f, 0.010109f, 0.010773f, 0.011627f, 0.012428f, 0.013351f, 0.014488f, 0.015472f, + 0.016479f, 0.017578f, 0.018845f, 0.020157f, 0.021591f, 0.023132f, 0.024765f, 0.026337f, 0.028473f, 0.030594f, 0.032867f, 0.035309f, + 0.037933f, 0.041107f, 0.044403f, 0.047852f, 0.051666f, 0.055756f, 0.060455f, 0.065552f, 0.070740f, 0.077454f, 0.083862f, 0.091125f, + 0.099304f, 0.107971f, 0.117859f, 0.127808f, 0.139038f, 0.150757f, 0.163574f, 0.176880f, 0.191162f, 0.206665f, 0.222656f, 0.239258f, + 0.257568f, 0.277100f, 0.636230f, 0.667969f, 0.675293f, 0.677734f, 0.678223f, 0.678711f, 0.000393f, 0.001375f, 0.002174f, 0.002773f, + 0.003334f, 0.004070f, 0.004692f, 0.005047f, 0.005672f, 0.006298f, 0.006893f, 0.007454f, 0.007957f, 0.008636f, 0.009171f, 0.010002f, + 0.010674f, 0.011574f, 0.012451f, 0.013145f, 0.014091f, 0.014893f, 0.016083f, 0.017151f, 0.018402f, 0.019714f, 0.021042f, 0.022415f, + 0.024155f, 0.026108f, 0.027786f, 0.030212f, 0.032379f, 0.034698f, 0.037415f, 0.040436f, 0.043793f, 0.047455f, 0.051727f, 0.056030f, + 0.061218f, 0.066284f, 0.072571f, 0.079041f, 0.086121f, 0.094299f, 0.102844f, 0.112305f, 0.122925f, 0.134033f, 0.145752f, 0.158569f, + 0.172729f, 0.187378f, 0.203003f, 0.219238f, 0.237671f, 0.255859f, 0.624023f, 0.657227f, 0.664062f, 0.666992f, 0.668457f, 0.668457f, + 0.000379f, 0.001404f, 0.001893f, 0.002403f, 0.002840f, 0.003458f, 0.004021f, 0.004459f, 0.004894f, 0.005527f, 0.005844f, 0.006256f, + 0.006866f, 0.007423f, 0.007957f, 0.008476f, 0.009155f, 0.009735f, 0.010422f, 0.011078f, 0.011925f, 0.012787f, 0.013458f, 0.014526f, + 0.015541f, 0.016632f, 0.017838f, 0.019028f, 0.020248f, 0.021851f, 0.023514f, 0.024979f, 0.027054f, 0.029236f, 0.031555f, 0.034180f, + 0.036713f, 0.040375f, 0.043854f, 0.047607f, 0.051727f, 0.056549f, 0.061768f, 0.067627f, 0.073792f, 0.081116f, 0.089111f, 0.097595f, + 0.107056f, 0.117371f, 0.128906f, 0.141113f, 0.154053f, 0.168579f, 0.183960f, 0.199585f, 0.216309f, 0.235352f, 0.612793f, 0.647949f, + 0.652832f, 0.656250f, 0.658691f, 0.658203f, 0.000506f, 0.001164f, 0.001575f, 0.002136f, 0.002600f, 0.003054f, 0.003405f, 0.003735f, + 0.004364f, 0.004681f, 0.004944f, 0.005569f, 0.005810f, 0.006187f, 0.006813f, 0.007233f, 0.007881f, 0.008217f, 0.008850f, 0.009293f, + 0.010109f, 0.010788f, 0.011543f, 0.012161f, 0.012993f, 0.013931f, 0.014809f, 0.015945f, 0.016983f, 0.018234f, 0.019440f, 0.020813f, + 0.022491f, 0.024261f, 0.026169f, 0.028458f, 0.030701f, 0.033295f, 0.036560f, 0.039520f, 0.043121f, 0.047333f, 0.052032f, 0.056885f, + 0.062561f, 0.068909f, 0.076111f, 0.083496f, 0.092407f, 0.101929f, 0.112671f, 0.124451f, 0.136719f, 0.150146f, 0.165039f, 0.180786f, + 0.197510f, 0.215210f, 0.597656f, 0.636230f, 0.642578f, 0.647461f, 0.647949f, 0.649902f, 0.000344f, 0.001057f, 0.001456f, 0.001907f, + 0.002377f, 0.002735f, 0.002983f, 0.003359f, 0.003651f, 0.003960f, 0.004311f, 0.004471f, 0.005009f, 0.005283f, 0.005653f, 0.006145f, + 0.006592f, 0.006889f, 0.007469f, 0.007889f, 0.008423f, 0.008911f, 0.009567f, 0.010124f, 0.010788f, 0.011574f, 0.012466f, 0.013123f, + 0.014053f, 0.015091f, 0.016159f, 0.017288f, 0.018539f, 0.020111f, 0.021698f, 0.023285f, 0.025024f, 0.027405f, 0.029800f, 0.032501f, + 0.035583f, 0.039001f, 0.042908f, 0.047302f, 0.052185f, 0.057465f, 0.063843f, 0.070984f, 0.078857f, 0.087463f, 0.097168f, 0.108215f, + 0.120117f, 0.132812f, 0.146851f, 0.161865f, 0.177856f, 0.195557f, 0.585449f, 0.624023f, 0.633301f, 0.636230f, 0.637695f, 0.638672f, + 0.000516f, 0.000847f, 0.001210f, 0.001663f, 0.002012f, 0.002218f, 0.002424f, 0.002861f, 0.002947f, 0.003275f, 0.003469f, 0.003819f, + 0.004169f, 0.004337f, 0.004658f, 0.005169f, 0.005424f, 0.005795f, 0.006138f, 0.006500f, 0.007057f, 0.007458f, 0.007874f, 0.008369f, + 0.008888f, 0.009583f, 0.010147f, 0.010864f, 0.011589f, 0.012428f, 0.013161f, 0.013931f, 0.015076f, 0.016266f, 0.017456f, 0.018845f, + 0.020432f, 0.022232f, 0.024094f, 0.026459f, 0.028809f, 0.031586f, 0.034973f, 0.038513f, 0.042755f, 0.047485f, 0.052643f, 0.058929f, + 0.065796f, 0.073792f, 0.082581f, 0.092407f, 0.103516f, 0.115723f, 0.128906f, 0.142944f, 0.158813f, 0.175781f, 0.572266f, 0.613770f, + 0.621094f, 0.625977f, 0.626953f, 0.628418f, 0.000262f, 0.000864f, 0.001096f, 0.001409f, 0.001576f, 0.001852f, 0.002047f, 0.002247f, + 0.002518f, 0.002741f, 0.002956f, 0.003157f, 0.003359f, 0.003597f, 0.003872f, 0.004230f, 0.004406f, 0.004772f, 0.005035f, 0.005379f, + 0.005695f, 0.006153f, 0.006485f, 0.006935f, 0.007275f, 0.007801f, 0.008301f, 0.008789f, 0.009300f, 0.009949f, 0.010727f, 0.011482f, + 0.012245f, 0.013145f, 0.014236f, 0.015236f, 0.016525f, 0.017838f, 0.019348f, 0.021088f, 0.023010f, 0.025253f, 0.027878f, 0.031128f, + 0.034149f, 0.038269f, 0.042694f, 0.047852f, 0.053833f, 0.060852f, 0.068665f, 0.077698f, 0.087891f, 0.099182f, 0.111633f, 0.125732f, + 0.140381f, 0.157227f, 0.558105f, 0.601562f, 0.610840f, 0.614746f, 0.617188f, 0.619141f, 0.000270f, 0.000683f, 0.000851f, 0.001138f, + 0.001346f, 0.001561f, 0.001701f, 0.001884f, 0.001984f, 0.002193f, 0.002455f, 0.002609f, 0.002743f, 0.002993f, 0.003159f, 0.003361f, + 0.003593f, 0.003883f, 0.004044f, 0.004360f, 0.004532f, 0.004971f, 0.005169f, 0.005573f, 0.005863f, 0.006252f, 0.006653f, 0.007095f, + 0.007572f, 0.008110f, 0.008713f, 0.009056f, 0.009827f, 0.010574f, 0.011307f, 0.012070f, 0.013069f, 0.014122f, 0.015297f, 0.016678f, + 0.018234f, 0.019775f, 0.021835f, 0.024216f, 0.026917f, 0.030151f, 0.033875f, 0.038147f, 0.043121f, 0.049408f, 0.056091f, 0.064026f, + 0.073059f, 0.083801f, 0.095276f, 0.108459f, 0.122803f, 0.138794f, 0.545410f, 0.590332f, 0.599609f, 0.603516f, 0.606445f, 0.607422f, + 0.000190f, 0.000607f, 0.000724f, 0.000989f, 0.001171f, 0.001265f, 0.001416f, 0.001602f, 0.001666f, 0.001761f, 0.001893f, 0.002102f, + 0.002199f, 0.002413f, 0.002537f, 0.002743f, 0.002850f, 0.003027f, 0.003258f, 0.003494f, 0.003729f, 0.003937f, 0.004204f, 0.004410f, + 0.004616f, 0.004921f, 0.005192f, 0.005604f, 0.005936f, 0.006298f, 0.006836f, 0.007233f, 0.007694f, 0.008224f, 0.008827f, 0.009506f, + 0.010262f, 0.011055f, 0.011978f, 0.012955f, 0.014099f, 0.015434f, 0.017029f, 0.018677f, 0.020813f, 0.023193f, 0.026169f, 0.029541f, + 0.033783f, 0.038513f, 0.044403f, 0.051208f, 0.059387f, 0.068665f, 0.079468f, 0.091858f, 0.105774f, 0.120728f, 0.530762f, 0.578125f, + 0.588379f, 0.592773f, 0.595215f, 0.597168f, 0.000151f, 0.000443f, 0.000673f, 0.000793f, 0.000937f, 0.000987f, 0.001092f, 0.001192f, + 0.001324f, 0.001460f, 0.001495f, 0.001565f, 0.001778f, 0.001944f, 0.002054f, 0.002096f, 0.002254f, 0.002338f, 0.002594f, 0.002737f, + 0.002886f, 0.003048f, 0.003294f, 0.003460f, 0.003679f, 0.003868f, 0.004086f, 0.004322f, 0.004642f, 0.004894f, 0.005199f, 0.005554f, + 0.006035f, 0.006451f, 0.006836f, 0.007359f, 0.007820f, 0.008461f, 0.009163f, 0.009956f, 0.010803f, 0.011871f, 0.012917f, 0.014343f, + 0.015900f, 0.017670f, 0.019791f, 0.022400f, 0.025589f, 0.029404f, 0.034210f, 0.039948f, 0.046936f, 0.055298f, 0.064941f, 0.076172f, + 0.089172f, 0.103821f, 0.517090f, 0.565918f, 0.576172f, 0.582031f, 0.584961f, 0.586426f, 0.000203f, 0.000287f, 0.000531f, 0.000688f, + 0.000738f, 0.000820f, 0.000915f, 0.000875f, 0.001036f, 0.001117f, 0.001215f, 0.001317f, 0.001374f, 0.001476f, 0.001524f, 0.001682f, + 0.001726f, 0.001867f, 0.002014f, 0.002056f, 0.002209f, 0.002365f, 0.002495f, 0.002663f, 0.002775f, 0.002953f, 0.003134f, 0.003325f, + 0.003567f, 0.003736f, 0.004070f, 0.004261f, 0.004494f, 0.004845f, 0.005116f, 0.005459f, 0.005928f, 0.006329f, 0.006863f, 0.007458f, + 0.008087f, 0.008873f, 0.009689f, 0.010651f, 0.011826f, 0.013130f, 0.014732f, 0.016617f, 0.018890f, 0.021912f, 0.025482f, 0.029938f, + 0.035736f, 0.042847f, 0.051453f, 0.061615f, 0.074158f, 0.087952f, 0.504395f, 0.554199f, 0.565918f, 0.569336f, 0.573242f, 0.574219f, + 0.000215f, 0.000259f, 0.000423f, 0.000534f, 0.000499f, 0.000649f, 0.000622f, 0.000690f, 0.000717f, 0.000817f, 0.000937f, 0.000984f, + 0.001045f, 0.001148f, 0.001182f, 0.001211f, 0.001339f, 0.001406f, 0.001463f, 0.001590f, 0.001666f, 0.001759f, 0.001867f, 0.001949f, + 0.002064f, 0.002176f, 0.002342f, 0.002453f, 0.002619f, 0.002871f, 0.003033f, 0.003101f, 0.003389f, 0.003620f, 0.003794f, 0.004059f, + 0.004368f, 0.004681f, 0.005035f, 0.005466f, 0.005917f, 0.006405f, 0.007092f, 0.007744f, 0.008591f, 0.009506f, 0.010567f, 0.011993f, + 0.013710f, 0.015762f, 0.018326f, 0.021759f, 0.026077f, 0.031891f, 0.039124f, 0.048462f, 0.059570f, 0.072571f, 0.489258f, 0.542480f, + 0.553223f, 0.558594f, 0.562012f, 0.563965f, 0.000067f, 0.000253f, 0.000305f, 0.000367f, 0.000422f, 0.000431f, 0.000530f, 0.000466f, + 0.000565f, 0.000590f, 0.000702f, 0.000690f, 0.000746f, 0.000795f, 0.000859f, 0.000897f, 0.000962f, 0.001021f, 0.001069f, 0.001105f, + 0.001207f, 0.001257f, 0.001354f, 0.001424f, 0.001483f, 0.001570f, 0.001687f, 0.001750f, 0.001857f, 0.001982f, 0.002071f, 0.002281f, + 0.002361f, 0.002527f, 0.002684f, 0.002846f, 0.003092f, 0.003342f, 0.003622f, 0.003866f, 0.004173f, 0.004520f, 0.004955f, 0.005428f, + 0.006023f, 0.006687f, 0.007481f, 0.008446f, 0.009628f, 0.011047f, 0.012840f, 0.015205f, 0.018326f, 0.022629f, 0.028442f, 0.036102f, + 0.046051f, 0.058197f, 0.476318f, 0.529785f, 0.541992f, 0.547852f, 0.550293f, 0.553223f, 0.000000f, 0.000118f, 0.000216f, 0.000288f, + 0.000272f, 0.000350f, 0.000312f, 0.000374f, 0.000395f, 0.000470f, 0.000488f, 0.000477f, 0.000495f, 0.000548f, 0.000573f, 0.000646f, + 0.000636f, 0.000714f, 0.000763f, 0.000803f, 0.000852f, 0.000897f, 0.000930f, 0.000985f, 0.001056f, 0.001089f, 0.001163f, 0.001210f, + 0.001281f, 0.001432f, 0.001431f, 0.001548f, 0.001622f, 0.001743f, 0.001869f, 0.001991f, 0.002104f, 0.002262f, 0.002428f, 0.002632f, + 0.002815f, 0.003077f, 0.003344f, 0.003656f, 0.004002f, 0.004478f, 0.004974f, 0.005627f, 0.006435f, 0.007481f, 0.008713f, 0.010307f, + 0.012291f, 0.015289f, 0.019409f, 0.025497f, 0.033966f, 0.045013f, 0.461914f, 0.517090f, 0.529297f, 0.536133f, 0.539551f, 0.541504f, + 0.000073f, 0.000175f, 0.000165f, 0.000149f, 0.000200f, 0.000208f, 0.000215f, 0.000260f, 0.000268f, 0.000277f, 0.000292f, 0.000341f, + 0.000334f, 0.000370f, 0.000413f, 0.000424f, 0.000449f, 0.000474f, 0.000488f, 0.000507f, 0.000555f, 0.000574f, 0.000616f, 0.000652f, + 0.000696f, 0.000746f, 0.000780f, 0.000804f, 0.000849f, 0.000888f, 0.000949f, 0.001011f, 0.001075f, 0.001151f, 0.001225f, 0.001266f, + 0.001385f, 0.001466f, 0.001596f, 0.001699f, 0.001808f, 0.001980f, 0.002157f, 0.002329f, 0.002544f, 0.002850f, 0.003178f, 0.003593f, + 0.004047f, 0.004658f, 0.005508f, 0.006565f, 0.007935f, 0.009819f, 0.012527f, 0.016647f, 0.023514f, 0.033173f, 0.447510f, 0.503906f, + 0.517578f, 0.523926f, 0.527344f, 0.529297f, 0.000000f, 0.000106f, 0.000097f, 0.000099f, 0.000136f, 0.000157f, 0.000129f, 0.000162f, + 0.000167f, 0.000172f, 0.000180f, 0.000186f, 0.000209f, 0.000227f, 0.000232f, 0.000248f, 0.000260f, 0.000291f, 0.000300f, 0.000327f, + 0.000335f, 0.000343f, 0.000363f, 0.000395f, 0.000428f, 0.000459f, 0.000458f, 0.000477f, 0.000515f, 0.000549f, 0.000578f, 0.000621f, + 0.000659f, 0.000683f, 0.000741f, 0.000767f, 0.000818f, 0.000877f, 0.000952f, 0.001010f, 0.001085f, 0.001177f, 0.001275f, 0.001406f, + 0.001516f, 0.001664f, 0.001884f, 0.002096f, 0.002415f, 0.002745f, 0.003231f, 0.003843f, 0.004715f, 0.005936f, 0.007629f, 0.010139f, + 0.014763f, 0.022812f, 0.433350f, 0.491455f, 0.506348f, 0.511719f, 0.515625f, 0.518066f, 0.000104f, 0.000080f, 0.000069f, 0.000062f, + 0.000074f, 0.000074f, 0.000089f, 0.000097f, 0.000099f, 0.000102f, 0.000105f, 0.000126f, 0.000106f, 0.000119f, 0.000139f, 0.000135f, + 0.000154f, 0.000164f, 0.000166f, 0.000175f, 0.000188f, 0.000194f, 0.000211f, 0.000220f, 0.000252f, 0.000248f, 0.000260f, 0.000272f, + 0.000293f, 0.000301f, 0.000328f, 0.000347f, 0.000365f, 0.000371f, 0.000401f, 0.000422f, 0.000447f, 0.000489f, 0.000524f, 0.000553f, + 0.000588f, 0.000635f, 0.000701f, 0.000751f, 0.000816f, 0.000897f, 0.000997f, 0.001109f, 0.001265f, 0.001460f, 0.001686f, 0.002035f, + 0.002457f, 0.003130f, 0.004124f, 0.005676f, 0.008263f, 0.014114f, 0.418945f, 0.479492f, 0.493652f, 0.500000f, 0.503418f, 0.506836f, + 0.000089f, 0.000065f, 0.000056f, 0.000050f, 0.000045f, 0.000042f, 0.000046f, 0.000042f, 0.000043f, 0.000055f, 0.000046f, 0.000049f, + 0.000065f, 0.000055f, 0.000057f, 0.000063f, 0.000075f, 0.000080f, 0.000078f, 0.000084f, 0.000085f, 0.000092f, 0.000097f, 0.000102f, + 0.000108f, 0.000117f, 0.000118f, 0.000138f, 0.000135f, 0.000142f, 0.000151f, 0.000160f, 0.000172f, 0.000180f, 0.000195f, 0.000197f, + 0.000210f, 0.000230f, 0.000244f, 0.000266f, 0.000279f, 0.000299f, 0.000324f, 0.000352f, 0.000383f, 0.000414f, 0.000457f, 0.000509f, + 0.000575f, 0.000650f, 0.000756f, 0.000904f, 0.001103f, 0.001410f, 0.001880f, 0.002668f, 0.004112f, 0.007290f, 0.404541f, 0.466309f, + 0.481201f, 0.488037f, 0.492432f, 0.495361f, 0.000066f, 0.000046f, 0.000038f, 0.000034f, 0.000031f, 0.000029f, 0.000027f, 0.000026f, + 0.000025f, 0.000023f, 0.000022f, 0.000024f, 0.000020f, 0.000021f, 0.000021f, 0.000026f, 0.000024f, 0.000028f, 0.000031f, 0.000032f, + 0.000032f, 0.000035f, 0.000040f, 0.000038f, 0.000041f, 0.000047f, 0.000049f, 0.000043f, 0.000050f, 0.000052f, 0.000056f, 0.000059f, + 0.000066f, 0.000062f, 0.000067f, 0.000071f, 0.000082f, 0.000083f, 0.000089f, 0.000098f, 0.000104f, 0.000107f, 0.000116f, 0.000125f, + 0.000141f, 0.000149f, 0.000160f, 0.000183f, 0.000207f, 0.000228f, 0.000264f, 0.000311f, 0.000376f, 0.000469f, 0.000646f, 0.000937f, + 0.001554f, 0.002983f, 0.390381f, 0.454346f, 0.469727f, 0.476318f, 0.480713f, 0.484131f, 0.000028f, 0.000019f, 0.000015f, 0.000014f, + 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f, + 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000007f, 0.000008f, 0.000009f, 0.000009f, 0.000010f, + 0.000010f, 0.000011f, 0.000012f, 0.000011f, 0.000014f, 0.000015f, 0.000016f, 0.000016f, 0.000018f, 0.000019f, 0.000019f, 0.000022f, + 0.000023f, 0.000024f, 0.000026f, 0.000028f, 0.000029f, 0.000032f, 0.000037f, 0.000037f, 0.000042f, 0.000048f, 0.000056f, 0.000066f, + 0.000077f, 0.000091f, 0.000124f, 0.000183f, 0.000318f, 0.000779f, 0.376465f, 0.441406f, 0.457275f, 0.464600f, 0.468994f, 0.471924f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, + 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, + 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000005f, 0.000010f, 0.000027f, 0.363037f, 0.428223f, + 0.444580f, 0.452881f, 0.457031f, 0.459961f, + }, + { + 0.014420f, 0.043488f, 0.072388f, 0.100830f, 0.129150f, 0.156494f, 0.183350f, 0.210327f, 0.235352f, 0.260986f, 0.285645f, 0.309082f, + 0.332764f, 0.355713f, 0.377441f, 0.399658f, 0.420898f, 0.441650f, 0.461914f, 0.481445f, 0.500977f, 0.520508f, 0.538574f, 0.556641f, + 0.574707f, 0.591797f, 0.608398f, 0.624512f, 0.641602f, 0.657227f, 0.672363f, 0.687500f, 0.702148f, 0.717285f, 0.730957f, 0.745117f, + 0.758789f, 0.772461f, 0.783203f, 0.797363f, 0.810547f, 0.822266f, 0.833984f, 0.845703f, 0.857422f, 0.868652f, 0.879395f, 0.890625f, + 0.901367f, 0.911621f, 0.921875f, 0.932129f, 0.941895f, 0.951660f, 0.960938f, 0.970215f, 0.979492f, 0.987793f, 0.981934f, 0.957031f, + 0.938965f, 0.923340f, 0.909668f, 0.897461f, 0.013199f, 0.039978f, 0.066284f, 0.093445f, 0.119324f, 0.145386f, 0.170410f, 0.195801f, + 0.220581f, 0.244019f, 0.268066f, 0.291260f, 0.314453f, 0.335938f, 0.358154f, 0.379639f, 0.399902f, 0.420898f, 0.441406f, 0.460938f, + 0.480225f, 0.498291f, 0.516602f, 0.535156f, 0.553223f, 0.570312f, 0.587891f, 0.603516f, 0.620117f, 0.636719f, 0.652832f, 0.667480f, + 0.682617f, 0.696777f, 0.711914f, 0.726074f, 0.739746f, 0.753418f, 0.766602f, 0.779785f, 0.791992f, 0.804688f, 0.817871f, 0.829102f, + 0.841309f, 0.852539f, 0.864258f, 0.875488f, 0.886230f, 0.896973f, 0.907227f, 0.917969f, 0.928223f, 0.937500f, 0.947266f, 0.957520f, + 0.966797f, 0.975586f, 0.976562f, 0.952637f, 0.935547f, 0.920898f, 0.907715f, 0.895996f, 0.011932f, 0.036499f, 0.061554f, 0.085999f, + 0.110962f, 0.135010f, 0.158813f, 0.182373f, 0.206421f, 0.229004f, 0.251221f, 0.274170f, 0.295654f, 0.317871f, 0.339111f, 0.360107f, + 0.379395f, 0.399414f, 0.420654f, 0.440430f, 0.458252f, 0.477295f, 0.496094f, 0.513672f, 0.531738f, 0.549805f, 0.566406f, 0.583984f, + 0.599121f, 0.616211f, 0.631348f, 0.647461f, 0.662598f, 0.677734f, 0.692383f, 0.705566f, 0.720703f, 0.734863f, 0.748047f, 0.761230f, + 0.774414f, 0.787598f, 0.799805f, 0.812500f, 0.824707f, 0.837402f, 0.848633f, 0.859375f, 0.871094f, 0.882324f, 0.892578f, 0.904297f, + 0.913574f, 0.924316f, 0.934570f, 0.943848f, 0.954102f, 0.963867f, 0.970703f, 0.948242f, 0.931641f, 0.917480f, 0.905273f, 0.894043f, + 0.011070f, 0.033478f, 0.056396f, 0.079529f, 0.101990f, 0.125244f, 0.147705f, 0.170410f, 0.192139f, 0.214111f, 0.235596f, 0.257812f, + 0.279053f, 0.300293f, 0.320557f, 0.340576f, 0.360596f, 0.381104f, 0.400635f, 0.420166f, 0.438965f, 0.458008f, 0.476562f, 0.493652f, + 0.511230f, 0.527832f, 0.545898f, 0.562012f, 0.579102f, 0.595703f, 0.610840f, 0.627930f, 0.642578f, 0.657227f, 0.672363f, 0.686523f, + 0.701660f, 0.715332f, 0.729492f, 0.742676f, 0.756348f, 0.769531f, 0.782227f, 0.795898f, 0.807617f, 0.820312f, 0.832031f, 0.843262f, + 0.855469f, 0.866699f, 0.877441f, 0.889648f, 0.899414f, 0.910156f, 0.920410f, 0.930664f, 0.940430f, 0.950684f, 0.964844f, 0.943848f, + 0.927734f, 0.914551f, 0.902344f, 0.891602f, 0.010010f, 0.031067f, 0.051880f, 0.073303f, 0.094421f, 0.116577f, 0.136963f, 0.157959f, + 0.180542f, 0.200684f, 0.221436f, 0.242676f, 0.262939f, 0.283447f, 0.303467f, 0.323242f, 0.342529f, 0.362305f, 0.381348f, 0.399414f, + 0.418701f, 0.437256f, 0.455322f, 0.472412f, 0.490479f, 0.507812f, 0.524902f, 0.541992f, 0.558105f, 0.574219f, 0.591309f, 0.606445f, + 0.622070f, 0.637695f, 0.652344f, 0.666504f, 0.683594f, 0.695801f, 0.710449f, 0.724121f, 0.737305f, 0.751465f, 0.765137f, 0.777344f, + 0.790039f, 0.802734f, 0.814941f, 0.827637f, 0.839355f, 0.851074f, 0.862305f, 0.874512f, 0.885254f, 0.895996f, 0.906738f, 0.917480f, + 0.927246f, 0.937988f, 0.958984f, 0.939453f, 0.923828f, 0.911133f, 0.899414f, 0.889160f, 0.009491f, 0.028305f, 0.047699f, 0.067810f, + 0.087341f, 0.107849f, 0.127686f, 0.147827f, 0.167725f, 0.187744f, 0.207886f, 0.227051f, 0.247314f, 0.266846f, 0.286377f, 0.305908f, + 0.324463f, 0.343262f, 0.361572f, 0.380371f, 0.399658f, 0.416748f, 0.435547f, 0.452881f, 0.470703f, 0.488281f, 0.503906f, 0.522461f, + 0.538086f, 0.554199f, 0.571289f, 0.586914f, 0.602051f, 0.617676f, 0.633789f, 0.647949f, 0.663086f, 0.677246f, 0.692871f, 0.705078f, + 0.718750f, 0.732910f, 0.746582f, 0.759766f, 0.773438f, 0.785645f, 0.798340f, 0.811035f, 0.823242f, 0.834961f, 0.847168f, 0.859863f, + 0.870117f, 0.881348f, 0.893066f, 0.903320f, 0.914551f, 0.924316f, 0.953125f, 0.934082f, 0.919434f, 0.906738f, 0.896484f, 0.885742f, + 0.008598f, 0.026245f, 0.044495f, 0.062622f, 0.081177f, 0.100098f, 0.119019f, 0.137817f, 0.156616f, 0.175903f, 0.194946f, 0.213745f, + 0.232788f, 0.251221f, 0.269775f, 0.288330f, 0.307129f, 0.325928f, 0.344238f, 0.362305f, 0.380371f, 0.397705f, 0.415771f, 0.433105f, + 0.450928f, 0.468262f, 0.484863f, 0.501953f, 0.518555f, 0.534668f, 0.550293f, 0.566406f, 0.582520f, 0.598145f, 0.612305f, 0.627930f, + 0.643555f, 0.657715f, 0.672852f, 0.687500f, 0.700684f, 0.715332f, 0.728516f, 0.742188f, 0.755371f, 0.769531f, 0.781738f, 0.794434f, + 0.807129f, 0.818359f, 0.831543f, 0.843262f, 0.855469f, 0.865723f, 0.877930f, 0.889160f, 0.900391f, 0.911621f, 0.946777f, 0.929199f, + 0.915039f, 0.903320f, 0.892578f, 0.883301f, 0.007896f, 0.024490f, 0.041138f, 0.057892f, 0.075439f, 0.092712f, 0.110229f, 0.128296f, + 0.146118f, 0.164429f, 0.181885f, 0.200562f, 0.218628f, 0.236572f, 0.255127f, 0.272949f, 0.291016f, 0.308594f, 0.326172f, 0.343994f, + 0.361816f, 0.380127f, 0.396973f, 0.414551f, 0.430908f, 0.447998f, 0.465576f, 0.481445f, 0.497559f, 0.514160f, 0.529785f, 0.546387f, + 0.562988f, 0.578613f, 0.593262f, 0.609375f, 0.623047f, 0.638672f, 0.653809f, 0.667480f, 0.681641f, 0.697266f, 0.710938f, 0.724121f, + 0.737305f, 0.752441f, 0.765625f, 0.776367f, 0.790527f, 0.803223f, 0.815918f, 0.827637f, 0.839844f, 0.851562f, 0.863281f, 0.875000f, + 0.886719f, 0.898926f, 0.940430f, 0.923828f, 0.910645f, 0.899414f, 0.889160f, 0.879883f, 0.007320f, 0.022369f, 0.038055f, 0.053925f, + 0.070190f, 0.086609f, 0.103027f, 0.119568f, 0.136475f, 0.153320f, 0.170532f, 0.187988f, 0.204834f, 0.223022f, 0.240112f, 0.257324f, + 0.275391f, 0.291504f, 0.308838f, 0.326904f, 0.344727f, 0.361572f, 0.378662f, 0.395020f, 0.411865f, 0.428711f, 0.445068f, 0.462646f, + 0.478271f, 0.494141f, 0.510254f, 0.525879f, 0.542480f, 0.557129f, 0.573242f, 0.588867f, 0.603516f, 0.618164f, 0.633789f, 0.648438f, + 0.663086f, 0.678223f, 0.691895f, 0.706543f, 0.720215f, 0.733398f, 0.746582f, 0.759766f, 0.774414f, 0.786621f, 0.799805f, 0.811523f, + 0.823730f, 0.836914f, 0.848145f, 0.860840f, 0.872070f, 0.884277f, 0.933594f, 0.918945f, 0.906250f, 0.895020f, 0.885254f, 0.876953f, + 0.006760f, 0.021011f, 0.034973f, 0.050049f, 0.065369f, 0.080261f, 0.095337f, 0.111633f, 0.127319f, 0.142822f, 0.159668f, 0.176514f, + 0.192383f, 0.209106f, 0.225586f, 0.242554f, 0.259277f, 0.275635f, 0.292480f, 0.309326f, 0.326904f, 0.343750f, 0.359619f, 0.376465f, + 0.393066f, 0.409424f, 0.426514f, 0.442871f, 0.458252f, 0.475586f, 0.490967f, 0.505859f, 0.522461f, 0.539062f, 0.554199f, 0.569336f, + 0.583984f, 0.600586f, 0.614258f, 0.630371f, 0.643555f, 0.658691f, 0.673340f, 0.687500f, 0.702148f, 0.715332f, 0.729980f, 0.743652f, + 0.756348f, 0.770020f, 0.782715f, 0.796387f, 0.808105f, 0.820801f, 0.833008f, 0.846680f, 0.857910f, 0.870117f, 0.927246f, 0.913574f, + 0.901367f, 0.891113f, 0.881348f, 0.873047f, 0.006367f, 0.019165f, 0.032379f, 0.046295f, 0.060089f, 0.074463f, 0.088867f, 0.103821f, + 0.118835f, 0.133911f, 0.149048f, 0.164673f, 0.180298f, 0.196289f, 0.212524f, 0.228516f, 0.244385f, 0.260742f, 0.277344f, 0.293213f, + 0.309570f, 0.326416f, 0.342773f, 0.358887f, 0.374512f, 0.391113f, 0.406982f, 0.423340f, 0.439453f, 0.455078f, 0.470947f, 0.487793f, + 0.502441f, 0.519043f, 0.533691f, 0.550293f, 0.564941f, 0.580078f, 0.595703f, 0.610840f, 0.625488f, 0.640137f, 0.654785f, 0.669434f, + 0.683594f, 0.696777f, 0.710938f, 0.725586f, 0.738770f, 0.752441f, 0.766113f, 0.778320f, 0.791016f, 0.805176f, 0.818359f, 0.830566f, + 0.842773f, 0.854980f, 0.920410f, 0.908203f, 0.896484f, 0.886230f, 0.877441f, 0.868652f, 0.005981f, 0.017914f, 0.030350f, 0.042908f, + 0.056213f, 0.069092f, 0.083008f, 0.096619f, 0.111084f, 0.124634f, 0.139526f, 0.154297f, 0.169312f, 0.184570f, 0.199951f, 0.215454f, + 0.230713f, 0.245728f, 0.261963f, 0.277588f, 0.293213f, 0.309326f, 0.325195f, 0.340820f, 0.356934f, 0.373047f, 0.388916f, 0.404785f, + 0.420410f, 0.436279f, 0.452148f, 0.468506f, 0.483154f, 0.499756f, 0.515137f, 0.530762f, 0.545898f, 0.560059f, 0.576172f, 0.590820f, + 0.606445f, 0.621094f, 0.635254f, 0.649902f, 0.663574f, 0.678223f, 0.692383f, 0.706543f, 0.720703f, 0.733887f, 0.748535f, 0.762695f, + 0.775391f, 0.789551f, 0.801758f, 0.814941f, 0.828125f, 0.840332f, 0.913574f, 0.902344f, 0.890625f, 0.881836f, 0.872559f, 0.865234f, + 0.005402f, 0.016617f, 0.028061f, 0.039948f, 0.051758f, 0.064270f, 0.076782f, 0.089600f, 0.102600f, 0.116455f, 0.130371f, 0.144165f, + 0.158936f, 0.172607f, 0.187744f, 0.201904f, 0.216431f, 0.232422f, 0.247192f, 0.261719f, 0.277100f, 0.292480f, 0.308838f, 0.323975f, + 0.339355f, 0.355469f, 0.371338f, 0.386230f, 0.402344f, 0.417725f, 0.433350f, 0.448486f, 0.464600f, 0.480225f, 0.495361f, 0.510742f, + 0.525879f, 0.541992f, 0.557129f, 0.571777f, 0.586914f, 0.601562f, 0.616211f, 0.631836f, 0.645508f, 0.661621f, 0.674805f, 0.688965f, + 0.703125f, 0.717773f, 0.731934f, 0.745605f, 0.757812f, 0.772949f, 0.785156f, 0.799316f, 0.812012f, 0.826172f, 0.906738f, 0.896484f, + 0.886230f, 0.876465f, 0.868164f, 0.860840f, 0.005264f, 0.015457f, 0.026474f, 0.037170f, 0.048157f, 0.059845f, 0.071594f, 0.083984f, + 0.096191f, 0.109070f, 0.121887f, 0.134766f, 0.148193f, 0.161255f, 0.175781f, 0.189209f, 0.203369f, 0.218384f, 0.233032f, 0.247681f, + 0.261963f, 0.277100f, 0.292480f, 0.307129f, 0.322998f, 0.337891f, 0.352539f, 0.368652f, 0.384033f, 0.399170f, 0.414307f, 0.430420f, + 0.445801f, 0.460693f, 0.475342f, 0.491211f, 0.506836f, 0.521973f, 0.537598f, 0.551758f, 0.567383f, 0.582520f, 0.598145f, 0.612305f, + 0.627441f, 0.642090f, 0.656738f, 0.670898f, 0.685059f, 0.698730f, 0.713867f, 0.728516f, 0.742188f, 0.755371f, 0.770020f, 0.782715f, + 0.796387f, 0.810547f, 0.899414f, 0.889648f, 0.879883f, 0.872070f, 0.863770f, 0.856445f, 0.004719f, 0.014229f, 0.024384f, 0.034607f, + 0.044708f, 0.055756f, 0.066895f, 0.077942f, 0.089600f, 0.101624f, 0.113525f, 0.125854f, 0.138428f, 0.151245f, 0.164673f, 0.177734f, + 0.191650f, 0.205078f, 0.219360f, 0.233154f, 0.247925f, 0.261475f, 0.276367f, 0.291504f, 0.305908f, 0.320312f, 0.335449f, 0.350098f, + 0.365723f, 0.380615f, 0.395996f, 0.411133f, 0.427002f, 0.441895f, 0.456543f, 0.472656f, 0.487793f, 0.502441f, 0.518555f, 0.533203f, + 0.547852f, 0.562988f, 0.577637f, 0.593262f, 0.607910f, 0.623535f, 0.638184f, 0.652344f, 0.666992f, 0.681641f, 0.696777f, 0.711426f, + 0.725098f, 0.738281f, 0.753418f, 0.766113f, 0.782227f, 0.794922f, 0.892090f, 0.884277f, 0.875000f, 0.866699f, 0.858887f, 0.852539f, + 0.004280f, 0.013329f, 0.022476f, 0.031982f, 0.042114f, 0.051849f, 0.062225f, 0.072449f, 0.083679f, 0.095032f, 0.105530f, 0.117676f, + 0.129517f, 0.141357f, 0.154297f, 0.166748f, 0.178711f, 0.192505f, 0.205933f, 0.219727f, 0.233521f, 0.247070f, 0.260986f, 0.275391f, + 0.290039f, 0.303955f, 0.319580f, 0.333740f, 0.347412f, 0.363037f, 0.377686f, 0.392822f, 0.408203f, 0.422852f, 0.437988f, 0.453125f, + 0.468506f, 0.483398f, 0.498779f, 0.514160f, 0.527832f, 0.543945f, 0.559570f, 0.574707f, 0.588867f, 0.604492f, 0.619141f, 0.634277f, + 0.648438f, 0.663086f, 0.678223f, 0.692383f, 0.707520f, 0.721680f, 0.735352f, 0.749512f, 0.764648f, 0.778320f, 0.884277f, 0.877441f, + 0.868652f, 0.861328f, 0.854492f, 0.847656f, 0.004280f, 0.012138f, 0.021103f, 0.029999f, 0.038940f, 0.048279f, 0.057831f, 0.067566f, + 0.077454f, 0.087524f, 0.098816f, 0.109558f, 0.120728f, 0.131958f, 0.143799f, 0.155762f, 0.168091f, 0.180176f, 0.193359f, 0.206177f, + 0.219360f, 0.232910f, 0.246338f, 0.260254f, 0.273682f, 0.287598f, 0.302246f, 0.316650f, 0.331299f, 0.344971f, 0.359863f, 0.374268f, + 0.389648f, 0.404297f, 0.419434f, 0.434326f, 0.449463f, 0.464844f, 0.479492f, 0.494141f, 0.509766f, 0.524414f, 0.540039f, 0.555176f, + 0.569824f, 0.584961f, 0.600098f, 0.615723f, 0.629883f, 0.645508f, 0.659668f, 0.675293f, 0.689453f, 0.704590f, 0.719238f, 0.732422f, + 0.748535f, 0.762207f, 0.876953f, 0.871582f, 0.863281f, 0.855957f, 0.849609f, 0.842773f, 0.003744f, 0.011436f, 0.019348f, 0.027893f, + 0.036102f, 0.044739f, 0.053711f, 0.063110f, 0.072205f, 0.081970f, 0.091919f, 0.101746f, 0.112732f, 0.122864f, 0.134521f, 0.145996f, + 0.157715f, 0.169434f, 0.181519f, 0.193848f, 0.206665f, 0.219360f, 0.231445f, 0.245361f, 0.259033f, 0.272217f, 0.286621f, 0.299805f, + 0.314209f, 0.328125f, 0.342285f, 0.357178f, 0.371826f, 0.386475f, 0.400635f, 0.415527f, 0.430420f, 0.445068f, 0.459717f, 0.476074f, + 0.490234f, 0.505371f, 0.521484f, 0.536133f, 0.551758f, 0.565430f, 0.581543f, 0.595703f, 0.611816f, 0.626465f, 0.641602f, 0.656738f, + 0.671875f, 0.686523f, 0.701172f, 0.715820f, 0.731445f, 0.746582f, 0.868652f, 0.864746f, 0.856934f, 0.851074f, 0.844727f, 0.837891f, + 0.003595f, 0.011093f, 0.018265f, 0.025711f, 0.033600f, 0.041656f, 0.050140f, 0.058350f, 0.067505f, 0.076416f, 0.085632f, 0.095093f, + 0.104919f, 0.115295f, 0.125610f, 0.136108f, 0.147583f, 0.157959f, 0.169800f, 0.181519f, 0.193359f, 0.205933f, 0.218140f, 0.231323f, + 0.243652f, 0.257324f, 0.270508f, 0.283447f, 0.297363f, 0.311523f, 0.325928f, 0.339111f, 0.353516f, 0.367432f, 0.382812f, 0.396973f, + 0.412109f, 0.426758f, 0.441406f, 0.456055f, 0.471436f, 0.486328f, 0.501953f, 0.516113f, 0.531738f, 0.546875f, 0.562500f, 0.577637f, + 0.592773f, 0.607910f, 0.622559f, 0.638184f, 0.653809f, 0.669434f, 0.684082f, 0.699219f, 0.714355f, 0.729492f, 0.860840f, 0.857422f, + 0.852051f, 0.844727f, 0.839355f, 0.832520f, 0.003349f, 0.009933f, 0.016754f, 0.024063f, 0.031204f, 0.038849f, 0.046356f, 0.054413f, + 0.062744f, 0.070984f, 0.080017f, 0.088989f, 0.097778f, 0.107361f, 0.117004f, 0.127197f, 0.137451f, 0.148071f, 0.159180f, 0.169922f, + 0.181519f, 0.192993f, 0.204956f, 0.217407f, 0.229980f, 0.242188f, 0.254883f, 0.267578f, 0.281494f, 0.294434f, 0.307861f, 0.321533f, + 0.335693f, 0.350098f, 0.364258f, 0.379150f, 0.393066f, 0.407715f, 0.422607f, 0.437500f, 0.452148f, 0.467041f, 0.482422f, 0.497314f, + 0.512695f, 0.527832f, 0.542969f, 0.558594f, 0.573730f, 0.589844f, 0.604004f, 0.619629f, 0.635254f, 0.651367f, 0.665527f, 0.681152f, + 0.696289f, 0.711914f, 0.852539f, 0.851562f, 0.846191f, 0.838867f, 0.832520f, 0.827637f, 0.003290f, 0.009415f, 0.015976f, 0.022095f, + 0.028946f, 0.036255f, 0.043396f, 0.050598f, 0.058502f, 0.066284f, 0.074036f, 0.082275f, 0.091187f, 0.099731f, 0.108826f, 0.118652f, + 0.128296f, 0.137939f, 0.148193f, 0.159302f, 0.170166f, 0.180786f, 0.191895f, 0.203491f, 0.215210f, 0.227661f, 0.240112f, 0.252686f, + 0.265625f, 0.278564f, 0.291748f, 0.305176f, 0.318604f, 0.332764f, 0.346924f, 0.360352f, 0.375000f, 0.389160f, 0.404297f, 0.418213f, + 0.433105f, 0.448486f, 0.463135f, 0.477783f, 0.493408f, 0.508301f, 0.523438f, 0.540039f, 0.554199f, 0.570312f, 0.585938f, 0.601074f, + 0.617188f, 0.633301f, 0.648926f, 0.664062f, 0.679688f, 0.695312f, 0.844727f, 0.844238f, 0.838867f, 0.833008f, 0.827148f, 0.822266f, + 0.002913f, 0.008621f, 0.014595f, 0.020950f, 0.027496f, 0.033600f, 0.040558f, 0.047119f, 0.054260f, 0.061615f, 0.068970f, 0.076782f, + 0.084717f, 0.093140f, 0.101562f, 0.109985f, 0.118591f, 0.129150f, 0.138306f, 0.148682f, 0.158447f, 0.169189f, 0.180054f, 0.191162f, + 0.202148f, 0.213379f, 0.225586f, 0.237305f, 0.250488f, 0.262939f, 0.275391f, 0.288086f, 0.302490f, 0.315186f, 0.329346f, 0.342529f, + 0.356934f, 0.370117f, 0.385742f, 0.400146f, 0.414795f, 0.429199f, 0.444336f, 0.459473f, 0.473389f, 0.489258f, 0.503906f, 0.519531f, + 0.535645f, 0.551270f, 0.566895f, 0.582520f, 0.598145f, 0.614258f, 0.629395f, 0.645996f, 0.661621f, 0.677734f, 0.837402f, 0.836914f, + 0.832520f, 0.826660f, 0.821777f, 0.816406f, 0.002748f, 0.008018f, 0.014168f, 0.019196f, 0.025040f, 0.031250f, 0.037506f, 0.043732f, + 0.050415f, 0.057098f, 0.063721f, 0.071167f, 0.078979f, 0.086609f, 0.094299f, 0.102783f, 0.111145f, 0.119812f, 0.128296f, 0.138306f, + 0.147583f, 0.157593f, 0.168213f, 0.178711f, 0.188843f, 0.200317f, 0.211792f, 0.223511f, 0.235352f, 0.247192f, 0.259521f, 0.272461f, + 0.285156f, 0.298584f, 0.312012f, 0.324707f, 0.339111f, 0.352783f, 0.366943f, 0.381348f, 0.395996f, 0.410889f, 0.425537f, 0.439941f, + 0.454834f, 0.470459f, 0.485352f, 0.501953f, 0.516113f, 0.531738f, 0.547363f, 0.563477f, 0.579102f, 0.595703f, 0.611328f, 0.626953f, + 0.642578f, 0.659668f, 0.828125f, 0.830566f, 0.825684f, 0.820801f, 0.815430f, 0.811035f, 0.002630f, 0.007412f, 0.012978f, 0.018356f, + 0.023758f, 0.028931f, 0.034729f, 0.040894f, 0.046631f, 0.053101f, 0.059143f, 0.065979f, 0.073669f, 0.080200f, 0.087585f, 0.095276f, + 0.102844f, 0.111633f, 0.119812f, 0.128296f, 0.137573f, 0.146729f, 0.156128f, 0.166382f, 0.176880f, 0.187256f, 0.197998f, 0.209351f, + 0.220581f, 0.232422f, 0.244385f, 0.256592f, 0.268799f, 0.281982f, 0.294922f, 0.308105f, 0.321045f, 0.334717f, 0.348633f, 0.363525f, + 0.378174f, 0.391846f, 0.406006f, 0.420898f, 0.436279f, 0.451660f, 0.466064f, 0.481934f, 0.496826f, 0.513184f, 0.528320f, 0.543945f, + 0.560059f, 0.576660f, 0.592285f, 0.608887f, 0.625000f, 0.640625f, 0.819336f, 0.822266f, 0.818848f, 0.813965f, 0.810059f, 0.805664f, + 0.002201f, 0.007240f, 0.011803f, 0.016617f, 0.021622f, 0.027344f, 0.032288f, 0.037598f, 0.043427f, 0.049194f, 0.055267f, 0.061462f, + 0.067566f, 0.073853f, 0.080872f, 0.088013f, 0.095703f, 0.103821f, 0.111145f, 0.119446f, 0.127563f, 0.136597f, 0.145752f, 0.155273f, + 0.165039f, 0.174683f, 0.185181f, 0.195801f, 0.206543f, 0.218140f, 0.229370f, 0.241455f, 0.253174f, 0.265381f, 0.278564f, 0.291504f, + 0.304199f, 0.317383f, 0.331299f, 0.344971f, 0.358643f, 0.373291f, 0.386963f, 0.402100f, 0.416016f, 0.431641f, 0.447266f, 0.462646f, + 0.477295f, 0.493652f, 0.509277f, 0.524902f, 0.541504f, 0.557617f, 0.574219f, 0.589844f, 0.605957f, 0.623047f, 0.810059f, 0.814453f, + 0.811035f, 0.807129f, 0.803223f, 0.798828f, 0.002293f, 0.006927f, 0.010994f, 0.015617f, 0.020584f, 0.025131f, 0.029663f, 0.034760f, + 0.040192f, 0.045532f, 0.050964f, 0.056793f, 0.062805f, 0.068726f, 0.074890f, 0.081482f, 0.088806f, 0.096069f, 0.103333f, 0.110535f, + 0.118896f, 0.126709f, 0.135254f, 0.144165f, 0.153442f, 0.162720f, 0.172119f, 0.182495f, 0.192749f, 0.203735f, 0.214600f, 0.225952f, + 0.237793f, 0.250000f, 0.261719f, 0.274170f, 0.287354f, 0.300293f, 0.313477f, 0.326904f, 0.340820f, 0.354980f, 0.369385f, 0.383545f, + 0.396973f, 0.411865f, 0.427734f, 0.442871f, 0.458740f, 0.473633f, 0.489502f, 0.505859f, 0.522461f, 0.537598f, 0.553711f, 0.572754f, + 0.588379f, 0.604492f, 0.802246f, 0.807617f, 0.804199f, 0.800781f, 0.797363f, 0.792969f, 0.002081f, 0.006172f, 0.010460f, 0.014503f, + 0.019104f, 0.023163f, 0.027832f, 0.032410f, 0.037354f, 0.041992f, 0.047211f, 0.052490f, 0.057831f, 0.063232f, 0.069458f, 0.075317f, + 0.082153f, 0.088257f, 0.094910f, 0.102295f, 0.110107f, 0.117554f, 0.125122f, 0.133667f, 0.142456f, 0.151001f, 0.160767f, 0.169922f, + 0.179443f, 0.190430f, 0.200562f, 0.211914f, 0.222412f, 0.234009f, 0.245850f, 0.258545f, 0.270752f, 0.283203f, 0.296387f, 0.309082f, + 0.322998f, 0.336670f, 0.350098f, 0.364990f, 0.378906f, 0.393311f, 0.408936f, 0.423096f, 0.438965f, 0.454834f, 0.470703f, 0.486572f, + 0.502441f, 0.518555f, 0.534668f, 0.551270f, 0.569336f, 0.585938f, 0.792480f, 0.799316f, 0.797363f, 0.793457f, 0.790039f, 0.786621f, + 0.002028f, 0.005669f, 0.009705f, 0.013565f, 0.017532f, 0.021286f, 0.025574f, 0.030197f, 0.034180f, 0.038757f, 0.043488f, 0.048737f, + 0.053497f, 0.058594f, 0.064026f, 0.070007f, 0.075623f, 0.081360f, 0.088135f, 0.094238f, 0.101379f, 0.108643f, 0.116028f, 0.123718f, + 0.131592f, 0.140137f, 0.149048f, 0.157715f, 0.167114f, 0.176636f, 0.187012f, 0.197388f, 0.208130f, 0.219238f, 0.230347f, 0.241943f, + 0.254150f, 0.266113f, 0.279053f, 0.291504f, 0.304932f, 0.318848f, 0.332031f, 0.345947f, 0.360107f, 0.375000f, 0.389404f, 0.404541f, + 0.419922f, 0.434814f, 0.450684f, 0.466553f, 0.482910f, 0.499023f, 0.516113f, 0.533203f, 0.550293f, 0.567383f, 0.783203f, 0.790527f, + 0.789551f, 0.786621f, 0.783691f, 0.780762f, 0.001852f, 0.005554f, 0.008957f, 0.012642f, 0.016296f, 0.020172f, 0.024033f, 0.027878f, + 0.031677f, 0.035919f, 0.040253f, 0.044952f, 0.049255f, 0.053955f, 0.058960f, 0.063965f, 0.069336f, 0.074951f, 0.080933f, 0.087219f, + 0.093201f, 0.100159f, 0.106689f, 0.114197f, 0.121521f, 0.129517f, 0.137817f, 0.146118f, 0.155151f, 0.164307f, 0.173462f, 0.183472f, + 0.193970f, 0.204224f, 0.215210f, 0.226562f, 0.238037f, 0.250244f, 0.262451f, 0.274902f, 0.287598f, 0.301025f, 0.314209f, 0.327393f, + 0.342041f, 0.356445f, 0.370850f, 0.385254f, 0.400879f, 0.415771f, 0.431396f, 0.446777f, 0.463379f, 0.480469f, 0.497314f, 0.514160f, + 0.530273f, 0.547363f, 0.774414f, 0.783203f, 0.782715f, 0.779297f, 0.776367f, 0.773438f, 0.001690f, 0.005207f, 0.008278f, 0.011696f, + 0.015068f, 0.018784f, 0.022186f, 0.025909f, 0.029221f, 0.033508f, 0.037109f, 0.041321f, 0.045471f, 0.049774f, 0.054108f, 0.058838f, + 0.063843f, 0.069214f, 0.074280f, 0.080078f, 0.086243f, 0.091980f, 0.098083f, 0.105164f, 0.111877f, 0.119446f, 0.126953f, 0.134888f, + 0.143555f, 0.151978f, 0.161133f, 0.170532f, 0.180176f, 0.189697f, 0.200684f, 0.211182f, 0.222412f, 0.234009f, 0.245972f, 0.257568f, + 0.270508f, 0.282959f, 0.295898f, 0.309570f, 0.323486f, 0.337158f, 0.351562f, 0.366211f, 0.381104f, 0.396729f, 0.411865f, 0.427490f, + 0.443604f, 0.459961f, 0.477051f, 0.494385f, 0.510742f, 0.529297f, 0.763184f, 0.774902f, 0.773438f, 0.771973f, 0.769043f, 0.767578f, + 0.001528f, 0.004692f, 0.007587f, 0.010956f, 0.014221f, 0.016907f, 0.020218f, 0.023407f, 0.027283f, 0.030273f, 0.033997f, 0.038055f, + 0.041809f, 0.045959f, 0.049683f, 0.053955f, 0.058838f, 0.063171f, 0.068176f, 0.073120f, 0.078491f, 0.084473f, 0.090332f, 0.096619f, + 0.102905f, 0.109619f, 0.116699f, 0.124207f, 0.131958f, 0.140503f, 0.148438f, 0.157349f, 0.166626f, 0.176392f, 0.186157f, 0.196045f, + 0.207031f, 0.218018f, 0.229736f, 0.241699f, 0.253174f, 0.265381f, 0.278320f, 0.291748f, 0.305176f, 0.318848f, 0.333496f, 0.347412f, + 0.362305f, 0.376709f, 0.392822f, 0.407715f, 0.424072f, 0.440430f, 0.457031f, 0.473633f, 0.491211f, 0.508789f, 0.753906f, 0.766602f, + 0.767090f, 0.764160f, 0.761719f, 0.759766f, 0.001261f, 0.004250f, 0.007389f, 0.010185f, 0.013023f, 0.015976f, 0.018692f, 0.021713f, + 0.024734f, 0.028183f, 0.031464f, 0.034943f, 0.038452f, 0.041870f, 0.045410f, 0.049561f, 0.054047f, 0.058044f, 0.062164f, 0.067017f, + 0.071838f, 0.077332f, 0.082581f, 0.088318f, 0.094360f, 0.100525f, 0.107117f, 0.114258f, 0.121643f, 0.128540f, 0.136841f, 0.144897f, + 0.153931f, 0.162476f, 0.171875f, 0.182007f, 0.192139f, 0.202637f, 0.213623f, 0.224854f, 0.237183f, 0.248657f, 0.260986f, 0.274170f, + 0.287354f, 0.300781f, 0.314453f, 0.328613f, 0.343018f, 0.358643f, 0.373291f, 0.388916f, 0.404785f, 0.420654f, 0.437744f, 0.454590f, + 0.471924f, 0.489990f, 0.744629f, 0.757812f, 0.757812f, 0.756836f, 0.754395f, 0.752441f, 0.001527f, 0.004047f, 0.006680f, 0.009369f, + 0.012024f, 0.014618f, 0.017288f, 0.020248f, 0.022705f, 0.025803f, 0.028778f, 0.031769f, 0.034912f, 0.038330f, 0.041595f, 0.045166f, + 0.048737f, 0.052673f, 0.056885f, 0.061218f, 0.065552f, 0.070251f, 0.075012f, 0.080505f, 0.086060f, 0.091614f, 0.097656f, 0.104065f, + 0.110901f, 0.118225f, 0.125366f, 0.133179f, 0.141357f, 0.149902f, 0.158569f, 0.168213f, 0.177734f, 0.187866f, 0.198364f, 0.208984f, + 0.220581f, 0.232422f, 0.244019f, 0.256836f, 0.269287f, 0.282471f, 0.296143f, 0.309326f, 0.324463f, 0.338379f, 0.353760f, 0.368652f, + 0.385498f, 0.400635f, 0.417725f, 0.434570f, 0.451660f, 0.469482f, 0.733887f, 0.749023f, 0.750977f, 0.749023f, 0.747070f, 0.744629f, + 0.001313f, 0.003803f, 0.006126f, 0.008507f, 0.011185f, 0.013550f, 0.015839f, 0.018219f, 0.021027f, 0.023438f, 0.026520f, 0.029129f, + 0.031738f, 0.034821f, 0.037964f, 0.041138f, 0.044434f, 0.048035f, 0.051636f, 0.055420f, 0.059540f, 0.063782f, 0.068176f, 0.073181f, + 0.077881f, 0.083496f, 0.088989f, 0.094849f, 0.101440f, 0.107849f, 0.114441f, 0.121887f, 0.129395f, 0.137207f, 0.145874f, 0.154419f, + 0.163574f, 0.173462f, 0.183228f, 0.193726f, 0.204712f, 0.216064f, 0.227661f, 0.239624f, 0.251709f, 0.264648f, 0.277832f, 0.291504f, + 0.305664f, 0.320312f, 0.334473f, 0.349854f, 0.365479f, 0.380615f, 0.397217f, 0.414551f, 0.432129f, 0.449951f, 0.722656f, 0.740234f, + 0.741699f, 0.741211f, 0.739746f, 0.737793f, 0.001137f, 0.003654f, 0.005871f, 0.007881f, 0.010262f, 0.012268f, 0.014496f, 0.017059f, + 0.018890f, 0.021317f, 0.023605f, 0.026291f, 0.029007f, 0.031494f, 0.034515f, 0.036987f, 0.040375f, 0.043457f, 0.046936f, 0.050385f, + 0.053925f, 0.058044f, 0.061981f, 0.066650f, 0.070679f, 0.075562f, 0.080994f, 0.085938f, 0.091919f, 0.098450f, 0.104370f, 0.110840f, + 0.118164f, 0.125366f, 0.133301f, 0.141357f, 0.150024f, 0.159546f, 0.168457f, 0.178711f, 0.189453f, 0.199707f, 0.211060f, 0.222656f, + 0.234741f, 0.247314f, 0.260010f, 0.272705f, 0.287354f, 0.300781f, 0.315674f, 0.330322f, 0.345947f, 0.362061f, 0.377441f, 0.394775f, + 0.412109f, 0.429199f, 0.712891f, 0.730957f, 0.733398f, 0.733398f, 0.731445f, 0.729492f, 0.001163f, 0.003218f, 0.005329f, 0.007542f, + 0.009331f, 0.011330f, 0.013367f, 0.015434f, 0.017685f, 0.019714f, 0.021515f, 0.024139f, 0.026062f, 0.028763f, 0.031204f, 0.033722f, + 0.036163f, 0.039398f, 0.041992f, 0.045624f, 0.048553f, 0.051971f, 0.056000f, 0.059937f, 0.063904f, 0.068054f, 0.072876f, 0.077820f, + 0.083374f, 0.088623f, 0.094116f, 0.100830f, 0.107117f, 0.114197f, 0.121399f, 0.129272f, 0.136963f, 0.145630f, 0.154785f, 0.163696f, + 0.173828f, 0.184204f, 0.194946f, 0.205933f, 0.217529f, 0.229614f, 0.242676f, 0.255859f, 0.269043f, 0.282471f, 0.296387f, 0.311523f, + 0.326172f, 0.341553f, 0.357910f, 0.374756f, 0.391846f, 0.409180f, 0.701660f, 0.721680f, 0.723633f, 0.724609f, 0.723145f, 0.722656f, + 0.001008f, 0.003147f, 0.004818f, 0.006882f, 0.008530f, 0.010468f, 0.012390f, 0.013832f, 0.016006f, 0.017899f, 0.019608f, 0.021866f, + 0.023849f, 0.025940f, 0.027847f, 0.030350f, 0.032806f, 0.035187f, 0.037994f, 0.040619f, 0.043732f, 0.046875f, 0.050110f, 0.053833f, + 0.057617f, 0.061371f, 0.065613f, 0.070068f, 0.074768f, 0.079895f, 0.085144f, 0.090637f, 0.096863f, 0.103149f, 0.110107f, 0.116943f, + 0.124634f, 0.132568f, 0.140991f, 0.149536f, 0.159302f, 0.169189f, 0.179443f, 0.189575f, 0.201538f, 0.213013f, 0.225342f, 0.236938f, + 0.250244f, 0.264160f, 0.278320f, 0.292236f, 0.307617f, 0.322021f, 0.337891f, 0.354248f, 0.371582f, 0.389160f, 0.689941f, 0.712891f, + 0.715820f, 0.715820f, 0.715820f, 0.714355f, 0.001126f, 0.002708f, 0.004486f, 0.006313f, 0.007927f, 0.009659f, 0.011238f, 0.012833f, + 0.014435f, 0.015823f, 0.017670f, 0.019485f, 0.021347f, 0.023453f, 0.025101f, 0.027161f, 0.029160f, 0.031525f, 0.033752f, 0.036560f, + 0.039154f, 0.041687f, 0.044891f, 0.047943f, 0.051453f, 0.054871f, 0.058655f, 0.062622f, 0.067078f, 0.071411f, 0.076355f, 0.081665f, + 0.086792f, 0.092957f, 0.098877f, 0.105713f, 0.112549f, 0.119995f, 0.127563f, 0.135864f, 0.144897f, 0.154297f, 0.164185f, 0.173828f, + 0.185059f, 0.196045f, 0.208008f, 0.219849f, 0.232666f, 0.245483f, 0.259033f, 0.273438f, 0.287842f, 0.302734f, 0.318604f, 0.334473f, + 0.351318f, 0.369385f, 0.679688f, 0.702637f, 0.707031f, 0.707031f, 0.707031f, 0.705566f, 0.000980f, 0.002733f, 0.004021f, 0.005688f, + 0.007084f, 0.008553f, 0.010345f, 0.011513f, 0.012962f, 0.014297f, 0.015823f, 0.017609f, 0.019119f, 0.020721f, 0.022568f, 0.024200f, + 0.026291f, 0.028000f, 0.030457f, 0.032410f, 0.034912f, 0.037476f, 0.039734f, 0.042786f, 0.045563f, 0.048920f, 0.052185f, 0.055817f, + 0.059662f, 0.063660f, 0.067993f, 0.072632f, 0.077759f, 0.083191f, 0.088623f, 0.094971f, 0.101135f, 0.107849f, 0.115479f, 0.122864f, + 0.131592f, 0.139893f, 0.149414f, 0.158447f, 0.169067f, 0.179443f, 0.191040f, 0.202393f, 0.214478f, 0.227539f, 0.240723f, 0.255127f, + 0.268555f, 0.283447f, 0.298828f, 0.315186f, 0.331787f, 0.348389f, 0.667480f, 0.693359f, 0.697754f, 0.698730f, 0.698242f, 0.697754f, + 0.000870f, 0.002420f, 0.003994f, 0.005165f, 0.006584f, 0.007763f, 0.009209f, 0.010468f, 0.011604f, 0.013336f, 0.013977f, 0.015442f, + 0.016830f, 0.018509f, 0.020065f, 0.021606f, 0.023224f, 0.024933f, 0.026672f, 0.028656f, 0.030914f, 0.033112f, 0.035187f, 0.037689f, + 0.040344f, 0.043335f, 0.046234f, 0.049438f, 0.052948f, 0.056427f, 0.060394f, 0.064331f, 0.069031f, 0.073853f, 0.078735f, 0.084412f, + 0.090271f, 0.096436f, 0.103455f, 0.110229f, 0.118042f, 0.126099f, 0.134766f, 0.143921f, 0.153198f, 0.163696f, 0.174438f, 0.185913f, + 0.197754f, 0.210083f, 0.222778f, 0.235962f, 0.250000f, 0.264648f, 0.279053f, 0.294922f, 0.311279f, 0.328613f, 0.655273f, 0.684082f, + 0.688477f, 0.689941f, 0.689941f, 0.689941f, 0.000790f, 0.002153f, 0.003576f, 0.004726f, 0.005966f, 0.007172f, 0.008186f, 0.009453f, + 0.010521f, 0.011482f, 0.012772f, 0.013771f, 0.015144f, 0.016434f, 0.017792f, 0.019226f, 0.020355f, 0.022049f, 0.023666f, 0.025375f, + 0.027145f, 0.029297f, 0.030975f, 0.033142f, 0.035339f, 0.037964f, 0.040405f, 0.043365f, 0.046478f, 0.049744f, 0.053101f, 0.057068f, + 0.060944f, 0.065063f, 0.069763f, 0.074646f, 0.079956f, 0.085938f, 0.091675f, 0.098083f, 0.105164f, 0.112732f, 0.121033f, 0.129395f, + 0.138428f, 0.148560f, 0.158325f, 0.169067f, 0.180664f, 0.192139f, 0.205078f, 0.217529f, 0.231934f, 0.246094f, 0.260010f, 0.275391f, + 0.292236f, 0.309570f, 0.644043f, 0.673340f, 0.678711f, 0.680664f, 0.680664f, 0.680176f, 0.000538f, 0.002022f, 0.003185f, 0.004456f, + 0.005360f, 0.006321f, 0.007286f, 0.008484f, 0.009422f, 0.010185f, 0.011177f, 0.012283f, 0.013191f, 0.014435f, 0.015587f, 0.016769f, + 0.017914f, 0.019302f, 0.020584f, 0.022171f, 0.023819f, 0.025391f, 0.027222f, 0.028992f, 0.030914f, 0.033234f, 0.035461f, 0.037903f, + 0.040649f, 0.043396f, 0.046326f, 0.049561f, 0.053131f, 0.056946f, 0.061279f, 0.065613f, 0.070374f, 0.075439f, 0.080811f, 0.086731f, + 0.093140f, 0.100037f, 0.107544f, 0.115662f, 0.124023f, 0.132935f, 0.143066f, 0.153320f, 0.163696f, 0.175415f, 0.187012f, 0.200195f, + 0.213013f, 0.227173f, 0.241455f, 0.256592f, 0.272461f, 0.288330f, 0.632812f, 0.663574f, 0.669434f, 0.670898f, 0.671387f, 0.671875f, + 0.000686f, 0.001864f, 0.002884f, 0.003883f, 0.004829f, 0.005592f, 0.006504f, 0.007454f, 0.008064f, 0.008995f, 0.009850f, 0.010948f, + 0.011711f, 0.012581f, 0.013763f, 0.014618f, 0.015701f, 0.016953f, 0.018112f, 0.019180f, 0.020691f, 0.021973f, 0.023560f, 0.025192f, + 0.026962f, 0.028717f, 0.030624f, 0.032959f, 0.035004f, 0.037567f, 0.040314f, 0.043121f, 0.046204f, 0.049713f, 0.053284f, 0.057129f, + 0.061157f, 0.065796f, 0.071167f, 0.076477f, 0.082214f, 0.088379f, 0.095276f, 0.102600f, 0.110596f, 0.118652f, 0.127808f, 0.137817f, + 0.147705f, 0.158569f, 0.170166f, 0.182251f, 0.195068f, 0.208008f, 0.222656f, 0.237671f, 0.252686f, 0.269287f, 0.620605f, 0.653320f, + 0.659180f, 0.661621f, 0.663086f, 0.663574f, 0.000782f, 0.001828f, 0.002949f, 0.003487f, 0.004421f, 0.005032f, 0.005878f, 0.006557f, + 0.007332f, 0.008110f, 0.008591f, 0.009537f, 0.010094f, 0.011147f, 0.011864f, 0.012779f, 0.013573f, 0.014549f, 0.015625f, 0.016846f, + 0.017822f, 0.018936f, 0.020279f, 0.021729f, 0.023117f, 0.024704f, 0.026505f, 0.028183f, 0.030289f, 0.032349f, 0.034546f, 0.037109f, + 0.039703f, 0.042786f, 0.045837f, 0.049133f, 0.053009f, 0.056763f, 0.061584f, 0.066284f, 0.071411f, 0.076843f, 0.083191f, 0.089722f, + 0.097290f, 0.104919f, 0.113647f, 0.122498f, 0.132324f, 0.142578f, 0.153809f, 0.164917f, 0.177612f, 0.190430f, 0.203857f, 0.218506f, + 0.233887f, 0.249390f, 0.606934f, 0.642578f, 0.649414f, 0.653320f, 0.652832f, 0.654785f, 0.000604f, 0.001636f, 0.002550f, 0.003180f, + 0.003799f, 0.004498f, 0.005051f, 0.005573f, 0.006325f, 0.006836f, 0.007607f, 0.008087f, 0.008820f, 0.009483f, 0.010132f, 0.010918f, + 0.011665f, 0.012527f, 0.013535f, 0.014297f, 0.015251f, 0.016190f, 0.017288f, 0.018433f, 0.019791f, 0.021133f, 0.022400f, 0.023865f, + 0.025742f, 0.027664f, 0.029373f, 0.031677f, 0.034027f, 0.036255f, 0.039032f, 0.042023f, 0.045197f, 0.048798f, 0.052643f, 0.056824f, + 0.061493f, 0.066467f, 0.072327f, 0.078308f, 0.084473f, 0.091858f, 0.099609f, 0.108032f, 0.117249f, 0.126831f, 0.137451f, 0.148193f, + 0.160034f, 0.172729f, 0.186035f, 0.199829f, 0.214722f, 0.229980f, 0.596680f, 0.632812f, 0.638672f, 0.642578f, 0.644531f, 0.645020f, + 0.000447f, 0.001384f, 0.001986f, 0.002697f, 0.003225f, 0.003828f, 0.004501f, 0.005009f, 0.005459f, 0.006027f, 0.006474f, 0.006935f, + 0.007591f, 0.008217f, 0.008644f, 0.009308f, 0.010025f, 0.010498f, 0.011330f, 0.012100f, 0.012909f, 0.013924f, 0.014618f, 0.015610f, + 0.016739f, 0.017807f, 0.019043f, 0.020340f, 0.021622f, 0.023178f, 0.024979f, 0.026520f, 0.028366f, 0.030640f, 0.032959f, 0.035492f, + 0.038239f, 0.041260f, 0.044495f, 0.048340f, 0.052399f, 0.056732f, 0.061768f, 0.067017f, 0.072754f, 0.079224f, 0.086304f, 0.093994f, + 0.102478f, 0.111511f, 0.121521f, 0.132080f, 0.143311f, 0.155518f, 0.168213f, 0.181763f, 0.196411f, 0.211548f, 0.583008f, 0.621094f, + 0.629395f, 0.632324f, 0.634766f, 0.635742f, 0.000375f, 0.001324f, 0.001728f, 0.002466f, 0.002872f, 0.003384f, 0.003685f, 0.004185f, + 0.004845f, 0.005184f, 0.005444f, 0.006130f, 0.006401f, 0.006844f, 0.007446f, 0.007957f, 0.008636f, 0.008965f, 0.009659f, 0.010139f, + 0.010971f, 0.011742f, 0.012497f, 0.013138f, 0.014099f, 0.014992f, 0.015900f, 0.017166f, 0.018143f, 0.019485f, 0.020676f, 0.022156f, + 0.023697f, 0.025528f, 0.027374f, 0.029556f, 0.031921f, 0.034424f, 0.037445f, 0.040375f, 0.044067f, 0.047577f, 0.052155f, 0.056824f, + 0.062042f, 0.067688f, 0.074158f, 0.081055f, 0.088745f, 0.097351f, 0.106323f, 0.116455f, 0.127075f, 0.138672f, 0.151123f, 0.164062f, + 0.177856f, 0.192871f, 0.570801f, 0.610840f, 0.619629f, 0.623047f, 0.625488f, 0.625977f, 0.000432f, 0.000921f, 0.001664f, 0.002056f, + 0.002697f, 0.003061f, 0.003326f, 0.003757f, 0.004044f, 0.004379f, 0.004761f, 0.004948f, 0.005463f, 0.005791f, 0.006199f, 0.006752f, + 0.007229f, 0.007526f, 0.008156f, 0.008621f, 0.009193f, 0.009712f, 0.010330f, 0.010994f, 0.011688f, 0.012466f, 0.013374f, 0.014153f, + 0.015099f, 0.016083f, 0.017212f, 0.018250f, 0.019623f, 0.021210f, 0.022614f, 0.024445f, 0.026321f, 0.028351f, 0.030762f, 0.033325f, + 0.036377f, 0.039642f, 0.043304f, 0.047485f, 0.051880f, 0.056885f, 0.062469f, 0.068542f, 0.075623f, 0.083374f, 0.091919f, 0.101135f, + 0.111389f, 0.122559f, 0.134277f, 0.146606f, 0.160278f, 0.174683f, 0.557617f, 0.600098f, 0.609375f, 0.612793f, 0.615723f, 0.616699f, + 0.000255f, 0.000997f, 0.001393f, 0.001908f, 0.002239f, 0.002512f, 0.002720f, 0.003166f, 0.003283f, 0.003616f, 0.003866f, 0.004223f, + 0.004597f, 0.004795f, 0.005127f, 0.005573f, 0.005939f, 0.006359f, 0.006657f, 0.007133f, 0.007687f, 0.008041f, 0.008545f, 0.009087f, + 0.009636f, 0.010300f, 0.010910f, 0.011757f, 0.012489f, 0.013313f, 0.014153f, 0.014954f, 0.016037f, 0.017258f, 0.018555f, 0.019867f, + 0.021530f, 0.023239f, 0.025055f, 0.027252f, 0.029663f, 0.032379f, 0.035339f, 0.038666f, 0.042664f, 0.047058f, 0.051849f, 0.057465f, + 0.063416f, 0.070557f, 0.078369f, 0.086731f, 0.096313f, 0.106384f, 0.117798f, 0.129761f, 0.143311f, 0.156982f, 0.544922f, 0.588867f, + 0.599121f, 0.602539f, 0.605469f, 0.606445f, 0.000353f, 0.000879f, 0.001276f, 0.001613f, 0.001785f, 0.002075f, 0.002300f, 0.002501f, + 0.002808f, 0.003010f, 0.003283f, 0.003487f, 0.003714f, 0.003967f, 0.004269f, 0.004597f, 0.004837f, 0.005230f, 0.005512f, 0.005878f, + 0.006203f, 0.006626f, 0.007030f, 0.007519f, 0.007866f, 0.008354f, 0.009010f, 0.009468f, 0.010017f, 0.010765f, 0.011444f, 0.012291f, + 0.013100f, 0.014030f, 0.015030f, 0.016098f, 0.017441f, 0.018646f, 0.020157f, 0.021912f, 0.023804f, 0.026047f, 0.028488f, 0.031342f, + 0.034424f, 0.037994f, 0.042206f, 0.046997f, 0.052338f, 0.058533f, 0.065369f, 0.073364f, 0.081787f, 0.091492f, 0.102356f, 0.113647f, + 0.126343f, 0.139526f, 0.531250f, 0.579102f, 0.587891f, 0.592773f, 0.595703f, 0.596680f, 0.000295f, 0.000784f, 0.000912f, 0.001261f, + 0.001517f, 0.001761f, 0.001893f, 0.002113f, 0.002211f, 0.002432f, 0.002676f, 0.002861f, 0.002993f, 0.003294f, 0.003479f, 0.003700f, + 0.003933f, 0.004242f, 0.004452f, 0.004745f, 0.004974f, 0.005428f, 0.005642f, 0.006081f, 0.006401f, 0.006817f, 0.007240f, 0.007641f, + 0.008209f, 0.008667f, 0.009361f, 0.009720f, 0.010506f, 0.011261f, 0.012024f, 0.012794f, 0.013840f, 0.014893f, 0.016113f, 0.017395f, + 0.018860f, 0.020493f, 0.022446f, 0.024658f, 0.027283f, 0.030228f, 0.033691f, 0.037659f, 0.042145f, 0.047546f, 0.053467f, 0.060547f, + 0.068359f, 0.077332f, 0.087158f, 0.098145f, 0.109741f, 0.123230f, 0.517090f, 0.566895f, 0.576660f, 0.581543f, 0.584961f, 0.587402f, + 0.000247f, 0.000702f, 0.000849f, 0.001033f, 0.001304f, 0.001416f, 0.001576f, 0.001754f, 0.001860f, 0.001953f, 0.002104f, 0.002327f, + 0.002419f, 0.002651f, 0.002785f, 0.003014f, 0.003134f, 0.003315f, 0.003584f, 0.003813f, 0.004078f, 0.004295f, 0.004555f, 0.004784f, + 0.005013f, 0.005329f, 0.005669f, 0.006069f, 0.006439f, 0.006821f, 0.007381f, 0.007797f, 0.008301f, 0.008812f, 0.009430f, 0.010139f, + 0.010948f, 0.011642f, 0.012573f, 0.013664f, 0.014671f, 0.016052f, 0.017502f, 0.019135f, 0.021255f, 0.023438f, 0.026199f, 0.029312f, + 0.033203f, 0.037476f, 0.042725f, 0.048828f, 0.055695f, 0.063721f, 0.072937f, 0.082947f, 0.094666f, 0.107117f, 0.504883f, 0.555664f, + 0.566406f, 0.572754f, 0.574707f, 0.577148f, 0.000217f, 0.000516f, 0.000750f, 0.000898f, 0.001011f, 0.001117f, 0.001203f, 0.001307f, + 0.001470f, 0.001604f, 0.001659f, 0.001750f, 0.001945f, 0.002121f, 0.002249f, 0.002316f, 0.002478f, 0.002581f, 0.002832f, 0.003000f, + 0.003164f, 0.003334f, 0.003593f, 0.003784f, 0.003990f, 0.004196f, 0.004440f, 0.004673f, 0.005035f, 0.005329f, 0.005642f, 0.005981f, + 0.006462f, 0.006916f, 0.007313f, 0.007805f, 0.008377f, 0.008987f, 0.009727f, 0.010521f, 0.011314f, 0.012421f, 0.013466f, 0.014755f, + 0.016235f, 0.017914f, 0.019913f, 0.022461f, 0.025330f, 0.028778f, 0.033081f, 0.038239f, 0.044189f, 0.051422f, 0.059662f, 0.069336f, + 0.080200f, 0.091980f, 0.492676f, 0.543945f, 0.555664f, 0.561035f, 0.564453f, 0.566406f, 0.000131f, 0.000355f, 0.000605f, 0.000759f, + 0.000832f, 0.000904f, 0.001018f, 0.000975f, 0.001144f, 0.001235f, 0.001336f, 0.001447f, 0.001518f, 0.001620f, 0.001668f, 0.001835f, + 0.001901f, 0.002045f, 0.002188f, 0.002270f, 0.002424f, 0.002577f, 0.002707f, 0.002893f, 0.003002f, 0.003223f, 0.003407f, 0.003572f, + 0.003851f, 0.004017f, 0.004391f, 0.004608f, 0.004833f, 0.005203f, 0.005497f, 0.005886f, 0.006351f, 0.006771f, 0.007278f, 0.007858f, + 0.008560f, 0.009315f, 0.010086f, 0.011078f, 0.012222f, 0.013443f, 0.015022f, 0.016769f, 0.018967f, 0.021591f, 0.024780f, 0.028931f, + 0.033875f, 0.039734f, 0.047241f, 0.056122f, 0.066101f, 0.077637f, 0.477783f, 0.532715f, 0.544922f, 0.551270f, 0.553711f, 0.555664f, + 0.000245f, 0.000303f, 0.000473f, 0.000498f, 0.000544f, 0.000707f, 0.000700f, 0.000767f, 0.000802f, 0.000892f, 0.001021f, 0.001086f, + 0.001140f, 0.001260f, 0.001303f, 0.001325f, 0.001462f, 0.001553f, 0.001603f, 0.001746f, 0.001816f, 0.001904f, 0.002043f, 0.002127f, + 0.002254f, 0.002356f, 0.002548f, 0.002672f, 0.002851f, 0.003092f, 0.003265f, 0.003374f, 0.003647f, 0.003891f, 0.004097f, 0.004360f, + 0.004669f, 0.004997f, 0.005390f, 0.005810f, 0.006226f, 0.006756f, 0.007450f, 0.008095f, 0.008934f, 0.009827f, 0.010902f, 0.012268f, + 0.013840f, 0.015701f, 0.018036f, 0.021072f, 0.024948f, 0.029800f, 0.035980f, 0.043945f, 0.053345f, 0.063843f, 0.465576f, 0.520996f, + 0.535645f, 0.540039f, 0.543457f, 0.545898f, 0.000108f, 0.000275f, 0.000332f, 0.000402f, 0.000462f, 0.000468f, 0.000580f, 0.000522f, + 0.000616f, 0.000657f, 0.000758f, 0.000762f, 0.000812f, 0.000870f, 0.000945f, 0.000978f, 0.001054f, 0.001109f, 0.001179f, 0.001213f, + 0.001311f, 0.001371f, 0.001473f, 0.001558f, 0.001629f, 0.001718f, 0.001837f, 0.001903f, 0.002016f, 0.002159f, 0.002258f, 0.002478f, + 0.002548f, 0.002731f, 0.002909f, 0.003086f, 0.003317f, 0.003580f, 0.003885f, 0.004116f, 0.004421f, 0.004818f, 0.005264f, 0.005745f, + 0.006294f, 0.006966f, 0.007748f, 0.008667f, 0.009766f, 0.011086f, 0.012787f, 0.014908f, 0.017746f, 0.021271f, 0.026382f, 0.032990f, + 0.041199f, 0.051239f, 0.452393f, 0.509277f, 0.522461f, 0.529297f, 0.533203f, 0.535156f, 0.000016f, 0.000143f, 0.000244f, 0.000315f, + 0.000309f, 0.000391f, 0.000344f, 0.000402f, 0.000429f, 0.000517f, 0.000522f, 0.000526f, 0.000546f, 0.000606f, 0.000628f, 0.000705f, + 0.000692f, 0.000781f, 0.000837f, 0.000868f, 0.000923f, 0.000969f, 0.001013f, 0.001070f, 0.001142f, 0.001186f, 0.001273f, 0.001326f, + 0.001397f, 0.001534f, 0.001561f, 0.001685f, 0.001775f, 0.001873f, 0.002024f, 0.002153f, 0.002272f, 0.002443f, 0.002611f, 0.002800f, + 0.003014f, 0.003250f, 0.003529f, 0.003868f, 0.004227f, 0.004692f, 0.005192f, 0.005836f, 0.006603f, 0.007587f, 0.008751f, 0.010193f, + 0.012001f, 0.014610f, 0.018219f, 0.023392f, 0.030594f, 0.039795f, 0.437744f, 0.498291f, 0.512207f, 0.517578f, 0.521484f, 0.525391f, + 0.000102f, 0.000186f, 0.000171f, 0.000181f, 0.000227f, 0.000229f, 0.000231f, 0.000278f, 0.000293f, 0.000304f, 0.000314f, 0.000375f, + 0.000365f, 0.000411f, 0.000446f, 0.000457f, 0.000496f, 0.000513f, 0.000533f, 0.000554f, 0.000603f, 0.000622f, 0.000669f, 0.000708f, + 0.000757f, 0.000789f, 0.000843f, 0.000875f, 0.000925f, 0.000964f, 0.001037f, 0.001094f, 0.001172f, 0.001243f, 0.001324f, 0.001373f, + 0.001497f, 0.001570f, 0.001712f, 0.001829f, 0.001947f, 0.002123f, 0.002291f, 0.002472f, 0.002703f, 0.003008f, 0.003342f, 0.003757f, + 0.004204f, 0.004810f, 0.005539f, 0.006554f, 0.007828f, 0.009537f, 0.011894f, 0.015442f, 0.021072f, 0.029282f, 0.424561f, 0.486084f, + 0.500488f, 0.506836f, 0.512207f, 0.514648f, 0.000014f, 0.000127f, 0.000112f, 0.000109f, 0.000143f, 0.000165f, 0.000141f, 0.000180f, + 0.000185f, 0.000191f, 0.000196f, 0.000203f, 0.000233f, 0.000252f, 0.000260f, 0.000274f, 0.000288f, 0.000314f, 0.000328f, 0.000363f, + 0.000362f, 0.000374f, 0.000400f, 0.000436f, 0.000464f, 0.000501f, 0.000504f, 0.000521f, 0.000563f, 0.000593f, 0.000635f, 0.000671f, + 0.000712f, 0.000740f, 0.000800f, 0.000837f, 0.000892f, 0.000955f, 0.001030f, 0.001092f, 0.001167f, 0.001270f, 0.001369f, 0.001491f, + 0.001626f, 0.001769f, 0.001993f, 0.002209f, 0.002523f, 0.002863f, 0.003325f, 0.003880f, 0.004715f, 0.005764f, 0.007320f, 0.009468f, + 0.013344f, 0.020187f, 0.410645f, 0.473877f, 0.489258f, 0.496826f, 0.500488f, 0.503906f, 0.000103f, 0.000078f, 0.000067f, 0.000065f, + 0.000086f, 0.000085f, 0.000101f, 0.000106f, 0.000106f, 0.000107f, 0.000115f, 0.000133f, 0.000118f, 0.000133f, 0.000154f, 0.000150f, + 0.000167f, 0.000177f, 0.000180f, 0.000190f, 0.000207f, 0.000213f, 0.000228f, 0.000238f, 0.000267f, 0.000277f, 0.000287f, 0.000298f, + 0.000313f, 0.000325f, 0.000347f, 0.000375f, 0.000393f, 0.000405f, 0.000440f, 0.000463f, 0.000486f, 0.000527f, 0.000562f, 0.000599f, + 0.000639f, 0.000688f, 0.000757f, 0.000807f, 0.000879f, 0.000961f, 0.001059f, 0.001180f, 0.001342f, 0.001533f, 0.001762f, 0.002102f, + 0.002502f, 0.003128f, 0.004028f, 0.005379f, 0.007591f, 0.012505f, 0.397217f, 0.462891f, 0.478760f, 0.485840f, 0.490479f, 0.492676f, + 0.000087f, 0.000063f, 0.000054f, 0.000048f, 0.000047f, 0.000044f, 0.000046f, 0.000047f, 0.000047f, 0.000060f, 0.000053f, 0.000056f, + 0.000072f, 0.000060f, 0.000064f, 0.000069f, 0.000078f, 0.000085f, 0.000084f, 0.000090f, 0.000094f, 0.000102f, 0.000105f, 0.000111f, + 0.000116f, 0.000126f, 0.000132f, 0.000150f, 0.000147f, 0.000158f, 0.000167f, 0.000178f, 0.000185f, 0.000192f, 0.000211f, 0.000216f, + 0.000226f, 0.000246f, 0.000265f, 0.000284f, 0.000299f, 0.000325f, 0.000349f, 0.000381f, 0.000415f, 0.000448f, 0.000490f, 0.000544f, + 0.000612f, 0.000694f, 0.000798f, 0.000943f, 0.001139f, 0.001436f, 0.001870f, 0.002586f, 0.003817f, 0.006474f, 0.383545f, 0.450195f, + 0.467041f, 0.474365f, 0.478760f, 0.482422f, 0.000065f, 0.000045f, 0.000037f, 0.000033f, 0.000030f, 0.000028f, 0.000026f, 0.000025f, + 0.000024f, 0.000022f, 0.000021f, 0.000025f, 0.000020f, 0.000021f, 0.000025f, 0.000029f, 0.000028f, 0.000031f, 0.000033f, 0.000034f, + 0.000036f, 0.000041f, 0.000045f, 0.000040f, 0.000045f, 0.000049f, 0.000051f, 0.000048f, 0.000055f, 0.000057f, 0.000061f, 0.000066f, + 0.000072f, 0.000068f, 0.000073f, 0.000078f, 0.000087f, 0.000089f, 0.000097f, 0.000104f, 0.000113f, 0.000115f, 0.000128f, 0.000137f, + 0.000148f, 0.000160f, 0.000174f, 0.000194f, 0.000221f, 0.000248f, 0.000283f, 0.000324f, 0.000396f, 0.000496f, 0.000657f, 0.000928f, + 0.001479f, 0.002684f, 0.371094f, 0.438477f, 0.455078f, 0.463867f, 0.468750f, 0.471191f, 0.000029f, 0.000019f, 0.000016f, 0.000014f, + 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, + 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000007f, 0.000008f, 0.000007f, 0.000008f, 0.000009f, 0.000010f, 0.000011f, + 0.000012f, 0.000011f, 0.000012f, 0.000013f, 0.000015f, 0.000017f, 0.000018f, 0.000018f, 0.000020f, 0.000019f, 0.000021f, 0.000024f, + 0.000024f, 0.000026f, 0.000028f, 0.000031f, 0.000031f, 0.000035f, 0.000040f, 0.000041f, 0.000045f, 0.000052f, 0.000059f, 0.000071f, + 0.000083f, 0.000099f, 0.000132f, 0.000188f, 0.000315f, 0.000712f, 0.356934f, 0.426514f, 0.444824f, 0.452637f, 0.457520f, 0.460938f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000001f, 0.000002f, 0.000002f, + 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000006f, 0.000010f, 0.000027f, 0.343750f, 0.414795f, + 0.433105f, 0.441895f, 0.446289f, 0.449951f, + }, + { + 0.012436f, 0.037598f, 0.062805f, 0.087891f, 0.113037f, 0.137329f, 0.161621f, 0.185425f, 0.209717f, 0.232544f, 0.255371f, 0.278076f, + 0.300049f, 0.321289f, 0.343506f, 0.364014f, 0.385010f, 0.404785f, 0.424561f, 0.444824f, 0.463623f, 0.482422f, 0.501465f, 0.520020f, + 0.537598f, 0.554688f, 0.572266f, 0.589355f, 0.605957f, 0.622070f, 0.639648f, 0.655273f, 0.670410f, 0.685547f, 0.700684f, 0.715332f, + 0.730469f, 0.744629f, 0.758301f, 0.771973f, 0.785156f, 0.799316f, 0.812012f, 0.825684f, 0.837891f, 0.850586f, 0.863281f, 0.875000f, + 0.887207f, 0.898926f, 0.910156f, 0.921387f, 0.933105f, 0.944336f, 0.954102f, 0.964844f, 0.976074f, 0.985840f, 0.978027f, 0.947266f, + 0.925781f, 0.907715f, 0.892090f, 0.877930f, 0.011276f, 0.034546f, 0.058289f, 0.082031f, 0.105469f, 0.128662f, 0.152344f, 0.174805f, + 0.197876f, 0.219604f, 0.241455f, 0.263672f, 0.284912f, 0.306152f, 0.326416f, 0.347168f, 0.366699f, 0.387695f, 0.406494f, 0.426025f, + 0.444824f, 0.463379f, 0.481934f, 0.500000f, 0.518066f, 0.535645f, 0.552246f, 0.569824f, 0.586426f, 0.603027f, 0.619141f, 0.634766f, + 0.650391f, 0.666016f, 0.681152f, 0.695801f, 0.710938f, 0.725586f, 0.739258f, 0.753906f, 0.768066f, 0.781250f, 0.794922f, 0.807617f, + 0.821289f, 0.833496f, 0.846191f, 0.858398f, 0.870605f, 0.882812f, 0.894531f, 0.906250f, 0.917480f, 0.929199f, 0.939453f, 0.951660f, + 0.961426f, 0.972656f, 0.971680f, 0.942871f, 0.921875f, 0.904785f, 0.889160f, 0.875977f, 0.010628f, 0.032288f, 0.054932f, 0.076172f, + 0.099060f, 0.121216f, 0.142700f, 0.164795f, 0.186279f, 0.207642f, 0.229248f, 0.249756f, 0.269531f, 0.291016f, 0.310791f, 0.331543f, + 0.349609f, 0.369385f, 0.388916f, 0.409180f, 0.427246f, 0.444824f, 0.463135f, 0.480713f, 0.499512f, 0.516602f, 0.533203f, 0.550293f, + 0.567383f, 0.583496f, 0.599609f, 0.615723f, 0.630859f, 0.646973f, 0.661621f, 0.677246f, 0.691895f, 0.705566f, 0.720703f, 0.735352f, + 0.749512f, 0.763184f, 0.776367f, 0.790039f, 0.803223f, 0.816406f, 0.828613f, 0.842285f, 0.854492f, 0.867676f, 0.878418f, 0.890137f, + 0.902832f, 0.913086f, 0.925293f, 0.936035f, 0.947754f, 0.958008f, 0.964844f, 0.937500f, 0.917480f, 0.901367f, 0.886719f, 0.873535f, + 0.009926f, 0.030167f, 0.050995f, 0.071594f, 0.092346f, 0.113892f, 0.134399f, 0.154663f, 0.175537f, 0.195679f, 0.216309f, 0.235840f, + 0.256104f, 0.276611f, 0.295654f, 0.314453f, 0.333496f, 0.353027f, 0.370850f, 0.389404f, 0.408936f, 0.427490f, 0.445312f, 0.462891f, + 0.480225f, 0.497803f, 0.513672f, 0.531250f, 0.547363f, 0.563965f, 0.580078f, 0.597168f, 0.612305f, 0.627930f, 0.642578f, 0.658691f, + 0.673340f, 0.687500f, 0.702637f, 0.717285f, 0.731445f, 0.744629f, 0.758301f, 0.772461f, 0.786133f, 0.799316f, 0.811523f, 0.824707f, + 0.837891f, 0.849121f, 0.861816f, 0.874023f, 0.887207f, 0.898438f, 0.910156f, 0.920898f, 0.932617f, 0.943848f, 0.958008f, 0.932129f, + 0.913086f, 0.897461f, 0.883301f, 0.871094f, 0.009178f, 0.028107f, 0.047729f, 0.066895f, 0.086182f, 0.106384f, 0.125977f, 0.145386f, + 0.165527f, 0.184937f, 0.203857f, 0.224121f, 0.242676f, 0.261475f, 0.281006f, 0.300049f, 0.318604f, 0.336426f, 0.355469f, 0.372314f, + 0.391113f, 0.409424f, 0.426514f, 0.444092f, 0.461426f, 0.477783f, 0.495850f, 0.512207f, 0.528809f, 0.544434f, 0.561035f, 0.576660f, + 0.593262f, 0.608398f, 0.623047f, 0.638184f, 0.655273f, 0.668945f, 0.682617f, 0.697754f, 0.712402f, 0.726562f, 0.740234f, 0.753906f, + 0.768066f, 0.781250f, 0.794434f, 0.807617f, 0.820312f, 0.833496f, 0.845215f, 0.858398f, 0.870605f, 0.881836f, 0.894043f, 0.906738f, + 0.917480f, 0.928711f, 0.951172f, 0.926758f, 0.909180f, 0.893555f, 0.880859f, 0.868164f, 0.008667f, 0.025986f, 0.044922f, 0.062805f, + 0.081421f, 0.099854f, 0.118347f, 0.137085f, 0.155518f, 0.173828f, 0.193115f, 0.211304f, 0.229858f, 0.248413f, 0.266602f, 0.285400f, + 0.303223f, 0.321045f, 0.339111f, 0.357178f, 0.373779f, 0.391357f, 0.409424f, 0.426270f, 0.443115f, 0.460449f, 0.476807f, 0.494141f, + 0.510254f, 0.526855f, 0.541992f, 0.559082f, 0.574219f, 0.589355f, 0.605469f, 0.620117f, 0.636230f, 0.649902f, 0.664551f, 0.678711f, + 0.693848f, 0.707031f, 0.723145f, 0.736328f, 0.750977f, 0.762695f, 0.776855f, 0.790039f, 0.803223f, 0.816406f, 0.828613f, 0.842285f, + 0.853516f, 0.866211f, 0.878906f, 0.890625f, 0.902832f, 0.913574f, 0.944336f, 0.921875f, 0.903809f, 0.889160f, 0.876953f, 0.865234f, + 0.008057f, 0.024658f, 0.041321f, 0.058411f, 0.075989f, 0.093811f, 0.110535f, 0.128784f, 0.146729f, 0.164307f, 0.182007f, 0.200073f, + 0.217773f, 0.234619f, 0.252930f, 0.271240f, 0.288086f, 0.306152f, 0.322998f, 0.341064f, 0.357910f, 0.374756f, 0.391357f, 0.409180f, + 0.425293f, 0.442383f, 0.458496f, 0.475342f, 0.491455f, 0.507324f, 0.523438f, 0.539551f, 0.555176f, 0.570312f, 0.585938f, 0.601074f, + 0.616699f, 0.631836f, 0.646484f, 0.660645f, 0.676270f, 0.688477f, 0.704102f, 0.718262f, 0.731445f, 0.745117f, 0.760254f, 0.771484f, + 0.785156f, 0.799316f, 0.812500f, 0.824707f, 0.836914f, 0.850098f, 0.862793f, 0.874512f, 0.886719f, 0.898438f, 0.937500f, 0.915527f, + 0.899414f, 0.885254f, 0.872559f, 0.861816f, 0.007477f, 0.022919f, 0.038971f, 0.054901f, 0.070801f, 0.087646f, 0.104065f, 0.121155f, + 0.137573f, 0.155029f, 0.171875f, 0.188721f, 0.206177f, 0.222778f, 0.240112f, 0.257080f, 0.274170f, 0.290283f, 0.308350f, 0.324463f, + 0.342041f, 0.358154f, 0.375488f, 0.391113f, 0.407471f, 0.424561f, 0.440430f, 0.456787f, 0.474121f, 0.489746f, 0.505371f, 0.521484f, + 0.536133f, 0.552246f, 0.565918f, 0.582031f, 0.597168f, 0.613281f, 0.626953f, 0.642578f, 0.656738f, 0.670898f, 0.684570f, 0.699219f, + 0.712891f, 0.727539f, 0.741211f, 0.754395f, 0.768066f, 0.781738f, 0.794434f, 0.808105f, 0.820312f, 0.833984f, 0.846680f, 0.858887f, + 0.871582f, 0.883301f, 0.930176f, 0.910156f, 0.894043f, 0.880371f, 0.868652f, 0.858398f, 0.007023f, 0.021240f, 0.036224f, 0.051300f, + 0.066467f, 0.082092f, 0.097900f, 0.113892f, 0.129517f, 0.145752f, 0.161743f, 0.178223f, 0.194702f, 0.210327f, 0.227661f, 0.243408f, + 0.260986f, 0.276855f, 0.292725f, 0.309814f, 0.326172f, 0.342041f, 0.358398f, 0.375732f, 0.391113f, 0.406982f, 0.422852f, 0.438965f, + 0.454590f, 0.471191f, 0.486816f, 0.502441f, 0.517578f, 0.533203f, 0.548340f, 0.562988f, 0.578613f, 0.593750f, 0.609375f, 0.623535f, + 0.638184f, 0.652832f, 0.666992f, 0.680664f, 0.695312f, 0.708984f, 0.722656f, 0.736816f, 0.750000f, 0.764160f, 0.777344f, 0.789551f, + 0.803223f, 0.816895f, 0.830078f, 0.842773f, 0.854980f, 0.868652f, 0.922852f, 0.904297f, 0.889160f, 0.875977f, 0.864746f, 0.854492f, + 0.006458f, 0.019913f, 0.033691f, 0.048126f, 0.062744f, 0.077026f, 0.092224f, 0.106567f, 0.122192f, 0.137207f, 0.152222f, 0.167725f, + 0.183838f, 0.199951f, 0.215088f, 0.231323f, 0.246826f, 0.262695f, 0.279053f, 0.294678f, 0.310547f, 0.326172f, 0.342041f, 0.358887f, + 0.374268f, 0.389893f, 0.405518f, 0.421143f, 0.437012f, 0.452637f, 0.467773f, 0.483643f, 0.499512f, 0.513672f, 0.529785f, 0.545410f, + 0.560059f, 0.575195f, 0.590332f, 0.604980f, 0.618652f, 0.634277f, 0.648438f, 0.662598f, 0.676270f, 0.690918f, 0.704102f, 0.718750f, + 0.732422f, 0.745605f, 0.760254f, 0.773438f, 0.786621f, 0.801270f, 0.812988f, 0.826172f, 0.839844f, 0.851562f, 0.915527f, 0.897949f, + 0.883789f, 0.871094f, 0.860352f, 0.850586f, 0.006077f, 0.018921f, 0.031464f, 0.045258f, 0.058411f, 0.072144f, 0.085999f, 0.100220f, + 0.114258f, 0.129028f, 0.143677f, 0.158691f, 0.173584f, 0.188477f, 0.203247f, 0.219238f, 0.234497f, 0.249634f, 0.264893f, 0.280273f, + 0.295410f, 0.310791f, 0.326904f, 0.342285f, 0.357910f, 0.373535f, 0.388428f, 0.404053f, 0.420166f, 0.435303f, 0.450195f, 0.465332f, + 0.481201f, 0.496338f, 0.511230f, 0.525879f, 0.540527f, 0.556641f, 0.570312f, 0.585938f, 0.600098f, 0.614746f, 0.629883f, 0.644531f, + 0.657715f, 0.672363f, 0.687012f, 0.700684f, 0.714355f, 0.729004f, 0.742188f, 0.755371f, 0.769531f, 0.782227f, 0.796875f, 0.810059f, + 0.823242f, 0.836426f, 0.907715f, 0.891602f, 0.877930f, 0.866211f, 0.855957f, 0.846680f, 0.005596f, 0.017654f, 0.029587f, 0.041840f, + 0.055115f, 0.067871f, 0.080566f, 0.093994f, 0.107361f, 0.120911f, 0.134766f, 0.149414f, 0.163452f, 0.177979f, 0.192261f, 0.206787f, + 0.221191f, 0.236816f, 0.250732f, 0.266113f, 0.281250f, 0.295898f, 0.311279f, 0.326904f, 0.342041f, 0.356201f, 0.371826f, 0.387451f, + 0.402344f, 0.417236f, 0.432373f, 0.447266f, 0.462891f, 0.477539f, 0.492432f, 0.506836f, 0.522949f, 0.536621f, 0.551758f, 0.566895f, + 0.582031f, 0.596191f, 0.610352f, 0.625488f, 0.640625f, 0.653320f, 0.668457f, 0.682617f, 0.696777f, 0.710449f, 0.724609f, 0.739258f, + 0.751465f, 0.765625f, 0.780273f, 0.792480f, 0.806152f, 0.820801f, 0.899902f, 0.885742f, 0.872070f, 0.861328f, 0.851562f, 0.842285f, + 0.005451f, 0.016479f, 0.028259f, 0.039856f, 0.051331f, 0.063416f, 0.075867f, 0.088196f, 0.100952f, 0.113770f, 0.126953f, 0.140747f, + 0.153564f, 0.167847f, 0.181519f, 0.195679f, 0.210083f, 0.223633f, 0.237427f, 0.252197f, 0.267334f, 0.281738f, 0.296143f, 0.311035f, + 0.325928f, 0.340332f, 0.355469f, 0.370361f, 0.385010f, 0.400635f, 0.415039f, 0.429688f, 0.444092f, 0.459717f, 0.474121f, 0.489258f, + 0.503906f, 0.519043f, 0.533203f, 0.548828f, 0.562012f, 0.577637f, 0.591797f, 0.606445f, 0.621582f, 0.635742f, 0.650391f, 0.664551f, + 0.678223f, 0.692871f, 0.706055f, 0.721191f, 0.733887f, 0.747559f, 0.762207f, 0.775879f, 0.791016f, 0.804199f, 0.892090f, 0.878906f, + 0.866699f, 0.855957f, 0.846191f, 0.837891f, 0.004963f, 0.015343f, 0.026169f, 0.037079f, 0.047943f, 0.059570f, 0.070801f, 0.083008f, + 0.095093f, 0.106750f, 0.119507f, 0.132080f, 0.145142f, 0.158569f, 0.171143f, 0.184692f, 0.198730f, 0.211792f, 0.225830f, 0.239380f, + 0.253662f, 0.267578f, 0.281738f, 0.295898f, 0.309814f, 0.324219f, 0.340088f, 0.353760f, 0.368164f, 0.383057f, 0.397705f, 0.412842f, + 0.426758f, 0.441406f, 0.456787f, 0.470947f, 0.485352f, 0.500000f, 0.515137f, 0.529785f, 0.543945f, 0.559082f, 0.572754f, 0.588379f, + 0.602539f, 0.616699f, 0.631348f, 0.645996f, 0.659180f, 0.674805f, 0.689453f, 0.703125f, 0.716797f, 0.729980f, 0.744629f, 0.758789f, + 0.772461f, 0.786621f, 0.883789f, 0.872070f, 0.860840f, 0.850586f, 0.841309f, 0.833008f, 0.004726f, 0.014549f, 0.024109f, 0.034668f, + 0.044708f, 0.055573f, 0.066467f, 0.077820f, 0.088928f, 0.100342f, 0.112000f, 0.124390f, 0.136230f, 0.148804f, 0.161621f, 0.173950f, + 0.186768f, 0.200439f, 0.213623f, 0.226074f, 0.239868f, 0.253418f, 0.267090f, 0.281250f, 0.295410f, 0.309570f, 0.323486f, 0.337891f, + 0.352295f, 0.365967f, 0.381104f, 0.394775f, 0.409180f, 0.423828f, 0.438477f, 0.452881f, 0.467773f, 0.481689f, 0.496582f, 0.511230f, + 0.525391f, 0.539551f, 0.554199f, 0.568848f, 0.583984f, 0.599121f, 0.612305f, 0.627441f, 0.641113f, 0.656250f, 0.669922f, 0.684570f, + 0.699219f, 0.713379f, 0.727539f, 0.741699f, 0.755859f, 0.771484f, 0.875488f, 0.865723f, 0.854492f, 0.845215f, 0.836426f, 0.828613f, + 0.004452f, 0.013359f, 0.022690f, 0.032745f, 0.042297f, 0.051910f, 0.061920f, 0.072693f, 0.083496f, 0.094177f, 0.105408f, 0.116760f, + 0.128174f, 0.140137f, 0.151855f, 0.164185f, 0.176758f, 0.189087f, 0.201660f, 0.214478f, 0.227173f, 0.240356f, 0.253906f, 0.267578f, + 0.280273f, 0.294922f, 0.307373f, 0.321045f, 0.336670f, 0.350098f, 0.363770f, 0.378174f, 0.392334f, 0.406006f, 0.420410f, 0.434082f, + 0.448975f, 0.463623f, 0.478271f, 0.492676f, 0.506836f, 0.520996f, 0.536133f, 0.550781f, 0.565430f, 0.580078f, 0.593750f, 0.608887f, + 0.623047f, 0.638184f, 0.651367f, 0.666016f, 0.681152f, 0.695312f, 0.709473f, 0.723145f, 0.738281f, 0.752930f, 0.867676f, 0.858398f, + 0.848633f, 0.839355f, 0.831055f, 0.823730f, 0.004143f, 0.012794f, 0.021713f, 0.030396f, 0.039551f, 0.048645f, 0.058563f, 0.068176f, + 0.078308f, 0.088928f, 0.098328f, 0.109924f, 0.120728f, 0.131592f, 0.142944f, 0.154175f, 0.165771f, 0.178223f, 0.190186f, 0.202881f, + 0.214844f, 0.227417f, 0.240845f, 0.253906f, 0.265869f, 0.279541f, 0.293213f, 0.305908f, 0.320068f, 0.333496f, 0.347168f, 0.361816f, + 0.375000f, 0.389160f, 0.403320f, 0.417236f, 0.431396f, 0.444824f, 0.459473f, 0.473633f, 0.488525f, 0.503418f, 0.517578f, 0.532227f, + 0.545410f, 0.560547f, 0.575684f, 0.590332f, 0.604004f, 0.618652f, 0.632812f, 0.647949f, 0.663086f, 0.676758f, 0.691895f, 0.706543f, + 0.721191f, 0.735840f, 0.859375f, 0.852539f, 0.842773f, 0.833496f, 0.824707f, 0.818848f, 0.003839f, 0.012062f, 0.020126f, 0.028366f, + 0.036774f, 0.045593f, 0.054718f, 0.063416f, 0.073120f, 0.082825f, 0.092957f, 0.102966f, 0.113464f, 0.123535f, 0.134277f, 0.145020f, + 0.155762f, 0.167847f, 0.179199f, 0.190796f, 0.202393f, 0.214844f, 0.227417f, 0.239868f, 0.252197f, 0.264648f, 0.277588f, 0.291016f, + 0.304199f, 0.317383f, 0.330811f, 0.343750f, 0.357422f, 0.371826f, 0.385254f, 0.399902f, 0.413574f, 0.427246f, 0.441162f, 0.455566f, + 0.469971f, 0.484375f, 0.498535f, 0.514160f, 0.527344f, 0.541992f, 0.556152f, 0.570312f, 0.585449f, 0.600098f, 0.614746f, 0.629883f, + 0.645508f, 0.658203f, 0.673340f, 0.688477f, 0.703125f, 0.718262f, 0.851074f, 0.844727f, 0.835938f, 0.827637f, 0.820312f, 0.812988f, + 0.003786f, 0.011147f, 0.018921f, 0.026550f, 0.034729f, 0.042664f, 0.051117f, 0.060028f, 0.068298f, 0.077454f, 0.086914f, 0.096130f, + 0.105835f, 0.115662f, 0.126343f, 0.136475f, 0.146606f, 0.157715f, 0.168457f, 0.180176f, 0.191528f, 0.202759f, 0.215088f, 0.226929f, + 0.239014f, 0.251221f, 0.263428f, 0.275391f, 0.289062f, 0.301514f, 0.314941f, 0.328369f, 0.341797f, 0.354736f, 0.367676f, 0.382324f, + 0.395264f, 0.409912f, 0.423340f, 0.437012f, 0.451660f, 0.465576f, 0.480469f, 0.494629f, 0.508301f, 0.522949f, 0.538086f, 0.551758f, + 0.567383f, 0.582031f, 0.596191f, 0.610840f, 0.625977f, 0.639648f, 0.655273f, 0.670410f, 0.685547f, 0.700684f, 0.842285f, 0.837402f, + 0.829590f, 0.821289f, 0.813965f, 0.808105f, 0.003504f, 0.010445f, 0.017609f, 0.025131f, 0.032349f, 0.040314f, 0.047485f, 0.055756f, + 0.064026f, 0.072571f, 0.080872f, 0.089661f, 0.099426f, 0.108459f, 0.118286f, 0.127930f, 0.137817f, 0.147583f, 0.158203f, 0.169189f, + 0.180908f, 0.191040f, 0.203003f, 0.214111f, 0.225708f, 0.237549f, 0.249023f, 0.261475f, 0.273926f, 0.286865f, 0.299316f, 0.311768f, + 0.325684f, 0.338623f, 0.351562f, 0.364746f, 0.378418f, 0.392578f, 0.405518f, 0.419678f, 0.433105f, 0.447998f, 0.461670f, 0.475830f, + 0.490479f, 0.503906f, 0.519531f, 0.533203f, 0.547852f, 0.562988f, 0.576660f, 0.591797f, 0.606445f, 0.622070f, 0.636719f, 0.652344f, + 0.666504f, 0.682617f, 0.833496f, 0.830078f, 0.822754f, 0.815918f, 0.808594f, 0.802734f, 0.003447f, 0.009941f, 0.016373f, 0.023300f, + 0.030228f, 0.037689f, 0.044128f, 0.052551f, 0.059845f, 0.068115f, 0.076538f, 0.083862f, 0.092896f, 0.101440f, 0.110596f, 0.119995f, + 0.129028f, 0.138916f, 0.148926f, 0.158936f, 0.169189f, 0.180176f, 0.190308f, 0.201416f, 0.212769f, 0.224365f, 0.235962f, 0.247192f, + 0.259033f, 0.271973f, 0.283936f, 0.296631f, 0.309570f, 0.321777f, 0.334961f, 0.348389f, 0.361572f, 0.374756f, 0.388184f, 0.401611f, + 0.415771f, 0.429443f, 0.443359f, 0.457520f, 0.471436f, 0.486084f, 0.500977f, 0.514648f, 0.528809f, 0.543457f, 0.558594f, 0.573242f, + 0.588867f, 0.603516f, 0.617676f, 0.633301f, 0.648926f, 0.664551f, 0.824219f, 0.823242f, 0.815918f, 0.809082f, 0.802246f, 0.796387f, + 0.003141f, 0.009407f, 0.015251f, 0.021851f, 0.028107f, 0.034882f, 0.041779f, 0.048340f, 0.056244f, 0.062988f, 0.071106f, 0.078796f, + 0.087036f, 0.094910f, 0.103149f, 0.112305f, 0.121460f, 0.130371f, 0.139404f, 0.149048f, 0.159180f, 0.169189f, 0.179565f, 0.189087f, + 0.200317f, 0.211548f, 0.222412f, 0.233765f, 0.245117f, 0.257324f, 0.269043f, 0.281006f, 0.293213f, 0.305664f, 0.318848f, 0.331055f, + 0.343750f, 0.358398f, 0.369873f, 0.384033f, 0.397217f, 0.411865f, 0.424805f, 0.438965f, 0.453125f, 0.467529f, 0.481689f, 0.495850f, + 0.510254f, 0.524414f, 0.539551f, 0.554688f, 0.569824f, 0.584961f, 0.599121f, 0.614258f, 0.629883f, 0.645020f, 0.815430f, 0.814453f, + 0.809570f, 0.802734f, 0.796875f, 0.791504f, 0.002838f, 0.008461f, 0.014236f, 0.020676f, 0.026749f, 0.032593f, 0.039032f, 0.045715f, + 0.052216f, 0.059479f, 0.066467f, 0.073608f, 0.080933f, 0.088623f, 0.096619f, 0.104919f, 0.113098f, 0.121521f, 0.130493f, 0.139526f, + 0.148560f, 0.158203f, 0.167969f, 0.177979f, 0.187988f, 0.198730f, 0.208862f, 0.220093f, 0.231323f, 0.242798f, 0.253906f, 0.265869f, + 0.278320f, 0.289551f, 0.302246f, 0.314941f, 0.327393f, 0.340088f, 0.353516f, 0.365967f, 0.379883f, 0.392822f, 0.406738f, 0.420898f, + 0.434814f, 0.447998f, 0.462891f, 0.477539f, 0.491455f, 0.506836f, 0.520996f, 0.536133f, 0.550781f, 0.565918f, 0.581055f, 0.596680f, + 0.611816f, 0.627441f, 0.806152f, 0.807617f, 0.801270f, 0.796387f, 0.790039f, 0.784668f, 0.002689f, 0.008102f, 0.013618f, 0.019058f, + 0.024719f, 0.030548f, 0.036560f, 0.042725f, 0.048615f, 0.054779f, 0.061615f, 0.068604f, 0.075012f, 0.082703f, 0.090271f, 0.097900f, + 0.105530f, 0.113586f, 0.121826f, 0.130371f, 0.139282f, 0.147705f, 0.157349f, 0.166504f, 0.176147f, 0.186401f, 0.196289f, 0.207520f, + 0.217651f, 0.228394f, 0.239868f, 0.251465f, 0.262451f, 0.274414f, 0.286377f, 0.298828f, 0.311035f, 0.323730f, 0.336670f, 0.349121f, + 0.362549f, 0.375244f, 0.389160f, 0.402344f, 0.417236f, 0.429932f, 0.443848f, 0.458984f, 0.472168f, 0.487793f, 0.501953f, 0.517578f, + 0.531738f, 0.546875f, 0.561523f, 0.576660f, 0.593262f, 0.608398f, 0.797852f, 0.798828f, 0.794922f, 0.789551f, 0.784668f, 0.779297f, + 0.002666f, 0.007462f, 0.012596f, 0.018066f, 0.023026f, 0.028412f, 0.033813f, 0.039398f, 0.045166f, 0.051239f, 0.057587f, 0.063721f, + 0.070312f, 0.077148f, 0.084167f, 0.090820f, 0.098267f, 0.105591f, 0.113159f, 0.121460f, 0.129761f, 0.138428f, 0.147217f, 0.156128f, + 0.165283f, 0.174438f, 0.183960f, 0.194092f, 0.204834f, 0.214844f, 0.225830f, 0.236816f, 0.247925f, 0.259033f, 0.270752f, 0.282227f, + 0.294678f, 0.306641f, 0.319336f, 0.332031f, 0.344482f, 0.357910f, 0.371094f, 0.384033f, 0.398682f, 0.412109f, 0.425781f, 0.440186f, + 0.454102f, 0.468018f, 0.482910f, 0.497314f, 0.512207f, 0.528320f, 0.542969f, 0.558594f, 0.573242f, 0.589355f, 0.787598f, 0.791016f, + 0.787109f, 0.781738f, 0.777344f, 0.772461f, 0.002569f, 0.007069f, 0.012199f, 0.016739f, 0.021393f, 0.026672f, 0.031189f, 0.037109f, + 0.042480f, 0.047729f, 0.053345f, 0.059387f, 0.065430f, 0.071838f, 0.078186f, 0.084167f, 0.091492f, 0.098816f, 0.105774f, 0.112976f, + 0.121155f, 0.129028f, 0.136963f, 0.145508f, 0.153687f, 0.163086f, 0.172363f, 0.181885f, 0.191406f, 0.201782f, 0.211670f, 0.222412f, + 0.233032f, 0.244263f, 0.255371f, 0.266846f, 0.278809f, 0.290527f, 0.302734f, 0.314697f, 0.327393f, 0.340820f, 0.353027f, 0.366455f, + 0.380127f, 0.393799f, 0.406006f, 0.421143f, 0.435059f, 0.449707f, 0.463623f, 0.479248f, 0.494141f, 0.509277f, 0.523438f, 0.539551f, + 0.555176f, 0.570801f, 0.778320f, 0.783203f, 0.779785f, 0.775879f, 0.770996f, 0.767090f, 0.002398f, 0.006733f, 0.010918f, 0.015495f, + 0.020203f, 0.024963f, 0.029663f, 0.034485f, 0.039246f, 0.044678f, 0.049896f, 0.055267f, 0.060486f, 0.066345f, 0.072693f, 0.078857f, + 0.085083f, 0.091370f, 0.097961f, 0.105530f, 0.112244f, 0.119629f, 0.127563f, 0.135376f, 0.143799f, 0.152100f, 0.160889f, 0.169922f, + 0.178833f, 0.188843f, 0.198608f, 0.208496f, 0.218628f, 0.229492f, 0.240479f, 0.251953f, 0.262695f, 0.274902f, 0.286377f, 0.298340f, + 0.310547f, 0.323242f, 0.335693f, 0.349365f, 0.362061f, 0.375000f, 0.388916f, 0.402832f, 0.416748f, 0.430420f, 0.445068f, 0.459473f, + 0.474854f, 0.489258f, 0.504883f, 0.519531f, 0.535645f, 0.551758f, 0.769043f, 0.774902f, 0.771973f, 0.768555f, 0.764160f, 0.759766f, + 0.002062f, 0.006191f, 0.010384f, 0.014786f, 0.018402f, 0.023270f, 0.027435f, 0.031891f, 0.036163f, 0.041199f, 0.045685f, 0.051208f, + 0.056244f, 0.061371f, 0.066772f, 0.072510f, 0.078369f, 0.084656f, 0.091125f, 0.097290f, 0.104309f, 0.111145f, 0.118164f, 0.126221f, + 0.133301f, 0.141724f, 0.149658f, 0.157837f, 0.167236f, 0.176025f, 0.185547f, 0.195190f, 0.205444f, 0.215332f, 0.225830f, 0.236084f, + 0.247314f, 0.259033f, 0.270020f, 0.281982f, 0.293701f, 0.305908f, 0.318848f, 0.331787f, 0.344482f, 0.357178f, 0.370361f, 0.384521f, + 0.397461f, 0.411621f, 0.426025f, 0.440674f, 0.455322f, 0.470703f, 0.485596f, 0.500977f, 0.517578f, 0.532227f, 0.759277f, 0.766602f, + 0.764160f, 0.761230f, 0.757324f, 0.753418f, 0.002064f, 0.005859f, 0.009613f, 0.013626f, 0.017456f, 0.021606f, 0.025574f, 0.029526f, + 0.034302f, 0.038422f, 0.042938f, 0.047485f, 0.052155f, 0.056763f, 0.061951f, 0.067139f, 0.072754f, 0.078308f, 0.084167f, 0.090149f, + 0.096191f, 0.102722f, 0.109558f, 0.116699f, 0.123901f, 0.131104f, 0.139160f, 0.146729f, 0.155273f, 0.163940f, 0.173096f, 0.182129f, + 0.192017f, 0.201172f, 0.211060f, 0.221558f, 0.232544f, 0.243530f, 0.254150f, 0.266113f, 0.277588f, 0.289307f, 0.301758f, 0.313965f, + 0.326904f, 0.338867f, 0.352051f, 0.366211f, 0.379150f, 0.393066f, 0.407471f, 0.421875f, 0.436768f, 0.450439f, 0.466553f, 0.481201f, + 0.497314f, 0.513184f, 0.749512f, 0.758301f, 0.756348f, 0.753906f, 0.750000f, 0.746582f, 0.001851f, 0.005405f, 0.009109f, 0.012589f, + 0.016129f, 0.020020f, 0.023926f, 0.027481f, 0.031738f, 0.035492f, 0.039734f, 0.044128f, 0.048065f, 0.052765f, 0.057373f, 0.061859f, + 0.066711f, 0.072388f, 0.077393f, 0.083130f, 0.088745f, 0.094727f, 0.101135f, 0.107666f, 0.114380f, 0.121704f, 0.128540f, 0.136108f, + 0.144043f, 0.151733f, 0.160522f, 0.169678f, 0.178589f, 0.187622f, 0.197998f, 0.207397f, 0.217285f, 0.227905f, 0.238892f, 0.250000f, + 0.261230f, 0.272461f, 0.284180f, 0.296387f, 0.308838f, 0.321533f, 0.334473f, 0.347656f, 0.361328f, 0.375000f, 0.388672f, 0.402588f, + 0.417969f, 0.432617f, 0.447021f, 0.461914f, 0.478516f, 0.493652f, 0.739258f, 0.749512f, 0.749023f, 0.745605f, 0.742188f, 0.739746f, + 0.001666f, 0.005405f, 0.008575f, 0.011696f, 0.015327f, 0.018646f, 0.022293f, 0.025650f, 0.029327f, 0.032776f, 0.036530f, 0.040619f, + 0.044128f, 0.048828f, 0.052887f, 0.057098f, 0.061829f, 0.066467f, 0.071350f, 0.076355f, 0.081909f, 0.087341f, 0.092896f, 0.099304f, + 0.105469f, 0.112000f, 0.118835f, 0.125977f, 0.133545f, 0.140991f, 0.148438f, 0.156982f, 0.165771f, 0.174805f, 0.183960f, 0.193115f, + 0.203369f, 0.212891f, 0.223389f, 0.234497f, 0.244751f, 0.256348f, 0.268066f, 0.279541f, 0.291260f, 0.303955f, 0.316406f, 0.329590f, + 0.342529f, 0.355957f, 0.369385f, 0.384766f, 0.398926f, 0.413330f, 0.428467f, 0.442383f, 0.458740f, 0.474609f, 0.728516f, 0.740723f, + 0.740234f, 0.738281f, 0.735352f, 0.732910f, 0.001534f, 0.004936f, 0.007980f, 0.011223f, 0.013893f, 0.017212f, 0.020294f, 0.023361f, + 0.026688f, 0.030182f, 0.033600f, 0.037537f, 0.040924f, 0.044495f, 0.048340f, 0.052155f, 0.056732f, 0.061035f, 0.065430f, 0.069824f, + 0.075073f, 0.080078f, 0.085571f, 0.091003f, 0.096863f, 0.103271f, 0.109009f, 0.115723f, 0.123230f, 0.129639f, 0.137207f, 0.145264f, + 0.153320f, 0.161499f, 0.170410f, 0.179688f, 0.189087f, 0.198364f, 0.208740f, 0.218750f, 0.229126f, 0.240356f, 0.251465f, 0.263184f, + 0.274902f, 0.286621f, 0.299072f, 0.311768f, 0.324463f, 0.337402f, 0.351074f, 0.364746f, 0.378662f, 0.394287f, 0.408936f, 0.423096f, + 0.439453f, 0.455322f, 0.716797f, 0.731934f, 0.732422f, 0.729980f, 0.728027f, 0.725586f, 0.001639f, 0.004337f, 0.007439f, 0.009888f, + 0.013092f, 0.015717f, 0.018921f, 0.021805f, 0.024612f, 0.027542f, 0.030762f, 0.034088f, 0.037598f, 0.041107f, 0.044189f, 0.047699f, + 0.051666f, 0.055664f, 0.059723f, 0.064148f, 0.068542f, 0.073425f, 0.078003f, 0.083435f, 0.088806f, 0.094360f, 0.100159f, 0.106079f, + 0.112915f, 0.119690f, 0.125977f, 0.133667f, 0.141357f, 0.149414f, 0.157349f, 0.166260f, 0.175049f, 0.184326f, 0.193970f, 0.203735f, + 0.214355f, 0.224609f, 0.235352f, 0.246460f, 0.257568f, 0.269287f, 0.281738f, 0.294189f, 0.305908f, 0.319824f, 0.332520f, 0.346680f, + 0.360596f, 0.375244f, 0.389648f, 0.404297f, 0.419189f, 0.435791f, 0.707520f, 0.723145f, 0.723633f, 0.722656f, 0.720703f, 0.717773f, + 0.001469f, 0.004345f, 0.006844f, 0.009483f, 0.012428f, 0.014679f, 0.017166f, 0.019989f, 0.022949f, 0.025574f, 0.028320f, 0.031525f, + 0.034088f, 0.037323f, 0.040710f, 0.043762f, 0.047119f, 0.050873f, 0.054352f, 0.058441f, 0.062561f, 0.066711f, 0.071167f, 0.075989f, + 0.080627f, 0.086426f, 0.091553f, 0.097473f, 0.103210f, 0.109680f, 0.115723f, 0.122986f, 0.129761f, 0.137451f, 0.145142f, 0.153198f, + 0.161621f, 0.170654f, 0.179688f, 0.189087f, 0.198730f, 0.209229f, 0.219604f, 0.230225f, 0.241211f, 0.252197f, 0.264404f, 0.276367f, + 0.288574f, 0.301270f, 0.314453f, 0.328125f, 0.341309f, 0.354980f, 0.370117f, 0.385498f, 0.399902f, 0.415771f, 0.696289f, 0.714355f, + 0.715820f, 0.714355f, 0.712891f, 0.710449f, 0.001227f, 0.003862f, 0.006245f, 0.008644f, 0.010796f, 0.013344f, 0.015823f, 0.018448f, + 0.020645f, 0.023331f, 0.025681f, 0.028305f, 0.030975f, 0.033722f, 0.036987f, 0.039673f, 0.043121f, 0.046112f, 0.049774f, 0.053406f, + 0.056854f, 0.060760f, 0.064697f, 0.069397f, 0.073364f, 0.078369f, 0.083313f, 0.088257f, 0.094116f, 0.100098f, 0.105957f, 0.112122f, + 0.118774f, 0.125854f, 0.133057f, 0.140869f, 0.148682f, 0.157227f, 0.165405f, 0.174927f, 0.184082f, 0.193726f, 0.204102f, 0.214111f, + 0.225098f, 0.236328f, 0.247314f, 0.259277f, 0.270752f, 0.282959f, 0.296143f, 0.309082f, 0.322510f, 0.336426f, 0.350830f, 0.365479f, + 0.380371f, 0.396240f, 0.684570f, 0.705078f, 0.706543f, 0.706543f, 0.705078f, 0.703125f, 0.001069f, 0.003525f, 0.006062f, 0.008286f, + 0.010178f, 0.012589f, 0.014542f, 0.017075f, 0.019241f, 0.021179f, 0.023499f, 0.026047f, 0.028137f, 0.030762f, 0.033417f, 0.035889f, + 0.038757f, 0.041779f, 0.044586f, 0.048309f, 0.051056f, 0.054810f, 0.058777f, 0.062347f, 0.066528f, 0.070740f, 0.075256f, 0.080261f, + 0.085205f, 0.090393f, 0.095886f, 0.102478f, 0.108154f, 0.114441f, 0.121399f, 0.128784f, 0.135742f, 0.144165f, 0.151978f, 0.160767f, + 0.169434f, 0.178833f, 0.188721f, 0.198608f, 0.208984f, 0.220215f, 0.230957f, 0.241943f, 0.253906f, 0.265869f, 0.278564f, 0.291260f, + 0.304443f, 0.318359f, 0.332031f, 0.346680f, 0.361572f, 0.377197f, 0.673828f, 0.695801f, 0.698242f, 0.697754f, 0.697266f, 0.695312f, + 0.001211f, 0.003250f, 0.005112f, 0.007195f, 0.009651f, 0.011414f, 0.013641f, 0.015205f, 0.017334f, 0.019608f, 0.021164f, 0.023712f, + 0.025726f, 0.027863f, 0.029984f, 0.032410f, 0.035034f, 0.037689f, 0.040466f, 0.042938f, 0.046478f, 0.049591f, 0.052856f, 0.056274f, + 0.060089f, 0.063721f, 0.068115f, 0.072266f, 0.076904f, 0.081970f, 0.087036f, 0.092285f, 0.097961f, 0.104309f, 0.110535f, 0.117126f, + 0.124084f, 0.131226f, 0.139038f, 0.147095f, 0.155884f, 0.164429f, 0.174194f, 0.183228f, 0.192749f, 0.203491f, 0.214233f, 0.224976f, + 0.236206f, 0.247925f, 0.260498f, 0.272705f, 0.285889f, 0.299805f, 0.312988f, 0.327637f, 0.342529f, 0.356934f, 0.662598f, 0.686523f, + 0.689453f, 0.689453f, 0.688965f, 0.687500f, 0.001138f, 0.003206f, 0.005180f, 0.007309f, 0.008377f, 0.010635f, 0.012352f, 0.014153f, + 0.015640f, 0.017487f, 0.019272f, 0.021164f, 0.023026f, 0.025314f, 0.027222f, 0.029282f, 0.031433f, 0.033600f, 0.036041f, 0.038788f, + 0.041626f, 0.044281f, 0.047455f, 0.050507f, 0.054047f, 0.057556f, 0.061188f, 0.065063f, 0.069214f, 0.073486f, 0.078369f, 0.083191f, + 0.088196f, 0.093811f, 0.099609f, 0.106018f, 0.112305f, 0.119385f, 0.126343f, 0.134033f, 0.142090f, 0.150635f, 0.159546f, 0.168579f, + 0.177734f, 0.187500f, 0.198242f, 0.208618f, 0.219604f, 0.231812f, 0.242188f, 0.254883f, 0.267578f, 0.281494f, 0.294434f, 0.308350f, + 0.322998f, 0.338379f, 0.651367f, 0.676758f, 0.681152f, 0.680664f, 0.680664f, 0.679688f, 0.000977f, 0.002806f, 0.004559f, 0.006176f, + 0.008034f, 0.009476f, 0.011131f, 0.012741f, 0.014275f, 0.015732f, 0.017334f, 0.019104f, 0.020767f, 0.022293f, 0.024323f, 0.026016f, + 0.028198f, 0.030197f, 0.032257f, 0.034515f, 0.036957f, 0.039856f, 0.042084f, 0.044891f, 0.047791f, 0.051147f, 0.054535f, 0.058197f, + 0.061768f, 0.065674f, 0.069946f, 0.074585f, 0.079102f, 0.084412f, 0.089600f, 0.095398f, 0.101196f, 0.107544f, 0.114258f, 0.121094f, + 0.128662f, 0.137085f, 0.145020f, 0.153687f, 0.162720f, 0.172607f, 0.182129f, 0.192749f, 0.203125f, 0.214111f, 0.226074f, 0.237671f, + 0.249878f, 0.262207f, 0.275635f, 0.289551f, 0.304199f, 0.318848f, 0.639160f, 0.666992f, 0.671387f, 0.671875f, 0.671875f, 0.671387f, + 0.000968f, 0.002722f, 0.004318f, 0.005634f, 0.007393f, 0.008667f, 0.010139f, 0.011383f, 0.012856f, 0.014389f, 0.015427f, 0.016907f, + 0.018387f, 0.020081f, 0.021683f, 0.023315f, 0.025085f, 0.026840f, 0.028641f, 0.030624f, 0.032837f, 0.035065f, 0.037445f, 0.039948f, + 0.042542f, 0.045410f, 0.048340f, 0.051514f, 0.054840f, 0.058502f, 0.062408f, 0.066223f, 0.070679f, 0.075134f, 0.080078f, 0.085388f, + 0.090515f, 0.096436f, 0.102722f, 0.109314f, 0.116333f, 0.123352f, 0.131592f, 0.139526f, 0.147949f, 0.156860f, 0.166748f, 0.176758f, + 0.187134f, 0.197632f, 0.209106f, 0.220337f, 0.232666f, 0.244751f, 0.257568f, 0.270996f, 0.284912f, 0.300537f, 0.627441f, 0.657227f, + 0.662598f, 0.663574f, 0.663574f, 0.663086f, 0.001081f, 0.002466f, 0.003862f, 0.005348f, 0.006447f, 0.007927f, 0.009018f, 0.010490f, + 0.011436f, 0.012627f, 0.013916f, 0.015015f, 0.016449f, 0.017563f, 0.019165f, 0.020706f, 0.021973f, 0.023834f, 0.025467f, 0.027130f, + 0.029175f, 0.030991f, 0.033081f, 0.035156f, 0.037384f, 0.040039f, 0.042603f, 0.045502f, 0.048492f, 0.051636f, 0.054962f, 0.058716f, + 0.062439f, 0.066467f, 0.071045f, 0.075378f, 0.080811f, 0.085815f, 0.091492f, 0.098022f, 0.103943f, 0.111023f, 0.118164f, 0.125732f, + 0.133911f, 0.142456f, 0.151367f, 0.161011f, 0.170898f, 0.181396f, 0.192139f, 0.203247f, 0.214844f, 0.227173f, 0.239380f, 0.252441f, + 0.266602f, 0.281006f, 0.616699f, 0.647949f, 0.653320f, 0.655273f, 0.654785f, 0.655273f, 0.000735f, 0.002331f, 0.003601f, 0.005005f, + 0.005825f, 0.007061f, 0.008049f, 0.009148f, 0.010315f, 0.011131f, 0.012230f, 0.013367f, 0.014328f, 0.015541f, 0.016968f, 0.018234f, + 0.019257f, 0.020798f, 0.022202f, 0.023666f, 0.025452f, 0.027115f, 0.028885f, 0.030792f, 0.032715f, 0.035034f, 0.037323f, 0.039825f, + 0.042419f, 0.045258f, 0.048157f, 0.051422f, 0.054810f, 0.058411f, 0.062378f, 0.066528f, 0.071106f, 0.076233f, 0.081116f, 0.086853f, + 0.092407f, 0.098938f, 0.105469f, 0.112854f, 0.120361f, 0.128418f, 0.136841f, 0.145752f, 0.155273f, 0.165283f, 0.175537f, 0.186646f, + 0.197510f, 0.209473f, 0.221558f, 0.234619f, 0.248047f, 0.261719f, 0.603516f, 0.636719f, 0.644531f, 0.645020f, 0.645508f, 0.646484f, + 0.000837f, 0.002073f, 0.003357f, 0.004292f, 0.005409f, 0.006271f, 0.007271f, 0.007973f, 0.008873f, 0.009956f, 0.010811f, 0.012032f, + 0.012848f, 0.013664f, 0.014870f, 0.015839f, 0.017090f, 0.018280f, 0.019333f, 0.020691f, 0.022186f, 0.023453f, 0.025223f, 0.026779f, + 0.028595f, 0.030441f, 0.032410f, 0.034729f, 0.036743f, 0.039307f, 0.042023f, 0.044434f, 0.047791f, 0.050781f, 0.054413f, 0.058075f, + 0.061951f, 0.066711f, 0.071106f, 0.076355f, 0.081848f, 0.087341f, 0.093872f, 0.099854f, 0.107483f, 0.114441f, 0.122925f, 0.131104f, + 0.140381f, 0.149414f, 0.159180f, 0.170166f, 0.181152f, 0.192139f, 0.204468f, 0.216553f, 0.230103f, 0.244507f, 0.592773f, 0.626953f, + 0.635254f, 0.637207f, 0.636719f, 0.637695f, 0.000524f, 0.001863f, 0.003014f, 0.003777f, 0.004852f, 0.005516f, 0.006428f, 0.007111f, + 0.008095f, 0.008888f, 0.009476f, 0.010345f, 0.011063f, 0.012016f, 0.012810f, 0.013786f, 0.014648f, 0.015717f, 0.016891f, 0.017929f, + 0.019150f, 0.020401f, 0.021606f, 0.023193f, 0.024597f, 0.026276f, 0.027939f, 0.029770f, 0.031738f, 0.033936f, 0.036194f, 0.038574f, + 0.041107f, 0.043945f, 0.047180f, 0.050385f, 0.054291f, 0.057770f, 0.061981f, 0.066345f, 0.071167f, 0.076355f, 0.082153f, 0.088074f, + 0.094666f, 0.101685f, 0.109131f, 0.117249f, 0.125610f, 0.134399f, 0.143921f, 0.154175f, 0.164795f, 0.175659f, 0.187256f, 0.199341f, + 0.211670f, 0.225464f, 0.580078f, 0.617676f, 0.625000f, 0.627930f, 0.628906f, 0.628906f, 0.000657f, 0.001829f, 0.002909f, 0.003525f, + 0.004295f, 0.005051f, 0.005592f, 0.006123f, 0.006920f, 0.007553f, 0.008339f, 0.008888f, 0.009689f, 0.010262f, 0.011017f, 0.011848f, + 0.012634f, 0.013489f, 0.014572f, 0.015427f, 0.016449f, 0.017426f, 0.018539f, 0.019852f, 0.021133f, 0.022507f, 0.023834f, 0.025375f, + 0.027084f, 0.028976f, 0.030792f, 0.032959f, 0.035400f, 0.037720f, 0.040405f, 0.043243f, 0.046356f, 0.049530f, 0.053314f, 0.057190f, + 0.061554f, 0.066223f, 0.071472f, 0.076782f, 0.082825f, 0.089417f, 0.096191f, 0.103210f, 0.111633f, 0.119934f, 0.128662f, 0.138550f, + 0.148315f, 0.158813f, 0.170288f, 0.182373f, 0.194458f, 0.207642f, 0.567383f, 0.606445f, 0.615234f, 0.619141f, 0.620117f, 0.620117f, + 0.000584f, 0.001548f, 0.002333f, 0.003086f, 0.003660f, 0.004303f, 0.005020f, 0.005543f, 0.006042f, 0.006538f, 0.007118f, 0.007641f, + 0.008301f, 0.008919f, 0.009499f, 0.010147f, 0.010918f, 0.011414f, 0.012222f, 0.013084f, 0.013901f, 0.014954f, 0.015671f, 0.016724f, + 0.017914f, 0.019012f, 0.020325f, 0.021698f, 0.022949f, 0.024445f, 0.026215f, 0.027954f, 0.029755f, 0.032043f, 0.034210f, 0.036591f, + 0.039215f, 0.042297f, 0.045441f, 0.048676f, 0.052612f, 0.056580f, 0.061432f, 0.066040f, 0.071350f, 0.077332f, 0.083496f, 0.090393f, + 0.097717f, 0.105835f, 0.114380f, 0.123413f, 0.133301f, 0.143066f, 0.153931f, 0.165039f, 0.177124f, 0.190308f, 0.555176f, 0.597656f, + 0.604980f, 0.609375f, 0.609863f, 0.611328f, 0.000438f, 0.001456f, 0.001925f, 0.002811f, 0.003246f, 0.003731f, 0.004108f, 0.004669f, + 0.005344f, 0.005535f, 0.005913f, 0.006641f, 0.007038f, 0.007473f, 0.008049f, 0.008675f, 0.009361f, 0.009689f, 0.010513f, 0.011032f, + 0.011894f, 0.012695f, 0.013390f, 0.014183f, 0.015114f, 0.016037f, 0.016998f, 0.018280f, 0.019272f, 0.020645f, 0.022003f, 0.023361f, + 0.024796f, 0.026779f, 0.028656f, 0.030685f, 0.032928f, 0.035370f, 0.038147f, 0.040955f, 0.044403f, 0.047821f, 0.052032f, 0.056183f, + 0.060974f, 0.066162f, 0.071777f, 0.078125f, 0.084656f, 0.092102f, 0.100159f, 0.109009f, 0.117981f, 0.127563f, 0.138306f, 0.148804f, + 0.160645f, 0.173218f, 0.542969f, 0.586914f, 0.594727f, 0.599609f, 0.601074f, 0.601074f, 0.000520f, 0.001104f, 0.001921f, 0.002256f, + 0.002886f, 0.003389f, 0.003689f, 0.004063f, 0.004440f, 0.004829f, 0.005230f, 0.005466f, 0.005966f, 0.006332f, 0.006786f, 0.007347f, + 0.007835f, 0.008232f, 0.008812f, 0.009216f, 0.009865f, 0.010490f, 0.011124f, 0.011803f, 0.012573f, 0.013390f, 0.014275f, 0.015121f, + 0.016144f, 0.016953f, 0.018234f, 0.019257f, 0.020782f, 0.022064f, 0.023743f, 0.025360f, 0.027176f, 0.029327f, 0.031616f, 0.034058f, + 0.036957f, 0.039917f, 0.043182f, 0.047272f, 0.051025f, 0.055695f, 0.060913f, 0.066345f, 0.072693f, 0.079285f, 0.086548f, 0.094543f, + 0.103271f, 0.112793f, 0.122864f, 0.132812f, 0.144531f, 0.156616f, 0.530273f, 0.576660f, 0.585449f, 0.590332f, 0.592285f, 0.593262f, + 0.000366f, 0.001040f, 0.001583f, 0.002129f, 0.002522f, 0.002792f, 0.003012f, 0.003420f, 0.003630f, 0.003967f, 0.004246f, 0.004623f, + 0.005039f, 0.005253f, 0.005627f, 0.006096f, 0.006447f, 0.006939f, 0.007179f, 0.007710f, 0.008324f, 0.008698f, 0.009247f, 0.009796f, + 0.010414f, 0.011063f, 0.011627f, 0.012543f, 0.013191f, 0.014099f, 0.014938f, 0.015930f, 0.016983f, 0.018219f, 0.019440f, 0.020813f, + 0.022324f, 0.024002f, 0.025818f, 0.027969f, 0.030289f, 0.032898f, 0.035583f, 0.038727f, 0.042450f, 0.046234f, 0.050781f, 0.055695f, + 0.061157f, 0.067383f, 0.074158f, 0.081360f, 0.089478f, 0.098267f, 0.107788f, 0.117737f, 0.129028f, 0.140503f, 0.517578f, 0.566406f, + 0.575195f, 0.581055f, 0.582520f, 0.584473f, 0.000482f, 0.001008f, 0.001481f, 0.001818f, 0.002001f, 0.002296f, 0.002569f, 0.002781f, + 0.002998f, 0.003319f, 0.003620f, 0.003828f, 0.004082f, 0.004364f, 0.004658f, 0.004978f, 0.005257f, 0.005665f, 0.005993f, 0.006340f, + 0.006725f, 0.007160f, 0.007576f, 0.008095f, 0.008522f, 0.008980f, 0.009621f, 0.010170f, 0.010765f, 0.011543f, 0.012161f, 0.013023f, + 0.013840f, 0.014801f, 0.015869f, 0.016861f, 0.018127f, 0.019379f, 0.020859f, 0.022583f, 0.024261f, 0.026596f, 0.028839f, 0.031555f, + 0.034271f, 0.037628f, 0.041504f, 0.045837f, 0.050598f, 0.056000f, 0.062134f, 0.068726f, 0.076172f, 0.084656f, 0.093567f, 0.103088f, + 0.113586f, 0.125000f, 0.504883f, 0.554688f, 0.565918f, 0.570801f, 0.573242f, 0.574219f, 0.000400f, 0.000803f, 0.001046f, 0.001427f, + 0.001657f, 0.001952f, 0.002033f, 0.002337f, 0.002453f, 0.002678f, 0.002871f, 0.003120f, 0.003286f, 0.003605f, 0.003817f, 0.004036f, + 0.004299f, 0.004604f, 0.004848f, 0.005142f, 0.005428f, 0.005871f, 0.006107f, 0.006584f, 0.006908f, 0.007332f, 0.007736f, 0.008186f, + 0.008820f, 0.009308f, 0.009964f, 0.010422f, 0.011200f, 0.011993f, 0.012726f, 0.013512f, 0.014511f, 0.015610f, 0.016724f, 0.017914f, + 0.019440f, 0.021057f, 0.022827f, 0.024933f, 0.027466f, 0.030197f, 0.033295f, 0.036896f, 0.041077f, 0.045776f, 0.050995f, 0.056976f, + 0.063721f, 0.071167f, 0.079773f, 0.089172f, 0.098633f, 0.109314f, 0.491699f, 0.543457f, 0.555176f, 0.561035f, 0.563477f, 0.565430f, + 0.000279f, 0.000821f, 0.000974f, 0.001161f, 0.001382f, 0.001583f, 0.001670f, 0.001934f, 0.002064f, 0.002153f, 0.002306f, 0.002544f, + 0.002670f, 0.002909f, 0.003052f, 0.003288f, 0.003429f, 0.003624f, 0.003893f, 0.004082f, 0.004406f, 0.004635f, 0.004925f, 0.005196f, + 0.005444f, 0.005764f, 0.006134f, 0.006546f, 0.006947f, 0.007343f, 0.007858f, 0.008270f, 0.008858f, 0.009346f, 0.010010f, 0.010757f, + 0.011475f, 0.012260f, 0.013206f, 0.014214f, 0.015236f, 0.016479f, 0.017975f, 0.019623f, 0.021515f, 0.023590f, 0.026062f, 0.028976f, + 0.032471f, 0.036224f, 0.040833f, 0.046082f, 0.052094f, 0.059052f, 0.066650f, 0.075684f, 0.084778f, 0.094971f, 0.479492f, 0.532715f, + 0.545898f, 0.551270f, 0.553711f, 0.555664f, 0.000253f, 0.000612f, 0.000835f, 0.000998f, 0.001111f, 0.001228f, 0.001334f, 0.001452f, + 0.001619f, 0.001757f, 0.001837f, 0.001920f, 0.002140f, 0.002321f, 0.002453f, 0.002544f, 0.002670f, 0.002790f, 0.003086f, 0.003260f, + 0.003422f, 0.003620f, 0.003893f, 0.004101f, 0.004326f, 0.004528f, 0.004761f, 0.005051f, 0.005444f, 0.005756f, 0.006065f, 0.006435f, + 0.006882f, 0.007378f, 0.007763f, 0.008286f, 0.008865f, 0.009506f, 0.010162f, 0.011024f, 0.011826f, 0.012917f, 0.013916f, 0.015175f, + 0.016602f, 0.018204f, 0.020035f, 0.022293f, 0.024948f, 0.028076f, 0.031921f, 0.036377f, 0.041565f, 0.047577f, 0.054535f, 0.062622f, + 0.071777f, 0.081787f, 0.465576f, 0.522461f, 0.535645f, 0.541992f, 0.544922f, 0.546875f, 0.000155f, 0.000398f, 0.000680f, 0.000828f, + 0.000907f, 0.000989f, 0.001113f, 0.001081f, 0.001253f, 0.001350f, 0.001453f, 0.001573f, 0.001661f, 0.001777f, 0.001829f, 0.001978f, + 0.002062f, 0.002216f, 0.002346f, 0.002470f, 0.002644f, 0.002804f, 0.002930f, 0.003134f, 0.003265f, 0.003485f, 0.003674f, 0.003866f, + 0.004154f, 0.004333f, 0.004707f, 0.004910f, 0.005180f, 0.005581f, 0.005875f, 0.006283f, 0.006729f, 0.007164f, 0.007713f, 0.008270f, + 0.008934f, 0.009727f, 0.010513f, 0.011482f, 0.012520f, 0.013710f, 0.015152f, 0.016815f, 0.018799f, 0.021118f, 0.024048f, 0.027756f, + 0.032104f, 0.037201f, 0.043518f, 0.050903f, 0.059418f, 0.068420f, 0.453125f, 0.511719f, 0.525391f, 0.530762f, 0.535156f, 0.536621f, + 0.000303f, 0.000337f, 0.000498f, 0.000560f, 0.000603f, 0.000721f, 0.000782f, 0.000845f, 0.000880f, 0.000988f, 0.001119f, 0.001184f, + 0.001258f, 0.001377f, 0.001420f, 0.001446f, 0.001590f, 0.001666f, 0.001754f, 0.001889f, 0.001980f, 0.002073f, 0.002216f, 0.002308f, + 0.002447f, 0.002562f, 0.002758f, 0.002899f, 0.003084f, 0.003328f, 0.003506f, 0.003641f, 0.003922f, 0.004147f, 0.004391f, 0.004665f, + 0.004959f, 0.005322f, 0.005695f, 0.006119f, 0.006588f, 0.007072f, 0.007790f, 0.008392f, 0.009178f, 0.010056f, 0.011124f, 0.012383f, + 0.013832f, 0.015587f, 0.017685f, 0.020309f, 0.023926f, 0.028076f, 0.033447f, 0.039978f, 0.047638f, 0.056335f, 0.440186f, 0.500000f, + 0.514160f, 0.520996f, 0.524414f, 0.526855f, 0.000132f, 0.000296f, 0.000368f, 0.000444f, 0.000501f, 0.000519f, 0.000631f, 0.000580f, + 0.000675f, 0.000735f, 0.000820f, 0.000840f, 0.000882f, 0.000946f, 0.001029f, 0.001070f, 0.001164f, 0.001221f, 0.001286f, 0.001317f, + 0.001416f, 0.001494f, 0.001607f, 0.001681f, 0.001763f, 0.001863f, 0.001978f, 0.002069f, 0.002169f, 0.002348f, 0.002451f, 0.002661f, + 0.002754f, 0.002943f, 0.003130f, 0.003323f, 0.003553f, 0.003813f, 0.004124f, 0.004364f, 0.004669f, 0.005062f, 0.005493f, 0.005985f, + 0.006546f, 0.007172f, 0.007950f, 0.008850f, 0.009857f, 0.011116f, 0.012695f, 0.014603f, 0.016983f, 0.020157f, 0.024490f, 0.029968f, + 0.036957f, 0.045166f, 0.426025f, 0.488770f, 0.503906f, 0.511719f, 0.515137f, 0.517578f, 0.000063f, 0.000160f, 0.000267f, 0.000282f, + 0.000339f, 0.000417f, 0.000377f, 0.000433f, 0.000472f, 0.000570f, 0.000563f, 0.000578f, 0.000599f, 0.000663f, 0.000681f, 0.000759f, + 0.000760f, 0.000845f, 0.000910f, 0.000941f, 0.000997f, 0.001057f, 0.001110f, 0.001169f, 0.001238f, 0.001288f, 0.001381f, 0.001441f, + 0.001514f, 0.001655f, 0.001693f, 0.001815f, 0.001910f, 0.002028f, 0.002153f, 0.002308f, 0.002441f, 0.002607f, 0.002783f, 0.002962f, + 0.003214f, 0.003458f, 0.003744f, 0.004051f, 0.004444f, 0.004883f, 0.005402f, 0.006031f, 0.006699f, 0.007610f, 0.008766f, 0.009933f, + 0.011688f, 0.013931f, 0.017075f, 0.021454f, 0.027313f, 0.035004f, 0.414307f, 0.478271f, 0.493652f, 0.501465f, 0.505859f, 0.508301f, + 0.000120f, 0.000194f, 0.000194f, 0.000205f, 0.000245f, 0.000246f, 0.000251f, 0.000301f, 0.000322f, 0.000332f, 0.000343f, 0.000413f, + 0.000397f, 0.000448f, 0.000481f, 0.000494f, 0.000545f, 0.000556f, 0.000582f, 0.000601f, 0.000653f, 0.000676f, 0.000726f, 0.000767f, + 0.000821f, 0.000840f, 0.000919f, 0.000952f, 0.001011f, 0.001054f, 0.001116f, 0.001186f, 0.001263f, 0.001337f, 0.001418f, 0.001482f, + 0.001607f, 0.001685f, 0.001842f, 0.001965f, 0.002090f, 0.002235f, 0.002420f, 0.002613f, 0.002851f, 0.003159f, 0.003492f, 0.003887f, + 0.004345f, 0.004906f, 0.005600f, 0.006474f, 0.007645f, 0.009186f, 0.011230f, 0.014305f, 0.019135f, 0.025848f, 0.400635f, 0.466797f, + 0.483398f, 0.490967f, 0.495117f, 0.498047f, 0.000030f, 0.000140f, 0.000121f, 0.000114f, 0.000147f, 0.000178f, 0.000159f, 0.000195f, + 0.000199f, 0.000204f, 0.000216f, 0.000223f, 0.000255f, 0.000271f, 0.000288f, 0.000302f, 0.000314f, 0.000346f, 0.000357f, 0.000395f, + 0.000397f, 0.000408f, 0.000436f, 0.000470f, 0.000501f, 0.000542f, 0.000547f, 0.000566f, 0.000612f, 0.000641f, 0.000692f, 0.000722f, + 0.000767f, 0.000798f, 0.000861f, 0.000898f, 0.000963f, 0.001030f, 0.001107f, 0.001164f, 0.001255f, 0.001361f, 0.001464f, 0.001591f, + 0.001719f, 0.001871f, 0.002111f, 0.002312f, 0.002617f, 0.002964f, 0.003368f, 0.003902f, 0.004654f, 0.005653f, 0.006958f, 0.008888f, + 0.012161f, 0.017822f, 0.388672f, 0.456543f, 0.473389f, 0.481201f, 0.486328f, 0.489014f, 0.000102f, 0.000076f, 0.000076f, 0.000075f, + 0.000095f, 0.000092f, 0.000109f, 0.000111f, 0.000112f, 0.000113f, 0.000126f, 0.000147f, 0.000135f, 0.000144f, 0.000165f, 0.000161f, + 0.000179f, 0.000192f, 0.000198f, 0.000202f, 0.000224f, 0.000232f, 0.000248f, 0.000259f, 0.000278f, 0.000295f, 0.000308f, 0.000320f, + 0.000340f, 0.000353f, 0.000379f, 0.000402f, 0.000423f, 0.000440f, 0.000472f, 0.000503f, 0.000526f, 0.000564f, 0.000610f, 0.000644f, + 0.000690f, 0.000741f, 0.000810f, 0.000862f, 0.000946f, 0.001024f, 0.001121f, 0.001247f, 0.001407f, 0.001603f, 0.001822f, 0.002144f, + 0.002539f, 0.003098f, 0.003901f, 0.005096f, 0.006931f, 0.011024f, 0.375244f, 0.444092f, 0.462158f, 0.470215f, 0.475586f, 0.478760f, + 0.000085f, 0.000061f, 0.000052f, 0.000047f, 0.000049f, 0.000046f, 0.000047f, 0.000050f, 0.000055f, 0.000069f, 0.000060f, 0.000062f, + 0.000077f, 0.000066f, 0.000069f, 0.000075f, 0.000084f, 0.000093f, 0.000093f, 0.000098f, 0.000102f, 0.000108f, 0.000111f, 0.000121f, + 0.000129f, 0.000136f, 0.000142f, 0.000154f, 0.000162f, 0.000172f, 0.000182f, 0.000187f, 0.000197f, 0.000209f, 0.000225f, 0.000231f, + 0.000246f, 0.000262f, 0.000290f, 0.000306f, 0.000321f, 0.000349f, 0.000380f, 0.000402f, 0.000437f, 0.000480f, 0.000525f, 0.000579f, + 0.000649f, 0.000735f, 0.000842f, 0.000984f, 0.001173f, 0.001451f, 0.001855f, 0.002485f, 0.003542f, 0.005753f, 0.362305f, 0.434326f, + 0.451904f, 0.460693f, 0.465576f, 0.468506f, 0.000064f, 0.000044f, 0.000036f, 0.000032f, 0.000029f, 0.000027f, 0.000025f, 0.000024f, + 0.000022f, 0.000023f, 0.000021f, 0.000027f, 0.000023f, 0.000022f, 0.000028f, 0.000031f, 0.000030f, 0.000034f, 0.000036f, 0.000038f, + 0.000040f, 0.000045f, 0.000048f, 0.000042f, 0.000047f, 0.000053f, 0.000055f, 0.000054f, 0.000060f, 0.000062f, 0.000065f, 0.000072f, + 0.000078f, 0.000075f, 0.000079f, 0.000087f, 0.000093f, 0.000098f, 0.000106f, 0.000113f, 0.000121f, 0.000126f, 0.000136f, 0.000150f, + 0.000159f, 0.000173f, 0.000190f, 0.000209f, 0.000235f, 0.000265f, 0.000302f, 0.000343f, 0.000416f, 0.000515f, 0.000665f, 0.000917f, + 0.001396f, 0.002401f, 0.349854f, 0.421875f, 0.440918f, 0.449951f, 0.455811f, 0.458008f, 0.000030f, 0.000020f, 0.000016f, 0.000014f, + 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, + 0.000009f, 0.000008f, 0.000008f, 0.000008f, 0.000007f, 0.000007f, 0.000008f, 0.000008f, 0.000009f, 0.000011f, 0.000011f, 0.000013f, + 0.000013f, 0.000012f, 0.000013f, 0.000014f, 0.000016f, 0.000018f, 0.000018f, 0.000019f, 0.000021f, 0.000021f, 0.000023f, 0.000027f, + 0.000025f, 0.000028f, 0.000031f, 0.000032f, 0.000033f, 0.000038f, 0.000043f, 0.000046f, 0.000050f, 0.000055f, 0.000062f, 0.000074f, + 0.000088f, 0.000106f, 0.000138f, 0.000191f, 0.000312f, 0.000653f, 0.337402f, 0.410645f, 0.431152f, 0.438965f, 0.445068f, 0.448975f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, + 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000004f, 0.000006f, 0.000010f, 0.000026f, 0.324219f, 0.399902f, + 0.419922f, 0.429688f, 0.435059f, 0.438965f, + }, + { + 0.010521f, 0.032043f, 0.054443f, 0.076843f, 0.098572f, 0.121216f, 0.142700f, 0.164062f, 0.185913f, 0.207275f, 0.229004f, 0.249268f, + 0.270508f, 0.290527f, 0.311035f, 0.331055f, 0.350586f, 0.370361f, 0.389648f, 0.408936f, 0.428223f, 0.446533f, 0.465088f, 0.482666f, + 0.500977f, 0.519043f, 0.536133f, 0.553223f, 0.570801f, 0.587891f, 0.604980f, 0.621582f, 0.637207f, 0.653320f, 0.668945f, 0.685547f, + 0.700684f, 0.716309f, 0.730957f, 0.745605f, 0.760254f, 0.774902f, 0.789551f, 0.803711f, 0.816895f, 0.831543f, 0.845703f, 0.858887f, + 0.871582f, 0.885254f, 0.897949f, 0.910645f, 0.923340f, 0.936035f, 0.948242f, 0.959961f, 0.972168f, 0.984375f, 0.972656f, 0.936035f, + 0.910645f, 0.890137f, 0.872070f, 0.855957f, 0.010048f, 0.030350f, 0.051392f, 0.072266f, 0.093506f, 0.114319f, 0.135620f, 0.155273f, + 0.177124f, 0.197144f, 0.217773f, 0.237915f, 0.257568f, 0.277588f, 0.298096f, 0.316895f, 0.336182f, 0.355225f, 0.374268f, 0.393311f, + 0.411865f, 0.430176f, 0.448486f, 0.466309f, 0.483398f, 0.501465f, 0.519043f, 0.535645f, 0.552734f, 0.570312f, 0.586426f, 0.602539f, + 0.618652f, 0.635254f, 0.650879f, 0.666016f, 0.682129f, 0.697266f, 0.712402f, 0.727539f, 0.741699f, 0.756836f, 0.770996f, 0.785645f, + 0.799805f, 0.812988f, 0.826660f, 0.840332f, 0.854004f, 0.867676f, 0.881348f, 0.893066f, 0.907715f, 0.919434f, 0.932617f, 0.943848f, + 0.955566f, 0.968262f, 0.965332f, 0.930664f, 0.906738f, 0.886719f, 0.869629f, 0.854004f, 0.009254f, 0.028961f, 0.048615f, 0.068054f, + 0.088562f, 0.108093f, 0.128540f, 0.147705f, 0.167236f, 0.188599f, 0.207886f, 0.227295f, 0.244873f, 0.265625f, 0.284668f, 0.303955f, + 0.322510f, 0.340820f, 0.358887f, 0.378662f, 0.396484f, 0.414307f, 0.431885f, 0.448975f, 0.466797f, 0.484619f, 0.500977f, 0.519043f, + 0.535645f, 0.551758f, 0.568359f, 0.584961f, 0.600586f, 0.616699f, 0.632324f, 0.647949f, 0.663086f, 0.678223f, 0.693848f, 0.708984f, + 0.723633f, 0.738281f, 0.752930f, 0.767578f, 0.780762f, 0.794922f, 0.809082f, 0.822754f, 0.835938f, 0.849609f, 0.863770f, 0.875488f, + 0.888672f, 0.902344f, 0.915527f, 0.927246f, 0.939453f, 0.952637f, 0.958008f, 0.925293f, 0.901855f, 0.882812f, 0.866211f, 0.851562f, + 0.008736f, 0.027039f, 0.045807f, 0.064514f, 0.083801f, 0.102844f, 0.121826f, 0.140869f, 0.159302f, 0.179077f, 0.197388f, 0.216064f, + 0.234741f, 0.253662f, 0.271729f, 0.290283f, 0.308350f, 0.327148f, 0.344238f, 0.362061f, 0.381836f, 0.398926f, 0.416016f, 0.432373f, + 0.450195f, 0.466797f, 0.484375f, 0.500977f, 0.517090f, 0.533691f, 0.550781f, 0.567871f, 0.582031f, 0.598145f, 0.613770f, 0.629395f, + 0.645020f, 0.659668f, 0.675781f, 0.689941f, 0.705566f, 0.719727f, 0.734375f, 0.749512f, 0.763184f, 0.776855f, 0.791016f, 0.804688f, + 0.818848f, 0.832031f, 0.845215f, 0.858398f, 0.872559f, 0.884766f, 0.897949f, 0.909668f, 0.922852f, 0.936035f, 0.950684f, 0.919434f, + 0.896973f, 0.878906f, 0.862793f, 0.848633f, 0.008339f, 0.025543f, 0.043427f, 0.060974f, 0.078979f, 0.097168f, 0.115051f, 0.133179f, + 0.151367f, 0.169678f, 0.187988f, 0.206055f, 0.223999f, 0.241821f, 0.260742f, 0.277832f, 0.295166f, 0.313232f, 0.331299f, 0.347412f, + 0.365479f, 0.383057f, 0.399902f, 0.416992f, 0.433350f, 0.450195f, 0.467773f, 0.484863f, 0.499756f, 0.515625f, 0.532715f, 0.548340f, + 0.564941f, 0.580566f, 0.596191f, 0.610840f, 0.626953f, 0.641602f, 0.656738f, 0.671875f, 0.686035f, 0.701660f, 0.714844f, 0.730469f, + 0.745117f, 0.759766f, 0.772461f, 0.786621f, 0.801270f, 0.814453f, 0.827637f, 0.841309f, 0.854004f, 0.867676f, 0.880859f, 0.893555f, + 0.907227f, 0.919434f, 0.943359f, 0.913086f, 0.891602f, 0.874512f, 0.858887f, 0.845703f, 0.008102f, 0.024002f, 0.040802f, 0.057098f, + 0.074768f, 0.091553f, 0.108826f, 0.126343f, 0.143921f, 0.161377f, 0.179077f, 0.195923f, 0.213745f, 0.230835f, 0.248047f, 0.265869f, + 0.282227f, 0.299561f, 0.316895f, 0.334473f, 0.350586f, 0.367920f, 0.384277f, 0.400391f, 0.417725f, 0.434326f, 0.450195f, 0.467285f, + 0.482910f, 0.498291f, 0.514648f, 0.530762f, 0.546387f, 0.561523f, 0.577637f, 0.593262f, 0.608398f, 0.623535f, 0.637695f, 0.654297f, + 0.668457f, 0.682617f, 0.698242f, 0.711914f, 0.727051f, 0.741211f, 0.754395f, 0.768066f, 0.782715f, 0.796387f, 0.810547f, 0.823730f, + 0.836426f, 0.849609f, 0.863770f, 0.876465f, 0.889648f, 0.902344f, 0.934570f, 0.907715f, 0.887207f, 0.870117f, 0.854980f, 0.842285f, + 0.007504f, 0.022812f, 0.038727f, 0.054871f, 0.070312f, 0.087097f, 0.103088f, 0.119446f, 0.136475f, 0.153442f, 0.169556f, 0.186523f, + 0.203369f, 0.219971f, 0.236450f, 0.253418f, 0.270264f, 0.287109f, 0.302979f, 0.319824f, 0.336182f, 0.353271f, 0.369141f, 0.386230f, + 0.402100f, 0.417725f, 0.433594f, 0.450684f, 0.466553f, 0.482178f, 0.498047f, 0.513184f, 0.528809f, 0.543945f, 0.559082f, 0.575195f, + 0.589844f, 0.605469f, 0.621094f, 0.634277f, 0.649414f, 0.665039f, 0.679688f, 0.694824f, 0.708496f, 0.722168f, 0.736816f, 0.750000f, + 0.763184f, 0.778809f, 0.791504f, 0.805664f, 0.819336f, 0.832520f, 0.845703f, 0.858887f, 0.872070f, 0.885742f, 0.927246f, 0.900879f, + 0.881836f, 0.864746f, 0.851074f, 0.838867f, 0.006836f, 0.021683f, 0.036224f, 0.051666f, 0.066772f, 0.081970f, 0.098022f, 0.113831f, + 0.129517f, 0.145264f, 0.161011f, 0.177856f, 0.193359f, 0.209106f, 0.226196f, 0.241821f, 0.257812f, 0.274414f, 0.290283f, 0.306641f, + 0.322754f, 0.338623f, 0.354492f, 0.370361f, 0.386230f, 0.402100f, 0.417725f, 0.433838f, 0.449463f, 0.465088f, 0.480469f, 0.495605f, + 0.511719f, 0.527344f, 0.541016f, 0.556641f, 0.571777f, 0.587402f, 0.601562f, 0.617676f, 0.631836f, 0.646484f, 0.660645f, 0.674805f, + 0.689941f, 0.704102f, 0.718262f, 0.731934f, 0.746582f, 0.760254f, 0.774414f, 0.786621f, 0.801758f, 0.815430f, 0.828125f, 0.842285f, + 0.854980f, 0.868652f, 0.918457f, 0.894531f, 0.875977f, 0.859863f, 0.846680f, 0.834961f, 0.006672f, 0.020401f, 0.034088f, 0.048462f, + 0.062927f, 0.077820f, 0.092529f, 0.107666f, 0.122803f, 0.137695f, 0.152954f, 0.169067f, 0.183716f, 0.199829f, 0.214722f, 0.230347f, + 0.246704f, 0.262207f, 0.277832f, 0.292969f, 0.308105f, 0.324219f, 0.339600f, 0.354492f, 0.371094f, 0.386963f, 0.401855f, 0.418457f, + 0.432861f, 0.449219f, 0.463379f, 0.478271f, 0.494385f, 0.508301f, 0.523438f, 0.539551f, 0.553711f, 0.568848f, 0.583984f, 0.598633f, + 0.612793f, 0.627441f, 0.642578f, 0.656250f, 0.670898f, 0.685547f, 0.698730f, 0.714355f, 0.728027f, 0.742188f, 0.755859f, 0.769531f, + 0.783691f, 0.795898f, 0.810059f, 0.824707f, 0.838379f, 0.850586f, 0.910645f, 0.887695f, 0.870117f, 0.854980f, 0.842285f, 0.831055f, + 0.006207f, 0.019211f, 0.032623f, 0.046112f, 0.059662f, 0.073181f, 0.087585f, 0.102051f, 0.116577f, 0.130249f, 0.145142f, 0.159790f, + 0.175171f, 0.189575f, 0.205322f, 0.219238f, 0.235474f, 0.249634f, 0.265137f, 0.280029f, 0.294678f, 0.310547f, 0.325928f, 0.340820f, + 0.356201f, 0.371094f, 0.386230f, 0.401367f, 0.416504f, 0.431885f, 0.446533f, 0.461670f, 0.476074f, 0.492188f, 0.507324f, 0.520996f, + 0.535645f, 0.550781f, 0.564941f, 0.580078f, 0.594727f, 0.609863f, 0.623535f, 0.637695f, 0.652832f, 0.667480f, 0.681152f, 0.695312f, + 0.709473f, 0.723633f, 0.737793f, 0.751953f, 0.765137f, 0.779297f, 0.793945f, 0.807129f, 0.819824f, 0.833496f, 0.901855f, 0.880859f, + 0.864258f, 0.850098f, 0.837891f, 0.826660f, 0.006020f, 0.018219f, 0.030579f, 0.043365f, 0.055908f, 0.069153f, 0.082336f, 0.096802f, + 0.109497f, 0.123535f, 0.137451f, 0.151855f, 0.165649f, 0.180054f, 0.194702f, 0.208252f, 0.223999f, 0.238037f, 0.252930f, 0.267334f, + 0.281982f, 0.296875f, 0.312012f, 0.326904f, 0.340820f, 0.355957f, 0.370850f, 0.385986f, 0.400391f, 0.415039f, 0.430176f, 0.445801f, + 0.459229f, 0.474365f, 0.489014f, 0.502441f, 0.518066f, 0.533203f, 0.547363f, 0.562012f, 0.576660f, 0.590820f, 0.605469f, 0.619629f, + 0.633789f, 0.647949f, 0.663574f, 0.676758f, 0.690918f, 0.705566f, 0.719238f, 0.733398f, 0.746582f, 0.760254f, 0.774414f, 0.788574f, + 0.802246f, 0.816406f, 0.894043f, 0.874023f, 0.858398f, 0.844238f, 0.832031f, 0.822266f, 0.005520f, 0.017059f, 0.028625f, 0.040649f, + 0.053131f, 0.065552f, 0.077698f, 0.091187f, 0.104065f, 0.117371f, 0.130859f, 0.143677f, 0.157349f, 0.171021f, 0.184814f, 0.198730f, + 0.213135f, 0.226807f, 0.241211f, 0.255127f, 0.269775f, 0.283691f, 0.298096f, 0.312744f, 0.326660f, 0.341553f, 0.355957f, 0.370117f, + 0.384766f, 0.399170f, 0.414307f, 0.427979f, 0.442627f, 0.457764f, 0.471924f, 0.486084f, 0.500488f, 0.515137f, 0.529785f, 0.543945f, + 0.558594f, 0.572754f, 0.587402f, 0.601074f, 0.615234f, 0.629395f, 0.644043f, 0.657715f, 0.672852f, 0.685547f, 0.700684f, 0.714844f, + 0.728027f, 0.743164f, 0.756348f, 0.770508f, 0.785645f, 0.798340f, 0.885254f, 0.867676f, 0.852051f, 0.839355f, 0.828125f, 0.817871f, + 0.005241f, 0.015854f, 0.027481f, 0.038605f, 0.050171f, 0.061859f, 0.073853f, 0.085693f, 0.098328f, 0.111206f, 0.123474f, 0.136475f, + 0.149658f, 0.162598f, 0.175293f, 0.188477f, 0.202148f, 0.216431f, 0.229858f, 0.242798f, 0.256104f, 0.270264f, 0.284668f, 0.298828f, + 0.312744f, 0.326904f, 0.341064f, 0.355469f, 0.369141f, 0.383057f, 0.396729f, 0.411621f, 0.426025f, 0.439697f, 0.454590f, 0.468506f, + 0.482666f, 0.497070f, 0.512207f, 0.525391f, 0.540527f, 0.555176f, 0.567871f, 0.582031f, 0.596191f, 0.610840f, 0.625488f, 0.639648f, + 0.653809f, 0.668457f, 0.681641f, 0.695801f, 0.710449f, 0.724121f, 0.738770f, 0.751953f, 0.766602f, 0.780273f, 0.876465f, 0.860352f, + 0.845703f, 0.833984f, 0.822754f, 0.812988f, 0.004982f, 0.015274f, 0.025681f, 0.036438f, 0.047119f, 0.058167f, 0.069397f, 0.081055f, + 0.092957f, 0.104492f, 0.116577f, 0.128418f, 0.141113f, 0.153442f, 0.166504f, 0.179321f, 0.192261f, 0.205200f, 0.218506f, 0.231934f, + 0.244629f, 0.258301f, 0.271729f, 0.284912f, 0.299072f, 0.312988f, 0.325684f, 0.340088f, 0.353271f, 0.367676f, 0.381836f, 0.395508f, + 0.408936f, 0.423584f, 0.438232f, 0.451416f, 0.466309f, 0.479736f, 0.493896f, 0.507812f, 0.521973f, 0.536133f, 0.550293f, 0.563965f, + 0.578613f, 0.592773f, 0.606934f, 0.620605f, 0.635254f, 0.649414f, 0.663086f, 0.677246f, 0.691406f, 0.706543f, 0.720703f, 0.734375f, + 0.748047f, 0.762695f, 0.868164f, 0.853027f, 0.839355f, 0.828125f, 0.817383f, 0.808105f, 0.004745f, 0.014290f, 0.024506f, 0.034393f, + 0.044617f, 0.054749f, 0.065308f, 0.076538f, 0.087646f, 0.098938f, 0.110535f, 0.121582f, 0.134155f, 0.145264f, 0.157837f, 0.170166f, + 0.182373f, 0.194824f, 0.207153f, 0.220337f, 0.233276f, 0.245728f, 0.259277f, 0.271973f, 0.285645f, 0.298584f, 0.311768f, 0.325684f, + 0.338623f, 0.352539f, 0.365967f, 0.379395f, 0.393066f, 0.406738f, 0.421143f, 0.434326f, 0.448730f, 0.462402f, 0.475586f, 0.490479f, + 0.503906f, 0.518066f, 0.532227f, 0.546387f, 0.560059f, 0.574219f, 0.588379f, 0.602539f, 0.616211f, 0.630371f, 0.644531f, 0.658691f, + 0.673340f, 0.686523f, 0.701660f, 0.715332f, 0.730469f, 0.745117f, 0.858887f, 0.845215f, 0.833008f, 0.821777f, 0.812012f, 0.802734f, + 0.004494f, 0.013550f, 0.022675f, 0.032227f, 0.042145f, 0.052002f, 0.061554f, 0.072205f, 0.082520f, 0.093323f, 0.104614f, 0.115112f, + 0.126099f, 0.137817f, 0.149536f, 0.160767f, 0.172607f, 0.184692f, 0.196167f, 0.208862f, 0.221924f, 0.233765f, 0.246216f, 0.258545f, + 0.272461f, 0.284424f, 0.297119f, 0.310547f, 0.323242f, 0.336914f, 0.350586f, 0.363281f, 0.376953f, 0.390869f, 0.403564f, 0.416992f, + 0.431152f, 0.444824f, 0.458496f, 0.472656f, 0.486084f, 0.500000f, 0.513672f, 0.527832f, 0.541504f, 0.555664f, 0.569824f, 0.583496f, + 0.598145f, 0.611816f, 0.626465f, 0.639648f, 0.654297f, 0.668457f, 0.683594f, 0.697754f, 0.711914f, 0.726562f, 0.849609f, 0.838867f, + 0.826172f, 0.815918f, 0.806641f, 0.796875f, 0.004288f, 0.012619f, 0.021713f, 0.030945f, 0.039368f, 0.048737f, 0.058533f, 0.067932f, + 0.077759f, 0.088013f, 0.098755f, 0.108398f, 0.119080f, 0.129639f, 0.141235f, 0.152466f, 0.163940f, 0.174927f, 0.186768f, 0.198608f, + 0.210205f, 0.222290f, 0.234131f, 0.246094f, 0.258789f, 0.270508f, 0.283203f, 0.296631f, 0.309326f, 0.321777f, 0.335449f, 0.348145f, + 0.361084f, 0.374023f, 0.386963f, 0.400391f, 0.414062f, 0.427734f, 0.441162f, 0.455078f, 0.467773f, 0.482422f, 0.495117f, 0.509277f, + 0.523926f, 0.536621f, 0.550781f, 0.564941f, 0.579102f, 0.593262f, 0.607422f, 0.621582f, 0.635742f, 0.649902f, 0.664551f, 0.678711f, + 0.693848f, 0.708008f, 0.840820f, 0.831055f, 0.819336f, 0.809570f, 0.801270f, 0.792969f, 0.004013f, 0.012070f, 0.019989f, 0.029190f, + 0.037415f, 0.045776f, 0.055023f, 0.064392f, 0.073669f, 0.083374f, 0.092224f, 0.102295f, 0.112610f, 0.122742f, 0.133057f, 0.143799f, + 0.155273f, 0.165527f, 0.176880f, 0.188110f, 0.199463f, 0.210815f, 0.222534f, 0.234619f, 0.245972f, 0.258301f, 0.270508f, 0.282715f, + 0.294678f, 0.307129f, 0.320557f, 0.333008f, 0.345947f, 0.358398f, 0.371826f, 0.384277f, 0.397461f, 0.410889f, 0.424561f, 0.437256f, + 0.451416f, 0.464600f, 0.477783f, 0.491455f, 0.504395f, 0.518555f, 0.532715f, 0.546875f, 0.560547f, 0.574219f, 0.588379f, 0.604004f, + 0.617188f, 0.631348f, 0.645020f, 0.660645f, 0.674316f, 0.689941f, 0.832031f, 0.823242f, 0.813477f, 0.803711f, 0.794922f, 0.787109f, + 0.003790f, 0.011559f, 0.019119f, 0.027069f, 0.035034f, 0.043762f, 0.052032f, 0.060059f, 0.069153f, 0.078369f, 0.087280f, 0.096741f, + 0.105957f, 0.115967f, 0.125732f, 0.135620f, 0.146118f, 0.156128f, 0.166992f, 0.177612f, 0.188965f, 0.199829f, 0.210815f, 0.222290f, + 0.233887f, 0.244873f, 0.257324f, 0.268799f, 0.281006f, 0.292969f, 0.305420f, 0.317627f, 0.329834f, 0.341797f, 0.355469f, 0.368164f, + 0.380859f, 0.393311f, 0.407227f, 0.419434f, 0.433350f, 0.446533f, 0.459961f, 0.473633f, 0.486328f, 0.500488f, 0.515625f, 0.528320f, + 0.541504f, 0.556152f, 0.570312f, 0.584473f, 0.598633f, 0.612305f, 0.626465f, 0.640625f, 0.655762f, 0.670410f, 0.822266f, 0.815918f, + 0.805664f, 0.796387f, 0.788574f, 0.782227f, 0.003599f, 0.010727f, 0.018219f, 0.025177f, 0.033203f, 0.041046f, 0.048981f, 0.057220f, + 0.065247f, 0.073792f, 0.082764f, 0.091064f, 0.100220f, 0.108826f, 0.118591f, 0.128052f, 0.137573f, 0.147705f, 0.158081f, 0.167603f, + 0.177979f, 0.188721f, 0.198975f, 0.210205f, 0.221924f, 0.232544f, 0.243774f, 0.255615f, 0.267090f, 0.278564f, 0.290039f, 0.302490f, + 0.314941f, 0.327393f, 0.338623f, 0.352295f, 0.364014f, 0.377441f, 0.390381f, 0.403564f, 0.415039f, 0.428955f, 0.441895f, 0.455078f, + 0.468994f, 0.482666f, 0.496094f, 0.509277f, 0.523926f, 0.537598f, 0.551270f, 0.565430f, 0.579590f, 0.594238f, 0.608887f, 0.622559f, + 0.637207f, 0.651855f, 0.813477f, 0.807617f, 0.798340f, 0.790527f, 0.782715f, 0.775391f, 0.003355f, 0.009918f, 0.017105f, 0.023911f, + 0.031281f, 0.038147f, 0.045990f, 0.053284f, 0.061493f, 0.069214f, 0.077026f, 0.085571f, 0.093567f, 0.102600f, 0.111755f, 0.120728f, + 0.129761f, 0.138916f, 0.148804f, 0.158447f, 0.167725f, 0.177979f, 0.188965f, 0.198608f, 0.209473f, 0.220215f, 0.231567f, 0.242554f, + 0.253906f, 0.264160f, 0.276123f, 0.287109f, 0.300049f, 0.312012f, 0.323975f, 0.336182f, 0.348145f, 0.360840f, 0.372803f, 0.385986f, + 0.398438f, 0.411621f, 0.424316f, 0.437256f, 0.450439f, 0.464844f, 0.478027f, 0.490723f, 0.504395f, 0.518066f, 0.532715f, 0.546387f, + 0.561523f, 0.575684f, 0.589355f, 0.604004f, 0.618164f, 0.632324f, 0.802246f, 0.800293f, 0.792480f, 0.783691f, 0.776367f, 0.769531f, + 0.003265f, 0.009575f, 0.016144f, 0.022415f, 0.029510f, 0.036316f, 0.042755f, 0.050812f, 0.057556f, 0.065002f, 0.072388f, 0.080200f, + 0.087952f, 0.096680f, 0.104858f, 0.113281f, 0.122070f, 0.130493f, 0.139771f, 0.148926f, 0.158447f, 0.168335f, 0.177612f, 0.187500f, + 0.198120f, 0.208130f, 0.218750f, 0.229492f, 0.240234f, 0.250732f, 0.262207f, 0.273682f, 0.285156f, 0.296143f, 0.308594f, 0.320068f, + 0.332520f, 0.344482f, 0.357178f, 0.368652f, 0.381836f, 0.394043f, 0.406494f, 0.420410f, 0.433105f, 0.445801f, 0.459717f, 0.473633f, + 0.486816f, 0.500000f, 0.513672f, 0.527832f, 0.541992f, 0.556152f, 0.570312f, 0.585449f, 0.598633f, 0.613770f, 0.794434f, 0.791504f, + 0.784180f, 0.776855f, 0.770020f, 0.764160f, 0.002954f, 0.008904f, 0.014961f, 0.021210f, 0.027420f, 0.033905f, 0.040619f, 0.047363f, + 0.053986f, 0.060883f, 0.068054f, 0.075378f, 0.082703f, 0.090515f, 0.098022f, 0.105896f, 0.114319f, 0.122742f, 0.131592f, 0.139771f, + 0.149170f, 0.157959f, 0.167480f, 0.177124f, 0.186768f, 0.196411f, 0.206543f, 0.216919f, 0.227539f, 0.237671f, 0.248413f, 0.259277f, + 0.270264f, 0.281738f, 0.292725f, 0.304443f, 0.315918f, 0.327637f, 0.340576f, 0.352539f, 0.364746f, 0.377930f, 0.390137f, 0.401855f, + 0.415039f, 0.428223f, 0.441406f, 0.454834f, 0.468506f, 0.481689f, 0.494873f, 0.509277f, 0.523438f, 0.537598f, 0.551758f, 0.565918f, + 0.580078f, 0.594727f, 0.783691f, 0.783203f, 0.776855f, 0.770508f, 0.763672f, 0.757324f, 0.002836f, 0.008659f, 0.014351f, 0.019913f, + 0.025772f, 0.032074f, 0.037933f, 0.044128f, 0.050903f, 0.057159f, 0.064026f, 0.070496f, 0.077698f, 0.085022f, 0.091919f, 0.099426f, + 0.107727f, 0.114990f, 0.123169f, 0.131226f, 0.140015f, 0.148682f, 0.157349f, 0.166260f, 0.175171f, 0.184692f, 0.194214f, 0.203979f, + 0.214355f, 0.224487f, 0.234985f, 0.245728f, 0.256104f, 0.267334f, 0.278320f, 0.288818f, 0.301025f, 0.312256f, 0.324219f, 0.335938f, + 0.347900f, 0.360596f, 0.372070f, 0.384521f, 0.397217f, 0.410400f, 0.423340f, 0.436279f, 0.449463f, 0.463135f, 0.476807f, 0.490723f, + 0.503906f, 0.517578f, 0.532227f, 0.546875f, 0.561035f, 0.575684f, 0.773926f, 0.775391f, 0.769043f, 0.763672f, 0.757812f, 0.751953f, + 0.002506f, 0.008080f, 0.013100f, 0.018738f, 0.024384f, 0.029953f, 0.035797f, 0.041473f, 0.047485f, 0.053558f, 0.059265f, 0.065918f, + 0.072693f, 0.079468f, 0.086426f, 0.093384f, 0.100708f, 0.108032f, 0.115417f, 0.122986f, 0.130615f, 0.139038f, 0.147827f, 0.156494f, + 0.165039f, 0.173828f, 0.182617f, 0.192139f, 0.201782f, 0.211426f, 0.221558f, 0.231323f, 0.242188f, 0.252686f, 0.263672f, 0.274414f, + 0.284912f, 0.296143f, 0.308105f, 0.319824f, 0.331543f, 0.343750f, 0.355225f, 0.367432f, 0.379883f, 0.393066f, 0.405273f, 0.418457f, + 0.431641f, 0.444580f, 0.457764f, 0.471924f, 0.485840f, 0.499268f, 0.512695f, 0.527344f, 0.542480f, 0.556641f, 0.764160f, 0.766602f, + 0.761719f, 0.756348f, 0.750488f, 0.745605f, 0.002640f, 0.007809f, 0.012497f, 0.017593f, 0.023102f, 0.028122f, 0.033569f, 0.038879f, + 0.044250f, 0.049988f, 0.055908f, 0.061615f, 0.067627f, 0.074036f, 0.080566f, 0.087524f, 0.093262f, 0.100769f, 0.107910f, 0.114929f, + 0.121948f, 0.130371f, 0.137939f, 0.146362f, 0.154297f, 0.163208f, 0.171509f, 0.180664f, 0.189697f, 0.199341f, 0.208618f, 0.218506f, + 0.228394f, 0.238892f, 0.248779f, 0.259277f, 0.270752f, 0.281250f, 0.292236f, 0.303467f, 0.315186f, 0.326660f, 0.338867f, 0.351074f, + 0.362305f, 0.374756f, 0.387939f, 0.400146f, 0.413330f, 0.426514f, 0.439209f, 0.452881f, 0.466553f, 0.480225f, 0.494141f, 0.508301f, + 0.522949f, 0.537109f, 0.753906f, 0.758301f, 0.754395f, 0.749023f, 0.743652f, 0.739258f, 0.002441f, 0.007088f, 0.011993f, 0.016266f, + 0.021255f, 0.026031f, 0.031189f, 0.036072f, 0.041260f, 0.046753f, 0.052155f, 0.057587f, 0.063232f, 0.068787f, 0.075623f, 0.081055f, + 0.087341f, 0.094177f, 0.100647f, 0.106689f, 0.113892f, 0.121399f, 0.129028f, 0.136841f, 0.144287f, 0.152222f, 0.160522f, 0.169312f, + 0.178101f, 0.186523f, 0.196045f, 0.205200f, 0.214966f, 0.224487f, 0.234863f, 0.244751f, 0.255371f, 0.265625f, 0.276367f, 0.287842f, + 0.298828f, 0.310303f, 0.321533f, 0.333984f, 0.345459f, 0.357666f, 0.370117f, 0.382568f, 0.394287f, 0.407959f, 0.421875f, 0.433838f, + 0.446777f, 0.461426f, 0.475098f, 0.488525f, 0.504395f, 0.517578f, 0.744141f, 0.749512f, 0.746094f, 0.741699f, 0.736816f, 0.732422f, + 0.002172f, 0.006695f, 0.011093f, 0.015266f, 0.020081f, 0.024521f, 0.029388f, 0.033966f, 0.038727f, 0.043427f, 0.048706f, 0.053772f, + 0.059418f, 0.064270f, 0.069580f, 0.075500f, 0.081421f, 0.087280f, 0.093262f, 0.099670f, 0.106567f, 0.113220f, 0.119995f, 0.127197f, + 0.134644f, 0.142212f, 0.150146f, 0.157959f, 0.166382f, 0.174927f, 0.184082f, 0.192505f, 0.201904f, 0.211792f, 0.220825f, 0.230713f, + 0.240601f, 0.251221f, 0.261719f, 0.272461f, 0.282715f, 0.294434f, 0.305420f, 0.316650f, 0.328369f, 0.340088f, 0.352783f, 0.364746f, + 0.377197f, 0.389648f, 0.402832f, 0.416016f, 0.429443f, 0.442627f, 0.456055f, 0.469971f, 0.484863f, 0.499268f, 0.733887f, 0.741211f, + 0.737793f, 0.734375f, 0.729980f, 0.725586f, 0.002045f, 0.006187f, 0.010406f, 0.014664f, 0.018570f, 0.022675f, 0.027176f, 0.031586f, + 0.035858f, 0.040253f, 0.045227f, 0.049774f, 0.054504f, 0.059692f, 0.065186f, 0.070374f, 0.075500f, 0.080627f, 0.086792f, 0.092285f, + 0.098999f, 0.104675f, 0.111816f, 0.118286f, 0.125610f, 0.132324f, 0.139771f, 0.147339f, 0.155029f, 0.163696f, 0.171631f, 0.180420f, + 0.189087f, 0.197754f, 0.207275f, 0.216309f, 0.226440f, 0.236694f, 0.246338f, 0.256836f, 0.267334f, 0.278320f, 0.289062f, 0.300537f, + 0.312012f, 0.323975f, 0.335449f, 0.347168f, 0.359375f, 0.372314f, 0.384521f, 0.396973f, 0.410400f, 0.423584f, 0.437500f, 0.450928f, + 0.465332f, 0.479736f, 0.723145f, 0.732422f, 0.729980f, 0.726562f, 0.722656f, 0.718750f, 0.002148f, 0.005802f, 0.009811f, 0.013565f, + 0.017578f, 0.021179f, 0.025040f, 0.029053f, 0.033417f, 0.037445f, 0.042114f, 0.046112f, 0.050720f, 0.055511f, 0.060028f, 0.065002f, + 0.069458f, 0.075134f, 0.080078f, 0.085693f, 0.091492f, 0.097290f, 0.103394f, 0.109802f, 0.116089f, 0.122925f, 0.129883f, 0.136963f, + 0.144165f, 0.151733f, 0.160156f, 0.167847f, 0.176392f, 0.184692f, 0.193848f, 0.203003f, 0.212402f, 0.221680f, 0.231689f, 0.242065f, + 0.251953f, 0.262207f, 0.273193f, 0.283936f, 0.295410f, 0.306152f, 0.318359f, 0.329590f, 0.342285f, 0.354248f, 0.366455f, 0.379150f, + 0.391846f, 0.405273f, 0.418701f, 0.432617f, 0.446289f, 0.460205f, 0.712891f, 0.723633f, 0.722168f, 0.718750f, 0.715332f, 0.712402f, + 0.001963f, 0.005642f, 0.009071f, 0.012756f, 0.016006f, 0.020020f, 0.023422f, 0.027679f, 0.030762f, 0.034943f, 0.038605f, 0.042969f, + 0.047028f, 0.051178f, 0.055542f, 0.060120f, 0.064575f, 0.069153f, 0.074280f, 0.079041f, 0.084595f, 0.089905f, 0.095276f, 0.101440f, + 0.107300f, 0.113586f, 0.119751f, 0.127075f, 0.134033f, 0.141357f, 0.148438f, 0.155884f, 0.164062f, 0.172729f, 0.180542f, 0.190063f, + 0.198364f, 0.207764f, 0.217163f, 0.226807f, 0.236938f, 0.247070f, 0.257324f, 0.268066f, 0.278320f, 0.289795f, 0.301025f, 0.312744f, + 0.324707f, 0.336182f, 0.347900f, 0.360840f, 0.372803f, 0.386230f, 0.399902f, 0.413574f, 0.427246f, 0.441162f, 0.702148f, 0.714355f, + 0.713867f, 0.711426f, 0.707520f, 0.704590f, 0.001995f, 0.005245f, 0.008553f, 0.011543f, 0.015015f, 0.018326f, 0.021881f, 0.025131f, + 0.028641f, 0.032349f, 0.035675f, 0.039520f, 0.043549f, 0.047089f, 0.051086f, 0.054962f, 0.059265f, 0.063782f, 0.068054f, 0.072571f, + 0.077759f, 0.082520f, 0.088013f, 0.093323f, 0.098755f, 0.104858f, 0.111145f, 0.117371f, 0.123840f, 0.130615f, 0.137207f, 0.144897f, + 0.152344f, 0.160278f, 0.167969f, 0.176514f, 0.185425f, 0.193848f, 0.202881f, 0.212524f, 0.221924f, 0.231323f, 0.241821f, 0.251953f, + 0.262451f, 0.272949f, 0.284424f, 0.295166f, 0.306396f, 0.319092f, 0.329590f, 0.343018f, 0.355225f, 0.368652f, 0.381348f, 0.393799f, + 0.408447f, 0.422852f, 0.691406f, 0.706055f, 0.706055f, 0.703125f, 0.700684f, 0.697754f, 0.001692f, 0.004898f, 0.007828f, 0.011070f, + 0.013992f, 0.017227f, 0.020187f, 0.023499f, 0.026520f, 0.029526f, 0.033081f, 0.036377f, 0.039459f, 0.043396f, 0.047028f, 0.050323f, + 0.054199f, 0.058350f, 0.062317f, 0.066711f, 0.071106f, 0.075928f, 0.080750f, 0.085510f, 0.090820f, 0.096497f, 0.102234f, 0.107727f, + 0.114075f, 0.120300f, 0.126587f, 0.133789f, 0.141113f, 0.148193f, 0.156006f, 0.163696f, 0.171753f, 0.180542f, 0.188965f, 0.198120f, + 0.207275f, 0.216797f, 0.226318f, 0.236206f, 0.246338f, 0.256836f, 0.267334f, 0.278809f, 0.289795f, 0.300781f, 0.313232f, 0.324707f, + 0.337402f, 0.349365f, 0.362305f, 0.376221f, 0.389404f, 0.403809f, 0.680176f, 0.696289f, 0.697266f, 0.695312f, 0.692871f, 0.689941f, + 0.001606f, 0.004543f, 0.007450f, 0.010269f, 0.012962f, 0.015900f, 0.018677f, 0.021591f, 0.024628f, 0.027618f, 0.030182f, 0.033783f, + 0.036194f, 0.039734f, 0.042725f, 0.046478f, 0.049652f, 0.053253f, 0.057251f, 0.060883f, 0.065186f, 0.069336f, 0.073730f, 0.078247f, + 0.083252f, 0.088501f, 0.093628f, 0.099182f, 0.104553f, 0.110718f, 0.116577f, 0.123108f, 0.129883f, 0.136719f, 0.143921f, 0.151367f, + 0.159302f, 0.167114f, 0.175415f, 0.183960f, 0.192871f, 0.202148f, 0.210938f, 0.221436f, 0.230713f, 0.240723f, 0.250977f, 0.261963f, + 0.272461f, 0.283691f, 0.295166f, 0.306885f, 0.319092f, 0.331055f, 0.343750f, 0.356689f, 0.370361f, 0.383545f, 0.669434f, 0.687500f, + 0.688965f, 0.687500f, 0.685547f, 0.682617f, 0.001701f, 0.004345f, 0.006802f, 0.009514f, 0.012283f, 0.014793f, 0.017288f, 0.019958f, + 0.022614f, 0.025177f, 0.027695f, 0.030487f, 0.033081f, 0.035858f, 0.039185f, 0.042236f, 0.045319f, 0.048523f, 0.051941f, 0.055847f, + 0.059326f, 0.063171f, 0.067139f, 0.071594f, 0.075928f, 0.080566f, 0.085571f, 0.090454f, 0.095520f, 0.101196f, 0.106567f, 0.112427f, + 0.119019f, 0.125610f, 0.132324f, 0.139282f, 0.146973f, 0.154419f, 0.161987f, 0.170532f, 0.178833f, 0.187134f, 0.196777f, 0.206177f, + 0.214966f, 0.225220f, 0.235352f, 0.246094f, 0.255615f, 0.266846f, 0.278320f, 0.290039f, 0.301270f, 0.313477f, 0.325195f, 0.338867f, + 0.352539f, 0.365234f, 0.657715f, 0.678711f, 0.679688f, 0.679199f, 0.677734f, 0.675293f, 0.001310f, 0.003979f, 0.006393f, 0.008522f, + 0.011223f, 0.013557f, 0.015976f, 0.018433f, 0.020737f, 0.022842f, 0.025421f, 0.027649f, 0.030289f, 0.032806f, 0.035645f, 0.038025f, + 0.041199f, 0.044220f, 0.047058f, 0.050720f, 0.053589f, 0.057281f, 0.061157f, 0.064941f, 0.068787f, 0.072998f, 0.077698f, 0.082153f, + 0.086975f, 0.092102f, 0.097229f, 0.103027f, 0.108826f, 0.114746f, 0.121094f, 0.127930f, 0.134521f, 0.141846f, 0.149292f, 0.157227f, + 0.164673f, 0.173218f, 0.182007f, 0.190552f, 0.199951f, 0.209717f, 0.219360f, 0.229004f, 0.239502f, 0.250244f, 0.260986f, 0.272461f, + 0.282959f, 0.295166f, 0.307373f, 0.320557f, 0.333252f, 0.346436f, 0.646973f, 0.668945f, 0.670898f, 0.671387f, 0.669922f, 0.668457f, + 0.001348f, 0.003523f, 0.005863f, 0.008133f, 0.010338f, 0.012520f, 0.014511f, 0.016464f, 0.018768f, 0.020920f, 0.022888f, 0.025665f, + 0.027588f, 0.029861f, 0.032135f, 0.034485f, 0.037140f, 0.040039f, 0.042725f, 0.045532f, 0.048859f, 0.051971f, 0.055237f, 0.058594f, + 0.062408f, 0.066101f, 0.070251f, 0.074280f, 0.078735f, 0.083435f, 0.088318f, 0.093567f, 0.098633f, 0.104431f, 0.110291f, 0.116455f, + 0.122986f, 0.129517f, 0.136963f, 0.143921f, 0.152222f, 0.159546f, 0.167358f, 0.176514f, 0.185181f, 0.194214f, 0.203857f, 0.213623f, + 0.223389f, 0.233521f, 0.244385f, 0.255127f, 0.266602f, 0.277832f, 0.289307f, 0.301758f, 0.314697f, 0.328613f, 0.635254f, 0.659668f, + 0.663086f, 0.663086f, 0.662109f, 0.660156f, 0.001084f, 0.003263f, 0.005554f, 0.007416f, 0.009445f, 0.011185f, 0.013161f, 0.015366f, + 0.017136f, 0.019058f, 0.020935f, 0.022781f, 0.024857f, 0.026886f, 0.029160f, 0.031097f, 0.033569f, 0.035858f, 0.038361f, 0.040924f, + 0.043427f, 0.046478f, 0.049500f, 0.052948f, 0.056122f, 0.059418f, 0.063293f, 0.067139f, 0.070923f, 0.075073f, 0.079712f, 0.084229f, + 0.089233f, 0.094604f, 0.100037f, 0.105774f, 0.111694f, 0.117798f, 0.124634f, 0.131226f, 0.139038f, 0.146484f, 0.154175f, 0.162231f, + 0.170654f, 0.179199f, 0.188599f, 0.197754f, 0.207153f, 0.217407f, 0.227295f, 0.238159f, 0.248657f, 0.260986f, 0.271973f, 0.284912f, + 0.296631f, 0.308838f, 0.623535f, 0.650391f, 0.653809f, 0.654297f, 0.653809f, 0.652832f, 0.001070f, 0.003069f, 0.005108f, 0.006855f, + 0.008522f, 0.010384f, 0.011993f, 0.013847f, 0.015549f, 0.016968f, 0.018677f, 0.020660f, 0.022079f, 0.024048f, 0.026077f, 0.027954f, + 0.030014f, 0.032135f, 0.034210f, 0.036560f, 0.038971f, 0.041840f, 0.044434f, 0.047089f, 0.049896f, 0.053284f, 0.056763f, 0.060120f, + 0.063477f, 0.067505f, 0.071533f, 0.075928f, 0.080261f, 0.085205f, 0.089905f, 0.095520f, 0.100830f, 0.106567f, 0.113159f, 0.119385f, + 0.126221f, 0.133301f, 0.140259f, 0.148560f, 0.156494f, 0.165039f, 0.173462f, 0.182861f, 0.192017f, 0.201172f, 0.211548f, 0.221802f, + 0.232666f, 0.243286f, 0.254639f, 0.265869f, 0.278809f, 0.291260f, 0.611816f, 0.640625f, 0.645508f, 0.645996f, 0.645508f, 0.645020f, + 0.001057f, 0.002815f, 0.004646f, 0.006187f, 0.007935f, 0.009583f, 0.011139f, 0.012428f, 0.013878f, 0.015404f, 0.016830f, 0.018433f, + 0.019836f, 0.021637f, 0.023300f, 0.024857f, 0.026855f, 0.028519f, 0.030533f, 0.032593f, 0.034790f, 0.037140f, 0.039520f, 0.041748f, + 0.044525f, 0.047302f, 0.050232f, 0.053497f, 0.056580f, 0.059998f, 0.063721f, 0.067627f, 0.071777f, 0.076111f, 0.080627f, 0.085571f, + 0.090698f, 0.096130f, 0.101624f, 0.107849f, 0.114258f, 0.120544f, 0.127686f, 0.135132f, 0.142700f, 0.150269f, 0.158813f, 0.167725f, + 0.176392f, 0.185791f, 0.195312f, 0.205444f, 0.216064f, 0.226562f, 0.237793f, 0.248657f, 0.260254f, 0.272949f, 0.600098f, 0.631348f, + 0.636230f, 0.637207f, 0.637695f, 0.636719f, 0.001022f, 0.002628f, 0.004486f, 0.005684f, 0.007179f, 0.008636f, 0.009911f, 0.011307f, + 0.012428f, 0.013771f, 0.015152f, 0.016342f, 0.017822f, 0.018997f, 0.020584f, 0.022263f, 0.023651f, 0.025482f, 0.027191f, 0.028793f, + 0.030960f, 0.032715f, 0.034912f, 0.036987f, 0.039368f, 0.041840f, 0.044495f, 0.047180f, 0.050110f, 0.053314f, 0.056580f, 0.060059f, + 0.063660f, 0.067383f, 0.071777f, 0.075928f, 0.081055f, 0.085938f, 0.091187f, 0.096619f, 0.102356f, 0.108826f, 0.115051f, 0.121948f, + 0.129150f, 0.136475f, 0.144653f, 0.152832f, 0.161621f, 0.170288f, 0.179932f, 0.189209f, 0.198730f, 0.209595f, 0.220459f, 0.231201f, + 0.242798f, 0.255615f, 0.588867f, 0.621094f, 0.626953f, 0.629883f, 0.629395f, 0.629883f, 0.001016f, 0.002304f, 0.003975f, 0.005024f, + 0.006584f, 0.007812f, 0.008926f, 0.009987f, 0.011024f, 0.012199f, 0.013321f, 0.014595f, 0.015617f, 0.016830f, 0.018326f, 0.019577f, + 0.020798f, 0.022293f, 0.023758f, 0.025253f, 0.027145f, 0.028656f, 0.030640f, 0.032501f, 0.034546f, 0.036682f, 0.039001f, 0.041412f, + 0.044037f, 0.046875f, 0.049622f, 0.052917f, 0.056030f, 0.059387f, 0.063354f, 0.067383f, 0.071655f, 0.075928f, 0.080750f, 0.085876f, + 0.091248f, 0.097168f, 0.102905f, 0.109497f, 0.116272f, 0.123413f, 0.130859f, 0.138550f, 0.147217f, 0.155518f, 0.164551f, 0.173828f, + 0.183350f, 0.193481f, 0.204102f, 0.214600f, 0.225342f, 0.237915f, 0.575684f, 0.611816f, 0.617188f, 0.621094f, 0.621582f, 0.620605f, + 0.000768f, 0.002398f, 0.003801f, 0.004875f, 0.005848f, 0.006889f, 0.008072f, 0.008820f, 0.009758f, 0.010910f, 0.011810f, 0.013023f, + 0.013878f, 0.014786f, 0.016083f, 0.017166f, 0.018402f, 0.019577f, 0.020691f, 0.022125f, 0.023743f, 0.025009f, 0.026779f, 0.028336f, + 0.030075f, 0.031921f, 0.033997f, 0.036255f, 0.038452f, 0.040833f, 0.043488f, 0.045959f, 0.049011f, 0.052216f, 0.055634f, 0.059052f, + 0.062744f, 0.066956f, 0.071289f, 0.075745f, 0.080566f, 0.086060f, 0.091614f, 0.097351f, 0.103821f, 0.110291f, 0.117432f, 0.124939f, + 0.132568f, 0.140869f, 0.149414f, 0.158325f, 0.168213f, 0.177368f, 0.187744f, 0.197876f, 0.208984f, 0.219849f, 0.563965f, 0.602051f, + 0.608887f, 0.610840f, 0.613770f, 0.612305f, 0.000764f, 0.002028f, 0.003302f, 0.004276f, 0.005325f, 0.006035f, 0.007034f, 0.007843f, + 0.008904f, 0.009628f, 0.010323f, 0.011192f, 0.012039f, 0.013092f, 0.013924f, 0.014854f, 0.015793f, 0.016953f, 0.018036f, 0.019211f, + 0.020355f, 0.021667f, 0.023010f, 0.024582f, 0.026016f, 0.027771f, 0.029434f, 0.031235f, 0.033264f, 0.035217f, 0.037628f, 0.039886f, + 0.042084f, 0.044952f, 0.048126f, 0.051392f, 0.054779f, 0.058197f, 0.062164f, 0.066223f, 0.070740f, 0.075439f, 0.080566f, 0.086182f, + 0.091919f, 0.098145f, 0.104431f, 0.111633f, 0.119080f, 0.126587f, 0.134888f, 0.143311f, 0.152710f, 0.162109f, 0.171631f, 0.182129f, + 0.192139f, 0.203491f, 0.552246f, 0.591309f, 0.599609f, 0.602539f, 0.604004f, 0.604980f, 0.000782f, 0.001970f, 0.003082f, 0.003859f, + 0.004635f, 0.005611f, 0.006123f, 0.006767f, 0.007595f, 0.008270f, 0.009140f, 0.009674f, 0.010490f, 0.011040f, 0.011902f, 0.012749f, + 0.013573f, 0.014526f, 0.015656f, 0.016541f, 0.017548f, 0.018631f, 0.019730f, 0.021103f, 0.022446f, 0.023758f, 0.025162f, 0.026611f, + 0.028458f, 0.030441f, 0.032074f, 0.034302f, 0.036316f, 0.038727f, 0.041138f, 0.044098f, 0.046997f, 0.050232f, 0.053711f, 0.057281f, + 0.061340f, 0.065491f, 0.070435f, 0.075256f, 0.080688f, 0.086426f, 0.092346f, 0.098694f, 0.105896f, 0.113098f, 0.120911f, 0.129028f, + 0.137695f, 0.146606f, 0.155884f, 0.165894f, 0.175903f, 0.186768f, 0.540527f, 0.582520f, 0.590332f, 0.593750f, 0.594727f, 0.596191f, + 0.000711f, 0.001649f, 0.002529f, 0.003332f, 0.004036f, 0.004799f, 0.005444f, 0.006050f, 0.006638f, 0.007160f, 0.007771f, 0.008331f, + 0.008980f, 0.009644f, 0.010307f, 0.010887f, 0.011787f, 0.012306f, 0.013176f, 0.014099f, 0.014915f, 0.015839f, 0.016708f, 0.017822f, + 0.019073f, 0.020233f, 0.021423f, 0.022690f, 0.024033f, 0.025589f, 0.027344f, 0.028976f, 0.030930f, 0.032990f, 0.035156f, 0.037445f, + 0.040131f, 0.042847f, 0.045776f, 0.049042f, 0.052551f, 0.056519f, 0.060486f, 0.064941f, 0.069458f, 0.074951f, 0.080444f, 0.086487f, + 0.092957f, 0.099915f, 0.107361f, 0.114929f, 0.123535f, 0.131714f, 0.140747f, 0.150513f, 0.160767f, 0.171265f, 0.527832f, 0.572754f, + 0.581543f, 0.583496f, 0.586426f, 0.587402f, 0.000504f, 0.001575f, 0.002235f, 0.003147f, 0.003641f, 0.004150f, 0.004570f, 0.005173f, + 0.005863f, 0.006016f, 0.006462f, 0.007111f, 0.007660f, 0.008156f, 0.008736f, 0.009354f, 0.010094f, 0.010475f, 0.011253f, 0.011879f, + 0.012657f, 0.013603f, 0.014267f, 0.015099f, 0.016144f, 0.017014f, 0.017990f, 0.019104f, 0.020416f, 0.021652f, 0.022919f, 0.024353f, + 0.025986f, 0.027710f, 0.029602f, 0.031494f, 0.033722f, 0.036102f, 0.038635f, 0.041412f, 0.044525f, 0.047729f, 0.051636f, 0.055511f, + 0.059540f, 0.064331f, 0.069580f, 0.075073f, 0.080750f, 0.087341f, 0.094116f, 0.101379f, 0.109558f, 0.117676f, 0.126221f, 0.135376f, + 0.145874f, 0.155518f, 0.516113f, 0.562012f, 0.571777f, 0.576172f, 0.578125f, 0.579102f, 0.000445f, 0.001304f, 0.002201f, 0.002535f, + 0.003126f, 0.003664f, 0.004047f, 0.004463f, 0.004887f, 0.005234f, 0.005711f, 0.005997f, 0.006500f, 0.006901f, 0.007389f, 0.007904f, + 0.008293f, 0.008919f, 0.009499f, 0.009941f, 0.010635f, 0.011269f, 0.011948f, 0.012589f, 0.013435f, 0.014252f, 0.015091f, 0.016052f, + 0.017059f, 0.017960f, 0.019241f, 0.020264f, 0.021667f, 0.022995f, 0.024628f, 0.026230f, 0.027985f, 0.029984f, 0.032288f, 0.034515f, + 0.037140f, 0.040009f, 0.043152f, 0.046722f, 0.050354f, 0.054504f, 0.059143f, 0.064026f, 0.069458f, 0.075256f, 0.081726f, 0.088562f, + 0.095825f, 0.103516f, 0.112000f, 0.120850f, 0.130005f, 0.140381f, 0.502441f, 0.551758f, 0.562012f, 0.566406f, 0.568848f, 0.571289f, + 0.000396f, 0.001226f, 0.001812f, 0.002357f, 0.002796f, 0.003094f, 0.003328f, 0.003763f, 0.003979f, 0.004364f, 0.004642f, 0.005051f, + 0.005489f, 0.005745f, 0.006126f, 0.006611f, 0.007004f, 0.007473f, 0.007771f, 0.008293f, 0.008919f, 0.009392f, 0.009941f, 0.010483f, + 0.011169f, 0.011765f, 0.012436f, 0.013344f, 0.014030f, 0.014908f, 0.015778f, 0.016769f, 0.017838f, 0.018997f, 0.020279f, 0.021622f, + 0.023056f, 0.024704f, 0.026474f, 0.028580f, 0.030579f, 0.033051f, 0.035706f, 0.038605f, 0.041840f, 0.045380f, 0.049500f, 0.053986f, + 0.058685f, 0.063843f, 0.069885f, 0.076050f, 0.083191f, 0.090576f, 0.098511f, 0.107056f, 0.115479f, 0.125122f, 0.491211f, 0.541504f, + 0.552734f, 0.557617f, 0.560547f, 0.562012f, 0.000559f, 0.001152f, 0.001668f, 0.001955f, 0.002234f, 0.002550f, 0.002821f, 0.003057f, + 0.003296f, 0.003635f, 0.003948f, 0.004189f, 0.004448f, 0.004761f, 0.005077f, 0.005417f, 0.005699f, 0.006142f, 0.006458f, 0.006844f, + 0.007271f, 0.007717f, 0.008156f, 0.008675f, 0.009132f, 0.009590f, 0.010277f, 0.010864f, 0.011482f, 0.012131f, 0.012901f, 0.013741f, + 0.014595f, 0.015549f, 0.016525f, 0.017563f, 0.018799f, 0.020111f, 0.021484f, 0.023087f, 0.024765f, 0.026840f, 0.028992f, 0.031403f, + 0.034119f, 0.037323f, 0.040680f, 0.044464f, 0.048584f, 0.053345f, 0.058838f, 0.064514f, 0.071045f, 0.078247f, 0.085571f, 0.093567f, + 0.101685f, 0.111023f, 0.477539f, 0.531738f, 0.542969f, 0.548340f, 0.552246f, 0.553711f, 0.000459f, 0.000939f, 0.001184f, 0.001600f, + 0.001761f, 0.002144f, 0.002258f, 0.002546f, 0.002708f, 0.002922f, 0.003157f, 0.003414f, 0.003588f, 0.003918f, 0.004154f, 0.004387f, + 0.004662f, 0.004993f, 0.005249f, 0.005566f, 0.005867f, 0.006252f, 0.006573f, 0.007061f, 0.007408f, 0.007858f, 0.008270f, 0.008713f, + 0.009361f, 0.009911f, 0.010513f, 0.011047f, 0.011841f, 0.012566f, 0.013252f, 0.014175f, 0.015182f, 0.016220f, 0.017258f, 0.018524f, + 0.019882f, 0.021454f, 0.023132f, 0.025146f, 0.027405f, 0.029877f, 0.032745f, 0.035919f, 0.039642f, 0.043823f, 0.048492f, 0.053619f, + 0.059235f, 0.065735f, 0.072693f, 0.080383f, 0.088867f, 0.097412f, 0.466309f, 0.520508f, 0.533691f, 0.539062f, 0.542480f, 0.543945f, + 0.000369f, 0.000915f, 0.001124f, 0.001297f, 0.001534f, 0.001741f, 0.001833f, 0.002111f, 0.002272f, 0.002369f, 0.002516f, 0.002766f, + 0.002920f, 0.003162f, 0.003317f, 0.003551f, 0.003723f, 0.003941f, 0.004211f, 0.004425f, 0.004757f, 0.004993f, 0.005306f, 0.005581f, + 0.005859f, 0.006203f, 0.006592f, 0.007015f, 0.007450f, 0.007828f, 0.008377f, 0.008797f, 0.009361f, 0.009895f, 0.010582f, 0.011322f, + 0.012016f, 0.012772f, 0.013687f, 0.014748f, 0.015778f, 0.016907f, 0.018326f, 0.019821f, 0.021622f, 0.023483f, 0.025742f, 0.028473f, + 0.031525f, 0.034943f, 0.038910f, 0.043457f, 0.048645f, 0.054749f, 0.061279f, 0.068420f, 0.076111f, 0.084778f, 0.453613f, 0.510742f, + 0.523926f, 0.529785f, 0.533203f, 0.536133f, 0.000186f, 0.000582f, 0.000925f, 0.001026f, 0.001228f, 0.001351f, 0.001470f, 0.001606f, + 0.001765f, 0.001908f, 0.001999f, 0.002104f, 0.002281f, 0.002476f, 0.002659f, 0.002766f, 0.002911f, 0.003040f, 0.003344f, 0.003475f, + 0.003683f, 0.003922f, 0.004185f, 0.004417f, 0.004673f, 0.004890f, 0.005123f, 0.005440f, 0.005817f, 0.006126f, 0.006481f, 0.006859f, + 0.007275f, 0.007740f, 0.008202f, 0.008728f, 0.009315f, 0.009972f, 0.010597f, 0.011391f, 0.012268f, 0.013252f, 0.014221f, 0.015388f, + 0.016724f, 0.018265f, 0.020004f, 0.022049f, 0.024445f, 0.027206f, 0.030762f, 0.034424f, 0.038971f, 0.044220f, 0.050262f, 0.056976f, + 0.064575f, 0.072083f, 0.441650f, 0.500488f, 0.514160f, 0.520020f, 0.524414f, 0.526855f, 0.000194f, 0.000467f, 0.000775f, 0.000911f, + 0.000994f, 0.001081f, 0.001221f, 0.001204f, 0.001368f, 0.001479f, 0.001582f, 0.001707f, 0.001801f, 0.001921f, 0.001993f, 0.002146f, + 0.002245f, 0.002398f, 0.002531f, 0.002674f, 0.002871f, 0.003033f, 0.003172f, 0.003374f, 0.003519f, 0.003742f, 0.003963f, 0.004158f, + 0.004448f, 0.004650f, 0.005032f, 0.005230f, 0.005550f, 0.005932f, 0.006241f, 0.006634f, 0.007088f, 0.007572f, 0.008110f, 0.008636f, + 0.009323f, 0.010071f, 0.010834f, 0.011757f, 0.012779f, 0.013863f, 0.015190f, 0.016769f, 0.018555f, 0.020706f, 0.023331f, 0.026352f, + 0.030182f, 0.034760f, 0.040039f, 0.046356f, 0.053406f, 0.060638f, 0.427979f, 0.489502f, 0.504883f, 0.511719f, 0.515137f, 0.518066f, + 0.000339f, 0.000388f, 0.000559f, 0.000617f, 0.000667f, 0.000795f, 0.000853f, 0.000938f, 0.000972f, 0.001079f, 0.001217f, 0.001274f, + 0.001369f, 0.001480f, 0.001536f, 0.001581f, 0.001711f, 0.001804f, 0.001900f, 0.002047f, 0.002129f, 0.002245f, 0.002394f, 0.002493f, + 0.002645f, 0.002773f, 0.002974f, 0.003124f, 0.003307f, 0.003559f, 0.003757f, 0.003893f, 0.004169f, 0.004353f, 0.004684f, 0.004963f, + 0.005272f, 0.005615f, 0.005981f, 0.006420f, 0.006878f, 0.007378f, 0.008080f, 0.008682f, 0.009438f, 0.010239f, 0.011299f, 0.012459f, + 0.013809f, 0.015305f, 0.017212f, 0.019501f, 0.022583f, 0.026245f, 0.030838f, 0.036255f, 0.042938f, 0.049988f, 0.416504f, 0.479492f, + 0.495361f, 0.501465f, 0.505859f, 0.508789f, 0.000148f, 0.000349f, 0.000414f, 0.000480f, 0.000554f, 0.000575f, 0.000675f, 0.000641f, + 0.000743f, 0.000809f, 0.000882f, 0.000919f, 0.000967f, 0.001019f, 0.001122f, 0.001156f, 0.001264f, 0.001322f, 0.001392f, 0.001431f, + 0.001529f, 0.001625f, 0.001735f, 0.001802f, 0.001912f, 0.002007f, 0.002131f, 0.002237f, 0.002338f, 0.002525f, 0.002638f, 0.002850f, + 0.002962f, 0.003130f, 0.003347f, 0.003536f, 0.003784f, 0.004063f, 0.004364f, 0.004623f, 0.004929f, 0.005314f, 0.005714f, 0.006191f, + 0.006760f, 0.007385f, 0.008080f, 0.008919f, 0.009933f, 0.011078f, 0.012390f, 0.014130f, 0.016251f, 0.019012f, 0.022720f, 0.027496f, + 0.033234f, 0.040192f, 0.403320f, 0.468994f, 0.485352f, 0.491943f, 0.497070f, 0.500000f, 0.000093f, 0.000191f, 0.000299f, 0.000284f, + 0.000367f, 0.000453f, 0.000420f, 0.000467f, 0.000519f, 0.000611f, 0.000607f, 0.000626f, 0.000647f, 0.000722f, 0.000741f, 0.000815f, + 0.000829f, 0.000910f, 0.000967f, 0.001023f, 0.001076f, 0.001138f, 0.001197f, 0.001260f, 0.001334f, 0.001393f, 0.001490f, 0.001562f, + 0.001633f, 0.001772f, 0.001831f, 0.001949f, 0.002056f, 0.002167f, 0.002312f, 0.002472f, 0.002607f, 0.002781f, 0.002972f, 0.003145f, + 0.003387f, 0.003647f, 0.003941f, 0.004253f, 0.004604f, 0.005051f, 0.005558f, 0.006165f, 0.006836f, 0.007660f, 0.008652f, 0.009796f, + 0.011284f, 0.013260f, 0.015945f, 0.019608f, 0.024734f, 0.031082f, 0.390625f, 0.459229f, 0.475586f, 0.482910f, 0.488037f, 0.490723f, + 0.000132f, 0.000208f, 0.000217f, 0.000221f, 0.000267f, 0.000272f, 0.000277f, 0.000320f, 0.000356f, 0.000372f, 0.000372f, 0.000446f, + 0.000436f, 0.000487f, 0.000514f, 0.000531f, 0.000587f, 0.000601f, 0.000629f, 0.000658f, 0.000707f, 0.000736f, 0.000784f, 0.000816f, + 0.000880f, 0.000909f, 0.000978f, 0.001035f, 0.001084f, 0.001135f, 0.001200f, 0.001278f, 0.001357f, 0.001429f, 0.001516f, 0.001588f, + 0.001724f, 0.001802f, 0.001949f, 0.002085f, 0.002230f, 0.002373f, 0.002554f, 0.002743f, 0.003000f, 0.003300f, 0.003611f, 0.003963f, + 0.004425f, 0.004967f, 0.005630f, 0.006424f, 0.007462f, 0.008812f, 0.010551f, 0.013184f, 0.017258f, 0.022980f, 0.377686f, 0.448242f, + 0.465820f, 0.474121f, 0.478760f, 0.481934f, 0.000041f, 0.000149f, 0.000126f, 0.000128f, 0.000158f, 0.000196f, 0.000174f, 0.000206f, + 0.000216f, 0.000223f, 0.000231f, 0.000244f, 0.000276f, 0.000291f, 0.000312f, 0.000326f, 0.000338f, 0.000374f, 0.000387f, 0.000423f, + 0.000430f, 0.000447f, 0.000471f, 0.000509f, 0.000538f, 0.000583f, 0.000591f, 0.000613f, 0.000659f, 0.000688f, 0.000743f, 0.000779f, + 0.000833f, 0.000865f, 0.000924f, 0.000966f, 0.001033f, 0.001106f, 0.001186f, 0.001245f, 0.001336f, 0.001453f, 0.001559f, 0.001685f, + 0.001807f, 0.001980f, 0.002207f, 0.002417f, 0.002689f, 0.003027f, 0.003418f, 0.003933f, 0.004604f, 0.005482f, 0.006641f, 0.008263f, + 0.011017f, 0.015778f, 0.364746f, 0.437256f, 0.456055f, 0.463623f, 0.469238f, 0.472656f, 0.000100f, 0.000089f, 0.000085f, 0.000081f, + 0.000101f, 0.000096f, 0.000116f, 0.000116f, 0.000119f, 0.000126f, 0.000141f, 0.000157f, 0.000149f, 0.000158f, 0.000179f, 0.000176f, + 0.000195f, 0.000206f, 0.000216f, 0.000222f, 0.000240f, 0.000246f, 0.000269f, 0.000279f, 0.000303f, 0.000320f, 0.000333f, 0.000345f, + 0.000365f, 0.000379f, 0.000409f, 0.000434f, 0.000453f, 0.000477f, 0.000511f, 0.000541f, 0.000569f, 0.000608f, 0.000656f, 0.000689f, + 0.000738f, 0.000795f, 0.000867f, 0.000918f, 0.001005f, 0.001087f, 0.001189f, 0.001312f, 0.001465f, 0.001656f, 0.001873f, 0.002171f, + 0.002546f, 0.003056f, 0.003767f, 0.004765f, 0.006390f, 0.009811f, 0.353516f, 0.426758f, 0.446045f, 0.455078f, 0.459717f, 0.464111f, + 0.000084f, 0.000059f, 0.000050f, 0.000049f, 0.000049f, 0.000047f, 0.000052f, 0.000058f, 0.000061f, 0.000075f, 0.000065f, 0.000066f, + 0.000080f, 0.000071f, 0.000076f, 0.000082f, 0.000092f, 0.000102f, 0.000100f, 0.000105f, 0.000110f, 0.000115f, 0.000121f, 0.000133f, + 0.000140f, 0.000146f, 0.000152f, 0.000164f, 0.000177f, 0.000185f, 0.000192f, 0.000202f, 0.000213f, 0.000224f, 0.000241f, 0.000252f, + 0.000268f, 0.000283f, 0.000310f, 0.000328f, 0.000348f, 0.000374f, 0.000406f, 0.000431f, 0.000470f, 0.000515f, 0.000560f, 0.000614f, + 0.000688f, 0.000771f, 0.000884f, 0.001019f, 0.001202f, 0.001466f, 0.001827f, 0.002369f, 0.003269f, 0.005184f, 0.341797f, 0.416016f, + 0.435791f, 0.445557f, 0.450928f, 0.455078f, 0.000062f, 0.000042f, 0.000035f, 0.000030f, 0.000028f, 0.000026f, 0.000024f, 0.000023f, + 0.000023f, 0.000023f, 0.000023f, 0.000030f, 0.000024f, 0.000024f, 0.000031f, 0.000034f, 0.000035f, 0.000037f, 0.000039f, 0.000040f, + 0.000043f, 0.000048f, 0.000050f, 0.000046f, 0.000051f, 0.000057f, 0.000059f, 0.000058f, 0.000063f, 0.000068f, 0.000070f, 0.000077f, + 0.000082f, 0.000082f, 0.000086f, 0.000093f, 0.000100f, 0.000106f, 0.000114f, 0.000120f, 0.000131f, 0.000136f, 0.000145f, 0.000161f, + 0.000171f, 0.000186f, 0.000204f, 0.000222f, 0.000251f, 0.000281f, 0.000318f, 0.000364f, 0.000430f, 0.000530f, 0.000672f, 0.000902f, + 0.001316f, 0.002153f, 0.329346f, 0.406006f, 0.426758f, 0.436035f, 0.441650f, 0.445801f, 0.000031f, 0.000020f, 0.000016f, 0.000014f, + 0.000014f, 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, + 0.000008f, 0.000008f, 0.000007f, 0.000007f, 0.000007f, 0.000008f, 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000012f, 0.000014f, + 0.000014f, 0.000013f, 0.000015f, 0.000016f, 0.000018f, 0.000019f, 0.000019f, 0.000020f, 0.000023f, 0.000023f, 0.000025f, 0.000027f, + 0.000028f, 0.000031f, 0.000034f, 0.000034f, 0.000037f, 0.000041f, 0.000045f, 0.000049f, 0.000053f, 0.000059f, 0.000066f, 0.000079f, + 0.000093f, 0.000112f, 0.000144f, 0.000196f, 0.000307f, 0.000598f, 0.317383f, 0.394531f, 0.416504f, 0.425781f, 0.432129f, 0.436279f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, + 0.000002f, 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000004f, 0.000007f, 0.000010f, 0.000026f, 0.305420f, 0.384277f, + 0.405762f, 0.416504f, 0.423340f, 0.427246f, + }, + { + 0.009338f, 0.028412f, 0.047394f, 0.066895f, 0.086548f, 0.105774f, 0.125854f, 0.145142f, 0.165039f, 0.184570f, 0.204712f, 0.223389f, + 0.243164f, 0.261719f, 0.280762f, 0.299805f, 0.318848f, 0.338135f, 0.356445f, 0.374512f, 0.393066f, 0.412354f, 0.429932f, 0.447510f, + 0.465576f, 0.483887f, 0.501465f, 0.518555f, 0.536133f, 0.553711f, 0.570312f, 0.587402f, 0.604492f, 0.621094f, 0.637695f, 0.653809f, + 0.670898f, 0.687012f, 0.702637f, 0.719238f, 0.734863f, 0.750488f, 0.765137f, 0.780762f, 0.795898f, 0.811523f, 0.825684f, 0.840820f, + 0.855469f, 0.870605f, 0.884277f, 0.899414f, 0.913086f, 0.926758f, 0.940918f, 0.955078f, 0.967773f, 0.981934f, 0.966797f, 0.923828f, + 0.894531f, 0.870605f, 0.850586f, 0.832520f, 0.008652f, 0.026825f, 0.045380f, 0.063965f, 0.082703f, 0.101807f, 0.120544f, 0.139282f, + 0.158569f, 0.177246f, 0.196167f, 0.214722f, 0.233521f, 0.252197f, 0.270508f, 0.289062f, 0.307861f, 0.325928f, 0.343994f, 0.361328f, + 0.380615f, 0.397705f, 0.415771f, 0.433594f, 0.450928f, 0.469238f, 0.485596f, 0.502930f, 0.520020f, 0.537598f, 0.553223f, 0.570801f, + 0.586914f, 0.603516f, 0.620117f, 0.636719f, 0.652832f, 0.668945f, 0.683594f, 0.700684f, 0.716309f, 0.731934f, 0.746582f, 0.762695f, + 0.777344f, 0.792480f, 0.807617f, 0.821777f, 0.836914f, 0.850586f, 0.865723f, 0.880371f, 0.894043f, 0.908691f, 0.921875f, 0.937012f, + 0.950195f, 0.963867f, 0.958496f, 0.917969f, 0.889648f, 0.867188f, 0.847656f, 0.830566f, 0.008293f, 0.025620f, 0.042999f, 0.061035f, + 0.079163f, 0.097656f, 0.115112f, 0.132812f, 0.151367f, 0.170532f, 0.188599f, 0.206787f, 0.223999f, 0.242920f, 0.259766f, 0.278809f, + 0.296143f, 0.313232f, 0.331055f, 0.349609f, 0.367432f, 0.385010f, 0.401611f, 0.418945f, 0.435791f, 0.453369f, 0.469727f, 0.487061f, + 0.503906f, 0.520508f, 0.537598f, 0.553223f, 0.569824f, 0.586426f, 0.603027f, 0.619141f, 0.634277f, 0.650879f, 0.666504f, 0.682129f, + 0.697754f, 0.713379f, 0.729004f, 0.743164f, 0.758301f, 0.773926f, 0.789062f, 0.803711f, 0.818359f, 0.833008f, 0.847168f, 0.862305f, + 0.875488f, 0.890137f, 0.903809f, 0.917480f, 0.931152f, 0.945801f, 0.950195f, 0.911133f, 0.884766f, 0.862793f, 0.844238f, 0.828125f, + 0.008148f, 0.024506f, 0.041016f, 0.058289f, 0.075256f, 0.092712f, 0.109802f, 0.127319f, 0.145020f, 0.162964f, 0.180298f, 0.198120f, + 0.215454f, 0.232300f, 0.250244f, 0.267822f, 0.285400f, 0.302734f, 0.318848f, 0.335693f, 0.354004f, 0.371582f, 0.388672f, 0.405029f, + 0.421143f, 0.438965f, 0.455078f, 0.472168f, 0.487549f, 0.503906f, 0.521484f, 0.537598f, 0.551758f, 0.568359f, 0.584961f, 0.601562f, + 0.616211f, 0.633301f, 0.648926f, 0.664062f, 0.679199f, 0.694824f, 0.709473f, 0.725098f, 0.740234f, 0.755371f, 0.770020f, 0.785156f, + 0.799805f, 0.813965f, 0.828125f, 0.842773f, 0.856934f, 0.871582f, 0.884766f, 0.898926f, 0.912598f, 0.926270f, 0.941895f, 0.905273f, + 0.879883f, 0.858887f, 0.840332f, 0.824707f, 0.007523f, 0.023010f, 0.039246f, 0.055542f, 0.072021f, 0.088257f, 0.105347f, 0.122070f, + 0.138306f, 0.155273f, 0.172852f, 0.189575f, 0.206421f, 0.223145f, 0.240112f, 0.256592f, 0.274170f, 0.291260f, 0.307617f, 0.323730f, + 0.340576f, 0.358154f, 0.374023f, 0.390137f, 0.406738f, 0.422852f, 0.440430f, 0.456543f, 0.472656f, 0.489014f, 0.504395f, 0.520996f, + 0.537109f, 0.552734f, 0.568848f, 0.584473f, 0.599121f, 0.615234f, 0.630859f, 0.645020f, 0.660645f, 0.677246f, 0.690918f, 0.706055f, + 0.721680f, 0.736328f, 0.750977f, 0.766113f, 0.780273f, 0.794922f, 0.809570f, 0.823730f, 0.837891f, 0.852539f, 0.866211f, 0.880371f, + 0.894531f, 0.908691f, 0.933105f, 0.898438f, 0.874023f, 0.853516f, 0.836426f, 0.821289f, 0.007339f, 0.021912f, 0.037170f, 0.052948f, + 0.068665f, 0.084412f, 0.100281f, 0.116333f, 0.133057f, 0.149048f, 0.164795f, 0.181274f, 0.198242f, 0.214233f, 0.230835f, 0.247314f, + 0.262939f, 0.279053f, 0.295898f, 0.312500f, 0.328613f, 0.344971f, 0.360107f, 0.376953f, 0.392578f, 0.408691f, 0.425293f, 0.441406f, + 0.456787f, 0.472656f, 0.488525f, 0.504883f, 0.520020f, 0.535156f, 0.550781f, 0.567383f, 0.582520f, 0.597656f, 0.612793f, 0.628418f, + 0.642578f, 0.657715f, 0.673340f, 0.688477f, 0.702637f, 0.718750f, 0.731445f, 0.748047f, 0.762207f, 0.775879f, 0.791016f, 0.804199f, + 0.818848f, 0.833008f, 0.847656f, 0.861328f, 0.875000f, 0.890625f, 0.924316f, 0.891602f, 0.868164f, 0.849121f, 0.832520f, 0.817871f, + 0.006817f, 0.021133f, 0.035675f, 0.050018f, 0.065186f, 0.080505f, 0.096069f, 0.111389f, 0.126831f, 0.142456f, 0.158203f, 0.174194f, + 0.189819f, 0.205444f, 0.220703f, 0.237183f, 0.253174f, 0.268555f, 0.284668f, 0.300049f, 0.316406f, 0.332275f, 0.347656f, 0.363281f, + 0.379395f, 0.394775f, 0.409668f, 0.426270f, 0.442139f, 0.457275f, 0.472656f, 0.488037f, 0.503906f, 0.518555f, 0.534668f, 0.548828f, + 0.564941f, 0.579590f, 0.595215f, 0.610352f, 0.625000f, 0.640137f, 0.654785f, 0.669434f, 0.685059f, 0.699707f, 0.713379f, 0.728027f, + 0.742676f, 0.758301f, 0.770996f, 0.786621f, 0.799316f, 0.813965f, 0.828613f, 0.842285f, 0.856445f, 0.871094f, 0.915527f, 0.884766f, + 0.862305f, 0.843750f, 0.827637f, 0.813965f, 0.006611f, 0.020111f, 0.033752f, 0.047974f, 0.062378f, 0.076843f, 0.091431f, 0.106262f, + 0.120911f, 0.136230f, 0.151123f, 0.166382f, 0.181396f, 0.196899f, 0.211670f, 0.227295f, 0.242554f, 0.257812f, 0.272705f, 0.288086f, + 0.304199f, 0.318848f, 0.334473f, 0.349609f, 0.365967f, 0.379883f, 0.395996f, 0.410889f, 0.426270f, 0.441895f, 0.457764f, 0.472412f, + 0.487061f, 0.502930f, 0.517090f, 0.532227f, 0.547363f, 0.563477f, 0.577637f, 0.592285f, 0.606934f, 0.621582f, 0.636230f, 0.651367f, + 0.665039f, 0.679688f, 0.694336f, 0.709473f, 0.724121f, 0.738770f, 0.752930f, 0.767578f, 0.780762f, 0.795410f, 0.809082f, 0.823242f, + 0.837891f, 0.852539f, 0.906250f, 0.877441f, 0.855957f, 0.838379f, 0.823242f, 0.809570f, 0.006153f, 0.019150f, 0.031952f, 0.045624f, + 0.059326f, 0.073303f, 0.087158f, 0.101562f, 0.115540f, 0.129395f, 0.144653f, 0.159180f, 0.173584f, 0.187866f, 0.203613f, 0.217651f, + 0.232300f, 0.247559f, 0.262207f, 0.277344f, 0.292969f, 0.307617f, 0.322021f, 0.336914f, 0.352051f, 0.367188f, 0.381592f, 0.396729f, + 0.411377f, 0.427002f, 0.440918f, 0.456787f, 0.471436f, 0.486572f, 0.500977f, 0.514648f, 0.530273f, 0.545410f, 0.560059f, 0.574219f, + 0.589355f, 0.604004f, 0.618164f, 0.632324f, 0.647461f, 0.661133f, 0.676270f, 0.691406f, 0.705078f, 0.719727f, 0.733887f, 0.748047f, + 0.763184f, 0.777344f, 0.791016f, 0.805176f, 0.819336f, 0.833496f, 0.896973f, 0.870117f, 0.849609f, 0.833008f, 0.818359f, 0.805176f, + 0.005947f, 0.018311f, 0.030731f, 0.043243f, 0.056732f, 0.069580f, 0.083435f, 0.096558f, 0.110474f, 0.123962f, 0.137695f, 0.152100f, + 0.166016f, 0.180054f, 0.194092f, 0.208862f, 0.222656f, 0.236816f, 0.251465f, 0.266113f, 0.281250f, 0.294922f, 0.309814f, 0.324219f, + 0.338623f, 0.352783f, 0.368164f, 0.382568f, 0.397461f, 0.411377f, 0.426025f, 0.441162f, 0.455078f, 0.469971f, 0.484131f, 0.499268f, + 0.513672f, 0.528320f, 0.542969f, 0.557129f, 0.571289f, 0.585449f, 0.599609f, 0.614258f, 0.628418f, 0.643066f, 0.657227f, 0.671875f, + 0.686523f, 0.700195f, 0.714355f, 0.729004f, 0.743164f, 0.756836f, 0.770996f, 0.785645f, 0.800293f, 0.814453f, 0.888184f, 0.862305f, + 0.843262f, 0.827148f, 0.813477f, 0.800781f, 0.005646f, 0.017136f, 0.029388f, 0.041534f, 0.053802f, 0.066162f, 0.078979f, 0.092285f, + 0.104980f, 0.118408f, 0.130981f, 0.144897f, 0.158203f, 0.172363f, 0.185547f, 0.199951f, 0.213501f, 0.226440f, 0.240356f, 0.254883f, + 0.269287f, 0.283691f, 0.297607f, 0.311279f, 0.325439f, 0.339600f, 0.353760f, 0.368408f, 0.382812f, 0.396973f, 0.410645f, 0.425049f, + 0.439697f, 0.454102f, 0.468262f, 0.482178f, 0.496094f, 0.510742f, 0.524902f, 0.539551f, 0.554199f, 0.568359f, 0.582031f, 0.596191f, + 0.610352f, 0.624023f, 0.639160f, 0.652832f, 0.667969f, 0.681152f, 0.696289f, 0.709961f, 0.723633f, 0.738770f, 0.752441f, 0.765625f, + 0.780273f, 0.794922f, 0.878418f, 0.855469f, 0.836914f, 0.821289f, 0.808105f, 0.796387f, 0.005478f, 0.016174f, 0.027740f, 0.038849f, + 0.051270f, 0.063293f, 0.075317f, 0.087402f, 0.099854f, 0.112793f, 0.125366f, 0.138184f, 0.151001f, 0.164307f, 0.177734f, 0.190918f, + 0.204102f, 0.217529f, 0.231079f, 0.244141f, 0.257324f, 0.271240f, 0.284668f, 0.299072f, 0.312744f, 0.326660f, 0.339600f, 0.354004f, + 0.368408f, 0.382324f, 0.395264f, 0.410156f, 0.423096f, 0.437500f, 0.452148f, 0.465332f, 0.480469f, 0.493408f, 0.507812f, 0.521484f, + 0.535645f, 0.549316f, 0.563477f, 0.578125f, 0.592285f, 0.605957f, 0.620605f, 0.634766f, 0.647949f, 0.662109f, 0.676758f, 0.691406f, + 0.705078f, 0.718750f, 0.732910f, 0.747559f, 0.762207f, 0.777344f, 0.869141f, 0.847656f, 0.830078f, 0.815430f, 0.802734f, 0.791504f, + 0.005005f, 0.015762f, 0.026657f, 0.037384f, 0.048218f, 0.059998f, 0.071594f, 0.083618f, 0.095215f, 0.107666f, 0.119141f, 0.131958f, + 0.144043f, 0.156128f, 0.169800f, 0.182129f, 0.194824f, 0.207031f, 0.219849f, 0.233032f, 0.247559f, 0.260010f, 0.272949f, 0.286133f, + 0.300293f, 0.313477f, 0.326172f, 0.339844f, 0.353516f, 0.367188f, 0.381592f, 0.394531f, 0.407959f, 0.422363f, 0.436279f, 0.449463f, + 0.462891f, 0.477539f, 0.490723f, 0.504395f, 0.518066f, 0.532227f, 0.545898f, 0.560059f, 0.574219f, 0.586914f, 0.602051f, 0.616211f, + 0.629395f, 0.644531f, 0.657227f, 0.671875f, 0.685547f, 0.699707f, 0.713867f, 0.728516f, 0.742676f, 0.756836f, 0.859375f, 0.840332f, + 0.823730f, 0.809082f, 0.797363f, 0.786621f, 0.004894f, 0.014786f, 0.025269f, 0.035614f, 0.045990f, 0.057129f, 0.068420f, 0.079224f, + 0.090698f, 0.102112f, 0.113708f, 0.125610f, 0.137817f, 0.149536f, 0.161377f, 0.174316f, 0.185791f, 0.198486f, 0.211670f, 0.223389f, + 0.236816f, 0.249512f, 0.261230f, 0.274414f, 0.287598f, 0.300537f, 0.313232f, 0.326904f, 0.340576f, 0.353027f, 0.366211f, 0.379883f, + 0.393066f, 0.406006f, 0.419678f, 0.433350f, 0.446289f, 0.460205f, 0.473633f, 0.487305f, 0.500977f, 0.515137f, 0.528320f, 0.542480f, + 0.554688f, 0.569824f, 0.583008f, 0.597656f, 0.610840f, 0.625488f, 0.638672f, 0.652832f, 0.666504f, 0.681152f, 0.694824f, 0.708984f, + 0.723145f, 0.737793f, 0.850098f, 0.833008f, 0.817383f, 0.802734f, 0.791992f, 0.780762f, 0.004536f, 0.014160f, 0.023972f, 0.033630f, + 0.043823f, 0.053955f, 0.064697f, 0.075195f, 0.086365f, 0.096802f, 0.108276f, 0.119751f, 0.130493f, 0.142212f, 0.153687f, 0.165405f, + 0.177246f, 0.189331f, 0.201538f, 0.213501f, 0.225464f, 0.237915f, 0.250244f, 0.262939f, 0.274902f, 0.288086f, 0.300781f, 0.312988f, + 0.326172f, 0.339600f, 0.352051f, 0.365479f, 0.377930f, 0.390625f, 0.403564f, 0.417480f, 0.430420f, 0.444092f, 0.457520f, 0.470215f, + 0.483643f, 0.497559f, 0.510742f, 0.524414f, 0.537598f, 0.551270f, 0.564941f, 0.579102f, 0.592285f, 0.605957f, 0.619629f, 0.633789f, + 0.647949f, 0.661621f, 0.675293f, 0.689453f, 0.704102f, 0.718262f, 0.840332f, 0.825195f, 0.809570f, 0.797363f, 0.786133f, 0.776367f, + 0.004433f, 0.013138f, 0.022720f, 0.032013f, 0.041199f, 0.051147f, 0.061462f, 0.071716f, 0.082336f, 0.091919f, 0.102722f, 0.113586f, + 0.124390f, 0.135010f, 0.145996f, 0.157837f, 0.168823f, 0.180054f, 0.192383f, 0.203491f, 0.215332f, 0.227417f, 0.239502f, 0.251221f, + 0.263672f, 0.275635f, 0.287842f, 0.300537f, 0.312500f, 0.324707f, 0.338135f, 0.350342f, 0.363037f, 0.375977f, 0.388672f, 0.401611f, + 0.413818f, 0.427246f, 0.440186f, 0.453613f, 0.466064f, 0.479736f, 0.492920f, 0.506836f, 0.519531f, 0.533203f, 0.546875f, 0.560059f, + 0.573242f, 0.587402f, 0.600098f, 0.614746f, 0.628418f, 0.642578f, 0.657227f, 0.670898f, 0.685059f, 0.699707f, 0.830566f, 0.816406f, + 0.802734f, 0.791016f, 0.780273f, 0.770996f, 0.004372f, 0.012619f, 0.021393f, 0.030350f, 0.039276f, 0.048523f, 0.058289f, 0.067505f, + 0.077393f, 0.087585f, 0.097290f, 0.107727f, 0.118225f, 0.128296f, 0.138550f, 0.149414f, 0.160278f, 0.171631f, 0.182739f, 0.193359f, + 0.205200f, 0.216187f, 0.228027f, 0.240234f, 0.251465f, 0.263428f, 0.275146f, 0.287598f, 0.298828f, 0.311523f, 0.323242f, 0.336182f, + 0.348633f, 0.360107f, 0.372803f, 0.385986f, 0.398682f, 0.411621f, 0.424072f, 0.436523f, 0.449951f, 0.462891f, 0.475098f, 0.488525f, + 0.501953f, 0.514648f, 0.527344f, 0.541992f, 0.555176f, 0.569336f, 0.582031f, 0.596191f, 0.609863f, 0.623047f, 0.637695f, 0.651855f, + 0.665527f, 0.679688f, 0.821289f, 0.808105f, 0.795410f, 0.784180f, 0.774902f, 0.765137f, 0.003937f, 0.012169f, 0.020477f, 0.028641f, + 0.037781f, 0.046448f, 0.055481f, 0.064209f, 0.073181f, 0.082458f, 0.092651f, 0.101990f, 0.111572f, 0.121948f, 0.132202f, 0.142212f, + 0.151978f, 0.162720f, 0.173340f, 0.184326f, 0.195312f, 0.206055f, 0.217163f, 0.228516f, 0.239990f, 0.250977f, 0.262695f, 0.274658f, + 0.285889f, 0.297363f, 0.308838f, 0.321045f, 0.333496f, 0.345459f, 0.357422f, 0.370117f, 0.382324f, 0.395020f, 0.407227f, 0.419922f, + 0.432617f, 0.444336f, 0.458008f, 0.470703f, 0.483398f, 0.497559f, 0.510254f, 0.522949f, 0.536133f, 0.550293f, 0.562988f, 0.577637f, + 0.590820f, 0.603516f, 0.618164f, 0.632324f, 0.645508f, 0.660645f, 0.811035f, 0.800293f, 0.788086f, 0.777832f, 0.768555f, 0.760254f, + 0.003868f, 0.011368f, 0.019257f, 0.027512f, 0.035431f, 0.043274f, 0.051880f, 0.060852f, 0.069214f, 0.078003f, 0.087524f, 0.096924f, + 0.105896f, 0.115112f, 0.124817f, 0.134766f, 0.144409f, 0.154663f, 0.164673f, 0.175415f, 0.184814f, 0.196289f, 0.206299f, 0.216797f, + 0.228394f, 0.239380f, 0.250244f, 0.260986f, 0.273193f, 0.284424f, 0.295410f, 0.307373f, 0.319092f, 0.331299f, 0.342285f, 0.354248f, + 0.366455f, 0.378662f, 0.390869f, 0.403809f, 0.415771f, 0.427734f, 0.440430f, 0.453369f, 0.466309f, 0.479736f, 0.492188f, 0.504883f, + 0.518066f, 0.531250f, 0.544922f, 0.558105f, 0.571777f, 0.584473f, 0.598633f, 0.612305f, 0.626465f, 0.641602f, 0.801758f, 0.792480f, + 0.781738f, 0.770508f, 0.761230f, 0.753906f, 0.003616f, 0.010872f, 0.018387f, 0.026077f, 0.033875f, 0.041351f, 0.049591f, 0.057434f, + 0.065674f, 0.073669f, 0.082153f, 0.091064f, 0.100098f, 0.109009f, 0.117981f, 0.127563f, 0.137207f, 0.146362f, 0.156494f, 0.165894f, + 0.176025f, 0.186157f, 0.196655f, 0.206421f, 0.216919f, 0.227539f, 0.237915f, 0.249268f, 0.260254f, 0.270752f, 0.282471f, 0.293945f, + 0.305176f, 0.316406f, 0.328125f, 0.338867f, 0.350342f, 0.361816f, 0.375244f, 0.387207f, 0.398926f, 0.411133f, 0.423584f, 0.436523f, + 0.448730f, 0.461182f, 0.474121f, 0.485840f, 0.499756f, 0.513672f, 0.525391f, 0.539062f, 0.552734f, 0.565918f, 0.580566f, 0.593750f, + 0.608398f, 0.621094f, 0.790527f, 0.783691f, 0.773926f, 0.764160f, 0.755859f, 0.747559f, 0.003450f, 0.010429f, 0.017487f, 0.024445f, + 0.031860f, 0.039581f, 0.046631f, 0.054718f, 0.061951f, 0.070251f, 0.078003f, 0.086121f, 0.094910f, 0.102905f, 0.111572f, 0.120300f, + 0.129761f, 0.138428f, 0.147217f, 0.156982f, 0.166992f, 0.176147f, 0.186157f, 0.196045f, 0.206299f, 0.216187f, 0.226318f, 0.236938f, + 0.247437f, 0.258301f, 0.268311f, 0.279785f, 0.290527f, 0.301758f, 0.312744f, 0.324219f, 0.335449f, 0.346680f, 0.359131f, 0.370605f, + 0.382812f, 0.394531f, 0.406982f, 0.419189f, 0.430908f, 0.443604f, 0.456055f, 0.468506f, 0.481445f, 0.494873f, 0.506836f, 0.520996f, + 0.534180f, 0.547363f, 0.561035f, 0.573730f, 0.588379f, 0.601074f, 0.780762f, 0.775879f, 0.766602f, 0.757324f, 0.748535f, 0.741699f, + 0.003281f, 0.009811f, 0.016174f, 0.023438f, 0.030060f, 0.037109f, 0.044464f, 0.051239f, 0.058441f, 0.066345f, 0.073792f, 0.081238f, + 0.089539f, 0.097229f, 0.105286f, 0.113647f, 0.122498f, 0.130615f, 0.139526f, 0.148438f, 0.157837f, 0.166626f, 0.176636f, 0.185547f, + 0.195312f, 0.204956f, 0.215088f, 0.224976f, 0.234863f, 0.245239f, 0.255859f, 0.266113f, 0.276367f, 0.287354f, 0.298096f, 0.309326f, + 0.320801f, 0.331787f, 0.343018f, 0.355225f, 0.366211f, 0.378418f, 0.389893f, 0.401611f, 0.413574f, 0.425781f, 0.438721f, 0.451416f, + 0.463135f, 0.476074f, 0.489014f, 0.501465f, 0.514648f, 0.528809f, 0.541992f, 0.554688f, 0.568848f, 0.582520f, 0.770508f, 0.767090f, + 0.758789f, 0.750488f, 0.743164f, 0.735352f, 0.002901f, 0.009422f, 0.015488f, 0.021729f, 0.028290f, 0.035278f, 0.041321f, 0.048523f, + 0.055420f, 0.062195f, 0.069336f, 0.076477f, 0.084412f, 0.091858f, 0.099609f, 0.107361f, 0.115112f, 0.123535f, 0.131592f, 0.140137f, + 0.148438f, 0.157715f, 0.166382f, 0.174927f, 0.184692f, 0.193970f, 0.203369f, 0.212646f, 0.222656f, 0.232910f, 0.242920f, 0.252197f, + 0.263184f, 0.273438f, 0.284180f, 0.294922f, 0.305664f, 0.316895f, 0.327881f, 0.338867f, 0.349854f, 0.361328f, 0.373291f, 0.385254f, + 0.397461f, 0.408691f, 0.420898f, 0.433350f, 0.445801f, 0.458252f, 0.470703f, 0.483154f, 0.496826f, 0.510254f, 0.522461f, 0.535645f, + 0.549805f, 0.562988f, 0.760742f, 0.758789f, 0.750488f, 0.743652f, 0.736328f, 0.729492f, 0.002861f, 0.008606f, 0.014488f, 0.021057f, + 0.026810f, 0.032898f, 0.038879f, 0.045532f, 0.051666f, 0.058319f, 0.065125f, 0.072449f, 0.079224f, 0.086426f, 0.093689f, 0.100830f, + 0.108276f, 0.116089f, 0.123962f, 0.131958f, 0.140625f, 0.148560f, 0.156494f, 0.164795f, 0.174194f, 0.183228f, 0.192017f, 0.201294f, + 0.210815f, 0.220093f, 0.229858f, 0.239746f, 0.249390f, 0.260010f, 0.270508f, 0.280518f, 0.290771f, 0.301758f, 0.312744f, 0.323486f, + 0.334473f, 0.345215f, 0.356934f, 0.368408f, 0.379883f, 0.391846f, 0.403564f, 0.416016f, 0.427490f, 0.439453f, 0.452881f, 0.465332f, + 0.478271f, 0.490234f, 0.503906f, 0.517090f, 0.529785f, 0.543945f, 0.750000f, 0.750000f, 0.743164f, 0.736328f, 0.729492f, 0.723145f, + 0.002977f, 0.008492f, 0.013931f, 0.019745f, 0.024948f, 0.030991f, 0.036804f, 0.042755f, 0.048889f, 0.055267f, 0.061737f, 0.067932f, + 0.074829f, 0.081116f, 0.087646f, 0.095215f, 0.102356f, 0.109436f, 0.116760f, 0.124023f, 0.131714f, 0.139648f, 0.147461f, 0.155762f, + 0.164185f, 0.172485f, 0.181152f, 0.189697f, 0.198730f, 0.208130f, 0.217285f, 0.226685f, 0.236572f, 0.245850f, 0.255859f, 0.265869f, + 0.276367f, 0.286377f, 0.297607f, 0.307861f, 0.318359f, 0.329102f, 0.340576f, 0.351807f, 0.363281f, 0.374023f, 0.386230f, 0.397949f, + 0.409668f, 0.422119f, 0.434082f, 0.446777f, 0.459229f, 0.471924f, 0.484863f, 0.497803f, 0.511230f, 0.525391f, 0.739746f, 0.741211f, + 0.735352f, 0.729004f, 0.722656f, 0.717285f, 0.002441f, 0.007896f, 0.013443f, 0.018402f, 0.023911f, 0.029343f, 0.034454f, 0.040375f, + 0.045868f, 0.051453f, 0.057800f, 0.063721f, 0.070068f, 0.075928f, 0.082520f, 0.089233f, 0.095703f, 0.102478f, 0.109314f, 0.116638f, + 0.123596f, 0.131348f, 0.138550f, 0.145996f, 0.153809f, 0.162109f, 0.170044f, 0.179199f, 0.187866f, 0.196045f, 0.205078f, 0.213745f, + 0.223389f, 0.233032f, 0.242554f, 0.252197f, 0.261963f, 0.271973f, 0.281982f, 0.292236f, 0.303223f, 0.312988f, 0.324463f, 0.335693f, + 0.346191f, 0.357910f, 0.368652f, 0.380371f, 0.391846f, 0.404541f, 0.415527f, 0.428467f, 0.440674f, 0.453369f, 0.466553f, 0.479248f, + 0.491455f, 0.505371f, 0.729492f, 0.732422f, 0.727539f, 0.721191f, 0.716309f, 0.709961f, 0.002457f, 0.007553f, 0.012489f, 0.017548f, + 0.022217f, 0.027405f, 0.032471f, 0.037689f, 0.043060f, 0.048553f, 0.054230f, 0.059631f, 0.065369f, 0.071533f, 0.077393f, 0.083069f, + 0.089417f, 0.096069f, 0.102356f, 0.108398f, 0.115417f, 0.122925f, 0.130127f, 0.137451f, 0.144531f, 0.152100f, 0.160156f, 0.168091f, + 0.176514f, 0.184570f, 0.192871f, 0.201660f, 0.210571f, 0.219238f, 0.229126f, 0.238281f, 0.248413f, 0.257812f, 0.267578f, 0.277588f, + 0.287354f, 0.298096f, 0.308594f, 0.319336f, 0.329590f, 0.340820f, 0.351318f, 0.363770f, 0.375732f, 0.386963f, 0.397949f, 0.409912f, + 0.422363f, 0.434326f, 0.446533f, 0.459473f, 0.473145f, 0.486084f, 0.718750f, 0.723633f, 0.719727f, 0.713867f, 0.708984f, 0.703613f, + 0.002436f, 0.006939f, 0.011612f, 0.016113f, 0.021072f, 0.025497f, 0.030640f, 0.035339f, 0.040222f, 0.045441f, 0.050690f, 0.055725f, + 0.060669f, 0.066589f, 0.072144f, 0.077881f, 0.083740f, 0.089294f, 0.095215f, 0.101501f, 0.108032f, 0.114868f, 0.121643f, 0.128052f, + 0.135010f, 0.142334f, 0.150024f, 0.157349f, 0.164917f, 0.173340f, 0.181274f, 0.189697f, 0.198120f, 0.206909f, 0.215698f, 0.224365f, + 0.234497f, 0.243652f, 0.252930f, 0.262695f, 0.272461f, 0.282471f, 0.292480f, 0.302979f, 0.313721f, 0.324463f, 0.335205f, 0.346436f, + 0.357666f, 0.369141f, 0.380859f, 0.391602f, 0.404541f, 0.416016f, 0.428467f, 0.440918f, 0.454102f, 0.466553f, 0.708496f, 0.715820f, + 0.711426f, 0.706055f, 0.701660f, 0.696777f, 0.002188f, 0.006599f, 0.011032f, 0.015068f, 0.019897f, 0.024048f, 0.028656f, 0.033264f, + 0.037720f, 0.042236f, 0.047028f, 0.051941f, 0.056824f, 0.062012f, 0.067444f, 0.072449f, 0.077942f, 0.083374f, 0.088867f, 0.094727f, + 0.100769f, 0.106750f, 0.112732f, 0.119263f, 0.126099f, 0.133179f, 0.139648f, 0.146729f, 0.154175f, 0.161987f, 0.170044f, 0.177612f, + 0.185791f, 0.194214f, 0.203125f, 0.211670f, 0.220581f, 0.229370f, 0.238770f, 0.248047f, 0.257812f, 0.267822f, 0.277344f, 0.287109f, + 0.297363f, 0.307861f, 0.318848f, 0.329590f, 0.341064f, 0.351562f, 0.363037f, 0.374512f, 0.385498f, 0.397461f, 0.409668f, 0.422363f, + 0.434326f, 0.447021f, 0.697266f, 0.706543f, 0.703125f, 0.698730f, 0.694336f, 0.689941f, 0.002024f, 0.006165f, 0.010399f, 0.014481f, + 0.018555f, 0.022797f, 0.026627f, 0.030869f, 0.035187f, 0.039459f, 0.043732f, 0.047943f, 0.052917f, 0.057434f, 0.062622f, 0.067261f, + 0.071838f, 0.077454f, 0.082581f, 0.087891f, 0.093628f, 0.099182f, 0.105469f, 0.111206f, 0.117126f, 0.123779f, 0.130371f, 0.137085f, + 0.143921f, 0.151001f, 0.158691f, 0.166016f, 0.173950f, 0.181641f, 0.190063f, 0.198120f, 0.206909f, 0.215698f, 0.224976f, 0.233398f, + 0.242798f, 0.252197f, 0.262207f, 0.271973f, 0.281738f, 0.291992f, 0.302734f, 0.313477f, 0.323242f, 0.334229f, 0.345459f, 0.355957f, + 0.368652f, 0.380615f, 0.391602f, 0.403809f, 0.415771f, 0.428467f, 0.686523f, 0.696777f, 0.695312f, 0.691895f, 0.687500f, 0.683105f, + 0.001931f, 0.005970f, 0.009651f, 0.013557f, 0.017136f, 0.021088f, 0.024902f, 0.028748f, 0.032623f, 0.036743f, 0.040833f, 0.044983f, + 0.049591f, 0.053467f, 0.057800f, 0.062500f, 0.066833f, 0.071533f, 0.076538f, 0.081238f, 0.086670f, 0.092224f, 0.097290f, 0.103088f, + 0.108887f, 0.114990f, 0.120972f, 0.127197f, 0.134277f, 0.140503f, 0.147705f, 0.154663f, 0.162231f, 0.169922f, 0.177612f, 0.185303f, + 0.193604f, 0.201904f, 0.210815f, 0.219238f, 0.228516f, 0.237427f, 0.247070f, 0.256592f, 0.265869f, 0.275879f, 0.285645f, 0.295898f, + 0.306396f, 0.317139f, 0.328369f, 0.338623f, 0.350342f, 0.362305f, 0.374023f, 0.385010f, 0.397461f, 0.410156f, 0.675781f, 0.687988f, + 0.687012f, 0.683594f, 0.680664f, 0.676270f, 0.001725f, 0.005436f, 0.009171f, 0.012589f, 0.016190f, 0.019485f, 0.023132f, 0.026978f, + 0.030899f, 0.034180f, 0.037659f, 0.041565f, 0.045074f, 0.049438f, 0.053345f, 0.057739f, 0.061768f, 0.065918f, 0.070679f, 0.075073f, + 0.080078f, 0.084656f, 0.089966f, 0.095215f, 0.100464f, 0.106445f, 0.112000f, 0.117615f, 0.124207f, 0.130737f, 0.136719f, 0.144043f, + 0.151123f, 0.158081f, 0.165405f, 0.173096f, 0.181152f, 0.189087f, 0.197510f, 0.205688f, 0.214600f, 0.223145f, 0.232178f, 0.241699f, + 0.250732f, 0.260254f, 0.270264f, 0.279785f, 0.289795f, 0.300293f, 0.310791f, 0.322510f, 0.333496f, 0.344238f, 0.355713f, 0.367188f, + 0.379395f, 0.392090f, 0.664551f, 0.678711f, 0.678223f, 0.675781f, 0.672852f, 0.669922f, 0.001741f, 0.005077f, 0.008522f, 0.011810f, + 0.014946f, 0.018524f, 0.021332f, 0.024872f, 0.028519f, 0.031799f, 0.034973f, 0.038727f, 0.041992f, 0.045654f, 0.049072f, 0.052856f, + 0.056671f, 0.060638f, 0.064819f, 0.069092f, 0.073425f, 0.078125f, 0.082886f, 0.087280f, 0.092651f, 0.098206f, 0.103638f, 0.109192f, + 0.114563f, 0.120667f, 0.126709f, 0.133057f, 0.139771f, 0.146851f, 0.153931f, 0.160767f, 0.168457f, 0.175903f, 0.183838f, 0.192505f, + 0.200195f, 0.208618f, 0.217407f, 0.226562f, 0.236084f, 0.245239f, 0.254639f, 0.263672f, 0.273926f, 0.283447f, 0.294189f, 0.304932f, + 0.315674f, 0.326172f, 0.337402f, 0.348877f, 0.360107f, 0.373291f, 0.653809f, 0.670410f, 0.669922f, 0.667480f, 0.665527f, 0.662109f, + 0.001639f, 0.004951f, 0.007996f, 0.010857f, 0.013779f, 0.016968f, 0.019974f, 0.023392f, 0.026001f, 0.029373f, 0.032013f, 0.035370f, + 0.038513f, 0.041992f, 0.044586f, 0.048706f, 0.052124f, 0.055634f, 0.059723f, 0.063354f, 0.067444f, 0.071289f, 0.075745f, 0.080444f, + 0.085022f, 0.089722f, 0.095032f, 0.100220f, 0.105347f, 0.111206f, 0.117126f, 0.123108f, 0.129395f, 0.135620f, 0.142090f, 0.148682f, + 0.156372f, 0.163574f, 0.170898f, 0.178711f, 0.186890f, 0.194580f, 0.203613f, 0.211426f, 0.220459f, 0.229492f, 0.238281f, 0.248169f, + 0.257324f, 0.267578f, 0.277832f, 0.287354f, 0.298340f, 0.308350f, 0.319824f, 0.331543f, 0.342041f, 0.354248f, 0.641602f, 0.660645f, + 0.662109f, 0.660645f, 0.658203f, 0.654785f, 0.001569f, 0.004539f, 0.007538f, 0.010368f, 0.013359f, 0.016006f, 0.018539f, 0.021210f, + 0.024384f, 0.026855f, 0.029892f, 0.032471f, 0.035034f, 0.038177f, 0.041199f, 0.044434f, 0.047485f, 0.050781f, 0.054321f, 0.057953f, + 0.061523f, 0.065430f, 0.069275f, 0.073547f, 0.077820f, 0.082092f, 0.086731f, 0.091736f, 0.096985f, 0.101990f, 0.107361f, 0.112549f, + 0.118774f, 0.124878f, 0.131104f, 0.137573f, 0.144409f, 0.150635f, 0.157837f, 0.165283f, 0.173340f, 0.181274f, 0.188599f, 0.197510f, + 0.205933f, 0.214600f, 0.223633f, 0.232056f, 0.241577f, 0.251709f, 0.261230f, 0.270996f, 0.281250f, 0.291260f, 0.302246f, 0.313477f, + 0.323730f, 0.336182f, 0.630859f, 0.651855f, 0.652832f, 0.652344f, 0.650391f, 0.647461f, 0.001558f, 0.004139f, 0.007103f, 0.009560f, + 0.012077f, 0.014313f, 0.016983f, 0.019653f, 0.021988f, 0.024490f, 0.027023f, 0.029526f, 0.031891f, 0.034821f, 0.037903f, 0.040192f, + 0.043457f, 0.046417f, 0.049316f, 0.052795f, 0.055725f, 0.059357f, 0.063354f, 0.066895f, 0.070740f, 0.074890f, 0.078979f, 0.083801f, + 0.088440f, 0.093018f, 0.097961f, 0.103394f, 0.108704f, 0.114563f, 0.120239f, 0.126343f, 0.132690f, 0.139038f, 0.145874f, 0.152710f, + 0.159912f, 0.168091f, 0.175537f, 0.183228f, 0.191650f, 0.199707f, 0.208130f, 0.216797f, 0.226074f, 0.235352f, 0.244507f, 0.254395f, + 0.264404f, 0.274414f, 0.285156f, 0.296631f, 0.307373f, 0.318604f, 0.619141f, 0.643066f, 0.644531f, 0.644043f, 0.642578f, 0.639648f, + 0.001314f, 0.004002f, 0.006603f, 0.009056f, 0.011490f, 0.013184f, 0.015587f, 0.017883f, 0.020157f, 0.022415f, 0.024582f, 0.027206f, + 0.029160f, 0.031677f, 0.034088f, 0.036530f, 0.039337f, 0.042206f, 0.044891f, 0.047729f, 0.050751f, 0.053955f, 0.057312f, 0.060486f, + 0.064148f, 0.068054f, 0.071960f, 0.075867f, 0.079895f, 0.084595f, 0.089172f, 0.094238f, 0.098999f, 0.104492f, 0.109802f, 0.115173f, + 0.121338f, 0.127686f, 0.134033f, 0.140991f, 0.147095f, 0.154541f, 0.161865f, 0.169800f, 0.177368f, 0.185547f, 0.193848f, 0.201904f, + 0.211060f, 0.219116f, 0.229004f, 0.238525f, 0.248047f, 0.257812f, 0.267822f, 0.277832f, 0.289062f, 0.300537f, 0.607910f, 0.633301f, + 0.636230f, 0.635742f, 0.634766f, 0.633301f, 0.001217f, 0.003571f, 0.005947f, 0.008011f, 0.010391f, 0.012207f, 0.014313f, 0.016617f, + 0.018280f, 0.020523f, 0.022537f, 0.024475f, 0.026443f, 0.028778f, 0.030884f, 0.032867f, 0.035553f, 0.037872f, 0.040375f, 0.042938f, + 0.045593f, 0.048431f, 0.051605f, 0.054688f, 0.057953f, 0.061279f, 0.065002f, 0.068665f, 0.072266f, 0.076294f, 0.080872f, 0.085083f, + 0.089783f, 0.094482f, 0.099915f, 0.104736f, 0.110901f, 0.116272f, 0.122314f, 0.128784f, 0.134888f, 0.142090f, 0.148560f, 0.155884f, + 0.163574f, 0.171753f, 0.179077f, 0.187500f, 0.195679f, 0.204346f, 0.213745f, 0.222656f, 0.231812f, 0.241455f, 0.250977f, 0.261230f, + 0.272461f, 0.282959f, 0.596680f, 0.623535f, 0.627441f, 0.627930f, 0.627441f, 0.625000f, 0.001111f, 0.003542f, 0.005569f, 0.007504f, + 0.009338f, 0.011452f, 0.012939f, 0.015030f, 0.016678f, 0.018326f, 0.020203f, 0.022217f, 0.023788f, 0.025604f, 0.027771f, 0.029877f, + 0.031860f, 0.033813f, 0.036102f, 0.038605f, 0.040985f, 0.043579f, 0.046448f, 0.049042f, 0.051849f, 0.055054f, 0.058319f, 0.061615f, + 0.065125f, 0.068909f, 0.072815f, 0.076843f, 0.080872f, 0.085571f, 0.089905f, 0.095398f, 0.100159f, 0.105713f, 0.111206f, 0.116882f, + 0.122925f, 0.129517f, 0.135742f, 0.142822f, 0.149902f, 0.157349f, 0.165161f, 0.172852f, 0.181152f, 0.189331f, 0.198120f, 0.206909f, + 0.215820f, 0.225342f, 0.235474f, 0.245239f, 0.254883f, 0.266602f, 0.584473f, 0.614746f, 0.619141f, 0.619629f, 0.619141f, 0.618164f, + 0.001149f, 0.003147f, 0.004826f, 0.006886f, 0.008629f, 0.010452f, 0.012024f, 0.013359f, 0.015175f, 0.016647f, 0.018143f, 0.019882f, + 0.021332f, 0.023026f, 0.024902f, 0.026550f, 0.028397f, 0.030045f, 0.032318f, 0.034393f, 0.036682f, 0.038910f, 0.041107f, 0.043671f, + 0.046295f, 0.048950f, 0.051819f, 0.054993f, 0.058258f, 0.061523f, 0.065063f, 0.068481f, 0.072510f, 0.076965f, 0.081055f, 0.085510f, + 0.090393f, 0.095093f, 0.100342f, 0.105774f, 0.111694f, 0.117371f, 0.124084f, 0.130371f, 0.136963f, 0.143921f, 0.151245f, 0.159058f, + 0.166626f, 0.174927f, 0.182983f, 0.191650f, 0.200195f, 0.209473f, 0.218750f, 0.228149f, 0.238037f, 0.249146f, 0.572266f, 0.604980f, + 0.609863f, 0.611328f, 0.610352f, 0.611328f, 0.001009f, 0.003059f, 0.004620f, 0.006283f, 0.007881f, 0.009415f, 0.010864f, 0.011940f, + 0.013443f, 0.014847f, 0.016403f, 0.017700f, 0.019012f, 0.020493f, 0.021927f, 0.023697f, 0.025177f, 0.026947f, 0.028732f, 0.030472f, + 0.032654f, 0.034302f, 0.036591f, 0.038757f, 0.041046f, 0.043488f, 0.045837f, 0.048706f, 0.051544f, 0.054810f, 0.057770f, 0.061188f, + 0.064331f, 0.068237f, 0.072083f, 0.076416f, 0.080872f, 0.085388f, 0.090149f, 0.095276f, 0.100403f, 0.105896f, 0.111877f, 0.117798f, + 0.124329f, 0.130859f, 0.138062f, 0.145020f, 0.152710f, 0.160034f, 0.168335f, 0.176514f, 0.185059f, 0.193481f, 0.203125f, 0.212158f, + 0.221924f, 0.232178f, 0.562500f, 0.594727f, 0.601074f, 0.602539f, 0.603516f, 0.602539f, 0.000865f, 0.002674f, 0.004444f, 0.005615f, + 0.007233f, 0.008430f, 0.009827f, 0.010880f, 0.011917f, 0.013206f, 0.014412f, 0.015717f, 0.016876f, 0.018173f, 0.019501f, 0.020950f, + 0.022217f, 0.023773f, 0.025284f, 0.026749f, 0.028610f, 0.030151f, 0.032166f, 0.034149f, 0.036041f, 0.038330f, 0.040558f, 0.042877f, + 0.045532f, 0.048157f, 0.050934f, 0.053894f, 0.056946f, 0.060303f, 0.063843f, 0.067566f, 0.071472f, 0.075806f, 0.080261f, 0.084778f, + 0.089600f, 0.094971f, 0.100220f, 0.105896f, 0.111877f, 0.118103f, 0.125000f, 0.131348f, 0.138550f, 0.146362f, 0.153687f, 0.161987f, + 0.169678f, 0.178223f, 0.187134f, 0.196045f, 0.205811f, 0.215698f, 0.549805f, 0.584961f, 0.592773f, 0.594238f, 0.593750f, 0.595215f, + 0.000951f, 0.002476f, 0.003956f, 0.005062f, 0.006268f, 0.007637f, 0.008888f, 0.009666f, 0.010628f, 0.011810f, 0.012856f, 0.013878f, + 0.014946f, 0.015900f, 0.017227f, 0.018356f, 0.019592f, 0.020889f, 0.022003f, 0.023438f, 0.025101f, 0.026489f, 0.028122f, 0.029739f, + 0.031555f, 0.033295f, 0.035431f, 0.037537f, 0.039795f, 0.041962f, 0.044647f, 0.047302f, 0.049957f, 0.052979f, 0.056122f, 0.059387f, + 0.062927f, 0.066956f, 0.070679f, 0.074951f, 0.079468f, 0.084167f, 0.089294f, 0.094482f, 0.100098f, 0.106018f, 0.112061f, 0.118835f, + 0.125366f, 0.132446f, 0.139893f, 0.147827f, 0.155762f, 0.163574f, 0.172607f, 0.180786f, 0.190063f, 0.199951f, 0.536621f, 0.576172f, + 0.583496f, 0.586914f, 0.587402f, 0.586914f, 0.000788f, 0.002115f, 0.003592f, 0.004780f, 0.005939f, 0.006615f, 0.007740f, 0.008598f, + 0.009514f, 0.010376f, 0.011200f, 0.012138f, 0.013016f, 0.014069f, 0.014977f, 0.015961f, 0.016922f, 0.018036f, 0.019043f, 0.020447f, + 0.021606f, 0.022995f, 0.024323f, 0.025864f, 0.027344f, 0.028946f, 0.030731f, 0.032593f, 0.034515f, 0.036530f, 0.038910f, 0.041016f, + 0.043274f, 0.046021f, 0.048981f, 0.051819f, 0.055176f, 0.058472f, 0.062012f, 0.065857f, 0.069946f, 0.074219f, 0.078796f, 0.083801f, + 0.088806f, 0.094299f, 0.100281f, 0.106018f, 0.112793f, 0.119446f, 0.126343f, 0.133545f, 0.141357f, 0.149292f, 0.157104f, 0.165894f, + 0.174683f, 0.184326f, 0.524902f, 0.566895f, 0.575195f, 0.576660f, 0.579102f, 0.579590f, 0.000661f, 0.001961f, 0.003382f, 0.004311f, + 0.005161f, 0.006062f, 0.006737f, 0.007427f, 0.008286f, 0.008995f, 0.009857f, 0.010368f, 0.011230f, 0.011955f, 0.012833f, 0.013786f, + 0.014565f, 0.015480f, 0.016647f, 0.017578f, 0.018677f, 0.019806f, 0.020950f, 0.022263f, 0.023651f, 0.024994f, 0.026306f, 0.027863f, + 0.029724f, 0.031525f, 0.033325f, 0.035370f, 0.037292f, 0.039673f, 0.042114f, 0.044769f, 0.047546f, 0.050537f, 0.053680f, 0.057098f, + 0.060852f, 0.064514f, 0.069031f, 0.073303f, 0.078064f, 0.083069f, 0.088379f, 0.094238f, 0.100220f, 0.106689f, 0.113342f, 0.120300f, + 0.127563f, 0.135132f, 0.142700f, 0.151245f, 0.160034f, 0.168823f, 0.512695f, 0.557129f, 0.566406f, 0.569824f, 0.569824f, 0.571289f, + 0.000757f, 0.001709f, 0.002844f, 0.003582f, 0.004448f, 0.005192f, 0.005989f, 0.006519f, 0.007038f, 0.007801f, 0.008453f, 0.009071f, + 0.009727f, 0.010391f, 0.011009f, 0.011726f, 0.012650f, 0.013184f, 0.014107f, 0.014977f, 0.015900f, 0.016800f, 0.017776f, 0.018936f, + 0.020172f, 0.021271f, 0.022446f, 0.023697f, 0.025055f, 0.026703f, 0.028397f, 0.030014f, 0.031921f, 0.033905f, 0.035919f, 0.038177f, + 0.040680f, 0.043243f, 0.045898f, 0.049072f, 0.052216f, 0.055725f, 0.059784f, 0.063538f, 0.067688f, 0.072327f, 0.077271f, 0.082764f, + 0.088379f, 0.094299f, 0.100708f, 0.107239f, 0.114136f, 0.121582f, 0.128906f, 0.136963f, 0.145630f, 0.153564f, 0.500977f, 0.547852f, + 0.556641f, 0.561523f, 0.562500f, 0.563965f, 0.000704f, 0.001769f, 0.002542f, 0.003523f, 0.004036f, 0.004562f, 0.005032f, 0.005661f, + 0.006176f, 0.006542f, 0.007072f, 0.007698f, 0.008339f, 0.008827f, 0.009323f, 0.010094f, 0.010757f, 0.011276f, 0.012093f, 0.012733f, + 0.013489f, 0.014488f, 0.015244f, 0.016006f, 0.017151f, 0.017975f, 0.018967f, 0.020142f, 0.021255f, 0.022552f, 0.023880f, 0.025314f, + 0.026840f, 0.028503f, 0.030441f, 0.032166f, 0.034424f, 0.036438f, 0.039001f, 0.041656f, 0.044464f, 0.047455f, 0.050842f, 0.054443f, + 0.058167f, 0.062286f, 0.066956f, 0.071899f, 0.076904f, 0.082458f, 0.088501f, 0.094482f, 0.101196f, 0.108337f, 0.115662f, 0.123352f, + 0.130981f, 0.139282f, 0.489746f, 0.538574f, 0.547852f, 0.551270f, 0.554688f, 0.555176f, 0.000579f, 0.001450f, 0.002396f, 0.002857f, + 0.003454f, 0.004032f, 0.004356f, 0.004791f, 0.005333f, 0.005718f, 0.006130f, 0.006485f, 0.007042f, 0.007473f, 0.007988f, 0.008476f, + 0.008865f, 0.009613f, 0.010086f, 0.010651f, 0.011345f, 0.012047f, 0.012764f, 0.013435f, 0.014282f, 0.015144f, 0.015884f, 0.016846f, + 0.017868f, 0.018814f, 0.020050f, 0.021164f, 0.022507f, 0.023773f, 0.025192f, 0.026978f, 0.028564f, 0.030640f, 0.032623f, 0.034882f, + 0.037231f, 0.039886f, 0.042786f, 0.046143f, 0.049286f, 0.052979f, 0.057098f, 0.061279f, 0.066223f, 0.071167f, 0.076660f, 0.082581f, + 0.088989f, 0.095581f, 0.102661f, 0.109863f, 0.117737f, 0.125488f, 0.476807f, 0.528320f, 0.538574f, 0.543945f, 0.546875f, 0.546875f, + 0.000510f, 0.001428f, 0.002037f, 0.002613f, 0.003086f, 0.003290f, 0.003672f, 0.004108f, 0.004345f, 0.004768f, 0.005035f, 0.005470f, + 0.005959f, 0.006207f, 0.006599f, 0.007095f, 0.007568f, 0.008003f, 0.008377f, 0.008904f, 0.009575f, 0.010010f, 0.010643f, 0.011131f, + 0.011871f, 0.012535f, 0.013199f, 0.014038f, 0.014839f, 0.015640f, 0.016586f, 0.017502f, 0.018585f, 0.019745f, 0.021088f, 0.022354f, + 0.023727f, 0.025253f, 0.026962f, 0.028870f, 0.030762f, 0.033051f, 0.035492f, 0.038177f, 0.041229f, 0.044403f, 0.048004f, 0.051880f, + 0.056213f, 0.060516f, 0.065857f, 0.071045f, 0.077271f, 0.083374f, 0.090027f, 0.096863f, 0.104492f, 0.112183f, 0.463623f, 0.518066f, + 0.529785f, 0.535156f, 0.538086f, 0.540039f, 0.000473f, 0.001222f, 0.001771f, 0.002117f, 0.002323f, 0.002796f, 0.003096f, 0.003355f, + 0.003601f, 0.003975f, 0.004295f, 0.004543f, 0.004833f, 0.005142f, 0.005455f, 0.005848f, 0.006165f, 0.006535f, 0.006947f, 0.007370f, + 0.007809f, 0.008240f, 0.008690f, 0.009216f, 0.009758f, 0.010223f, 0.010925f, 0.011536f, 0.012146f, 0.012833f, 0.013573f, 0.014389f, + 0.015244f, 0.016220f, 0.017120f, 0.018219f, 0.019379f, 0.020599f, 0.021988f, 0.023514f, 0.025131f, 0.027054f, 0.029037f, 0.031311f, + 0.033752f, 0.036591f, 0.039520f, 0.042999f, 0.046661f, 0.050873f, 0.055603f, 0.060333f, 0.066101f, 0.071960f, 0.078491f, 0.084961f, + 0.091797f, 0.099426f, 0.452148f, 0.508301f, 0.520508f, 0.526367f, 0.528809f, 0.530273f, 0.000299f, 0.001057f, 0.001329f, 0.001771f, + 0.001957f, 0.002350f, 0.002483f, 0.002697f, 0.002964f, 0.003181f, 0.003441f, 0.003653f, 0.003904f, 0.004238f, 0.004501f, 0.004738f, + 0.005024f, 0.005390f, 0.005657f, 0.005985f, 0.006279f, 0.006714f, 0.007053f, 0.007507f, 0.007881f, 0.008369f, 0.008774f, 0.009300f, + 0.009888f, 0.010483f, 0.011093f, 0.011627f, 0.012398f, 0.013130f, 0.013855f, 0.014717f, 0.015686f, 0.016739f, 0.017761f, 0.018890f, + 0.020248f, 0.021698f, 0.023376f, 0.025131f, 0.027237f, 0.029556f, 0.032166f, 0.035004f, 0.038208f, 0.041962f, 0.045868f, 0.050507f, + 0.055359f, 0.060852f, 0.066772f, 0.073242f, 0.080017f, 0.087097f, 0.440674f, 0.498047f, 0.511719f, 0.517090f, 0.520508f, 0.522949f, + 0.000427f, 0.001020f, 0.001253f, 0.001431f, 0.001690f, 0.001900f, 0.002018f, 0.002304f, 0.002481f, 0.002569f, 0.002731f, 0.002998f, + 0.003157f, 0.003424f, 0.003592f, 0.003838f, 0.004017f, 0.004253f, 0.004551f, 0.004776f, 0.005100f, 0.005379f, 0.005699f, 0.005932f, + 0.006290f, 0.006630f, 0.007038f, 0.007465f, 0.007927f, 0.008286f, 0.008858f, 0.009293f, 0.009888f, 0.010429f, 0.011086f, 0.011765f, + 0.012482f, 0.013298f, 0.014168f, 0.015068f, 0.016129f, 0.017288f, 0.018585f, 0.019943f, 0.021622f, 0.023361f, 0.025436f, 0.027847f, + 0.030655f, 0.033447f, 0.037079f, 0.041229f, 0.045776f, 0.050568f, 0.056061f, 0.062317f, 0.068726f, 0.075684f, 0.427734f, 0.488525f, + 0.502441f, 0.508789f, 0.513184f, 0.513672f, 0.000255f, 0.000597f, 0.001032f, 0.001150f, 0.001353f, 0.001493f, 0.001608f, 0.001750f, + 0.001933f, 0.002062f, 0.002178f, 0.002302f, 0.002474f, 0.002670f, 0.002872f, 0.002995f, 0.003147f, 0.003298f, 0.003565f, 0.003729f, + 0.003941f, 0.004219f, 0.004436f, 0.004719f, 0.005005f, 0.005230f, 0.005489f, 0.005806f, 0.006191f, 0.006496f, 0.006897f, 0.007267f, + 0.007671f, 0.008179f, 0.008636f, 0.009163f, 0.009766f, 0.010368f, 0.011047f, 0.011810f, 0.012611f, 0.013527f, 0.014519f, 0.015640f, + 0.016800f, 0.018265f, 0.019897f, 0.021698f, 0.023895f, 0.026260f, 0.029175f, 0.032715f, 0.036682f, 0.041168f, 0.045929f, 0.051758f, + 0.057922f, 0.064575f, 0.415771f, 0.478271f, 0.493652f, 0.500000f, 0.503906f, 0.505859f, 0.000255f, 0.000544f, 0.000863f, 0.000994f, + 0.001086f, 0.001183f, 0.001317f, 0.001328f, 0.001491f, 0.001608f, 0.001716f, 0.001851f, 0.001943f, 0.002075f, 0.002161f, 0.002319f, + 0.002426f, 0.002596f, 0.002741f, 0.002884f, 0.003088f, 0.003265f, 0.003391f, 0.003620f, 0.003777f, 0.004005f, 0.004215f, 0.004452f, + 0.004734f, 0.004963f, 0.005341f, 0.005577f, 0.005875f, 0.006271f, 0.006603f, 0.006996f, 0.007450f, 0.007919f, 0.008446f, 0.009003f, + 0.009674f, 0.010338f, 0.011101f, 0.011909f, 0.012917f, 0.013977f, 0.015190f, 0.016495f, 0.018112f, 0.020325f, 0.022415f, 0.025146f, + 0.028473f, 0.032349f, 0.036804f, 0.041992f, 0.047913f, 0.054077f, 0.404541f, 0.468506f, 0.484131f, 0.490967f, 0.495361f, 0.498291f, + 0.000377f, 0.000440f, 0.000606f, 0.000685f, 0.000735f, 0.000876f, 0.000929f, 0.001035f, 0.001068f, 0.001157f, 0.001307f, 0.001381f, + 0.001473f, 0.001595f, 0.001664f, 0.001708f, 0.001850f, 0.001957f, 0.002043f, 0.002195f, 0.002291f, 0.002422f, 0.002571f, 0.002687f, + 0.002842f, 0.002979f, 0.003183f, 0.003345f, 0.003532f, 0.003794f, 0.004002f, 0.004154f, 0.004429f, 0.004635f, 0.004967f, 0.005253f, + 0.005573f, 0.005909f, 0.006275f, 0.006695f, 0.007183f, 0.007660f, 0.008316f, 0.008934f, 0.009644f, 0.010429f, 0.011360f, 0.012497f, + 0.013634f, 0.014977f, 0.016663f, 0.018875f, 0.021423f, 0.024643f, 0.028549f, 0.033020f, 0.038483f, 0.044525f, 0.391602f, 0.458984f, + 0.474854f, 0.482178f, 0.488037f, 0.489990f, 0.000159f, 0.000401f, 0.000450f, 0.000522f, 0.000605f, 0.000634f, 0.000728f, 0.000702f, + 0.000808f, 0.000882f, 0.000959f, 0.000991f, 0.001043f, 0.001112f, 0.001205f, 0.001245f, 0.001357f, 0.001419f, 0.001513f, 0.001546f, + 0.001648f, 0.001752f, 0.001863f, 0.001942f, 0.002056f, 0.002159f, 0.002289f, 0.002392f, 0.002506f, 0.002697f, 0.002827f, 0.003023f, + 0.003172f, 0.003330f, 0.003542f, 0.003750f, 0.004017f, 0.004292f, 0.004559f, 0.004871f, 0.005161f, 0.005539f, 0.005932f, 0.006416f, + 0.006973f, 0.007526f, 0.008232f, 0.008980f, 0.009918f, 0.010895f, 0.012085f, 0.013680f, 0.015472f, 0.017975f, 0.021103f, 0.025146f, + 0.029938f, 0.035645f, 0.379395f, 0.448486f, 0.465820f, 0.473633f, 0.478760f, 0.481689f, 0.000112f, 0.000220f, 0.000321f, 0.000322f, + 0.000401f, 0.000489f, 0.000469f, 0.000510f, 0.000568f, 0.000653f, 0.000659f, 0.000676f, 0.000703f, 0.000789f, 0.000811f, 0.000886f, + 0.000888f, 0.000994f, 0.001048f, 0.001096f, 0.001155f, 0.001220f, 0.001289f, 0.001357f, 0.001431f, 0.001496f, 0.001599f, 0.001675f, + 0.001759f, 0.001894f, 0.001965f, 0.002083f, 0.002193f, 0.002310f, 0.002464f, 0.002634f, 0.002758f, 0.002949f, 0.003134f, 0.003319f, + 0.003551f, 0.003830f, 0.004120f, 0.004440f, 0.004784f, 0.005188f, 0.005680f, 0.006222f, 0.006886f, 0.007614f, 0.008461f, 0.009529f, + 0.010864f, 0.012596f, 0.014961f, 0.018097f, 0.022263f, 0.027466f, 0.367920f, 0.438232f, 0.456543f, 0.465332f, 0.470215f, 0.472900f, + 0.000140f, 0.000219f, 0.000241f, 0.000245f, 0.000290f, 0.000291f, 0.000302f, 0.000342f, 0.000380f, 0.000409f, 0.000408f, 0.000485f, + 0.000473f, 0.000527f, 0.000556f, 0.000575f, 0.000630f, 0.000642f, 0.000673f, 0.000711f, 0.000762f, 0.000800f, 0.000852f, 0.000886f, + 0.000952f, 0.000982f, 0.001049f, 0.001108f, 0.001159f, 0.001220f, 0.001281f, 0.001369f, 0.001454f, 0.001522f, 0.001595f, 0.001695f, + 0.001839f, 0.001928f, 0.002068f, 0.002209f, 0.002337f, 0.002504f, 0.002686f, 0.002876f, 0.003139f, 0.003437f, 0.003723f, 0.004078f, + 0.004509f, 0.005009f, 0.005615f, 0.006332f, 0.007317f, 0.008461f, 0.009926f, 0.012154f, 0.015640f, 0.020325f, 0.356445f, 0.429199f, + 0.447266f, 0.456299f, 0.462158f, 0.464844f, 0.000048f, 0.000154f, 0.000141f, 0.000147f, 0.000174f, 0.000207f, 0.000188f, 0.000221f, + 0.000233f, 0.000242f, 0.000248f, 0.000271f, 0.000299f, 0.000312f, 0.000337f, 0.000350f, 0.000367f, 0.000403f, 0.000416f, 0.000458f, + 0.000465f, 0.000483f, 0.000507f, 0.000546f, 0.000576f, 0.000625f, 0.000637f, 0.000659f, 0.000705f, 0.000742f, 0.000797f, 0.000837f, + 0.000890f, 0.000925f, 0.000978f, 0.001036f, 0.001103f, 0.001181f, 0.001253f, 0.001329f, 0.001421f, 0.001529f, 0.001647f, 0.001782f, + 0.001906f, 0.002075f, 0.002291f, 0.002483f, 0.002758f, 0.003059f, 0.003450f, 0.003906f, 0.004536f, 0.005306f, 0.006325f, 0.007713f, + 0.010101f, 0.014084f, 0.343262f, 0.418457f, 0.437744f, 0.447510f, 0.452881f, 0.456543f, 0.000099f, 0.000100f, 0.000091f, 0.000085f, + 0.000105f, 0.000099f, 0.000127f, 0.000127f, 0.000130f, 0.000137f, 0.000152f, 0.000164f, 0.000164f, 0.000172f, 0.000195f, 0.000186f, + 0.000209f, 0.000222f, 0.000231f, 0.000241f, 0.000258f, 0.000266f, 0.000290f, 0.000301f, 0.000324f, 0.000343f, 0.000357f, 0.000369f, + 0.000392f, 0.000409f, 0.000440f, 0.000463f, 0.000484f, 0.000513f, 0.000544f, 0.000578f, 0.000607f, 0.000650f, 0.000702f, 0.000737f, + 0.000787f, 0.000846f, 0.000918f, 0.000977f, 0.001062f, 0.001146f, 0.001259f, 0.001379f, 0.001524f, 0.001701f, 0.001924f, 0.002207f, + 0.002542f, 0.003006f, 0.003628f, 0.004494f, 0.005821f, 0.008774f, 0.332031f, 0.409180f, 0.428467f, 0.438965f, 0.444336f, 0.447998f, + 0.000082f, 0.000057f, 0.000048f, 0.000051f, 0.000055f, 0.000054f, 0.000057f, 0.000064f, 0.000066f, 0.000079f, 0.000070f, 0.000070f, + 0.000084f, 0.000078f, 0.000084f, 0.000091f, 0.000099f, 0.000108f, 0.000108f, 0.000114f, 0.000119f, 0.000124f, 0.000129f, 0.000144f, + 0.000151f, 0.000158f, 0.000163f, 0.000176f, 0.000188f, 0.000196f, 0.000208f, 0.000220f, 0.000227f, 0.000239f, 0.000259f, 0.000273f, + 0.000290f, 0.000303f, 0.000331f, 0.000351f, 0.000376f, 0.000402f, 0.000432f, 0.000460f, 0.000500f, 0.000547f, 0.000593f, 0.000648f, + 0.000720f, 0.000805f, 0.000918f, 0.001045f, 0.001225f, 0.001462f, 0.001788f, 0.002264f, 0.003029f, 0.004623f, 0.320801f, 0.398682f, + 0.419922f, 0.430420f, 0.436279f, 0.440674f, 0.000061f, 0.000041f, 0.000033f, 0.000029f, 0.000026f, 0.000025f, 0.000024f, 0.000024f, + 0.000023f, 0.000023f, 0.000025f, 0.000032f, 0.000026f, 0.000027f, 0.000035f, 0.000037f, 0.000039f, 0.000041f, 0.000041f, 0.000041f, + 0.000044f, 0.000050f, 0.000054f, 0.000051f, 0.000055f, 0.000060f, 0.000061f, 0.000062f, 0.000069f, 0.000074f, 0.000075f, 0.000081f, + 0.000087f, 0.000090f, 0.000093f, 0.000098f, 0.000108f, 0.000114f, 0.000123f, 0.000130f, 0.000142f, 0.000144f, 0.000156f, 0.000173f, + 0.000179f, 0.000200f, 0.000218f, 0.000237f, 0.000267f, 0.000299f, 0.000335f, 0.000382f, 0.000448f, 0.000544f, 0.000677f, 0.000883f, + 0.001233f, 0.001933f, 0.309570f, 0.388672f, 0.410889f, 0.421143f, 0.427246f, 0.431885f, 0.000031f, 0.000020f, 0.000016f, 0.000014f, + 0.000013f, 0.000012f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000008f, 0.000009f, + 0.000009f, 0.000007f, 0.000007f, 0.000007f, 0.000008f, 0.000009f, 0.000011f, 0.000012f, 0.000012f, 0.000012f, 0.000013f, 0.000015f, + 0.000015f, 0.000014f, 0.000016f, 0.000017f, 0.000019f, 0.000020f, 0.000020f, 0.000022f, 0.000025f, 0.000023f, 0.000026f, 0.000029f, + 0.000031f, 0.000034f, 0.000036f, 0.000037f, 0.000040f, 0.000044f, 0.000048f, 0.000052f, 0.000056f, 0.000063f, 0.000068f, 0.000083f, + 0.000098f, 0.000117f, 0.000149f, 0.000201f, 0.000301f, 0.000544f, 0.297607f, 0.379150f, 0.400879f, 0.411865f, 0.419189f, 0.423340f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, + 0.000002f, 0.000002f, 0.000003f, 0.000004f, 0.000004f, 0.000004f, 0.000005f, 0.000007f, 0.000011f, 0.000026f, 0.286621f, 0.368896f, + 0.391846f, 0.402588f, 0.409912f, 0.414551f, + }, + { + 0.007935f, 0.024429f, 0.041290f, 0.058838f, 0.076355f, 0.093933f, 0.111145f, 0.128174f, 0.146606f, 0.164429f, 0.182617f, 0.200562f, + 0.218750f, 0.236206f, 0.254150f, 0.271729f, 0.289551f, 0.308105f, 0.325684f, 0.342773f, 0.360596f, 0.379150f, 0.396240f, 0.414795f, + 0.431641f, 0.450439f, 0.468018f, 0.484619f, 0.502441f, 0.520020f, 0.536621f, 0.554688f, 0.571777f, 0.588379f, 0.605469f, 0.622559f, + 0.640137f, 0.657227f, 0.672852f, 0.689941f, 0.707031f, 0.723633f, 0.740234f, 0.756836f, 0.773926f, 0.789551f, 0.805664f, 0.821777f, + 0.838379f, 0.854980f, 0.870117f, 0.885742f, 0.901855f, 0.917480f, 0.932617f, 0.948730f, 0.963379f, 0.979492f, 0.960449f, 0.909668f, + 0.876465f, 0.850098f, 0.827637f, 0.807617f, 0.007530f, 0.023422f, 0.039764f, 0.056610f, 0.073303f, 0.090149f, 0.107300f, 0.124084f, + 0.141968f, 0.158569f, 0.176392f, 0.193604f, 0.210815f, 0.228760f, 0.246094f, 0.262695f, 0.280518f, 0.298340f, 0.315430f, 0.333252f, + 0.350586f, 0.367432f, 0.384766f, 0.402344f, 0.419678f, 0.436768f, 0.453613f, 0.471436f, 0.488037f, 0.504883f, 0.521973f, 0.538574f, + 0.556641f, 0.573242f, 0.589844f, 0.605957f, 0.623535f, 0.639160f, 0.656250f, 0.673340f, 0.688477f, 0.706055f, 0.721680f, 0.738770f, + 0.754883f, 0.770508f, 0.786133f, 0.803711f, 0.817871f, 0.834473f, 0.850586f, 0.866211f, 0.881348f, 0.896973f, 0.913086f, 0.928223f, + 0.942871f, 0.958984f, 0.951172f, 0.903320f, 0.871094f, 0.845703f, 0.824219f, 0.805664f, 0.007320f, 0.022552f, 0.038391f, 0.054260f, + 0.070312f, 0.086792f, 0.103271f, 0.120178f, 0.136841f, 0.153564f, 0.170410f, 0.187256f, 0.203735f, 0.220825f, 0.237793f, 0.255127f, + 0.271240f, 0.288086f, 0.305420f, 0.322021f, 0.339844f, 0.356689f, 0.373047f, 0.390137f, 0.406738f, 0.423340f, 0.440186f, 0.456787f, + 0.474121f, 0.490967f, 0.507324f, 0.523926f, 0.540527f, 0.557129f, 0.573242f, 0.590332f, 0.606445f, 0.623047f, 0.638672f, 0.655273f, + 0.671875f, 0.687500f, 0.703613f, 0.720215f, 0.735840f, 0.751953f, 0.767578f, 0.783203f, 0.799316f, 0.814941f, 0.830078f, 0.845703f, + 0.861328f, 0.877441f, 0.892090f, 0.908203f, 0.922852f, 0.938477f, 0.941895f, 0.895996f, 0.865723f, 0.841309f, 0.820801f, 0.802734f, + 0.007008f, 0.021667f, 0.036865f, 0.052216f, 0.067871f, 0.083862f, 0.099426f, 0.115479f, 0.131470f, 0.148315f, 0.164551f, 0.180298f, + 0.196899f, 0.213379f, 0.229370f, 0.246460f, 0.262695f, 0.279541f, 0.295410f, 0.311523f, 0.329102f, 0.345215f, 0.360840f, 0.378174f, + 0.394043f, 0.410156f, 0.427246f, 0.443115f, 0.459717f, 0.476318f, 0.493652f, 0.508789f, 0.524902f, 0.541016f, 0.557129f, 0.573242f, + 0.589844f, 0.605469f, 0.621582f, 0.638672f, 0.652832f, 0.669434f, 0.685547f, 0.701660f, 0.717285f, 0.731934f, 0.749023f, 0.764160f, + 0.779785f, 0.794922f, 0.810059f, 0.826172f, 0.841309f, 0.856445f, 0.872070f, 0.886719f, 0.902344f, 0.917480f, 0.932129f, 0.889648f, + 0.859863f, 0.835938f, 0.816895f, 0.799316f, 0.006817f, 0.020645f, 0.035156f, 0.050110f, 0.065247f, 0.080383f, 0.096313f, 0.111450f, + 0.126587f, 0.142456f, 0.158447f, 0.174316f, 0.189819f, 0.205566f, 0.221802f, 0.237427f, 0.253662f, 0.269775f, 0.285889f, 0.301514f, + 0.317627f, 0.333740f, 0.349609f, 0.366211f, 0.381348f, 0.397705f, 0.414307f, 0.429932f, 0.447266f, 0.462646f, 0.477539f, 0.494385f, + 0.509766f, 0.525879f, 0.541992f, 0.557617f, 0.571777f, 0.588379f, 0.605469f, 0.619629f, 0.636230f, 0.651855f, 0.666992f, 0.681152f, + 0.698242f, 0.714355f, 0.729980f, 0.745117f, 0.759766f, 0.775391f, 0.790527f, 0.806152f, 0.821289f, 0.835938f, 0.850586f, 0.866211f, + 0.882324f, 0.896484f, 0.922363f, 0.882324f, 0.854004f, 0.831543f, 0.812500f, 0.795898f, 0.006378f, 0.019989f, 0.034027f, 0.048004f, + 0.062744f, 0.077148f, 0.091980f, 0.107178f, 0.122192f, 0.137207f, 0.152466f, 0.167603f, 0.183960f, 0.199097f, 0.214111f, 0.229736f, + 0.244995f, 0.260254f, 0.276367f, 0.291504f, 0.306641f, 0.322998f, 0.338623f, 0.354248f, 0.369629f, 0.385254f, 0.400879f, 0.416504f, + 0.432617f, 0.447510f, 0.464111f, 0.479492f, 0.494141f, 0.511230f, 0.525879f, 0.541016f, 0.556641f, 0.572754f, 0.586914f, 0.602051f, + 0.617676f, 0.633789f, 0.648926f, 0.665039f, 0.679688f, 0.695312f, 0.710449f, 0.726074f, 0.739746f, 0.755859f, 0.771484f, 0.785645f, + 0.800781f, 0.815918f, 0.831055f, 0.846680f, 0.860840f, 0.875977f, 0.912598f, 0.874512f, 0.847656f, 0.826172f, 0.807617f, 0.791504f, + 0.006603f, 0.019287f, 0.032776f, 0.046356f, 0.060272f, 0.073914f, 0.088135f, 0.102905f, 0.117554f, 0.132690f, 0.147095f, 0.161377f, + 0.176636f, 0.191162f, 0.205444f, 0.221680f, 0.236572f, 0.251465f, 0.267090f, 0.281250f, 0.296875f, 0.312256f, 0.327393f, 0.342285f, + 0.357666f, 0.373291f, 0.388184f, 0.403076f, 0.418457f, 0.433838f, 0.448975f, 0.465088f, 0.479980f, 0.494385f, 0.509277f, 0.525879f, + 0.540039f, 0.555176f, 0.570801f, 0.586426f, 0.601074f, 0.616211f, 0.631348f, 0.646484f, 0.661133f, 0.676270f, 0.692383f, 0.705078f, + 0.720215f, 0.735352f, 0.751953f, 0.766602f, 0.781250f, 0.796387f, 0.810059f, 0.825684f, 0.840820f, 0.855469f, 0.902344f, 0.866699f, + 0.841797f, 0.820312f, 0.803223f, 0.787598f, 0.006111f, 0.018433f, 0.031097f, 0.044739f, 0.057892f, 0.071472f, 0.085205f, 0.099304f, + 0.113037f, 0.127319f, 0.141357f, 0.156128f, 0.169678f, 0.183838f, 0.198608f, 0.213745f, 0.227661f, 0.243652f, 0.257324f, 0.272705f, + 0.286865f, 0.301025f, 0.316406f, 0.331543f, 0.345703f, 0.360107f, 0.375000f, 0.390625f, 0.405762f, 0.420410f, 0.435303f, 0.449951f, + 0.465088f, 0.479492f, 0.494141f, 0.509277f, 0.523926f, 0.538574f, 0.553711f, 0.569336f, 0.583496f, 0.598145f, 0.612793f, 0.628418f, + 0.642578f, 0.657227f, 0.671387f, 0.687012f, 0.702637f, 0.716797f, 0.731934f, 0.745605f, 0.761230f, 0.775391f, 0.790527f, 0.805176f, + 0.819824f, 0.834961f, 0.892578f, 0.858887f, 0.834473f, 0.814941f, 0.798340f, 0.783203f, 0.005756f, 0.017761f, 0.029907f, 0.042572f, + 0.055481f, 0.068420f, 0.081482f, 0.095276f, 0.108826f, 0.122070f, 0.135620f, 0.149902f, 0.163330f, 0.177368f, 0.191284f, 0.206421f, + 0.219482f, 0.233521f, 0.247925f, 0.262451f, 0.277100f, 0.290771f, 0.304688f, 0.319580f, 0.334229f, 0.348389f, 0.362549f, 0.377441f, + 0.391602f, 0.406250f, 0.421143f, 0.435791f, 0.450439f, 0.463867f, 0.478760f, 0.493164f, 0.507812f, 0.521973f, 0.537109f, 0.551270f, + 0.565430f, 0.580078f, 0.594727f, 0.609863f, 0.624023f, 0.638672f, 0.653320f, 0.668457f, 0.682129f, 0.697266f, 0.711914f, 0.726562f, + 0.740723f, 0.755859f, 0.770996f, 0.785156f, 0.799805f, 0.814453f, 0.882812f, 0.851562f, 0.827148f, 0.808594f, 0.792969f, 0.778809f, + 0.005741f, 0.017166f, 0.029053f, 0.041138f, 0.053345f, 0.065796f, 0.078674f, 0.091248f, 0.104614f, 0.117004f, 0.130737f, 0.143921f, + 0.156860f, 0.170288f, 0.183960f, 0.197754f, 0.211304f, 0.224976f, 0.238892f, 0.251953f, 0.266357f, 0.280273f, 0.294922f, 0.308594f, + 0.322021f, 0.336914f, 0.350098f, 0.364502f, 0.378174f, 0.393066f, 0.407471f, 0.420166f, 0.435059f, 0.449219f, 0.463135f, 0.477295f, + 0.491699f, 0.506348f, 0.520996f, 0.534668f, 0.549316f, 0.563477f, 0.577148f, 0.591309f, 0.605469f, 0.620605f, 0.634766f, 0.648438f, + 0.663086f, 0.677734f, 0.691895f, 0.706543f, 0.720215f, 0.734863f, 0.750488f, 0.765137f, 0.779297f, 0.793945f, 0.872559f, 0.843262f, + 0.820801f, 0.803223f, 0.787598f, 0.773926f, 0.005283f, 0.016052f, 0.028030f, 0.039246f, 0.050751f, 0.063232f, 0.074829f, 0.087341f, + 0.099976f, 0.112732f, 0.125122f, 0.138062f, 0.150757f, 0.163696f, 0.176758f, 0.189697f, 0.203125f, 0.216553f, 0.229614f, 0.243286f, + 0.256592f, 0.269775f, 0.283203f, 0.297119f, 0.310547f, 0.324463f, 0.337891f, 0.351807f, 0.365234f, 0.378662f, 0.392822f, 0.406738f, + 0.419922f, 0.434814f, 0.448730f, 0.461182f, 0.476562f, 0.489746f, 0.502930f, 0.517578f, 0.531738f, 0.545410f, 0.559082f, 0.573730f, + 0.587402f, 0.602051f, 0.615723f, 0.629395f, 0.644043f, 0.658203f, 0.672363f, 0.686523f, 0.701660f, 0.714844f, 0.729980f, 0.743652f, + 0.758301f, 0.774414f, 0.862305f, 0.835449f, 0.813965f, 0.796875f, 0.782227f, 0.769043f, 0.005272f, 0.015427f, 0.026230f, 0.037506f, + 0.049164f, 0.060516f, 0.072021f, 0.083740f, 0.095825f, 0.108521f, 0.120361f, 0.132324f, 0.144897f, 0.156738f, 0.169922f, 0.182373f, + 0.195068f, 0.208008f, 0.220459f, 0.233887f, 0.246948f, 0.260254f, 0.272461f, 0.285889f, 0.299561f, 0.312500f, 0.325684f, 0.338867f, + 0.352783f, 0.365479f, 0.378906f, 0.392334f, 0.406006f, 0.419189f, 0.432861f, 0.446777f, 0.460693f, 0.473877f, 0.486572f, 0.500977f, + 0.515137f, 0.528809f, 0.542480f, 0.555176f, 0.569824f, 0.583984f, 0.597656f, 0.611328f, 0.625000f, 0.639648f, 0.653320f, 0.667480f, + 0.681641f, 0.695801f, 0.709961f, 0.723633f, 0.738281f, 0.752930f, 0.852539f, 0.827148f, 0.807129f, 0.790527f, 0.776367f, 0.764160f, + 0.004822f, 0.014885f, 0.025360f, 0.035767f, 0.046570f, 0.057587f, 0.068726f, 0.080139f, 0.091736f, 0.103577f, 0.115479f, 0.126709f, + 0.138672f, 0.150879f, 0.162231f, 0.174805f, 0.187622f, 0.199951f, 0.212524f, 0.224854f, 0.236694f, 0.249878f, 0.262207f, 0.275391f, + 0.287842f, 0.300293f, 0.313477f, 0.326904f, 0.340088f, 0.353027f, 0.365479f, 0.378174f, 0.391602f, 0.404541f, 0.417236f, 0.431641f, + 0.444336f, 0.457764f, 0.470703f, 0.484375f, 0.497803f, 0.510742f, 0.524902f, 0.537598f, 0.552246f, 0.564941f, 0.579590f, 0.592285f, + 0.606445f, 0.621094f, 0.634277f, 0.646973f, 0.662109f, 0.675781f, 0.689453f, 0.704102f, 0.718262f, 0.733398f, 0.842285f, 0.818848f, + 0.799805f, 0.784180f, 0.770996f, 0.758301f, 0.004745f, 0.014427f, 0.024277f, 0.034546f, 0.044800f, 0.055176f, 0.066040f, 0.076477f, + 0.087341f, 0.099060f, 0.110474f, 0.121216f, 0.132690f, 0.144165f, 0.156006f, 0.167358f, 0.179688f, 0.191284f, 0.203247f, 0.216187f, + 0.227905f, 0.239868f, 0.252441f, 0.264648f, 0.277100f, 0.289307f, 0.301270f, 0.314453f, 0.326660f, 0.338867f, 0.352539f, 0.364990f, + 0.377686f, 0.390137f, 0.403076f, 0.416016f, 0.428467f, 0.441406f, 0.453857f, 0.468262f, 0.480957f, 0.494385f, 0.507324f, 0.520020f, + 0.534180f, 0.547363f, 0.560059f, 0.573730f, 0.586914f, 0.601074f, 0.615234f, 0.628418f, 0.641602f, 0.656250f, 0.669434f, 0.683594f, + 0.697754f, 0.712402f, 0.832520f, 0.809570f, 0.792480f, 0.778320f, 0.764160f, 0.753906f, 0.004612f, 0.013840f, 0.023483f, 0.033081f, + 0.042999f, 0.052490f, 0.063049f, 0.073303f, 0.083801f, 0.094238f, 0.105042f, 0.115967f, 0.127319f, 0.138062f, 0.149048f, 0.160645f, + 0.171875f, 0.183228f, 0.194946f, 0.206665f, 0.218384f, 0.230347f, 0.241699f, 0.253906f, 0.265869f, 0.277832f, 0.290039f, 0.301758f, + 0.314209f, 0.326660f, 0.339111f, 0.351074f, 0.363281f, 0.375977f, 0.388428f, 0.401123f, 0.413330f, 0.426270f, 0.439453f, 0.451904f, + 0.464111f, 0.478027f, 0.489746f, 0.503418f, 0.515625f, 0.529297f, 0.542480f, 0.556152f, 0.569336f, 0.582031f, 0.595215f, 0.608887f, + 0.622559f, 0.636230f, 0.649902f, 0.663574f, 0.677246f, 0.691895f, 0.821289f, 0.802246f, 0.785645f, 0.771484f, 0.758789f, 0.748047f, + 0.004345f, 0.012985f, 0.022156f, 0.030884f, 0.040802f, 0.050568f, 0.060303f, 0.069946f, 0.079956f, 0.090393f, 0.100403f, 0.111084f, + 0.120667f, 0.131714f, 0.142700f, 0.153198f, 0.164429f, 0.175659f, 0.186523f, 0.197876f, 0.208496f, 0.220337f, 0.231567f, 0.243286f, + 0.254639f, 0.266113f, 0.277832f, 0.289795f, 0.301758f, 0.313477f, 0.325439f, 0.337402f, 0.349609f, 0.361328f, 0.373779f, 0.385986f, + 0.398193f, 0.410889f, 0.423340f, 0.435059f, 0.447998f, 0.460205f, 0.473389f, 0.486084f, 0.499023f, 0.511230f, 0.524414f, 0.537109f, + 0.549805f, 0.563477f, 0.576172f, 0.589355f, 0.603027f, 0.616699f, 0.629883f, 0.644531f, 0.658691f, 0.670898f, 0.811035f, 0.792969f, + 0.777832f, 0.764648f, 0.752441f, 0.742676f, 0.004002f, 0.012718f, 0.021210f, 0.029877f, 0.039246f, 0.048431f, 0.057281f, 0.067078f, + 0.076538f, 0.086121f, 0.096008f, 0.105957f, 0.115540f, 0.125732f, 0.136475f, 0.146729f, 0.157227f, 0.167236f, 0.177979f, 0.189819f, + 0.200195f, 0.210693f, 0.221802f, 0.232788f, 0.243896f, 0.255127f, 0.266602f, 0.278320f, 0.289062f, 0.300293f, 0.312012f, 0.323975f, + 0.335449f, 0.347168f, 0.359131f, 0.371094f, 0.382812f, 0.394775f, 0.406982f, 0.419434f, 0.431152f, 0.443604f, 0.455566f, 0.468506f, + 0.481445f, 0.493408f, 0.506348f, 0.519043f, 0.531738f, 0.544922f, 0.558105f, 0.570801f, 0.583984f, 0.597168f, 0.610352f, 0.624512f, + 0.637695f, 0.651855f, 0.800293f, 0.785156f, 0.770508f, 0.757812f, 0.747070f, 0.737305f, 0.003967f, 0.011940f, 0.020203f, 0.028931f, + 0.037109f, 0.045898f, 0.054840f, 0.063477f, 0.073059f, 0.082214f, 0.090942f, 0.100647f, 0.110535f, 0.120178f, 0.129639f, 0.139648f, + 0.149902f, 0.160156f, 0.170044f, 0.180786f, 0.190674f, 0.201416f, 0.211792f, 0.222412f, 0.233521f, 0.244751f, 0.255615f, 0.266113f, + 0.276855f, 0.288574f, 0.299561f, 0.311279f, 0.322266f, 0.333984f, 0.344727f, 0.356934f, 0.368164f, 0.379395f, 0.390869f, 0.403076f, + 0.415283f, 0.427246f, 0.439453f, 0.451172f, 0.464111f, 0.476807f, 0.488281f, 0.500977f, 0.513672f, 0.526367f, 0.538574f, 0.551758f, + 0.564453f, 0.577637f, 0.590820f, 0.604492f, 0.618164f, 0.631836f, 0.790039f, 0.775879f, 0.763184f, 0.750977f, 0.740723f, 0.731445f, + 0.003679f, 0.011749f, 0.019135f, 0.027237f, 0.035431f, 0.043884f, 0.052399f, 0.060577f, 0.069153f, 0.077881f, 0.086731f, 0.095947f, + 0.104797f, 0.114380f, 0.123535f, 0.133057f, 0.142700f, 0.152588f, 0.162231f, 0.171753f, 0.182129f, 0.192261f, 0.202026f, 0.212524f, + 0.222900f, 0.233643f, 0.243896f, 0.254395f, 0.264893f, 0.276123f, 0.286621f, 0.297119f, 0.308105f, 0.319336f, 0.331299f, 0.341553f, + 0.353027f, 0.364258f, 0.375977f, 0.387451f, 0.399414f, 0.410645f, 0.422607f, 0.434814f, 0.445801f, 0.458984f, 0.470703f, 0.482910f, + 0.495361f, 0.508301f, 0.520020f, 0.532227f, 0.545410f, 0.558594f, 0.570801f, 0.584961f, 0.597656f, 0.611816f, 0.778809f, 0.768066f, + 0.754883f, 0.743652f, 0.733887f, 0.725098f, 0.003525f, 0.010956f, 0.018433f, 0.026260f, 0.033295f, 0.041870f, 0.049377f, 0.057709f, + 0.065735f, 0.074463f, 0.082764f, 0.091736f, 0.099976f, 0.108582f, 0.118103f, 0.126465f, 0.135742f, 0.144775f, 0.154175f, 0.164307f, + 0.173218f, 0.182983f, 0.192505f, 0.202759f, 0.212646f, 0.221924f, 0.232910f, 0.242188f, 0.252930f, 0.262939f, 0.273926f, 0.284180f, + 0.294922f, 0.305420f, 0.316162f, 0.327637f, 0.338867f, 0.349609f, 0.361084f, 0.371826f, 0.382812f, 0.395020f, 0.406494f, 0.417725f, + 0.429688f, 0.441406f, 0.452637f, 0.465088f, 0.477783f, 0.489258f, 0.501953f, 0.514160f, 0.527344f, 0.539062f, 0.551758f, 0.564941f, + 0.578125f, 0.591797f, 0.768555f, 0.759277f, 0.748047f, 0.736816f, 0.728027f, 0.718750f, 0.003363f, 0.010353f, 0.017548f, 0.024765f, + 0.032196f, 0.039673f, 0.046936f, 0.054565f, 0.062561f, 0.070496f, 0.078308f, 0.086731f, 0.094910f, 0.103333f, 0.111633f, 0.120422f, + 0.129150f, 0.137695f, 0.146973f, 0.155762f, 0.164673f, 0.173950f, 0.183228f, 0.193359f, 0.201782f, 0.212036f, 0.221436f, 0.231323f, + 0.241699f, 0.251221f, 0.261719f, 0.271729f, 0.281494f, 0.291992f, 0.302734f, 0.312988f, 0.323730f, 0.334961f, 0.345459f, 0.357666f, + 0.367432f, 0.378662f, 0.389893f, 0.401855f, 0.412842f, 0.424316f, 0.435791f, 0.447266f, 0.459473f, 0.471436f, 0.482910f, 0.495605f, + 0.507324f, 0.520508f, 0.533203f, 0.545898f, 0.558594f, 0.570801f, 0.757812f, 0.750488f, 0.740234f, 0.729980f, 0.720703f, 0.712402f, + 0.003254f, 0.010048f, 0.016815f, 0.023453f, 0.030609f, 0.037537f, 0.044617f, 0.051971f, 0.059265f, 0.066833f, 0.074280f, 0.082153f, + 0.089905f, 0.097717f, 0.106018f, 0.113770f, 0.122131f, 0.131104f, 0.139282f, 0.147705f, 0.155762f, 0.165161f, 0.173950f, 0.183228f, + 0.192139f, 0.200928f, 0.210693f, 0.220093f, 0.229736f, 0.239258f, 0.248657f, 0.259277f, 0.268799f, 0.279053f, 0.288574f, 0.299561f, + 0.309814f, 0.319580f, 0.330322f, 0.340820f, 0.352783f, 0.362549f, 0.374023f, 0.385010f, 0.395752f, 0.407471f, 0.418701f, 0.429688f, + 0.441650f, 0.453125f, 0.465088f, 0.477539f, 0.489014f, 0.500977f, 0.513184f, 0.526855f, 0.539062f, 0.552246f, 0.747559f, 0.741699f, + 0.731934f, 0.722656f, 0.714355f, 0.707031f, 0.003345f, 0.009262f, 0.015900f, 0.022614f, 0.029282f, 0.035522f, 0.042633f, 0.048981f, + 0.056000f, 0.063110f, 0.070801f, 0.077454f, 0.084839f, 0.092590f, 0.100281f, 0.107849f, 0.116089f, 0.123169f, 0.131348f, 0.139648f, + 0.148193f, 0.156616f, 0.164795f, 0.173584f, 0.182617f, 0.191284f, 0.200073f, 0.208740f, 0.218140f, 0.227417f, 0.236694f, 0.246338f, + 0.255859f, 0.265381f, 0.275146f, 0.285889f, 0.294922f, 0.305420f, 0.315918f, 0.325928f, 0.336670f, 0.347412f, 0.358154f, 0.368652f, + 0.378662f, 0.390381f, 0.402100f, 0.412842f, 0.424316f, 0.435059f, 0.447021f, 0.458984f, 0.470459f, 0.482422f, 0.494873f, 0.508301f, + 0.520020f, 0.532227f, 0.737305f, 0.732910f, 0.723633f, 0.715820f, 0.708008f, 0.700195f, 0.003195f, 0.009010f, 0.015137f, 0.021225f, + 0.027466f, 0.033844f, 0.040161f, 0.046417f, 0.053497f, 0.059875f, 0.066711f, 0.073425f, 0.080505f, 0.087280f, 0.094788f, 0.102173f, + 0.109070f, 0.117004f, 0.124634f, 0.132446f, 0.139893f, 0.147705f, 0.155884f, 0.163940f, 0.172729f, 0.180908f, 0.189697f, 0.198242f, + 0.206665f, 0.215820f, 0.225220f, 0.233765f, 0.243408f, 0.251953f, 0.262207f, 0.271484f, 0.281494f, 0.291260f, 0.300537f, 0.311035f, + 0.320801f, 0.332520f, 0.341797f, 0.352051f, 0.362305f, 0.373535f, 0.384521f, 0.395264f, 0.406494f, 0.417480f, 0.429443f, 0.440430f, + 0.451904f, 0.463867f, 0.476074f, 0.487793f, 0.499268f, 0.513184f, 0.726562f, 0.723633f, 0.716309f, 0.708496f, 0.700684f, 0.694336f, + 0.002859f, 0.008507f, 0.014366f, 0.020203f, 0.026123f, 0.031891f, 0.038025f, 0.044281f, 0.050354f, 0.056519f, 0.062683f, 0.069275f, + 0.075195f, 0.082458f, 0.088806f, 0.095947f, 0.102783f, 0.110046f, 0.117065f, 0.124878f, 0.132080f, 0.139282f, 0.146851f, 0.154907f, + 0.162598f, 0.171265f, 0.178833f, 0.187500f, 0.195435f, 0.204590f, 0.213013f, 0.221680f, 0.231079f, 0.239502f, 0.248047f, 0.258301f, + 0.267334f, 0.277100f, 0.286133f, 0.296387f, 0.306641f, 0.316162f, 0.326416f, 0.336426f, 0.346924f, 0.357422f, 0.367188f, 0.378418f, + 0.389160f, 0.400391f, 0.411865f, 0.422852f, 0.433594f, 0.445557f, 0.457520f, 0.468994f, 0.481445f, 0.493408f, 0.715332f, 0.715332f, + 0.708984f, 0.700684f, 0.693848f, 0.687988f, 0.002701f, 0.008080f, 0.013718f, 0.019058f, 0.024582f, 0.030197f, 0.035675f, 0.041748f, + 0.047302f, 0.053589f, 0.059082f, 0.065308f, 0.071777f, 0.077576f, 0.084106f, 0.090332f, 0.097107f, 0.103577f, 0.110046f, 0.117493f, + 0.124146f, 0.131470f, 0.138550f, 0.145508f, 0.153564f, 0.161377f, 0.169067f, 0.176880f, 0.184814f, 0.192627f, 0.201294f, 0.209717f, + 0.218140f, 0.226929f, 0.235229f, 0.245117f, 0.253418f, 0.262939f, 0.272705f, 0.281738f, 0.290771f, 0.300781f, 0.310791f, 0.321289f, + 0.330566f, 0.341064f, 0.351562f, 0.361572f, 0.372559f, 0.382568f, 0.393066f, 0.405273f, 0.415771f, 0.426758f, 0.438721f, 0.450439f, + 0.461670f, 0.474121f, 0.704102f, 0.706543f, 0.700195f, 0.693359f, 0.687012f, 0.681152f, 0.002546f, 0.007771f, 0.012985f, 0.017975f, + 0.023392f, 0.028976f, 0.034180f, 0.039368f, 0.044556f, 0.050110f, 0.055847f, 0.061218f, 0.066895f, 0.072815f, 0.078674f, 0.085083f, + 0.091309f, 0.097168f, 0.103516f, 0.110107f, 0.116821f, 0.123413f, 0.130371f, 0.137329f, 0.144165f, 0.151733f, 0.158813f, 0.166382f, + 0.174438f, 0.182129f, 0.190063f, 0.197510f, 0.206055f, 0.214355f, 0.222778f, 0.231812f, 0.240723f, 0.249023f, 0.258789f, 0.267578f, + 0.276855f, 0.285889f, 0.295654f, 0.305420f, 0.315430f, 0.324463f, 0.334961f, 0.345215f, 0.354492f, 0.365234f, 0.376221f, 0.387451f, + 0.398926f, 0.409424f, 0.419678f, 0.432129f, 0.443848f, 0.455566f, 0.693848f, 0.697266f, 0.691895f, 0.686523f, 0.680176f, 0.674805f, + 0.002542f, 0.007271f, 0.012337f, 0.017181f, 0.021744f, 0.026840f, 0.031555f, 0.037231f, 0.042236f, 0.046906f, 0.051941f, 0.057709f, + 0.063049f, 0.068542f, 0.073853f, 0.079712f, 0.085266f, 0.091064f, 0.096985f, 0.103027f, 0.109009f, 0.115417f, 0.122192f, 0.128540f, + 0.135132f, 0.141846f, 0.148926f, 0.156250f, 0.163696f, 0.171387f, 0.178223f, 0.186035f, 0.194580f, 0.202271f, 0.210327f, 0.218994f, + 0.227173f, 0.235596f, 0.244385f, 0.252930f, 0.262451f, 0.271240f, 0.280762f, 0.290771f, 0.299805f, 0.309082f, 0.318359f, 0.329102f, + 0.338623f, 0.348633f, 0.358643f, 0.370117f, 0.379639f, 0.390869f, 0.401611f, 0.413330f, 0.425293f, 0.436523f, 0.682129f, 0.688477f, + 0.684082f, 0.678711f, 0.673340f, 0.667969f, 0.002300f, 0.007076f, 0.011505f, 0.016251f, 0.020401f, 0.025665f, 0.029816f, 0.034790f, + 0.039368f, 0.044159f, 0.048798f, 0.053955f, 0.059174f, 0.064148f, 0.069153f, 0.074463f, 0.079346f, 0.085266f, 0.090759f, 0.096191f, + 0.102112f, 0.108032f, 0.114075f, 0.120117f, 0.126587f, 0.133057f, 0.139648f, 0.146240f, 0.153442f, 0.160400f, 0.167725f, 0.174683f, + 0.182739f, 0.190308f, 0.198120f, 0.206177f, 0.214355f, 0.222656f, 0.230713f, 0.239258f, 0.248413f, 0.257080f, 0.265869f, 0.274658f, + 0.284424f, 0.292725f, 0.302490f, 0.313232f, 0.321777f, 0.331787f, 0.341797f, 0.352295f, 0.363281f, 0.373535f, 0.383545f, 0.395264f, + 0.405762f, 0.416992f, 0.671387f, 0.679688f, 0.675293f, 0.670898f, 0.666016f, 0.661133f, 0.002104f, 0.006474f, 0.010506f, 0.015099f, + 0.018875f, 0.023911f, 0.028534f, 0.032715f, 0.036652f, 0.041290f, 0.046021f, 0.050171f, 0.054535f, 0.059570f, 0.064575f, 0.069458f, + 0.074341f, 0.079346f, 0.084351f, 0.089844f, 0.095032f, 0.100830f, 0.106628f, 0.112122f, 0.117859f, 0.124084f, 0.130249f, 0.136841f, + 0.143188f, 0.149780f, 0.157349f, 0.163940f, 0.171021f, 0.178345f, 0.186279f, 0.193848f, 0.201172f, 0.209717f, 0.217529f, 0.225464f, + 0.233765f, 0.242676f, 0.251221f, 0.260254f, 0.268311f, 0.278076f, 0.287109f, 0.296143f, 0.305908f, 0.315674f, 0.325195f, 0.335449f, + 0.344971f, 0.355469f, 0.365967f, 0.377441f, 0.387939f, 0.398193f, 0.660645f, 0.670410f, 0.667969f, 0.663086f, 0.659180f, 0.654785f, + 0.002085f, 0.006306f, 0.010506f, 0.014107f, 0.018448f, 0.022293f, 0.026215f, 0.029953f, 0.034515f, 0.038391f, 0.042786f, 0.046844f, + 0.051361f, 0.055573f, 0.059784f, 0.064331f, 0.068970f, 0.073425f, 0.078430f, 0.083313f, 0.088318f, 0.093567f, 0.098816f, 0.104126f, + 0.109924f, 0.115662f, 0.121521f, 0.127197f, 0.133545f, 0.139771f, 0.146729f, 0.153076f, 0.160278f, 0.166992f, 0.174316f, 0.181274f, + 0.188965f, 0.196045f, 0.204468f, 0.212036f, 0.220459f, 0.228638f, 0.237183f, 0.245483f, 0.254150f, 0.262451f, 0.271484f, 0.281250f, + 0.290283f, 0.299561f, 0.308350f, 0.318115f, 0.328369f, 0.337158f, 0.349121f, 0.358887f, 0.370117f, 0.380615f, 0.649414f, 0.661133f, + 0.659668f, 0.655762f, 0.651855f, 0.647949f, 0.001922f, 0.005867f, 0.009399f, 0.013565f, 0.017380f, 0.020859f, 0.024551f, 0.028442f, + 0.032318f, 0.035980f, 0.039551f, 0.043488f, 0.047333f, 0.051239f, 0.055573f, 0.059875f, 0.063660f, 0.067810f, 0.072876f, 0.077087f, + 0.081726f, 0.086304f, 0.091370f, 0.096863f, 0.101746f, 0.107483f, 0.112732f, 0.117920f, 0.124329f, 0.130005f, 0.136108f, 0.142822f, + 0.149170f, 0.155396f, 0.162598f, 0.169434f, 0.176636f, 0.183838f, 0.191772f, 0.198975f, 0.206665f, 0.214478f, 0.222290f, 0.230835f, + 0.239258f, 0.247803f, 0.256836f, 0.264893f, 0.274414f, 0.283203f, 0.292725f, 0.301758f, 0.311035f, 0.321289f, 0.332275f, 0.340820f, + 0.351562f, 0.363037f, 0.637695f, 0.652832f, 0.651367f, 0.647949f, 0.644531f, 0.641602f, 0.002052f, 0.005253f, 0.009117f, 0.012482f, + 0.016113f, 0.019302f, 0.022842f, 0.026230f, 0.029831f, 0.033447f, 0.036682f, 0.040588f, 0.044189f, 0.047333f, 0.051178f, 0.055267f, + 0.058807f, 0.062683f, 0.067200f, 0.070984f, 0.075195f, 0.079895f, 0.084534f, 0.088806f, 0.093933f, 0.098999f, 0.104309f, 0.109619f, + 0.114807f, 0.120422f, 0.126587f, 0.132080f, 0.138550f, 0.144775f, 0.151245f, 0.157837f, 0.164551f, 0.171387f, 0.178467f, 0.186157f, + 0.193359f, 0.201294f, 0.208740f, 0.216797f, 0.224854f, 0.233398f, 0.241211f, 0.250000f, 0.258545f, 0.267822f, 0.276855f, 0.286133f, + 0.295410f, 0.304932f, 0.314697f, 0.324463f, 0.334229f, 0.344238f, 0.626953f, 0.642578f, 0.643066f, 0.641113f, 0.637695f, 0.634277f, + 0.001711f, 0.005424f, 0.008347f, 0.012024f, 0.014977f, 0.018066f, 0.021500f, 0.024399f, 0.027756f, 0.030869f, 0.034058f, 0.037048f, + 0.040558f, 0.044006f, 0.046906f, 0.050690f, 0.054169f, 0.057983f, 0.061584f, 0.065247f, 0.069336f, 0.073425f, 0.077576f, 0.082092f, + 0.086670f, 0.091064f, 0.095886f, 0.101196f, 0.105957f, 0.111267f, 0.116943f, 0.122559f, 0.128174f, 0.133789f, 0.140259f, 0.146118f, + 0.153076f, 0.159424f, 0.166016f, 0.173462f, 0.180542f, 0.187744f, 0.195435f, 0.203003f, 0.209961f, 0.218994f, 0.226562f, 0.234619f, + 0.243286f, 0.251709f, 0.260742f, 0.269531f, 0.277832f, 0.287354f, 0.297363f, 0.306885f, 0.316406f, 0.326660f, 0.615234f, 0.633789f, + 0.634277f, 0.632812f, 0.630371f, 0.626953f, 0.001721f, 0.004829f, 0.008034f, 0.010857f, 0.013893f, 0.016953f, 0.019806f, 0.022705f, + 0.025589f, 0.028793f, 0.031616f, 0.034180f, 0.036926f, 0.039978f, 0.043213f, 0.046356f, 0.049744f, 0.052887f, 0.056305f, 0.059906f, + 0.063416f, 0.067322f, 0.070862f, 0.075134f, 0.079285f, 0.083435f, 0.088074f, 0.092712f, 0.097534f, 0.102173f, 0.107544f, 0.112305f, + 0.118225f, 0.123657f, 0.129272f, 0.135376f, 0.141602f, 0.147705f, 0.153931f, 0.160889f, 0.167847f, 0.174683f, 0.181885f, 0.189209f, + 0.196533f, 0.204224f, 0.212524f, 0.219727f, 0.228271f, 0.236572f, 0.245483f, 0.253418f, 0.261719f, 0.270996f, 0.280029f, 0.289307f, + 0.300537f, 0.309326f, 0.604004f, 0.625000f, 0.626953f, 0.625000f, 0.622559f, 0.620117f, 0.001624f, 0.004730f, 0.007412f, 0.010300f, + 0.013199f, 0.015717f, 0.018448f, 0.020935f, 0.023163f, 0.026138f, 0.028687f, 0.031204f, 0.033875f, 0.036743f, 0.039825f, 0.042389f, + 0.045166f, 0.048523f, 0.051422f, 0.054535f, 0.057953f, 0.061249f, 0.064880f, 0.068542f, 0.072388f, 0.076355f, 0.080505f, 0.084534f, + 0.089294f, 0.093750f, 0.098389f, 0.103210f, 0.108337f, 0.113647f, 0.118896f, 0.124817f, 0.130737f, 0.135986f, 0.142212f, 0.148560f, + 0.155151f, 0.162109f, 0.168579f, 0.175415f, 0.183105f, 0.190552f, 0.197998f, 0.205322f, 0.213623f, 0.221436f, 0.229370f, 0.237915f, + 0.246216f, 0.254883f, 0.264160f, 0.273438f, 0.282471f, 0.292236f, 0.593262f, 0.615723f, 0.618164f, 0.617188f, 0.615234f, 0.612793f, + 0.001355f, 0.004463f, 0.007061f, 0.009506f, 0.011612f, 0.014381f, 0.016830f, 0.019394f, 0.021576f, 0.023697f, 0.026428f, 0.028778f, + 0.030975f, 0.033386f, 0.035950f, 0.038513f, 0.041260f, 0.044067f, 0.046967f, 0.049622f, 0.052612f, 0.055847f, 0.059052f, 0.062164f, + 0.065918f, 0.069397f, 0.073242f, 0.077271f, 0.081055f, 0.085327f, 0.089661f, 0.094177f, 0.098877f, 0.103455f, 0.108582f, 0.113647f, + 0.119812f, 0.125000f, 0.130981f, 0.137085f, 0.142944f, 0.149414f, 0.156006f, 0.162354f, 0.169434f, 0.176514f, 0.183716f, 0.191284f, + 0.198975f, 0.206421f, 0.214844f, 0.222412f, 0.231323f, 0.238647f, 0.247437f, 0.256592f, 0.265625f, 0.276367f, 0.581055f, 0.606445f, + 0.609863f, 0.608887f, 0.607910f, 0.606445f, 0.001413f, 0.004128f, 0.006180f, 0.008781f, 0.010994f, 0.013496f, 0.015427f, 0.017654f, + 0.019684f, 0.021881f, 0.024139f, 0.025879f, 0.028137f, 0.030334f, 0.032471f, 0.034821f, 0.037354f, 0.039642f, 0.042236f, 0.044708f, + 0.047394f, 0.050079f, 0.053223f, 0.056244f, 0.059479f, 0.062622f, 0.066223f, 0.069946f, 0.073608f, 0.077209f, 0.081604f, 0.085632f, + 0.089722f, 0.094360f, 0.098999f, 0.103943f, 0.108826f, 0.114319f, 0.119568f, 0.125122f, 0.131104f, 0.137085f, 0.143433f, 0.150024f, + 0.156494f, 0.163330f, 0.170044f, 0.177490f, 0.184326f, 0.191895f, 0.199707f, 0.207764f, 0.215698f, 0.223755f, 0.231812f, 0.240845f, + 0.249756f, 0.258789f, 0.568848f, 0.598145f, 0.601562f, 0.600586f, 0.600586f, 0.599121f, 0.001182f, 0.003773f, 0.005970f, 0.008293f, + 0.010277f, 0.012512f, 0.014030f, 0.016129f, 0.017929f, 0.019791f, 0.021683f, 0.023590f, 0.025452f, 0.027328f, 0.029404f, 0.031677f, + 0.033539f, 0.035583f, 0.037903f, 0.040314f, 0.042877f, 0.045319f, 0.048126f, 0.050690f, 0.053436f, 0.056519f, 0.059723f, 0.062744f, + 0.066284f, 0.069702f, 0.073608f, 0.077209f, 0.081055f, 0.085754f, 0.089783f, 0.094421f, 0.099060f, 0.103821f, 0.109192f, 0.114563f, + 0.119934f, 0.125488f, 0.131104f, 0.137695f, 0.144043f, 0.149780f, 0.156738f, 0.163940f, 0.170654f, 0.177856f, 0.185181f, 0.192871f, + 0.200439f, 0.208740f, 0.216675f, 0.225342f, 0.233521f, 0.242554f, 0.557617f, 0.587891f, 0.592285f, 0.592773f, 0.592285f, 0.592285f, + 0.001198f, 0.003677f, 0.005547f, 0.007561f, 0.009468f, 0.011253f, 0.012833f, 0.014465f, 0.016205f, 0.017792f, 0.019394f, 0.021240f, + 0.022751f, 0.024475f, 0.026260f, 0.028015f, 0.030136f, 0.031708f, 0.034088f, 0.036102f, 0.038361f, 0.040497f, 0.042816f, 0.045288f, + 0.047882f, 0.050476f, 0.053284f, 0.056183f, 0.059174f, 0.062500f, 0.065796f, 0.069153f, 0.072998f, 0.076904f, 0.080994f, 0.085083f, + 0.089478f, 0.094116f, 0.098633f, 0.103394f, 0.108704f, 0.113953f, 0.119934f, 0.125366f, 0.131348f, 0.137329f, 0.143555f, 0.150391f, + 0.157227f, 0.163818f, 0.170776f, 0.178467f, 0.185791f, 0.193359f, 0.201538f, 0.209717f, 0.218018f, 0.226807f, 0.544922f, 0.578613f, + 0.583984f, 0.584961f, 0.585449f, 0.584473f, 0.001067f, 0.003101f, 0.004974f, 0.006855f, 0.008522f, 0.009949f, 0.011635f, 0.012985f, + 0.014595f, 0.016052f, 0.017685f, 0.019012f, 0.020264f, 0.021851f, 0.023346f, 0.025146f, 0.026688f, 0.028336f, 0.030304f, 0.031860f, + 0.034119f, 0.035889f, 0.038025f, 0.040283f, 0.042450f, 0.044952f, 0.047302f, 0.050049f, 0.052765f, 0.055908f, 0.058594f, 0.061859f, + 0.064880f, 0.068481f, 0.072327f, 0.076172f, 0.080200f, 0.084290f, 0.088684f, 0.093262f, 0.098145f, 0.102905f, 0.108337f, 0.113708f, + 0.119080f, 0.125000f, 0.131348f, 0.137329f, 0.143921f, 0.150391f, 0.157593f, 0.164551f, 0.171753f, 0.179077f, 0.186768f, 0.194702f, + 0.203003f, 0.210815f, 0.534180f, 0.569336f, 0.575684f, 0.577637f, 0.577637f, 0.577148f, 0.001196f, 0.003178f, 0.004601f, 0.006241f, + 0.007782f, 0.009262f, 0.010391f, 0.011795f, 0.012955f, 0.014198f, 0.015518f, 0.016785f, 0.018097f, 0.019409f, 0.020782f, 0.022247f, + 0.023544f, 0.025269f, 0.026749f, 0.028152f, 0.030045f, 0.031555f, 0.033630f, 0.035645f, 0.037567f, 0.039642f, 0.041992f, 0.044281f, + 0.046692f, 0.049042f, 0.052094f, 0.054779f, 0.057831f, 0.060760f, 0.064209f, 0.067627f, 0.071228f, 0.075256f, 0.079224f, 0.083557f, + 0.087891f, 0.092468f, 0.097168f, 0.102356f, 0.107605f, 0.113098f, 0.119019f, 0.124878f, 0.130859f, 0.137451f, 0.144287f, 0.150635f, + 0.157471f, 0.164917f, 0.171997f, 0.179932f, 0.187378f, 0.196899f, 0.521973f, 0.560547f, 0.566895f, 0.569824f, 0.570312f, 0.568848f, + 0.001242f, 0.002674f, 0.004421f, 0.005573f, 0.006882f, 0.008354f, 0.009491f, 0.010559f, 0.011406f, 0.012695f, 0.013893f, 0.014908f, + 0.015854f, 0.017044f, 0.018234f, 0.019501f, 0.020752f, 0.022003f, 0.023254f, 0.024689f, 0.026154f, 0.027802f, 0.029434f, 0.031113f, + 0.032898f, 0.034668f, 0.036774f, 0.038910f, 0.040802f, 0.043030f, 0.045593f, 0.048065f, 0.050873f, 0.053680f, 0.056458f, 0.059692f, + 0.062866f, 0.066467f, 0.069946f, 0.074036f, 0.077942f, 0.082275f, 0.086731f, 0.091614f, 0.096313f, 0.101562f, 0.106934f, 0.112671f, + 0.118591f, 0.124634f, 0.130859f, 0.137207f, 0.144043f, 0.151123f, 0.157593f, 0.165283f, 0.173218f, 0.180664f, 0.510254f, 0.550781f, + 0.558105f, 0.561035f, 0.562012f, 0.562012f, 0.000842f, 0.002552f, 0.003769f, 0.005333f, 0.006149f, 0.007298f, 0.008362f, 0.009224f, + 0.010254f, 0.011230f, 0.012108f, 0.013092f, 0.014000f, 0.014992f, 0.016006f, 0.016953f, 0.017990f, 0.019196f, 0.020142f, 0.021622f, + 0.022827f, 0.024216f, 0.025513f, 0.026993f, 0.028564f, 0.030212f, 0.032013f, 0.033813f, 0.035706f, 0.037598f, 0.039703f, 0.041840f, + 0.044159f, 0.046539f, 0.049347f, 0.052155f, 0.055084f, 0.058228f, 0.061554f, 0.065002f, 0.068909f, 0.072693f, 0.076599f, 0.081238f, + 0.085388f, 0.090515f, 0.095764f, 0.100891f, 0.106689f, 0.112366f, 0.118103f, 0.124634f, 0.130859f, 0.137573f, 0.144287f, 0.151855f, + 0.158447f, 0.166260f, 0.498535f, 0.541992f, 0.549805f, 0.553711f, 0.554199f, 0.554688f, 0.000874f, 0.002186f, 0.003445f, 0.004807f, + 0.005562f, 0.006607f, 0.007378f, 0.008102f, 0.008919f, 0.009666f, 0.010513f, 0.011131f, 0.012039f, 0.012848f, 0.013779f, 0.014671f, + 0.015465f, 0.016464f, 0.017517f, 0.018585f, 0.019730f, 0.020798f, 0.022018f, 0.023300f, 0.024612f, 0.026093f, 0.027374f, 0.029022f, + 0.030624f, 0.032440f, 0.034180f, 0.036285f, 0.038116f, 0.040344f, 0.042725f, 0.045349f, 0.047913f, 0.050476f, 0.053406f, 0.056488f, + 0.059998f, 0.063354f, 0.067383f, 0.071289f, 0.075562f, 0.079834f, 0.084656f, 0.089478f, 0.094849f, 0.100342f, 0.106140f, 0.111877f, + 0.118042f, 0.124573f, 0.130981f, 0.137451f, 0.144653f, 0.152588f, 0.486816f, 0.531738f, 0.541016f, 0.545410f, 0.547363f, 0.546875f, + 0.000667f, 0.002001f, 0.003244f, 0.003895f, 0.004936f, 0.005608f, 0.006477f, 0.006901f, 0.007648f, 0.008354f, 0.009132f, 0.009766f, + 0.010490f, 0.011177f, 0.011780f, 0.012543f, 0.013420f, 0.014084f, 0.015045f, 0.015961f, 0.016876f, 0.017822f, 0.018768f, 0.019958f, + 0.021255f, 0.022232f, 0.023560f, 0.024780f, 0.026108f, 0.027634f, 0.029221f, 0.030762f, 0.032684f, 0.034576f, 0.036621f, 0.038605f, + 0.040985f, 0.043488f, 0.046021f, 0.049042f, 0.051727f, 0.054901f, 0.058441f, 0.061981f, 0.065552f, 0.069885f, 0.074097f, 0.078857f, + 0.083923f, 0.088623f, 0.094360f, 0.099854f, 0.105957f, 0.111694f, 0.118164f, 0.124817f, 0.131836f, 0.138794f, 0.474365f, 0.522949f, + 0.532227f, 0.536621f, 0.538574f, 0.539062f, 0.000876f, 0.002020f, 0.002857f, 0.003855f, 0.004436f, 0.005009f, 0.005482f, 0.006130f, + 0.006588f, 0.007084f, 0.007656f, 0.008286f, 0.008949f, 0.009506f, 0.010025f, 0.010803f, 0.011444f, 0.012047f, 0.012802f, 0.013512f, + 0.014305f, 0.015282f, 0.016052f, 0.016846f, 0.017914f, 0.018829f, 0.019882f, 0.021027f, 0.022232f, 0.023453f, 0.024689f, 0.026169f, + 0.027573f, 0.029327f, 0.031036f, 0.032806f, 0.034882f, 0.036743f, 0.039032f, 0.041626f, 0.044312f, 0.046936f, 0.050018f, 0.053253f, + 0.056610f, 0.060272f, 0.064392f, 0.068542f, 0.072937f, 0.078003f, 0.082886f, 0.088318f, 0.093933f, 0.099670f, 0.106140f, 0.112000f, + 0.118713f, 0.125732f, 0.463135f, 0.513672f, 0.524414f, 0.528809f, 0.530762f, 0.532227f, 0.000573f, 0.001698f, 0.002670f, 0.003082f, + 0.003735f, 0.004318f, 0.004673f, 0.005161f, 0.005779f, 0.006203f, 0.006565f, 0.007015f, 0.007591f, 0.007965f, 0.008583f, 0.009094f, + 0.009491f, 0.010239f, 0.010780f, 0.011353f, 0.012047f, 0.012787f, 0.013504f, 0.014206f, 0.015060f, 0.015915f, 0.016708f, 0.017685f, + 0.018677f, 0.019653f, 0.020828f, 0.021866f, 0.023224f, 0.024445f, 0.025818f, 0.027557f, 0.029114f, 0.030991f, 0.032928f, 0.035034f, + 0.037201f, 0.039581f, 0.042328f, 0.045166f, 0.048157f, 0.051392f, 0.054962f, 0.058685f, 0.062988f, 0.067444f, 0.072021f, 0.077148f, + 0.082520f, 0.088196f, 0.093750f, 0.100403f, 0.106201f, 0.112976f, 0.450928f, 0.503906f, 0.515137f, 0.520020f, 0.522949f, 0.524414f, + 0.000643f, 0.001637f, 0.002197f, 0.002800f, 0.003376f, 0.003613f, 0.003914f, 0.004391f, 0.004742f, 0.005150f, 0.005466f, 0.005924f, + 0.006344f, 0.006645f, 0.007046f, 0.007591f, 0.008118f, 0.008560f, 0.008934f, 0.009529f, 0.010147f, 0.010651f, 0.011276f, 0.011787f, + 0.012543f, 0.013229f, 0.013916f, 0.014740f, 0.015564f, 0.016388f, 0.017258f, 0.018188f, 0.019257f, 0.020355f, 0.021729f, 0.022766f, + 0.024277f, 0.025696f, 0.027237f, 0.029022f, 0.030945f, 0.033020f, 0.035248f, 0.037689f, 0.040405f, 0.043182f, 0.046295f, 0.049866f, + 0.053528f, 0.057526f, 0.061920f, 0.066284f, 0.071716f, 0.077209f, 0.082703f, 0.088196f, 0.094177f, 0.101074f, 0.438965f, 0.494629f, + 0.507324f, 0.512207f, 0.515137f, 0.516113f, 0.000484f, 0.001272f, 0.001968f, 0.002327f, 0.002573f, 0.003054f, 0.003338f, 0.003660f, + 0.003906f, 0.004303f, 0.004658f, 0.004921f, 0.005222f, 0.005547f, 0.005878f, 0.006290f, 0.006542f, 0.007015f, 0.007442f, 0.007851f, + 0.008339f, 0.008713f, 0.009247f, 0.009811f, 0.010345f, 0.010849f, 0.011490f, 0.012123f, 0.012733f, 0.013428f, 0.014183f, 0.014961f, + 0.015839f, 0.016815f, 0.017731f, 0.018768f, 0.019821f, 0.021072f, 0.022385f, 0.023727f, 0.025345f, 0.027084f, 0.028946f, 0.030914f, + 0.033295f, 0.035614f, 0.038513f, 0.041473f, 0.044678f, 0.048462f, 0.052338f, 0.056671f, 0.061310f, 0.066101f, 0.071533f, 0.077148f, + 0.083069f, 0.089172f, 0.427246f, 0.485352f, 0.498535f, 0.503906f, 0.508301f, 0.509766f, 0.000416f, 0.001121f, 0.001410f, 0.001959f, + 0.002159f, 0.002558f, 0.002724f, 0.002939f, 0.003220f, 0.003447f, 0.003733f, 0.003944f, 0.004219f, 0.004578f, 0.004810f, 0.005100f, + 0.005402f, 0.005783f, 0.006077f, 0.006382f, 0.006729f, 0.007141f, 0.007526f, 0.007965f, 0.008354f, 0.008858f, 0.009300f, 0.009789f, + 0.010452f, 0.010986f, 0.011658f, 0.012131f, 0.012833f, 0.013702f, 0.014435f, 0.015266f, 0.016113f, 0.017136f, 0.018143f, 0.019241f, + 0.020493f, 0.021820f, 0.023346f, 0.025085f, 0.027023f, 0.028976f, 0.031174f, 0.033966f, 0.036743f, 0.039856f, 0.043396f, 0.047180f, + 0.051605f, 0.056152f, 0.061127f, 0.066284f, 0.072021f, 0.078247f, 0.415283f, 0.475586f, 0.490234f, 0.496338f, 0.499756f, 0.501953f, + 0.000493f, 0.001126f, 0.001391f, 0.001574f, 0.001786f, 0.002073f, 0.002188f, 0.002417f, 0.002657f, 0.002785f, 0.002964f, 0.003189f, + 0.003384f, 0.003687f, 0.003859f, 0.004124f, 0.004330f, 0.004555f, 0.004890f, 0.005119f, 0.005451f, 0.005749f, 0.006054f, 0.006348f, + 0.006683f, 0.007050f, 0.007458f, 0.007889f, 0.008339f, 0.008751f, 0.009323f, 0.009766f, 0.010353f, 0.010887f, 0.011520f, 0.012192f, + 0.012932f, 0.013748f, 0.014542f, 0.015434f, 0.016434f, 0.017471f, 0.018723f, 0.019989f, 0.021500f, 0.023117f, 0.024948f, 0.027100f, + 0.029770f, 0.032166f, 0.035248f, 0.038696f, 0.042633f, 0.046875f, 0.051605f, 0.056427f, 0.061859f, 0.067688f, 0.403320f, 0.467041f, + 0.480957f, 0.487793f, 0.491699f, 0.494385f, 0.000336f, 0.000673f, 0.001150f, 0.001274f, 0.001482f, 0.001630f, 0.001748f, 0.001904f, + 0.002087f, 0.002232f, 0.002306f, 0.002497f, 0.002672f, 0.002872f, 0.003092f, 0.003225f, 0.003387f, 0.003553f, 0.003819f, 0.003979f, + 0.004230f, 0.004517f, 0.004738f, 0.005016f, 0.005322f, 0.005569f, 0.005848f, 0.006184f, 0.006573f, 0.006851f, 0.007271f, 0.007660f, + 0.008064f, 0.008568f, 0.009048f, 0.009567f, 0.010139f, 0.010788f, 0.011391f, 0.012161f, 0.012939f, 0.013763f, 0.014694f, 0.015717f, + 0.016815f, 0.018097f, 0.019714f, 0.021149f, 0.023270f, 0.025421f, 0.028015f, 0.030991f, 0.034271f, 0.038116f, 0.042328f, 0.046997f, + 0.052094f, 0.057770f, 0.391113f, 0.457031f, 0.472412f, 0.479736f, 0.484375f, 0.486816f, 0.000309f, 0.000612f, 0.000953f, 0.001086f, + 0.001191f, 0.001281f, 0.001351f, 0.001442f, 0.001610f, 0.001733f, 0.001783f, 0.001991f, 0.002087f, 0.002232f, 0.002337f, 0.002495f, + 0.002611f, 0.002775f, 0.002935f, 0.003101f, 0.003302f, 0.003496f, 0.003622f, 0.003839f, 0.004047f, 0.004265f, 0.004494f, 0.004738f, + 0.005039f, 0.005272f, 0.005650f, 0.005898f, 0.006210f, 0.006588f, 0.006950f, 0.007332f, 0.007782f, 0.008240f, 0.008766f, 0.009331f, + 0.009964f, 0.010612f, 0.011314f, 0.012062f, 0.013023f, 0.014038f, 0.015007f, 0.016251f, 0.017761f, 0.019501f, 0.021530f, 0.023926f, + 0.026718f, 0.030106f, 0.033905f, 0.038361f, 0.043060f, 0.048370f, 0.379395f, 0.446777f, 0.464111f, 0.471191f, 0.475586f, 0.479492f, + 0.000439f, 0.000476f, 0.000672f, 0.000752f, 0.000810f, 0.000949f, 0.001011f, 0.001121f, 0.001160f, 0.001249f, 0.001408f, 0.001493f, + 0.001591f, 0.001719f, 0.001788f, 0.001845f, 0.001982f, 0.002106f, 0.002201f, 0.002357f, 0.002460f, 0.002598f, 0.002724f, 0.002869f, + 0.003036f, 0.003187f, 0.003397f, 0.003569f, 0.003763f, 0.004017f, 0.004211f, 0.004414f, 0.004704f, 0.004890f, 0.005234f, 0.005524f, + 0.005825f, 0.006187f, 0.006535f, 0.006977f, 0.007423f, 0.007874f, 0.008553f, 0.009079f, 0.009857f, 0.010567f, 0.011360f, 0.012306f, + 0.013390f, 0.014702f, 0.016220f, 0.017960f, 0.020157f, 0.022995f, 0.026352f, 0.030212f, 0.034790f, 0.039459f, 0.368408f, 0.437744f, + 0.455322f, 0.463379f, 0.468018f, 0.471436f, 0.000202f, 0.000437f, 0.000488f, 0.000579f, 0.000664f, 0.000692f, 0.000792f, 0.000762f, + 0.000875f, 0.000949f, 0.001038f, 0.001068f, 0.001116f, 0.001196f, 0.001300f, 0.001352f, 0.001458f, 0.001529f, 0.001623f, 0.001667f, + 0.001770f, 0.001884f, 0.001989f, 0.002071f, 0.002203f, 0.002310f, 0.002445f, 0.002556f, 0.002680f, 0.002876f, 0.002991f, 0.003206f, + 0.003365f, 0.003531f, 0.003759f, 0.003956f, 0.004227f, 0.004513f, 0.004768f, 0.005074f, 0.005402f, 0.005756f, 0.006142f, 0.006603f, + 0.007160f, 0.007645f, 0.008339f, 0.008987f, 0.009819f, 0.010780f, 0.011803f, 0.013153f, 0.014763f, 0.016876f, 0.019623f, 0.022995f, + 0.026978f, 0.031708f, 0.356445f, 0.428223f, 0.446533f, 0.455078f, 0.460449f, 0.463379f, 0.000126f, 0.000241f, 0.000344f, 0.000353f, + 0.000437f, 0.000522f, 0.000513f, 0.000552f, 0.000613f, 0.000699f, 0.000717f, 0.000727f, 0.000763f, 0.000848f, 0.000877f, 0.000956f, + 0.000963f, 0.001068f, 0.001128f, 0.001170f, 0.001238f, 0.001311f, 0.001385f, 0.001454f, 0.001534f, 0.001603f, 0.001714f, 0.001779f, + 0.001885f, 0.002016f, 0.002092f, 0.002214f, 0.002331f, 0.002460f, 0.002613f, 0.002777f, 0.002924f, 0.003120f, 0.003298f, 0.003496f, + 0.003708f, 0.004009f, 0.004292f, 0.004601f, 0.004951f, 0.005341f, 0.005772f, 0.006260f, 0.006901f, 0.007572f, 0.008324f, 0.009300f, + 0.010445f, 0.011848f, 0.013870f, 0.016678f, 0.020218f, 0.024536f, 0.345703f, 0.419189f, 0.437500f, 0.447021f, 0.452393f, 0.455811f, + 0.000146f, 0.000240f, 0.000268f, 0.000268f, 0.000310f, 0.000311f, 0.000331f, 0.000366f, 0.000410f, 0.000447f, 0.000446f, 0.000517f, + 0.000511f, 0.000571f, 0.000596f, 0.000618f, 0.000674f, 0.000691f, 0.000723f, 0.000762f, 0.000822f, 0.000856f, 0.000912f, 0.000950f, + 0.001014f, 0.001049f, 0.001128f, 0.001188f, 0.001237f, 0.001303f, 0.001371f, 0.001466f, 0.001532f, 0.001623f, 0.001701f, 0.001805f, + 0.001945f, 0.002035f, 0.002186f, 0.002329f, 0.002460f, 0.002632f, 0.002819f, 0.003012f, 0.003271f, 0.003550f, 0.003819f, 0.004162f, + 0.004539f, 0.005024f, 0.005585f, 0.006233f, 0.007050f, 0.008072f, 0.009331f, 0.011269f, 0.014160f, 0.018112f, 0.333740f, 0.408447f, + 0.428711f, 0.438232f, 0.443359f, 0.447510f, 0.000053f, 0.000163f, 0.000155f, 0.000160f, 0.000191f, 0.000228f, 0.000206f, 0.000233f, + 0.000248f, 0.000263f, 0.000267f, 0.000294f, 0.000324f, 0.000335f, 0.000364f, 0.000378f, 0.000396f, 0.000435f, 0.000445f, 0.000490f, + 0.000502f, 0.000522f, 0.000543f, 0.000582f, 0.000619f, 0.000665f, 0.000679f, 0.000705f, 0.000755f, 0.000797f, 0.000856f, 0.000887f, + 0.000953f, 0.000988f, 0.001043f, 0.001103f, 0.001177f, 0.001256f, 0.001331f, 0.001410f, 0.001508f, 0.001612f, 0.001734f, 0.001873f, + 0.001999f, 0.002163f, 0.002378f, 0.002565f, 0.002827f, 0.003119f, 0.003479f, 0.003899f, 0.004463f, 0.005116f, 0.005951f, 0.007153f, + 0.009163f, 0.012535f, 0.322510f, 0.400146f, 0.420654f, 0.430176f, 0.436523f, 0.440430f, 0.000097f, 0.000107f, 0.000095f, 0.000087f, + 0.000107f, 0.000110f, 0.000137f, 0.000139f, 0.000140f, 0.000147f, 0.000168f, 0.000175f, 0.000177f, 0.000184f, 0.000210f, 0.000200f, + 0.000224f, 0.000239f, 0.000246f, 0.000258f, 0.000278f, 0.000288f, 0.000312f, 0.000324f, 0.000347f, 0.000368f, 0.000382f, 0.000395f, + 0.000418f, 0.000440f, 0.000471f, 0.000495f, 0.000521f, 0.000547f, 0.000577f, 0.000620f, 0.000649f, 0.000695f, 0.000749f, 0.000785f, + 0.000838f, 0.000897f, 0.000972f, 0.001028f, 0.001118f, 0.001204f, 0.001316f, 0.001432f, 0.001580f, 0.001748f, 0.001961f, 0.002207f, + 0.002533f, 0.002941f, 0.003487f, 0.004223f, 0.005371f, 0.007809f, 0.311523f, 0.390381f, 0.411377f, 0.421875f, 0.428467f, 0.432617f, + 0.000000f, 0.000055f, 0.000046f, 0.000054f, 0.000060f, 0.000058f, 0.000060f, 0.000068f, 0.000068f, 0.000082f, 0.000076f, 0.000078f, + 0.000092f, 0.000087f, 0.000091f, 0.000097f, 0.000105f, 0.000115f, 0.000118f, 0.000124f, 0.000128f, 0.000133f, 0.000139f, 0.000154f, + 0.000160f, 0.000172f, 0.000175f, 0.000191f, 0.000201f, 0.000211f, 0.000221f, 0.000238f, 0.000242f, 0.000257f, 0.000277f, 0.000295f, + 0.000309f, 0.000326f, 0.000351f, 0.000375f, 0.000400f, 0.000428f, 0.000459f, 0.000490f, 0.000535f, 0.000579f, 0.000626f, 0.000683f, + 0.000754f, 0.000836f, 0.000952f, 0.001064f, 0.001237f, 0.001460f, 0.001751f, 0.002157f, 0.002800f, 0.004189f, 0.299561f, 0.380127f, + 0.403076f, 0.413574f, 0.419922f, 0.424072f, 0.000059f, 0.000039f, 0.000032f, 0.000028f, 0.000025f, 0.000025f, 0.000025f, 0.000024f, + 0.000023f, 0.000024f, 0.000026f, 0.000034f, 0.000029f, 0.000031f, 0.000038f, 0.000040f, 0.000042f, 0.000043f, 0.000042f, 0.000043f, + 0.000048f, 0.000054f, 0.000058f, 0.000056f, 0.000060f, 0.000062f, 0.000066f, 0.000069f, 0.000072f, 0.000078f, 0.000082f, 0.000085f, + 0.000093f, 0.000096f, 0.000099f, 0.000106f, 0.000116f, 0.000123f, 0.000132f, 0.000140f, 0.000150f, 0.000154f, 0.000167f, 0.000184f, + 0.000192f, 0.000212f, 0.000231f, 0.000251f, 0.000282f, 0.000314f, 0.000350f, 0.000401f, 0.000463f, 0.000554f, 0.000679f, 0.000861f, + 0.001157f, 0.001750f, 0.289307f, 0.371582f, 0.394043f, 0.406006f, 0.412109f, 0.417236f, 0.000031f, 0.000020f, 0.000016f, 0.000014f, + 0.000013f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000008f, 0.000008f, 0.000009f, + 0.000009f, 0.000007f, 0.000008f, 0.000008f, 0.000010f, 0.000011f, 0.000012f, 0.000013f, 0.000013f, 0.000013f, 0.000014f, 0.000017f, + 0.000017f, 0.000016f, 0.000018f, 0.000019f, 0.000021f, 0.000021f, 0.000022f, 0.000025f, 0.000027f, 0.000025f, 0.000028f, 0.000030f, + 0.000033f, 0.000036f, 0.000038f, 0.000040f, 0.000042f, 0.000047f, 0.000052f, 0.000057f, 0.000060f, 0.000068f, 0.000073f, 0.000089f, + 0.000104f, 0.000124f, 0.000153f, 0.000204f, 0.000293f, 0.000497f, 0.278076f, 0.362793f, 0.385498f, 0.397705f, 0.405029f, 0.409912f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, + 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000005f, 0.000005f, 0.000008f, 0.000012f, 0.000026f, 0.267822f, 0.353027f, + 0.376953f, 0.388916f, 0.395996f, 0.401367f, + }, + { + 0.006824f, 0.021286f, 0.036285f, 0.051208f, 0.066467f, 0.082825f, 0.098694f, 0.114563f, 0.130737f, 0.146973f, 0.162720f, 0.179932f, + 0.196411f, 0.212646f, 0.229370f, 0.246338f, 0.263184f, 0.279785f, 0.297363f, 0.314209f, 0.331055f, 0.348389f, 0.365479f, 0.383301f, + 0.400146f, 0.417725f, 0.435303f, 0.451904f, 0.469971f, 0.486816f, 0.503906f, 0.521484f, 0.539551f, 0.556641f, 0.573730f, 0.592285f, + 0.609375f, 0.627441f, 0.644531f, 0.662598f, 0.679688f, 0.696777f, 0.714355f, 0.731934f, 0.749512f, 0.768066f, 0.784180f, 0.802246f, + 0.820312f, 0.837891f, 0.854980f, 0.871582f, 0.889648f, 0.906738f, 0.924805f, 0.941406f, 0.959473f, 0.976074f, 0.953125f, 0.895020f, + 0.857422f, 0.827637f, 0.803223f, 0.781738f, 0.006741f, 0.020706f, 0.035187f, 0.049866f, 0.065125f, 0.079895f, 0.095581f, 0.111206f, + 0.126953f, 0.142822f, 0.158569f, 0.174561f, 0.190796f, 0.207031f, 0.223511f, 0.239380f, 0.256104f, 0.272705f, 0.289307f, 0.305664f, + 0.322754f, 0.338867f, 0.356201f, 0.372314f, 0.389404f, 0.406494f, 0.423828f, 0.440430f, 0.457520f, 0.474854f, 0.491211f, 0.508789f, + 0.525391f, 0.541992f, 0.559082f, 0.576660f, 0.594238f, 0.610840f, 0.627930f, 0.645508f, 0.662598f, 0.679199f, 0.696289f, 0.713379f, + 0.731445f, 0.747559f, 0.765137f, 0.782715f, 0.799805f, 0.816895f, 0.834473f, 0.851074f, 0.868164f, 0.884766f, 0.902344f, 0.919434f, + 0.936523f, 0.953613f, 0.942871f, 0.887695f, 0.851562f, 0.823730f, 0.799805f, 0.779297f, 0.006504f, 0.020004f, 0.033875f, 0.048676f, + 0.063110f, 0.077759f, 0.092712f, 0.108032f, 0.123230f, 0.138672f, 0.153931f, 0.170044f, 0.185791f, 0.200806f, 0.217041f, 0.233276f, + 0.248901f, 0.265137f, 0.280762f, 0.297363f, 0.313721f, 0.329834f, 0.346680f, 0.363037f, 0.378418f, 0.395752f, 0.411621f, 0.428467f, + 0.445312f, 0.461670f, 0.479004f, 0.494873f, 0.511230f, 0.527832f, 0.544434f, 0.561523f, 0.578613f, 0.594727f, 0.611328f, 0.628906f, + 0.645508f, 0.662109f, 0.679199f, 0.695312f, 0.712402f, 0.729004f, 0.746094f, 0.762695f, 0.779297f, 0.796387f, 0.812500f, 0.829590f, + 0.846191f, 0.863281f, 0.879395f, 0.896973f, 0.914062f, 0.930176f, 0.932129f, 0.879395f, 0.845703f, 0.818848f, 0.795898f, 0.776367f, + 0.006226f, 0.019318f, 0.032959f, 0.046631f, 0.060699f, 0.075745f, 0.089966f, 0.104553f, 0.119385f, 0.134277f, 0.149292f, 0.164917f, + 0.179932f, 0.195190f, 0.210693f, 0.226562f, 0.242188f, 0.257568f, 0.273438f, 0.289062f, 0.304932f, 0.320557f, 0.336426f, 0.352539f, + 0.368652f, 0.384766f, 0.400391f, 0.417236f, 0.433105f, 0.448730f, 0.465088f, 0.481689f, 0.497559f, 0.513672f, 0.528809f, 0.546875f, + 0.562500f, 0.578613f, 0.595215f, 0.612793f, 0.627930f, 0.645508f, 0.661621f, 0.677246f, 0.693848f, 0.709961f, 0.726562f, 0.743164f, + 0.759766f, 0.774902f, 0.791992f, 0.808594f, 0.825195f, 0.841309f, 0.856934f, 0.874023f, 0.890625f, 0.907715f, 0.921387f, 0.872070f, + 0.839355f, 0.813477f, 0.791504f, 0.772461f, 0.005928f, 0.018997f, 0.031830f, 0.045380f, 0.059235f, 0.072754f, 0.087463f, 0.101562f, + 0.115723f, 0.130371f, 0.145264f, 0.159668f, 0.175049f, 0.189453f, 0.204468f, 0.219482f, 0.234497f, 0.250000f, 0.266113f, 0.280273f, + 0.295410f, 0.311768f, 0.327393f, 0.343018f, 0.357422f, 0.373779f, 0.389404f, 0.404785f, 0.421143f, 0.437012f, 0.452881f, 0.468262f, + 0.484375f, 0.499512f, 0.515137f, 0.531738f, 0.546875f, 0.562500f, 0.579102f, 0.595215f, 0.610840f, 0.627441f, 0.643555f, 0.659180f, + 0.674805f, 0.691406f, 0.708008f, 0.723145f, 0.738770f, 0.755371f, 0.771484f, 0.787598f, 0.803711f, 0.819824f, 0.835449f, 0.851562f, + 0.867676f, 0.884277f, 0.910156f, 0.864258f, 0.832520f, 0.808105f, 0.787109f, 0.769043f, 0.005939f, 0.018066f, 0.030991f, 0.043488f, + 0.057312f, 0.070557f, 0.084473f, 0.098328f, 0.112610f, 0.126587f, 0.140259f, 0.154907f, 0.169678f, 0.184326f, 0.198608f, 0.213379f, + 0.227783f, 0.242065f, 0.257568f, 0.272705f, 0.287109f, 0.302246f, 0.318115f, 0.333252f, 0.347656f, 0.362549f, 0.378418f, 0.393555f, + 0.408936f, 0.423828f, 0.439697f, 0.455078f, 0.471191f, 0.484863f, 0.500488f, 0.517578f, 0.532227f, 0.547363f, 0.562500f, 0.579102f, + 0.594727f, 0.610352f, 0.625488f, 0.641602f, 0.657227f, 0.671875f, 0.687500f, 0.704102f, 0.719238f, 0.733887f, 0.750488f, 0.767090f, + 0.782715f, 0.798340f, 0.813965f, 0.830566f, 0.845215f, 0.862305f, 0.899902f, 0.855469f, 0.825684f, 0.801758f, 0.782227f, 0.764648f, + 0.005684f, 0.017639f, 0.030334f, 0.042572f, 0.055298f, 0.068054f, 0.081787f, 0.095276f, 0.108765f, 0.122192f, 0.136353f, 0.150513f, + 0.164307f, 0.178467f, 0.192627f, 0.206665f, 0.221436f, 0.234985f, 0.249634f, 0.264404f, 0.278564f, 0.293213f, 0.308350f, 0.321533f, + 0.337646f, 0.353027f, 0.367432f, 0.381592f, 0.395996f, 0.411865f, 0.426758f, 0.441895f, 0.456543f, 0.471680f, 0.485840f, 0.501465f, + 0.517090f, 0.531738f, 0.546387f, 0.562012f, 0.576660f, 0.592773f, 0.608398f, 0.623047f, 0.638672f, 0.654297f, 0.668457f, 0.684082f, + 0.699707f, 0.714844f, 0.730469f, 0.745605f, 0.761230f, 0.777832f, 0.791504f, 0.807617f, 0.823242f, 0.839355f, 0.889160f, 0.847656f, + 0.818848f, 0.796387f, 0.776855f, 0.760254f, 0.005417f, 0.017136f, 0.028778f, 0.041016f, 0.054047f, 0.066528f, 0.079590f, 0.092102f, + 0.105225f, 0.118652f, 0.131714f, 0.145630f, 0.158813f, 0.172607f, 0.186523f, 0.200317f, 0.213745f, 0.227905f, 0.242188f, 0.256104f, + 0.270020f, 0.283936f, 0.299072f, 0.312744f, 0.327148f, 0.341797f, 0.355957f, 0.369629f, 0.384766f, 0.399414f, 0.413574f, 0.427490f, + 0.443115f, 0.457764f, 0.472656f, 0.487061f, 0.501465f, 0.516602f, 0.530762f, 0.545898f, 0.560547f, 0.574707f, 0.589844f, 0.605469f, + 0.619629f, 0.633301f, 0.648926f, 0.665527f, 0.679688f, 0.694824f, 0.709961f, 0.725586f, 0.739746f, 0.755371f, 0.770020f, 0.786133f, + 0.802246f, 0.817383f, 0.877930f, 0.838867f, 0.812012f, 0.790039f, 0.771973f, 0.755371f, 0.005520f, 0.016464f, 0.027695f, 0.039948f, + 0.051575f, 0.063965f, 0.076660f, 0.089111f, 0.101807f, 0.114319f, 0.126953f, 0.140381f, 0.153564f, 0.166992f, 0.180298f, 0.193970f, + 0.207153f, 0.220337f, 0.234131f, 0.248169f, 0.261475f, 0.275146f, 0.288818f, 0.302734f, 0.316162f, 0.330566f, 0.345459f, 0.358887f, + 0.372803f, 0.386719f, 0.401367f, 0.415527f, 0.429199f, 0.443848f, 0.458008f, 0.472412f, 0.486572f, 0.500977f, 0.515137f, 0.529785f, + 0.544434f, 0.558105f, 0.572754f, 0.587891f, 0.601074f, 0.617188f, 0.631836f, 0.645020f, 0.660645f, 0.674805f, 0.689453f, 0.704590f, + 0.719727f, 0.734375f, 0.750000f, 0.764160f, 0.780273f, 0.794922f, 0.866699f, 0.830566f, 0.804688f, 0.784180f, 0.766113f, 0.750977f, + 0.005222f, 0.016022f, 0.026962f, 0.038086f, 0.050049f, 0.061798f, 0.074158f, 0.085876f, 0.098145f, 0.110718f, 0.122986f, 0.135864f, + 0.148438f, 0.161133f, 0.173584f, 0.187378f, 0.199707f, 0.213501f, 0.226440f, 0.240112f, 0.252441f, 0.266113f, 0.279785f, 0.292725f, + 0.306152f, 0.320068f, 0.333984f, 0.347900f, 0.361572f, 0.374512f, 0.387695f, 0.402344f, 0.416504f, 0.429688f, 0.443604f, 0.458008f, + 0.471680f, 0.485596f, 0.499023f, 0.513184f, 0.527832f, 0.541016f, 0.555664f, 0.569336f, 0.583984f, 0.598633f, 0.612793f, 0.626465f, + 0.641602f, 0.656250f, 0.669922f, 0.684570f, 0.698730f, 0.713867f, 0.728516f, 0.742188f, 0.757812f, 0.771484f, 0.855957f, 0.822266f, + 0.797852f, 0.777832f, 0.760742f, 0.746094f, 0.004944f, 0.015327f, 0.026230f, 0.037201f, 0.048187f, 0.059448f, 0.071167f, 0.082642f, + 0.094727f, 0.106506f, 0.119019f, 0.130371f, 0.143555f, 0.155640f, 0.167725f, 0.180908f, 0.193604f, 0.206177f, 0.218506f, 0.231812f, + 0.244873f, 0.257568f, 0.270996f, 0.283203f, 0.296387f, 0.309814f, 0.322754f, 0.336670f, 0.348877f, 0.362061f, 0.376465f, 0.389893f, + 0.402588f, 0.415283f, 0.429443f, 0.443115f, 0.457031f, 0.470459f, 0.483887f, 0.497314f, 0.511230f, 0.524414f, 0.538574f, 0.551758f, + 0.565918f, 0.579590f, 0.593750f, 0.606934f, 0.621094f, 0.635254f, 0.649902f, 0.664062f, 0.678223f, 0.692871f, 0.707031f, 0.721191f, + 0.735840f, 0.750488f, 0.846191f, 0.813477f, 0.790527f, 0.770996f, 0.754883f, 0.740723f, 0.004951f, 0.014656f, 0.025253f, 0.035309f, + 0.046417f, 0.057465f, 0.068665f, 0.079773f, 0.091370f, 0.102844f, 0.114441f, 0.126099f, 0.138062f, 0.150391f, 0.161987f, 0.174561f, + 0.186523f, 0.198730f, 0.211060f, 0.223267f, 0.235352f, 0.248779f, 0.260986f, 0.274414f, 0.286621f, 0.298584f, 0.312256f, 0.324463f, + 0.337158f, 0.350342f, 0.363281f, 0.376953f, 0.389404f, 0.402344f, 0.415283f, 0.428955f, 0.441162f, 0.455322f, 0.467285f, 0.481201f, + 0.493896f, 0.507324f, 0.520996f, 0.534668f, 0.547852f, 0.561035f, 0.575195f, 0.588867f, 0.603027f, 0.616211f, 0.630371f, 0.643555f, + 0.658203f, 0.671875f, 0.686035f, 0.699707f, 0.714844f, 0.729492f, 0.833984f, 0.804688f, 0.782227f, 0.764160f, 0.749512f, 0.735352f, + 0.004700f, 0.014343f, 0.024200f, 0.034515f, 0.044586f, 0.055176f, 0.066162f, 0.077209f, 0.087830f, 0.098816f, 0.110413f, 0.121826f, + 0.132690f, 0.144897f, 0.156372f, 0.168213f, 0.179443f, 0.191650f, 0.203369f, 0.215088f, 0.227661f, 0.239990f, 0.251709f, 0.263916f, + 0.276611f, 0.289551f, 0.301270f, 0.313965f, 0.325928f, 0.338135f, 0.350586f, 0.363037f, 0.376465f, 0.388428f, 0.401123f, 0.414062f, + 0.426514f, 0.439209f, 0.452393f, 0.465088f, 0.478271f, 0.491455f, 0.503906f, 0.517090f, 0.530273f, 0.543457f, 0.556641f, 0.570312f, + 0.583008f, 0.597168f, 0.610352f, 0.624512f, 0.638184f, 0.651367f, 0.665527f, 0.679199f, 0.692871f, 0.708496f, 0.823242f, 0.796387f, + 0.774902f, 0.757812f, 0.742676f, 0.729980f, 0.004395f, 0.013802f, 0.023499f, 0.033173f, 0.043121f, 0.053345f, 0.063538f, 0.073730f, + 0.085083f, 0.095581f, 0.106140f, 0.116760f, 0.127930f, 0.139160f, 0.150757f, 0.161621f, 0.173096f, 0.184814f, 0.196289f, 0.207520f, + 0.219971f, 0.231201f, 0.242920f, 0.254150f, 0.266602f, 0.278320f, 0.290527f, 0.302490f, 0.314209f, 0.326904f, 0.338867f, 0.349854f, + 0.362305f, 0.375488f, 0.387451f, 0.400146f, 0.412354f, 0.424805f, 0.436768f, 0.449219f, 0.461914f, 0.475098f, 0.487061f, 0.500000f, + 0.512695f, 0.525391f, 0.538574f, 0.551758f, 0.564453f, 0.577148f, 0.590820f, 0.604004f, 0.618164f, 0.631348f, 0.644531f, 0.658203f, + 0.672363f, 0.686523f, 0.812500f, 0.786621f, 0.767090f, 0.750977f, 0.736816f, 0.724609f, 0.004425f, 0.013405f, 0.022385f, 0.032043f, + 0.041565f, 0.051605f, 0.061340f, 0.071106f, 0.081116f, 0.091125f, 0.101868f, 0.112671f, 0.123169f, 0.133667f, 0.144897f, 0.155029f, + 0.166748f, 0.177246f, 0.188599f, 0.199585f, 0.211182f, 0.222046f, 0.233643f, 0.245361f, 0.255615f, 0.268066f, 0.279053f, 0.291260f, + 0.303223f, 0.314209f, 0.325684f, 0.338379f, 0.349854f, 0.361572f, 0.374023f, 0.385254f, 0.397949f, 0.409912f, 0.421143f, 0.434082f, + 0.445801f, 0.457764f, 0.470215f, 0.482910f, 0.495361f, 0.508301f, 0.520996f, 0.534180f, 0.546387f, 0.560059f, 0.572266f, 0.584961f, + 0.597168f, 0.610840f, 0.624023f, 0.638184f, 0.650879f, 0.666016f, 0.801270f, 0.778320f, 0.760254f, 0.744141f, 0.730469f, 0.719238f, + 0.004261f, 0.012543f, 0.021591f, 0.031052f, 0.039734f, 0.049164f, 0.058838f, 0.068420f, 0.077881f, 0.087402f, 0.098145f, 0.108276f, + 0.118225f, 0.128784f, 0.138550f, 0.149292f, 0.159790f, 0.170654f, 0.181519f, 0.191772f, 0.203003f, 0.213623f, 0.225098f, 0.235107f, + 0.247070f, 0.257324f, 0.269287f, 0.280273f, 0.291260f, 0.302246f, 0.313721f, 0.325439f, 0.336670f, 0.348145f, 0.359619f, 0.371338f, + 0.382812f, 0.395020f, 0.406738f, 0.418213f, 0.429932f, 0.442139f, 0.454102f, 0.466309f, 0.479004f, 0.490723f, 0.502930f, 0.515625f, + 0.526855f, 0.540527f, 0.552246f, 0.565918f, 0.578613f, 0.591309f, 0.604492f, 0.617188f, 0.630859f, 0.644043f, 0.790039f, 0.769531f, + 0.751953f, 0.737305f, 0.724121f, 0.713379f, 0.003983f, 0.012329f, 0.020538f, 0.029312f, 0.038452f, 0.047241f, 0.056244f, 0.065552f, + 0.075195f, 0.084290f, 0.094238f, 0.103638f, 0.113403f, 0.123413f, 0.133057f, 0.143066f, 0.153076f, 0.163696f, 0.173584f, 0.184204f, + 0.194580f, 0.204834f, 0.215332f, 0.225952f, 0.237305f, 0.247803f, 0.258545f, 0.269531f, 0.280518f, 0.291260f, 0.301758f, 0.312988f, + 0.324219f, 0.335205f, 0.346191f, 0.357178f, 0.368896f, 0.380127f, 0.391113f, 0.403076f, 0.414551f, 0.426270f, 0.437500f, 0.449951f, + 0.460938f, 0.473389f, 0.485596f, 0.497314f, 0.509277f, 0.522461f, 0.533691f, 0.546875f, 0.558594f, 0.571289f, 0.583496f, 0.596680f, + 0.608887f, 0.623047f, 0.778809f, 0.761230f, 0.744141f, 0.730957f, 0.718262f, 0.707031f, 0.003717f, 0.012016f, 0.020142f, 0.028137f, + 0.036682f, 0.045441f, 0.053711f, 0.062927f, 0.071777f, 0.080627f, 0.090210f, 0.099060f, 0.108643f, 0.118164f, 0.127808f, 0.137329f, + 0.147095f, 0.156128f, 0.166748f, 0.175903f, 0.186157f, 0.196655f, 0.206909f, 0.216797f, 0.227417f, 0.236816f, 0.247559f, 0.258301f, + 0.268799f, 0.278809f, 0.289795f, 0.299805f, 0.310547f, 0.321777f, 0.333008f, 0.343262f, 0.354492f, 0.365234f, 0.376953f, 0.387939f, + 0.398438f, 0.410400f, 0.421387f, 0.433105f, 0.444824f, 0.455811f, 0.467529f, 0.479736f, 0.491943f, 0.502930f, 0.515625f, 0.527344f, + 0.540039f, 0.551758f, 0.563965f, 0.576660f, 0.589844f, 0.602539f, 0.767578f, 0.751465f, 0.736328f, 0.723633f, 0.711914f, 0.701660f, + 0.003813f, 0.011337f, 0.019028f, 0.027252f, 0.035583f, 0.043396f, 0.051849f, 0.060028f, 0.068481f, 0.077026f, 0.086121f, 0.095093f, + 0.103821f, 0.112610f, 0.121765f, 0.131470f, 0.140503f, 0.149780f, 0.159058f, 0.168701f, 0.178711f, 0.187744f, 0.197998f, 0.207397f, + 0.217651f, 0.227661f, 0.236694f, 0.246704f, 0.257080f, 0.267334f, 0.277832f, 0.288330f, 0.298584f, 0.308838f, 0.319336f, 0.329590f, + 0.340332f, 0.351318f, 0.361816f, 0.372559f, 0.383301f, 0.395020f, 0.405273f, 0.416260f, 0.427734f, 0.439209f, 0.450195f, 0.462158f, + 0.473389f, 0.485107f, 0.497314f, 0.508301f, 0.520996f, 0.533203f, 0.544922f, 0.557617f, 0.568848f, 0.582031f, 0.757324f, 0.742676f, + 0.729004f, 0.716309f, 0.705566f, 0.695801f, 0.003633f, 0.011040f, 0.018280f, 0.026062f, 0.033569f, 0.041229f, 0.049591f, 0.057373f, + 0.065308f, 0.073975f, 0.082214f, 0.090393f, 0.099243f, 0.107544f, 0.116028f, 0.125854f, 0.134155f, 0.143311f, 0.151978f, 0.160767f, + 0.170410f, 0.179321f, 0.188477f, 0.198242f, 0.207764f, 0.217896f, 0.227051f, 0.236328f, 0.246338f, 0.256104f, 0.265869f, 0.276123f, + 0.285645f, 0.295898f, 0.306152f, 0.316162f, 0.326172f, 0.336914f, 0.347412f, 0.358154f, 0.368164f, 0.378906f, 0.389648f, 0.400146f, + 0.410889f, 0.421631f, 0.432861f, 0.444824f, 0.456055f, 0.466797f, 0.479004f, 0.490234f, 0.501465f, 0.514160f, 0.525879f, 0.537598f, + 0.549316f, 0.561523f, 0.745605f, 0.733887f, 0.721191f, 0.708496f, 0.699219f, 0.689453f, 0.003469f, 0.010429f, 0.017609f, 0.024612f, + 0.032135f, 0.039520f, 0.047516f, 0.055206f, 0.062347f, 0.070618f, 0.078308f, 0.085938f, 0.094727f, 0.102417f, 0.111511f, 0.119446f, + 0.127441f, 0.136475f, 0.144897f, 0.154175f, 0.162476f, 0.171509f, 0.180054f, 0.189697f, 0.198486f, 0.207886f, 0.216553f, 0.225830f, + 0.235229f, 0.244873f, 0.254395f, 0.263428f, 0.273193f, 0.283203f, 0.292969f, 0.302734f, 0.312744f, 0.322510f, 0.333008f, 0.342773f, + 0.353027f, 0.363037f, 0.374023f, 0.384521f, 0.395264f, 0.405762f, 0.416260f, 0.427002f, 0.438232f, 0.449219f, 0.460449f, 0.471924f, + 0.482910f, 0.494629f, 0.506348f, 0.517578f, 0.529785f, 0.541504f, 0.734375f, 0.725098f, 0.712891f, 0.701660f, 0.692383f, 0.683594f, + 0.003328f, 0.009804f, 0.016373f, 0.023727f, 0.030746f, 0.037994f, 0.044952f, 0.052032f, 0.059998f, 0.067383f, 0.074707f, 0.082214f, + 0.089783f, 0.097961f, 0.105774f, 0.114197f, 0.122131f, 0.129517f, 0.137695f, 0.146118f, 0.154419f, 0.163330f, 0.171997f, 0.180664f, + 0.188477f, 0.197388f, 0.206055f, 0.215332f, 0.224365f, 0.233765f, 0.242798f, 0.251709f, 0.260986f, 0.270020f, 0.279785f, 0.289062f, + 0.299561f, 0.308594f, 0.318115f, 0.328613f, 0.338135f, 0.348877f, 0.358154f, 0.368408f, 0.378174f, 0.388916f, 0.399658f, 0.410156f, + 0.420898f, 0.431885f, 0.442871f, 0.453369f, 0.463867f, 0.475342f, 0.486572f, 0.498535f, 0.510742f, 0.521973f, 0.723633f, 0.715820f, + 0.705078f, 0.694336f, 0.686035f, 0.677246f, 0.003090f, 0.009628f, 0.016129f, 0.022644f, 0.029068f, 0.036407f, 0.042633f, 0.049866f, + 0.056946f, 0.063904f, 0.071167f, 0.078186f, 0.085327f, 0.092896f, 0.100098f, 0.107788f, 0.115662f, 0.123230f, 0.131104f, 0.139160f, + 0.146973f, 0.154907f, 0.162964f, 0.171265f, 0.179565f, 0.188110f, 0.196777f, 0.204834f, 0.213745f, 0.222168f, 0.231079f, 0.239868f, + 0.248779f, 0.258057f, 0.267090f, 0.276611f, 0.285645f, 0.294434f, 0.304688f, 0.314209f, 0.323242f, 0.332520f, 0.342773f, 0.353027f, + 0.362549f, 0.373047f, 0.383057f, 0.393311f, 0.404053f, 0.414307f, 0.424561f, 0.435059f, 0.445801f, 0.456787f, 0.467773f, 0.479004f, + 0.490479f, 0.501953f, 0.712891f, 0.707031f, 0.696777f, 0.687500f, 0.679199f, 0.671387f, 0.003096f, 0.009026f, 0.015450f, 0.021606f, + 0.027695f, 0.034302f, 0.040833f, 0.047455f, 0.054077f, 0.060669f, 0.067444f, 0.074097f, 0.081604f, 0.088501f, 0.095337f, 0.102295f, + 0.109375f, 0.116821f, 0.124146f, 0.131592f, 0.139404f, 0.147217f, 0.155029f, 0.162231f, 0.170288f, 0.177979f, 0.186646f, 0.194092f, + 0.203247f, 0.211670f, 0.219604f, 0.228149f, 0.236816f, 0.245605f, 0.254639f, 0.263184f, 0.272217f, 0.281250f, 0.290527f, 0.299805f, + 0.308838f, 0.318604f, 0.327637f, 0.337646f, 0.347900f, 0.356934f, 0.367432f, 0.376953f, 0.387451f, 0.397217f, 0.407227f, 0.417480f, + 0.427979f, 0.439209f, 0.449463f, 0.459717f, 0.470947f, 0.482666f, 0.701172f, 0.698242f, 0.688477f, 0.680176f, 0.671875f, 0.665039f, + 0.002831f, 0.008789f, 0.014702f, 0.020523f, 0.026642f, 0.032684f, 0.038757f, 0.044708f, 0.051666f, 0.057312f, 0.063660f, 0.070190f, + 0.076904f, 0.083435f, 0.090454f, 0.097046f, 0.103821f, 0.110535f, 0.117981f, 0.124817f, 0.131714f, 0.138916f, 0.146606f, 0.153687f, + 0.161011f, 0.168823f, 0.176270f, 0.184570f, 0.192139f, 0.200317f, 0.208008f, 0.216309f, 0.224609f, 0.233032f, 0.241821f, 0.250244f, + 0.258789f, 0.268066f, 0.276611f, 0.285400f, 0.294678f, 0.303223f, 0.312500f, 0.322021f, 0.331787f, 0.340088f, 0.350830f, 0.360596f, + 0.369385f, 0.380371f, 0.389893f, 0.399658f, 0.410645f, 0.420654f, 0.430908f, 0.442383f, 0.452148f, 0.464111f, 0.690430f, 0.688965f, + 0.681152f, 0.672852f, 0.665039f, 0.658691f, 0.002712f, 0.008553f, 0.013878f, 0.019638f, 0.025360f, 0.030716f, 0.037231f, 0.042633f, + 0.048615f, 0.054810f, 0.060638f, 0.066650f, 0.072205f, 0.078796f, 0.085083f, 0.091492f, 0.097961f, 0.104065f, 0.110718f, 0.117859f, + 0.124207f, 0.130981f, 0.138550f, 0.145142f, 0.152588f, 0.160156f, 0.166992f, 0.174561f, 0.181885f, 0.189453f, 0.197754f, 0.205444f, + 0.213013f, 0.220825f, 0.229004f, 0.237061f, 0.246094f, 0.254639f, 0.262939f, 0.271484f, 0.280273f, 0.288818f, 0.298584f, 0.307129f, + 0.316162f, 0.325195f, 0.334229f, 0.344482f, 0.353516f, 0.363525f, 0.372803f, 0.382812f, 0.392822f, 0.402344f, 0.412842f, 0.423096f, + 0.433350f, 0.444092f, 0.679199f, 0.679688f, 0.672852f, 0.665039f, 0.658203f, 0.651855f, 0.002674f, 0.007828f, 0.013290f, 0.018723f, + 0.023743f, 0.029160f, 0.034790f, 0.040100f, 0.045929f, 0.051544f, 0.057068f, 0.063110f, 0.068359f, 0.074280f, 0.080078f, 0.086243f, + 0.092346f, 0.098206f, 0.104919f, 0.110779f, 0.117493f, 0.123291f, 0.130005f, 0.136963f, 0.143677f, 0.150635f, 0.157471f, 0.164307f, + 0.171631f, 0.179199f, 0.186279f, 0.193604f, 0.201904f, 0.209229f, 0.217163f, 0.224976f, 0.233154f, 0.240967f, 0.249634f, 0.258301f, + 0.266113f, 0.274414f, 0.283691f, 0.291748f, 0.301025f, 0.310059f, 0.319336f, 0.327148f, 0.337402f, 0.347168f, 0.355957f, 0.364746f, + 0.375488f, 0.385498f, 0.394043f, 0.405273f, 0.415283f, 0.426025f, 0.667969f, 0.670410f, 0.664551f, 0.657227f, 0.651367f, 0.645508f, + 0.002731f, 0.007622f, 0.012627f, 0.017868f, 0.022781f, 0.028107f, 0.032959f, 0.037811f, 0.043121f, 0.048615f, 0.053925f, 0.059235f, + 0.064514f, 0.070007f, 0.075562f, 0.080688f, 0.086914f, 0.092102f, 0.098083f, 0.104309f, 0.110107f, 0.115906f, 0.122314f, 0.128540f, + 0.135010f, 0.141479f, 0.147949f, 0.154663f, 0.161865f, 0.168579f, 0.175415f, 0.182739f, 0.191040f, 0.197510f, 0.205200f, 0.212891f, + 0.219971f, 0.228638f, 0.236328f, 0.244263f, 0.252686f, 0.260498f, 0.268799f, 0.278076f, 0.286133f, 0.294434f, 0.303223f, 0.312500f, + 0.320801f, 0.329834f, 0.339844f, 0.347656f, 0.357910f, 0.367676f, 0.376709f, 0.386963f, 0.396729f, 0.406982f, 0.656738f, 0.662598f, + 0.656738f, 0.649902f, 0.644531f, 0.638672f, 0.002411f, 0.007168f, 0.012238f, 0.016739f, 0.021957f, 0.026184f, 0.031311f, 0.035583f, + 0.041016f, 0.045685f, 0.050568f, 0.055573f, 0.060791f, 0.065735f, 0.070557f, 0.076111f, 0.081238f, 0.086792f, 0.092163f, 0.097534f, + 0.103271f, 0.108887f, 0.114563f, 0.120605f, 0.126587f, 0.132446f, 0.139038f, 0.145508f, 0.152100f, 0.158447f, 0.165527f, 0.171997f, + 0.178833f, 0.186035f, 0.193481f, 0.200928f, 0.207886f, 0.215820f, 0.222900f, 0.230713f, 0.238770f, 0.246948f, 0.255127f, 0.262695f, + 0.271484f, 0.280029f, 0.287842f, 0.296631f, 0.305420f, 0.313965f, 0.322754f, 0.331787f, 0.340576f, 0.350342f, 0.359375f, 0.369385f, + 0.379150f, 0.388184f, 0.645508f, 0.652832f, 0.648438f, 0.643066f, 0.637695f, 0.632324f, 0.002480f, 0.006691f, 0.011452f, 0.015900f, + 0.020828f, 0.024734f, 0.029327f, 0.033752f, 0.038513f, 0.042999f, 0.047638f, 0.052429f, 0.056671f, 0.061859f, 0.066040f, 0.071289f, + 0.075684f, 0.080688f, 0.086243f, 0.091248f, 0.096436f, 0.101562f, 0.107300f, 0.112366f, 0.118347f, 0.124146f, 0.130249f, 0.135864f, + 0.141968f, 0.148438f, 0.155029f, 0.161377f, 0.167969f, 0.174683f, 0.181641f, 0.188599f, 0.195679f, 0.203247f, 0.210449f, 0.217529f, + 0.225342f, 0.233398f, 0.241577f, 0.249023f, 0.256592f, 0.264893f, 0.273193f, 0.281494f, 0.289795f, 0.297607f, 0.306885f, 0.315430f, + 0.323730f, 0.333496f, 0.342529f, 0.351318f, 0.360840f, 0.370605f, 0.634766f, 0.643555f, 0.640625f, 0.635742f, 0.630859f, 0.625488f, + 0.002230f, 0.006477f, 0.010582f, 0.014870f, 0.019073f, 0.023270f, 0.027893f, 0.031860f, 0.036072f, 0.040253f, 0.044373f, 0.048706f, + 0.052856f, 0.057312f, 0.061859f, 0.066406f, 0.070984f, 0.075317f, 0.080139f, 0.084839f, 0.089661f, 0.094910f, 0.099792f, 0.104858f, + 0.110718f, 0.115356f, 0.121399f, 0.126831f, 0.132690f, 0.138672f, 0.145142f, 0.151001f, 0.157471f, 0.164185f, 0.170532f, 0.177002f, + 0.184082f, 0.191040f, 0.197876f, 0.205200f, 0.212402f, 0.219604f, 0.227295f, 0.234985f, 0.242188f, 0.250244f, 0.257812f, 0.266113f, + 0.274170f, 0.282471f, 0.290771f, 0.299072f, 0.307373f, 0.316162f, 0.326416f, 0.333984f, 0.343750f, 0.353271f, 0.622070f, 0.634277f, + 0.631836f, 0.627930f, 0.623535f, 0.619141f, 0.002220f, 0.006039f, 0.010353f, 0.014328f, 0.017838f, 0.022141f, 0.025742f, 0.029510f, + 0.033600f, 0.037781f, 0.041443f, 0.045502f, 0.049469f, 0.053436f, 0.057190f, 0.061462f, 0.065735f, 0.069946f, 0.074524f, 0.078674f, + 0.083069f, 0.087830f, 0.092468f, 0.097412f, 0.102783f, 0.107910f, 0.112793f, 0.118164f, 0.123901f, 0.129395f, 0.135132f, 0.140991f, + 0.147339f, 0.152954f, 0.159302f, 0.165527f, 0.172363f, 0.178589f, 0.185425f, 0.191895f, 0.199219f, 0.206665f, 0.213989f, 0.221069f, + 0.228516f, 0.236206f, 0.243042f, 0.251709f, 0.258789f, 0.266846f, 0.275146f, 0.283203f, 0.291260f, 0.300537f, 0.308350f, 0.317627f, + 0.326904f, 0.335938f, 0.611816f, 0.625000f, 0.624023f, 0.620117f, 0.616211f, 0.612793f, 0.001965f, 0.005882f, 0.009613f, 0.013184f, + 0.016785f, 0.020370f, 0.024384f, 0.027664f, 0.031311f, 0.035126f, 0.038727f, 0.042572f, 0.046112f, 0.049347f, 0.053253f, 0.056915f, + 0.060883f, 0.064697f, 0.068909f, 0.072693f, 0.076843f, 0.081055f, 0.085754f, 0.090088f, 0.094849f, 0.099609f, 0.104614f, 0.109741f, + 0.114746f, 0.119995f, 0.125488f, 0.130981f, 0.136719f, 0.142700f, 0.148315f, 0.154541f, 0.160522f, 0.166870f, 0.173828f, 0.179932f, + 0.186768f, 0.193604f, 0.200439f, 0.207764f, 0.214844f, 0.221802f, 0.228882f, 0.236328f, 0.244385f, 0.252197f, 0.259277f, 0.268066f, + 0.275635f, 0.283447f, 0.292236f, 0.301270f, 0.309570f, 0.318848f, 0.600098f, 0.616211f, 0.615234f, 0.612793f, 0.609375f, 0.605469f, + 0.001966f, 0.005653f, 0.009109f, 0.012428f, 0.015945f, 0.018967f, 0.022537f, 0.025894f, 0.029175f, 0.032440f, 0.035797f, 0.038818f, + 0.042389f, 0.046051f, 0.049072f, 0.052521f, 0.056335f, 0.059906f, 0.063293f, 0.067017f, 0.070923f, 0.075134f, 0.078979f, 0.083496f, + 0.087646f, 0.091980f, 0.096619f, 0.101196f, 0.105957f, 0.111145f, 0.116028f, 0.121277f, 0.126831f, 0.132080f, 0.137817f, 0.143311f, + 0.149780f, 0.155029f, 0.161621f, 0.167847f, 0.173950f, 0.180786f, 0.187622f, 0.194214f, 0.201050f, 0.207764f, 0.215210f, 0.222046f, + 0.229370f, 0.236816f, 0.244751f, 0.251953f, 0.260010f, 0.268311f, 0.276123f, 0.284180f, 0.293213f, 0.301514f, 0.588379f, 0.606934f, + 0.607422f, 0.604980f, 0.602051f, 0.599609f, 0.001963f, 0.005333f, 0.008377f, 0.011589f, 0.014450f, 0.017593f, 0.021133f, 0.023972f, + 0.027145f, 0.030075f, 0.033295f, 0.035858f, 0.038818f, 0.041992f, 0.045288f, 0.048279f, 0.051849f, 0.054840f, 0.058289f, 0.061737f, + 0.065186f, 0.068848f, 0.072632f, 0.076721f, 0.080505f, 0.084717f, 0.088806f, 0.093079f, 0.097717f, 0.102356f, 0.106934f, 0.111755f, + 0.116882f, 0.121887f, 0.127319f, 0.132935f, 0.138306f, 0.144287f, 0.149902f, 0.156250f, 0.162109f, 0.168579f, 0.174316f, 0.180908f, + 0.187500f, 0.194458f, 0.201538f, 0.208252f, 0.215210f, 0.222656f, 0.229980f, 0.237061f, 0.244629f, 0.252441f, 0.260254f, 0.267334f, + 0.276123f, 0.284180f, 0.576660f, 0.597656f, 0.599609f, 0.598145f, 0.595215f, 0.591797f, 0.001631f, 0.004906f, 0.007805f, 0.010826f, + 0.013802f, 0.016983f, 0.019485f, 0.022079f, 0.024750f, 0.027939f, 0.030136f, 0.033112f, 0.035797f, 0.038727f, 0.041443f, 0.044281f, + 0.047058f, 0.050018f, 0.053253f, 0.056396f, 0.059662f, 0.063049f, 0.066406f, 0.069946f, 0.073730f, 0.077454f, 0.081360f, 0.085388f, + 0.089417f, 0.093750f, 0.098267f, 0.102844f, 0.107727f, 0.112244f, 0.117615f, 0.122253f, 0.127441f, 0.133057f, 0.138550f, 0.144287f, + 0.150024f, 0.156250f, 0.161987f, 0.167969f, 0.174805f, 0.181274f, 0.187744f, 0.194580f, 0.201294f, 0.208374f, 0.215210f, 0.222412f, + 0.229736f, 0.237183f, 0.244629f, 0.252197f, 0.260010f, 0.269287f, 0.566406f, 0.588867f, 0.590820f, 0.590332f, 0.587891f, 0.585938f, + 0.001858f, 0.004318f, 0.007465f, 0.010246f, 0.012550f, 0.015793f, 0.018143f, 0.020782f, 0.022980f, 0.025116f, 0.027924f, 0.030106f, + 0.032623f, 0.035126f, 0.037720f, 0.040283f, 0.042847f, 0.045380f, 0.048492f, 0.051300f, 0.054321f, 0.057373f, 0.060516f, 0.063599f, + 0.067139f, 0.070496f, 0.074219f, 0.078003f, 0.081848f, 0.085754f, 0.089783f, 0.093994f, 0.098267f, 0.102783f, 0.107239f, 0.112366f, + 0.117371f, 0.122498f, 0.127686f, 0.132935f, 0.138428f, 0.144043f, 0.150024f, 0.155884f, 0.161865f, 0.168091f, 0.174316f, 0.180664f, + 0.187622f, 0.194214f, 0.200928f, 0.207520f, 0.214966f, 0.221680f, 0.229370f, 0.236816f, 0.244751f, 0.252441f, 0.553223f, 0.579102f, + 0.583496f, 0.582031f, 0.581055f, 0.579590f, 0.001425f, 0.004284f, 0.007019f, 0.009521f, 0.011894f, 0.014191f, 0.016632f, 0.018723f, + 0.021210f, 0.023209f, 0.025482f, 0.027344f, 0.029617f, 0.032043f, 0.034210f, 0.036407f, 0.039001f, 0.041077f, 0.043976f, 0.046448f, + 0.049133f, 0.051819f, 0.054932f, 0.057770f, 0.060730f, 0.063965f, 0.067322f, 0.070862f, 0.074280f, 0.077698f, 0.082031f, 0.085571f, + 0.089844f, 0.093994f, 0.098022f, 0.102722f, 0.107178f, 0.111877f, 0.116821f, 0.121887f, 0.127075f, 0.132446f, 0.138062f, 0.143799f, + 0.149414f, 0.155518f, 0.161377f, 0.167480f, 0.173950f, 0.180176f, 0.186890f, 0.193481f, 0.200562f, 0.207397f, 0.214355f, 0.221313f, + 0.229492f, 0.237427f, 0.541504f, 0.570801f, 0.575195f, 0.575195f, 0.573730f, 0.572266f, 0.001613f, 0.004181f, 0.006252f, 0.008774f, + 0.011108f, 0.013054f, 0.015152f, 0.016937f, 0.019150f, 0.021011f, 0.023163f, 0.024826f, 0.026993f, 0.028793f, 0.030823f, 0.033081f, + 0.035156f, 0.037201f, 0.039612f, 0.041748f, 0.044464f, 0.046814f, 0.049438f, 0.052155f, 0.054840f, 0.057831f, 0.060699f, 0.063599f, + 0.067078f, 0.070374f, 0.073853f, 0.077087f, 0.081177f, 0.085083f, 0.089111f, 0.093262f, 0.097473f, 0.101929f, 0.106689f, 0.111023f, + 0.116455f, 0.121277f, 0.126343f, 0.132080f, 0.137573f, 0.142700f, 0.148682f, 0.154907f, 0.161133f, 0.167236f, 0.173340f, 0.179688f, + 0.186768f, 0.193115f, 0.200684f, 0.207275f, 0.214233f, 0.221924f, 0.530273f, 0.561523f, 0.565430f, 0.567383f, 0.564941f, 0.564941f, + 0.001237f, 0.003775f, 0.006348f, 0.008141f, 0.010117f, 0.012184f, 0.013763f, 0.015656f, 0.017319f, 0.018967f, 0.020645f, 0.022507f, + 0.023926f, 0.025757f, 0.027573f, 0.029449f, 0.031677f, 0.033325f, 0.035645f, 0.037659f, 0.039734f, 0.041809f, 0.044189f, 0.046692f, + 0.049133f, 0.051697f, 0.054504f, 0.057251f, 0.060059f, 0.063110f, 0.066467f, 0.069763f, 0.072937f, 0.076477f, 0.080505f, 0.084290f, + 0.088013f, 0.092407f, 0.096436f, 0.101013f, 0.105713f, 0.110352f, 0.115356f, 0.120605f, 0.125488f, 0.130981f, 0.136353f, 0.142090f, + 0.148438f, 0.153931f, 0.159912f, 0.166260f, 0.172485f, 0.179321f, 0.185791f, 0.193115f, 0.199463f, 0.206665f, 0.520020f, 0.552246f, + 0.558105f, 0.559570f, 0.559082f, 0.557617f, 0.001151f, 0.003399f, 0.005611f, 0.007439f, 0.009354f, 0.010925f, 0.012489f, 0.014061f, + 0.015610f, 0.017258f, 0.018845f, 0.020248f, 0.021484f, 0.023193f, 0.024796f, 0.026459f, 0.028183f, 0.029785f, 0.031738f, 0.033386f, + 0.035309f, 0.037384f, 0.039368f, 0.041626f, 0.043701f, 0.046204f, 0.048553f, 0.051178f, 0.053955f, 0.056488f, 0.059418f, 0.062256f, + 0.065308f, 0.068542f, 0.071899f, 0.075623f, 0.079224f, 0.082947f, 0.087097f, 0.091064f, 0.095520f, 0.099854f, 0.104736f, 0.109314f, + 0.114136f, 0.119324f, 0.124756f, 0.130127f, 0.135498f, 0.141113f, 0.146973f, 0.153198f, 0.159180f, 0.165527f, 0.172241f, 0.178711f, + 0.185425f, 0.192749f, 0.507324f, 0.543945f, 0.549316f, 0.552246f, 0.551270f, 0.551270f, 0.001070f, 0.002996f, 0.004986f, 0.006851f, + 0.008514f, 0.009850f, 0.011330f, 0.012596f, 0.014015f, 0.015259f, 0.016586f, 0.017731f, 0.019287f, 0.020676f, 0.022079f, 0.023468f, + 0.024765f, 0.026489f, 0.028030f, 0.029465f, 0.031311f, 0.032898f, 0.034851f, 0.036743f, 0.038940f, 0.040833f, 0.043091f, 0.045074f, + 0.047729f, 0.050079f, 0.052673f, 0.055389f, 0.058136f, 0.061188f, 0.064087f, 0.067261f, 0.070618f, 0.074158f, 0.077942f, 0.081726f, + 0.085815f, 0.089783f, 0.094055f, 0.098572f, 0.103088f, 0.107971f, 0.113037f, 0.118164f, 0.123413f, 0.128784f, 0.134521f, 0.140137f, + 0.146118f, 0.152100f, 0.158325f, 0.164307f, 0.171387f, 0.177368f, 0.496094f, 0.534668f, 0.541992f, 0.543945f, 0.544434f, 0.544434f, + 0.001086f, 0.003069f, 0.004463f, 0.006256f, 0.007393f, 0.009026f, 0.010178f, 0.011276f, 0.012260f, 0.013542f, 0.014648f, 0.015808f, + 0.016861f, 0.017899f, 0.019333f, 0.020599f, 0.021942f, 0.023117f, 0.024384f, 0.025833f, 0.027344f, 0.028992f, 0.030579f, 0.032318f, + 0.034149f, 0.035828f, 0.037842f, 0.039764f, 0.041901f, 0.044037f, 0.046539f, 0.048645f, 0.051147f, 0.053894f, 0.056641f, 0.059631f, + 0.062500f, 0.065735f, 0.069031f, 0.072754f, 0.076294f, 0.080139f, 0.083984f, 0.088379f, 0.092712f, 0.097229f, 0.101929f, 0.106873f, + 0.111694f, 0.117004f, 0.122314f, 0.127930f, 0.133789f, 0.139282f, 0.145142f, 0.151367f, 0.157349f, 0.163818f, 0.484619f, 0.525391f, + 0.534180f, 0.536621f, 0.536133f, 0.536621f, 0.001125f, 0.002892f, 0.003883f, 0.005867f, 0.006603f, 0.007935f, 0.009026f, 0.009911f, + 0.010956f, 0.012077f, 0.012909f, 0.013901f, 0.014977f, 0.015671f, 0.016983f, 0.018021f, 0.019058f, 0.020279f, 0.021225f, 0.022598f, + 0.023941f, 0.025299f, 0.026535f, 0.028107f, 0.029755f, 0.031113f, 0.033020f, 0.034668f, 0.036682f, 0.038483f, 0.040527f, 0.042511f, + 0.044708f, 0.046936f, 0.049744f, 0.052216f, 0.054840f, 0.057800f, 0.060791f, 0.064087f, 0.067505f, 0.071045f, 0.074463f, 0.078491f, + 0.082397f, 0.086609f, 0.091248f, 0.095581f, 0.100342f, 0.105530f, 0.110474f, 0.116272f, 0.120972f, 0.126953f, 0.132812f, 0.138672f, + 0.144287f, 0.150513f, 0.472412f, 0.516113f, 0.524902f, 0.528809f, 0.529785f, 0.529785f, 0.000859f, 0.002470f, 0.003815f, 0.005226f, + 0.005913f, 0.007206f, 0.007942f, 0.008652f, 0.009583f, 0.010406f, 0.011223f, 0.011971f, 0.012856f, 0.013664f, 0.014664f, 0.015549f, + 0.016464f, 0.017487f, 0.018478f, 0.019592f, 0.020767f, 0.021774f, 0.023117f, 0.024338f, 0.025604f, 0.027008f, 0.028519f, 0.029953f, + 0.031525f, 0.033173f, 0.034943f, 0.036865f, 0.038696f, 0.040863f, 0.042969f, 0.045471f, 0.048004f, 0.050293f, 0.052979f, 0.055847f, + 0.058960f, 0.062042f, 0.065491f, 0.069153f, 0.072937f, 0.076660f, 0.080750f, 0.085144f, 0.089539f, 0.094177f, 0.099304f, 0.104187f, + 0.109741f, 0.114807f, 0.120483f, 0.125977f, 0.131836f, 0.138306f, 0.460449f, 0.507812f, 0.516602f, 0.520020f, 0.522461f, 0.522949f, + 0.000906f, 0.002359f, 0.003643f, 0.004356f, 0.005310f, 0.005989f, 0.007030f, 0.007507f, 0.008255f, 0.009010f, 0.009834f, 0.010483f, + 0.011230f, 0.011887f, 0.012573f, 0.013367f, 0.014252f, 0.014954f, 0.015900f, 0.016785f, 0.017776f, 0.018631f, 0.019775f, 0.020874f, + 0.022110f, 0.023117f, 0.024368f, 0.025589f, 0.026932f, 0.028549f, 0.029938f, 0.031525f, 0.033325f, 0.035187f, 0.037109f, 0.038971f, + 0.041138f, 0.043396f, 0.045715f, 0.048370f, 0.051025f, 0.053772f, 0.057129f, 0.060089f, 0.063416f, 0.067261f, 0.070679f, 0.075012f, + 0.079285f, 0.083618f, 0.088379f, 0.093018f, 0.098083f, 0.102478f, 0.108093f, 0.114380f, 0.119507f, 0.125488f, 0.448975f, 0.498291f, + 0.508789f, 0.513672f, 0.514648f, 0.516113f, 0.000728f, 0.001932f, 0.003067f, 0.003990f, 0.004784f, 0.005295f, 0.005974f, 0.006584f, + 0.007099f, 0.007652f, 0.008255f, 0.008904f, 0.009491f, 0.010109f, 0.010658f, 0.011497f, 0.012131f, 0.012718f, 0.013535f, 0.014336f, + 0.015083f, 0.016083f, 0.016785f, 0.017761f, 0.018738f, 0.019669f, 0.020691f, 0.021805f, 0.023010f, 0.024170f, 0.025467f, 0.026794f, + 0.028336f, 0.029922f, 0.031555f, 0.033203f, 0.035034f, 0.036987f, 0.039062f, 0.041290f, 0.043671f, 0.046143f, 0.048920f, 0.051880f, + 0.054901f, 0.058228f, 0.061615f, 0.065369f, 0.069214f, 0.073425f, 0.077637f, 0.082214f, 0.087097f, 0.091797f, 0.096497f, 0.102356f, + 0.107483f, 0.113464f, 0.437256f, 0.489746f, 0.500977f, 0.504883f, 0.507812f, 0.509277f, 0.000724f, 0.001842f, 0.002728f, 0.003332f, + 0.004101f, 0.004707f, 0.005020f, 0.005497f, 0.006245f, 0.006603f, 0.007027f, 0.007515f, 0.008156f, 0.008537f, 0.009125f, 0.009659f, + 0.010101f, 0.010864f, 0.011482f, 0.012070f, 0.012756f, 0.013496f, 0.014236f, 0.014931f, 0.015808f, 0.016632f, 0.017487f, 0.018433f, + 0.019379f, 0.020416f, 0.021530f, 0.022583f, 0.023804f, 0.024979f, 0.026443f, 0.027939f, 0.029526f, 0.031235f, 0.033020f, 0.035004f, + 0.037018f, 0.039185f, 0.041595f, 0.044159f, 0.046783f, 0.049866f, 0.052856f, 0.056274f, 0.059906f, 0.063721f, 0.067749f, 0.072327f, + 0.076172f, 0.081299f, 0.085938f, 0.091309f, 0.096558f, 0.101807f, 0.426270f, 0.480469f, 0.492676f, 0.498047f, 0.500488f, 0.501953f, + 0.000673f, 0.001715f, 0.002426f, 0.002953f, 0.003588f, 0.003944f, 0.004200f, 0.004776f, 0.005131f, 0.005527f, 0.005886f, 0.006371f, + 0.006790f, 0.007076f, 0.007538f, 0.008133f, 0.008644f, 0.009140f, 0.009483f, 0.010071f, 0.010689f, 0.011230f, 0.011879f, 0.012474f, + 0.013222f, 0.013916f, 0.014587f, 0.015411f, 0.016190f, 0.016983f, 0.017883f, 0.018845f, 0.019867f, 0.020935f, 0.022141f, 0.023270f, + 0.024567f, 0.026001f, 0.027481f, 0.029114f, 0.030777f, 0.032684f, 0.034698f, 0.036865f, 0.039337f, 0.041748f, 0.044647f, 0.047882f, + 0.050964f, 0.054260f, 0.058258f, 0.062195f, 0.066528f, 0.070679f, 0.075623f, 0.080505f, 0.085510f, 0.090515f, 0.414307f, 0.472168f, + 0.484131f, 0.490234f, 0.492920f, 0.495850f, 0.000484f, 0.001445f, 0.002169f, 0.002569f, 0.002836f, 0.003317f, 0.003569f, 0.003952f, + 0.004215f, 0.004623f, 0.004959f, 0.005306f, 0.005592f, 0.005951f, 0.006306f, 0.006737f, 0.007004f, 0.007492f, 0.007942f, 0.008331f, + 0.008865f, 0.009270f, 0.009781f, 0.010338f, 0.010887f, 0.011429f, 0.012047f, 0.012726f, 0.013336f, 0.014030f, 0.014771f, 0.015572f, + 0.016418f, 0.017258f, 0.018234f, 0.019196f, 0.020279f, 0.021423f, 0.022675f, 0.023987f, 0.025375f, 0.027039f, 0.028702f, 0.030563f, + 0.032623f, 0.034698f, 0.037262f, 0.040039f, 0.042664f, 0.046051f, 0.049194f, 0.052948f, 0.057129f, 0.061371f, 0.065613f, 0.070007f, + 0.075317f, 0.080200f, 0.402588f, 0.462402f, 0.476807f, 0.482666f, 0.485107f, 0.487061f, 0.000459f, 0.001265f, 0.001572f, 0.002138f, + 0.002365f, 0.002775f, 0.002920f, 0.003189f, 0.003454f, 0.003723f, 0.003986f, 0.004250f, 0.004536f, 0.004906f, 0.005150f, 0.005463f, + 0.005787f, 0.006172f, 0.006481f, 0.006794f, 0.007156f, 0.007542f, 0.007980f, 0.008430f, 0.008827f, 0.009361f, 0.009796f, 0.010300f, + 0.010910f, 0.011497f, 0.012161f, 0.012672f, 0.013336f, 0.014183f, 0.014893f, 0.015640f, 0.016541f, 0.017517f, 0.018448f, 0.019485f, + 0.020676f, 0.021912f, 0.023392f, 0.024979f, 0.026627f, 0.028351f, 0.030457f, 0.032806f, 0.035034f, 0.037933f, 0.041229f, 0.044373f, + 0.047821f, 0.052002f, 0.056244f, 0.060547f, 0.065247f, 0.069885f, 0.390869f, 0.453857f, 0.468018f, 0.475098f, 0.478027f, 0.480469f, + 0.000332f, 0.001075f, 0.001464f, 0.001721f, 0.001911f, 0.002235f, 0.002375f, 0.002558f, 0.002834f, 0.002998f, 0.003185f, 0.003441f, + 0.003647f, 0.003952f, 0.004139f, 0.004421f, 0.004631f, 0.004879f, 0.005180f, 0.005447f, 0.005795f, 0.006115f, 0.006416f, 0.006718f, + 0.007099f, 0.007462f, 0.007881f, 0.008331f, 0.008797f, 0.009140f, 0.009735f, 0.010223f, 0.010803f, 0.011337f, 0.011986f, 0.012611f, + 0.013283f, 0.014076f, 0.014847f, 0.015732f, 0.016693f, 0.017700f, 0.018784f, 0.019897f, 0.021317f, 0.022873f, 0.024429f, 0.026306f, + 0.028473f, 0.030960f, 0.033600f, 0.036407f, 0.039856f, 0.043549f, 0.047119f, 0.051392f, 0.055969f, 0.060394f, 0.379639f, 0.444580f, + 0.458984f, 0.467529f, 0.470947f, 0.472900f, 0.000408f, 0.000770f, 0.001271f, 0.001390f, 0.001601f, 0.001762f, 0.001848f, 0.002052f, + 0.002247f, 0.002401f, 0.002491f, 0.002684f, 0.002878f, 0.003086f, 0.003304f, 0.003452f, 0.003626f, 0.003805f, 0.004074f, 0.004257f, + 0.004513f, 0.004807f, 0.005039f, 0.005299f, 0.005638f, 0.005905f, 0.006191f, 0.006516f, 0.006927f, 0.007206f, 0.007645f, 0.008034f, + 0.008415f, 0.008911f, 0.009384f, 0.009941f, 0.010483f, 0.011116f, 0.011711f, 0.012428f, 0.013191f, 0.013969f, 0.014862f, 0.015854f, + 0.016785f, 0.017975f, 0.019348f, 0.020721f, 0.022461f, 0.024445f, 0.026733f, 0.029175f, 0.032227f, 0.035248f, 0.038788f, 0.042755f, + 0.046967f, 0.051636f, 0.367920f, 0.435059f, 0.452148f, 0.459229f, 0.463623f, 0.466797f, 0.000382f, 0.000669f, 0.001037f, 0.001185f, + 0.001293f, 0.001379f, 0.001470f, 0.001565f, 0.001729f, 0.001864f, 0.001928f, 0.002138f, 0.002237f, 0.002398f, 0.002510f, 0.002672f, + 0.002802f, 0.002966f, 0.003134f, 0.003319f, 0.003517f, 0.003723f, 0.003870f, 0.004089f, 0.004311f, 0.004532f, 0.004772f, 0.005013f, + 0.005314f, 0.005573f, 0.005924f, 0.006203f, 0.006523f, 0.006897f, 0.007240f, 0.007660f, 0.008041f, 0.008530f, 0.009048f, 0.009621f, + 0.010201f, 0.010841f, 0.011467f, 0.012192f, 0.013138f, 0.013969f, 0.014931f, 0.016113f, 0.017380f, 0.018936f, 0.020630f, 0.022751f, + 0.025208f, 0.027924f, 0.031311f, 0.034851f, 0.038879f, 0.043274f, 0.356689f, 0.426270f, 0.443848f, 0.451660f, 0.456055f, 0.459473f, + 0.000482f, 0.000542f, 0.000723f, 0.000822f, 0.000881f, 0.001025f, 0.001100f, 0.001209f, 0.001249f, 0.001355f, 0.001522f, 0.001599f, + 0.001708f, 0.001836f, 0.001918f, 0.001970f, 0.002129f, 0.002251f, 0.002357f, 0.002522f, 0.002636f, 0.002768f, 0.002911f, 0.003056f, + 0.003237f, 0.003393f, 0.003605f, 0.003771f, 0.003994f, 0.004234f, 0.004444f, 0.004635f, 0.004932f, 0.005150f, 0.005486f, 0.005779f, + 0.006081f, 0.006458f, 0.006775f, 0.007179f, 0.007668f, 0.008110f, 0.008690f, 0.009209f, 0.009926f, 0.010551f, 0.011330f, 0.012184f, + 0.013184f, 0.014297f, 0.015610f, 0.017181f, 0.019165f, 0.021500f, 0.024384f, 0.027618f, 0.031372f, 0.035614f, 0.345459f, 0.417236f, + 0.435303f, 0.443604f, 0.448730f, 0.451904f, 0.000240f, 0.000479f, 0.000533f, 0.000625f, 0.000716f, 0.000746f, 0.000857f, 0.000835f, + 0.000941f, 0.001024f, 0.001104f, 0.001155f, 0.001204f, 0.001282f, 0.001396f, 0.001453f, 0.001554f, 0.001627f, 0.001737f, 0.001787f, + 0.001894f, 0.002012f, 0.002119f, 0.002218f, 0.002335f, 0.002453f, 0.002611f, 0.002714f, 0.002848f, 0.003050f, 0.003168f, 0.003395f, + 0.003529f, 0.003740f, 0.003963f, 0.004158f, 0.004429f, 0.004688f, 0.004982f, 0.005280f, 0.005600f, 0.005959f, 0.006340f, 0.006775f, + 0.007252f, 0.007748f, 0.008369f, 0.008980f, 0.009705f, 0.010513f, 0.011513f, 0.012665f, 0.014069f, 0.015869f, 0.018158f, 0.020950f, + 0.024338f, 0.028366f, 0.335205f, 0.408203f, 0.427002f, 0.435547f, 0.441162f, 0.445312f, 0.000138f, 0.000265f, 0.000381f, 0.000386f, + 0.000465f, 0.000556f, 0.000558f, 0.000597f, 0.000659f, 0.000748f, 0.000770f, 0.000786f, 0.000829f, 0.000904f, 0.000940f, 0.001021f, + 0.001043f, 0.001139f, 0.001201f, 0.001253f, 0.001327f, 0.001396f, 0.001481f, 0.001555f, 0.001637f, 0.001712f, 0.001813f, 0.001899f, + 0.002005f, 0.002140f, 0.002220f, 0.002348f, 0.002462f, 0.002600f, 0.002733f, 0.002932f, 0.003075f, 0.003279f, 0.003452f, 0.003630f, + 0.003872f, 0.004166f, 0.004436f, 0.004742f, 0.005077f, 0.005459f, 0.005848f, 0.006310f, 0.006874f, 0.007492f, 0.008171f, 0.009026f, + 0.009995f, 0.011307f, 0.013008f, 0.015343f, 0.018265f, 0.021881f, 0.323486f, 0.399170f, 0.418945f, 0.428467f, 0.434326f, 0.437988f, + 0.000165f, 0.000260f, 0.000287f, 0.000296f, 0.000331f, 0.000339f, 0.000360f, 0.000395f, 0.000442f, 0.000482f, 0.000487f, 0.000551f, + 0.000546f, 0.000611f, 0.000640f, 0.000667f, 0.000711f, 0.000742f, 0.000775f, 0.000816f, 0.000876f, 0.000916f, 0.000974f, 0.001015f, + 0.001081f, 0.001123f, 0.001195f, 0.001267f, 0.001317f, 0.001388f, 0.001459f, 0.001558f, 0.001630f, 0.001718f, 0.001804f, 0.001916f, + 0.002033f, 0.002148f, 0.002295f, 0.002455f, 0.002583f, 0.002754f, 0.002941f, 0.003134f, 0.003386f, 0.003639f, 0.003910f, 0.004215f, + 0.004597f, 0.005013f, 0.005520f, 0.006130f, 0.006821f, 0.007690f, 0.008789f, 0.010452f, 0.012909f, 0.016174f, 0.312012f, 0.390381f, + 0.410645f, 0.420654f, 0.426270f, 0.430664f, 0.000057f, 0.000171f, 0.000164f, 0.000170f, 0.000211f, 0.000213f, 0.000229f, 0.000247f, + 0.000267f, 0.000279f, 0.000289f, 0.000317f, 0.000349f, 0.000364f, 0.000390f, 0.000407f, 0.000427f, 0.000467f, 0.000476f, 0.000521f, + 0.000537f, 0.000561f, 0.000578f, 0.000626f, 0.000667f, 0.000714f, 0.000729f, 0.000753f, 0.000806f, 0.000855f, 0.000911f, 0.000945f, + 0.001004f, 0.001054f, 0.001112f, 0.001172f, 0.001251f, 0.001333f, 0.001406f, 0.001489f, 0.001595f, 0.001694f, 0.001811f, 0.001952f, + 0.002090f, 0.002243f, 0.002453f, 0.002638f, 0.002888f, 0.003143f, 0.003489f, 0.003870f, 0.004353f, 0.004921f, 0.005672f, 0.006664f, + 0.008423f, 0.011230f, 0.301758f, 0.381104f, 0.402832f, 0.413330f, 0.418457f, 0.423828f, 0.000096f, 0.000112f, 0.000097f, 0.000090f, + 0.000113f, 0.000119f, 0.000144f, 0.000149f, 0.000151f, 0.000158f, 0.000181f, 0.000184f, 0.000179f, 0.000201f, 0.000224f, 0.000216f, + 0.000237f, 0.000255f, 0.000263f, 0.000276f, 0.000297f, 0.000308f, 0.000332f, 0.000347f, 0.000369f, 0.000395f, 0.000408f, 0.000422f, + 0.000447f, 0.000471f, 0.000500f, 0.000531f, 0.000554f, 0.000583f, 0.000617f, 0.000660f, 0.000690f, 0.000739f, 0.000795f, 0.000833f, + 0.000885f, 0.000948f, 0.001022f, 0.001085f, 0.001175f, 0.001262f, 0.001371f, 0.001487f, 0.001633f, 0.001778f, 0.001986f, 0.002218f, + 0.002502f, 0.002865f, 0.003330f, 0.003979f, 0.004932f, 0.007000f, 0.291260f, 0.372070f, 0.394043f, 0.404541f, 0.412109f, 0.416260f, + 0.000000f, 0.000056f, 0.000049f, 0.000061f, 0.000064f, 0.000061f, 0.000062f, 0.000071f, 0.000072f, 0.000088f, 0.000083f, 0.000086f, + 0.000097f, 0.000094f, 0.000098f, 0.000105f, 0.000116f, 0.000122f, 0.000126f, 0.000134f, 0.000137f, 0.000143f, 0.000150f, 0.000164f, + 0.000171f, 0.000183f, 0.000188f, 0.000204f, 0.000214f, 0.000224f, 0.000236f, 0.000255f, 0.000258f, 0.000277f, 0.000293f, 0.000315f, + 0.000328f, 0.000349f, 0.000376f, 0.000396f, 0.000426f, 0.000454f, 0.000486f, 0.000521f, 0.000563f, 0.000605f, 0.000657f, 0.000714f, + 0.000791f, 0.000866f, 0.000977f, 0.001085f, 0.001243f, 0.001441f, 0.001703f, 0.002058f, 0.002573f, 0.003740f, 0.280029f, 0.362793f, + 0.385742f, 0.397217f, 0.404297f, 0.408936f, 0.000058f, 0.000038f, 0.000031f, 0.000027f, 0.000025f, 0.000026f, 0.000025f, 0.000024f, + 0.000024f, 0.000027f, 0.000030f, 0.000038f, 0.000032f, 0.000035f, 0.000040f, 0.000041f, 0.000044f, 0.000045f, 0.000045f, 0.000047f, + 0.000052f, 0.000058f, 0.000061f, 0.000059f, 0.000065f, 0.000067f, 0.000069f, 0.000073f, 0.000078f, 0.000083f, 0.000089f, 0.000091f, + 0.000099f, 0.000103f, 0.000106f, 0.000114f, 0.000124f, 0.000132f, 0.000141f, 0.000150f, 0.000158f, 0.000164f, 0.000180f, 0.000193f, + 0.000205f, 0.000225f, 0.000245f, 0.000267f, 0.000297f, 0.000329f, 0.000365f, 0.000416f, 0.000479f, 0.000563f, 0.000676f, 0.000839f, + 0.001088f, 0.001589f, 0.270264f, 0.353760f, 0.377197f, 0.390137f, 0.396973f, 0.402100f, 0.000030f, 0.000019f, 0.000016f, 0.000014f, + 0.000013f, 0.000012f, 0.000011f, 0.000011f, 0.000010f, 0.000010f, 0.000009f, 0.000009f, 0.000009f, 0.000008f, 0.000007f, 0.000009f, + 0.000009f, 0.000008f, 0.000009f, 0.000010f, 0.000011f, 0.000012f, 0.000012f, 0.000014f, 0.000014f, 0.000014f, 0.000015f, 0.000018f, + 0.000017f, 0.000017f, 0.000019f, 0.000020f, 0.000022f, 0.000022f, 0.000023f, 0.000026f, 0.000028f, 0.000027f, 0.000030f, 0.000032f, + 0.000035f, 0.000038f, 0.000040f, 0.000042f, 0.000045f, 0.000049f, 0.000055f, 0.000060f, 0.000065f, 0.000074f, 0.000078f, 0.000095f, + 0.000109f, 0.000129f, 0.000160f, 0.000205f, 0.000284f, 0.000452f, 0.259766f, 0.345703f, 0.369629f, 0.382812f, 0.390625f, 0.395264f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, + 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000001f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, 0.000002f, + 0.000002f, 0.000003f, 0.000003f, 0.000004f, 0.000004f, 0.000005f, 0.000006f, 0.000009f, 0.000012f, 0.000026f, 0.249878f, 0.336182f, + 0.362061f, 0.374512f, 0.382080f, 0.387695f, + } +}; + +/* 4 different blue noise, one per channel */ +static float blue_noise[64 * 64][4] = { + {0.367188f, 0.855469f, 0.523438f, 0.375000f}, {0.242188f, 0.699219f, 0.164062f, 0.292969f}, + {0.828125f, 0.257812f, 0.449219f, 0.679688f}, {0.128906f, 0.523438f, 0.058594f, 0.164062f}, + {0.214844f, 0.648438f, 0.750000f, 0.492188f}, {0.535156f, 0.226562f, 0.492188f, 0.429688f}, + {0.050781f, 0.425781f, 0.886719f, 0.019531f}, {0.199219f, 0.785156f, 0.378906f, 0.984375f}, + {0.390625f, 0.039062f, 0.222656f, 0.777344f}, {0.574219f, 0.460938f, 0.687500f, 0.085938f}, + {0.757812f, 0.117188f, 0.968750f, 0.343750f}, {0.109375f, 0.398438f, 0.500000f, 0.871094f}, + {0.871094f, 0.796875f, 0.628906f, 0.132812f}, {0.289062f, 0.480469f, 0.851562f, 0.484375f}, + {0.519531f, 0.035156f, 0.234375f, 0.832031f}, {0.390625f, 0.558594f, 0.738281f, 0.636719f}, + {0.015625f, 0.648438f, 0.910156f, 0.507812f}, {0.199219f, 0.257812f, 0.640625f, 0.578125f}, + {0.359375f, 0.976562f, 0.855469f, 0.726562f}, {0.523438f, 0.445312f, 0.335938f, 0.304688f}, + {0.046875f, 0.296875f, 0.921875f, 0.687500f}, {0.476562f, 0.929688f, 0.777344f, 0.164062f}, + {0.726562f, 0.515625f, 0.398438f, 0.781250f}, {0.652344f, 0.156250f, 0.191406f, 0.015625f}, + {0.300781f, 0.695312f, 0.011719f, 0.417969f}, {0.433594f, 0.882812f, 0.738281f, 0.843750f}, + {0.890625f, 0.308594f, 0.523438f, 0.496094f}, {0.589844f, 0.730469f, 0.050781f, 0.886719f}, + {0.738281f, 0.539062f, 0.683594f, 0.640625f}, {0.421875f, 0.191406f, 0.265625f, 0.996094f}, + {0.609375f, 0.339844f, 0.617188f, 0.066406f}, {0.371094f, 0.398438f, 0.378906f, 0.898438f}, + {0.937500f, 0.578125f, 0.136719f, 0.136719f}, {0.453125f, 0.820312f, 0.664062f, 0.968750f}, + {0.828125f, 0.070312f, 0.316406f, 0.328125f}, {0.558594f, 0.714844f, 0.593750f, 0.714844f}, + {0.351562f, 0.781250f, 0.355469f, 0.804688f}, {0.203125f, 0.398438f, 0.214844f, 0.519531f}, + {0.785156f, 0.207031f, 0.398438f, 0.453125f}, {0.617188f, 0.289062f, 0.281250f, 0.257812f}, + {0.171875f, 0.609375f, 0.792969f, 0.027344f}, {0.539062f, 0.871094f, 0.007812f, 0.886719f}, + {0.019531f, 0.246094f, 0.226562f, 0.363281f}, {0.988281f, 0.582031f, 0.777344f, 0.054688f}, + {0.468750f, 0.933594f, 0.312500f, 0.246094f}, {0.218750f, 0.015625f, 0.851562f, 0.167969f}, + {0.566406f, 0.699219f, 0.519531f, 0.902344f}, {0.125000f, 0.507812f, 0.136719f, 0.386719f}, + {0.296875f, 0.812500f, 0.558594f, 0.203125f}, {0.402344f, 0.199219f, 0.058594f, 0.875000f}, + {0.898438f, 0.386719f, 0.664062f, 0.660156f}, {0.027344f, 0.078125f, 0.296875f, 0.453125f}, + {0.667969f, 0.828125f, 0.808594f, 0.171875f}, {0.257812f, 0.535156f, 0.464844f, 0.914062f}, + {0.597656f, 0.363281f, 0.886719f, 0.718750f}, {0.332031f, 0.042969f, 0.683594f, 0.003906f}, + {0.632812f, 0.480469f, 0.429688f, 0.425781f}, {0.226562f, 0.910156f, 0.566406f, 0.558594f}, + {0.496094f, 0.062500f, 0.863281f, 0.226562f}, {0.105469f, 0.976562f, 0.707031f, 0.941406f}, + {0.394531f, 0.203125f, 0.285156f, 0.277344f}, {0.003906f, 0.804688f, 0.781250f, 0.050781f}, + {0.210938f, 0.289062f, 0.117188f, 0.601562f}, {0.972656f, 0.179688f, 0.589844f, 0.144531f}, + {0.152344f, 0.359375f, 0.730469f, 0.449219f}, {0.765625f, 0.105469f, 0.292969f, 0.101562f}, + {0.519531f, 0.812500f, 0.617188f, 0.976562f}, {0.988281f, 0.960938f, 0.902344f, 0.054688f}, + {0.457031f, 0.738281f, 0.335938f, 0.875000f}, {0.871094f, 0.121094f, 0.195312f, 0.210938f}, + {0.781250f, 0.296875f, 0.539062f, 0.585938f}, {0.636719f, 0.667969f, 0.621094f, 0.328125f}, + {0.324219f, 0.929688f, 0.855469f, 0.148438f}, {0.984375f, 0.718750f, 0.421875f, 0.824219f}, + {0.500000f, 0.308594f, 0.757812f, 0.699219f}, {0.664062f, 0.214844f, 0.269531f, 0.558594f}, + {0.414062f, 0.984375f, 0.074219f, 0.757812f}, {0.589844f, 0.339844f, 0.925781f, 0.273438f}, + {0.089844f, 0.847656f, 0.316406f, 0.398438f}, {0.695312f, 0.921875f, 0.460938f, 0.890625f}, + {0.894531f, 0.093750f, 0.113281f, 0.347656f}, {0.562500f, 0.386719f, 0.289062f, 0.964844f}, + {0.121094f, 0.820312f, 0.003906f, 0.214844f}, {0.765625f, 0.187500f, 0.710938f, 0.914062f}, + {0.878906f, 0.773438f, 0.445312f, 0.078125f}, {0.218750f, 0.117188f, 0.613281f, 0.617188f}, + {0.085938f, 0.652344f, 0.996094f, 0.339844f}, {0.863281f, 0.359375f, 0.496094f, 0.531250f}, + {0.148438f, 0.437500f, 0.320312f, 0.695312f}, {0.503906f, 0.613281f, 0.792969f, 0.082031f}, + {0.097656f, 0.109375f, 0.960938f, 0.238281f}, {0.246094f, 0.914062f, 0.414062f, 0.328125f}, + {0.011719f, 0.648438f, 0.828125f, 0.738281f}, {0.980469f, 0.457031f, 0.343750f, 0.117188f}, + {0.140625f, 0.937500f, 0.976562f, 0.601562f}, {0.234375f, 0.867188f, 0.574219f, 0.230469f}, + {0.542969f, 0.519531f, 0.902344f, 0.402344f}, {0.027344f, 0.300781f, 0.253906f, 0.503906f}, + {0.757812f, 0.964844f, 0.949219f, 0.058594f}, {0.152344f, 0.234375f, 0.039062f, 0.925781f}, + {0.687500f, 0.628906f, 0.492188f, 0.386719f}, {0.929688f, 0.546875f, 0.667969f, 0.109375f}, + {0.269531f, 0.136719f, 0.964844f, 0.617188f}, {0.320312f, 0.464844f, 0.542969f, 0.972656f}, + {0.960938f, 0.960938f, 0.171875f, 0.093750f}, {0.355469f, 0.523438f, 0.429688f, 0.765625f}, + {0.246094f, 0.328125f, 0.992188f, 0.496094f}, {0.648438f, 0.074219f, 0.097656f, 0.605469f}, + {0.144531f, 0.648438f, 0.476562f, 0.808594f}, {0.855469f, 0.832031f, 0.195312f, 0.546875f}, + {0.925781f, 0.414062f, 0.960938f, 0.675781f}, {0.000000f, 0.113281f, 0.746094f, 0.835938f}, + {0.828125f, 0.324219f, 0.613281f, 0.500000f}, {0.699219f, 0.738281f, 0.332031f, 0.125000f}, + {0.542969f, 0.906250f, 0.898438f, 0.250000f}, {0.105469f, 0.632812f, 0.511719f, 0.062500f}, + {0.433594f, 0.273438f, 0.097656f, 0.816406f}, {0.511719f, 0.707031f, 0.593750f, 0.632812f}, + {0.179688f, 0.980469f, 0.367188f, 0.335938f}, {0.882812f, 0.113281f, 0.031250f, 0.980469f}, + {0.410156f, 0.656250f, 0.253906f, 0.675781f}, {0.039062f, 0.300781f, 0.785156f, 0.800781f}, + {0.695312f, 0.382812f, 0.386719f, 0.156250f}, {0.847656f, 0.457031f, 0.000000f, 0.847656f}, + {0.945312f, 0.542969f, 0.664062f, 0.683594f}, {0.730469f, 0.707031f, 0.238281f, 0.535156f}, + {0.472656f, 0.921875f, 0.871094f, 0.910156f}, {0.867188f, 0.601562f, 0.031250f, 0.812500f}, + {0.632812f, 0.769531f, 0.925781f, 0.625000f}, {0.433594f, 0.558594f, 0.078125f, 0.851562f}, + {0.015625f, 0.187500f, 0.792969f, 0.515625f}, {0.343750f, 0.386719f, 0.562500f, 0.773438f}, + {0.679688f, 0.035156f, 0.121094f, 0.347656f}, {0.300781f, 0.582031f, 0.703125f, 0.660156f}, + {0.152344f, 0.878906f, 0.929688f, 0.902344f}, {0.433594f, 0.507812f, 0.093750f, 0.460938f}, + {0.714844f, 0.171875f, 0.042969f, 0.531250f}, {0.828125f, 0.550781f, 0.312500f, 0.945312f}, + {0.011719f, 0.894531f, 0.136719f, 0.417969f}, {0.257812f, 0.046875f, 0.562500f, 0.226562f}, + {0.187500f, 0.601562f, 0.800781f, 0.929688f}, {0.949219f, 0.128906f, 0.437500f, 0.613281f}, + {0.816406f, 0.277344f, 0.054688f, 0.035156f}, {0.226562f, 0.425781f, 0.542969f, 0.183594f}, + {0.628906f, 0.750000f, 0.984375f, 0.113281f}, {0.839844f, 0.003906f, 0.792969f, 0.796875f}, + {0.269531f, 0.324219f, 0.496094f, 0.003906f}, {0.683594f, 0.601562f, 0.574219f, 0.546875f}, + {0.957031f, 0.703125f, 0.164062f, 0.378906f}, {0.605469f, 0.398438f, 0.078125f, 0.855469f}, + {0.449219f, 0.250000f, 0.257812f, 0.988281f}, {0.367188f, 0.964844f, 0.859375f, 0.195312f}, + {0.820312f, 0.007812f, 0.125000f, 0.753906f}, {0.625000f, 0.832031f, 0.453125f, 0.609375f}, + {0.929688f, 0.230469f, 0.246094f, 0.925781f}, {0.394531f, 0.375000f, 0.097656f, 0.550781f}, + {0.558594f, 0.148438f, 0.183594f, 0.191406f}, {0.480469f, 0.796875f, 0.488281f, 0.785156f}, + {0.714844f, 0.250000f, 0.011719f, 0.296875f}, {0.660156f, 0.085938f, 0.804688f, 0.691406f}, + {0.890625f, 0.695312f, 0.101562f, 0.855469f}, {0.320312f, 0.195312f, 0.441406f, 0.761719f}, + {0.265625f, 0.375000f, 0.765625f, 0.191406f}, {0.996094f, 0.113281f, 0.832031f, 0.585938f}, + {0.101562f, 0.882812f, 0.152344f, 0.285156f}, {0.468750f, 0.332031f, 0.722656f, 0.882812f}, + {0.656250f, 0.816406f, 0.105469f, 0.339844f}, {0.035156f, 0.703125f, 0.855469f, 0.687500f}, + {0.738281f, 0.003906f, 0.601562f, 0.566406f}, {0.441406f, 0.664062f, 0.703125f, 0.843750f}, + {0.875000f, 0.789062f, 0.839844f, 0.187500f}, {0.781250f, 0.457031f, 0.640625f, 0.996094f}, + {0.050781f, 0.210938f, 0.355469f, 0.332031f}, {0.363281f, 0.351562f, 0.039062f, 0.421875f}, + {0.429688f, 0.550781f, 0.699219f, 0.089844f}, {0.753906f, 0.917969f, 0.269531f, 0.285156f}, + {0.496094f, 0.058594f, 0.929688f, 0.980469f}, {0.343750f, 0.445312f, 0.445312f, 0.566406f}, + {0.152344f, 0.160156f, 0.003906f, 0.750000f}, {0.738281f, 0.570312f, 0.847656f, 0.941406f}, + {0.808594f, 0.027344f, 0.167969f, 0.292969f}, {0.992188f, 0.867188f, 0.921875f, 0.519531f}, + {0.074219f, 0.187500f, 0.761719f, 0.199219f}, {0.750000f, 0.597656f, 0.312500f, 0.472656f}, + {0.277344f, 0.753906f, 0.945312f, 0.089844f}, {0.796875f, 0.820312f, 0.511719f, 0.375000f}, + {0.542969f, 0.878906f, 0.191406f, 0.503906f}, {0.175781f, 0.632812f, 0.597656f, 0.109375f}, + {0.257812f, 0.335938f, 0.980469f, 0.339844f}, {0.664062f, 0.000000f, 0.542969f, 0.417969f}, + {0.324219f, 0.144531f, 0.410156f, 0.078125f}, {0.062500f, 0.437500f, 0.472656f, 0.250000f}, + {0.925781f, 0.058594f, 0.636719f, 0.332031f}, {0.269531f, 0.671875f, 0.234375f, 0.175781f}, + {0.714844f, 0.285156f, 0.382812f, 0.574219f}, {0.570312f, 0.906250f, 0.988281f, 0.414062f}, + {0.097656f, 0.460938f, 0.425781f, 0.257812f}, {0.953125f, 0.796875f, 0.265625f, 0.117188f}, + {0.589844f, 0.367188f, 0.777344f, 0.746094f}, {0.035156f, 0.082031f, 0.457031f, 0.062500f}, + {0.226562f, 0.253906f, 0.953125f, 0.628906f}, {0.527344f, 0.417969f, 0.519531f, 0.261719f}, + {0.132812f, 0.812500f, 0.828125f, 0.000000f}, {0.906250f, 0.660156f, 0.386719f, 0.367188f}, + {0.742188f, 0.500000f, 0.207031f, 0.093750f}, {0.359375f, 0.769531f, 0.609375f, 0.718750f}, + {0.480469f, 0.695312f, 0.679688f, 0.539062f}, {0.144531f, 0.179688f, 0.757812f, 0.765625f}, + {0.332031f, 0.625000f, 0.179688f, 0.679688f}, {0.445312f, 0.492188f, 0.378906f, 0.425781f}, + {0.035156f, 0.550781f, 0.230469f, 0.476562f}, {0.402344f, 0.898438f, 0.898438f, 0.652344f}, + {0.156250f, 0.046875f, 0.820312f, 0.132812f}, {0.328125f, 0.484375f, 0.679688f, 0.246094f}, + {0.746094f, 0.750000f, 0.363281f, 0.453125f}, {0.238281f, 0.863281f, 0.558594f, 0.105469f}, + {0.023438f, 0.289062f, 0.648438f, 0.292969f}, {0.683594f, 0.566406f, 0.906250f, 0.804688f}, + {0.335938f, 0.773438f, 0.601562f, 0.375000f}, {0.781250f, 0.496094f, 0.710938f, 0.023438f}, + {0.847656f, 0.996094f, 0.929688f, 0.425781f}, {0.308594f, 0.027344f, 0.656250f, 0.871094f}, + {0.183594f, 0.625000f, 0.292969f, 0.480469f}, {0.089844f, 0.753906f, 0.164062f, 0.363281f}, + {0.804688f, 0.476562f, 0.687500f, 0.011719f}, {0.503906f, 0.910156f, 0.523438f, 0.644531f}, + {0.605469f, 0.609375f, 0.203125f, 0.441406f}, {0.417969f, 0.742188f, 0.621094f, 0.085938f}, + {0.839844f, 0.441406f, 0.296875f, 0.679688f}, {0.531250f, 0.042969f, 0.929688f, 0.781250f}, + {0.378906f, 0.929688f, 0.460938f, 0.148438f}, {0.902344f, 0.238281f, 0.050781f, 0.222656f}, + {0.570312f, 0.378906f, 0.328125f, 0.390625f}, {0.105469f, 0.121094f, 0.253906f, 0.460938f}, + {0.500000f, 0.906250f, 0.515625f, 0.281250f}, {0.296875f, 0.160156f, 0.148438f, 0.664062f}, + {0.699219f, 0.722656f, 0.757812f, 0.007812f}, {0.539062f, 0.968750f, 0.589844f, 0.914062f}, + {0.253906f, 0.246094f, 0.406250f, 0.769531f}, {0.609375f, 0.613281f, 0.105469f, 0.707031f}, + {0.195312f, 0.687500f, 0.179688f, 0.031250f}, {0.949219f, 0.523438f, 0.785156f, 0.339844f}, + {0.863281f, 0.804688f, 0.234375f, 0.433594f}, {0.230469f, 0.355469f, 0.648438f, 0.687500f}, + {0.304688f, 0.757812f, 0.421875f, 0.378906f}, {0.375000f, 0.464844f, 0.539062f, 0.046875f}, + {0.558594f, 0.324219f, 0.214844f, 0.761719f}, {0.679688f, 0.410156f, 0.074219f, 0.839844f}, + {0.464844f, 0.519531f, 0.710938f, 0.281250f}, {0.968750f, 0.152344f, 0.140625f, 0.925781f}, + {0.359375f, 0.230469f, 0.902344f, 0.609375f}, {0.593750f, 0.097656f, 0.457031f, 0.761719f}, + {0.441406f, 0.785156f, 0.058594f, 0.960938f}, {0.125000f, 0.890625f, 0.312500f, 0.203125f}, + {0.812500f, 0.488281f, 0.804688f, 0.878906f}, {0.558594f, 0.992188f, 0.175781f, 0.742188f}, + {0.179688f, 0.222656f, 0.343750f, 0.039062f}, {0.789062f, 0.871094f, 0.843750f, 0.949219f}, + {0.902344f, 0.503906f, 0.507812f, 0.718750f}, {0.402344f, 0.625000f, 0.027344f, 0.011719f}, + {0.195312f, 0.152344f, 0.605469f, 0.929688f}, {0.753906f, 0.214844f, 0.160156f, 0.839844f}, + {0.488281f, 0.687500f, 0.671875f, 0.390625f}, {0.851562f, 0.992188f, 0.363281f, 0.191406f}, + {0.933594f, 0.617188f, 0.230469f, 0.308594f}, {0.375000f, 0.746094f, 0.656250f, 0.867188f}, + {0.613281f, 0.105469f, 0.898438f, 0.671875f}, {0.316406f, 0.371094f, 0.714844f, 0.503906f}, + {0.687500f, 0.234375f, 0.031250f, 0.808594f}, {0.550781f, 0.957031f, 0.957031f, 0.433594f}, + {0.023438f, 0.539062f, 0.351562f, 0.308594f}, {0.964844f, 0.359375f, 0.261719f, 0.980469f}, + {0.750000f, 0.941406f, 0.863281f, 0.234375f}, {0.906250f, 0.863281f, 0.605469f, 0.863281f}, + {0.503906f, 0.109375f, 0.093750f, 0.289062f}, {0.582031f, 0.238281f, 0.414062f, 0.949219f}, + {0.792969f, 0.992188f, 0.308594f, 0.757812f}, {0.062500f, 0.164062f, 0.039062f, 0.816406f}, + {0.902344f, 0.542969f, 0.933594f, 0.675781f}, {0.554688f, 0.085938f, 0.726562f, 0.507812f}, + {0.984375f, 0.460938f, 0.175781f, 0.890625f}, {0.468750f, 0.179688f, 0.027344f, 0.140625f}, + {0.125000f, 0.679688f, 0.304688f, 0.468750f}, {0.203125f, 0.058594f, 0.531250f, 0.953125f}, + {0.070312f, 0.328125f, 0.375000f, 0.667969f}, {0.746094f, 0.554688f, 0.785156f, 0.578125f}, + {0.917969f, 0.421875f, 0.558594f, 0.089844f}, {0.445312f, 0.289062f, 0.855469f, 0.937500f}, + {0.378906f, 0.156250f, 0.398438f, 0.539062f}, {0.066406f, 0.015625f, 0.335938f, 0.265625f}, + {0.730469f, 0.812500f, 0.878906f, 0.820312f}, {0.191406f, 0.535156f, 0.015625f, 0.988281f}, + {0.046875f, 0.171875f, 0.554688f, 0.484375f}, {0.777344f, 0.656250f, 0.375000f, 0.015625f}, + {0.230469f, 0.488281f, 0.238281f, 0.535156f}, {0.144531f, 0.578125f, 0.750000f, 0.910156f}, + {0.812500f, 0.757812f, 0.910156f, 0.714844f}, {0.207031f, 0.429688f, 0.386719f, 0.042969f}, + {0.945312f, 0.292969f, 0.023438f, 0.136719f}, {0.597656f, 0.859375f, 0.941406f, 0.742188f}, + {0.171875f, 0.593750f, 0.289062f, 0.519531f}, {0.914062f, 0.031250f, 0.886719f, 0.234375f}, + {0.808594f, 0.773438f, 0.824219f, 0.160156f}, {0.082031f, 0.132812f, 0.496094f, 0.464844f}, + {0.664062f, 0.871094f, 0.675781f, 0.597656f}, {0.042969f, 0.289062f, 0.546875f, 0.195312f}, + {0.453125f, 0.996094f, 0.363281f, 0.859375f}, {0.585938f, 0.226562f, 0.718750f, 0.140625f}, + {0.648438f, 0.093750f, 0.277344f, 0.609375f}, {0.035156f, 0.933594f, 0.980469f, 0.898438f}, + {0.910156f, 0.671875f, 0.625000f, 0.410156f}, {0.210938f, 0.246094f, 0.472656f, 0.578125f}, + {0.136719f, 0.960938f, 0.832031f, 0.031250f}, {0.066406f, 0.054688f, 0.656250f, 0.660156f}, + {0.898438f, 0.714844f, 0.347656f, 0.218750f}, {0.765625f, 0.589844f, 0.820312f, 0.449219f}, + {0.023438f, 0.398438f, 0.734375f, 0.011719f}, {0.960938f, 0.253906f, 0.132812f, 0.582031f}, + {0.378906f, 0.644531f, 0.945312f, 0.480469f}, {0.496094f, 0.320312f, 0.683594f, 0.656250f}, + {0.085938f, 0.722656f, 0.105469f, 0.386719f}, {0.316406f, 0.414062f, 0.753906f, 0.226562f}, + {0.046875f, 0.011719f, 0.199219f, 0.464844f}, {0.621094f, 0.968750f, 0.714844f, 0.300781f}, + {0.878906f, 0.726562f, 0.863281f, 0.593750f}, {0.257812f, 0.312500f, 0.324219f, 0.523438f}, + {0.347656f, 0.835938f, 0.816406f, 0.687500f}, {0.074219f, 0.480469f, 0.000000f, 0.972656f}, + {0.656250f, 0.007812f, 0.578125f, 0.785156f}, {0.792969f, 0.914062f, 0.152344f, 0.570312f}, + {0.464844f, 0.292969f, 0.292969f, 0.152344f}, {0.863281f, 0.843750f, 0.101562f, 0.957031f}, + {0.066406f, 0.449219f, 0.484375f, 0.199219f}, {0.437500f, 0.019531f, 0.878906f, 0.886719f}, + {0.800781f, 0.074219f, 0.132812f, 0.136719f}, {0.296875f, 0.800781f, 0.511719f, 0.488281f}, + {0.656250f, 0.253906f, 0.019531f, 0.371094f}, {0.101562f, 0.148438f, 0.726562f, 0.609375f}, + {0.203125f, 0.664062f, 0.660156f, 0.089844f}, {0.976562f, 0.437500f, 0.972656f, 0.175781f}, + {0.289062f, 0.781250f, 0.765625f, 0.578125f}, {0.660156f, 0.343750f, 0.519531f, 0.312500f}, + {0.507812f, 0.625000f, 0.441406f, 0.019531f}, {0.175781f, 0.933594f, 0.230469f, 0.394531f}, + {0.796875f, 0.722656f, 0.824219f, 0.570312f}, {0.277344f, 0.410156f, 0.406250f, 0.226562f}, + {0.597656f, 0.949219f, 0.761719f, 0.707031f}, {0.949219f, 0.609375f, 0.882812f, 0.070312f}, + {0.519531f, 0.859375f, 0.128906f, 0.273438f}, {0.632812f, 0.203125f, 0.042969f, 0.156250f}, + {0.265625f, 0.890625f, 0.449219f, 0.812500f}, {0.585938f, 0.664062f, 0.230469f, 0.210938f}, + {0.968750f, 0.960938f, 0.742188f, 0.726562f}, {0.226562f, 0.339844f, 0.992188f, 0.117188f}, + {0.875000f, 0.410156f, 0.093750f, 0.894531f}, {0.640625f, 0.261719f, 0.710938f, 0.324219f}, + {0.917969f, 0.980469f, 0.425781f, 0.234375f}, {0.308594f, 0.300781f, 0.804688f, 0.628906f}, + {0.589844f, 0.105469f, 0.648438f, 0.421875f}, {0.714844f, 0.847656f, 0.125000f, 0.808594f}, + {0.406250f, 0.187500f, 0.480469f, 0.300781f}, {0.667969f, 0.992188f, 0.679688f, 0.960938f}, + {0.070312f, 0.542969f, 0.800781f, 0.859375f}, {0.835938f, 0.082031f, 0.554688f, 0.578125f}, + {0.398438f, 0.496094f, 0.449219f, 0.402344f}, {0.113281f, 0.398438f, 0.222656f, 0.828125f}, + {0.460938f, 0.308594f, 0.054688f, 0.625000f}, {0.976562f, 0.472656f, 0.984375f, 0.375000f}, + {0.281250f, 0.203125f, 0.312500f, 0.937500f}, {0.386719f, 0.000000f, 0.875000f, 0.785156f}, + {0.785156f, 0.402344f, 0.078125f, 0.527344f}, {0.117188f, 0.644531f, 0.812500f, 0.082031f}, + {0.941406f, 0.503906f, 0.132812f, 0.972656f}, {0.488281f, 0.140625f, 0.023438f, 0.238281f}, + {0.832031f, 0.843750f, 0.859375f, 0.167969f}, {0.335938f, 0.011719f, 0.382812f, 0.730469f}, + {0.628906f, 0.777344f, 0.570312f, 0.875000f}, {0.527344f, 0.355469f, 0.285156f, 0.132812f}, + {0.234375f, 0.472656f, 0.093750f, 0.312500f}, {0.308594f, 0.941406f, 0.214844f, 0.820312f}, + {0.640625f, 0.164062f, 0.628906f, 0.714844f}, {0.871094f, 0.832031f, 0.390625f, 0.156250f}, + {0.218750f, 0.531250f, 0.265625f, 0.289062f}, {0.699219f, 0.117188f, 0.550781f, 0.796875f}, + {0.980469f, 0.578125f, 0.890625f, 0.125000f}, {0.523438f, 0.824219f, 0.460938f, 0.890625f}, + {0.445312f, 0.347656f, 0.285156f, 0.675781f}, {0.816406f, 0.097656f, 0.949219f, 0.781250f}, + {0.140625f, 0.550781f, 0.089844f, 0.160156f}, {0.675781f, 0.421875f, 0.484375f, 0.074219f}, + {0.542969f, 0.062500f, 0.535156f, 0.230469f}, {0.421875f, 0.570312f, 0.886719f, 0.484375f}, + {0.167969f, 0.339844f, 0.734375f, 0.035156f}, {0.277344f, 0.199219f, 0.425781f, 0.441406f}, + {0.093750f, 0.527344f, 0.996094f, 0.714844f}, {0.214844f, 0.148438f, 0.632812f, 0.335938f}, + {0.941406f, 0.585938f, 0.242188f, 0.593750f}, {0.160156f, 0.886719f, 0.410156f, 0.652344f}, + {0.597656f, 0.679688f, 0.812500f, 0.019531f}, {0.242188f, 0.312500f, 0.585938f, 0.562500f}, + {0.531250f, 0.460938f, 0.937500f, 0.921875f}, {0.375000f, 0.734375f, 0.328125f, 0.054688f}, + {0.703125f, 0.382812f, 0.472656f, 0.734375f}, {0.824219f, 0.835938f, 0.140625f, 0.519531f}, + {0.441406f, 0.289062f, 0.203125f, 0.414062f}, {0.121094f, 0.691406f, 0.628906f, 0.925781f}, + {0.378906f, 0.019531f, 0.105469f, 0.082031f}, {0.714844f, 0.222656f, 0.347656f, 0.734375f}, + {0.046875f, 0.816406f, 0.968750f, 0.976562f}, {0.421875f, 0.320312f, 0.078125f, 0.628906f}, + {0.871094f, 0.097656f, 0.484375f, 0.835938f}, {0.695312f, 0.265625f, 0.207031f, 0.332031f}, + {0.351562f, 0.718750f, 0.273438f, 0.761719f}, {0.406250f, 0.382812f, 0.957031f, 0.511719f}, + {0.042969f, 0.785156f, 0.628906f, 0.980469f}, {0.832031f, 0.117188f, 0.910156f, 0.343750f}, + {0.144531f, 0.500000f, 0.058594f, 0.421875f}, {0.699219f, 0.843750f, 0.589844f, 0.601562f}, + {0.546875f, 0.574219f, 0.488281f, 0.164062f}, {0.363281f, 0.054688f, 0.265625f, 0.390625f}, + {0.128906f, 0.785156f, 0.949219f, 0.746094f}, {0.492188f, 0.691406f, 0.175781f, 0.949219f}, + {0.972656f, 0.902344f, 0.894531f, 0.183594f}, {0.027344f, 0.359375f, 0.570312f, 0.070312f}, + {0.273438f, 0.062500f, 0.207031f, 0.500000f}, {0.472656f, 0.730469f, 0.972656f, 0.613281f}, + {0.351562f, 0.640625f, 0.089844f, 0.363281f}, {0.742188f, 0.226562f, 0.187500f, 0.195312f}, + {0.234375f, 0.699219f, 0.730469f, 0.945312f}, {0.625000f, 0.945312f, 0.636719f, 0.082031f}, + {0.328125f, 0.839844f, 0.378906f, 0.312500f}, {0.707031f, 0.652344f, 0.574219f, 0.875000f}, + {0.566406f, 0.742188f, 0.148438f, 0.050781f}, {0.882812f, 0.921875f, 0.460938f, 0.246094f}, + {0.519531f, 0.585938f, 0.917969f, 0.656250f}, {0.730469f, 0.718750f, 0.597656f, 0.316406f}, + {0.261719f, 0.808594f, 0.500000f, 0.460938f}, {0.171875f, 0.285156f, 0.324219f, 0.796875f}, + {0.773438f, 0.562500f, 0.746094f, 0.546875f}, {0.433594f, 0.429688f, 0.183594f, 0.343750f}, + {0.726562f, 0.628906f, 0.050781f, 0.488281f}, {0.859375f, 0.898438f, 0.972656f, 0.996094f}, + {0.402344f, 0.542969f, 0.429688f, 0.402344f}, {0.101562f, 0.304688f, 0.535156f, 0.542969f}, + {0.476562f, 0.675781f, 0.863281f, 0.902344f}, {0.734375f, 0.035156f, 0.488281f, 0.359375f}, + {0.289062f, 0.761719f, 0.773438f, 0.976562f}, {0.589844f, 0.949219f, 0.007812f, 0.519531f}, + {0.843750f, 0.269531f, 0.417969f, 0.835938f}, {0.664062f, 0.183594f, 0.144531f, 0.554688f}, + {0.226562f, 0.652344f, 0.656250f, 0.085938f}, {0.367188f, 0.789062f, 0.562500f, 0.957031f}, + {0.972656f, 0.238281f, 0.394531f, 0.433594f}, {0.000000f, 0.894531f, 0.207031f, 0.644531f}, + {0.777344f, 0.136719f, 0.968750f, 0.820312f}, {0.910156f, 0.949219f, 0.261719f, 0.355469f}, + {0.722656f, 0.785156f, 0.070312f, 0.917969f}, {0.996094f, 0.707031f, 0.792969f, 0.105469f}, + {0.562500f, 0.644531f, 0.511719f, 0.246094f}, {0.648438f, 0.937500f, 0.335938f, 0.851562f}, + {0.398438f, 0.738281f, 0.777344f, 0.078125f}, {0.832031f, 0.410156f, 0.695312f, 0.285156f}, + {0.722656f, 0.210938f, 0.167969f, 0.785156f}, {0.042969f, 0.609375f, 0.296875f, 0.214844f}, + {0.863281f, 0.976562f, 0.441406f, 0.824219f}, {0.167969f, 0.027344f, 0.066406f, 0.664062f}, + {0.609375f, 0.562500f, 0.828125f, 0.347656f}, {0.000000f, 0.191406f, 0.562500f, 0.839844f}, + {0.250000f, 0.070312f, 0.281250f, 0.207031f}, {0.875000f, 0.875000f, 0.917969f, 0.644531f}, + {0.941406f, 0.523438f, 0.781250f, 0.867188f}, {0.617188f, 0.378906f, 0.687500f, 0.343750f}, + {0.316406f, 0.132812f, 0.546875f, 0.171875f}, {0.542969f, 0.574219f, 0.609375f, 0.101562f}, + {0.230469f, 0.484375f, 0.851562f, 0.433594f}, {0.007812f, 0.828125f, 0.671875f, 0.910156f}, + {0.160156f, 0.160156f, 0.734375f, 0.605469f}, {0.890625f, 0.527344f, 0.351562f, 0.394531f}, + {0.757812f, 0.042969f, 0.511719f, 0.039062f}, {0.507812f, 0.593750f, 0.144531f, 0.640625f}, + {0.335938f, 0.238281f, 0.316406f, 0.781250f}, {0.464844f, 0.726562f, 0.191406f, 0.500000f}, + {0.000000f, 0.093750f, 0.667969f, 0.707031f}, {0.273438f, 0.636719f, 0.843750f, 0.031250f}, + {0.746094f, 0.210938f, 0.101562f, 0.570312f}, {0.437500f, 0.421875f, 0.343750f, 0.832031f}, + {0.625000f, 0.519531f, 0.027344f, 0.355469f}, {0.824219f, 0.613281f, 0.777344f, 0.667969f}, + {0.886719f, 0.261719f, 0.296875f, 0.121094f}, {0.554688f, 0.476562f, 0.609375f, 0.777344f}, + {0.992188f, 0.328125f, 0.417969f, 0.253906f}, {0.007812f, 0.812500f, 0.339844f, 0.050781f}, + {0.519531f, 0.371094f, 0.921875f, 0.476562f}, {0.867188f, 0.167969f, 0.121094f, 0.660156f}, + {0.773438f, 0.054688f, 0.789062f, 0.718750f}, {0.066406f, 0.535156f, 0.253906f, 0.128906f}, + {0.156250f, 0.343750f, 0.753906f, 0.503906f}, {0.218750f, 0.437500f, 0.027344f, 0.410156f}, + {0.347656f, 0.070312f, 0.398438f, 0.839844f}, {0.019531f, 0.175781f, 0.222656f, 0.714844f}, + {0.410156f, 0.375000f, 0.953125f, 0.011719f}, {0.605469f, 0.886719f, 0.652344f, 0.640625f}, + {0.093750f, 0.082031f, 0.414062f, 0.097656f}, {0.289062f, 0.707031f, 0.886719f, 0.269531f}, + {0.003906f, 0.195312f, 0.242188f, 0.691406f}, {0.980469f, 0.261719f, 0.781250f, 0.070312f}, + {0.671875f, 0.070312f, 0.722656f, 0.621094f}, {0.820312f, 0.851562f, 0.914062f, 0.250000f}, + {0.550781f, 0.429688f, 0.164062f, 0.097656f}, {0.140625f, 0.210938f, 0.082031f, 0.671875f}, + {0.042969f, 0.367188f, 0.996094f, 0.054688f}, {0.394531f, 0.457031f, 0.605469f, 0.613281f}, + {0.164062f, 0.695312f, 0.312500f, 0.417969f}, {0.109375f, 0.132812f, 0.929688f, 0.320312f}, + {0.734375f, 0.937500f, 0.800781f, 0.207031f}, {0.578125f, 0.476562f, 0.039062f, 0.367188f}, + {0.500000f, 0.382812f, 0.761719f, 0.859375f}, {0.304688f, 0.750000f, 0.628906f, 0.273438f}, + {0.207031f, 0.617188f, 0.121094f, 0.730469f}, {0.597656f, 0.269531f, 0.683594f, 0.140625f}, + {0.324219f, 0.445312f, 0.371094f, 0.613281f}, {0.027344f, 0.386719f, 0.187500f, 0.761719f}, + {0.507812f, 0.093750f, 0.597656f, 0.546875f}, {0.769531f, 0.250000f, 0.015625f, 0.386719f}, + {0.265625f, 0.335938f, 0.914062f, 0.472656f}, {0.335938f, 0.113281f, 0.539062f, 0.972656f}, + {0.496094f, 0.828125f, 0.078125f, 0.730469f}, {0.980469f, 0.507812f, 0.656250f, 0.410156f}, + {0.410156f, 0.093750f, 0.871094f, 0.148438f}, {0.777344f, 0.910156f, 0.238281f, 0.464844f}, + {0.929688f, 0.644531f, 0.746094f, 0.253906f}, {0.343750f, 0.488281f, 0.394531f, 0.992188f}, + {0.566406f, 0.949219f, 0.011719f, 0.117188f}, {0.476562f, 0.597656f, 0.859375f, 0.476562f}, + {0.210938f, 0.449219f, 0.476562f, 0.273438f}, {0.816406f, 0.902344f, 0.156250f, 0.542969f}, + {0.093750f, 0.738281f, 0.253906f, 0.773438f}, {0.964844f, 0.640625f, 0.316406f, 0.500000f}, + {0.738281f, 0.925781f, 0.007812f, 0.257812f}, {0.828125f, 0.066406f, 0.433594f, 0.000000f}, + {0.457031f, 0.437500f, 0.578125f, 0.187500f}, {0.667969f, 0.980469f, 0.089844f, 0.699219f}, + {0.207031f, 0.351562f, 0.824219f, 0.886719f}, {0.105469f, 0.902344f, 0.703125f, 0.246094f}, + {0.933594f, 0.183594f, 0.796875f, 0.070312f}, {0.796875f, 0.449219f, 0.457031f, 0.925781f}, + {0.656250f, 0.945312f, 0.378906f, 0.289062f}, {0.957031f, 0.878906f, 0.769531f, 0.875000f}, + {0.847656f, 0.335938f, 0.531250f, 0.097656f}, {0.089844f, 0.128906f, 0.628906f, 0.464844f}, + {0.199219f, 0.824219f, 0.437500f, 0.273438f}, {0.335938f, 0.035156f, 0.507812f, 0.925781f}, + {0.113281f, 0.773438f, 0.839844f, 0.554688f}, {0.160156f, 0.925781f, 0.042969f, 0.437500f}, + {0.695312f, 0.132812f, 0.875000f, 0.687500f}, {0.300781f, 0.007812f, 0.519531f, 0.878906f}, + {0.921875f, 0.898438f, 0.671875f, 0.800781f}, {0.187500f, 0.582031f, 0.000000f, 0.539062f}, + {0.421875f, 0.253906f, 0.484375f, 0.265625f}, {0.503906f, 0.800781f, 0.945312f, 0.988281f}, + {0.917969f, 0.117188f, 0.625000f, 0.753906f}, {0.812500f, 0.859375f, 0.707031f, 0.578125f}, + {0.671875f, 0.269531f, 0.296875f, 0.171875f}, {0.984375f, 0.949219f, 0.769531f, 0.367188f}, + {0.847656f, 0.476562f, 0.156250f, 0.957031f}, {0.703125f, 0.613281f, 0.554688f, 0.867188f}, + {0.890625f, 0.328125f, 0.101562f, 0.421875f}, {0.503906f, 0.976562f, 0.687500f, 0.910156f}, + {0.570312f, 0.511719f, 0.503906f, 0.777344f}, {0.156250f, 0.808594f, 0.597656f, 0.179688f}, + {0.355469f, 0.125000f, 0.019531f, 0.839844f}, {0.199219f, 0.730469f, 0.308594f, 0.738281f}, + {0.949219f, 0.984375f, 0.671875f, 0.496094f}, {0.429688f, 0.613281f, 0.246094f, 0.199219f}, + {0.910156f, 0.085938f, 0.363281f, 0.765625f}, {0.769531f, 0.878906f, 0.707031f, 0.261719f}, + {0.472656f, 0.519531f, 0.187500f, 0.000000f}, {0.894531f, 0.328125f, 0.519531f, 0.750000f}, + {0.277344f, 0.593750f, 0.238281f, 0.632812f}, {0.058594f, 0.855469f, 0.359375f, 0.500000f}, + {0.855469f, 0.023438f, 0.910156f, 0.027344f}, {0.699219f, 0.523438f, 0.449219f, 0.562500f}, + {0.457031f, 0.667969f, 0.308594f, 0.980469f}, {0.125000f, 0.175781f, 0.824219f, 0.312500f}, + {0.867188f, 0.867188f, 0.476562f, 0.414062f}, {0.375000f, 0.027344f, 0.929688f, 0.882812f}, + {0.683594f, 0.812500f, 0.851562f, 0.175781f}, {0.117188f, 0.480469f, 0.125000f, 0.804688f}, + {0.878906f, 0.980469f, 0.210938f, 0.679688f}, {0.058594f, 0.554688f, 0.378906f, 0.042969f}, + {0.628906f, 0.167969f, 0.976562f, 0.527344f}, {0.132812f, 0.757812f, 0.769531f, 0.621094f}, + {0.308594f, 0.371094f, 0.191406f, 0.312500f}, {0.464844f, 0.273438f, 0.527344f, 0.898438f}, + {0.085938f, 0.808594f, 0.960938f, 0.007812f}, {0.734375f, 0.324219f, 0.691406f, 0.757812f}, + {0.671875f, 0.105469f, 0.339844f, 0.593750f}, {0.058594f, 0.765625f, 0.585938f, 0.703125f}, + {0.761719f, 0.246094f, 0.062500f, 0.031250f}, {0.156250f, 0.167969f, 0.417969f, 0.917969f}, + {0.355469f, 0.035156f, 0.800781f, 0.382812f}, {0.644531f, 0.281250f, 0.925781f, 0.683594f}, + {0.496094f, 0.773438f, 0.136719f, 0.957031f}, {0.121094f, 0.226562f, 0.890625f, 0.562500f}, + {0.304688f, 0.699219f, 0.187500f, 0.824219f}, {0.992188f, 0.628906f, 0.980469f, 0.457031f}, + {0.550781f, 0.300781f, 0.410156f, 0.308594f}, {0.621094f, 0.761719f, 0.242188f, 0.148438f}, + {0.292969f, 0.671875f, 0.609375f, 0.816406f}, {0.414062f, 0.386719f, 0.000000f, 0.445312f}, + {0.167969f, 0.289062f, 0.890625f, 0.207031f}, {0.238281f, 0.542969f, 0.140625f, 0.523438f}, + {0.566406f, 0.710938f, 0.218750f, 0.625000f}, {0.382812f, 0.464844f, 0.980469f, 0.156250f}, + {0.785156f, 0.972656f, 0.695312f, 0.730469f}, {0.535156f, 0.199219f, 0.246094f, 0.863281f}, + {0.648438f, 0.390625f, 0.371094f, 0.210938f}, {0.425781f, 0.550781f, 0.722656f, 0.000000f}, + {0.773438f, 0.671875f, 0.140625f, 0.980469f}, {0.585938f, 0.425781f, 0.234375f, 0.304688f}, + {0.105469f, 0.734375f, 0.812500f, 0.164062f}, {0.656250f, 0.460938f, 0.281250f, 0.421875f}, + {0.277344f, 0.632812f, 0.863281f, 0.351562f}, {0.031250f, 0.968750f, 0.347656f, 0.015625f}, + {0.613281f, 0.195312f, 0.195312f, 0.214844f}, {0.445312f, 0.507812f, 0.527344f, 0.906250f}, + {0.296875f, 0.777344f, 0.855469f, 0.093750f}, {0.132812f, 0.660156f, 0.062500f, 0.285156f}, + {0.546875f, 0.031250f, 0.457031f, 0.496094f}, {0.195312f, 0.230469f, 0.808594f, 0.144531f}, + {0.375000f, 0.750000f, 0.273438f, 0.210938f}, {0.933594f, 0.156250f, 0.941406f, 0.601562f}, + {0.230469f, 0.402344f, 0.355469f, 0.367188f}, {0.753906f, 0.656250f, 0.128906f, 0.449219f}, + {0.058594f, 0.351562f, 0.464844f, 0.015625f}, {0.597656f, 0.570312f, 0.398438f, 0.957031f}, + {0.789062f, 0.289062f, 0.824219f, 0.386719f}, {0.246094f, 0.492188f, 0.578125f, 0.863281f}, + {0.636719f, 0.792969f, 0.046875f, 0.457031f}, {0.332031f, 0.019531f, 0.839844f, 0.929688f}, + {0.207031f, 0.410156f, 0.109375f, 0.707031f}, {0.617188f, 0.765625f, 0.621094f, 0.992188f}, + {0.960938f, 0.066406f, 0.691406f, 0.132812f}, {0.417969f, 0.289062f, 0.074219f, 0.906250f}, + {0.789062f, 0.207031f, 0.851562f, 0.769531f}, {0.093750f, 0.972656f, 0.171875f, 0.183594f}, + {0.937500f, 0.101562f, 0.726562f, 0.066406f}, {0.253906f, 0.324219f, 0.554688f, 0.527344f}, + {0.820312f, 0.503906f, 0.062500f, 0.656250f}, {0.476562f, 0.593750f, 0.648438f, 0.007812f}, + {0.179688f, 0.910156f, 0.281250f, 0.289062f}, {0.957031f, 0.062500f, 0.445312f, 0.921875f}, + {0.441406f, 0.632812f, 0.726562f, 0.128906f}, {0.574219f, 0.292969f, 0.621094f, 0.234375f}, + {0.203125f, 0.875000f, 0.476562f, 0.363281f}, {0.679688f, 0.667969f, 0.031250f, 0.945312f}, + {0.914062f, 0.441406f, 0.347656f, 0.097656f}, {0.546875f, 0.214844f, 0.609375f, 0.687500f}, + {0.191406f, 0.718750f, 0.113281f, 0.550781f}, {0.269531f, 0.148438f, 0.164062f, 0.375000f}, + {0.992188f, 0.414062f, 0.898438f, 0.164062f}, {0.398438f, 0.652344f, 0.652344f, 0.429688f}, + {0.523438f, 0.351562f, 0.210938f, 0.800781f}, {0.863281f, 0.820312f, 0.992188f, 0.218750f}, + {0.437500f, 0.988281f, 0.707031f, 0.066406f}, {0.261719f, 0.421875f, 0.382812f, 0.859375f}, + {0.921875f, 0.339844f, 0.644531f, 0.132812f}, {0.585938f, 0.539062f, 0.746094f, 0.359375f}, + {0.386719f, 0.855469f, 0.488281f, 0.738281f}, {0.804688f, 0.019531f, 0.289062f, 0.105469f}, + {0.253906f, 0.480469f, 0.050781f, 0.539062f}, {0.027344f, 0.109375f, 0.867188f, 0.945312f}, + {0.898438f, 0.828125f, 0.523438f, 0.582031f}, {0.718750f, 0.046875f, 0.964844f, 0.339844f}, + {0.519531f, 0.152344f, 0.281250f, 0.675781f}, {0.062500f, 0.765625f, 0.570312f, 0.984375f}, + {0.886719f, 0.003906f, 0.738281f, 0.792969f}, {0.687500f, 0.257812f, 0.316406f, 0.410156f}, + {0.019531f, 0.585938f, 0.078125f, 0.039062f}, {0.964844f, 0.660156f, 0.164062f, 0.320312f}, + {0.257812f, 0.863281f, 0.941406f, 0.597656f}, {0.906250f, 0.292969f, 0.640625f, 0.386719f}, + {0.214844f, 0.960938f, 0.472656f, 0.746094f}, {0.464844f, 0.214844f, 0.996094f, 0.628906f}, + {0.378906f, 0.851562f, 0.558594f, 0.097656f}, {0.820312f, 0.300781f, 0.394531f, 0.898438f}, + {0.718750f, 0.066406f, 0.597656f, 0.566406f}, {0.968750f, 0.406250f, 0.085938f, 0.843750f}, + {0.363281f, 0.687500f, 0.433594f, 0.683594f}, {0.750000f, 0.574219f, 0.125000f, 0.437500f}, + {0.078125f, 0.316406f, 0.980469f, 0.617188f}, {0.636719f, 0.136719f, 0.675781f, 0.812500f}, + {0.468750f, 0.910156f, 0.367188f, 0.757812f}, {0.324219f, 0.546875f, 0.910156f, 0.554688f}, + {0.050781f, 0.832031f, 0.003906f, 0.671875f}, {0.808594f, 0.054688f, 0.203125f, 0.042969f}, + {0.625000f, 0.929688f, 0.632812f, 0.937500f}, {0.460938f, 0.468750f, 0.796875f, 0.523438f}, + {0.882812f, 0.003906f, 0.964844f, 0.292969f}, {0.304688f, 0.902344f, 0.195312f, 0.589844f}, + {0.503906f, 0.160156f, 0.515625f, 0.128906f}, {0.011719f, 0.671875f, 0.933594f, 0.328125f}, + {0.714844f, 0.250000f, 0.765625f, 0.570312f}, {0.539062f, 0.921875f, 0.472656f, 0.167969f}, + {0.820312f, 0.187500f, 0.871094f, 0.355469f}, {0.031250f, 0.996094f, 0.953125f, 0.476562f}, + {0.355469f, 0.628906f, 0.425781f, 0.289062f}, {0.554688f, 0.449219f, 0.578125f, 0.593750f}, + {0.183594f, 0.710938f, 0.273438f, 0.398438f}, {0.644531f, 0.359375f, 0.511719f, 0.695312f}, + {0.398438f, 0.820312f, 0.015625f, 0.464844f}, {0.535156f, 0.925781f, 0.941406f, 0.933594f}, + {0.628906f, 0.691406f, 0.238281f, 0.222656f}, {0.074219f, 0.222656f, 0.402344f, 0.707031f}, + {0.785156f, 0.757812f, 0.761719f, 0.496094f}, {0.242188f, 0.367188f, 0.570312f, 0.589844f}, + {0.726562f, 0.718750f, 0.320312f, 0.445312f}, {0.925781f, 0.417969f, 0.890625f, 0.863281f}, + {0.382812f, 0.000000f, 0.261719f, 0.753906f}, {0.753906f, 0.953125f, 0.839844f, 0.179688f}, + {0.023438f, 0.078125f, 0.414062f, 0.832031f}, {0.843750f, 0.597656f, 0.906250f, 0.496094f}, + {0.617188f, 0.894531f, 0.492188f, 0.792969f}, {0.886719f, 0.542969f, 0.261719f, 0.289062f}, + {0.140625f, 0.968750f, 0.437500f, 0.960938f}, {0.296875f, 0.046875f, 0.757812f, 0.851562f}, + {0.601562f, 0.710938f, 0.300781f, 0.324219f}, {0.699219f, 0.500000f, 0.496094f, 0.574219f}, + {0.019531f, 0.558594f, 0.035156f, 0.648438f}, {0.785156f, 0.675781f, 0.535156f, 0.449219f}, + {0.078125f, 0.089844f, 0.234375f, 0.300781f}, {0.191406f, 0.175781f, 0.339844f, 0.617188f}, + {0.714844f, 0.398438f, 0.785156f, 0.222656f}, {0.054688f, 0.921875f, 0.562500f, 0.875000f}, + {0.488281f, 0.257812f, 0.683594f, 0.652344f}, {0.765625f, 0.566406f, 0.335938f, 0.386719f}, + {0.371094f, 0.957031f, 0.121094f, 0.750000f}, {0.117188f, 0.511719f, 0.718750f, 0.007812f}, + {0.820312f, 0.871094f, 0.421875f, 0.125000f}, {0.453125f, 0.617188f, 0.062500f, 0.371094f}, + {0.613281f, 0.937500f, 0.914062f, 0.246094f}, {0.300781f, 0.371094f, 0.460938f, 0.703125f}, + {0.480469f, 0.078125f, 0.863281f, 0.957031f}, {0.730469f, 0.746094f, 0.785156f, 0.488281f}, + {0.363281f, 0.164062f, 0.566406f, 0.812500f}, {0.074219f, 0.093750f, 0.093750f, 0.140625f}, + {0.859375f, 0.503906f, 0.320312f, 0.527344f}, {0.039062f, 0.050781f, 0.765625f, 0.464844f}, + {0.953125f, 0.566406f, 0.058594f, 0.222656f}, {0.531250f, 0.156250f, 0.156250f, 0.773438f}, + {0.230469f, 0.914062f, 0.738281f, 0.644531f}, {0.117188f, 0.750000f, 0.898438f, 0.152344f}, + {0.574219f, 0.363281f, 0.656250f, 0.484375f}, {0.179688f, 0.011719f, 0.808594f, 0.312500f}, + {0.894531f, 0.980469f, 0.328125f, 0.941406f}, {0.246094f, 0.730469f, 0.242188f, 0.066406f}, + {0.949219f, 0.386719f, 0.609375f, 0.398438f}, {0.781250f, 0.445312f, 0.511719f, 0.257812f}, + {0.675781f, 0.679688f, 0.730469f, 0.843750f}, {0.121094f, 0.273438f, 0.433594f, 0.324219f}, + {0.273438f, 0.582031f, 0.855469f, 0.726562f}, {0.390625f, 0.863281f, 0.289062f, 0.816406f}, + {0.699219f, 0.226562f, 0.707031f, 0.218750f}, {0.925781f, 0.757812f, 0.078125f, 0.687500f}, + {0.128906f, 0.382812f, 0.640625f, 0.906250f}, {0.382812f, 0.101562f, 0.140625f, 0.789062f}, + {0.988281f, 0.843750f, 0.273438f, 0.074219f}, {0.093750f, 0.562500f, 0.386719f, 0.660156f}, + {0.441406f, 0.726562f, 0.230469f, 0.218750f}, {0.746094f, 0.238281f, 0.023438f, 0.875000f}, + {0.683594f, 0.109375f, 0.750000f, 0.042969f}, {0.238281f, 0.898438f, 0.328125f, 0.812500f}, + {0.902344f, 0.796875f, 0.988281f, 0.230469f}, {0.335938f, 0.574219f, 0.792969f, 0.335938f}, + {0.015625f, 0.035156f, 0.613281f, 0.835938f}, {0.738281f, 0.414062f, 0.343750f, 0.101562f}, + {0.976562f, 0.128906f, 0.867188f, 0.789062f}, {0.308594f, 0.285156f, 0.148438f, 0.371094f}, + {0.554688f, 0.535156f, 0.980469f, 0.964844f}, {0.351562f, 0.191406f, 0.046875f, 0.074219f}, + {0.003906f, 0.140625f, 0.812500f, 0.324219f}, {0.515625f, 0.804688f, 0.101562f, 0.644531f}, + {0.292969f, 0.242188f, 0.152344f, 0.546875f}, {0.816406f, 0.527344f, 0.554688f, 0.277344f}, + {0.246094f, 0.343750f, 0.664062f, 0.050781f}, {0.425781f, 0.839844f, 0.058594f, 0.425781f}, + {0.347656f, 0.031250f, 0.714844f, 0.207031f}, {0.496094f, 0.460938f, 0.804688f, 0.652344f}, + {0.800781f, 0.226562f, 0.078125f, 0.058594f}, {0.039062f, 0.859375f, 0.546875f, 0.484375f}, + {0.945312f, 0.300781f, 0.847656f, 0.109375f}, {0.226562f, 0.121094f, 0.121094f, 0.933594f}, + {0.906250f, 0.210938f, 0.878906f, 0.746094f}, {0.546875f, 0.875000f, 0.601562f, 0.187500f}, + {0.675781f, 0.953125f, 0.085938f, 0.804688f}, {0.339844f, 0.601562f, 0.933594f, 0.507812f}, + {0.859375f, 0.792969f, 0.023438f, 0.996094f}, {0.429688f, 0.128906f, 0.156250f, 0.031250f}, + {0.929688f, 0.742188f, 0.906250f, 0.269531f}, {0.179688f, 0.203125f, 0.453125f, 0.484375f}, + {0.671875f, 0.640625f, 0.644531f, 0.195312f}, {0.582031f, 0.328125f, 0.191406f, 0.847656f}, + {0.976562f, 0.425781f, 0.832031f, 0.601562f}, {0.343750f, 0.191406f, 0.347656f, 0.906250f}, + {0.210938f, 0.488281f, 0.605469f, 0.062500f}, {0.941406f, 0.804688f, 0.023438f, 0.546875f}, + {0.101562f, 0.910156f, 0.527344f, 0.191406f}, {0.175781f, 0.437500f, 0.402344f, 0.648438f}, + {0.820312f, 0.332031f, 0.265625f, 0.914062f}, {0.515625f, 0.636719f, 0.882812f, 0.062500f}, + {0.621094f, 0.785156f, 0.429688f, 0.253906f}, {0.746094f, 0.707031f, 0.199219f, 0.937500f}, + {0.152344f, 0.355469f, 0.683594f, 0.332031f}, {0.332031f, 0.804688f, 0.457031f, 0.074219f}, + {0.878906f, 0.492188f, 0.964844f, 0.968750f}, {0.480469f, 0.109375f, 0.226562f, 0.382812f}, + {0.792969f, 0.867188f, 0.035156f, 0.042969f}, {0.417969f, 0.234375f, 0.480469f, 0.734375f}, + {0.843750f, 0.464844f, 0.566406f, 0.539062f}, {0.511719f, 0.609375f, 0.171875f, 0.187500f}, + {0.011719f, 0.062500f, 0.046875f, 0.703125f}, {0.582031f, 0.191406f, 0.871094f, 0.968750f}, + {0.429688f, 0.347656f, 0.308594f, 0.121094f}, {0.988281f, 0.777344f, 0.578125f, 0.484375f}, + {0.527344f, 0.109375f, 0.152344f, 0.078125f}, {0.085938f, 0.320312f, 0.050781f, 0.160156f}, + {0.835938f, 0.699219f, 0.539062f, 0.640625f}, {0.558594f, 0.531250f, 0.890625f, 0.433594f}, + {0.183594f, 0.968750f, 0.332031f, 0.031250f}, {0.660156f, 0.449219f, 0.433594f, 0.269531f}, + {0.851562f, 0.640625f, 0.722656f, 0.503906f}, {0.289062f, 0.347656f, 0.558594f, 0.835938f}, + {0.156250f, 0.488281f, 0.171875f, 0.101562f}, {0.878906f, 0.828125f, 0.804688f, 0.550781f}, + {0.511719f, 0.386719f, 0.492188f, 0.437500f}, {0.132812f, 0.531250f, 0.148438f, 0.671875f}, + {0.765625f, 0.144531f, 0.101562f, 0.117188f}, {0.484375f, 0.257812f, 0.210938f, 0.910156f}, + {0.835938f, 0.480469f, 0.433594f, 0.574219f}, {0.152344f, 0.628906f, 0.699219f, 0.269531f}, + {0.214844f, 0.773438f, 0.089844f, 0.441406f}, {0.417969f, 0.992188f, 0.535156f, 0.152344f}, + {0.898438f, 0.453125f, 0.667969f, 0.746094f}, {0.640625f, 0.867188f, 0.195312f, 0.207031f}, + {0.148438f, 0.578125f, 0.507812f, 0.796875f}, {0.855469f, 0.921875f, 0.699219f, 0.027344f}, + {0.097656f, 0.468750f, 0.960938f, 0.988281f}, {0.585938f, 0.625000f, 0.757812f, 0.382812f}, + {0.160156f, 0.773438f, 0.300781f, 0.613281f}, {0.714844f, 0.183594f, 0.214844f, 0.875000f}, + {0.070312f, 0.691406f, 0.980469f, 0.937500f}, {0.656250f, 0.375000f, 0.332031f, 0.125000f}, + {0.746094f, 0.789062f, 0.621094f, 0.738281f}, {0.457031f, 0.585938f, 0.949219f, 0.605469f}, + {0.335938f, 0.933594f, 0.179688f, 0.253906f}, {0.171875f, 0.625000f, 0.359375f, 0.523438f}, + {0.386719f, 0.457031f, 0.730469f, 0.394531f}, {0.472656f, 0.003906f, 0.273438f, 0.039062f}, + {0.281250f, 0.726562f, 0.457031f, 0.902344f}, {0.972656f, 0.488281f, 0.832031f, 0.093750f}, + {0.617188f, 0.312500f, 0.406250f, 0.414062f}, {0.136719f, 0.660156f, 0.613281f, 0.687500f}, + {0.562500f, 0.441406f, 0.226562f, 0.781250f}, {0.324219f, 0.375000f, 0.800781f, 0.074219f}, + {0.871094f, 0.808594f, 0.082031f, 0.964844f}, {0.269531f, 0.089844f, 0.941406f, 0.699219f}, + {0.011719f, 0.250000f, 0.503906f, 0.503906f}, {0.148438f, 0.671875f, 0.242188f, 0.300781f}, + {0.707031f, 0.125000f, 0.679688f, 0.453125f}, {0.843750f, 0.296875f, 0.812500f, 0.835938f}, + {0.417969f, 0.566406f, 0.187500f, 0.113281f}, {0.578125f, 0.226562f, 0.652344f, 0.285156f}, + {0.675781f, 0.523438f, 0.718750f, 0.363281f}, {0.312500f, 0.894531f, 0.039062f, 0.691406f}, + {0.406250f, 0.398438f, 0.605469f, 0.781250f}, {0.265625f, 0.246094f, 0.917969f, 0.851562f}, + {0.570312f, 0.992188f, 0.843750f, 0.589844f}, {0.644531f, 0.605469f, 0.339844f, 0.714844f}, + {0.003906f, 0.269531f, 0.531250f, 0.511719f}, {0.699219f, 0.652344f, 0.296875f, 0.277344f}, + {0.312500f, 0.546875f, 0.710938f, 0.824219f}, {0.054688f, 0.152344f, 0.402344f, 0.238281f}, + {0.667969f, 0.796875f, 0.914062f, 0.875000f}, {0.351562f, 0.281250f, 0.769531f, 0.351562f}, + {0.730469f, 0.839844f, 0.691406f, 0.000000f}, {0.289062f, 0.894531f, 0.394531f, 0.632812f}, + {0.152344f, 0.519531f, 0.113281f, 0.429688f}, {0.867188f, 0.988281f, 0.992188f, 0.582031f}, + {0.210938f, 0.636719f, 0.480469f, 0.878906f}, {0.640625f, 0.171875f, 0.753906f, 0.984375f}, + {0.023438f, 0.425781f, 0.371094f, 0.343750f}, {0.437500f, 0.039062f, 0.222656f, 0.539062f}, + {0.257812f, 0.800781f, 0.835938f, 0.718750f}, {0.777344f, 0.300781f, 0.007812f, 0.964844f}, + {0.484375f, 0.054688f, 0.984375f, 0.406250f}, {0.582031f, 0.140625f, 0.664062f, 0.617188f}, + {0.398438f, 0.597656f, 0.906250f, 0.933594f}, {0.933594f, 0.019531f, 0.367188f, 0.726562f}, + {0.312500f, 0.691406f, 0.601562f, 0.164062f}, {0.074219f, 0.320312f, 0.882812f, 0.964844f}, + {0.589844f, 0.644531f, 0.679688f, 0.515625f}, {0.949219f, 0.964844f, 0.375000f, 0.742188f}, + {0.281250f, 0.187500f, 0.910156f, 0.023438f}, {0.687500f, 0.886719f, 0.773438f, 0.640625f}, + {0.597656f, 0.343750f, 0.292969f, 0.871094f}, {0.054688f, 0.089844f, 0.464844f, 0.535156f}, + {0.808594f, 0.015625f, 0.839844f, 0.613281f}, {0.710938f, 0.675781f, 0.339844f, 0.902344f}, + {0.484375f, 0.320312f, 0.429688f, 0.406250f}, {0.988281f, 0.062500f, 0.242188f, 0.687500f}, + {0.664062f, 0.707031f, 0.375000f, 0.140625f}, {0.460938f, 0.128906f, 0.019531f, 0.480469f}, + {0.960938f, 0.296875f, 0.453125f, 0.707031f}, {0.535156f, 0.980469f, 0.828125f, 0.246094f}, + {0.894531f, 0.101562f, 0.578125f, 0.570312f}, {0.218750f, 0.273438f, 0.398438f, 0.335938f}, + {0.113281f, 0.507812f, 0.000000f, 0.406250f}, {0.554688f, 0.160156f, 0.242188f, 0.890625f}, + {0.828125f, 0.066406f, 0.671875f, 0.695312f}, {0.632812f, 0.398438f, 0.425781f, 0.148438f}, + {0.730469f, 0.781250f, 0.785156f, 0.968750f}, {0.125000f, 0.273438f, 0.964844f, 0.281250f}, + {0.820312f, 0.371094f, 0.191406f, 0.707031f}, {0.031250f, 0.218750f, 0.695312f, 0.585938f}, + {0.507812f, 0.054688f, 0.511719f, 0.343750f}, {0.242188f, 0.890625f, 0.988281f, 0.167969f}, + {0.734375f, 0.972656f, 0.730469f, 0.531250f}, {0.070312f, 0.011719f, 0.285156f, 0.316406f}, + {0.460938f, 0.707031f, 0.394531f, 0.417969f}, {0.781250f, 0.546875f, 0.585938f, 0.234375f}, + {0.402344f, 0.992188f, 0.769531f, 0.152344f}, {0.644531f, 0.738281f, 0.148438f, 0.773438f}, + {0.757812f, 0.855469f, 0.976562f, 0.636719f}, {0.539062f, 0.050781f, 0.382812f, 0.390625f}, + {0.246094f, 0.714844f, 0.296875f, 0.742188f}, {0.910156f, 0.972656f, 0.125000f, 0.886719f}, + {0.128906f, 0.011719f, 0.960938f, 0.445312f}, {0.984375f, 0.828125f, 0.351562f, 0.554688f}, + {0.054688f, 0.132812f, 0.511719f, 0.175781f}, {0.800781f, 0.464844f, 0.117188f, 0.398438f}, + {0.921875f, 0.027344f, 0.257812f, 0.019531f}, {0.437500f, 0.191406f, 0.015625f, 0.441406f}, + {0.203125f, 0.433594f, 0.785156f, 0.195312f}, {0.996094f, 0.953125f, 0.632812f, 0.917969f}, + {0.257812f, 0.335938f, 0.144531f, 0.652344f}, {0.617188f, 0.703125f, 0.835938f, 0.101562f}, + {0.941406f, 0.929688f, 0.265625f, 0.597656f}, {0.109375f, 0.503906f, 0.097656f, 0.468750f}, + {0.195312f, 0.093750f, 0.957031f, 0.785156f}, {0.917969f, 0.714844f, 0.218750f, 0.906250f}, + {0.761719f, 0.242188f, 0.648438f, 0.281250f}, {0.367188f, 0.019531f, 0.789062f, 0.195312f}, + {0.707031f, 0.480469f, 0.253906f, 0.386719f}, {0.328125f, 0.828125f, 0.917969f, 0.757812f}, + {0.960938f, 0.941406f, 0.667969f, 0.242188f}, {0.742188f, 0.601562f, 0.601562f, 0.105469f}, + {0.347656f, 0.203125f, 0.496094f, 0.871094f}, {0.886719f, 0.687500f, 0.777344f, 0.152344f}, + {0.046875f, 0.886719f, 0.089844f, 0.316406f}, {0.222656f, 0.957031f, 0.316406f, 0.773438f}, + {0.625000f, 0.750000f, 0.527344f, 0.253906f}, {0.003906f, 0.277344f, 0.050781f, 0.382812f}, + {0.660156f, 0.937500f, 0.250000f, 0.328125f}, {0.808594f, 0.078125f, 0.734375f, 0.625000f}, + {0.437500f, 0.425781f, 0.460938f, 0.281250f}, {0.386719f, 0.738281f, 0.566406f, 0.394531f}, + {0.039062f, 0.050781f, 0.035156f, 0.175781f}, {0.523438f, 0.546875f, 0.175781f, 0.996094f}, + {0.925781f, 0.714844f, 0.957031f, 0.347656f}, {0.453125f, 0.843750f, 0.585938f, 0.039062f}, + {0.109375f, 0.617188f, 0.003906f, 0.296875f}, {0.269531f, 0.406250f, 0.750000f, 0.109375f}, + {0.390625f, 0.949219f, 0.933594f, 0.519531f}, {0.207031f, 0.222656f, 0.597656f, 0.238281f}, + {0.332031f, 0.378906f, 0.640625f, 0.820312f}, {0.785156f, 0.898438f, 0.914062f, 0.906250f}, + {0.054688f, 0.496094f, 0.523438f, 0.085938f}, {0.386719f, 0.417969f, 0.089844f, 0.777344f}, + {0.304688f, 0.562500f, 0.148438f, 0.031250f}, {0.929688f, 0.925781f, 0.773438f, 0.519531f}, + {0.414062f, 0.667969f, 0.468750f, 0.195312f}, {0.257812f, 0.738281f, 0.835938f, 0.800781f}, + {0.972656f, 0.332031f, 0.519531f, 0.003906f}, {0.078125f, 0.847656f, 0.062500f, 0.359375f}, + {0.882812f, 0.691406f, 0.566406f, 0.625000f}, {0.585938f, 0.148438f, 0.140625f, 0.777344f}, + {0.214844f, 0.941406f, 0.652344f, 0.476562f}, {0.757812f, 0.824219f, 0.308594f, 0.238281f}, + {0.402344f, 0.527344f, 0.113281f, 0.867188f}, {0.945312f, 0.585938f, 0.359375f, 0.937500f}, + {0.839844f, 0.277344f, 0.062500f, 0.621094f}, {0.632812f, 0.167969f, 0.550781f, 0.804688f}, + {0.222656f, 0.464844f, 0.894531f, 0.914062f}, {0.535156f, 0.882812f, 0.011719f, 0.566406f}, + {0.886719f, 0.039062f, 0.312500f, 0.085938f}, {0.496094f, 0.394531f, 0.449219f, 0.875000f}, + {0.085938f, 0.593750f, 0.097656f, 0.972656f}, {0.289062f, 0.343750f, 0.742188f, 0.011719f}, + {0.031250f, 0.460938f, 0.894531f, 0.589844f}, {0.777344f, 0.156250f, 0.488281f, 0.222656f}, + {0.468750f, 0.679688f, 0.835938f, 0.042969f}, {0.195312f, 0.281250f, 0.230469f, 0.992188f}, + {0.718750f, 0.589844f, 0.796875f, 0.109375f}, {0.492188f, 0.921875f, 0.667969f, 0.667969f}, + {0.097656f, 0.667969f, 0.390625f, 0.292969f}, {0.835938f, 0.871094f, 0.582031f, 0.871094f}, + {0.378906f, 0.097656f, 0.878906f, 0.128906f}, {0.753906f, 0.765625f, 0.078125f, 0.558594f}, + {0.503906f, 0.039062f, 0.937500f, 0.761719f}, {0.148438f, 0.207031f, 0.515625f, 0.425781f}, + {0.816406f, 0.421875f, 0.593750f, 0.996094f}, {0.390625f, 0.367188f, 0.335938f, 0.136719f}, + {0.550781f, 0.656250f, 0.441406f, 0.226562f}, {0.488281f, 0.144531f, 0.828125f, 0.523438f}, + {0.605469f, 0.593750f, 0.531250f, 0.734375f}, {0.035156f, 0.390625f, 0.347656f, 0.671875f}, + {0.464844f, 0.742188f, 0.019531f, 0.023438f}, {0.812500f, 0.265625f, 0.421875f, 0.492188f}, + {0.164062f, 0.359375f, 0.101562f, 0.605469f}, {0.507812f, 0.121094f, 0.171875f, 0.800781f}, + {0.605469f, 0.503906f, 0.933594f, 0.453125f}, {0.082031f, 0.250000f, 0.261719f, 0.203125f}, + {0.968750f, 0.550781f, 0.460938f, 0.570312f}, {0.718750f, 0.410156f, 0.628906f, 0.054688f}, + {0.835938f, 0.105469f, 0.710938f, 0.468750f}, {0.359375f, 0.457031f, 0.421875f, 0.894531f}, + {0.250000f, 0.875000f, 0.968750f, 0.015625f}, {0.996094f, 0.210938f, 0.074219f, 0.855469f}, + {0.179688f, 0.785156f, 0.304688f, 0.074219f}, {0.714844f, 0.855469f, 0.832031f, 0.804688f}, + {0.230469f, 0.296875f, 0.500000f, 0.488281f}, {0.859375f, 0.394531f, 0.253906f, 0.222656f}, + {0.324219f, 0.230469f, 0.640625f, 0.679688f}, {0.765625f, 0.511719f, 0.390625f, 0.820312f}, + {0.179688f, 0.269531f, 0.222656f, 0.726562f}, {0.843750f, 0.121094f, 0.128906f, 0.468750f}, + {0.609375f, 0.781250f, 0.859375f, 0.960938f}, {0.035156f, 0.531250f, 0.066406f, 0.335938f}, + {0.734375f, 0.855469f, 0.167969f, 0.578125f}, {0.261719f, 0.023438f, 0.324219f, 0.175781f}, + {0.867188f, 0.652344f, 0.875000f, 0.304688f}, {0.632812f, 0.746094f, 0.683594f, 0.371094f}, + {0.183594f, 0.214844f, 0.273438f, 0.851562f}, {0.773438f, 0.832031f, 0.921875f, 0.667969f}, + {0.589844f, 0.011719f, 0.703125f, 0.992188f}, {0.691406f, 0.433594f, 0.113281f, 0.300781f}, + {0.003906f, 0.246094f, 0.933594f, 0.457031f}, {0.511719f, 0.984375f, 0.320312f, 0.843750f}, + {0.300781f, 0.496094f, 0.886719f, 0.203125f}, {0.433594f, 0.578125f, 0.390625f, 0.539062f}, + {0.914062f, 0.648438f, 0.007812f, 0.121094f}, {0.085938f, 0.421875f, 0.867188f, 0.824219f}, + {0.683594f, 0.117188f, 0.753906f, 0.015625f}, {0.304688f, 0.750000f, 0.210938f, 0.460938f}, + {0.113281f, 0.355469f, 0.828125f, 0.113281f}, {0.367188f, 0.843750f, 0.472656f, 0.718750f}, + {0.988281f, 0.621094f, 0.167969f, 0.035156f}, {0.050781f, 0.308594f, 0.710938f, 0.363281f}, + {0.171875f, 0.144531f, 0.871094f, 0.667969f}, {0.929688f, 0.515625f, 0.648438f, 0.265625f}, + {0.363281f, 0.781250f, 0.542969f, 0.183594f}, {0.859375f, 0.203125f, 0.226562f, 0.335938f}, + {0.609375f, 0.878906f, 0.574219f, 0.496094f}, {0.386719f, 0.621094f, 0.003906f, 0.800781f}, + {0.644531f, 0.378906f, 0.628906f, 0.625000f}, {0.871094f, 0.757812f, 0.437500f, 0.324219f}, + {0.238281f, 0.082031f, 0.160156f, 0.750000f}, {0.355469f, 0.535156f, 0.984375f, 0.519531f}, + {0.691406f, 0.308594f, 0.734375f, 0.960938f}, {0.167969f, 0.722656f, 0.480469f, 0.628906f}, + {0.550781f, 0.390625f, 0.179688f, 0.792969f}, {0.070312f, 0.511719f, 0.441406f, 0.347656f}, + {0.906250f, 0.843750f, 0.363281f, 0.023438f}, {0.589844f, 0.636719f, 0.203125f, 0.289062f}, + {0.449219f, 0.070312f, 0.007812f, 0.695312f}, {0.238281f, 0.566406f, 0.746094f, 0.382812f}, + {0.683594f, 0.953125f, 0.492188f, 0.832031f}, {0.855469f, 0.324219f, 0.062500f, 0.328125f}, + {0.093750f, 0.812500f, 0.156250f, 0.093750f}, {0.253906f, 0.917969f, 0.609375f, 0.929688f}, + {0.925781f, 0.550781f, 0.710938f, 0.812500f}, {0.574219f, 0.082031f, 0.843750f, 0.304688f}, + {0.109375f, 0.894531f, 0.308594f, 0.066406f}, {0.234375f, 0.718750f, 0.550781f, 0.941406f}, + {0.683594f, 0.851562f, 0.699219f, 0.371094f}, {0.410156f, 0.773438f, 0.402344f, 0.636719f}, + {0.308594f, 0.335938f, 0.136719f, 0.843750f}, {0.519531f, 0.175781f, 0.820312f, 0.687500f}, + {0.109375f, 0.820312f, 0.292969f, 0.527344f}, {0.457031f, 0.539062f, 0.183594f, 0.191406f}, + {0.742188f, 0.617188f, 0.847656f, 0.750000f}, {0.539062f, 0.363281f, 0.617188f, 0.566406f}, + {0.085938f, 0.500000f, 0.140625f, 0.449219f}, {0.890625f, 0.578125f, 0.937500f, 0.699219f}, + {0.632812f, 0.113281f, 0.664062f, 0.917969f}, {0.128906f, 0.660156f, 0.105469f, 0.582031f}, + {0.375000f, 0.933594f, 0.812500f, 0.410156f}, {0.652344f, 0.160156f, 0.882812f, 0.132812f}, + {0.503906f, 0.820312f, 0.691406f, 0.253906f}, {0.941406f, 0.457031f, 0.300781f, 0.851562f}, + {0.550781f, 0.734375f, 0.546875f, 0.656250f}, {0.902344f, 0.175781f, 0.488281f, 0.000000f}, + {0.437500f, 0.593750f, 0.730469f, 0.753906f}, {0.125000f, 0.261719f, 0.785156f, 0.437500f}, + {0.570312f, 0.816406f, 0.203125f, 0.632812f}, {0.500000f, 0.074219f, 0.417969f, 0.949219f}, + {0.031250f, 0.351562f, 0.632812f, 0.472656f}, {0.839844f, 0.601562f, 0.343750f, 0.152344f}, + {0.136719f, 0.128906f, 0.187500f, 0.753906f}, {0.476562f, 0.886719f, 0.597656f, 0.101562f}, + {0.371094f, 0.550781f, 0.265625f, 0.578125f}, {0.792969f, 0.187500f, 0.722656f, 0.925781f}, + {0.164062f, 0.089844f, 0.203125f, 0.070312f}, {0.660156f, 0.035156f, 0.617188f, 0.417969f}, + {0.359375f, 0.324219f, 0.476562f, 0.671875f}, {0.539062f, 0.871094f, 0.542969f, 0.300781f}, + {0.812500f, 0.195312f, 0.925781f, 0.750000f}, {0.171875f, 0.675781f, 0.433594f, 0.394531f}, + {0.492188f, 0.066406f, 0.597656f, 0.210938f}, {0.710938f, 0.507812f, 0.675781f, 0.281250f}, + {0.574219f, 0.765625f, 0.964844f, 0.851562f}, {0.808594f, 0.226562f, 0.250000f, 0.468750f}, + {0.316406f, 0.925781f, 0.367188f, 0.757812f}, {0.675781f, 0.656250f, 0.816406f, 0.429688f}, + {0.214844f, 0.265625f, 0.062500f, 0.539062f}, {0.457031f, 0.953125f, 0.937500f, 0.722656f}, + {0.972656f, 0.101562f, 0.410156f, 0.132812f}, {0.070312f, 0.800781f, 0.320312f, 0.929688f}, + {0.320312f, 0.500000f, 0.769531f, 0.261719f}, {0.527344f, 0.218750f, 0.085938f, 0.472656f}, + {0.015625f, 0.851562f, 0.550781f, 0.820312f}, {0.960938f, 0.359375f, 0.285156f, 0.210938f}, + {0.609375f, 0.144531f, 0.062500f, 0.371094f}, {0.292969f, 0.812500f, 0.925781f, 0.058594f}, + {0.664062f, 0.226562f, 0.308594f, 0.242188f}, {0.863281f, 0.582031f, 0.671875f, 0.488281f}, + {0.332031f, 0.292969f, 0.765625f, 0.945312f}, {0.023438f, 0.910156f, 0.988281f, 0.183594f}, + {0.726562f, 0.734375f, 0.621094f, 0.531250f}, {0.968750f, 0.261719f, 0.898438f, 0.902344f}, + {0.058594f, 0.851562f, 0.675781f, 0.046875f}, {0.320312f, 0.187500f, 0.292969f, 0.609375f}, + {0.781250f, 0.449219f, 0.949219f, 0.167969f}, {0.410156f, 0.054688f, 0.882812f, 0.441406f}, + {0.667969f, 0.210938f, 0.207031f, 0.542969f}, {0.296875f, 0.667969f, 0.468750f, 0.855469f}, + {0.871094f, 0.417969f, 0.980469f, 0.148438f}, {0.761719f, 0.164062f, 0.765625f, 0.699219f}, + {0.914062f, 0.460938f, 0.035156f, 0.511719f}, {0.148438f, 0.027344f, 0.871094f, 0.007812f}, + {0.800781f, 0.929688f, 0.210938f, 0.988281f}, {0.199219f, 0.675781f, 0.945312f, 0.128906f}, + {0.574219f, 0.230469f, 0.027344f, 0.796875f}, {0.875000f, 0.980469f, 0.781250f, 0.648438f}, + {0.140625f, 0.144531f, 0.542969f, 0.968750f}, {0.609375f, 0.003906f, 0.359375f, 0.238281f}, + {0.335938f, 0.683594f, 0.222656f, 0.148438f}, {0.476562f, 0.171875f, 0.761719f, 0.308594f}, + {0.757812f, 0.902344f, 0.402344f, 0.105469f}, {0.562500f, 0.445312f, 0.324219f, 0.757812f}, + {0.972656f, 0.039062f, 0.527344f, 0.050781f}, {0.019531f, 0.570312f, 0.054688f, 0.933594f}, + {0.296875f, 0.964844f, 0.457031f, 0.562500f}, {0.695312f, 0.351562f, 0.984375f, 0.183594f}, + {0.078125f, 0.636719f, 0.800781f, 0.382812f}, {0.347656f, 0.082031f, 0.402344f, 0.093750f}, + {0.804688f, 0.988281f, 0.257812f, 0.921875f}, {0.191406f, 0.316406f, 0.101562f, 0.535156f}, + {0.707031f, 0.453125f, 0.570312f, 0.722656f}, {0.937500f, 0.160156f, 0.996094f, 0.050781f}, + {0.363281f, 0.960938f, 0.023438f, 0.230469f}, {0.671875f, 0.480469f, 0.496094f, 0.414062f}, + {0.320312f, 0.296875f, 0.859375f, 0.554688f}, {0.949219f, 0.644531f, 0.386719f, 0.261719f}, + {0.867188f, 0.757812f, 0.035156f, 0.648438f}, {0.226562f, 0.359375f, 0.460938f, 0.726562f}, + {0.714844f, 0.804688f, 0.816406f, 0.328125f}, {0.996094f, 0.914062f, 0.980469f, 0.886719f}, + {0.023438f, 0.257812f, 0.250000f, 0.976562f}, {0.265625f, 0.773438f, 0.789062f, 0.171875f}, + {0.605469f, 0.472656f, 0.046875f, 0.636719f}, {0.449219f, 0.945312f, 0.273438f, 0.957031f}, + {0.902344f, 0.250000f, 0.128906f, 0.582031f}, {0.000000f, 0.906250f, 0.332031f, 0.519531f}, + {0.273438f, 0.101562f, 0.042969f, 0.175781f}, {0.421875f, 0.386719f, 0.515625f, 0.988281f}, + {0.742188f, 0.820312f, 0.605469f, 0.605469f}, {0.589844f, 0.453125f, 0.132812f, 0.066406f}, + {0.128906f, 0.066406f, 0.285156f, 0.910156f}, {0.800781f, 0.550781f, 0.714844f, 0.835938f}, + {0.699219f, 0.421875f, 0.855469f, 0.398438f}, {0.175781f, 0.304688f, 0.175781f, 0.664062f}, + {0.738281f, 0.039062f, 0.683594f, 0.074219f}, {0.832031f, 0.984375f, 0.898438f, 0.867188f}, + {0.574219f, 0.437500f, 0.363281f, 0.144531f}, {0.421875f, 0.640625f, 0.859375f, 0.597656f}, + {0.898438f, 0.937500f, 0.640625f, 0.906250f}, {0.125000f, 0.484375f, 0.214844f, 0.449219f}, + {0.472656f, 0.000000f, 0.808594f, 0.675781f}, {0.218750f, 0.960938f, 0.109375f, 0.847656f}, + {0.425781f, 0.167969f, 0.539062f, 0.585938f}, {0.800781f, 0.460938f, 0.257812f, 0.734375f}, + {0.289062f, 0.125000f, 0.402344f, 0.070312f}, {0.179688f, 0.777344f, 0.125000f, 0.648438f}, + {0.890625f, 0.011719f, 0.187500f, 0.480469f}, {0.628906f, 0.492188f, 0.558594f, 0.761719f}, + {0.144531f, 0.691406f, 0.769531f, 0.957031f}, {0.957031f, 0.765625f, 0.378906f, 0.351562f}, + {0.187500f, 0.292969f, 0.074219f, 0.222656f}, {0.496094f, 0.957031f, 0.589844f, 0.652344f}, + {0.378906f, 0.597656f, 0.128906f, 0.410156f}, {0.007812f, 0.316406f, 0.269531f, 0.273438f}, + {0.449219f, 0.644531f, 0.367188f, 0.777344f}, {0.542969f, 0.093750f, 0.648438f, 0.234375f}, + {0.660156f, 0.582031f, 0.503906f, 0.335938f}, {0.941406f, 0.382812f, 0.585938f, 0.421875f}, + {0.031250f, 0.042969f, 0.117188f, 0.285156f}, {0.414062f, 0.304688f, 0.679688f, 0.082031f}, + {0.781250f, 0.722656f, 0.484375f, 0.351562f}, {0.277344f, 0.800781f, 0.875000f, 0.496094f}, + {0.914062f, 0.265625f, 0.007812f, 0.816406f}, {0.406250f, 0.968750f, 0.445312f, 0.628906f}, + {0.066406f, 0.339844f, 0.710938f, 0.375000f}, {0.261719f, 0.746094f, 0.968750f, 0.878906f}, + {0.203125f, 0.800781f, 0.160156f, 0.511719f}, {0.812500f, 0.312500f, 0.613281f, 0.328125f}, + {0.414062f, 0.691406f, 0.359375f, 0.445312f}, {0.148438f, 0.007812f, 0.179688f, 0.625000f}, + {0.238281f, 0.226562f, 0.027344f, 0.785156f}, {0.476562f, 0.507812f, 0.664062f, 0.875000f}, + {0.648438f, 0.390625f, 0.945312f, 0.210938f}, {0.972656f, 0.710938f, 0.367188f, 0.269531f}, + {0.285156f, 0.558594f, 0.464844f, 0.128906f}, {0.082031f, 0.679688f, 0.816406f, 0.832031f}, + {0.457031f, 0.769531f, 0.078125f, 0.601562f}, {0.242188f, 0.867188f, 0.738281f, 0.898438f}, + {0.750000f, 0.394531f, 0.554688f, 0.019531f}, {0.101562f, 0.042969f, 0.968750f, 0.367188f}, + {0.621094f, 0.957031f, 0.769531f, 0.820312f}, {0.046875f, 0.449219f, 0.660156f, 0.492188f}, + {0.562500f, 0.613281f, 0.089844f, 0.234375f}, {0.480469f, 0.710938f, 0.335938f, 0.027344f}, + {0.851562f, 0.402344f, 0.156250f, 0.566406f}, {0.144531f, 0.554688f, 0.691406f, 0.507812f}, + {0.957031f, 0.023438f, 0.378906f, 0.355469f}, {0.750000f, 0.605469f, 0.640625f, 0.054688f}, + {0.207031f, 0.722656f, 0.941406f, 0.878906f}, {0.644531f, 0.429688f, 0.847656f, 0.660156f}, + {0.847656f, 0.558594f, 0.773438f, 0.328125f}, {0.089844f, 0.691406f, 0.425781f, 0.125000f}, + {0.480469f, 0.000000f, 0.195312f, 0.816406f}, {0.960938f, 0.332031f, 0.992188f, 0.226562f}, + {0.019531f, 0.750000f, 0.457031f, 0.304688f}, {0.546875f, 0.175781f, 0.503906f, 0.027344f}, + {0.253906f, 0.703125f, 0.046875f, 0.566406f}, {0.433594f, 0.898438f, 0.601562f, 0.199219f}, + {0.925781f, 0.582031f, 0.972656f, 0.359375f}, {0.136719f, 0.687500f, 0.250000f, 0.699219f}, + {0.269531f, 0.183594f, 0.468750f, 0.417969f}, {0.792969f, 0.066406f, 0.031250f, 0.003906f}, + {0.050781f, 0.566406f, 0.578125f, 0.718750f}, {0.710938f, 0.273438f, 0.414062f, 0.093750f}, + {0.769531f, 0.695312f, 0.500000f, 0.300781f}, {0.976562f, 0.792969f, 0.867188f, 0.152344f}, + {0.093750f, 0.613281f, 0.054688f, 0.410156f}, {0.652344f, 0.339844f, 0.722656f, 0.808594f}, + {0.570312f, 0.527344f, 0.804688f, 0.214844f}, {0.480469f, 0.398438f, 0.324219f, 0.312500f}, + {0.371094f, 0.996094f, 0.851562f, 0.867188f}, {0.531250f, 0.621094f, 0.429688f, 0.250000f}, + {0.441406f, 0.117188f, 0.039062f, 0.574219f}, {0.718750f, 0.355469f, 0.250000f, 0.703125f}, + {0.843750f, 0.867188f, 0.515625f, 0.050781f}, {0.078125f, 0.511719f, 0.816406f, 0.976562f}, + {0.621094f, 0.000000f, 0.667969f, 0.589844f}, {0.992188f, 0.800781f, 0.441406f, 0.882812f}, + {0.277344f, 0.988281f, 0.898438f, 0.093750f}, {0.058594f, 0.277344f, 0.070312f, 0.722656f}, + {0.351562f, 0.867188f, 0.746094f, 0.914062f}, {0.246094f, 0.507812f, 0.343750f, 0.601562f}, + {0.707031f, 0.433594f, 0.996094f, 0.875000f}, {0.972656f, 0.640625f, 0.394531f, 0.406250f}, + {0.664062f, 0.894531f, 0.253906f, 0.710938f}, {0.195312f, 0.406250f, 0.640625f, 0.906250f}, + {0.015625f, 0.480469f, 0.921875f, 0.035156f}, {0.800781f, 0.070312f, 0.582031f, 0.953125f}, + {0.679688f, 0.628906f, 0.062500f, 0.199219f}, {0.855469f, 0.218750f, 0.273438f, 0.265625f}, + {0.449219f, 0.492188f, 0.792969f, 0.664062f}, {0.714844f, 0.101562f, 0.906250f, 0.808594f}, + {0.578125f, 0.894531f, 0.714844f, 0.980469f}, {0.957031f, 0.421875f, 0.246094f, 0.058594f}, + {0.757812f, 0.851562f, 0.578125f, 0.304688f}, {0.886719f, 0.789062f, 0.839844f, 0.488281f}, + {0.000000f, 0.925781f, 0.140625f, 0.679688f}, {0.523438f, 0.121094f, 0.617188f, 0.355469f}, + {0.406250f, 0.886719f, 0.710938f, 0.984375f}, {0.769531f, 0.035156f, 0.285156f, 0.503906f}, + {0.890625f, 0.242188f, 0.906250f, 0.292969f}, {0.574219f, 0.531250f, 0.242188f, 0.703125f}, + {0.171875f, 0.179688f, 0.121094f, 0.769531f}, {0.527344f, 0.718750f, 0.308594f, 0.968750f}, + {0.433594f, 0.226562f, 0.171875f, 0.171875f}, {0.281250f, 0.105469f, 0.523438f, 0.125000f}, + {0.761719f, 0.285156f, 0.417969f, 0.402344f}, {0.328125f, 0.515625f, 0.574219f, 0.691406f}, + {0.406250f, 0.164062f, 0.910156f, 0.792969f}, {0.652344f, 0.996094f, 0.101562f, 0.109375f}, + {0.062500f, 0.121094f, 0.507812f, 0.832031f}, {0.320312f, 0.378906f, 0.742188f, 0.242188f}, + {0.390625f, 0.316406f, 0.175781f, 0.703125f}, {0.527344f, 0.156250f, 0.558594f, 0.417969f}, + {0.933594f, 0.972656f, 0.085938f, 0.000000f}, {0.160156f, 0.199219f, 0.722656f, 0.734375f}, + {0.242188f, 0.589844f, 0.898438f, 0.378906f}, {0.386719f, 0.941406f, 0.664062f, 0.503906f}, + {0.652344f, 0.851562f, 0.339844f, 0.695312f}, {0.910156f, 0.628906f, 0.765625f, 0.953125f}, + {0.343750f, 0.367188f, 0.218750f, 0.460938f}, {0.503906f, 0.136719f, 0.386719f, 0.769531f}, + {0.078125f, 0.816406f, 0.117188f, 0.976562f}, {0.632812f, 0.257812f, 0.523438f, 0.511719f}, + {0.378906f, 0.335938f, 0.722656f, 0.281250f}, {0.203125f, 0.769531f, 0.789062f, 0.558594f}, + {0.511719f, 0.882812f, 0.144531f, 0.953125f}, {0.347656f, 0.117188f, 0.695312f, 0.769531f}, + {0.253906f, 0.371094f, 0.964844f, 0.523438f}, {0.542969f, 0.425781f, 0.355469f, 0.878906f}, + {0.382812f, 0.082031f, 0.167969f, 0.109375f}, {0.910156f, 0.894531f, 0.582031f, 0.363281f}, + {0.132812f, 0.707031f, 0.472656f, 0.980469f}, {0.765625f, 0.210938f, 0.023438f, 0.445312f}, + {0.000000f, 0.304688f, 0.976562f, 0.148438f}, {0.820312f, 0.542969f, 0.695312f, 0.023438f}, + {0.230469f, 0.925781f, 0.625000f, 0.398438f}, {0.042969f, 0.429688f, 0.902344f, 0.792969f}, + {0.554688f, 0.152344f, 0.738281f, 0.117188f}, {0.339844f, 0.730469f, 0.320312f, 0.480469f}, + {0.804688f, 0.234375f, 0.960938f, 0.187500f}, {0.714844f, 0.375000f, 0.183594f, 0.347656f}, + {0.578125f, 0.492188f, 0.539062f, 0.457031f}, {0.859375f, 0.203125f, 0.230469f, 0.550781f}, + {0.769531f, 0.730469f, 0.832031f, 0.175781f}, {0.484375f, 0.789062f, 0.453125f, 0.031250f}, + {0.308594f, 0.953125f, 0.718750f, 0.746094f}, {0.066406f, 0.554688f, 0.890625f, 0.214844f}, + {0.378906f, 0.105469f, 0.085938f, 0.121094f}, {0.503906f, 0.195312f, 0.316406f, 0.605469f}, + {0.949219f, 0.867188f, 0.167969f, 0.429688f}, {0.546875f, 0.531250f, 0.824219f, 0.542969f}, + {0.316406f, 0.832031f, 0.207031f, 0.718750f}, {0.117188f, 0.390625f, 0.554688f, 0.460938f}, + {0.515625f, 0.152344f, 0.492188f, 0.011719f}, {0.906250f, 0.597656f, 0.117188f, 0.156250f}, + {0.046875f, 0.261719f, 0.417969f, 0.234375f}, {0.625000f, 0.542969f, 0.773438f, 0.707031f}, + {0.386719f, 0.667969f, 0.476562f, 0.121094f}, {0.308594f, 0.062500f, 0.320312f, 0.593750f}, + {0.167969f, 0.285156f, 0.886719f, 0.417969f}, {0.601562f, 0.199219f, 0.042969f, 0.777344f}, + {0.835938f, 0.425781f, 0.187500f, 0.082031f}, {0.214844f, 0.343750f, 0.539062f, 0.648438f}, + {0.023438f, 0.632812f, 0.398438f, 0.390625f}, {0.640625f, 0.093750f, 0.671875f, 0.195312f}, + {0.984375f, 0.820312f, 0.445312f, 0.074219f}, {0.382812f, 0.921875f, 0.617188f, 0.449219f}, + {0.910156f, 0.492188f, 0.828125f, 0.531250f}, {0.832031f, 0.683594f, 0.941406f, 0.859375f}, + {0.125000f, 0.859375f, 0.046875f, 0.941406f}, {0.929688f, 0.058594f, 0.750000f, 0.617188f}, + {0.218750f, 0.816406f, 0.835938f, 0.273438f}, {0.730469f, 0.222656f, 0.296875f, 0.441406f}, + {0.574219f, 0.652344f, 0.441406f, 0.921875f}, {0.832031f, 0.886719f, 0.878906f, 0.484375f}, + {0.117188f, 0.835938f, 0.226562f, 0.085938f}, {0.773438f, 0.050781f, 0.476562f, 0.781250f}, + {0.343750f, 0.789062f, 0.292969f, 0.929688f}, {0.695312f, 0.468750f, 0.382812f, 0.535156f}, + {0.882812f, 0.281250f, 0.019531f, 0.898438f}, {0.785156f, 0.125000f, 0.804688f, 0.160156f}, + {0.304688f, 0.507812f, 0.101562f, 0.640625f}, {0.093750f, 0.230469f, 0.546875f, 0.105469f}, + {0.839844f, 0.968750f, 0.929688f, 0.253906f}, {0.593750f, 0.476562f, 0.652344f, 0.605469f}, + {0.773438f, 0.011719f, 0.816406f, 0.046875f}, {0.976562f, 0.527344f, 0.304688f, 0.890625f}, + {0.464844f, 0.941406f, 0.187500f, 0.183594f}, {0.660156f, 0.460938f, 0.921875f, 0.804688f}, + {0.875000f, 0.718750f, 0.328125f, 0.335938f}, {0.933594f, 0.175781f, 0.246094f, 0.214844f}, + {0.011719f, 0.636719f, 0.000000f, 0.640625f}, {0.628906f, 0.980469f, 0.632812f, 0.925781f}, + {0.187500f, 0.246094f, 0.281250f, 0.261719f}, {0.835938f, 0.046875f, 0.921875f, 0.617188f}, + {0.273438f, 0.832031f, 0.660156f, 0.542969f}, {0.691406f, 0.648438f, 0.226562f, 0.726562f}, + {0.988281f, 0.882812f, 0.527344f, 0.675781f}, {0.597656f, 0.039062f, 0.351562f, 0.921875f}, + {0.304688f, 0.253906f, 0.152344f, 0.515625f}, {0.902344f, 0.804688f, 0.484375f, 0.277344f}, + {0.656250f, 0.632812f, 0.113281f, 0.898438f}, {0.257812f, 0.078125f, 0.410156f, 0.742188f}, + {0.132812f, 0.566406f, 0.000000f, 0.828125f}, {0.210938f, 0.914062f, 0.781250f, 0.042969f}, + {0.394531f, 0.675781f, 0.613281f, 0.949219f}, {0.171875f, 0.117188f, 0.929688f, 0.664062f}, + {0.910156f, 0.351562f, 0.300781f, 0.808594f}, {0.605469f, 0.160156f, 0.160156f, 0.503906f}, + {0.214844f, 0.695312f, 0.597656f, 0.980469f}, {0.550781f, 0.246094f, 0.207031f, 0.562500f}, + {0.847656f, 0.335938f, 0.789062f, 0.851562f}, {0.152344f, 0.601562f, 0.519531f, 0.277344f}, + {0.722656f, 0.738281f, 0.742188f, 0.171875f}, {0.226562f, 0.296875f, 0.375000f, 0.777344f}, + {0.625000f, 0.031250f, 0.683594f, 0.078125f}, {0.984375f, 0.917969f, 0.867188f, 0.851562f}, + {0.171875f, 0.710938f, 0.339844f, 0.585938f}, {0.351562f, 0.996094f, 0.011719f, 0.746094f}, + {0.277344f, 0.765625f, 0.636719f, 0.406250f}, {0.101562f, 0.183594f, 0.964844f, 0.890625f}, + {0.539062f, 0.332031f, 0.089844f, 0.542969f}, {0.847656f, 0.472656f, 0.218750f, 0.960938f}, + {0.722656f, 0.621094f, 0.515625f, 0.015625f}, {0.109375f, 0.750000f, 0.750000f, 0.859375f}, + {0.355469f, 0.835938f, 0.347656f, 0.167969f}, {0.679688f, 0.976562f, 0.949219f, 0.562500f}, + {0.496094f, 0.468750f, 0.148438f, 0.812500f}, {0.292969f, 0.281250f, 0.789062f, 0.945312f}, + {0.789062f, 0.585938f, 0.882812f, 0.335938f}, {0.062500f, 0.324219f, 0.007812f, 0.679688f}, + {0.695312f, 0.410156f, 0.214844f, 0.597656f}, {0.191406f, 0.140625f, 0.371094f, 0.292969f}, + {0.636719f, 0.933594f, 0.261719f, 0.054688f}, {0.078125f, 0.351562f, 0.675781f, 0.753906f}, + {0.515625f, 0.585938f, 0.191406f, 0.195312f}, {0.886719f, 0.742188f, 0.625000f, 0.332031f}, + {0.441406f, 0.457031f, 0.988281f, 0.726562f}, {0.253906f, 0.265625f, 0.015625f, 0.156250f}, + {0.980469f, 0.511719f, 0.355469f, 0.570312f}, {0.031250f, 0.628906f, 0.824219f, 0.296875f}, + {0.617188f, 0.347656f, 0.949219f, 0.203125f}, {0.566406f, 0.875000f, 0.636719f, 0.621094f}, + {0.058594f, 0.664062f, 0.246094f, 0.257812f}, {0.515625f, 0.734375f, 0.574219f, 0.437500f}, + {0.183594f, 0.406250f, 0.167969f, 0.796875f}, {0.414062f, 0.062500f, 0.273438f, 0.343750f}, + {0.703125f, 0.292969f, 0.843750f, 0.855469f}, {0.222656f, 0.781250f, 0.011719f, 0.152344f}, + {0.023438f, 0.648438f, 0.437500f, 0.312500f}, {0.292969f, 0.382812f, 0.582031f, 0.738281f}, + {0.726562f, 0.851562f, 0.074219f, 0.628906f}, {0.066406f, 0.050781f, 0.406250f, 0.121094f}, + {0.171875f, 0.300781f, 0.843750f, 0.464844f}, {0.585938f, 0.542969f, 0.539062f, 0.386719f}, + {0.804688f, 0.839844f, 0.750000f, 0.039062f}, {0.453125f, 0.500000f, 0.882812f, 0.707031f}, + {0.722656f, 0.757812f, 0.445312f, 0.484375f}, {0.066406f, 0.578125f, 0.382812f, 0.007812f}, + {0.429688f, 0.449219f, 0.835938f, 0.789062f}, {0.347656f, 0.109375f, 0.085938f, 0.089844f}, + {0.203125f, 0.378906f, 0.781250f, 0.343750f}, {0.085938f, 0.742188f, 0.269531f, 0.835938f}, + {0.742188f, 0.585938f, 0.929688f, 0.179688f}, {0.394531f, 0.191406f, 0.839844f, 0.632812f}, + {0.964844f, 0.960938f, 0.210938f, 0.328125f}, {0.515625f, 0.464844f, 0.570312f, 0.539062f}, + {0.460938f, 0.828125f, 0.710938f, 0.226562f}, {0.941406f, 0.042969f, 0.351562f, 0.613281f}, + {0.671875f, 0.425781f, 0.085938f, 0.386719f}, {0.085938f, 0.882812f, 0.484375f, 0.128906f}, + {0.437500f, 0.617188f, 0.660156f, 0.253906f}, {0.125000f, 0.058594f, 0.015625f, 0.324219f}, + {0.929688f, 0.468750f, 0.550781f, 0.632812f}, {0.792969f, 0.824219f, 0.425781f, 0.468750f}, + {0.636719f, 0.023438f, 0.949219f, 0.007812f}, {0.335938f, 0.937500f, 0.046875f, 0.667969f}, + {0.882812f, 0.437500f, 0.468750f, 0.339844f}, {0.437500f, 0.125000f, 0.976562f, 0.976562f}, + {0.085938f, 0.671875f, 0.082031f, 0.394531f}, {0.398438f, 0.562500f, 0.433594f, 0.308594f}, + {0.773438f, 0.351562f, 0.937500f, 0.925781f}, {0.664062f, 0.453125f, 0.742188f, 0.523438f}, + {0.871094f, 0.046875f, 0.289062f, 0.351562f}, {0.792969f, 0.871094f, 0.847656f, 0.832031f}, + {0.195312f, 0.132812f, 0.378906f, 0.261719f}, {0.425781f, 0.964844f, 0.687500f, 0.187500f}, + {0.996094f, 0.570312f, 0.933594f, 0.734375f}, {0.253906f, 0.011719f, 0.429688f, 0.316406f}, + {0.906250f, 0.519531f, 0.820312f, 0.457031f}, {0.140625f, 0.132812f, 0.644531f, 0.250000f}, + {0.820312f, 0.667969f, 0.074219f, 0.035156f}, {0.089844f, 0.902344f, 0.500000f, 0.488281f}, + {0.449219f, 0.781250f, 0.324219f, 0.871094f}, {0.339844f, 0.000000f, 0.562500f, 0.230469f}, + {0.246094f, 0.546875f, 0.695312f, 0.101562f}, {0.578125f, 0.644531f, 0.898438f, 0.804688f}, + {0.460938f, 0.757812f, 0.496094f, 0.367188f}, {0.796875f, 0.437500f, 0.117188f, 0.476562f}, + {0.359375f, 0.304688f, 0.347656f, 0.984375f}, {0.015625f, 0.906250f, 0.542969f, 0.015625f}, + {0.175781f, 0.007812f, 0.074219f, 0.605469f}, {0.660156f, 0.703125f, 0.718750f, 0.882812f}, + {0.496094f, 0.183594f, 0.582031f, 0.382812f}, {0.410156f, 0.761719f, 0.687500f, 0.968750f}, + {0.199219f, 0.093750f, 0.117188f, 0.460938f}, {0.285156f, 0.222656f, 0.519531f, 0.070312f}, + {0.445312f, 0.539062f, 0.855469f, 0.859375f}, {0.746094f, 0.023438f, 0.445312f, 0.039062f}, + {0.996094f, 0.828125f, 0.957031f, 0.558594f}, {0.625000f, 0.914062f, 0.714844f, 0.707031f}, + {0.890625f, 0.574219f, 0.484375f, 0.917969f}, {0.144531f, 0.089844f, 0.355469f, 0.527344f}, + {0.367188f, 0.710938f, 0.894531f, 0.390625f}, {0.906250f, 0.160156f, 0.746094f, 0.441406f}, + {0.531250f, 0.218750f, 0.671875f, 0.062500f}, {0.828125f, 0.605469f, 0.957031f, 0.851562f}, + {0.324219f, 0.414062f, 0.617188f, 0.992188f}, {0.406250f, 0.917969f, 0.113281f, 0.601562f}, + {0.125000f, 0.023438f, 0.480469f, 0.160156f}, {0.296875f, 0.328125f, 0.199219f, 0.828125f}, + {0.953125f, 0.191406f, 0.070312f, 0.429688f}, {0.527344f, 0.941406f, 0.730469f, 0.199219f}, + {0.609375f, 0.289062f, 0.140625f, 0.894531f}, {0.929688f, 0.160156f, 0.949219f, 0.285156f}, + {0.503906f, 0.812500f, 0.601562f, 0.582031f}, {0.863281f, 0.484375f, 0.421875f, 0.464844f}, + {0.457031f, 0.082031f, 0.058594f, 0.078125f}, {0.164062f, 0.398438f, 0.644531f, 0.968750f}, + {0.097656f, 0.281250f, 0.300781f, 0.425781f}, {0.781250f, 0.695312f, 0.945312f, 0.003906f}, + {0.015625f, 0.328125f, 0.871094f, 0.695312f}, {0.851562f, 0.179688f, 0.257812f, 0.292969f}, + {0.531250f, 0.777344f, 0.144531f, 0.765625f}, {0.328125f, 0.527344f, 0.859375f, 0.863281f}, + {0.824219f, 0.296875f, 0.375000f, 0.437500f}, {0.726562f, 0.917969f, 0.808594f, 0.062500f}, + {0.273438f, 0.394531f, 0.109375f, 0.164062f}, {0.417969f, 0.515625f, 0.332031f, 0.378906f}, + {0.097656f, 0.761719f, 0.695312f, 0.792969f}, {0.472656f, 0.652344f, 0.609375f, 0.898438f}, + {0.039062f, 0.171875f, 0.277344f, 0.511719f}, {0.261719f, 0.976562f, 0.136719f, 0.695312f}, + {0.828125f, 0.238281f, 0.648438f, 0.140625f}, {0.585938f, 0.792969f, 0.234375f, 0.632812f}, + {0.007812f, 0.082031f, 0.593750f, 0.218750f}, {0.492188f, 0.281250f, 0.152344f, 0.097656f}, + {0.234375f, 0.636719f, 0.199219f, 0.652344f}, {0.457031f, 0.402344f, 0.542969f, 0.035156f}, + {0.691406f, 0.714844f, 0.050781f, 0.476562f}, {0.054688f, 0.808594f, 0.625000f, 0.382812f}, + {0.628906f, 0.371094f, 0.125000f, 0.617188f}, {0.480469f, 0.253906f, 0.261719f, 0.933594f}, + {0.558594f, 0.699219f, 0.015625f, 0.667969f}, {0.414062f, 0.394531f, 0.585938f, 0.902344f}, + {0.964844f, 0.214844f, 0.230469f, 0.746094f}, {0.726562f, 0.070312f, 0.968750f, 0.136719f}, + {0.609375f, 0.714844f, 0.742188f, 0.628906f}, {0.871094f, 0.171875f, 0.109375f, 0.425781f}, + {0.035156f, 0.988281f, 0.421875f, 0.917969f}, {0.742188f, 0.253906f, 0.781250f, 0.710938f}, + {0.972656f, 0.039062f, 0.605469f, 0.554688f}, {0.285156f, 0.191406f, 0.968750f, 0.140625f}, + {0.554688f, 0.531250f, 0.851562f, 0.656250f}, {0.949219f, 0.101562f, 0.406250f, 0.828125f}, + {0.710938f, 0.394531f, 0.242188f, 0.507812f}, {0.312500f, 0.953125f, 0.796875f, 0.265625f}, + {0.816406f, 0.566406f, 0.156250f, 0.683594f}, {0.902344f, 0.433594f, 0.425781f, 0.121094f}, + {0.726562f, 0.921875f, 0.210938f, 0.820312f}, {0.953125f, 0.386719f, 0.054688f, 0.726562f}, + {0.132812f, 0.988281f, 0.761719f, 0.320312f}, {0.847656f, 0.167969f, 0.320312f, 0.996094f}, + {0.007812f, 0.445312f, 0.398438f, 0.406250f}, {0.261719f, 0.621094f, 0.632812f, 0.210938f}, + {0.472656f, 0.343750f, 0.082031f, 0.011719f}, {0.804688f, 0.882812f, 0.207031f, 0.656250f}, + {0.574219f, 0.429688f, 0.140625f, 0.816406f}, {0.429688f, 0.988281f, 0.265625f, 0.937500f}, + {0.246094f, 0.757812f, 0.488281f, 0.242188f}, {0.109375f, 0.109375f, 0.042969f, 0.675781f}, + {0.691406f, 0.675781f, 0.367188f, 0.507812f}, {0.992188f, 0.234375f, 0.292969f, 0.269531f}, + {0.500000f, 0.730469f, 0.808594f, 0.753906f}, {0.761719f, 0.128906f, 0.984375f, 0.312500f}, + {0.234375f, 0.667969f, 0.648438f, 0.964844f}, {0.851562f, 0.398438f, 0.550781f, 0.664062f}, + {0.039062f, 0.523438f, 0.312500f, 0.136719f}, {0.152344f, 0.699219f, 0.492188f, 0.406250f}, + {0.644531f, 0.976562f, 0.187500f, 0.945312f}, {0.253906f, 0.320312f, 0.710938f, 0.210938f}, + {0.687500f, 0.667969f, 0.546875f, 0.761719f}, {0.570312f, 0.898438f, 0.757812f, 0.667969f}, + {0.882812f, 0.769531f, 0.097656f, 0.144531f}, {0.359375f, 0.519531f, 0.460938f, 0.878906f}, + {0.597656f, 0.105469f, 0.675781f, 0.472656f}, {0.285156f, 0.976562f, 0.523438f, 0.996094f}, + {0.750000f, 0.250000f, 0.421875f, 0.082031f}, {0.050781f, 0.578125f, 0.980469f, 0.523438f}, + {0.625000f, 0.738281f, 0.742188f, 0.683594f}, {0.500000f, 0.214844f, 0.269531f, 0.937500f}, + {0.000000f, 0.992188f, 0.917969f, 0.296875f}, {0.187500f, 0.144531f, 0.832031f, 0.726562f}, + {0.988281f, 0.277344f, 0.156250f, 0.226562f}, {0.769531f, 0.363281f, 0.398438f, 0.097656f}, + {0.562500f, 0.570312f, 0.898438f, 0.437500f}, {0.687500f, 0.851562f, 0.531250f, 0.246094f}, + {0.941406f, 0.410156f, 0.839844f, 0.027344f}, {0.730469f, 0.511719f, 0.308594f, 0.867188f}, + {0.300781f, 0.199219f, 0.796875f, 0.492188f}, {0.914062f, 0.828125f, 0.496094f, 0.781250f}, + {0.132812f, 0.949219f, 0.703125f, 0.171875f}, {0.953125f, 0.527344f, 0.445312f, 0.941406f}, + {0.582031f, 0.230469f, 0.878906f, 0.691406f}, {0.339844f, 0.085938f, 0.781250f, 0.816406f}, + {0.804688f, 0.890625f, 0.570312f, 0.062500f}, {0.082031f, 0.164062f, 0.312500f, 0.523438f}, + {0.765625f, 0.785156f, 0.859375f, 0.101562f}, {0.312500f, 0.925781f, 0.453125f, 0.359375f}, + {0.230469f, 0.558594f, 0.691406f, 0.578125f}, {0.535156f, 0.335938f, 0.378906f, 0.277344f}, + {0.167969f, 0.441406f, 0.273438f, 0.777344f}, {0.941406f, 0.875000f, 0.855469f, 0.000000f}, + {0.507812f, 0.371094f, 0.160156f, 0.507812f}, {0.394531f, 0.800781f, 0.050781f, 0.191406f}, + {0.148438f, 0.597656f, 0.304688f, 0.261719f}, {0.679688f, 0.960938f, 0.457031f, 0.894531f}, + {0.226562f, 0.855469f, 0.027344f, 0.410156f}, {0.843750f, 0.675781f, 0.765625f, 0.093750f}, + {0.601562f, 0.796875f, 0.937500f, 0.222656f}, {0.097656f, 0.148438f, 0.488281f, 0.785156f}, + {0.148438f, 0.300781f, 0.320312f, 0.035156f}, {0.539062f, 0.039062f, 0.906250f, 0.632812f}, + {0.070312f, 0.609375f, 0.609375f, 0.363281f}, {0.671875f, 0.816406f, 0.972656f, 0.500000f}, + {0.371094f, 0.312500f, 0.699219f, 0.585938f}, {0.589844f, 0.699219f, 0.136719f, 0.148438f}, + {0.328125f, 0.261719f, 0.031250f, 0.773438f}, {0.546875f, 0.746094f, 0.910156f, 0.277344f}, + {0.105469f, 0.195312f, 0.589844f, 0.472656f}, {0.679688f, 0.519531f, 0.773438f, 0.109375f}, + {0.937500f, 0.246094f, 0.996094f, 0.722656f}, {0.179688f, 0.324219f, 0.558594f, 0.195312f}, + {0.753906f, 0.562500f, 0.878906f, 0.562500f}, {0.601562f, 0.488281f, 0.222656f, 0.355469f}, + {0.867188f, 0.949219f, 0.773438f, 0.105469f}, {0.210938f, 0.808594f, 0.167969f, 0.867188f}, + {0.648438f, 0.363281f, 0.574219f, 0.058594f}, {0.078125f, 0.468750f, 0.410156f, 0.574219f}, + {0.375000f, 0.878906f, 0.035156f, 0.515625f}, {0.679688f, 0.796875f, 0.234375f, 0.351562f}, + {0.316406f, 0.007812f, 0.765625f, 0.742188f}, {0.792969f, 0.609375f, 0.375000f, 0.625000f}, + {0.402344f, 0.234375f, 0.890625f, 0.808594f}, {0.019531f, 0.871094f, 0.007812f, 0.054688f}, + {0.824219f, 0.546875f, 0.332031f, 0.546875f}, {0.320312f, 0.015625f, 0.812500f, 0.363281f}, + {0.222656f, 0.144531f, 0.390625f, 0.246094f}, {0.722656f, 0.363281f, 0.167969f, 0.597656f}, + {0.417969f, 0.859375f, 0.031250f, 0.792969f}, {0.179688f, 0.648438f, 0.800781f, 0.167969f}, + {0.917969f, 0.402344f, 0.632812f, 0.351562f}, {0.246094f, 0.007812f, 0.058594f, 0.207031f}, + {0.964844f, 0.839844f, 0.191406f, 0.585938f}, {0.367188f, 0.097656f, 0.503906f, 0.820312f}, + {0.878906f, 0.609375f, 0.039062f, 0.117188f}, {0.589844f, 0.871094f, 0.640625f, 0.914062f}, + {0.675781f, 0.058594f, 0.230469f, 0.542969f}, {0.296875f, 0.796875f, 0.773438f, 0.613281f}, + {0.898438f, 0.484375f, 0.019531f, 0.828125f}, {0.140625f, 0.007812f, 0.730469f, 0.937500f}, + {0.355469f, 0.304688f, 0.363281f, 0.578125f}, {0.191406f, 0.753906f, 0.070312f, 0.722656f}, + {0.535156f, 0.906250f, 0.902344f, 0.433594f}, {0.636719f, 0.578125f, 0.031250f, 0.992188f}, + {0.367188f, 0.019531f, 0.992188f, 0.332031f}, {0.738281f, 0.683594f, 0.343750f, 0.554688f}, + {0.027344f, 0.320312f, 0.250000f, 0.128906f}, {0.285156f, 0.441406f, 0.167969f, 0.296875f}, + {0.933594f, 0.605469f, 0.488281f, 0.234375f}, {0.179688f, 0.500000f, 0.980469f, 0.785156f}, + {0.660156f, 0.304688f, 0.734375f, 0.433594f}, {0.011719f, 0.035156f, 0.183594f, 0.207031f}, + {0.855469f, 0.843750f, 0.906250f, 0.703125f}, {0.371094f, 0.617188f, 0.042969f, 0.988281f}, + {0.105469f, 0.269531f, 0.480469f, 0.398438f}, {0.656250f, 0.519531f, 0.640625f, 0.328125f}, + {0.773438f, 0.097656f, 0.941406f, 0.843750f}, {0.312500f, 0.472656f, 0.539062f, 0.964844f}, + {0.894531f, 0.703125f, 0.238281f, 0.046875f}, {0.109375f, 0.132812f, 0.703125f, 0.769531f}, + {0.429688f, 0.273438f, 0.175781f, 0.585938f}, {0.046875f, 0.492188f, 0.574219f, 0.347656f}, + {0.382812f, 0.355469f, 0.285156f, 0.953125f}, {0.472656f, 0.636719f, 0.660156f, 0.437500f}, + {0.769531f, 0.847656f, 0.093750f, 0.542969f}, {0.347656f, 0.246094f, 0.832031f, 0.910156f}, + {0.250000f, 0.726562f, 0.371094f, 0.175781f}, {0.875000f, 0.136719f, 0.273438f, 0.238281f}, + {0.492188f, 0.484375f, 0.500000f, 0.671875f}, {0.210938f, 0.562500f, 0.871094f, 0.089844f}, + {0.820312f, 0.078125f, 0.234375f, 0.890625f}, {0.718750f, 0.957031f, 0.812500f, 0.621094f}, + {0.398438f, 0.121094f, 0.515625f, 0.949219f}, {0.035156f, 0.804688f, 0.300781f, 0.367188f}, + {0.308594f, 0.015625f, 0.386719f, 0.589844f}, {0.640625f, 0.636719f, 0.707031f, 0.296875f}, + {0.054688f, 0.898438f, 0.101562f, 0.023438f}, {0.468750f, 0.042969f, 0.445312f, 0.789062f}, + {0.359375f, 0.285156f, 0.652344f, 0.714844f}, {0.027344f, 0.167969f, 0.925781f, 0.421875f}, + {0.554688f, 0.539062f, 0.710938f, 0.929688f}, {0.890625f, 0.621094f, 0.332031f, 0.226562f}, + {0.164062f, 0.093750f, 0.906250f, 0.109375f}, {0.578125f, 0.265625f, 0.855469f, 0.882812f}, + {0.460938f, 0.910156f, 0.671875f, 0.042969f}, {0.914062f, 0.367188f, 0.105469f, 0.250000f}, + {0.734375f, 0.070312f, 0.621094f, 0.492188f}, {0.542969f, 0.183594f, 0.996094f, 0.308594f}, + {0.980469f, 0.421875f, 0.238281f, 0.703125f}, {0.128906f, 0.621094f, 0.503906f, 0.933594f}, + {0.632812f, 0.925781f, 0.906250f, 0.839844f}, {0.953125f, 0.218750f, 0.597656f, 0.109375f}, + {0.039062f, 0.589844f, 0.960938f, 0.402344f}, {0.667969f, 0.714844f, 0.218750f, 0.550781f}, + {0.472656f, 0.484375f, 0.312500f, 0.718750f}, {0.558594f, 0.152344f, 0.582031f, 0.894531f}, + {0.152344f, 0.355469f, 0.691406f, 0.023438f}, {0.691406f, 0.671875f, 0.445312f, 0.410156f}, + {0.753906f, 0.316406f, 0.867188f, 0.496094f}, {0.527344f, 0.546875f, 0.562500f, 0.656250f}, + {0.125000f, 0.714844f, 0.304688f, 0.042969f}, {0.390625f, 0.218750f, 0.988281f, 0.320312f}, + {0.218750f, 0.894531f, 0.585938f, 0.183594f}, {0.511719f, 0.691406f, 0.187500f, 0.761719f}, + {0.457031f, 0.101562f, 0.457031f, 0.296875f}, {0.050781f, 0.628906f, 0.671875f, 0.371094f}, + {0.816406f, 0.148438f, 0.554688f, 0.054688f}, {0.082031f, 0.371094f, 0.386719f, 0.269531f}, + {0.417969f, 0.472656f, 0.753906f, 0.617188f}, {0.839844f, 0.175781f, 0.109375f, 0.750000f}, + {0.218750f, 0.933594f, 0.656250f, 0.421875f}, {0.527344f, 0.742188f, 0.910156f, 0.910156f}, + {0.875000f, 0.050781f, 0.402344f, 0.589844f}, {0.390625f, 0.988281f, 0.082031f, 0.972656f}, + {0.460938f, 0.652344f, 0.355469f, 0.148438f}, {0.921875f, 0.464844f, 0.546875f, 0.847656f}, + {0.601562f, 0.113281f, 0.132812f, 0.484375f}, {0.710938f, 0.964844f, 0.773438f, 0.089844f}, + {0.273438f, 0.761719f, 0.593750f, 0.550781f}, {0.433594f, 0.664062f, 0.199219f, 0.156250f}, + {0.203125f, 0.222656f, 0.355469f, 0.664062f}, {0.000000f, 0.835938f, 0.812500f, 0.609375f}, + {0.625000f, 0.320312f, 0.738281f, 0.445312f}, {0.804688f, 0.410156f, 0.914062f, 0.304688f}, + {0.523438f, 0.617188f, 0.644531f, 0.695312f}, {0.738281f, 0.070312f, 0.121094f, 0.179688f}, + {0.886719f, 0.210938f, 0.890625f, 0.859375f}, {0.210938f, 0.984375f, 0.531250f, 0.730469f}, + {0.988281f, 0.464844f, 0.000000f, 0.312500f}, {0.628906f, 0.527344f, 0.726562f, 0.078125f}, + {0.433594f, 0.902344f, 0.472656f, 0.765625f}, {0.789062f, 0.058594f, 0.171875f, 0.957031f}, + {0.042969f, 0.656250f, 0.570312f, 0.441406f}, {0.652344f, 0.796875f, 0.656250f, 0.832031f}, + {0.914062f, 0.371094f, 0.339844f, 0.332031f}, {0.164062f, 0.875000f, 0.453125f, 0.515625f}, + {0.968750f, 0.476562f, 0.167969f, 0.750000f}, {0.777344f, 0.683594f, 0.683594f, 0.160156f}, + {0.492188f, 0.851562f, 0.019531f, 0.843750f}, {0.855469f, 0.144531f, 0.808594f, 0.972656f}, + {0.960938f, 0.449219f, 0.332031f, 0.453125f}, {0.265625f, 0.781250f, 0.531250f, 0.898438f}, + {0.781250f, 0.394531f, 0.851562f, 0.183594f}, {0.921875f, 0.855469f, 0.015625f, 0.628906f}, + {0.285156f, 0.066406f, 0.132812f, 0.378906f}, {0.421875f, 0.992188f, 0.507812f, 0.796875f}, + {0.816406f, 0.753906f, 0.269531f, 0.695312f}, {0.972656f, 0.570312f, 0.468750f, 0.449219f}, + {0.113281f, 0.148438f, 0.160156f, 0.554688f}, {0.199219f, 0.726562f, 0.796875f, 0.992188f}, + {0.285156f, 0.464844f, 0.289062f, 0.164062f}, {0.070312f, 0.785156f, 0.453125f, 0.875000f}, + {0.375000f, 0.832031f, 0.843750f, 0.437500f}, {0.500000f, 0.269531f, 0.125000f, 0.023438f}, + {0.445312f, 0.726562f, 0.687500f, 0.507812f}, {0.089844f, 0.457031f, 0.277344f, 0.289062f}, + {0.839844f, 0.046875f, 0.359375f, 0.917969f}, {0.773438f, 0.300781f, 0.761719f, 0.050781f}, + {0.347656f, 0.945312f, 0.882812f, 0.640625f}, {0.101562f, 0.902344f, 0.117188f, 0.460938f}, + {0.816406f, 0.785156f, 0.937500f, 0.265625f}, {0.445312f, 0.453125f, 0.351562f, 0.765625f}, + {0.226562f, 0.171875f, 0.726562f, 0.351562f}, {0.324219f, 0.921875f, 0.082031f, 0.839844f}, + {0.808594f, 0.402344f, 0.421875f, 0.988281f}, {0.027344f, 0.113281f, 0.492188f, 0.398438f}, + {0.855469f, 0.589844f, 0.109375f, 0.480469f}, {0.648438f, 0.339844f, 0.878906f, 0.066406f}, + {0.976562f, 0.945312f, 0.257812f, 0.539062f}, {0.765625f, 0.433594f, 0.953125f, 0.160156f}, + {0.250000f, 0.726562f, 0.140625f, 0.820312f}, {0.570312f, 0.261719f, 0.210938f, 0.894531f}, + {0.964844f, 0.789062f, 0.613281f, 0.097656f}, {0.160156f, 0.117188f, 0.300781f, 0.210938f}, + {0.488281f, 0.839844f, 0.820312f, 0.859375f}, {0.707031f, 0.542969f, 0.019531f, 0.496094f}, + {0.605469f, 0.273438f, 0.714844f, 0.007812f}, {0.125000f, 0.820312f, 0.222656f, 0.718750f}, + {0.750000f, 0.363281f, 0.652344f, 0.339844f}, {0.207031f, 0.195312f, 0.804688f, 0.636719f}, + {0.050781f, 0.718750f, 0.300781f, 0.039062f}, {0.492188f, 0.406250f, 0.406250f, 0.906250f}, + {0.910156f, 0.152344f, 0.992188f, 0.796875f}, {0.832031f, 0.015625f, 0.683594f, 0.214844f}, + {0.570312f, 0.937500f, 0.085938f, 0.738281f}, {0.984375f, 0.570312f, 0.472656f, 0.371094f}, + {0.468750f, 0.050781f, 0.394531f, 0.121094f}, {0.253906f, 0.886719f, 0.066406f, 0.820312f}, + {0.328125f, 0.769531f, 0.332031f, 0.535156f}, {0.937500f, 0.921875f, 0.441406f, 0.011719f}, + {0.640625f, 0.718750f, 0.199219f, 0.488281f}, {0.289062f, 0.031250f, 0.390625f, 0.136719f}, + {0.007812f, 0.773438f, 0.992188f, 0.601562f}, {0.566406f, 0.398438f, 0.230469f, 0.406250f}, + {0.171875f, 0.191406f, 0.785156f, 0.855469f}, {0.933594f, 0.343750f, 0.046875f, 0.285156f}, + {0.121094f, 0.949219f, 0.921875f, 0.003906f}, {0.292969f, 0.218750f, 0.097656f, 0.558594f}, + {0.441406f, 0.027344f, 0.734375f, 0.199219f}, {0.515625f, 0.597656f, 0.976562f, 0.050781f}, + {0.250000f, 0.402344f, 0.066406f, 0.425781f}, {0.363281f, 0.300781f, 0.859375f, 0.250000f}, + {0.203125f, 0.546875f, 0.433594f, 0.066406f}, {0.117188f, 0.363281f, 0.613281f, 0.644531f}, + {0.542969f, 0.726562f, 0.191406f, 0.535156f}, {0.410156f, 0.199219f, 0.964844f, 0.125000f}, + {0.140625f, 0.578125f, 0.261719f, 0.316406f}, {0.667969f, 0.660156f, 0.394531f, 0.496094f}, + {0.488281f, 0.441406f, 0.625000f, 0.003906f}, {0.734375f, 0.304688f, 0.820312f, 0.601562f}, + {0.007812f, 0.203125f, 0.082031f, 0.292969f}, {0.250000f, 0.417969f, 0.593750f, 0.191406f}, + {0.511719f, 0.503906f, 0.953125f, 0.832031f}, {0.703125f, 0.960938f, 0.417969f, 0.656250f}, + {0.605469f, 0.656250f, 0.566406f, 0.386719f}, {0.886719f, 0.312500f, 0.070312f, 0.097656f}, + {0.753906f, 0.511719f, 0.640625f, 0.777344f}, {0.191406f, 0.109375f, 0.203125f, 0.621094f}, + {0.917969f, 0.992188f, 0.738281f, 0.175781f}, {0.300781f, 0.390625f, 0.437500f, 0.664062f}, + {0.515625f, 0.816406f, 0.078125f, 0.742188f}, {0.230469f, 0.085938f, 0.488281f, 0.226562f}, + {0.589844f, 0.203125f, 0.546875f, 0.324219f}, {0.894531f, 0.558594f, 0.406250f, 0.832031f}, + {0.292969f, 0.261719f, 0.250000f, 0.964844f}, {0.058594f, 0.027344f, 0.789062f, 0.179688f}, + {0.968750f, 0.812500f, 0.515625f, 0.554688f}, {0.484375f, 0.496094f, 0.207031f, 0.242188f}, + {0.914062f, 0.253906f, 0.921875f, 0.144531f}, {0.605469f, 0.968750f, 0.816406f, 0.714844f}, + {0.734375f, 0.457031f, 0.699219f, 0.648438f}, {0.097656f, 0.183594f, 0.332031f, 0.882812f}, + {0.410156f, 0.832031f, 0.605469f, 0.957031f}, {0.292969f, 0.542969f, 0.761719f, 0.679688f}, + {0.691406f, 0.039062f, 0.421875f, 0.597656f}, {0.878906f, 0.984375f, 0.859375f, 0.468750f}, + {0.324219f, 0.601562f, 0.507812f, 0.710938f}, {0.664062f, 0.343750f, 0.925781f, 0.363281f}, + {0.785156f, 0.640625f, 0.453125f, 0.070312f}, {0.093750f, 0.214844f, 0.582031f, 0.652344f}, + {0.347656f, 0.417969f, 0.519531f, 0.390625f}, {0.949219f, 0.140625f, 0.843750f, 0.277344f}, + {0.261719f, 0.769531f, 0.937500f, 0.546875f}, {0.566406f, 0.535156f, 0.066406f, 0.757812f}, + {0.328125f, 0.250000f, 0.503906f, 0.253906f}, {0.796875f, 0.589844f, 0.871094f, 0.445312f}, + {0.144531f, 0.898438f, 0.003906f, 0.304688f}, {0.074219f, 0.308594f, 0.261719f, 0.953125f}, + {0.355469f, 0.390625f, 0.839844f, 0.492188f}, {0.691406f, 0.742188f, 0.144531f, 0.062500f}, + {0.863281f, 0.183594f, 0.589844f, 0.917969f}, {0.175781f, 0.527344f, 0.976562f, 0.230469f}, + {0.582031f, 0.238281f, 0.511719f, 0.992188f}, {0.074219f, 0.441406f, 0.855469f, 0.644531f}, + {0.140625f, 0.554688f, 0.750000f, 0.277344f}, {0.488281f, 0.328125f, 0.687500f, 0.941406f}, + {0.824219f, 0.121094f, 0.582031f, 0.210938f}, {0.703125f, 0.687500f, 0.332031f, 0.699219f}, + {0.324219f, 0.593750f, 0.625000f, 0.519531f}, {0.734375f, 0.859375f, 0.429688f, 0.644531f}, + {0.390625f, 0.433594f, 0.839844f, 0.378906f}, {0.609375f, 0.515625f, 0.390625f, 0.738281f}, + {0.761719f, 0.714844f, 0.539062f, 0.976562f}, {0.074219f, 0.269531f, 0.277344f, 0.679688f}, + {0.882812f, 0.167969f, 0.636719f, 0.796875f}, {0.667969f, 0.769531f, 0.226562f, 0.886719f}, + {0.593750f, 0.925781f, 0.941406f, 0.492188f}, {0.734375f, 0.078125f, 0.128906f, 0.386719f}, + {0.332031f, 0.980469f, 0.722656f, 0.765625f}, {0.699219f, 0.269531f, 0.058594f, 0.265625f}, + {0.835938f, 0.105469f, 0.476562f, 0.699219f}, {0.058594f, 0.917969f, 0.753906f, 0.984375f}, + {0.191406f, 0.710938f, 0.214844f, 0.847656f}, {0.609375f, 0.023438f, 0.976562f, 0.144531f}, + {0.332031f, 0.894531f, 0.683594f, 0.953125f}, {0.640625f, 0.339844f, 0.355469f, 0.761719f}, + {0.867188f, 0.839844f, 0.023438f, 0.027344f}, {0.359375f, 0.117188f, 0.222656f, 0.328125f}, + {0.441406f, 0.242188f, 0.718750f, 0.726562f}, {0.136719f, 0.933594f, 0.878906f, 0.585938f}, + {0.656250f, 0.027344f, 0.382812f, 0.218750f}, {0.796875f, 0.566406f, 0.531250f, 0.976562f}, + {0.582031f, 0.160156f, 0.023438f, 0.339844f}, {0.703125f, 0.664062f, 0.921875f, 0.425781f}, + {0.390625f, 0.765625f, 0.851562f, 0.812500f}, {0.132812f, 0.515625f, 0.156250f, 0.945312f}, + {0.996094f, 0.871094f, 0.718750f, 0.140625f}, {0.718750f, 0.417969f, 0.003906f, 0.593750f}, + {0.406250f, 0.632812f, 0.621094f, 0.066406f}, {0.652344f, 0.738281f, 0.148438f, 0.679688f}, + {0.167969f, 0.363281f, 0.285156f, 0.929688f}, {0.082031f, 0.078125f, 0.667969f, 0.000000f}, + {0.429688f, 0.675781f, 0.027344f, 0.453125f}, {0.261719f, 0.617188f, 0.382812f, 0.796875f}, + {0.339844f, 0.785156f, 0.234375f, 0.265625f}, {0.546875f, 0.050781f, 0.523438f, 0.105469f}, + {0.164062f, 0.273438f, 0.007812f, 0.222656f}, {0.910156f, 0.667969f, 0.804688f, 0.390625f}, + {0.492188f, 0.203125f, 0.082031f, 0.011719f}, {0.121094f, 0.863281f, 0.269531f, 0.242188f}, + {0.011719f, 0.414062f, 0.695312f, 0.519531f}, {0.449219f, 0.496094f, 0.058594f, 0.972656f}, + {0.238281f, 0.914062f, 0.191406f, 0.765625f}, {0.855469f, 0.078125f, 0.367188f, 0.179688f}, + {0.046875f, 0.882812f, 0.281250f, 0.828125f}, {0.437500f, 0.687500f, 0.148438f, 0.113281f}, + {0.816406f, 0.015625f, 0.613281f, 0.949219f}, {0.683594f, 0.937500f, 0.437500f, 0.187500f}, + {0.988281f, 0.859375f, 0.238281f, 0.867188f}, {0.398438f, 0.085938f, 0.574219f, 0.597656f}, + {0.636719f, 0.496094f, 0.722656f, 0.683594f}, {0.742188f, 0.808594f, 0.339844f, 0.019531f}, + {0.234375f, 0.625000f, 0.531250f, 0.574219f}, {0.535156f, 0.460938f, 0.890625f, 0.269531f}, + {0.050781f, 0.976562f, 0.289062f, 0.781250f}, {0.730469f, 0.109375f, 0.214844f, 0.460938f}, + {0.371094f, 0.363281f, 0.789062f, 0.390625f}, {0.789062f, 0.656250f, 0.042969f, 0.074219f}, + {0.679688f, 0.164062f, 0.269531f, 0.757812f}, {0.402344f, 0.839844f, 0.105469f, 0.359375f}, + {0.875000f, 0.261719f, 0.875000f, 0.808594f}, {0.234375f, 0.933594f, 0.144531f, 0.046875f}, + {0.062500f, 0.082031f, 0.945312f, 0.125000f}, {0.523438f, 0.285156f, 0.289062f, 0.937500f}, + {0.855469f, 0.753906f, 0.691406f, 0.164062f}, {0.984375f, 0.148438f, 0.207031f, 0.464844f}, + {0.027344f, 0.894531f, 0.132812f, 0.265625f}, {0.562500f, 0.976562f, 0.785156f, 0.593750f}, + {0.144531f, 0.625000f, 0.476562f, 0.136719f}, {0.824219f, 0.046875f, 0.355469f, 0.320312f}, + {0.445312f, 0.226562f, 0.558594f, 0.710938f}, {0.000000f, 0.664062f, 0.289062f, 0.207031f}, + {0.910156f, 0.468750f, 0.835938f, 0.921875f}, {0.222656f, 0.609375f, 0.589844f, 0.039062f}, + {0.582031f, 0.820312f, 0.898438f, 0.812500f}, {0.984375f, 0.347656f, 0.308594f, 0.445312f}, + {0.378906f, 0.238281f, 0.550781f, 0.238281f}, {0.796875f, 0.523438f, 0.437500f, 0.542969f}, + {0.937500f, 0.792969f, 0.179688f, 0.355469f}, {0.097656f, 0.687500f, 0.742188f, 0.429688f}, + {0.761719f, 0.597656f, 0.523438f, 0.511719f}, {0.035156f, 0.050781f, 0.929688f, 0.132812f}, + {0.957031f, 0.406250f, 0.328125f, 0.921875f}, {0.230469f, 0.609375f, 0.148438f, 0.472656f}, + {0.335938f, 0.707031f, 0.777344f, 0.285156f}, {0.019531f, 0.351562f, 0.976562f, 0.824219f}, + {0.261719f, 0.859375f, 0.316406f, 0.058594f}, {0.058594f, 0.230469f, 0.570312f, 0.570312f}, + {0.882812f, 0.324219f, 0.652344f, 0.484375f}, {0.628906f, 0.601562f, 0.210938f, 0.015625f}, + {0.195312f, 0.132812f, 0.988281f, 0.371094f}, {0.015625f, 0.699219f, 0.832031f, 0.527344f}, + {0.535156f, 0.066406f, 0.335938f, 0.433594f}, {0.851562f, 0.976562f, 0.953125f, 0.742188f}, + {0.574219f, 0.578125f, 0.468750f, 0.621094f}, {0.773438f, 0.855469f, 0.843750f, 0.316406f}, + {0.703125f, 0.148438f, 0.750000f, 0.898438f}, {0.187500f, 0.300781f, 0.136719f, 0.582031f}, + {0.960938f, 0.742188f, 0.644531f, 0.359375f}, {0.796875f, 0.378906f, 0.972656f, 0.523438f}, + {0.031250f, 0.917969f, 0.171875f, 0.847656f}, {0.593750f, 0.507812f, 0.468750f, 0.445312f}, + {0.207031f, 0.332031f, 0.359375f, 0.785156f}, {0.753906f, 0.105469f, 0.566406f, 0.914062f}, + {0.386719f, 0.695312f, 0.960938f, 0.128906f}, {0.613281f, 0.000000f, 0.128906f, 0.308594f}, + {0.914062f, 0.296875f, 0.792969f, 0.570312f}, {0.300781f, 0.730469f, 0.734375f, 0.457031f}, + {0.550781f, 0.574219f, 0.972656f, 0.890625f}, {0.644531f, 0.480469f, 0.046875f, 0.687500f}, + {0.160156f, 0.312500f, 0.335938f, 0.500000f}, {0.507812f, 0.625000f, 0.765625f, 0.417969f}, + {0.093750f, 0.433594f, 0.164062f, 0.082031f}, {0.195312f, 0.347656f, 0.953125f, 0.355469f}, + {0.468750f, 0.699219f, 0.109375f, 0.140625f}, {0.941406f, 0.210938f, 0.449219f, 0.832031f}, + {0.296875f, 0.039062f, 0.656250f, 0.410156f}, {0.417969f, 0.277344f, 0.761719f, 0.878906f}, + {0.121094f, 0.679688f, 0.027344f, 0.625000f}, {0.910156f, 0.792969f, 0.699219f, 0.156250f}, + {0.449219f, 0.863281f, 0.625000f, 0.710938f}, {0.968750f, 0.011719f, 0.367188f, 0.871094f}, + {0.199219f, 0.964844f, 0.554688f, 0.546875f}, {0.531250f, 0.605469f, 0.816406f, 0.441406f}, + {0.105469f, 0.496094f, 0.460938f, 0.906250f}, {0.960938f, 0.804688f, 0.062500f, 0.484375f}, + {0.457031f, 0.546875f, 0.515625f, 0.324219f}, {0.660156f, 0.003906f, 0.753906f, 0.578125f}, + {0.199219f, 0.636719f, 0.035156f, 0.804688f}, {0.265625f, 0.320312f, 0.593750f, 0.093750f}, + {0.347656f, 0.101562f, 0.957031f, 0.906250f}, {0.710938f, 0.453125f, 0.875000f, 0.363281f}, + {0.402344f, 0.824219f, 0.027344f, 0.019531f}, {0.292969f, 0.531250f, 0.750000f, 0.554688f}, + {0.976562f, 0.414062f, 0.910156f, 0.949219f}, {0.078125f, 0.863281f, 0.507812f, 0.089844f}, + {0.792969f, 0.312500f, 0.390625f, 0.609375f}, {0.500000f, 0.000000f, 0.664062f, 0.347656f}, + {0.304688f, 0.507812f, 0.160156f, 0.570312f}, {0.089844f, 0.152344f, 0.109375f, 0.097656f}, + {0.457031f, 0.957031f, 0.800781f, 0.664062f}, {0.539062f, 0.636719f, 0.066406f, 0.738281f}, + {0.144531f, 0.085938f, 0.878906f, 0.082031f}, {0.414062f, 0.175781f, 0.277344f, 0.886719f}, + {0.292969f, 0.285156f, 0.835938f, 0.636719f}, {0.570312f, 0.750000f, 0.617188f, 0.257812f}, + {0.812500f, 0.886719f, 0.058594f, 0.851562f}, {0.527344f, 0.199219f, 0.464844f, 0.082031f}, + {0.851562f, 0.773438f, 0.664062f, 0.535156f}, {0.414062f, 0.441406f, 0.257812f, 0.679688f}, + {0.976562f, 0.914062f, 0.109375f, 0.148438f}, {0.539062f, 0.488281f, 0.812500f, 0.886719f}, + {0.816406f, 0.000000f, 0.371094f, 0.257812f}, {0.316406f, 0.960938f, 0.285156f, 0.703125f}, + {0.484375f, 0.382812f, 0.457031f, 0.785156f}, {0.785156f, 0.277344f, 0.675781f, 0.875000f}, + {0.265625f, 0.476562f, 0.070312f, 0.289062f}, {0.355469f, 0.207031f, 0.585938f, 0.109375f}, + {0.636719f, 0.917969f, 0.179688f, 0.851562f}, {0.929688f, 0.519531f, 0.347656f, 0.515625f}, + {0.007812f, 0.425781f, 0.554688f, 0.199219f}, {0.507812f, 0.011719f, 0.445312f, 0.085938f}, + {0.667969f, 0.886719f, 0.859375f, 0.976562f}, {0.382812f, 0.476562f, 0.300781f, 0.738281f}, + {0.843750f, 0.128906f, 0.726562f, 0.613281f}, {0.437500f, 0.808594f, 0.898438f, 0.183594f}, + {0.652344f, 0.582031f, 0.667969f, 0.332031f}, {0.984375f, 0.753906f, 0.835938f, 0.699219f}, + {0.812500f, 0.242188f, 0.320312f, 0.636719f}, {0.511719f, 0.945312f, 0.625000f, 0.816406f}, + {0.183594f, 0.796875f, 0.421875f, 0.027344f}, {0.742188f, 0.179688f, 0.882812f, 0.253906f}, + {0.972656f, 0.375000f, 0.660156f, 0.613281f}, {0.378906f, 0.964844f, 0.480469f, 0.324219f}, + {0.015625f, 0.222656f, 0.863281f, 0.046875f}, {0.871094f, 0.058594f, 0.695312f, 0.800781f}, + {0.289062f, 0.792969f, 0.382812f, 0.644531f}, {0.765625f, 0.171875f, 0.636719f, 0.929688f}, + {0.554688f, 0.988281f, 0.808594f, 0.531250f}, {0.023438f, 0.546875f, 0.218750f, 0.730469f}, + {0.882812f, 0.886719f, 0.929688f, 0.191406f}, {0.605469f, 0.136719f, 0.167969f, 0.332031f}, + {0.812500f, 0.335938f, 0.414062f, 0.519531f}, {0.652344f, 0.585938f, 0.953125f, 0.093750f}, + {0.269531f, 0.488281f, 0.132812f, 0.312500f}, {0.019531f, 0.292969f, 0.472656f, 0.589844f}, + {0.316406f, 0.410156f, 0.914062f, 0.195312f}, {0.613281f, 0.742188f, 0.175781f, 0.023438f}, + {0.761719f, 0.207031f, 0.398438f, 0.660156f}, {0.363281f, 0.363281f, 0.664062f, 0.253906f}, + {0.585938f, 0.449219f, 0.246094f, 0.746094f}, {0.796875f, 0.996094f, 0.902344f, 0.882812f}, + {0.136719f, 0.835938f, 0.367188f, 0.230469f}, {0.492188f, 0.390625f, 0.492188f, 0.707031f}, + {0.812500f, 0.562500f, 0.316406f, 0.515625f}, {0.636719f, 0.687500f, 0.421875f, 0.839844f}, + {0.898438f, 0.343750f, 0.164062f, 0.664062f}, {0.179688f, 0.125000f, 0.695312f, 0.453125f}, + {0.527344f, 0.746094f, 0.097656f, 0.816406f}, {0.625000f, 0.183594f, 0.207031f, 0.156250f}, + {0.371094f, 0.906250f, 0.003906f, 0.421875f}, {0.160156f, 0.707031f, 0.781250f, 0.683594f}, + {0.656250f, 0.773438f, 0.343750f, 0.894531f}, {0.875000f, 0.406250f, 0.945312f, 0.171875f}, + {0.242188f, 0.859375f, 0.699219f, 0.394531f}, {0.703125f, 0.460938f, 0.375000f, 0.281250f}, + {0.902344f, 0.371094f, 0.636719f, 0.937500f}, {0.207031f, 0.558594f, 0.476562f, 0.574219f}, + {0.679688f, 0.980469f, 0.121094f, 0.203125f}, {0.476562f, 0.484375f, 0.402344f, 0.773438f}, + {0.171875f, 0.332031f, 0.808594f, 0.699219f}, {0.718750f, 0.144531f, 0.906250f, 0.417969f}, + {0.113281f, 0.527344f, 0.195312f, 0.351562f}, {0.617188f, 0.066406f, 0.507812f, 0.933594f}, + {0.460938f, 0.277344f, 0.417969f, 0.734375f}, {0.160156f, 0.640625f, 0.613281f, 0.394531f}, + {0.730469f, 0.738281f, 0.039062f, 0.105469f}, {0.078125f, 0.187500f, 0.777344f, 0.617188f}, + {0.425781f, 0.824219f, 0.527344f, 0.171875f}, {0.679688f, 0.898438f, 0.128906f, 0.984375f}, + {0.949219f, 0.769531f, 0.414062f, 0.230469f}, {0.128906f, 0.320312f, 0.886719f, 0.402344f}, + {0.234375f, 0.648438f, 0.046875f, 0.160156f}, {0.394531f, 0.242188f, 0.964844f, 0.691406f}, + {0.312500f, 0.800781f, 0.265625f, 0.769531f}, {0.875000f, 0.695312f, 0.785156f, 0.414062f}, + {0.132812f, 0.562500f, 0.085938f, 0.046875f}, {0.238281f, 0.218750f, 0.574219f, 0.292969f}, + {0.722656f, 0.640625f, 0.394531f, 0.136719f}, {0.304688f, 0.062500f, 0.222656f, 0.941406f}, + {0.074219f, 0.972656f, 0.039062f, 0.078125f}, {0.351562f, 0.445312f, 0.152344f, 0.542969f}, + {0.265625f, 0.148438f, 0.500000f, 0.417969f}, {0.054688f, 0.531250f, 0.246094f, 0.203125f}, + {0.687500f, 0.621094f, 0.007812f, 0.937500f}, {0.113281f, 0.457031f, 0.535156f, 0.378906f}, + {0.472656f, 0.105469f, 0.210938f, 0.144531f}, {0.218750f, 0.664062f, 0.113281f, 0.996094f}, + {0.703125f, 0.843750f, 0.261719f, 0.218750f}, {0.925781f, 0.523438f, 0.550781f, 0.722656f}, + {0.613281f, 0.730469f, 0.019531f, 0.289062f}, {0.367188f, 0.269531f, 0.886719f, 0.472656f}, + {0.843750f, 0.074219f, 0.304688f, 0.238281f}, {0.703125f, 0.648438f, 0.054688f, 0.984375f}, + {0.171875f, 0.425781f, 0.371094f, 0.078125f}, {0.335938f, 0.734375f, 0.566406f, 0.660156f}, + {0.496094f, 0.949219f, 0.500000f, 0.906250f}, {0.214844f, 0.058594f, 0.312500f, 0.750000f}, + {0.554688f, 0.203125f, 0.867188f, 0.964844f}, {0.839844f, 0.707031f, 0.238281f, 0.257812f}, + {0.707031f, 0.113281f, 0.679688f, 0.828125f}, {0.890625f, 0.890625f, 0.296875f, 0.144531f}, + {0.164062f, 0.042969f, 0.968750f, 0.972656f}, {0.273438f, 0.671875f, 0.796875f, 0.609375f}, + {0.019531f, 0.156250f, 0.562500f, 0.078125f}, {0.910156f, 0.246094f, 0.183594f, 0.371094f}, + {0.414062f, 0.707031f, 0.824219f, 0.437500f}, {0.085938f, 0.195312f, 0.082031f, 0.046875f}, + {0.945312f, 0.781250f, 0.683594f, 0.308594f}, {0.218750f, 0.023438f, 0.621094f, 0.175781f}, + {0.464844f, 0.234375f, 0.261719f, 0.964844f}, {0.105469f, 0.957031f, 0.582031f, 0.234375f}, + {0.750000f, 0.488281f, 0.808594f, 0.738281f}, {0.253906f, 0.582031f, 0.457031f, 0.285156f}, + {0.855469f, 0.367188f, 0.984375f, 0.859375f}, {0.425781f, 0.121094f, 0.250000f, 0.492188f}, + {0.945312f, 0.550781f, 0.433594f, 0.222656f}, {0.738281f, 0.214844f, 0.503906f, 0.953125f}, + {0.019531f, 0.046875f, 0.226562f, 0.515625f}, {0.324219f, 0.734375f, 0.574219f, 0.785156f}, + {0.589844f, 0.257812f, 0.011719f, 0.015625f}, {0.843750f, 0.812500f, 0.988281f, 0.468750f}, + {0.992188f, 0.007812f, 0.238281f, 0.312500f}, {0.082031f, 0.425781f, 0.699219f, 0.054688f}, + {0.382812f, 0.843750f, 0.304688f, 0.972656f}, {0.890625f, 0.667969f, 0.558594f, 0.183594f}, + {0.281250f, 0.968750f, 0.000000f, 0.003906f}, {0.687500f, 0.812500f, 0.742188f, 0.632812f}, + {0.910156f, 0.121094f, 0.867188f, 0.207031f}, {0.347656f, 0.574219f, 0.957031f, 0.511719f}, + {0.238281f, 0.421875f, 0.183594f, 0.957031f}, {0.960938f, 0.097656f, 0.707031f, 0.316406f}, + {0.585938f, 0.667969f, 0.921875f, 0.445312f}, {0.835938f, 0.535156f, 0.238281f, 0.660156f}, + {0.039062f, 0.031250f, 0.800781f, 0.074219f}, {0.464844f, 0.125000f, 0.734375f, 0.808594f}, + {0.742188f, 0.390625f, 0.503906f, 0.367188f}, {0.828125f, 0.054688f, 0.113281f, 0.953125f}, + {0.550781f, 0.996094f, 0.621094f, 0.472656f}, {0.625000f, 0.175781f, 0.203125f, 0.636719f}, + {0.472656f, 0.347656f, 0.941406f, 0.871094f}, {0.046875f, 0.945312f, 0.050781f, 0.675781f}, + {0.937500f, 0.414062f, 0.503906f, 0.492188f}, {0.500000f, 0.265625f, 0.632812f, 0.832031f}, + {0.894531f, 0.683594f, 0.992188f, 0.753906f}, {0.148438f, 0.367188f, 0.437500f, 0.277344f}, + {0.550781f, 0.890625f, 0.777344f, 0.050781f}, {0.945312f, 0.316406f, 0.710938f, 0.871094f}, + {0.410156f, 0.046875f, 0.343750f, 0.484375f}, {0.597656f, 0.855469f, 0.949219f, 0.671875f}, + {0.843750f, 0.261719f, 0.398438f, 0.781250f}, {0.781250f, 0.769531f, 0.597656f, 0.515625f}, + {0.320312f, 0.140625f, 0.796875f, 0.578125f}, {0.425781f, 0.406250f, 0.988281f, 0.894531f}, + {0.062500f, 0.593750f, 0.191406f, 0.160156f}, {0.246094f, 0.875000f, 0.515625f, 0.824219f}, + {0.132812f, 0.484375f, 0.468750f, 0.031250f}, {0.437500f, 0.367188f, 0.605469f, 0.375000f}, + {0.976562f, 0.835938f, 0.859375f, 0.785156f}, {0.046875f, 0.242188f, 0.726562f, 0.433594f}, + {0.765625f, 0.519531f, 0.089844f, 0.226562f}, {0.921875f, 0.394531f, 0.824219f, 0.003906f}, + {0.105469f, 0.921875f, 0.585938f, 0.382812f}, {0.390625f, 0.824219f, 0.007812f, 0.476562f}, + {0.484375f, 0.558594f, 0.738281f, 0.683594f}, {0.070312f, 0.441406f, 0.082031f, 0.347656f}, + {0.433594f, 0.332031f, 0.605469f, 0.417969f}, {0.949219f, 0.765625f, 0.339844f, 0.789062f}, + {0.738281f, 0.906250f, 0.015625f, 0.183594f}, {0.312500f, 0.601562f, 0.441406f, 0.527344f}, + {0.695312f, 0.089844f, 0.722656f, 0.992188f}, {0.605469f, 0.867188f, 0.925781f, 0.644531f}, + {0.539062f, 0.500000f, 0.218750f, 0.769531f}, {0.011719f, 0.929688f, 0.847656f, 0.414062f}, + {0.777344f, 0.296875f, 0.972656f, 0.613281f}, {0.332031f, 0.644531f, 0.398438f, 0.058594f}, + {0.937500f, 0.835938f, 0.328125f, 0.378906f}, {0.691406f, 0.042969f, 0.867188f, 0.542969f}, + {0.039062f, 0.257812f, 0.625000f, 0.011719f}, {0.546875f, 0.964844f, 0.562500f, 0.753906f}, + {0.117188f, 0.632812f, 0.738281f, 0.320312f}, {0.605469f, 0.296875f, 0.054688f, 0.050781f}, + {0.824219f, 0.902344f, 0.820312f, 0.621094f}, {0.507812f, 0.589844f, 0.906250f, 0.863281f}, + {0.058594f, 0.136719f, 0.324219f, 0.152344f}, {0.445312f, 0.929688f, 0.753906f, 0.671875f}, + {0.253906f, 0.703125f, 0.167969f, 0.828125f}, {0.644531f, 0.218750f, 0.593750f, 0.375000f}, + {0.781250f, 0.574219f, 0.085938f, 0.609375f}, {0.000000f, 0.042969f, 0.964844f, 0.550781f}, + {0.500000f, 0.296875f, 0.359375f, 0.871094f}, {0.207031f, 0.394531f, 0.683594f, 0.457031f}, + {0.062500f, 0.214844f, 0.136719f, 0.277344f}, {0.777344f, 0.933594f, 0.480469f, 0.847656f}, + {0.648438f, 0.863281f, 0.332031f, 0.765625f}, {0.121094f, 0.351562f, 0.089844f, 0.042969f}, + {0.367188f, 0.250000f, 0.390625f, 0.554688f}, {0.183594f, 0.433594f, 0.566406f, 0.730469f}, + {0.300781f, 0.593750f, 0.300781f, 0.500000f}, {0.894531f, 0.726562f, 0.636719f, 0.589844f}, + {0.105469f, 0.839844f, 0.375000f, 0.296875f}, {0.199219f, 0.468750f, 0.710938f, 0.125000f}, + {0.062500f, 0.289062f, 0.902344f, 0.027344f}, {0.992188f, 0.609375f, 0.410156f, 0.250000f}, + {0.281250f, 0.101562f, 0.687500f, 0.343750f}, {0.789062f, 0.718750f, 0.343750f, 0.558594f}, + {0.578125f, 0.832031f, 0.878906f, 0.214844f}, {0.187500f, 0.539062f, 0.746094f, 0.378906f}, + {0.691406f, 0.187500f, 0.277344f, 0.457031f}, {0.621094f, 0.031250f, 0.105469f, 0.984375f}, + {0.859375f, 0.812500f, 0.917969f, 0.597656f}, {0.757812f, 0.656250f, 0.558594f, 0.343750f}, + {0.332031f, 0.402344f, 0.179688f, 0.726562f}, {0.027344f, 0.996094f, 0.812500f, 0.085938f}, + {0.261719f, 0.554688f, 0.074219f, 0.851562f}, {0.144531f, 0.351562f, 0.742188f, 0.003906f}, + {0.519531f, 0.925781f, 0.449219f, 0.406250f}, {0.585938f, 0.027344f, 0.324219f, 0.347656f}, + {0.824219f, 0.320312f, 0.097656f, 0.109375f}, {0.953125f, 0.953125f, 0.707031f, 0.558594f}, + {0.671875f, 0.121094f, 0.773438f, 0.695312f}, {0.523438f, 0.773438f, 0.128906f, 0.609375f}, + {0.273438f, 0.003906f, 0.964844f, 0.496094f}, {0.621094f, 0.617188f, 0.265625f, 0.132812f}, + {0.367188f, 0.167969f, 0.199219f, 0.847656f}, {0.722656f, 0.761719f, 0.652344f, 0.539062f}, + {0.156250f, 0.652344f, 0.437500f, 0.621094f}, {0.996094f, 0.253906f, 0.359375f, 0.777344f}, + {0.648438f, 0.148438f, 0.937500f, 0.109375f}, {0.242188f, 0.632812f, 0.496094f, 0.902344f}, + {0.828125f, 0.957031f, 0.769531f, 0.562500f}, {0.558594f, 0.074219f, 0.136719f, 0.289062f}, + {0.503906f, 0.531250f, 0.878906f, 0.703125f}, {0.175781f, 0.476562f, 0.636719f, 0.843750f}, + {0.878906f, 0.277344f, 0.292969f, 0.132812f}, {0.367188f, 0.417969f, 0.125000f, 0.574219f}, + {0.281250f, 0.062500f, 0.550781f, 0.910156f}, {0.847656f, 0.589844f, 0.054688f, 0.273438f}, + {0.664062f, 0.730469f, 0.511719f, 0.121094f}, {0.394531f, 0.402344f, 0.140625f, 0.503906f}, + {0.578125f, 0.089844f, 0.039062f, 0.914062f}, {0.480469f, 0.777344f, 0.714844f, 0.652344f}, + {0.195312f, 0.445312f, 0.179688f, 0.976562f}, {0.785156f, 0.675781f, 0.113281f, 0.132812f}, + {0.351562f, 0.816406f, 0.886719f, 0.835938f}, {0.265625f, 0.488281f, 0.296875f, 0.453125f}, + {0.175781f, 0.093750f, 0.144531f, 0.722656f}, {0.386719f, 0.335938f, 0.656250f, 0.339844f}, + {0.753906f, 0.656250f, 0.531250f, 0.234375f}, {0.132812f, 0.398438f, 0.421875f, 0.421875f}, + {0.351562f, 0.515625f, 0.929688f, 0.925781f}, {0.917969f, 0.105469f, 0.500000f, 0.492188f}, + {0.601562f, 0.914062f, 0.773438f, 0.136719f}, {0.324219f, 0.613281f, 0.441406f, 0.750000f}, + {0.949219f, 0.730469f, 0.222656f, 0.324219f}, {0.578125f, 0.480469f, 0.824219f, 0.808594f}, + {0.402344f, 0.660156f, 0.289062f, 0.062500f}, {0.863281f, 0.761719f, 0.585938f, 0.578125f}, + {0.488281f, 0.515625f, 0.898438f, 0.132812f}, {0.550781f, 0.050781f, 0.644531f, 0.355469f}, + {0.921875f, 0.968750f, 0.832031f, 0.882812f}, {0.710938f, 0.796875f, 0.011719f, 0.261719f}, + {0.511719f, 0.160156f, 0.980469f, 0.019531f}, {0.605469f, 0.945312f, 0.199219f, 0.921875f}, + {0.343750f, 0.214844f, 0.789062f, 0.218750f}, {0.675781f, 0.550781f, 0.019531f, 0.570312f}, + {0.437500f, 0.746094f, 0.468750f, 0.734375f}, {0.707031f, 0.875000f, 0.542969f, 0.804688f}, + {0.144531f, 0.503906f, 0.285156f, 0.910156f}, {0.406250f, 0.019531f, 0.121094f, 0.101562f}, + {0.742188f, 0.312500f, 0.816406f, 0.714844f}, {0.097656f, 0.933594f, 0.183594f, 0.007812f}, + {0.371094f, 0.761719f, 0.589844f, 0.648438f}, {0.453125f, 0.492188f, 0.378906f, 0.167969f}, + {0.222656f, 0.585938f, 0.847656f, 0.796875f}, {0.121094f, 0.214844f, 0.058594f, 0.128906f}, + {0.484375f, 0.730469f, 0.632812f, 0.546875f}, {0.914062f, 0.078125f, 0.871094f, 0.296875f}, + {0.640625f, 0.191406f, 0.304688f, 0.441406f}, {0.886719f, 0.714844f, 0.148438f, 0.242188f}, + {0.082031f, 0.464844f, 0.933594f, 0.750000f}, {0.742188f, 0.632812f, 0.640625f, 0.667969f}, + {0.183594f, 0.230469f, 0.386719f, 0.953125f}, {0.484375f, 0.687500f, 0.917969f, 0.445312f}, + {0.007812f, 0.187500f, 0.226562f, 0.308594f}, {0.804688f, 0.570312f, 0.417969f, 0.914062f}, + {0.195312f, 0.304688f, 0.671875f, 0.253906f}, {0.878906f, 0.902344f, 0.351562f, 0.960938f}, + {0.078125f, 0.082031f, 0.042969f, 0.710938f}, {0.460938f, 0.449219f, 0.988281f, 0.292969f}, + {0.300781f, 0.320312f, 0.781250f, 0.058594f}, {0.593750f, 0.023438f, 0.171875f, 0.949219f}, + {0.796875f, 0.500000f, 0.539062f, 0.207031f}, {0.339844f, 0.839844f, 0.218750f, 0.503906f}, + {0.132812f, 0.289062f, 0.417969f, 0.070312f}, {0.675781f, 0.218750f, 0.269531f, 0.871094f}, + {0.042969f, 0.378906f, 0.996094f, 0.035156f}, {0.230469f, 0.816406f, 0.515625f, 0.472656f}, + {0.453125f, 0.964844f, 0.375000f, 0.332031f}, {0.746094f, 0.664062f, 0.792969f, 0.214844f}, + {0.058594f, 0.351562f, 0.457031f, 0.000000f}, {0.968750f, 0.882812f, 0.343750f, 0.718750f}, + {0.160156f, 0.140625f, 0.765625f, 0.878906f}, {0.238281f, 0.207031f, 0.675781f, 0.789062f}, + {0.070312f, 0.535156f, 0.945312f, 0.335938f}, {0.894531f, 0.917969f, 0.277344f, 0.179688f}, + {0.296875f, 0.332031f, 0.535156f, 0.597656f}, {0.988281f, 0.167969f, 0.359375f, 0.398438f}, + {0.718750f, 0.015625f, 0.671875f, 0.257812f}, {0.472656f, 0.414062f, 0.960938f, 0.554688f}, + {0.890625f, 0.996094f, 0.460938f, 0.109375f}, {0.964844f, 0.789062f, 0.199219f, 0.996094f}, + {0.667969f, 0.875000f, 0.089844f, 0.585938f}, {0.804688f, 0.183594f, 0.859375f, 0.703125f}, + {0.546875f, 0.312500f, 0.261719f, 0.089844f}, {0.050781f, 0.769531f, 0.046875f, 0.273438f}, + {0.187500f, 0.253906f, 0.843750f, 0.894531f}, {0.441406f, 0.367188f, 0.644531f, 0.230469f}, + {0.742188f, 0.171875f, 0.105469f, 0.097656f}, {0.824219f, 0.890625f, 0.535156f, 0.984375f}, + {0.144531f, 0.015625f, 0.394531f, 0.656250f}, {0.296875f, 0.316406f, 0.058594f, 0.402344f}, + {0.019531f, 0.144531f, 0.210938f, 0.691406f}, {0.753906f, 0.621094f, 0.730469f, 0.929688f}, + {0.250000f, 0.703125f, 0.492188f, 0.191406f}, {0.054688f, 0.292969f, 0.152344f, 0.414062f}, + {0.410156f, 0.492188f, 0.445312f, 0.777344f}, {0.796875f, 0.339844f, 0.871094f, 0.855469f}, + {0.902344f, 0.085938f, 0.250000f, 0.632812f}, {0.531250f, 0.906250f, 0.324219f, 0.394531f}, + {0.250000f, 0.132812f, 0.839844f, 0.976562f}, {0.917969f, 0.375000f, 0.160156f, 0.523438f}, + {0.859375f, 0.792969f, 0.601562f, 0.160156f}, {0.335938f, 0.453125f, 0.714844f, 0.425781f}, + {0.523438f, 0.152344f, 0.464844f, 0.949219f}, {0.957031f, 0.625000f, 0.000000f, 0.863281f}, + {0.800781f, 0.089844f, 0.531250f, 0.257812f}, {0.000000f, 0.863281f, 0.316406f, 0.511719f}, + {0.308594f, 0.285156f, 0.679688f, 0.906250f}, {0.824219f, 0.132812f, 0.472656f, 0.230469f}, + {0.535156f, 0.917969f, 0.265625f, 0.656250f}, {0.683594f, 0.503906f, 0.429688f, 0.960938f}, + {0.363281f, 0.609375f, 0.515625f, 0.171875f}, {0.445312f, 0.289062f, 0.683594f, 0.917969f}, + {0.964844f, 0.808594f, 0.238281f, 0.617188f}, {0.277344f, 0.085938f, 0.042969f, 0.062500f}, + {0.394531f, 0.511719f, 0.839844f, 0.203125f}, {0.636719f, 0.753906f, 0.585938f, 0.843750f}, + {0.343750f, 0.417969f, 0.289062f, 0.761719f}, {0.746094f, 0.933594f, 0.011719f, 0.171875f}, + {0.566406f, 0.472656f, 0.816406f, 0.066406f}, {0.398438f, 0.671875f, 0.550781f, 0.566406f}, + {0.675781f, 0.855469f, 0.750000f, 0.351562f}, {0.832031f, 0.546875f, 0.488281f, 0.179688f}, + {0.222656f, 0.992188f, 0.285156f, 0.449219f}, {0.531250f, 0.792969f, 0.117188f, 0.839844f}, + {0.003906f, 0.382812f, 0.875000f, 0.320312f}, {0.718750f, 0.722656f, 0.625000f, 0.718750f}, + {0.925781f, 0.574219f, 0.843750f, 0.636719f}, {0.382812f, 0.878906f, 0.070312f, 0.238281f}, + {0.621094f, 0.015625f, 0.707031f, 0.398438f}, {0.988281f, 0.738281f, 0.195312f, 0.925781f}, + {0.796875f, 0.125000f, 0.039062f, 0.667969f}, {0.136719f, 0.179688f, 0.953125f, 0.796875f}, + {0.632812f, 0.542969f, 0.648438f, 0.382812f}, {0.496094f, 0.804688f, 0.253906f, 0.550781f}, + {0.433594f, 0.449219f, 0.894531f, 0.457031f}, {0.730469f, 0.988281f, 0.203125f, 0.675781f}, + {0.800781f, 0.273438f, 0.484375f, 0.222656f}, {0.136719f, 0.710938f, 0.414062f, 0.074219f}, + {0.617188f, 0.597656f, 0.789062f, 0.472656f}, {0.417969f, 0.851562f, 0.843750f, 0.800781f}, + {0.027344f, 0.242188f, 0.031250f, 0.695312f}, {0.566406f, 0.699219f, 0.398438f, 0.898438f}, + {0.089844f, 0.195312f, 0.593750f, 0.187500f}, {0.617188f, 0.531250f, 0.792969f, 0.382812f}, + {0.199219f, 0.445312f, 0.351562f, 0.769531f}, {0.289062f, 0.074219f, 0.675781f, 0.035156f}, + {0.492188f, 0.632812f, 0.730469f, 0.535156f}, {0.699219f, 0.976562f, 0.382812f, 0.800781f}, + {0.875000f, 0.464844f, 0.308594f, 0.640625f}, {0.121094f, 0.800781f, 0.171875f, 0.437500f}, + {0.257812f, 0.078125f, 0.925781f, 0.714844f}, {0.523438f, 0.550781f, 0.718750f, 0.507812f}, + {0.625000f, 0.992188f, 0.996094f, 0.171875f}, {0.968750f, 0.238281f, 0.781250f, 0.246094f}, + {0.191406f, 0.453125f, 0.433594f, 0.468750f}, {0.441406f, 0.839844f, 0.269531f, 0.812500f}, + {0.855469f, 0.203125f, 0.941406f, 0.621094f}, {0.652344f, 0.890625f, 0.347656f, 0.113281f}, + {0.972656f, 0.007812f, 0.687500f, 0.480469f}, {0.156250f, 0.679688f, 0.585938f, 0.683594f}, + {0.015625f, 0.617188f, 0.519531f, 0.078125f}, {0.761719f, 0.437500f, 0.945312f, 0.453125f}, + {0.371094f, 0.261719f, 0.078125f, 0.320312f}, {0.585938f, 0.652344f, 0.757812f, 0.054688f}, + {0.031250f, 0.207031f, 0.972656f, 0.609375f}, {0.644531f, 0.585938f, 0.375000f, 0.292969f}, + {0.210938f, 0.894531f, 0.242188f, 0.769531f}, {0.269531f, 0.246094f, 0.902344f, 0.574219f}, + {0.882812f, 0.390625f, 0.957031f, 0.355469f}, {0.570312f, 0.457031f, 0.769531f, 0.062500f}, + {0.726562f, 0.953125f, 0.214844f, 0.406250f}, {0.988281f, 0.347656f, 0.136719f, 0.742188f}, + {0.066406f, 0.785156f, 0.972656f, 0.035156f}, {0.156250f, 0.425781f, 0.726562f, 0.375000f}, + {0.207031f, 0.015625f, 0.015625f, 0.589844f}, {0.710938f, 0.898438f, 0.894531f, 0.480469f}, + {0.031250f, 0.160156f, 0.562500f, 0.792969f}, {0.546875f, 0.980469f, 0.480469f, 0.273438f}, + {0.863281f, 0.859375f, 0.738281f, 0.535156f}, {0.101562f, 0.355469f, 0.171875f, 0.371094f}, + {0.910156f, 0.054688f, 0.523438f, 0.011719f}, {0.296875f, 0.808594f, 0.894531f, 0.640625f}, + {0.937500f, 0.257812f, 0.457031f, 0.414062f}, {0.125000f, 0.113281f, 0.152344f, 0.804688f}, + {0.507812f, 0.363281f, 0.617188f, 0.882812f}, {0.957031f, 0.195312f, 0.394531f, 0.656250f}, + {0.054688f, 0.695312f, 0.906250f, 0.750000f}, {0.902344f, 0.070312f, 0.703125f, 0.582031f}, + {0.421875f, 0.929688f, 0.031250f, 0.140625f}, {0.187500f, 0.167969f, 0.671875f, 0.433594f}, + {0.476562f, 0.101562f, 0.363281f, 0.980469f}, {0.281250f, 0.683594f, 0.570312f, 0.765625f}, + {0.847656f, 0.437500f, 0.472656f, 0.167969f}, {0.078125f, 0.628906f, 0.832031f, 0.605469f}, + {0.570312f, 0.328125f, 0.593750f, 0.101562f}, {0.261719f, 0.765625f, 0.738281f, 0.503906f}, + {0.906250f, 0.242188f, 0.164062f, 0.960938f}, {0.324219f, 0.007812f, 0.824219f, 0.164062f}, + {0.593750f, 0.683594f, 0.570312f, 0.089844f}, {0.921875f, 0.617188f, 0.105469f, 0.296875f}, + {0.527344f, 0.050781f, 0.632812f, 0.851562f}, {0.359375f, 0.375000f, 0.910156f, 0.726562f}, + {0.835938f, 0.128906f, 0.070312f, 0.937500f}, {0.664062f, 0.515625f, 0.226562f, 0.027344f}, + {0.226562f, 0.890625f, 0.500000f, 0.300781f}, {0.851562f, 0.574219f, 0.757812f, 0.648438f}, + {0.316406f, 0.753906f, 0.257812f, 0.058594f}, {0.429688f, 0.277344f, 0.937500f, 0.507812f}, + {0.007812f, 0.031250f, 0.019531f, 0.878906f}, {0.933594f, 0.714844f, 0.550781f, 0.308594f}, + {0.835938f, 0.847656f, 0.136719f, 0.164062f}, {0.234375f, 0.546875f, 0.617188f, 0.968750f}, + {0.394531f, 0.132812f, 0.902344f, 0.355469f}, {0.980469f, 0.679688f, 0.566406f, 0.019531f}, + {0.671875f, 0.839844f, 0.468750f, 0.585938f}, {0.046875f, 0.417969f, 0.250000f, 0.378906f}, + {0.375000f, 0.597656f, 0.023438f, 0.898438f}, {0.695312f, 0.789062f, 0.625000f, 0.753906f}, + {0.898438f, 0.375000f, 0.875000f, 0.007812f}, {0.328125f, 0.542969f, 0.113281f, 0.531250f}, + {0.578125f, 0.109375f, 0.542969f, 0.300781f}, {0.085938f, 0.406250f, 0.765625f, 0.988281f}, + {0.285156f, 0.566406f, 0.062500f, 0.339844f}, {0.472656f, 0.777344f, 0.128906f, 0.164062f}, + {0.636719f, 0.363281f, 0.628906f, 0.750000f}, {0.832031f, 0.035156f, 0.394531f, 0.835938f}, + {0.109375f, 0.972656f, 0.667969f, 0.195312f}, {0.183594f, 0.710938f, 0.222656f, 0.890625f}, + {0.808594f, 0.066406f, 0.046875f, 0.707031f}, {0.460938f, 0.953125f, 0.855469f, 0.476562f}, + {0.082031f, 0.335938f, 0.652344f, 0.203125f}, {0.667969f, 0.738281f, 0.093750f, 0.121094f}, + {0.425781f, 0.664062f, 0.417969f, 0.683594f}, {0.164062f, 0.007812f, 0.613281f, 0.964844f}, + {0.632812f, 0.703125f, 0.042969f, 0.617188f}, {0.250000f, 0.554688f, 0.804688f, 0.464844f}, + {0.394531f, 0.242188f, 0.371094f, 0.878906f}, {0.937500f, 0.847656f, 0.601562f, 0.816406f}, + {0.804688f, 0.679688f, 0.195312f, 0.113281f}, {0.601562f, 0.378906f, 0.335938f, 0.320312f}, + {0.339844f, 0.562500f, 0.812500f, 0.867188f}, {0.785156f, 0.437500f, 0.125000f, 0.140625f}, + {0.230469f, 0.273438f, 0.355469f, 0.980469f}, {0.687500f, 0.656250f, 0.957031f, 0.468750f}, + {0.156250f, 0.148438f, 0.082031f, 0.726562f}, {0.464844f, 0.535156f, 0.703125f, 0.898438f}, + {0.039062f, 0.722656f, 0.324219f, 0.285156f}, {0.250000f, 0.945312f, 0.945312f, 0.117188f}, + {0.777344f, 0.589844f, 0.093750f, 0.484375f}, {0.328125f, 0.285156f, 0.222656f, 0.023438f}, + {0.609375f, 0.421875f, 0.828125f, 0.390625f}, {0.746094f, 0.617188f, 0.335938f, 0.929688f}, + {0.261719f, 0.238281f, 0.449219f, 0.265625f}, {0.863281f, 0.472656f, 0.953125f, 0.031250f}, + {0.105469f, 0.316406f, 0.292969f, 0.355469f}, {0.765625f, 0.976562f, 0.152344f, 0.531250f}, + {0.523438f, 0.195312f, 0.933594f, 0.828125f}, {0.343750f, 0.554688f, 0.242188f, 0.304688f}, + {0.414062f, 0.890625f, 0.414062f, 0.742188f}, {0.695312f, 0.496094f, 0.085938f, 0.250000f}, + {0.824219f, 0.933594f, 0.316406f, 0.832031f}, {0.109375f, 0.386719f, 0.433594f, 0.347656f}, + {0.199219f, 0.304688f, 0.000000f, 0.632812f}, {0.023438f, 0.843750f, 0.378906f, 0.988281f}, + {0.679688f, 0.480469f, 0.746094f, 0.429688f}, {0.265625f, 0.769531f, 0.312500f, 0.574219f}, + {0.058594f, 0.941406f, 0.593750f, 0.359375f}, {0.507812f, 0.074219f, 0.992188f, 0.527344f}, + {0.160156f, 0.308594f, 0.167969f, 0.214844f}, {0.945312f, 0.382812f, 0.644531f, 0.964844f}, + {0.789062f, 0.105469f, 0.117188f, 0.441406f}, {0.523438f, 0.613281f, 0.875000f, 0.812500f}, + {0.722656f, 0.953125f, 0.492188f, 0.226562f}, {0.371094f, 0.347656f, 0.226562f, 0.617188f}, + {0.101562f, 0.214844f, 0.984375f, 0.464844f}, {0.628906f, 0.406250f, 0.433594f, 0.742188f}, + {0.777344f, 0.011719f, 0.035156f, 0.199219f}, {0.480469f, 0.277344f, 0.753906f, 0.855469f}, + {0.339844f, 0.332031f, 0.347656f, 0.281250f}, {0.093750f, 0.207031f, 0.671875f, 0.792969f}, + {0.808594f, 0.699219f, 0.156250f, 0.121094f}, {0.226562f, 0.097656f, 0.507812f, 0.335938f}, + {0.476562f, 0.941406f, 0.367188f, 0.945312f}, {0.109375f, 0.660156f, 0.187500f, 0.210938f}, + {0.800781f, 0.750000f, 0.609375f, 0.066406f}, {0.382812f, 0.984375f, 0.824219f, 0.714844f}, + {0.738281f, 0.242188f, 0.296875f, 0.554688f}, {0.222656f, 0.832031f, 0.917969f, 0.906250f}, + {0.320312f, 0.929688f, 0.464844f, 0.503906f}, {0.980469f, 0.519531f, 0.175781f, 0.277344f}, + {0.500000f, 0.312500f, 0.808594f, 0.664062f}, {0.285156f, 0.816406f, 0.562500f, 0.789062f}, + {0.929688f, 0.542969f, 0.437500f, 0.382812f}, {0.542969f, 0.414062f, 0.507812f, 0.023438f}, + {0.777344f, 0.847656f, 0.308594f, 0.843750f}, {0.976562f, 0.121094f, 0.738281f, 0.527344f}, + {0.042969f, 0.511719f, 0.164062f, 0.316406f}, {0.507812f, 0.812500f, 0.492188f, 0.824219f}, + {0.339844f, 0.183594f, 0.875000f, 0.089844f}, {0.773438f, 0.074219f, 0.546875f, 0.281250f}, + {0.460938f, 0.640625f, 0.929688f, 0.195312f}, {0.558594f, 0.121094f, 0.105469f, 0.695312f}, + {0.285156f, 0.316406f, 0.781250f, 0.523438f}, {0.875000f, 0.769531f, 0.414062f, 0.019531f}, + {0.121094f, 0.222656f, 0.984375f, 0.710938f}, {0.488281f, 0.710938f, 0.269531f, 0.398438f}, + {0.992188f, 0.031250f, 0.625000f, 0.656250f}, {0.421875f, 0.597656f, 0.437500f, 0.101562f}, + {0.593750f, 0.890625f, 0.777344f, 0.226562f}, {0.839844f, 0.214844f, 0.601562f, 0.589844f}, + {0.718750f, 0.402344f, 0.253906f, 0.523438f}, {0.644531f, 0.019531f, 0.855469f, 0.687500f}, + {0.433594f, 0.820312f, 0.667969f, 0.992188f}, {0.167969f, 0.746094f, 0.050781f, 0.238281f}, + {0.109375f, 0.128906f, 0.582031f, 0.105469f}, {0.363281f, 0.847656f, 0.527344f, 0.527344f}, + {0.687500f, 0.531250f, 0.191406f, 0.804688f}, {0.562500f, 0.777344f, 0.101562f, 0.683594f}, + {0.636719f, 0.597656f, 0.796875f, 0.890625f}, {0.953125f, 0.402344f, 0.726562f, 0.113281f}, + {0.164062f, 0.832031f, 0.011719f, 0.453125f}, {0.734375f, 0.265625f, 0.343750f, 0.019531f}, + {0.210938f, 0.046875f, 0.675781f, 0.941406f}, {0.003906f, 0.089844f, 0.910156f, 0.421875f}, + {0.535156f, 0.703125f, 0.523438f, 0.058594f}, {0.382812f, 0.578125f, 0.980469f, 0.582031f}, + {0.984375f, 0.113281f, 0.699219f, 0.761719f}, {0.304688f, 0.906250f, 0.851562f, 0.023438f}, + {0.859375f, 0.167969f, 0.250000f, 0.261719f}, {0.453125f, 0.230469f, 0.144531f, 0.113281f}, + {0.960938f, 0.429688f, 0.453125f, 0.828125f}, {0.757812f, 0.628906f, 0.695312f, 0.156250f}, + {0.375000f, 0.792969f, 0.343750f, 0.757812f}, {0.691406f, 0.476562f, 0.558594f, 0.593750f}, + {0.250000f, 0.906250f, 0.300781f, 0.332031f}, {0.140625f, 0.152344f, 0.707031f, 0.136719f}, + {0.871094f, 0.824219f, 0.394531f, 0.667969f}, {0.582031f, 0.496094f, 0.828125f, 0.941406f}, + {0.453125f, 0.589844f, 0.769531f, 0.394531f}, {0.167969f, 0.910156f, 0.285156f, 0.058594f}, + {0.027344f, 0.750000f, 0.195312f, 0.675781f}, {0.570312f, 0.949219f, 0.867188f, 0.515625f}, + {0.843750f, 0.519531f, 0.078125f, 0.933594f}, {0.937500f, 0.878906f, 0.835938f, 0.070312f}, + {0.539062f, 0.039062f, 0.292969f, 0.625000f}, {0.761719f, 0.492188f, 0.796875f, 0.558594f}, + {0.597656f, 0.285156f, 0.703125f, 0.828125f}, {0.160156f, 0.171875f, 0.957031f, 0.656250f}, + {0.671875f, 0.058594f, 0.035156f, 0.433594f}, {0.503906f, 0.324219f, 0.417969f, 0.863281f}, + {0.925781f, 0.453125f, 0.230469f, 0.250000f}, {0.566406f, 0.136719f, 0.742188f, 0.031250f}, + {0.066406f, 0.195312f, 0.097656f, 0.968750f}, {0.417969f, 0.753906f, 0.988281f, 0.097656f}, + {0.675781f, 0.113281f, 0.273438f, 0.546875f}, {0.726562f, 0.468750f, 0.339844f, 0.136719f}, + {0.394531f, 0.171875f, 0.914062f, 0.253906f}, {0.144531f, 0.277344f, 0.128906f, 0.996094f}, + {0.316406f, 0.039062f, 0.578125f, 0.644531f}, {0.714844f, 0.574219f, 0.820312f, 0.910156f}, + {0.378906f, 0.222656f, 0.269531f, 0.437500f}, {0.906250f, 0.984375f, 0.707031f, 0.175781f}, + {0.113281f, 0.371094f, 0.339844f, 0.765625f}, {0.851562f, 0.882812f, 0.242188f, 0.570312f}, + {0.015625f, 0.472656f, 0.453125f, 0.343750f}, {0.664062f, 0.972656f, 0.292969f, 0.984375f}, + {0.097656f, 0.523438f, 0.660156f, 0.421875f}, {0.429688f, 0.058594f, 0.527344f, 0.234375f}, + {0.187500f, 0.933594f, 0.070312f, 0.925781f}, {0.628906f, 0.132812f, 0.679688f, 0.558594f}, + {0.753906f, 0.796875f, 0.203125f, 0.773438f}, {0.070312f, 0.484375f, 0.847656f, 0.328125f}, + {0.355469f, 0.964844f, 0.035156f, 0.855469f}, {0.527344f, 0.335938f, 0.390625f, 0.933594f}, + {0.210938f, 0.625000f, 0.191406f, 0.367188f}, {0.976562f, 0.460938f, 0.507812f, 0.191406f}, + {0.582031f, 0.171875f, 0.425781f, 0.765625f}, {0.882812f, 0.507812f, 0.761719f, 0.332031f}, + {0.812500f, 0.914062f, 0.265625f, 0.636719f}, {0.496094f, 0.050781f, 0.976562f, 0.875000f}, + {0.980469f, 0.355469f, 0.738281f, 0.187500f}, {0.031250f, 0.898438f, 0.605469f, 0.476562f}, + {0.320312f, 0.027344f, 0.410156f, 0.597656f}, {0.441406f, 0.734375f, 0.507812f, 0.218750f}, + {0.066406f, 0.140625f, 0.894531f, 0.714844f}, {0.894531f, 0.468750f, 0.550781f, 0.562500f}, + {0.652344f, 0.789062f, 0.785156f, 0.648438f}, {0.863281f, 0.972656f, 0.132812f, 0.191406f}, + {0.457031f, 0.425781f, 0.277344f, 0.894531f}, {0.738281f, 0.203125f, 0.605469f, 0.683594f}, + {0.640625f, 0.808594f, 0.480469f, 0.472656f}, {0.777344f, 0.515625f, 0.183594f, 0.199219f}, + {0.125000f, 0.339844f, 0.953125f, 0.921875f}, {0.570312f, 0.671875f, 0.539062f, 0.500000f}, + {0.210938f, 0.730469f, 0.781250f, 0.671875f}, {0.097656f, 0.019531f, 0.019531f, 0.890625f}, + {0.597656f, 0.968750f, 0.835938f, 0.406250f}, {0.468750f, 0.191406f, 0.914062f, 0.082031f}, + {0.042969f, 0.667969f, 0.445312f, 0.847656f}, {0.648438f, 0.421875f, 0.050781f, 0.722656f}, + {0.335938f, 0.773438f, 0.179688f, 0.000000f}, {0.992188f, 0.300781f, 0.636719f, 0.257812f}, + {0.273438f, 0.066406f, 0.093750f, 0.562500f}, {0.750000f, 0.171875f, 0.476562f, 0.902344f}, + {0.902344f, 0.660156f, 0.691406f, 0.320312f}, {0.300781f, 0.445312f, 0.527344f, 0.144531f}, + {0.195312f, 0.621094f, 0.406250f, 0.457031f}, {0.429688f, 0.152344f, 0.968750f, 0.707031f}, + {0.273438f, 0.734375f, 0.453125f, 0.414062f}, {0.003906f, 0.914062f, 0.578125f, 0.265625f}, + {0.410156f, 0.355469f, 0.093750f, 0.484375f}, {0.996094f, 0.847656f, 0.316406f, 0.148438f}, + {0.839844f, 0.605469f, 0.484375f, 0.359375f}, {0.031250f, 0.511719f, 0.898438f, 0.773438f}, + {0.187500f, 0.726562f, 0.679688f, 0.589844f}, {0.867188f, 0.644531f, 0.355469f, 0.390625f}, + {0.136719f, 0.878906f, 0.843750f, 0.640625f}, {0.597656f, 0.589844f, 0.597656f, 0.441406f}, + {0.222656f, 0.394531f, 0.714844f, 0.355469f}, {0.003906f, 0.863281f, 0.031250f, 0.925781f}, + {0.871094f, 0.691406f, 0.761719f, 0.597656f}, {0.621094f, 0.628906f, 0.195312f, 0.414062f}, + {0.230469f, 0.769531f, 0.941406f, 0.074219f}, {0.582031f, 0.929688f, 0.023438f, 0.230469f}, + {0.812500f, 0.433594f, 0.398438f, 0.722656f}, {0.195312f, 0.304688f, 0.996094f, 0.000000f}, + {0.679688f, 0.761719f, 0.089844f, 0.496094f}, {0.593750f, 0.605469f, 0.636719f, 0.925781f}, + {0.222656f, 0.277344f, 0.750000f, 0.136719f}, {0.902344f, 0.730469f, 0.164062f, 0.644531f}, + {0.515625f, 0.191406f, 0.863281f, 0.785156f}, {0.722656f, 0.585938f, 0.031250f, 0.601562f}, + {0.949219f, 0.457031f, 0.921875f, 0.183594f}, {0.312500f, 0.851562f, 0.468750f, 0.066406f}, + {0.003906f, 0.390625f, 0.750000f, 0.257812f}, {0.265625f, 0.304688f, 0.308594f, 0.496094f}, + {0.808594f, 0.097656f, 0.542969f, 0.035156f}, {0.894531f, 0.761719f, 0.136719f, 0.152344f}, + {0.089844f, 0.691406f, 0.992188f, 0.445312f}, {0.382812f, 0.070312f, 0.792969f, 0.070312f}, + {0.011719f, 0.984375f, 0.355469f, 0.843750f}, {0.281250f, 0.308594f, 0.910156f, 0.593750f}, + {0.660156f, 0.648438f, 0.152344f, 0.429688f}, {0.210938f, 0.210938f, 0.468750f, 0.722656f}, + {0.406250f, 0.703125f, 0.019531f, 0.304688f}, {0.148438f, 0.273438f, 0.882812f, 0.078125f}, + {0.832031f, 0.089844f, 0.250000f, 0.968750f}, {0.242188f, 0.863281f, 0.652344f, 0.335938f}, + {0.601562f, 0.371094f, 0.199219f, 0.847656f}, {0.484375f, 0.679688f, 0.062500f, 0.277344f}, + {0.289062f, 0.617188f, 0.453125f, 0.378906f}, {0.941406f, 0.343750f, 0.863281f, 0.515625f}, + {0.152344f, 0.281250f, 0.218750f, 0.128906f}, {0.238281f, 0.746094f, 0.039062f, 0.316406f}, + {0.046875f, 0.636719f, 0.792969f, 0.871094f}, {0.496094f, 0.031250f, 0.351562f, 0.390625f}, + {0.406250f, 0.980469f, 0.660156f, 0.789062f}, {0.707031f, 0.558594f, 0.054688f, 0.609375f}, + {0.886719f, 0.859375f, 0.890625f, 0.320312f}, {0.312500f, 0.132812f, 0.394531f, 0.039062f}, + {0.816406f, 0.265625f, 0.250000f, 0.242188f}, {0.906250f, 0.355469f, 0.097656f, 0.488281f}, + {0.410156f, 0.539062f, 0.746094f, 0.921875f}, {0.769531f, 0.093750f, 0.972656f, 0.539062f}, + {0.203125f, 0.246094f, 0.527344f, 0.425781f}, {0.070312f, 0.695312f, 0.324219f, 0.800781f}, + {0.820312f, 0.878906f, 0.906250f, 0.117188f}, {0.515625f, 0.375000f, 0.574219f, 0.761719f}, + {0.660156f, 0.238281f, 0.941406f, 0.605469f}, {0.113281f, 0.105469f, 0.132812f, 0.835938f}, + {0.710938f, 0.820312f, 0.652344f, 0.238281f}, {0.621094f, 0.394531f, 0.214844f, 0.992188f}, + {0.136719f, 0.253906f, 0.011719f, 0.187500f}, {0.921875f, 0.578125f, 0.902344f, 0.046875f}, + {0.730469f, 0.441406f, 0.246094f, 0.886719f}, {0.300781f, 0.800781f, 0.847656f, 0.957031f}, + {0.238281f, 0.222656f, 0.648438f, 0.687500f}, {0.355469f, 0.894531f, 0.136719f, 0.109375f}, + {0.707031f, 0.027344f, 0.554688f, 0.199219f}, {0.453125f, 0.285156f, 0.003906f, 0.800781f}, + {0.953125f, 0.074219f, 0.511719f, 0.156250f}, {0.750000f, 0.671875f, 0.152344f, 0.863281f}, + {0.824219f, 0.238281f, 0.402344f, 0.699219f}, {0.339844f, 0.003906f, 0.492188f, 0.042969f}, + {0.964844f, 0.980469f, 0.867188f, 0.753906f}, {0.101562f, 0.367188f, 0.617188f, 0.511719f}, + {0.492188f, 0.488281f, 0.363281f, 0.300781f}, {0.062500f, 0.156250f, 0.667969f, 0.800781f}, + {0.277344f, 0.652344f, 0.550781f, 0.355469f}, {0.441406f, 0.062500f, 0.847656f, 0.601562f}, + {0.953125f, 0.535156f, 0.199219f, 0.847656f}, {0.316406f, 0.140625f, 0.011719f, 0.250000f}, + {0.757812f, 0.019531f, 0.910156f, 0.390625f}, {0.359375f, 0.390625f, 0.570312f, 0.042969f}, + {0.054688f, 0.902344f, 0.386719f, 0.863281f}, {0.824219f, 0.339844f, 0.714844f, 0.304688f}, + {0.390625f, 0.632812f, 0.242188f, 0.457031f}, {0.562500f, 0.238281f, 0.589844f, 0.734375f}, + {0.921875f, 0.683594f, 0.097656f, 0.953125f}, {0.507812f, 0.550781f, 0.949219f, 0.816406f}, + {0.671875f, 0.191406f, 0.878906f, 0.617188f}, {0.175781f, 0.835938f, 0.644531f, 0.703125f}, + {0.316406f, 0.273438f, 0.718750f, 0.789062f}, {0.757812f, 0.871094f, 0.000000f, 0.550781f}, + {0.546875f, 0.566406f, 0.113281f, 0.265625f}, {0.472656f, 0.382812f, 0.621094f, 0.941406f}, + {0.925781f, 0.796875f, 0.699219f, 0.156250f}, {0.058594f, 0.437500f, 0.386719f, 0.050781f}, + {0.777344f, 0.945312f, 0.308594f, 0.781250f}, {0.535156f, 0.496094f, 0.820312f, 0.394531f}, + {0.906250f, 0.644531f, 0.125000f, 0.656250f}, {0.703125f, 0.542969f, 0.371094f, 0.144531f}, + {0.804688f, 0.226562f, 0.988281f, 0.914062f}, {0.378906f, 0.906250f, 0.300781f, 0.046875f}, + {0.035156f, 0.175781f, 0.753906f, 0.785156f}, {0.570312f, 0.566406f, 0.628906f, 0.976562f}, + {0.343750f, 0.125000f, 0.390625f, 0.730469f}, {0.804688f, 0.878906f, 0.722656f, 0.238281f}, + {0.605469f, 0.453125f, 0.921875f, 0.539062f}, {0.953125f, 0.257812f, 0.089844f, 0.093750f}, + {0.179688f, 0.085938f, 0.429688f, 0.714844f}, {0.347656f, 0.402344f, 0.281250f, 0.167969f}, + {0.628906f, 0.300781f, 0.613281f, 0.449219f}, {0.007812f, 0.503906f, 0.507812f, 0.984375f}, + {0.539062f, 0.601562f, 0.187500f, 0.710938f}, {0.281250f, 0.835938f, 0.660156f, 0.632812f}, + {0.113281f, 0.738281f, 0.363281f, 0.285156f}, {0.953125f, 0.933594f, 0.593750f, 0.191406f}, + {0.554688f, 0.007812f, 0.238281f, 0.355469f}, {0.683594f, 0.625000f, 0.800781f, 0.980469f}, + {0.417969f, 0.472656f, 0.000000f, 0.500000f}, {0.222656f, 0.984375f, 0.371094f, 0.218750f}, + {0.382812f, 0.777344f, 0.253906f, 0.070312f}, {0.972656f, 0.566406f, 0.808594f, 0.378906f}, + {0.472656f, 0.308594f, 0.316406f, 0.542969f}, {0.789062f, 0.058594f, 0.609375f, 0.781250f}, + {0.855469f, 0.972656f, 0.726562f, 0.648438f}, {0.359375f, 0.652344f, 0.519531f, 0.746094f}, + {0.511719f, 0.000000f, 0.425781f, 0.582031f}, {0.074219f, 0.125000f, 0.750000f, 0.296875f}, + {0.625000f, 0.683594f, 0.382812f, 0.027344f}, {0.546875f, 0.960938f, 0.199219f, 0.523438f}, + {0.792969f, 0.414062f, 0.964844f, 0.917969f}, {0.269531f, 0.488281f, 0.773438f, 0.308594f}, + {0.375000f, 0.332031f, 0.312500f, 0.007812f}, {0.519531f, 0.941406f, 0.894531f, 0.570312f}, + {0.175781f, 0.777344f, 0.226562f, 0.210938f}, {0.558594f, 0.558594f, 0.687500f, 0.324219f}, + {0.449219f, 0.316406f, 0.078125f, 0.828125f}, {0.656250f, 0.101562f, 0.449219f, 0.164062f}, + {0.839844f, 0.832031f, 0.250000f, 0.683594f}, {0.914062f, 0.253906f, 0.777344f, 0.554688f}, + {0.738281f, 0.906250f, 0.144531f, 0.125000f}, {0.550781f, 0.714844f, 0.472656f, 0.945312f}, + {0.039062f, 0.863281f, 0.695312f, 0.660156f}, {0.140625f, 0.445312f, 0.421875f, 0.453125f}, + {0.476562f, 0.832031f, 0.796875f, 0.738281f}, {0.980469f, 0.679688f, 0.496094f, 0.101562f}, + {0.269531f, 0.792969f, 0.121094f, 0.500000f}, {0.160156f, 0.101562f, 0.324219f, 0.152344f}, + {0.656250f, 0.960938f, 0.820312f, 0.894531f}, {0.226562f, 0.000000f, 0.406250f, 0.640625f}, + {0.851562f, 0.742188f, 0.156250f, 0.343750f}, {0.136719f, 0.917969f, 0.359375f, 0.425781f}, + {0.414062f, 0.054688f, 0.492188f, 0.210938f}, {0.613281f, 0.441406f, 0.257812f, 0.300781f}, + {0.941406f, 0.511719f, 0.449219f, 0.972656f}, {0.699219f, 0.128906f, 0.570312f, 0.652344f}, + {0.847656f, 0.226562f, 0.281250f, 0.003906f}, {0.128906f, 0.734375f, 0.871094f, 0.375000f}, + {0.339844f, 0.007812f, 0.535156f, 0.507812f}, {0.726562f, 0.117188f, 0.074219f, 0.894531f}, + {0.257812f, 0.582031f, 0.933594f, 0.570312f}, {0.593750f, 0.171875f, 0.566406f, 0.250000f}, + {0.351562f, 0.410156f, 0.484375f, 0.488281f}, {0.117188f, 0.996094f, 0.703125f, 0.761719f}, + {0.191406f, 0.308594f, 0.843750f, 0.425781f}, {0.992188f, 0.003906f, 0.578125f, 0.609375f}, + {0.769531f, 0.503906f, 0.164062f, 0.097656f}, {0.105469f, 0.816406f, 0.945312f, 0.460938f}, + {0.699219f, 0.046875f, 0.109375f, 0.824219f}, {0.421875f, 0.957031f, 0.535156f, 0.007812f}, + {0.898438f, 0.359375f, 0.312500f, 0.636719f}, {0.281250f, 0.718750f, 0.582031f, 0.964844f}, + {0.082031f, 0.605469f, 0.863281f, 0.285156f}, {0.847656f, 0.800781f, 0.757812f, 0.070312f}, + {0.445312f, 0.203125f, 0.125000f, 0.820312f}, {0.980469f, 0.902344f, 0.714844f, 0.562500f}, + {0.164062f, 0.691406f, 0.921875f, 0.359375f}, {0.734375f, 0.046875f, 0.812500f, 0.144531f}, + {0.613281f, 0.457031f, 0.480469f, 0.777344f}, {0.359375f, 0.320312f, 0.140625f, 0.089844f}, + {0.488281f, 0.574219f, 0.886719f, 0.863281f}, {0.152344f, 0.855469f, 0.703125f, 0.636719f}, + {0.921875f, 0.136719f, 0.421875f, 0.296875f}, {0.011719f, 0.527344f, 0.167969f, 0.710938f}, + {0.601562f, 0.027344f, 0.742188f, 0.441406f}, {0.328125f, 0.707031f, 0.066406f, 0.882812f}, + {0.050781f, 0.906250f, 0.875000f, 0.015625f}, {0.246094f, 0.500000f, 0.378906f, 0.339844f}, + {0.566406f, 0.769531f, 0.117188f, 0.121094f}, {0.179688f, 0.195312f, 0.175781f, 0.386719f}, + {0.656250f, 0.527344f, 0.988281f, 0.816406f}, {0.882812f, 0.304688f, 0.042969f, 0.449219f}, + {0.425781f, 0.375000f, 0.601562f, 0.242188f}, {0.929688f, 0.562500f, 0.812500f, 0.617188f}, + {0.101562f, 0.164062f, 0.261719f, 0.468750f}, {0.644531f, 0.820312f, 0.441406f, 0.718750f}, + {0.023438f, 0.523438f, 0.632812f, 0.261719f}, {0.898438f, 0.437500f, 0.945312f, 0.953125f}, + {0.066406f, 0.140625f, 0.109375f, 0.492188f}, {0.281250f, 0.882812f, 0.832031f, 0.902344f}, + {0.781250f, 0.207031f, 0.292969f, 0.445312f}, {0.148438f, 0.722656f, 0.976562f, 0.089844f}, + {0.402344f, 0.593750f, 0.523438f, 0.960938f}, {0.351562f, 0.046875f, 0.066406f, 0.871094f}, + {0.175781f, 0.402344f, 0.316406f, 0.402344f}, {0.640625f, 0.339844f, 0.937500f, 0.046875f}, + {0.871094f, 0.199219f, 0.589844f, 0.203125f}, {0.414062f, 0.945312f, 0.355469f, 0.316406f}, + {0.691406f, 0.246094f, 0.277344f, 0.902344f}, {0.539062f, 0.507812f, 0.980469f, 0.566406f}, + {0.609375f, 0.167969f, 0.214844f, 0.679688f}, {0.781250f, 0.429688f, 0.617188f, 0.820312f}, + {0.464844f, 0.285156f, 0.875000f, 0.375000f}, {0.101562f, 0.488281f, 0.511719f, 0.019531f}, + {0.710938f, 0.156250f, 0.691406f, 0.121094f}, {0.363281f, 0.359375f, 0.792969f, 0.578125f}, + {0.792969f, 0.593750f, 0.046875f, 0.906250f}, {0.476562f, 0.972656f, 0.199219f, 0.089844f}, + {0.031250f, 0.667969f, 0.824219f, 0.390625f}, {0.242188f, 0.343750f, 0.933594f, 0.480469f}, + {0.421875f, 0.937500f, 0.339844f, 0.132812f}, {0.191406f, 0.613281f, 0.183594f, 0.750000f}, + {0.617188f, 0.472656f, 0.800781f, 0.675781f}, {0.867188f, 0.855469f, 0.230469f, 0.203125f}, + {0.449219f, 0.328125f, 0.660156f, 0.953125f}, {0.964844f, 0.746094f, 0.769531f, 0.828125f}, + {0.007812f, 0.824219f, 0.179688f, 0.011719f}, {0.503906f, 0.125000f, 0.085938f, 0.531250f}, + {0.421875f, 0.777344f, 0.433594f, 0.199219f}, {0.660156f, 0.710938f, 0.027344f, 0.679688f}, + {0.261719f, 0.941406f, 0.347656f, 0.257812f}, {0.527344f, 0.386719f, 0.492188f, 0.351562f}, + {0.843750f, 0.660156f, 0.671875f, 0.179688f}, {0.195312f, 0.195312f, 0.246094f, 0.578125f}, + {0.062500f, 0.539062f, 0.828125f, 0.429688f}, {0.519531f, 0.847656f, 0.156250f, 0.363281f}, + {0.730469f, 0.156250f, 0.472656f, 0.855469f}, {0.789062f, 0.941406f, 0.210938f, 0.527344f}, + {0.250000f, 0.445312f, 0.960938f, 0.218750f}, {0.671875f, 0.078125f, 0.320312f, 0.753906f}, + {0.500000f, 0.378906f, 0.417969f, 0.015625f}, {0.222656f, 0.988281f, 0.066406f, 0.949219f}, + {0.828125f, 0.164062f, 0.285156f, 0.453125f}, {0.031250f, 0.222656f, 0.761719f, 0.589844f}, + {0.878906f, 0.800781f, 0.042969f, 0.691406f}, {0.308594f, 0.351562f, 0.460938f, 0.027344f}, + {0.789062f, 0.417969f, 0.656250f, 0.160156f}, {0.726562f, 0.285156f, 0.972656f, 0.941406f}, + {0.859375f, 0.207031f, 0.597656f, 0.796875f}, {0.535156f, 0.839844f, 0.496094f, 0.621094f}, + {0.941406f, 0.343750f, 0.445312f, 0.285156f}, {0.097656f, 0.164062f, 0.949219f, 0.914062f}, + {0.687500f, 0.421875f, 0.789062f, 0.492188f}, {0.453125f, 0.871094f, 0.675781f, 0.214844f}, + {0.035156f, 0.710938f, 0.289062f, 0.078125f}, {0.781250f, 0.941406f, 0.542969f, 0.703125f}, + {0.207031f, 0.777344f, 0.101562f, 0.867188f}, {0.152344f, 0.089844f, 0.339844f, 0.984375f}, + {0.480469f, 0.257812f, 0.707031f, 0.371094f}, {0.843750f, 0.722656f, 0.070312f, 0.835938f}, + {0.230469f, 0.199219f, 0.750000f, 0.417969f}, {0.417969f, 0.054688f, 0.542969f, 0.773438f}, + {0.617188f, 0.632812f, 0.375000f, 0.070312f}, {0.710938f, 0.386719f, 0.578125f, 0.613281f}, + {0.921875f, 0.500000f, 0.652344f, 0.281250f}, {0.246094f, 0.921875f, 0.164062f, 0.644531f}, + {0.687500f, 0.445312f, 0.890625f, 0.218750f}, {0.023438f, 0.789062f, 0.718750f, 0.476562f}, + {0.996094f, 0.523438f, 0.820312f, 0.269531f}, {0.507812f, 0.117188f, 0.234375f, 0.710938f}, + {0.253906f, 0.628906f, 0.105469f, 0.531250f}, {0.824219f, 0.574219f, 0.886719f, 0.800781f}, + {0.070312f, 0.316406f, 0.050781f, 0.164062f}, {0.199219f, 0.039062f, 0.664062f, 0.964844f}, + {0.867188f, 0.652344f, 0.769531f, 0.277344f}, {0.023438f, 0.867188f, 0.078125f, 0.222656f}, + {0.335938f, 0.769531f, 0.960938f, 0.535156f}, {0.898438f, 0.535156f, 0.015625f, 0.996094f}, + {0.585938f, 0.890625f, 0.269531f, 0.691406f}, {0.054688f, 0.644531f, 0.925781f, 0.175781f}, + {0.980469f, 0.261719f, 0.585938f, 0.511719f}, {0.285156f, 0.789062f, 0.667969f, 0.742188f}, + {0.113281f, 0.023438f, 0.402344f, 0.859375f}, {0.578125f, 0.417969f, 0.066406f, 0.230469f}, + {0.800781f, 0.816406f, 0.753906f, 0.921875f}, {0.992188f, 0.164062f, 0.492188f, 0.816406f}, + {0.519531f, 0.281250f, 0.414062f, 0.289062f}, {0.085938f, 0.675781f, 0.968750f, 0.449219f}, + {0.167969f, 0.964844f, 0.046875f, 0.347656f}, {0.671875f, 0.035156f, 0.347656f, 0.113281f}, + {0.761719f, 0.257812f, 0.277344f, 0.714844f}, {0.300781f, 0.457031f, 0.925781f, 0.316406f}, + {0.578125f, 0.605469f, 0.617188f, 0.984375f}, {0.875000f, 0.082031f, 0.789062f, 0.851562f}, + {0.156250f, 0.437500f, 0.265625f, 0.558594f}, {0.453125f, 0.253906f, 0.738281f, 0.898438f}, + {0.968750f, 0.761719f, 0.882812f, 0.703125f}, {0.312500f, 0.480469f, 0.406250f, 0.949219f}, + {0.679688f, 0.097656f, 0.031250f, 0.773438f}, {0.589844f, 0.308594f, 0.996094f, 0.125000f}, + {0.375000f, 0.679688f, 0.691406f, 0.675781f}, {0.128906f, 0.000000f, 0.375000f, 0.929688f}, + {0.562500f, 0.753906f, 0.570312f, 0.421875f}, {0.050781f, 0.562500f, 0.003906f, 0.304688f}, + {0.386719f, 0.250000f, 0.531250f, 0.648438f}, {0.937500f, 0.781250f, 0.621094f, 0.843750f}, + {0.437500f, 0.636719f, 0.953125f, 0.515625f}, {0.695312f, 0.515625f, 0.214844f, 0.242188f}, + {0.253906f, 0.949219f, 0.562500f, 0.910156f}, {0.636719f, 0.097656f, 0.296875f, 0.406250f}, + {0.453125f, 0.746094f, 0.109375f, 0.566406f}, {0.121094f, 0.917969f, 0.832031f, 0.480469f}, + {0.269531f, 0.632812f, 0.207031f, 0.105469f}, {0.183594f, 0.449219f, 0.281250f, 0.179688f}, + {0.746094f, 0.675781f, 0.031250f, 0.691406f}, {0.402344f, 0.113281f, 0.558594f, 0.574219f}, + {0.894531f, 0.613281f, 0.238281f, 0.839844f}, {0.277344f, 0.277344f, 0.351562f, 0.964844f}, + {0.976562f, 0.074219f, 0.832031f, 0.535156f}, {0.332031f, 0.472656f, 0.464844f, 0.335938f}, + {0.738281f, 0.597656f, 0.882812f, 0.171875f}, {0.601562f, 0.855469f, 0.937500f, 0.125000f}, + {0.292969f, 0.648438f, 0.500000f, 0.058594f}, {0.687500f, 0.996094f, 0.175781f, 0.660156f}, + {0.984375f, 0.582031f, 0.820312f, 0.527344f}, {0.757812f, 0.761719f, 0.253906f, 0.339844f}, + {0.488281f, 0.843750f, 0.472656f, 0.128906f}, {0.324219f, 0.265625f, 0.007812f, 0.726562f}, + {0.085938f, 0.023438f, 0.792969f, 0.386719f}, {0.519531f, 0.664062f, 0.414062f, 0.789062f}, + {0.578125f, 0.175781f, 0.351562f, 0.015625f}, {0.792969f, 0.292969f, 0.035156f, 0.585938f}, + {0.308594f, 0.992188f, 0.441406f, 0.769531f}, {0.105469f, 0.683594f, 0.648438f, 0.988281f}, + {0.765625f, 0.804688f, 0.519531f, 0.093750f}, {0.371094f, 0.074219f, 0.734375f, 0.621094f}, + {0.929688f, 0.746094f, 0.156250f, 0.359375f}, {0.296875f, 0.964844f, 0.546875f, 0.011719f}, + {0.722656f, 0.554688f, 0.453125f, 0.414062f}, {0.402344f, 0.347656f, 0.371094f, 0.761719f}, + {0.964844f, 0.207031f, 0.187500f, 0.078125f}, {0.511719f, 0.074219f, 0.558594f, 0.476562f}, + {0.257812f, 0.808594f, 0.433594f, 0.781250f}, {0.191406f, 0.410156f, 0.746094f, 0.839844f}, + {0.750000f, 0.109375f, 0.117188f, 0.281250f}, {0.531250f, 0.195312f, 0.312500f, 0.031250f}, + {0.859375f, 0.562500f, 0.976562f, 0.570312f}, {0.664062f, 0.703125f, 0.148438f, 0.320312f}, + {0.363281f, 0.078125f, 0.687500f, 0.613281f}, {0.062500f, 0.531250f, 0.593750f, 0.082031f}, + {0.703125f, 0.886719f, 0.105469f, 0.539062f}, {0.316406f, 0.382812f, 0.632812f, 0.035156f}, + {0.390625f, 0.218750f, 0.453125f, 0.644531f}, {0.835938f, 0.562500f, 0.718750f, 0.582031f}, + {0.214844f, 0.660156f, 0.546875f, 0.886719f}, {0.933594f, 0.359375f, 0.875000f, 0.160156f}, + {0.089844f, 0.890625f, 0.218750f, 0.378906f}, {0.730469f, 0.210938f, 0.519531f, 0.062500f}, + {0.359375f, 0.558594f, 0.972656f, 0.480469f}, {0.621094f, 0.324219f, 0.074219f, 0.136719f}, + {0.042969f, 0.871094f, 0.191406f, 0.304688f}, {0.761719f, 0.589844f, 0.449219f, 0.050781f}, + {0.476562f, 0.914062f, 0.750000f, 0.253906f}, {0.929688f, 0.414062f, 0.621094f, 0.476562f}, + {0.218750f, 0.234375f, 0.269531f, 0.195312f}, {0.867188f, 0.519531f, 0.082031f, 0.042969f}, + {0.320312f, 0.648438f, 0.773438f, 0.613281f}, {0.898438f, 0.328125f, 0.882812f, 0.882812f}, + {0.769531f, 0.882812f, 0.175781f, 0.113281f}, {0.093750f, 0.109375f, 0.828125f, 0.183594f}, + {0.566406f, 0.406250f, 0.687500f, 0.378906f}, {0.179688f, 0.714844f, 0.394531f, 0.054688f}, + {0.984375f, 0.042969f, 0.863281f, 0.316406f}, {0.066406f, 0.671875f, 0.937500f, 0.824219f}, + {0.574219f, 0.183594f, 0.351562f, 0.757812f}, {0.371094f, 0.570312f, 0.531250f, 0.347656f}, + {0.675781f, 0.070312f, 0.718750f, 0.261719f}, {0.480469f, 0.949219f, 0.902344f, 0.976562f}, + {0.808594f, 0.250000f, 0.648438f, 0.398438f}, {0.343750f, 0.539062f, 0.761719f, 0.054688f}, + {0.601562f, 0.984375f, 0.082031f, 0.152344f}, {0.828125f, 0.828125f, 0.917969f, 0.730469f}, + {0.121094f, 0.355469f, 0.625000f, 0.636719f}, {0.554688f, 0.226562f, 0.148438f, 0.406250f}, + {0.398438f, 0.148438f, 0.222656f, 0.792969f}, {0.945312f, 0.429688f, 0.664062f, 0.562500f}, + {0.082031f, 0.015625f, 0.410156f, 0.753906f}, {0.351562f, 0.367188f, 0.039062f, 0.187500f}, + {0.562500f, 0.121094f, 0.359375f, 0.238281f}, {0.191406f, 0.308594f, 0.992188f, 0.886719f}, + {0.128906f, 0.703125f, 0.144531f, 0.988281f}, {0.812500f, 0.539062f, 0.707031f, 0.558594f}, + {0.968750f, 0.968750f, 0.933594f, 0.179688f}, {0.429688f, 0.335938f, 0.214844f, 0.929688f}, + {0.195312f, 0.753906f, 0.554688f, 0.859375f}, {0.902344f, 0.867188f, 0.613281f, 0.363281f}, + {0.468750f, 0.031250f, 0.960938f, 0.152344f}, {0.613281f, 0.234375f, 0.183594f, 0.304688f}, + {0.210938f, 0.417969f, 0.292969f, 0.429688f}, {0.570312f, 0.476562f, 0.855469f, 0.882812f}, + {0.652344f, 0.828125f, 0.406250f, 0.480469f}, {0.453125f, 0.386719f, 0.941406f, 0.722656f}, + {0.085938f, 0.117188f, 0.246094f, 0.585938f}, {0.558594f, 0.710938f, 0.730469f, 0.933594f}, + {0.140625f, 0.609375f, 0.804688f, 0.632812f}, {0.828125f, 0.996094f, 0.652344f, 0.320312f}, + {0.687500f, 0.312500f, 0.335938f, 0.234375f}, {0.441406f, 0.472656f, 0.222656f, 0.402344f}, + {0.632812f, 0.730469f, 0.890625f, 0.937500f}, {0.332031f, 0.871094f, 0.531250f, 0.675781f}, + {0.164062f, 0.304688f, 0.464844f, 0.445312f}, {0.906250f, 0.914062f, 0.851562f, 0.160156f}, + {0.460938f, 0.238281f, 0.246094f, 0.722656f}, {0.273438f, 0.753906f, 0.917969f, 0.398438f}, + {0.777344f, 0.046875f, 0.304688f, 0.992188f}, {0.941406f, 0.496094f, 0.863281f, 0.847656f}, + {0.554688f, 0.781250f, 0.144531f, 0.179688f}, {0.050781f, 0.097656f, 0.816406f, 0.406250f}, + {0.621094f, 0.925781f, 0.003906f, 0.789062f}, {0.468750f, 0.515625f, 0.406250f, 0.273438f}, + {0.820312f, 0.156250f, 0.679688f, 0.621094f}, {0.027344f, 0.691406f, 0.140625f, 0.734375f}, + {0.234375f, 0.828125f, 0.382812f, 0.808594f}, {0.890625f, 0.054688f, 0.640625f, 0.410156f}, + {0.398438f, 0.144531f, 0.582031f, 0.652344f}, {0.117188f, 0.722656f, 0.804688f, 0.519531f}, + {0.265625f, 0.035156f, 0.132812f, 0.835938f}, {0.824219f, 0.781250f, 0.335938f, 0.589844f}, + {0.015625f, 0.972656f, 0.503906f, 0.324219f}, {0.644531f, 0.367188f, 0.843750f, 0.792969f}, + {0.460938f, 0.839844f, 0.656250f, 0.375000f}, {0.707031f, 0.179688f, 0.445312f, 0.496094f}, + {0.148438f, 0.484375f, 0.253906f, 0.269531f}, {0.292969f, 0.585938f, 0.347656f, 0.710938f}, + {0.800781f, 0.292969f, 0.101562f, 0.792969f}, {0.343750f, 0.847656f, 0.503906f, 0.992188f}, + {0.511719f, 0.453125f, 0.160156f, 0.542969f}, {0.843750f, 0.261719f, 0.628906f, 0.207031f}, + {0.214844f, 0.878906f, 0.777344f, 0.082031f}, {0.957031f, 0.492188f, 0.054688f, 0.855469f}, + {0.890625f, 0.382812f, 0.136719f, 0.656250f}, {0.019531f, 0.804688f, 0.328125f, 0.519531f}, + {0.636719f, 0.042969f, 0.402344f, 0.753906f}, {0.148438f, 0.753906f, 0.179688f, 0.449219f}, + {0.046875f, 0.398438f, 0.507812f, 0.320312f}, {0.511719f, 0.019531f, 0.429688f, 0.253906f}, + {0.222656f, 0.660156f, 0.003906f, 0.003906f}, {0.707031f, 0.910156f, 0.726562f, 0.933594f}, + {0.011719f, 0.742188f, 0.781250f, 0.281250f}, {0.863281f, 0.316406f, 0.281250f, 0.445312f}, + {0.515625f, 0.496094f, 0.570312f, 0.910156f}, {0.785156f, 0.875000f, 0.867188f, 0.605469f}, + {0.042969f, 0.230469f, 0.207031f, 0.824219f}, {0.667969f, 0.468750f, 0.605469f, 0.472656f}, + {0.878906f, 0.906250f, 0.316406f, 0.046875f}, {0.382812f, 0.164062f, 0.765625f, 0.671875f}, + {0.015625f, 0.093750f, 0.070312f, 0.312500f}, {0.640625f, 0.425781f, 0.277344f, 0.457031f}, + {0.847656f, 0.613281f, 0.859375f, 0.113281f}, {0.062500f, 0.128906f, 0.128906f, 0.691406f}, + {0.726562f, 0.558594f, 0.761719f, 0.503906f}, {0.398438f, 0.355469f, 0.382812f, 0.917969f}, + {0.886719f, 0.925781f, 0.000000f, 0.667969f}, {0.000000f, 0.148438f, 0.792969f, 0.062500f}, + {0.156250f, 0.277344f, 0.597656f, 0.242188f}, {0.808594f, 0.191406f, 0.316406f, 0.855469f}, + {0.945312f, 0.910156f, 0.042969f, 0.117188f}, {0.226562f, 0.453125f, 0.914062f, 0.191406f}, + {0.761719f, 0.250000f, 0.109375f, 0.441406f}, {0.308594f, 0.015625f, 0.480469f, 0.882812f}, + {0.015625f, 0.671875f, 0.847656f, 0.132812f}, {0.878906f, 0.144531f, 0.074219f, 0.605469f}, + {0.933594f, 0.945312f, 0.613281f, 0.074219f}, {0.074219f, 0.503906f, 0.777344f, 0.359375f}, + {0.406250f, 0.378906f, 0.050781f, 0.796875f}, {0.718750f, 0.605469f, 0.367188f, 0.886719f}, + {0.003906f, 0.449219f, 0.554688f, 0.500000f}, {0.218750f, 0.988281f, 0.015625f, 0.218750f}, + {0.640625f, 0.636719f, 0.730469f, 0.769531f}, {0.117188f, 0.144531f, 0.375000f, 0.269531f}, + {0.429688f, 0.429688f, 0.250000f, 0.691406f}, {0.902344f, 0.839844f, 0.488281f, 0.957031f}, + {0.261719f, 0.316406f, 0.949219f, 0.460938f}, {0.339844f, 0.738281f, 0.304688f, 0.085938f}, + {0.531250f, 0.015625f, 0.101562f, 0.507812f}, {0.691406f, 0.984375f, 0.832031f, 0.941406f}, + {0.945312f, 0.378906f, 0.890625f, 0.015625f}, {0.562500f, 0.628906f, 0.324219f, 0.203125f}, + {0.796875f, 0.953125f, 0.011719f, 0.921875f}, {0.656250f, 0.285156f, 0.953125f, 0.730469f}, + {0.167969f, 0.183594f, 0.542969f, 0.085938f}, {0.542969f, 0.468750f, 0.906250f, 0.890625f}, + {0.410156f, 0.617188f, 0.046875f, 0.695312f}, {0.996094f, 0.128906f, 0.199219f, 0.972656f}, + {0.191406f, 0.050781f, 0.945312f, 0.148438f}, {0.511719f, 0.937500f, 0.117188f, 0.738281f}, + {0.613281f, 0.734375f, 0.722656f, 0.910156f}, {0.921875f, 0.019531f, 0.988281f, 0.429688f}, + {0.652344f, 0.972656f, 0.601562f, 0.601562f}, {0.003906f, 0.136719f, 0.746094f, 0.664062f}, + {0.722656f, 0.359375f, 0.011719f, 0.148438f}, {0.402344f, 0.609375f, 0.257812f, 0.718750f}, + {0.765625f, 0.785156f, 0.414062f, 0.437500f}, {0.082031f, 0.296875f, 0.480469f, 0.605469f}, + {0.542969f, 0.144531f, 0.996094f, 0.011719f}, {0.312500f, 0.699219f, 0.589844f, 0.882812f}, + {0.242188f, 0.328125f, 0.859375f, 0.222656f}, {0.968750f, 0.593750f, 0.699219f, 0.804688f}, + {0.425781f, 0.156250f, 0.964844f, 0.902344f}, {0.753906f, 0.492188f, 0.296875f, 0.605469f}, + {0.917969f, 0.792969f, 0.582031f, 0.472656f}, {0.468750f, 0.546875f, 0.382812f, 0.847656f}, + {0.632812f, 0.058594f, 0.074219f, 0.066406f}, {0.261719f, 0.937500f, 0.968750f, 0.683594f}, + {0.160156f, 0.687500f, 0.125000f, 0.320312f}, {0.441406f, 0.781250f, 0.648438f, 0.019531f}, + {0.320312f, 0.972656f, 0.023438f, 0.710938f}, {0.937500f, 0.070312f, 0.429688f, 0.164062f}, + {0.273438f, 0.406250f, 0.886719f, 0.414062f}, {0.585938f, 0.789062f, 0.511719f, 0.804688f}, + {0.234375f, 0.574219f, 0.636719f, 0.230469f}, {0.750000f, 0.832031f, 0.460938f, 0.531250f}, + {0.355469f, 0.250000f, 0.695312f, 0.750000f}, {0.281250f, 0.480469f, 0.328125f, 0.250000f}, + {0.132812f, 0.726562f, 0.500000f, 0.035156f}, {0.671875f, 0.886719f, 0.917969f, 0.601562f}, + {0.972656f, 0.621094f, 0.664062f, 0.199219f}, {0.328125f, 0.699219f, 0.472656f, 0.789062f}, + {0.511719f, 0.519531f, 0.121094f, 0.519531f}, {0.695312f, 0.593750f, 0.699219f, 0.300781f}, + {0.351562f, 0.054688f, 0.503906f, 0.683594f}, {0.621094f, 0.757812f, 0.628906f, 0.351562f}, + {0.484375f, 0.882812f, 0.285156f, 0.808594f}, {0.660156f, 0.394531f, 0.152344f, 0.046875f}, + {0.386719f, 0.574219f, 0.992188f, 0.660156f}, {0.121094f, 0.824219f, 0.691406f, 0.738281f}, + {0.242188f, 0.234375f, 0.410156f, 0.531250f}, {0.601562f, 0.031250f, 0.171875f, 0.191406f}, + {0.773438f, 0.085938f, 0.277344f, 0.960938f}, {0.507812f, 0.839844f, 0.656250f, 0.113281f}, + {0.968750f, 0.179688f, 0.812500f, 0.023438f}, {0.566406f, 0.351562f, 0.203125f, 0.632812f}, + {0.878906f, 0.289062f, 0.515625f, 0.343750f}, {0.484375f, 0.710938f, 0.996094f, 0.121094f}, + {0.183594f, 0.957031f, 0.589844f, 0.519531f}, {0.734375f, 0.191406f, 0.187500f, 0.042969f}, + {0.804688f, 0.621094f, 0.644531f, 0.222656f}, {0.148438f, 0.269531f, 0.757812f, 0.898438f}, + {0.406250f, 0.480469f, 0.574219f, 0.664062f}, {0.109375f, 0.789062f, 0.457031f, 0.328125f}, + {0.296875f, 0.234375f, 0.718750f, 0.246094f}, {0.191406f, 0.523438f, 0.500000f, 0.570312f}, + {0.500000f, 0.449219f, 0.281250f, 0.351562f}, {0.324219f, 0.347656f, 0.218750f, 0.160156f}, + {0.953125f, 0.683594f, 0.378906f, 0.441406f}, {0.710938f, 0.539062f, 0.703125f, 0.382812f}, + {0.097656f, 0.886719f, 0.425781f, 0.003906f}, {0.347656f, 0.281250f, 0.296875f, 0.546875f}, + {0.761719f, 0.695312f, 0.554688f, 0.246094f}, {0.039062f, 0.433594f, 0.386719f, 0.078125f}, + {0.253906f, 0.230469f, 0.496094f, 0.566406f}, {0.378906f, 0.804688f, 0.058594f, 0.023438f}, + {0.449219f, 0.648438f, 0.304688f, 0.335938f}, {0.875000f, 0.199219f, 0.437500f, 0.101562f}, + {0.136719f, 0.917969f, 0.917969f, 0.476562f}, {0.285156f, 0.539062f, 0.847656f, 0.902344f}, + {0.617188f, 0.003906f, 0.703125f, 0.250000f}, {0.167969f, 0.996094f, 0.210938f, 0.953125f}, + {0.429688f, 0.437500f, 0.800781f, 0.308594f}, {0.738281f, 0.847656f, 0.265625f, 0.140625f}, + {0.847656f, 0.210938f, 0.019531f, 0.566406f}, {0.558594f, 0.929688f, 0.125000f, 0.085938f}, + {0.660156f, 0.878906f, 0.808594f, 0.363281f}, {0.179688f, 0.289062f, 0.203125f, 0.671875f}, + {0.308594f, 0.203125f, 0.851562f, 0.117188f}, {0.367188f, 0.414062f, 0.902344f, 0.746094f}, + {0.101562f, 0.621094f, 0.527344f, 0.210938f}, {0.804688f, 0.265625f, 0.332031f, 0.500000f}, + {0.914062f, 0.175781f, 0.464844f, 0.960938f}, {0.726562f, 0.535156f, 0.734375f, 0.378906f}, + {0.628906f, 0.656250f, 0.539062f, 0.628906f}, {0.074219f, 0.601562f, 0.804688f, 0.273438f}, + {0.453125f, 0.347656f, 0.109375f, 0.578125f}, {0.531250f, 0.210938f, 0.378906f, 0.867188f}, + {0.699219f, 0.683594f, 0.175781f, 0.085938f}, {0.156250f, 0.050781f, 0.832031f, 0.972656f}, + {0.492188f, 0.945312f, 0.972656f, 0.625000f}, {0.953125f, 0.382812f, 0.085938f, 0.820312f}, + {0.550781f, 0.199219f, 0.253906f, 0.417969f}, {0.246094f, 0.082031f, 0.566406f, 0.847656f}, + {0.449219f, 0.308594f, 0.070312f, 0.371094f}, {0.785156f, 0.003906f, 0.234375f, 0.132812f}, + {0.097656f, 0.984375f, 0.984375f, 0.746094f}, {0.269531f, 0.847656f, 0.187500f, 0.980469f}, + {0.871094f, 0.656250f, 0.824219f, 0.031250f}, {0.039062f, 0.296875f, 0.398438f, 0.550781f}, + {0.187500f, 0.503906f, 0.882812f, 0.917969f}, {0.992188f, 0.179688f, 0.589844f, 0.500000f}, + {0.789062f, 0.718750f, 0.363281f, 0.289062f}, {0.558594f, 0.332031f, 0.007812f, 0.980469f}, + {0.464844f, 0.531250f, 0.507812f, 0.460938f}, {0.824219f, 0.640625f, 0.902344f, 0.253906f}, + {0.203125f, 0.781250f, 0.722656f, 0.593750f}, {0.304688f, 0.687500f, 0.960938f, 0.308594f}, + {0.136719f, 0.117188f, 0.125000f, 0.707031f}, {0.839844f, 0.550781f, 0.410156f, 0.917969f}, + {0.351562f, 0.808594f, 0.769531f, 0.468750f}, {0.289062f, 0.000000f, 0.074219f, 0.863281f}, + {0.667969f, 0.582031f, 0.691406f, 0.597656f}, {0.015625f, 0.375000f, 0.117188f, 0.371094f}, + {0.578125f, 0.054688f, 0.902344f, 0.765625f}, {0.957031f, 0.882812f, 0.351562f, 0.558594f}, + {0.644531f, 0.417969f, 0.058594f, 0.128906f}, {0.847656f, 0.664062f, 0.238281f, 0.429688f}, + {0.464844f, 0.070312f, 0.171875f, 0.773438f}, {0.746094f, 0.917969f, 0.929688f, 0.855469f}, + {0.000000f, 0.109375f, 0.777344f, 0.613281f}, {0.867188f, 0.851562f, 0.660156f, 0.996094f}, + {0.609375f, 0.796875f, 0.851562f, 0.273438f}, {0.445312f, 0.222656f, 0.160156f, 0.777344f}, + {0.808594f, 0.078125f, 0.597656f, 0.199219f}, {0.277344f, 0.394531f, 0.800781f, 0.636719f}, + {0.582031f, 0.824219f, 0.753906f, 0.464844f}, {0.945312f, 0.511719f, 0.632812f, 0.851562f}, + {0.835938f, 0.316406f, 0.226562f, 0.941406f}, {0.082031f, 0.554688f, 0.863281f, 0.210938f}, + {0.546875f, 0.378906f, 0.785156f, 0.812500f}, {0.222656f, 0.468750f, 0.191406f, 0.289062f}, + {0.953125f, 0.753906f, 0.535156f, 0.843750f}, {0.484375f, 0.089844f, 0.652344f, 0.367188f}, + {0.828125f, 0.226562f, 0.089844f, 0.042969f}, {0.687500f, 0.722656f, 0.566406f, 0.746094f}, + {0.937500f, 0.640625f, 0.375000f, 0.488281f}, {0.496094f, 0.105469f, 0.675781f, 0.386719f}, + {0.113281f, 0.527344f, 0.460938f, 0.699219f}, {0.375000f, 0.453125f, 0.546875f, 0.945312f}, + {0.878906f, 0.679688f, 0.343750f, 0.511719f}, {0.070312f, 0.085938f, 0.644531f, 0.179688f}, + {0.820312f, 0.718750f, 0.480469f, 0.996094f}, {0.992188f, 0.957031f, 0.160156f, 0.390625f}, + {0.683594f, 0.121094f, 0.695312f, 0.582031f}, {0.582031f, 0.824219f, 0.242188f, 0.148438f}, + {0.203125f, 0.382812f, 0.835938f, 0.867188f}, {0.386719f, 0.042969f, 0.925781f, 0.105469f}, + {0.832031f, 0.285156f, 0.296875f, 0.792969f}, {0.152344f, 0.738281f, 0.671875f, 0.945312f}, + {0.765625f, 0.855469f, 0.234375f, 0.347656f}, {0.855469f, 0.511719f, 0.914062f, 0.734375f}, + {0.101562f, 0.917969f, 0.582031f, 0.000000f}, {0.917969f, 0.316406f, 0.019531f, 0.394531f}, + {0.804688f, 0.636719f, 0.410156f, 0.328125f}, {0.601562f, 0.765625f, 0.199219f, 0.171875f}, + {0.027344f, 0.515625f, 0.800781f, 0.949219f}, {0.761719f, 0.835938f, 0.890625f, 0.285156f}, + {0.183594f, 0.429688f, 0.734375f, 0.554688f}, {0.855469f, 0.773438f, 0.433594f, 0.925781f}, + {0.593750f, 0.222656f, 0.871094f, 0.457031f}, {0.402344f, 0.351562f, 0.351562f, 0.625000f}, + {0.917969f, 0.414062f, 0.554688f, 0.402344f}, {0.539062f, 0.136719f, 0.023438f, 0.257812f}, + {0.433594f, 0.792969f, 0.718750f, 0.757812f}, {0.082031f, 0.960938f, 0.210938f, 0.160156f}, + {0.281250f, 0.097656f, 0.789062f, 0.378906f}, {0.714844f, 0.863281f, 0.304688f, 0.859375f}, + {0.343750f, 0.433594f, 0.828125f, 0.000000f}, {0.953125f, 0.976562f, 0.226562f, 0.769531f}, + {0.042969f, 0.273438f, 0.566406f, 0.843750f}, {0.691406f, 0.402344f, 0.335938f, 0.425781f}, + {0.394531f, 0.937500f, 0.476562f, 0.550781f}, {0.613281f, 0.476562f, 0.636719f, 0.808594f}, + {0.093750f, 0.878906f, 0.890625f, 0.167969f}, {0.789062f, 0.234375f, 0.324219f, 0.066406f}, + {0.980469f, 0.511719f, 0.441406f, 0.933594f}, {0.382812f, 0.675781f, 0.796875f, 0.710938f}, + {0.500000f, 0.765625f, 0.273438f, 0.312500f}, {0.078125f, 0.125000f, 0.527344f, 0.839844f}, + {0.757812f, 0.554688f, 0.980469f, 0.187500f}, {0.246094f, 0.332031f, 0.816406f, 0.960938f}, + {0.589844f, 0.167969f, 0.421875f, 0.687500f}, {0.984375f, 0.582031f, 0.609375f, 0.074219f}, + {0.089844f, 0.746094f, 0.097656f, 0.472656f}, {0.375000f, 0.406250f, 0.046875f, 0.117188f}, + {0.238281f, 0.023438f, 0.468750f, 0.664062f}, {0.042969f, 0.570312f, 0.984375f, 0.527344f}, + {0.894531f, 0.988281f, 0.097656f, 0.917969f}, {0.679688f, 0.750000f, 0.882812f, 0.824219f}, + {0.121094f, 0.156250f, 0.015625f, 0.296875f}, {0.417969f, 0.601562f, 0.152344f, 0.675781f}, + {0.714844f, 0.062500f, 0.925781f, 0.367188f}, {0.187500f, 0.878906f, 0.679688f, 0.515625f}, + {0.789062f, 0.097656f, 0.574219f, 0.632812f}, {0.671875f, 0.683594f, 0.132812f, 0.968750f}, + {0.593750f, 0.828125f, 0.363281f, 0.695312f}, {0.332031f, 0.324219f, 0.281250f, 0.535156f}, + {0.058594f, 0.406250f, 0.957031f, 0.585938f}, {0.250000f, 0.871094f, 0.164062f, 0.800781f}, + {0.355469f, 0.574219f, 0.894531f, 0.187500f}, {0.042969f, 0.359375f, 0.070312f, 0.625000f}, + {0.207031f, 0.265625f, 0.949219f, 0.839844f}, {0.703125f, 0.031250f, 0.746094f, 0.039062f}, + {0.273438f, 0.609375f, 0.242188f, 0.246094f}, {0.601562f, 0.371094f, 0.093750f, 0.781250f}, + {0.535156f, 0.859375f, 0.765625f, 0.542969f}, {0.140625f, 0.324219f, 0.035156f, 0.292969f}, + {0.425781f, 0.476562f, 0.605469f, 0.812500f}, {0.292969f, 0.585938f, 0.417969f, 0.660156f}, + {0.023438f, 0.890625f, 0.066406f, 0.246094f}, {0.542969f, 0.445312f, 0.183594f, 0.539062f}, + {0.484375f, 0.152344f, 0.976562f, 0.027344f}, {0.226562f, 0.953125f, 0.480469f, 0.488281f}, + {0.988281f, 0.003906f, 0.054688f, 0.128906f}, {0.339844f, 0.125000f, 0.703125f, 0.648438f}, + {0.406250f, 0.265625f, 0.281250f, 0.511719f}, {0.203125f, 0.453125f, 0.746094f, 0.890625f}, + {0.308594f, 0.164062f, 0.535156f, 0.105469f}, {0.425781f, 0.023438f, 0.679688f, 0.574219f}, + {0.871094f, 0.976562f, 0.609375f, 0.718750f}, {0.371094f, 0.664062f, 0.367188f, 0.078125f}, + {0.531250f, 0.140625f, 0.160156f, 0.660156f}, {0.050781f, 0.570312f, 0.289062f, 0.007812f}, + {0.710938f, 0.488281f, 0.636719f, 0.332031f}, {0.214844f, 0.089844f, 0.773438f, 0.207031f}, + {0.132812f, 0.937500f, 0.097656f, 0.871094f}, {0.746094f, 0.554688f, 0.257812f, 0.097656f}, + {0.832031f, 0.039062f, 0.964844f, 0.601562f}, {0.597656f, 0.625000f, 0.464844f, 0.703125f}, + {0.898438f, 0.371094f, 0.539062f, 0.218750f}, {0.160156f, 0.207031f, 0.132812f, 0.574219f}, + {0.515625f, 0.050781f, 0.937500f, 0.121094f}, {0.089844f, 0.734375f, 0.449219f, 0.343750f}, + {0.640625f, 0.156250f, 0.093750f, 0.671875f}, {0.894531f, 0.578125f, 0.039062f, 0.058594f}, + {0.449219f, 0.218750f, 0.847656f, 0.226562f}, {0.753906f, 0.726562f, 0.175781f, 0.382812f}, + {0.035156f, 0.082031f, 0.261719f, 0.281250f}, {0.542969f, 0.328125f, 0.023438f, 0.652344f}, + {0.234375f, 0.910156f, 0.562500f, 0.433594f}, {0.707031f, 0.449219f, 0.855469f, 0.242188f}, + {0.312500f, 0.941406f, 0.394531f, 0.003906f}, {0.203125f, 0.218750f, 0.035156f, 0.625000f}, + {0.917969f, 0.835938f, 0.628906f, 0.492188f}, {0.363281f, 0.972656f, 0.699219f, 0.382812f}, + {0.156250f, 0.710938f, 0.125000f, 0.035156f}, {0.425781f, 0.265625f, 0.367188f, 0.535156f}, + {0.667969f, 0.875000f, 0.535156f, 0.300781f}, {0.527344f, 0.640625f, 0.742188f, 0.753906f}, + {0.769531f, 0.148438f, 0.328125f, 0.871094f}, {0.152344f, 0.484375f, 0.230469f, 0.046875f}, + {0.488281f, 0.332031f, 0.511719f, 0.339844f}, {0.214844f, 0.656250f, 0.265625f, 0.105469f}, + {0.539062f, 0.906250f, 0.363281f, 0.417969f}, {0.878906f, 0.207031f, 0.464844f, 0.167969f}, + {0.304688f, 0.957031f, 0.324219f, 0.769531f}, {0.496094f, 0.726562f, 0.039062f, 0.117188f}, + {0.980469f, 0.273438f, 0.406250f, 0.453125f}, {0.031250f, 0.167969f, 0.976562f, 0.058594f}, + {0.414062f, 0.585938f, 0.804688f, 0.156250f}, {0.117188f, 0.960938f, 0.023438f, 0.222656f}, + {0.882812f, 0.507812f, 0.449219f, 0.414062f}, {0.554688f, 0.066406f, 0.757812f, 0.113281f}, + {0.808594f, 0.175781f, 0.515625f, 0.984375f}, {0.621094f, 0.937500f, 0.304688f, 0.269531f}, + {0.769531f, 0.824219f, 0.609375f, 0.449219f}, {0.906250f, 0.750000f, 0.386719f, 0.738281f}, + {0.464844f, 0.980469f, 0.878906f, 0.335938f}, {0.000000f, 0.542969f, 0.441406f, 0.429688f}, + {0.781250f, 0.179688f, 0.984375f, 0.027344f}, {0.238281f, 0.765625f, 0.304688f, 0.914062f}, + {0.500000f, 0.011719f, 0.914062f, 0.082031f}, {0.871094f, 0.238281f, 0.792969f, 0.355469f}, + {0.750000f, 0.707031f, 0.632812f, 0.742188f}, {0.945312f, 0.796875f, 0.382812f, 0.433594f}, + {0.109375f, 0.207031f, 0.570312f, 0.316406f}, {0.707031f, 0.492188f, 0.761719f, 0.203125f}, + {0.597656f, 0.390625f, 0.328125f, 0.917969f}, {0.003906f, 0.554688f, 0.941406f, 0.261719f}, + {0.519531f, 0.777344f, 0.453125f, 0.445312f}, {0.628906f, 0.699219f, 0.144531f, 0.679688f}, + {0.066406f, 0.867188f, 0.878906f, 0.226562f}, {0.683594f, 0.589844f, 0.308594f, 0.777344f}, + {0.117188f, 0.246094f, 0.464844f, 0.437500f}, {0.933594f, 0.339844f, 0.027344f, 0.488281f}, + {0.632812f, 0.917969f, 0.925781f, 0.234375f}, {0.320312f, 0.273438f, 0.535156f, 0.886719f}, + {0.980469f, 0.816406f, 0.050781f, 0.734375f}, {0.476562f, 0.734375f, 0.488281f, 0.152344f}, + {0.648438f, 0.187500f, 0.687500f, 0.824219f}, {0.308594f, 0.875000f, 0.847656f, 0.460938f}, + {0.367188f, 0.695312f, 0.417969f, 0.949219f}, {0.234375f, 0.281250f, 0.097656f, 0.035156f}, + {0.007812f, 0.468750f, 0.667969f, 0.421875f}, {0.664062f, 0.921875f, 0.753906f, 0.914062f}, + {0.863281f, 0.597656f, 0.605469f, 0.718750f}, {0.378906f, 0.320312f, 0.386719f, 0.476562f}, + {0.273438f, 0.492188f, 0.683594f, 0.953125f}, {0.550781f, 0.851562f, 0.781250f, 0.144531f}, + {0.167969f, 0.027344f, 0.593750f, 0.613281f}, {0.250000f, 0.367188f, 0.925781f, 0.976562f}, + {0.941406f, 0.656250f, 0.511719f, 0.746094f}, {0.468750f, 0.757812f, 0.675781f, 0.531250f}, + {0.156250f, 0.140625f, 0.953125f, 0.132812f}, {0.890625f, 0.269531f, 0.164062f, 0.792969f}, + {0.820312f, 0.074219f, 0.734375f, 0.988281f}, {0.449219f, 0.605469f, 0.476562f, 0.105469f}, + {0.546875f, 0.503906f, 0.210938f, 0.738281f}, {0.058594f, 0.019531f, 0.320312f, 0.277344f}, + {0.875000f, 0.390625f, 0.867188f, 0.914062f}, {0.718750f, 0.468750f, 0.261719f, 0.808594f}, + {0.281250f, 0.207031f, 0.953125f, 0.175781f}, {0.832031f, 0.312500f, 0.835938f, 0.402344f}, + {0.914062f, 0.945312f, 0.640625f, 0.230469f}, {0.316406f, 0.816406f, 0.402344f, 0.457031f}, + {0.648438f, 0.257812f, 0.730469f, 0.593750f}, {0.976562f, 0.441406f, 0.667969f, 0.730469f}, + {0.363281f, 0.011719f, 0.957031f, 0.984375f}, {0.015625f, 0.363281f, 0.820312f, 0.019531f}, + {0.636719f, 0.476562f, 0.531250f, 0.574219f}, {0.144531f, 0.632812f, 0.734375f, 0.878906f}, + {0.355469f, 0.421875f, 0.253906f, 0.269531f}, {0.269531f, 0.929688f, 0.484375f, 0.730469f}, + {0.773438f, 0.027344f, 0.621094f, 0.339844f}, {0.921875f, 0.253906f, 0.707031f, 0.925781f}, + {0.722656f, 0.660156f, 0.328125f, 0.867188f}, {0.453125f, 0.777344f, 0.839844f, 0.679688f}, + {0.156250f, 0.292969f, 0.234375f, 0.324219f}, {0.988281f, 0.699219f, 0.128906f, 0.062500f}, + {0.523438f, 0.402344f, 0.820312f, 0.898438f}, {0.128906f, 0.140625f, 0.183594f, 0.160156f}, + {0.394531f, 0.238281f, 0.050781f, 0.597656f}, {0.964844f, 0.062500f, 0.660156f, 0.855469f}, + {0.339844f, 0.429688f, 0.558594f, 0.707031f}, {0.722656f, 0.648438f, 0.363281f, 0.628906f}, + {0.921875f, 0.515625f, 0.207031f, 0.460938f}, {0.054688f, 0.988281f, 0.503906f, 0.878906f}, + {0.652344f, 0.089844f, 0.718750f, 0.179688f}, {0.351562f, 0.339844f, 0.140625f, 0.980469f}, + {0.800781f, 0.902344f, 0.085938f, 0.679688f}, {0.429688f, 0.679688f, 0.859375f, 0.765625f}, + {0.296875f, 0.820312f, 0.195312f, 0.546875f}, {0.675781f, 0.613281f, 0.621094f, 0.839844f}, + {0.882812f, 0.933594f, 0.816406f, 0.167969f}, {0.769531f, 0.070312f, 0.363281f, 0.812500f}, + {0.964844f, 0.367188f, 0.062500f, 0.937500f}, {0.480469f, 0.421875f, 0.988281f, 0.351562f}, + {0.226562f, 0.113281f, 0.121094f, 0.144531f}, {0.277344f, 0.726562f, 0.828125f, 0.992188f}, + {0.742188f, 0.464844f, 0.695312f, 0.804688f}, {0.152344f, 0.058594f, 0.398438f, 0.382812f}, + {0.421875f, 0.675781f, 0.960938f, 0.574219f}, {0.792969f, 0.601562f, 0.144531f, 0.511719f}, + {0.031250f, 0.320312f, 0.332031f, 0.648438f}, {0.933594f, 0.441406f, 0.578125f, 0.292969f}, + {0.703125f, 0.230469f, 0.179688f, 0.789062f}, {0.492188f, 0.773438f, 0.925781f, 0.527344f}, + {0.960938f, 0.535156f, 0.339844f, 0.324219f}, {0.425781f, 0.671875f, 0.035156f, 0.820312f}, + {0.734375f, 0.804688f, 0.257812f, 0.628906f}, {0.207031f, 0.113281f, 0.164062f, 0.187500f}, + {0.808594f, 0.902344f, 0.984375f, 0.289062f}, {0.988281f, 0.636719f, 0.300781f, 0.886719f}, + {0.707031f, 0.441406f, 0.214844f, 0.507812f}, {0.328125f, 0.968750f, 0.371094f, 0.015625f}, + {0.859375f, 0.183594f, 0.742188f, 0.839844f}, {0.656250f, 0.570312f, 0.121094f, 0.332031f}, + {0.398438f, 0.414062f, 0.343750f, 0.882812f}, {0.113281f, 0.816406f, 0.234375f, 0.476562f}, + {0.613281f, 0.703125f, 0.656250f, 0.398438f}, {0.027344f, 0.359375f, 0.093750f, 0.550781f}, + {0.683594f, 0.292969f, 0.789062f, 0.855469f}, {0.785156f, 0.804688f, 0.917969f, 0.214844f}, + {0.328125f, 0.910156f, 0.574219f, 0.617188f}, {0.621094f, 0.085938f, 0.007812f, 0.359375f}, + {0.199219f, 0.687500f, 0.445312f, 0.964844f}, {0.117188f, 0.519531f, 0.183594f, 0.699219f}, + {0.574219f, 0.066406f, 0.121094f, 0.628906f}, {0.394531f, 0.605469f, 0.914062f, 0.945312f}, + {0.730469f, 0.718750f, 0.574219f, 0.144531f}, {0.078125f, 0.105469f, 0.066406f, 0.265625f}, + {0.800781f, 0.546875f, 0.191406f, 0.523438f}, {0.460938f, 0.792969f, 0.609375f, 0.703125f}, + {0.746094f, 0.847656f, 0.101562f, 0.218750f}, {0.582031f, 0.125000f, 0.914062f, 0.945312f}, + {0.859375f, 0.335938f, 0.851562f, 0.402344f}, {0.695312f, 0.535156f, 0.070312f, 0.785156f}, + {0.523438f, 0.792969f, 0.207031f, 0.593750f}, {0.210938f, 0.445312f, 0.886719f, 0.464844f}, + {0.628906f, 0.132812f, 0.582031f, 0.000000f}, {0.285156f, 0.902344f, 0.054688f, 0.515625f}, + {0.019531f, 0.472656f, 0.648438f, 0.773438f}, {0.410156f, 0.011719f, 0.414062f, 0.558594f}, + {0.312500f, 0.632812f, 0.699219f, 0.652344f}, {0.230469f, 0.500000f, 0.527344f, 0.500000f}, + {0.656250f, 0.789062f, 0.921875f, 0.109375f}, {0.843750f, 0.308594f, 0.265625f, 0.960938f}, + {0.183594f, 0.835938f, 0.734375f, 0.218750f}, {0.632812f, 0.925781f, 0.109375f, 0.140625f}, + {0.093750f, 0.136719f, 0.847656f, 0.269531f}, {0.394531f, 0.371094f, 0.011719f, 0.523438f}, + {0.191406f, 0.625000f, 0.273438f, 0.046875f}, {0.269531f, 0.566406f, 0.894531f, 0.593750f}, + {0.574219f, 0.035156f, 0.359375f, 0.906250f}, {0.164062f, 0.300781f, 0.523438f, 0.085938f}, + {0.925781f, 0.101562f, 0.425781f, 0.359375f}, {0.089844f, 0.230469f, 0.003906f, 0.054688f}, + {0.257812f, 0.332031f, 0.550781f, 0.589844f}, {0.378906f, 0.187500f, 0.242188f, 0.300781f}, + {0.167969f, 0.531250f, 0.785156f, 0.023438f}, {0.722656f, 0.824219f, 0.640625f, 0.628906f}, + {0.578125f, 0.898438f, 0.519531f, 0.546875f}, {0.835938f, 0.621094f, 0.257812f, 0.054688f}, + {0.503906f, 0.175781f, 0.195312f, 0.691406f}, {0.074219f, 0.394531f, 0.601562f, 0.304688f}, + {0.882812f, 0.953125f, 0.796875f, 0.085938f}, {0.574219f, 0.015625f, 0.230469f, 0.968750f}, + {0.273438f, 0.515625f, 0.886719f, 0.050781f}, {0.113281f, 0.828125f, 0.742188f, 0.367188f}, + {0.816406f, 0.101562f, 0.281250f, 0.183594f}, {0.187500f, 0.968750f, 0.625000f, 0.671875f}, + {0.562500f, 0.003906f, 0.796875f, 0.113281f}, {0.320312f, 0.164062f, 0.898438f, 0.257812f}, + {0.128906f, 0.257812f, 0.503906f, 0.062500f}, {0.593750f, 0.390625f, 0.843750f, 0.542969f}, + {0.472656f, 0.757812f, 0.726562f, 0.402344f}, {0.023438f, 0.062500f, 0.539062f, 0.792969f}, + {0.113281f, 0.296875f, 0.425781f, 0.722656f}, {0.523438f, 0.808594f, 0.054688f, 0.449219f}, + {0.800781f, 0.515625f, 0.816406f, 0.093750f}, {0.054688f, 0.867188f, 0.460938f, 0.207031f}, + {0.566406f, 0.019531f, 0.605469f, 0.582031f}, {0.742188f, 0.992188f, 0.882812f, 0.671875f}, + {0.265625f, 0.472656f, 0.546875f, 0.171875f}, {0.992188f, 0.171875f, 0.964844f, 0.316406f}, + {0.406250f, 0.746094f, 0.429688f, 0.695312f}, {0.132812f, 0.628906f, 0.160156f, 0.453125f}, + {0.488281f, 0.140625f, 0.507812f, 0.136719f}, {0.937500f, 0.562500f, 0.679688f, 0.566406f}, + {0.019531f, 0.789062f, 0.769531f, 0.085938f}, {0.464844f, 0.898438f, 0.597656f, 0.492188f}, + {0.957031f, 0.378906f, 0.304688f, 0.011719f}, {0.050781f, 0.179688f, 0.027344f, 0.765625f}, + {0.261719f, 0.859375f, 0.875000f, 0.375000f}, {0.609375f, 0.964844f, 0.437500f, 0.812500f}, + {0.175781f, 0.296875f, 0.781250f, 0.894531f}, {0.929688f, 0.691406f, 0.289062f, 0.468750f}, + {0.238281f, 0.234375f, 0.382812f, 0.347656f}, {0.093750f, 0.054688f, 0.160156f, 0.652344f}, + {0.914062f, 0.750000f, 0.656250f, 0.035156f}, {0.445312f, 0.863281f, 0.320312f, 0.187500f}, + {0.167969f, 0.199219f, 0.519531f, 0.828125f}, {0.070312f, 0.703125f, 0.117188f, 0.644531f}, + {0.371094f, 0.382812f, 0.386719f, 0.289062f}, {0.949219f, 0.601562f, 0.917969f, 0.144531f}, + {0.675781f, 0.218750f, 0.476562f, 0.394531f}, {0.867188f, 0.550781f, 0.988281f, 0.933594f}, + {0.585938f, 0.960938f, 0.003906f, 0.199219f}, {0.753906f, 0.339844f, 0.328125f, 0.371094f}, + {0.078125f, 0.914062f, 0.773438f, 0.796875f}, {0.542969f, 0.593750f, 0.488281f, 0.308594f}, + {0.449219f, 0.683594f, 0.148438f, 0.558594f}, {0.289062f, 0.218750f, 0.406250f, 0.402344f}, + {0.582031f, 0.281250f, 0.589844f, 0.929688f}, {0.828125f, 0.734375f, 0.941406f, 0.714844f}, + {0.460938f, 0.867188f, 0.449219f, 0.832031f}, {0.960938f, 0.453125f, 0.660156f, 0.398438f}, + {0.027344f, 0.757812f, 0.234375f, 0.230469f}, {0.742188f, 0.972656f, 0.730469f, 0.468750f}, + {0.488281f, 0.429688f, 0.128906f, 0.640625f}, {0.839844f, 0.722656f, 0.968750f, 0.960938f}, + {0.558594f, 0.484375f, 0.664062f, 0.742188f}, {0.039062f, 0.964844f, 0.894531f, 0.390625f}, + {0.812500f, 0.753906f, 0.183594f, 0.503906f}, {0.335938f, 0.281250f, 0.417969f, 0.757812f}, + {0.441406f, 0.035156f, 0.726562f, 0.878906f}, {0.019531f, 0.496094f, 0.347656f, 0.269531f}, + {0.921875f, 0.777344f, 0.867188f, 0.175781f}, {0.679688f, 0.859375f, 0.074219f, 0.605469f}, + {0.355469f, 0.242188f, 0.449219f, 0.433594f}, {0.175781f, 0.363281f, 0.656250f, 0.765625f}, + {0.515625f, 0.898438f, 0.003906f, 0.246094f}, {0.613281f, 0.152344f, 0.468750f, 0.894531f}, + {0.386719f, 0.402344f, 0.523438f, 0.566406f}, {0.066406f, 0.613281f, 0.062500f, 0.988281f}, + {0.765625f, 0.347656f, 0.390625f, 0.449219f}, {0.851562f, 0.843750f, 0.203125f, 0.875000f}, + {0.054688f, 0.445312f, 0.441406f, 0.750000f}, {0.929688f, 0.992188f, 0.644531f, 0.937500f}, + {0.769531f, 0.554688f, 0.000000f, 0.597656f}, {0.632812f, 0.234375f, 0.132812f, 0.101562f}, + {0.367188f, 0.691406f, 0.867188f, 0.347656f}, {0.425781f, 0.125000f, 0.632812f, 0.261719f}, + {0.183594f, 0.613281f, 0.968750f, 0.691406f}, {0.285156f, 0.250000f, 0.078125f, 0.929688f}, + {0.917969f, 0.320312f, 0.292969f, 0.039062f}, {0.347656f, 0.644531f, 0.800781f, 0.269531f}, + {0.851562f, 0.539062f, 0.019531f, 0.945312f}, {0.515625f, 0.882812f, 0.359375f, 0.070312f}, + {0.218750f, 0.050781f, 0.277344f, 0.886719f}, {0.898438f, 0.242188f, 0.714844f, 0.019531f}, + {0.558594f, 0.441406f, 0.062500f, 0.773438f}, {0.250000f, 0.964844f, 0.390625f, 0.902344f}, + {0.820312f, 0.343750f, 0.226562f, 0.265625f}, {0.343750f, 0.003906f, 0.972656f, 0.832031f}, + {0.757812f, 0.753906f, 0.484375f, 0.316406f}, {0.507812f, 0.234375f, 0.808594f, 0.554688f}, + {0.859375f, 0.410156f, 0.347656f, 0.203125f}, {0.425781f, 0.503906f, 0.140625f, 0.062500f}, + {0.687500f, 0.140625f, 0.496094f, 0.601562f}, {0.292969f, 0.582031f, 0.996094f, 0.093750f}, + {0.828125f, 0.386719f, 0.707031f, 0.300781f}, {0.398438f, 0.980469f, 0.578125f, 0.859375f}, + {0.042969f, 0.496094f, 0.441406f, 0.500000f}, {0.320312f, 0.609375f, 0.777344f, 0.550781f}, + {0.601562f, 0.304688f, 0.945312f, 0.089844f}, {0.851562f, 0.093750f, 0.269531f, 0.234375f}, + {0.492188f, 0.988281f, 0.753906f, 0.953125f}, {0.792969f, 0.332031f, 0.175781f, 0.847656f}, + {0.089844f, 0.843750f, 0.726562f, 0.710938f}, {0.183594f, 0.082031f, 0.277344f, 0.246094f}, + {0.476562f, 0.714844f, 0.566406f, 0.039062f}, {0.925781f, 0.187500f, 0.835938f, 0.878906f}, + {0.035156f, 0.109375f, 0.214844f, 0.691406f}, {0.695312f, 0.464844f, 0.621094f, 0.007812f}, + {0.949219f, 0.023438f, 0.968750f, 0.472656f}, {0.136719f, 0.558594f, 0.800781f, 0.769531f}, + {0.773438f, 0.410156f, 0.679688f, 0.066406f}, {0.519531f, 0.816406f, 0.320312f, 0.644531f}, + {0.683594f, 0.066406f, 0.171875f, 0.296875f}, {0.867188f, 0.253906f, 0.820312f, 0.125000f}, + {0.386719f, 0.523438f, 0.054688f, 0.562500f}, {0.332031f, 0.156250f, 0.601562f, 0.863281f}, + {0.648438f, 0.851562f, 0.796875f, 0.281250f}, {0.214844f, 0.644531f, 0.269531f, 0.425781f}, + {0.417969f, 0.023438f, 0.390625f, 0.140625f}, {0.917969f, 0.132812f, 0.082031f, 0.902344f}, + {0.617188f, 0.664062f, 0.496094f, 0.093750f}, {0.101562f, 0.578125f, 0.589844f, 0.207031f}, + {0.996094f, 0.222656f, 0.015625f, 0.414062f}, {0.199219f, 0.996094f, 0.949219f, 0.824219f}, + {0.398438f, 0.316406f, 0.757812f, 0.480469f}, {0.605469f, 0.550781f, 0.562500f, 0.929688f}, + {0.246094f, 0.085938f, 0.300781f, 0.855469f}, {0.832031f, 0.648438f, 0.363281f, 0.128906f}, + {0.914062f, 0.757812f, 0.914062f, 0.699219f}, {0.691406f, 0.566406f, 0.828125f, 0.410156f}, + {0.980469f, 0.292969f, 0.121094f, 0.007812f}, {0.457031f, 0.742188f, 0.949219f, 0.730469f}, + {0.648438f, 0.914062f, 0.714844f, 0.148438f}, {0.257812f, 0.511719f, 0.566406f, 0.503906f}, + {0.527344f, 0.082031f, 0.105469f, 0.375000f}, {0.398438f, 0.707031f, 0.285156f, 0.019531f}, + {0.300781f, 0.183594f, 0.359375f, 0.230469f}, {0.222656f, 0.355469f, 0.933594f, 0.867188f}, + {0.867188f, 0.500000f, 0.476562f, 0.167969f}, {0.964844f, 0.945312f, 0.257812f, 0.636719f}, + {0.683594f, 0.386719f, 0.171875f, 0.535156f}, {0.601562f, 0.074219f, 0.710938f, 0.781250f}, + {0.484375f, 0.785156f, 0.414062f, 0.359375f}, {0.074219f, 0.214844f, 0.503906f, 0.742188f}, + {0.167969f, 0.113281f, 0.144531f, 0.609375f}, {0.640625f, 0.378906f, 0.746094f, 0.800781f}, + {0.304688f, 0.949219f, 0.851562f, 0.507812f}, {0.750000f, 0.507812f, 0.613281f, 0.339844f}, + {0.082031f, 0.671875f, 0.894531f, 0.656250f}, {0.660156f, 0.195312f, 0.324219f, 0.410156f}, + {0.414062f, 0.281250f, 0.824219f, 0.722656f}, {0.703125f, 0.640625f, 0.085938f, 0.167969f}, + {0.597656f, 0.464844f, 0.718750f, 0.437500f}, {0.140625f, 0.578125f, 0.253906f, 0.863281f}, + {0.207031f, 0.667969f, 0.546875f, 0.921875f}, {0.968750f, 0.042969f, 0.679688f, 0.667969f}, + {0.531250f, 0.875000f, 0.218750f, 0.410156f}, {0.117188f, 0.761719f, 0.000000f, 0.164062f}, + {0.488281f, 0.179688f, 0.894531f, 0.800781f}, {0.562500f, 0.660156f, 0.238281f, 0.722656f}, + {0.789062f, 0.265625f, 0.050781f, 0.125000f}, {0.664062f, 0.007812f, 0.835938f, 0.992188f}, + {0.996094f, 0.894531f, 0.410156f, 0.375000f}, {0.753906f, 0.566406f, 0.636719f, 0.757812f}, + {0.234375f, 0.804688f, 0.550781f, 0.437500f}, {0.562500f, 0.046875f, 0.082031f, 0.074219f}, + {0.343750f, 0.757812f, 0.359375f, 0.597656f}, {0.726562f, 0.429688f, 0.863281f, 0.480469f}, + {0.257812f, 0.875000f, 0.136719f, 0.753906f}, {0.816406f, 0.261719f, 0.437500f, 0.429688f}, + {0.332031f, 0.390625f, 0.089844f, 0.273438f}, {0.382812f, 0.742188f, 0.351562f, 0.621094f}, + {0.222656f, 0.890625f, 0.027344f, 0.839844f}, {0.890625f, 0.093750f, 0.246094f, 0.988281f}, + {0.011719f, 0.968750f, 0.539062f, 0.203125f}, {0.316406f, 0.484375f, 0.074219f, 0.363281f}, + {0.238281f, 0.187500f, 0.500000f, 0.496094f}, {0.105469f, 0.660156f, 0.996094f, 0.796875f}, + {0.777344f, 0.386719f, 0.414062f, 0.167969f}, {0.531250f, 0.589844f, 0.308594f, 0.730469f}, + {0.976562f, 0.347656f, 0.871094f, 0.027344f}, {0.125000f, 0.261719f, 0.468750f, 0.691406f}, + {0.710938f, 0.910156f, 0.703125f, 0.531250f}, {0.468750f, 0.812500f, 0.328125f, 0.250000f}, + {0.277344f, 0.441406f, 0.765625f, 0.667969f}, {0.535156f, 0.375000f, 0.917969f, 0.972656f}, + {0.648438f, 0.074219f, 0.292969f, 0.324219f}, {0.785156f, 0.687500f, 0.156250f, 0.710938f}, + {0.304688f, 0.136719f, 0.484375f, 0.011719f}, {0.089844f, 0.714844f, 0.113281f, 0.652344f}, + {0.769531f, 0.453125f, 0.992188f, 0.214844f}, {0.437500f, 0.199219f, 0.703125f, 0.328125f}, + {0.003906f, 0.980469f, 0.171875f, 0.488281f}, {0.300781f, 0.476562f, 0.410156f, 0.621094f}, + {0.218750f, 0.695312f, 0.218750f, 0.843750f}, {0.140625f, 0.058594f, 0.652344f, 0.222656f}, + {0.347656f, 0.199219f, 0.320312f, 0.335938f}, {0.945312f, 0.652344f, 0.863281f, 0.652344f}, + {0.703125f, 0.312500f, 0.976562f, 0.808594f}, {0.171875f, 0.585938f, 0.753906f, 0.292969f}, + {0.906250f, 0.863281f, 0.808594f, 0.683594f}, {0.082031f, 0.781250f, 0.582031f, 0.488281f}, + {0.562500f, 0.007812f, 0.691406f, 0.988281f}, {0.734375f, 0.886719f, 0.332031f, 0.406250f}, + {0.000000f, 0.730469f, 0.550781f, 0.894531f}, {0.234375f, 0.460938f, 0.894531f, 0.117188f}, + {0.761719f, 0.929688f, 0.207031f, 0.492188f}, {0.957031f, 0.683594f, 0.933594f, 0.441406f}, + {0.386719f, 0.828125f, 0.644531f, 0.152344f}, {0.718750f, 0.593750f, 0.246094f, 0.394531f}, + {0.011719f, 0.308594f, 0.484375f, 0.242188f}, {0.839844f, 0.851562f, 0.113281f, 0.972656f}, + {0.359375f, 0.765625f, 0.195312f, 0.199219f}, {0.957031f, 0.406250f, 0.933594f, 0.531250f}, + {0.175781f, 0.117188f, 0.535156f, 0.054688f}, {0.039062f, 0.863281f, 0.648438f, 0.992188f}, + {0.285156f, 0.996094f, 0.152344f, 0.648438f}, {0.898438f, 0.074219f, 0.410156f, 0.117188f}, + {0.375000f, 0.808594f, 0.929688f, 0.507812f}, {0.777344f, 0.347656f, 0.761719f, 0.277344f}, + {0.007812f, 0.937500f, 0.617188f, 0.757812f}, {0.339844f, 0.433594f, 0.816406f, 0.972656f}, + {0.718750f, 0.085938f, 0.328125f, 0.621094f}, {0.957031f, 0.921875f, 0.542969f, 0.250000f}, + {0.214844f, 0.460938f, 0.132812f, 0.421875f}, {0.128906f, 0.734375f, 0.691406f, 0.882812f}, + {0.277344f, 0.398438f, 0.195312f, 0.312500f}, {0.011719f, 0.179688f, 0.011719f, 0.667969f}, + {0.406250f, 0.476562f, 0.960938f, 0.566406f}, {0.140625f, 0.644531f, 0.796875f, 0.175781f}, + {0.898438f, 0.277344f, 0.222656f, 0.343750f}, {0.433594f, 0.156250f, 0.675781f, 0.980469f}, + {0.613281f, 0.664062f, 0.601562f, 0.125000f}, {0.117188f, 0.539062f, 0.953125f, 0.546875f}, + {0.511719f, 0.820312f, 0.722656f, 0.914062f}, {0.859375f, 0.625000f, 0.902344f, 0.156250f}, + {0.593750f, 0.355469f, 0.464844f, 0.332031f}, {0.421875f, 0.167969f, 0.871094f, 0.101562f}, + {0.730469f, 0.707031f, 0.714844f, 0.582031f}, {0.996094f, 0.613281f, 0.375000f, 0.746094f}, + {0.156250f, 0.328125f, 0.769531f, 0.039062f}, {0.625000f, 0.929688f, 0.628906f, 0.949219f}, + {0.449219f, 0.113281f, 0.910156f, 0.625000f}, {0.257812f, 0.800781f, 0.562500f, 0.339844f}, + {0.046875f, 0.054688f, 0.031250f, 0.996094f}, {0.792969f, 0.496094f, 0.160156f, 0.195312f}, + {0.324219f, 0.562500f, 0.929688f, 0.847656f}, {0.175781f, 0.203125f, 0.210938f, 0.789062f}, + {0.863281f, 0.304688f, 0.847656f, 0.468750f}, {0.746094f, 0.925781f, 0.070312f, 0.609375f}, + {0.136719f, 0.843750f, 0.675781f, 0.156250f}, {0.886719f, 0.605469f, 0.390625f, 0.562500f}, + {0.519531f, 0.414062f, 0.636719f, 0.113281f}, {0.710938f, 0.910156f, 0.214844f, 0.375000f}, + {0.964844f, 0.808594f, 0.785156f, 0.531250f}, {0.128906f, 0.281250f, 0.066406f, 0.957031f}, + {0.488281f, 0.031250f, 0.609375f, 0.816406f}, {0.750000f, 0.128906f, 0.542969f, 0.101562f}, + {0.550781f, 0.878906f, 0.757812f, 0.281250f}, {0.886719f, 0.250000f, 0.261719f, 0.917969f}, + {0.808594f, 0.417969f, 0.476562f, 0.585938f}, {0.585938f, 0.812500f, 0.156250f, 0.085938f}, + {0.011719f, 0.027344f, 0.042969f, 0.968750f}, {0.445312f, 0.941406f, 0.515625f, 0.429688f}, + {0.671875f, 0.136719f, 0.179688f, 0.136719f}, {0.812500f, 0.640625f, 0.230469f, 0.832031f}, + {0.480469f, 0.433594f, 0.070312f, 0.562500f}, {0.144531f, 0.281250f, 0.789062f, 0.031250f}, + {0.320312f, 0.179688f, 0.023438f, 0.304688f}, {0.886719f, 0.558594f, 0.757812f, 0.234375f}, + {0.445312f, 0.347656f, 0.371094f, 0.968750f}, {0.121094f, 0.039062f, 0.585938f, 0.863281f}, + {0.816406f, 0.421875f, 0.054688f, 0.648438f}, {0.578125f, 0.160156f, 0.992188f, 0.089844f}, + {0.429688f, 0.722656f, 0.402344f, 0.574219f}, {0.148438f, 0.097656f, 0.562500f, 0.835938f}, + {0.613281f, 0.035156f, 0.785156f, 0.117188f}, {0.468750f, 0.605469f, 0.449219f, 0.296875f}, + {0.851562f, 0.800781f, 0.035156f, 0.609375f}, {0.535156f, 0.523438f, 0.367188f, 0.789062f}, + {0.796875f, 0.152344f, 0.863281f, 0.238281f}, {0.667969f, 0.300781f, 0.585938f, 0.343750f}, + {0.074219f, 0.722656f, 0.042969f, 0.714844f}, {0.574219f, 0.199219f, 0.300781f, 0.039062f}, + {0.648438f, 0.269531f, 0.089844f, 0.464844f}, {0.847656f, 0.621094f, 0.402344f, 0.367188f}, + {0.164062f, 0.527344f, 0.457031f, 0.003906f}, {0.617188f, 0.328125f, 0.742188f, 0.566406f}, + {0.367188f, 0.835938f, 0.972656f, 0.195312f}, {0.468750f, 0.136719f, 0.351562f, 0.695312f}, + {0.542969f, 0.679688f, 0.496094f, 0.480469f}, {0.695312f, 0.941406f, 0.855469f, 0.046875f}, + {0.933594f, 0.234375f, 0.312500f, 0.902344f}, {0.640625f, 0.527344f, 0.429688f, 0.804688f}, + {0.832031f, 0.375000f, 0.500000f, 0.640625f}, {0.046875f, 0.949219f, 0.066406f, 0.292969f}, + {0.984375f, 0.460938f, 0.390625f, 0.824219f}, {0.675781f, 0.066406f, 0.179688f, 0.058594f}, + {0.175781f, 0.992188f, 0.531250f, 0.664062f}, {0.785156f, 0.230469f, 0.660156f, 0.511719f}, + {0.089844f, 0.792969f, 0.300781f, 0.242188f}, {0.652344f, 0.292969f, 0.121094f, 0.699219f}, + {0.480469f, 0.535156f, 0.195312f, 0.433594f}, {0.363281f, 0.777344f, 0.933594f, 0.894531f}, + {0.550781f, 0.011719f, 0.273438f, 0.265625f}, {0.886719f, 0.871094f, 0.144531f, 0.410156f}, + {0.937500f, 0.679688f, 0.699219f, 0.515625f}, {0.183594f, 0.214844f, 0.218750f, 0.097656f}, + {0.855469f, 0.988281f, 0.777344f, 0.457031f}, {0.566406f, 0.761719f, 0.519531f, 0.593750f}, + {0.664062f, 0.394531f, 0.593750f, 0.308594f}, {0.960938f, 0.695312f, 0.113281f, 0.070312f}, + {0.007812f, 0.101562f, 0.425781f, 0.359375f}, {0.242188f, 0.742188f, 0.546875f, 0.042969f}, + {0.355469f, 0.480469f, 0.250000f, 0.921875f}, {0.433594f, 0.187500f, 0.828125f, 0.859375f}, + {0.035156f, 0.000000f, 0.894531f, 0.789062f}, {0.218750f, 0.343750f, 0.535156f, 0.285156f}, + {0.558594f, 0.523438f, 0.433594f, 0.734375f}, {0.371094f, 0.625000f, 0.273438f, 0.031250f}, + {0.652344f, 0.835938f, 0.875000f, 0.171875f}, {0.851562f, 0.375000f, 0.332031f, 0.550781f}, + {0.062500f, 0.605469f, 0.968750f, 0.371094f}, {0.417969f, 0.539062f, 0.031250f, 0.460938f}, + {0.097656f, 0.957031f, 0.820312f, 0.761719f}, {0.500000f, 0.750000f, 0.601562f, 0.191406f}, + {0.242188f, 0.472656f, 0.371094f, 0.535156f}, {0.757812f, 0.269531f, 0.660156f, 0.625000f}, + {0.343750f, 0.394531f, 0.453125f, 0.730469f}, {0.613281f, 0.535156f, 0.914062f, 0.332031f}, + {0.265625f, 0.085938f, 0.410156f, 0.097656f}, {0.410156f, 0.835938f, 0.980469f, 0.757812f}, + {0.832031f, 0.664062f, 0.484375f, 0.812500f}, {0.644531f, 0.128906f, 0.664062f, 0.593750f}, + {0.546875f, 0.761719f, 0.109375f, 0.191406f}, {0.207031f, 0.503906f, 0.304688f, 0.007812f}, + {0.667969f, 0.898438f, 0.812500f, 0.300781f}, {0.253906f, 0.230469f, 0.687500f, 0.921875f}, + {0.976562f, 0.468750f, 0.339844f, 0.687500f}, {0.519531f, 0.554688f, 0.003906f, 0.468750f}, + {0.769531f, 0.359375f, 0.632812f, 0.746094f}, {0.230469f, 0.929688f, 0.289062f, 0.933594f}, + {0.109375f, 0.695312f, 0.691406f, 0.367188f}, {0.328125f, 0.242188f, 0.246094f, 0.484375f}, + {0.984375f, 0.429688f, 0.984375f, 0.082031f}, {0.242188f, 0.910156f, 0.464844f, 0.582031f}, + {0.480469f, 0.488281f, 0.199219f, 0.957031f}, {0.300781f, 0.558594f, 0.835938f, 0.816406f}, + {0.437500f, 0.023438f, 0.957031f, 0.214844f}, {0.933594f, 0.687500f, 0.527344f, 0.859375f}, + {0.269531f, 0.800781f, 0.179688f, 0.511719f}, {0.039062f, 0.222656f, 0.871094f, 0.921875f}, + {0.894531f, 0.062500f, 0.628906f, 0.074219f}, {0.746094f, 0.546875f, 0.277344f, 0.820312f}, + {0.863281f, 0.343750f, 0.589844f, 0.265625f}, {0.335938f, 0.855469f, 0.105469f, 0.140625f}, + {0.078125f, 0.109375f, 0.707031f, 0.515625f}, {0.515625f, 0.722656f, 0.617188f, 0.226562f}, + {0.292969f, 0.886719f, 0.878906f, 0.027344f}, {0.214844f, 0.003906f, 0.937500f, 0.699219f}, + {0.554688f, 0.601562f, 0.757812f, 0.402344f}, {0.390625f, 0.324219f, 0.281250f, 0.207031f}, + {0.304688f, 0.128906f, 0.039062f, 0.957031f}, {0.960938f, 0.500000f, 0.808594f, 0.367188f}, + {0.265625f, 0.031250f, 0.406250f, 0.808594f}, {0.054688f, 0.925781f, 0.613281f, 0.871094f}, + {0.195312f, 0.429688f, 0.558594f, 0.539062f}, {0.835938f, 0.136719f, 0.828125f, 0.121094f}, + {0.699219f, 0.242188f, 0.015625f, 0.660156f}, {0.035156f, 0.464844f, 0.480469f, 0.835938f}, + {0.312500f, 0.554688f, 0.320312f, 0.003906f}, {0.738281f, 0.308594f, 0.093750f, 0.785156f}, + {0.484375f, 0.621094f, 0.406250f, 0.890625f}, {0.375000f, 0.160156f, 0.957031f, 0.386719f}, + {0.093750f, 0.882812f, 0.355469f, 0.125000f}, {0.410156f, 0.015625f, 0.644531f, 0.941406f}, + {0.593750f, 0.597656f, 0.722656f, 0.542969f}, {0.492188f, 0.531250f, 0.984375f, 0.734375f}, + {0.683594f, 0.265625f, 0.464844f, 0.398438f}, {0.835938f, 0.968750f, 0.035156f, 0.242188f}, + {0.945312f, 0.761719f, 0.328125f, 0.453125f}, {0.625000f, 0.246094f, 0.730469f, 0.910156f}, + {0.328125f, 0.078125f, 0.937500f, 0.593750f}, {0.902344f, 0.945312f, 0.015625f, 0.425781f}, + {0.171875f, 0.433594f, 0.488281f, 0.687500f}, {0.250000f, 0.312500f, 0.804688f, 0.781250f}, + {0.609375f, 0.781250f, 0.093750f, 0.941406f}, {0.312500f, 0.097656f, 0.687500f, 0.667969f}, + {0.710938f, 0.160156f, 0.425781f, 0.031250f}, {0.164062f, 0.355469f, 0.945312f, 0.878906f}, + {0.968750f, 0.628906f, 0.738281f, 0.261719f}, {0.839844f, 0.218750f, 0.296875f, 0.058594f}, + {0.128906f, 0.902344f, 0.875000f, 0.933594f}, {0.035156f, 0.726562f, 0.113281f, 0.207031f}, + {0.996094f, 0.335938f, 0.625000f, 0.464844f}, {0.531250f, 0.984375f, 0.277344f, 0.660156f}, + {0.066406f, 0.589844f, 0.148438f, 0.367188f}, {0.363281f, 0.242188f, 0.867188f, 0.707031f}, + {0.945312f, 0.953125f, 0.437500f, 0.527344f}, {0.042969f, 0.292969f, 0.535156f, 0.828125f}, + {0.492188f, 0.617188f, 0.175781f, 0.730469f}, {0.332031f, 0.785156f, 0.886719f, 0.351562f}, + {0.875000f, 0.984375f, 0.226562f, 0.179688f}, {0.062500f, 0.269531f, 0.839844f, 0.039062f}, + {0.292969f, 0.875000f, 0.960938f, 0.421875f}, {0.917969f, 0.175781f, 0.167969f, 0.867188f}, + {0.714844f, 0.324219f, 0.753906f, 0.000000f}, {0.593750f, 0.582031f, 0.523438f, 0.671875f}, + {0.421875f, 0.089844f, 0.117188f, 0.910156f}, {0.136719f, 0.652344f, 0.730469f, 0.402344f}, + {0.750000f, 0.363281f, 0.335938f, 0.179688f}, {0.906250f, 0.824219f, 0.660156f, 0.550781f}, + {0.199219f, 0.976562f, 0.128906f, 0.128906f}, {0.101562f, 0.125000f, 0.714844f, 0.664062f}, + {0.800781f, 0.378906f, 0.257812f, 0.296875f}, {0.515625f, 0.890625f, 0.027344f, 0.773438f}, + {0.414062f, 0.605469f, 0.082031f, 0.351562f}, {0.070312f, 0.765625f, 0.804688f, 0.585938f}, + {0.187500f, 0.433594f, 0.910156f, 0.968750f}, {0.796875f, 0.031250f, 0.468750f, 0.726562f}, + {0.457031f, 0.589844f, 0.156250f, 0.410156f}, {0.160156f, 0.312500f, 0.257812f, 0.949219f}, + {0.718750f, 0.785156f, 0.027344f, 0.363281f}, {0.773438f, 0.210938f, 0.554688f, 0.863281f}, + {0.476562f, 0.683594f, 0.335938f, 0.488281f}, {0.007812f, 0.765625f, 0.839844f, 0.769531f}, + {0.707031f, 0.859375f, 0.488281f, 0.605469f}, {0.445312f, 0.406250f, 0.230469f, 0.082031f}, + {0.566406f, 0.675781f, 0.746094f, 0.464844f}, {0.757812f, 0.582031f, 0.957031f, 0.023438f}, + {0.925781f, 0.843750f, 0.066406f, 0.183594f}, {0.281250f, 0.367188f, 0.429688f, 0.976562f}, + {0.125000f, 0.957031f, 0.644531f, 0.324219f}, {0.421875f, 0.746094f, 0.757812f, 0.214844f}, + {0.675781f, 0.410156f, 0.976562f, 0.933594f}, {0.074219f, 0.914062f, 0.851562f, 0.558594f}, + {0.617188f, 0.070312f, 0.667969f, 0.238281f}, {0.910156f, 0.457031f, 0.246094f, 0.742188f}, + {0.285156f, 0.335938f, 0.824219f, 0.636719f}, {0.722656f, 0.832031f, 0.007812f, 0.828125f}, + {0.816406f, 0.949219f, 0.289062f, 0.273438f}, {0.925781f, 0.152344f, 0.148438f, 0.675781f}, + {0.085938f, 0.359375f, 0.789062f, 0.187500f}, {0.277344f, 0.640625f, 0.585938f, 0.507812f}, + {0.164062f, 0.867188f, 0.105469f, 0.640625f}, {0.457031f, 0.570312f, 0.183594f, 0.050781f}, + {0.789062f, 0.675781f, 0.371094f, 0.203125f}, {0.050781f, 0.164062f, 0.675781f, 0.996094f}, + {0.726562f, 0.718750f, 0.152344f, 0.316406f}, {0.992188f, 0.210938f, 0.578125f, 0.066406f}, + {0.464844f, 0.894531f, 0.386719f, 0.242188f}, {0.792969f, 0.500000f, 0.203125f, 0.140625f}, + {0.925781f, 0.687500f, 0.527344f, 0.414062f}, {0.644531f, 0.062500f, 0.132812f, 0.824219f}, + {0.289062f, 0.847656f, 0.234375f, 0.492188f}, {0.390625f, 0.570312f, 0.054688f, 0.394531f}, + {0.554688f, 0.042969f, 0.546875f, 0.890625f}, {0.917969f, 0.796875f, 0.695312f, 0.589844f}, + {0.203125f, 0.207031f, 0.839844f, 0.273438f}, {0.773438f, 0.484375f, 0.355469f, 0.960938f}, + {0.699219f, 0.035156f, 0.593750f, 0.152344f}, {0.171875f, 0.410156f, 0.218750f, 0.050781f}, + {0.289062f, 0.824219f, 0.921875f, 0.406250f}, {0.851562f, 0.078125f, 0.765625f, 0.261719f}, + {0.781250f, 0.703125f, 0.066406f, 0.457031f}, {0.105469f, 0.000000f, 0.460938f, 0.546875f}, + {0.695312f, 0.140625f, 0.734375f, 0.792969f}, {0.187500f, 0.660156f, 0.515625f, 0.632812f}, + {0.636719f, 0.433594f, 0.085938f, 0.257812f}, {0.402344f, 0.500000f, 0.425781f, 0.562500f}, + {0.003906f, 0.019531f, 0.890625f, 0.214844f}, {0.878906f, 0.953125f, 0.816406f, 0.156250f}, + {0.503906f, 0.847656f, 0.058594f, 0.835938f}, {0.062500f, 0.746094f, 0.617188f, 0.738281f}, + {0.839844f, 0.058594f, 0.902344f, 0.312500f}, {0.691406f, 0.171875f, 0.496094f, 0.640625f}, + {0.390625f, 0.417969f, 0.378906f, 0.433594f}, {0.593750f, 0.742188f, 0.578125f, 0.945312f}, + {0.734375f, 0.484375f, 0.917969f, 0.722656f}, {0.316406f, 0.289062f, 0.667969f, 0.113281f}, + {0.675781f, 0.164062f, 0.429688f, 0.460938f}, {0.972656f, 0.984375f, 0.371094f, 0.628906f}, + {0.628906f, 0.257812f, 0.218750f, 0.015625f}, {0.242188f, 0.656250f, 0.773438f, 0.320312f}, + {0.589844f, 0.957031f, 0.984375f, 0.777344f}, {0.957031f, 0.492188f, 0.402344f, 0.550781f}, + {0.359375f, 0.144531f, 0.726562f, 0.105469f}, {0.859375f, 0.425781f, 0.203125f, 0.582031f}, + {0.113281f, 0.921875f, 0.128906f, 0.261719f}, {0.933594f, 0.253906f, 0.628906f, 0.144531f}, + {0.812500f, 0.570312f, 0.992188f, 0.890625f}, {0.148438f, 0.179688f, 0.093750f, 0.308594f}, + {0.894531f, 0.734375f, 0.160156f, 0.734375f}, {0.339844f, 0.269531f, 0.343750f, 0.628906f}, + {0.621094f, 0.089844f, 0.500000f, 0.394531f}, {0.523438f, 0.644531f, 0.906250f, 0.773438f}, + {0.796875f, 0.507812f, 0.203125f, 0.480469f}, {0.582031f, 0.042969f, 0.367188f, 0.710938f}, +}; + +#endif /* __EEVEE_LUT_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c new file mode 100644 index 00000000000..85c312d311c --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -0,0 +1,1745 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_materials.c + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "BLI_dynstr.h" +#include "BLI_ghash.h" +#include "BLI_alloca.h" +#include "BLI_rand.h" +#include "BLI_string_utils.h" + +#include "BKE_particle.h" +#include "BKE_paint.h" +#include "BKE_pbvh.h" +#include "BKE_studiolight.h" + +#include "DNA_world_types.h" +#include "DNA_modifier_types.h" +#include "DNA_view3d_types.h" + +#include "GPU_material.h" + +#include "eevee_engine.h" +#include "eevee_lut.h" +#include "eevee_private.h" + +/* *********** STATIC *********** */ +static struct { + char *frag_shader_lib; + char *vert_shader_str; + char *volume_shader_lib; + + struct GPUShader *default_prepass_sh; + struct GPUShader *default_prepass_clip_sh; + struct GPUShader *default_hair_prepass_sh; + struct GPUShader *default_hair_prepass_clip_sh; + struct GPUShader *default_lit[VAR_MAT_MAX]; + struct GPUShader *default_background; + struct GPUShader *default_studiolight_background; + struct GPUShader *update_noise_sh; + + /* 64*64 array texture containing all LUTs and other utilitarian arrays. + * Packing enables us to same precious textures slots. */ + struct GPUTexture *util_tex; + struct GPUTexture *noise_tex; + + uint sss_count; + + float alpha_hash_offset; + float noise_offsets[3]; +} e_data = {NULL}; /* Engine data */ + +extern char datatoc_lamps_lib_glsl[]; +extern char datatoc_lightprobe_lib_glsl[]; +extern char datatoc_ambient_occlusion_lib_glsl[]; +extern char datatoc_prepass_frag_glsl[]; +extern char datatoc_prepass_vert_glsl[]; +extern char datatoc_default_frag_glsl[]; +extern char datatoc_default_world_frag_glsl[]; +extern char datatoc_ltc_lib_glsl[]; +extern char datatoc_bsdf_lut_frag_glsl[]; +extern char datatoc_btdf_lut_frag_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_bsdf_direct_lib_glsl[]; +extern char datatoc_bsdf_sampling_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_common_hair_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_irradiance_lib_glsl[]; +extern char datatoc_octahedron_lib_glsl[]; +extern char datatoc_lit_surface_frag_glsl[]; +extern char datatoc_lit_surface_vert_glsl[]; +extern char datatoc_raytrace_lib_glsl[]; +extern char datatoc_ssr_lib_glsl[]; +extern char datatoc_shadow_vert_glsl[]; +extern char datatoc_lightprobe_geom_glsl[]; +extern char datatoc_lightprobe_vert_glsl[]; +extern char datatoc_background_vert_glsl[]; +extern char datatoc_update_noise_frag_glsl[]; +extern char datatoc_volumetric_vert_glsl[]; +extern char datatoc_volumetric_geom_glsl[]; +extern char datatoc_volumetric_frag_glsl[]; +extern char datatoc_volumetric_lib_glsl[]; + +extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; + +extern Material defmaterial; +extern GlobalsUboStorage ts; + +/* *********** FUNCTIONS *********** */ + +#if 0 /* Used only to generate the LUT values */ +static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h)) +{ + struct GPUTexture *tex; + struct GPUFrameBuffer *fb = NULL; + static float samples_ct = 8192.0f; + static float inv_samples_ct = 1.0f / 8192.0f; + + char *lib_str = BLI_string_joinN( + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl); + + struct GPUShader *sh = DRW_shader_create_with_lib( + datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, datatoc_bsdf_lut_frag_glsl, lib_str, + "#define HAMMERSLEY_SIZE 8192\n" + "#define BRDF_LUT_SIZE 64\n" + "#define NOISE_SIZE 64\n"); + + DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_float(grp, "sampleCount", &samples_ct, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_ct, 1); + DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); + DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter); + + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + DRW_shgroup_call_add(grp, geom, NULL); + + float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut"); + + tex = DRW_texture_create_2D(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels); + + DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER}; + GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1); + + GPU_framebuffer_bind(fb); + DRW_draw_pass(pass); + + float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut"); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data); + + printf("{"); + for (int i = 0; i < w*h * 3; i+=3) { + printf("%ff, %ff, ", data[i], data[i+1]); i+=3; + printf("%ff, %ff, ", data[i], data[i+1]); i+=3; + printf("%ff, %ff, ", data[i], data[i+1]); i+=3; + printf("%ff, %ff, \n", data[i], data[i+1]); + } + printf("}"); + + MEM_freeN(texels); + MEM_freeN(data); + + return tex; +} + +static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h) +{ + struct GPUTexture *tex; + struct GPUTexture *hammersley = create_hammersley_sample_texture(8192); + struct GPUFrameBuffer *fb = NULL; + static float samples_ct = 8192.0f; + static float a2 = 0.0f; + static float inv_samples_ct = 1.0f / 8192.0f; + + char *frag_str = BLI_string_joinN( + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_btdf_lut_frag_glsl); + + struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str, + "#define HAMMERSLEY_SIZE 8192\n" + "#define BRDF_LUT_SIZE 64\n" + "#define NOISE_SIZE 64\n" + "#define LUT_SIZE 64\n"); + + MEM_freeN(frag_str); + + DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_float(grp, "a2", &a2, 1); + DRW_shgroup_uniform_float(grp, "sampleCount", &samples_ct, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_ct, 1); + DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley); + DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex); + + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + DRW_shgroup_call_add(grp, geom, NULL); + + float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut"); + + tex = DRW_texture_create_2D(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels); + + DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER}; + GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1); + + GPU_framebuffer_bind(fb); + + float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut"); + + float inc = 1.0f / 31.0f; + float roughness = 1e-8f - inc; + FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w"); + fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n"); + do { + roughness += inc; + CLAMP(roughness, 1e-4f, 1.0f); + a2 = powf(roughness, 4.0f); + DRW_draw_pass(pass); + + GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data); + +#if 1 + fprintf(f, "\t{\n\t\t"); + for (int i = 0; i < w*h * 3; i+=3) { + fprintf(f, "%ff,", data[i]); + if (((i/3)+1) % 12 == 0) fprintf(f, "\n\t\t"); + else fprintf(f, " "); + } + fprintf(f, "\n\t},\n"); +#else + for (int i = 0; i < w*h * 3; i+=3) { + if (data[i] < 0.01) printf(" "); + else if (data[i] < 0.3) printf("."); + else if (data[i] < 0.6) printf("+"); + else if (data[i] < 0.9) printf("%%"); + else printf("#"); + if ((i/3+1) % 64 == 0) printf("\n"); + } +#endif + + } while (roughness < 1.0f); + fprintf(f, "\n};\n"); + + fclose(f); + + MEM_freeN(texels); + MEM_freeN(data); + + return tex; +} +#endif +/* XXX TODO define all shared resources in a shared place without duplication */ +struct GPUTexture *EEVEE_materials_get_util_tex(void) +{ + return e_data.util_tex; +} + +static int eevee_material_shadow_option(int shadow_method) +{ + switch (shadow_method) { + case SHADOW_ESM: return VAR_MAT_ESM; + case SHADOW_VSM: return VAR_MAT_VSM; + default: + BLI_assert(!"Incorrect Shadow Method"); + break; + } + + return 0; +} + +static char *eevee_get_defines(int options) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + BLI_dynstr_appendf(ds, SHADER_DEFINES); + + if ((options & VAR_MAT_MESH) != 0) { + BLI_dynstr_appendf(ds, "#define MESH_SHADER\n"); + } + if ((options & VAR_MAT_HAIR) != 0) { + BLI_dynstr_appendf(ds, "#define HAIR_SHADER\n"); + } + if ((options & VAR_MAT_PROBE) != 0) { + BLI_dynstr_appendf(ds, "#define PROBE_CAPTURE\n"); + } + if ((options & VAR_MAT_FLAT) != 0) { + BLI_dynstr_appendf(ds, "#define USE_FLAT_NORMAL\n"); + } + if ((options & VAR_MAT_CLIP) != 0) { + BLI_dynstr_appendf(ds, "#define USE_ALPHA_CLIP\n"); + } + if ((options & VAR_MAT_SHADOW) != 0) { + BLI_dynstr_appendf(ds, "#define SHADOW_SHADER\n"); + } + if ((options & VAR_MAT_HASH) != 0) { + BLI_dynstr_appendf(ds, "#define USE_ALPHA_HASH\n"); + } + if ((options & VAR_MAT_BLEND) != 0) { + BLI_dynstr_appendf(ds, "#define USE_ALPHA_BLEND\n"); + } + if ((options & VAR_MAT_MULT) != 0) { + BLI_dynstr_appendf(ds, "#define USE_MULTIPLY\n"); + } + if ((options & VAR_MAT_REFRACT) != 0) { + BLI_dynstr_appendf(ds, "#define USE_REFRACTION\n"); + } + if ((options & VAR_MAT_SSS) != 0) { + BLI_dynstr_appendf(ds, "#define USE_SSS\n"); + } + if ((options & VAR_MAT_SSSALBED) != 0) { + BLI_dynstr_appendf(ds, "#define USE_SSS_ALBEDO\n"); + } + if ((options & VAR_MAT_TRANSLUC) != 0) { + BLI_dynstr_appendf(ds, "#define USE_TRANSLUCENCY\n"); + } + if ((options & VAR_MAT_VSM) != 0) { + BLI_dynstr_appendf(ds, "#define SHADOW_VSM\n"); + } + if ((options & VAR_MAT_ESM) != 0) { + BLI_dynstr_appendf(ds, "#define SHADOW_ESM\n"); + } + if (((options & VAR_MAT_VOLUME) != 0) && ((options & VAR_MAT_BLEND) != 0)) { + BLI_dynstr_appendf(ds, "#define USE_ALPHA_BLEND_VOLUMETRICS\n"); + } + if ((options & VAR_MAT_LOOKDEV) != 0) { + BLI_dynstr_appendf(ds, "#define LOOKDEV\n"); + } + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + return str; +} + +static char *eevee_get_volume_defines(int options) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + BLI_dynstr_appendf(ds, SHADER_DEFINES); + BLI_dynstr_appendf(ds, "#define VOLUMETRICS\n"); + + if ((options & VAR_MAT_VOLUME) != 0) { + BLI_dynstr_appendf(ds, "#define MESH_SHADER\n"); + } + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + return str; +} + +/** + * ssr_id can be null to disable ssr contribution. + **/ +static void add_standard_uniforms( + DRWShadingGroup *shgrp, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, + int *ssr_id, float *refract_depth, bool use_ssrefraction, bool use_alpha_blend) +{ + if (ssr_id == NULL) { + static int no_ssr = -1.0f; + ssr_id = &no_ssr; + } + + DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(shgrp, "clip_block", sldata->clip_ubo); + + /* TODO if glossy or diffuse bsdf */ + if (true) { + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); + DRW_shgroup_uniform_texture_ref(shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool); + DRW_shgroup_uniform_texture_ref(shgrp, "shadowCascadeTexture", &sldata->shadow_cascade_pool); + DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer); + + if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) != 0) { + DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &vedata->stl->effects->gtao_horizons); + } + else { + /* Use maxzbuffer as fallback to avoid sampling problem on certain platform, see: T52593 */ + DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &vedata->txl->maxzbuffer); + } + } + + /* TODO if diffuse bsdf */ + if (true) { + DRW_shgroup_uniform_texture_ref(shgrp, "irradianceGrid", &sldata->irradiance_pool); + } + + /* TODO if glossy bsdf */ + if (true) { + DRW_shgroup_uniform_texture_ref(shgrp, "probeCubes", &sldata->probe_pool); + DRW_shgroup_uniform_texture_ref(shgrp, "probePlanars", &vedata->txl->planar_pool); + DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1); + } + + if (use_ssrefraction) { + BLI_assert(refract_depth != NULL); + DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1); + DRW_shgroup_uniform_texture_ref(shgrp, "colorBuffer", &vedata->txl->refract_color); + } + + if ((vedata->stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0 && + use_alpha_blend) + { + /* Do not use history buffers as they already have been swapped */ + DRW_shgroup_uniform_texture_ref(shgrp, "inScattering", &vedata->txl->volume_scatter); + DRW_shgroup_uniform_texture_ref(shgrp, "inTransmittance", &vedata->txl->volume_transmittance); + } +} + +static void create_default_shader(int options) +{ + char *frag_str = BLI_string_joinN( + e_data.frag_shader_lib, + datatoc_default_frag_glsl); + + char *defines = eevee_get_defines(options); + + e_data.default_lit[options] = DRW_shader_create(e_data.vert_shader_str, NULL, frag_str, defines); + + MEM_freeN(defines); + MEM_freeN(frag_str); +} + +static void eevee_init_noise_texture(void) +{ + e_data.noise_tex = DRW_texture_create_2D(64, 64, GPU_RGBA16F, 0, (float *)blue_noise); +} + +static void eevee_init_util_texture(void) +{ + const int layers = 3 + 16; + float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * 64 * 64 * layers, "utils texels"); + float (*texels_layer)[4] = texels; + + /* Copy ltc_mat_ggx into 1st layer */ + memcpy(texels_layer, ltc_mat_ggx, sizeof(float[4]) * 64 * 64); + texels_layer += 64 * 64; + + /* Copy bsdf_split_sum_ggx into 2nd layer red and green channels. + Copy ltc_mag_ggx into 2nd layer blue channel. */ + for (int i = 0; i < 64 * 64; i++) { + texels_layer[i][0] = bsdf_split_sum_ggx[i * 2 + 0]; + texels_layer[i][1] = bsdf_split_sum_ggx[i * 2 + 1]; + texels_layer[i][2] = ltc_mag_ggx[i]; + texels_layer[i][3] = ltc_disk_integral[i]; + } + texels_layer += 64 * 64; + + /* Copy blue noise in 3rd layer */ + for (int i = 0; i < 64 * 64; i++) { + texels_layer[i][0] = blue_noise[i][0]; + texels_layer[i][1] = blue_noise[i][2]; + texels_layer[i][2] = cosf(blue_noise[i][1] * 2.0f * M_PI); + texels_layer[i][3] = sinf(blue_noise[i][1] * 2.0f * M_PI); + } + texels_layer += 64 * 64; + + /* Copy Refraction GGX LUT in layer 4 - 20 */ + for (int j = 0; j < 16; ++j) { + for (int i = 0; i < 64 * 64; i++) { + texels_layer[i][0] = btdf_split_sum_ggx[j * 2][i]; + texels_layer[i][1] = btdf_split_sum_ggx[j * 2][i]; + texels_layer[i][2] = btdf_split_sum_ggx[j * 2][i]; + texels_layer[i][3] = btdf_split_sum_ggx[j * 2][i]; + } + texels_layer += 64 * 64; + } + + e_data.util_tex = DRW_texture_create_2D_array( + 64, 64, layers, GPU_RGBA16F, DRW_TEX_FILTER | DRW_TEX_WRAP, (float *)texels); + + MEM_freeN(texels); +} + +void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]) +{ + e_data.noise_offsets[0] = offsets[0]; + e_data.noise_offsets[1] = offsets[1]; + e_data.noise_offsets[2] = offsets[2]; + + /* Attach & detach because we don't currently support multiple FB per texture, + * and this would be the case for multiple viewport. */ + GPU_framebuffer_bind(fbl->update_noise_fb); + DRW_draw_pass(psl->update_noise_pass); +} + +static void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]) +{ + /* view vectors for the corners of the view frustum. + * Can be used to recreate the world space position easily */ + float view_vecs[4][4] = { + {-1.0f, -1.0f, -1.0f, 1.0f}, + { 1.0f, -1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f, 1.0f}, + {-1.0f, -1.0f, 1.0f, 1.0f} + }; + + /* convert the view vectors to view space */ + const bool is_persp = (winmat[3][3] == 0.0f); + for (int i = 0; i < 4; i++) { + mul_project_m4_v3(invproj, view_vecs[i]); + /* normalized trick see: + * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ + if (is_persp) { + /* Divide XY by Z. */ + mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]); + } + } + + /** + * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and + * view_vecs[1] is the vector going from the near-bottom-left corner to + * the far-top-right corner. + * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner + * when Z = 1, and top-left corner if Z = 1. + * view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed) + * distance from the near plane to the far clip plane. + **/ + copy_v4_v4(r_viewvecs[0], view_vecs[0]); + + /* we need to store the differences */ + r_viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0]; + r_viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1]; + r_viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2]; +} + +void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl) +{ + if (!e_data.frag_shader_lib) { + /* Shaders */ + e_data.frag_shader_lib = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_raytrace_lib_glsl, + datatoc_ssr_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_ltc_lib_glsl, + datatoc_bsdf_direct_lib_glsl, + datatoc_lamps_lib_glsl, + /* Add one for each Closure */ + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_volumetric_lib_glsl); + + e_data.volume_shader_lib = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_ltc_lib_glsl, + datatoc_bsdf_direct_lib_glsl, + datatoc_lamps_lib_glsl, + datatoc_volumetric_lib_glsl, + datatoc_volumetric_frag_glsl); + + e_data.vert_shader_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_hair_lib_glsl, + datatoc_lit_surface_vert_glsl); + + e_data.default_background = DRW_shader_create( + datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, + NULL); + + e_data.default_studiolight_background = DRW_shader_create( + datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, + "#define LOOKDEV\n"); + + e_data.default_prepass_sh = DRW_shader_create( + datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl, + NULL); + + e_data.default_prepass_clip_sh = DRW_shader_create( + datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl, + "#define CLIP_PLANES\n"); + + char *vert_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_hair_lib_glsl, + datatoc_prepass_vert_glsl); + + e_data.default_hair_prepass_sh = DRW_shader_create( + vert_str, NULL, datatoc_prepass_frag_glsl, + "#define HAIR_SHADER\n"); + + e_data.default_hair_prepass_clip_sh = DRW_shader_create( + vert_str, NULL, datatoc_prepass_frag_glsl, + "#define HAIR_SHADER\n" + "#define CLIP_PLANES\n"); + + MEM_freeN(vert_str); + + e_data.update_noise_sh = DRW_shader_create_fullscreen( + datatoc_update_noise_frag_glsl, NULL); + + eevee_init_util_texture(); + eevee_init_noise_texture(); + } + + if (!DRW_state_is_image_render() && + ((stl->effects->enabled_effects & EFFECT_TAA) == 0)) + { + e_data.alpha_hash_offset = 0.0f; + } + else { + double r; + BLI_halton_1D(5, 0.0, stl->effects->taa_current_sample - 1, &r); + e_data.alpha_hash_offset = (float)r; + } + + { + /* Update view_vecs */ + float invproj[4][4], winmat[4][4]; + DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); + DRW_viewport_matrix_get(invproj, DRW_MAT_WININV); + + EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs); + } + + { + /* Update noise Framebuffer. */ + GPU_framebuffer_ensure_config(&fbl->update_noise_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE_LAYER(e_data.util_tex, 2) + }); + } +} + +struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo) +{ + const void *engine = &DRW_engine_viewport_eevee_type; + const int options = VAR_WORLD_PROBE; + + GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options); + if (mat != NULL) { + return mat; + } + return DRW_shader_create_from_world( + scene, wo, engine, options, + datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib, + SHADER_DEFINES "#define PROBE_CAPTURE\n"); +} + +struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, World *wo) +{ + const void *engine = &DRW_engine_viewport_eevee_type; + int options = VAR_WORLD_BACKGROUND; + + GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options); + if (mat != NULL) { + return mat; + } + return DRW_shader_create_from_world( + scene, wo, engine, options, + datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib, + SHADER_DEFINES "#define WORLD_BACKGROUND\n"); +} + +struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *wo) +{ + const void *engine = &DRW_engine_viewport_eevee_type; + int options = VAR_WORLD_VOLUME; + + GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options); + if (mat != NULL) { + return mat; + } + + char *defines = eevee_get_volume_defines(options); + + mat = DRW_shader_create_from_world( + scene, wo, engine, options, + datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib, + defines); + + MEM_freeN(defines); + + return mat; +} + +struct GPUMaterial *EEVEE_material_mesh_get( + struct Scene *scene, Material *ma, EEVEE_Data *vedata, + bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method) +{ + EEVEE_EffectsInfo *effects = vedata->stl->effects; + const void *engine = &DRW_engine_viewport_eevee_type; + int options = VAR_MAT_MESH; + + if (use_blend) options |= VAR_MAT_BLEND; + if (use_multiply) options |= VAR_MAT_MULT; + if (use_refract) options |= VAR_MAT_REFRACT; + if (use_sss) options |= VAR_MAT_SSS; + if (use_sss && effects->sss_separate_albedo) options |= VAR_MAT_SSSALBED; + if (use_translucency) options |= VAR_MAT_TRANSLUC; + if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) options |= VAR_MAT_VOLUME; + + options |= eevee_material_shadow_option(shadow_method); + + GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options); + if (mat) { + return mat; + } + + char *defines = eevee_get_defines(options); + + mat = DRW_shader_create_from_material( + scene, ma, engine, options, + e_data.vert_shader_str, NULL, e_data.frag_shader_lib, + defines); + + MEM_freeN(defines); + + return mat; +} + +struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma) +{ + const void *engine = &DRW_engine_viewport_eevee_type; + int options = VAR_MAT_VOLUME; + + GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options); + if (mat != NULL) { + return mat; + } + + char *defines = eevee_get_volume_defines(options); + + mat = DRW_shader_create_from_material( + scene, ma, engine, options, + datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib, + defines); + + MEM_freeN(defines); + + return mat; +} + +struct GPUMaterial *EEVEE_material_mesh_depth_get( + struct Scene *scene, Material *ma, + bool use_hashed_alpha, bool is_shadow) +{ + const void *engine = &DRW_engine_viewport_eevee_type; + int options = VAR_MAT_MESH; + + if (use_hashed_alpha) { + options |= VAR_MAT_HASH; + } + else { + options |= VAR_MAT_CLIP; + } + + if (is_shadow) + options |= VAR_MAT_SHADOW; + + GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options); + if (mat) { + return mat; + } + + char *defines = eevee_get_defines(options); + + char *frag_str = BLI_string_joinN( + e_data.frag_shader_lib, + datatoc_prepass_frag_glsl); + + mat = DRW_shader_create_from_material( + scene, ma, engine, options, + (is_shadow) ? datatoc_shadow_vert_glsl : e_data.vert_shader_str, + NULL, + frag_str, + defines); + + MEM_freeN(frag_str); + MEM_freeN(defines); + + return mat; +} + +struct GPUMaterial *EEVEE_material_hair_get( + struct Scene *scene, Material *ma, int shadow_method) +{ + const void *engine = &DRW_engine_viewport_eevee_type; + int options = VAR_MAT_MESH | VAR_MAT_HAIR; + + options |= eevee_material_shadow_option(shadow_method); + + GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options); + if (mat) { + return mat; + } + + char *defines = eevee_get_defines(options); + + mat = DRW_shader_create_from_material( + scene, ma, engine, options, + e_data.vert_shader_str, NULL, e_data.frag_shader_lib, + defines); + + MEM_freeN(defines); + + return mat; +} + +/** + * Create a default shading group inside the given pass. + **/ +static struct DRWShadingGroup *EEVEE_default_shading_group_create( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWPass *pass, + bool is_hair, bool is_flat_normal, bool use_blend, bool use_ssr, int shadow_method) +{ + EEVEE_EffectsInfo *effects = vedata->stl->effects; + static int ssr_id; + ssr_id = (use_ssr) ? 1 : -1; + int options = VAR_MAT_MESH; + + if (is_hair) options |= VAR_MAT_HAIR; + if (is_flat_normal) options |= VAR_MAT_FLAT; + if (use_blend) options |= VAR_MAT_BLEND; + if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) options |= VAR_MAT_VOLUME; + + options |= eevee_material_shadow_option(shadow_method); + + if (e_data.default_lit[options] == NULL) { + create_default_shader(options); + } + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass); + add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, use_blend); + + return shgrp; +} + +/** + * Create a default shading group inside the default pass without standard uniforms. + **/ +static struct DRWShadingGroup *EEVEE_default_shading_group_get( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, + Object *ob, ParticleSystem *psys, ModifierData *md, + bool is_hair, bool is_flat_normal, bool use_ssr, int shadow_method) +{ + static int ssr_id; + ssr_id = (use_ssr) ? 1 : -1; + int options = VAR_MAT_MESH; + + BLI_assert(!is_hair || (ob && psys && md)); + + if (is_hair) options |= VAR_MAT_HAIR; + if (is_flat_normal) options |= VAR_MAT_FLAT; + + options |= eevee_material_shadow_option(shadow_method); + + if (e_data.default_lit[options] == NULL) { + create_default_shader(options); + } + + if (vedata->psl->default_pass[options] == NULL) { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; + vedata->psl->default_pass[options] = DRW_pass_create("Default Lit Pass", state); + + /* XXX / WATCH: This creates non persistent binds for the ubos and textures. + * But it's currently OK because the following shgroups does not add any bind. + * EDIT: THIS IS NOT THE CASE FOR HAIRS !!! DUMMY!!! */ + if (!is_hair) { + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); + add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false); + } + } + + if (is_hair) { + DRWShadingGroup *shgrp = DRW_shgroup_hair_create(ob, psys, md, + vedata->psl->default_pass[options], vedata->psl->hair_tf_pass, + e_data.default_lit[options]); + add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false); + return shgrp; + } + else { + return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); + } +} + +/** + * Create a default shading group inside the lookdev pass without standard uniforms. + **/ +static struct DRWShadingGroup *EEVEE_lookdev_shading_group_get( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, + bool use_ssr, int shadow_method) +{ + static int ssr_id; + ssr_id = (use_ssr) ? 1 : -1; + int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV; + + options |= eevee_material_shadow_option(shadow_method); + + if (e_data.default_lit[options] == NULL) { + create_default_shader(options); + } + + if (vedata->psl->lookdev_pass == NULL) { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_CULL_BACK; + vedata->psl->lookdev_pass = DRW_pass_create("LookDev Pass", state); + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->lookdev_pass); + /* XXX / WATCH: This creates non persistent binds for the ubos and textures. + * But it's currently OK because the following shgroups does not add any bind. */ + add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false); + } + + return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->lookdev_pass); +} +void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + + /* Create Material Ghash */ + { + stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash"); + stl->g_data->hair_material_hash = BLI_ghash_ptr_new("Eevee_hair_material ghash"); + } + + { + psl->background_pass = DRW_pass_create("Background Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); + + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + DRWShadingGroup *grp = NULL; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + World *wo = scene->world; + + float *col = ts.colorBackground; + + /* LookDev */ + EEVEE_lookdev_cache_init(vedata, &grp, e_data.default_studiolight_background, psl->background_pass, wo, NULL); + /* END */ + + if (!grp && wo) { + col = &wo->horr; + + if (wo->use_nodes && wo->nodetree) { + static float error_col[3] = {1.0f, 0.0f, 1.0f}; + static float compile_col[3] = {0.5f, 0.5f, 0.5f}; + struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo); + + switch (GPU_material_status(gpumat)) { + case GPU_MAT_SUCCESS: + grp = DRW_shgroup_material_create(gpumat, psl->background_pass); + DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + DRW_shgroup_call_add(grp, geom, NULL); + break; + case GPU_MAT_QUEUED: + sldata->probes->all_materials_updated = false; + /* TODO Bypass probe compilation. */ + col = compile_col; + break; + case GPU_MAT_FAILED: + default: + col = error_col; + break; + } + } + } + + /* Fallback if shader fails or if not using nodetree. */ + if (grp == NULL) { + grp = DRW_shgroup_create(e_data.default_background, psl->background_pass); + DRW_shgroup_uniform_vec3(grp, "color", col, 1); + DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + DRW_shgroup_call_add(grp, geom, NULL); + } + } + + { + DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE; + psl->depth_pass = DRW_pass_create("Depth Pass", state); + stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass); + + state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; + psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull", state); + stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass_cull); + + state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; + psl->depth_pass_clip = DRW_pass_create("Depth Pass Clip", state); + stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->depth_pass_clip); + DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip, "clip_block", sldata->clip_ubo); + + state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK; + psl->depth_pass_clip_cull = DRW_pass_create("Depth Pass Cull Clip", state); + stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create( + e_data.default_prepass_clip_sh, psl->depth_pass_clip_cull); + DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo); + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; + psl->material_pass = DRW_pass_create("Material Shader Pass", state); + } + + { + DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE; + psl->refract_depth_pass = DRW_pass_create("Refract Depth Pass", state); + stl->g_data->refract_depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->refract_depth_pass); + + state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; + psl->refract_depth_pass_cull = DRW_pass_create("Refract Depth Pass Cull", state); + stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create( + e_data.default_prepass_sh, psl->refract_depth_pass_cull); + + state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; + psl->refract_depth_pass_clip = DRW_pass_create("Refract Depth Pass Clip", state); + stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create( + e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip); + DRW_shgroup_uniform_block(stl->g_data->refract_depth_shgrp_clip, "clip_block", sldata->clip_ubo); + + state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK; + psl->refract_depth_pass_clip_cull = DRW_pass_create("Refract Depth Pass Cull Clip", state); + stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create( + e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull); + DRW_shgroup_uniform_block(stl->g_data->refract_depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo); + } + + { + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | + DRW_STATE_WIRE); + psl->refract_pass = DRW_pass_create("Opaque Refraction Pass", state); + } + + { + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | + DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL); + psl->sss_pass = DRW_pass_create("Subsurface Pass", state); + e_data.sss_count = 0; + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; + psl->transparent_pass = DRW_pass_create("Material Transparent Pass", state); + } + + { + psl->update_noise_pass = DRW_pass_create("Update Noise Pass", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass); + DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex); + DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + + { + psl->hair_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_TRANS_FEEDBACK); + } +} + +#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) do { \ + if (is_sculpt_mode_draw) { \ + DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat); \ + } \ + else { \ + if (oedata) { \ + DRW_shgroup_call_object_add_with_callback(shgrp, geom, ob, EEVEE_lightprobes_obj_visibility_cb, oedata); \ + } \ + else { \ + DRW_shgroup_call_object_add(shgrp, geom, ob); \ + } \ + } \ +} while (0) + +#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) do { \ + if (shgrp) { \ + ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \ + } \ +} while (0) + +typedef struct EeveeMaterialShadingGroups { + struct DRWShadingGroup *shading_grp; + struct DRWShadingGroup *depth_grp; + struct DRWShadingGroup *depth_clip_grp; +} EeveeMaterialShadingGroups; + +static void material_opaque( + Material *ma, GHash *material_hash, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, + bool do_cull, bool use_flat_nor, struct GPUMaterial **gpumat, struct GPUMaterial **gpumat_depth, + struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth, struct DRWShadingGroup **shgrp_depth_clip) +{ + EEVEE_EffectsInfo *effects = vedata->stl->effects; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + EEVEE_LampsInfo *linfo = sldata->lamps; + + float *color_p = &ma->r; + float *metal_p = &ma->ray_mirror; + float *spec_p = &ma->spec; + float *rough_p = &ma->gloss_mir; + + const bool use_gpumat = (ma->use_nodes && ma->nodetree); + const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && + ((effects->enabled_effects & EFFECT_REFRACT) != 0); + const bool use_sss = ((ma->blend_flag & MA_BL_SS_SUBSURFACE) != 0) && + ((effects->enabled_effects & EFFECT_SSS) != 0); + const bool use_translucency = use_sss && ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0); + + EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma); + + if (emsg) { + *shgrp = emsg->shading_grp; + *shgrp_depth = emsg->depth_grp; + *shgrp_depth_clip = emsg->depth_clip_grp; + + /* This will have been created already, just perform a lookup. */ + *gpumat = (use_gpumat) ? EEVEE_material_mesh_get( + scene, ma, vedata, false, false, use_refract, use_sss, use_translucency, linfo->shadow_method) : NULL; + *gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get( + scene, ma, (ma->blend_method == MA_BM_HASHED), false) : NULL; + return; + } + + if (use_gpumat) { + static float error_col[3] = {1.0f, 0.0f, 1.0f}; + static float compile_col[3] = {0.5f, 0.5f, 0.5f}; + static float half = 0.5f; + + /* Shading */ + *gpumat = EEVEE_material_mesh_get( + scene, ma, vedata, false, false, use_refract, + use_sss, use_translucency, linfo->shadow_method); + + GPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat); + + /* Alpha CLipped : Discard pixel from depth pass, then + * fail the depth test for shading. */ + if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) { + *gpumat_depth = EEVEE_material_mesh_depth_get(scene, ma, (ma->blend_method == MA_BM_HASHED), false); + + GPUMaterialStatus status_mat_depth = GPU_material_status(*gpumat_depth); + if (status_mat_depth != GPU_MAT_SUCCESS) { + /* Mixing both flags. If depth shader fails, show it to the user by not using + * the surface shader. */ + status_mat_surface = status_mat_depth; + } + else if (use_refract) { + *shgrp_depth = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass); + *shgrp_depth_clip = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip); + } + else { + *shgrp_depth = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass); + *shgrp_depth_clip = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip); + } + + if (*shgrp_depth != NULL) { + add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false); + add_standard_uniforms(*shgrp_depth_clip, sldata, vedata, NULL, NULL, false, false); + + if (ma->blend_method == MA_BM_CLIP) { + DRW_shgroup_uniform_float(*shgrp_depth, "alphaThreshold", &ma->alpha_threshold, 1); + DRW_shgroup_uniform_float(*shgrp_depth_clip, "alphaThreshold", &ma->alpha_threshold, 1); + } + else if (ma->blend_method == MA_BM_HASHED) { + DRW_shgroup_uniform_float(*shgrp_depth, "hashAlphaOffset", &e_data.alpha_hash_offset, 1); + DRW_shgroup_uniform_float(*shgrp_depth_clip, "hashAlphaOffset", &e_data.alpha_hash_offset, 1); + } + } + } + + switch (status_mat_surface) { + case GPU_MAT_SUCCESS: + { + static int no_ssr = -1; + static int first_ssr = 1; + int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr; + + *shgrp = DRW_shgroup_material_create( + *gpumat, + (use_refract) ? psl->refract_pass : + (use_sss) ? psl->sss_pass : psl->material_pass); + add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false); + + if (use_sss) { + struct GPUTexture *sss_tex_profile = NULL; + struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get( + *gpumat, + stl->effects->sss_sample_count, + &sss_tex_profile); + + if (sss_profile) { + if (use_translucency) { + DRW_shgroup_uniform_block(*shgrp, "sssProfile", sss_profile); + DRW_shgroup_uniform_texture(*shgrp, "sssTexProfile", sss_tex_profile); + } + + /* Limit of 8 bit stencil buffer. ID 255 is refraction. */ + if (e_data.sss_count < 254) { + DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1); + EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile); + e_data.sss_count++; + } + else { + /* TODO : display message. */ + printf("Error: Too many different Subsurface shader in the scene.\n"); + } + } + } + break; + } + case GPU_MAT_QUEUED: + { + sldata->probes->all_materials_updated = false; + /* TODO Bypass probe compilation. */ + color_p = compile_col; + metal_p = spec_p = rough_p = ½ + break; + } + case GPU_MAT_FAILED: + default: + color_p = error_col; + metal_p = spec_p = rough_p = ½ + break; + } + } + + /* Fallback to default shader */ + if (*shgrp == NULL) { + bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0); + *shgrp = EEVEE_default_shading_group_get(sldata, vedata, + NULL, NULL, NULL, + false, use_flat_nor, use_ssr, linfo->shadow_method); + DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(*shgrp, "roughness", rough_p, 1); + } + + /* Fallback default depth prepass */ + if (*shgrp_depth == NULL) { + if (use_refract) { + *shgrp_depth = (do_cull) ? stl->g_data->refract_depth_shgrp_cull : stl->g_data->refract_depth_shgrp; + *shgrp_depth_clip = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull : stl->g_data->refract_depth_shgrp_clip; + } + else { + *shgrp_depth = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp; + *shgrp_depth_clip = (do_cull) ? stl->g_data->depth_shgrp_clip_cull : stl->g_data->depth_shgrp_clip; + } + } + + emsg = MEM_mallocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups"); + emsg->shading_grp = *shgrp; + emsg->depth_grp = *shgrp_depth; + emsg->depth_clip_grp = *shgrp_depth_clip; + BLI_ghash_insert(material_hash, ma, emsg); +} + +static void material_transparent( + Material *ma, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, + bool do_cull, bool use_flat_nor, + struct GPUMaterial **gpumat, struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + EEVEE_LampsInfo *linfo = sldata->lamps; + + const bool use_refract = ( + ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && + ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0) + ); + float *color_p = &ma->r; + float *metal_p = &ma->ray_mirror; + float *spec_p = &ma->spec; + float *rough_p = &ma->gloss_mir; + + if (ma->use_nodes && ma->nodetree) { + static float error_col[3] = {1.0f, 0.0f, 1.0f}; + static float compile_col[3] = {0.5f, 0.5f, 0.5f}; + static float half = 0.5f; + + /* Shading */ + *gpumat = EEVEE_material_mesh_get( + scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract, + false, false, linfo->shadow_method); + + switch (GPU_material_status(*gpumat)) { + case GPU_MAT_SUCCESS: + { + static int ssr_id = -1; /* TODO transparent SSR */ + bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0; + + *shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass); + add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend); + break; + } + case GPU_MAT_QUEUED: + { + sldata->probes->all_materials_updated = false; + /* TODO Bypass probe compilation. */ + color_p = compile_col; + metal_p = spec_p = rough_p = ½ + break; + } + case GPU_MAT_FAILED: + default: + color_p = error_col; + metal_p = spec_p = rough_p = ½ + break; + } + } + + /* Fallback to default shader */ + if (*shgrp == NULL) { + *shgrp = EEVEE_default_shading_group_create( + sldata, vedata, psl->transparent_pass, + false, use_flat_nor, true, false, linfo->shadow_method); + DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(*shgrp, "roughness", rough_p, 1); + } + + const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKSIDE) != 0); + + DRWState all_state = ( + DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | + DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY + ); + + DRWState cur_state = DRW_STATE_WRITE_COLOR; + cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL; + cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; + + switch (ma->blend_method) { + case MA_BM_ADD: + cur_state |= DRW_STATE_ADDITIVE; + break; + case MA_BM_MULTIPLY: + cur_state |= DRW_STATE_MULTIPLY; + break; + case MA_BM_BLEND: + cur_state |= DRW_STATE_BLEND; + break; + default: + BLI_assert(0); + break; + } + + /* Disable other blend modes and use the one we want. */ + DRW_shgroup_state_disable(*shgrp, all_state); + DRW_shgroup_state_enable(*shgrp, cur_state); + + /* Depth prepass */ + if (use_prepass) { + *shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass); + DRW_shgroup_uniform_block(*shgrp_depth, "clip_block", sldata->clip_ubo); + + cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; + + DRW_shgroup_state_disable(*shgrp_depth, all_state); + DRW_shgroup_state_enable(*shgrp_depth, cur_state); + } +} + +void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, bool *cast_shadow) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + GHash *material_hash = stl->g_data->material_hash; + + const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING)); + const bool is_active = (ob == draw_ctx->obact); + const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; +#if 0 + const bool is_sculpt_mode_draw = is_sculpt_mode && (draw_ctx->v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE) == 0; +#else + /* For now just force fully shaded with eevee when supported. */ + const bool is_sculpt_mode_draw = + is_sculpt_mode && + ((ob->sculpt && ob->sculpt->pbvh) && (BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES)); +#endif + const bool is_default_mode_shader = is_sculpt_mode; + + /* First get materials for this mesh. */ + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + const int materials_len = MAX2(1, (is_sculpt_mode_draw ? 1 : ob->totcol)); + + struct DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len); + struct DRWShadingGroup **shgrp_depth_array = BLI_array_alloca(shgrp_depth_array, materials_len); + struct DRWShadingGroup **shgrp_depth_clip_array = BLI_array_alloca(shgrp_depth_clip_array, materials_len); + + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + struct GPUMaterial **gpumat_depth_array = BLI_array_alloca(gpumat_array, materials_len); + + bool use_flat_nor = false; + + if (is_default_mode_shader) { + if (is_sculpt_mode_draw) { + use_flat_nor = DRW_object_is_flat_normal(ob); + } + } + + for (int i = 0; i < materials_len; ++i) { + Material *ma; + + if (is_sculpt_mode_draw) { + ma = NULL; + } + else { + ma = give_current_material(ob, i + 1); + } + + gpumat_array[i] = NULL; + gpumat_depth_array[i] = NULL; + shgrp_array[i] = NULL; + shgrp_depth_array[i] = NULL; + shgrp_depth_clip_array[i] = NULL; + + if (ma == NULL) + ma = &defmaterial; + + switch (ma->blend_method) { + case MA_BM_SOLID: + case MA_BM_CLIP: + case MA_BM_HASHED: + material_opaque(ma, material_hash, sldata, vedata, do_cull, use_flat_nor, + &gpumat_array[i], &gpumat_depth_array[i], + &shgrp_array[i], &shgrp_depth_array[i], &shgrp_depth_clip_array[i]); + break; + case MA_BM_ADD: + case MA_BM_MULTIPLY: + case MA_BM_BLEND: + material_transparent(ma, sldata, vedata, do_cull, use_flat_nor, + &gpumat_array[i], &shgrp_array[i], &shgrp_depth_array[i]); + break; + default: + BLI_assert(0); + break; + } + } + + if (is_sculpt_mode && is_sculpt_mode_draw == false) { + DRW_cache_mesh_sculpt_coords_ensure(ob); + } + + /* Only support single volume material for now. */ + /* XXX We rely on the previously compiled surface shader + * to know if the material has a "volume nodetree". + */ + bool use_volume_material = (gpumat_array[0] && GPU_material_use_domain_volume(gpumat_array[0])); + + /* Get per-material split surface */ + char *auto_layer_names; + int *auto_layer_is_srgb; + int auto_layer_count; + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, + &auto_layer_names, + &auto_layer_is_srgb, + &auto_layer_count); + if (mat_geom) { + for (int i = 0; i < materials_len; ++i) { + EEVEE_ObjectEngineData *oedata = NULL; + Material *ma = give_current_material(ob, i + 1); + + if (ma == NULL) + ma = &defmaterial; + + /* Do not render surface if we are rendering a volume object + * and do not have a surface closure. */ + if (use_volume_material && + (gpumat_array[i] && !GPU_material_use_domain_surface(gpumat_array[i]))) + { + continue; + } + + /* XXX TODO rewrite this to include the dupli objects. + * This means we cannot exclude dupli objects from reflections!!! */ + if ((ob->base_flag & BASE_FROMDUPLI) == 0) { + oedata = EEVEE_object_data_ensure(ob); + oedata->ob = ob; + oedata->test_data = &sldata->probes->vis_data; + } + + /* Shading pass */ + ADD_SHGROUP_CALL(shgrp_array[i], ob, mat_geom[i], oedata); + + /* Depth Prepass */ + ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, mat_geom[i], oedata); + ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, mat_geom[i], oedata); + + char *name = auto_layer_names; + for (int j = 0; j < auto_layer_count; ++j) { + /* TODO don't add these uniform when not needed (default pass shaders). */ + if (shgrp_array[i]) { + DRW_shgroup_uniform_bool(shgrp_array[i], name, &auto_layer_is_srgb[j], 1); + } + if (shgrp_depth_array[i]) { + DRW_shgroup_uniform_bool(shgrp_depth_array[i], name, &auto_layer_is_srgb[j], 1); + } + if (shgrp_depth_clip_array[i]) { + DRW_shgroup_uniform_bool(shgrp_depth_clip_array[i], name, &auto_layer_is_srgb[j], 1); + } + /* Go to next layer name. */ + while (*name != '\0') { name++; } + name += 1; + } + + /* Shadow Pass */ + if (ma->use_nodes && ma->nodetree && (ma->blend_method != MA_BM_SOLID)) { + struct GPUMaterial *gpumat; + switch (ma->blend_shadow) { + case MA_BS_SOLID: + EEVEE_lights_cache_shcaster_add( + sldata, stl, mat_geom[i], ob); + *cast_shadow = true; + break; + case MA_BS_CLIP: + gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true); + EEVEE_lights_cache_shcaster_material_add( + sldata, psl, gpumat, mat_geom[i], ob, &ma->alpha_threshold); + *cast_shadow = true; + break; + case MA_BS_HASHED: + gpumat = EEVEE_material_mesh_depth_get(scene, ma, true, true); + EEVEE_lights_cache_shcaster_material_add( + sldata, psl, gpumat, mat_geom[i], ob, NULL); + *cast_shadow = true; + break; + case MA_BS_NONE: + default: + break; + } + } + else { + EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob); + *cast_shadow = true; + } + } + } + + /* Volumetrics */ + if (((stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_volume_material) { + EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob); + } + } + + if (ob->type == OB_MESH) { + if (ob != draw_ctx->object_edit) { + material_hash = stl->g_data->hair_material_hash; + for (ModifierData *md = ob->modifiers.first; md; md = md->next) { + if (md->type != eModifierType_ParticleSystem) { + continue; + } + ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys; + if (!psys_check_enabled(ob, psys, false)) { + continue; + } + if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + continue; + } + ParticleSettings *part = psys->part; + const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + if (draw_as != PART_DRAW_PATH) { + continue; + } + + DRWShadingGroup *shgrp = NULL; + Material *ma = give_current_material(ob, part->omat); + + if (ma == NULL) { + ma = &defmaterial; + } + + float *color_p = &ma->r; + float *metal_p = &ma->ray_mirror; + float *spec_p = &ma->spec; + float *rough_p = &ma->gloss_mir; + + shgrp = DRW_shgroup_hair_create( + ob, psys, md, + psl->depth_pass, psl->hair_tf_pass, + e_data.default_hair_prepass_sh); + + shgrp = DRW_shgroup_hair_create( + ob, psys, md, + psl->depth_pass_clip, psl->hair_tf_pass, + e_data.default_hair_prepass_clip_sh); + DRW_shgroup_uniform_block(shgrp, "clip_block", sldata->clip_ubo); + + shgrp = NULL; + if (ma->use_nodes && ma->nodetree) { + static float half = 0.5f; + static float error_col[3] = {1.0f, 0.0f, 1.0f}; + static float compile_col[3] = {0.5f, 0.5f, 0.5f}; + struct GPUMaterial *gpumat = EEVEE_material_hair_get(scene, ma, sldata->lamps->shadow_method); + + switch (GPU_material_status(gpumat)) { + case GPU_MAT_SUCCESS: + { + shgrp = DRW_shgroup_material_hair_create( + ob, psys, md, + psl->material_pass, psl->hair_tf_pass, + gpumat); + add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false); + break; + } + case GPU_MAT_QUEUED: + { + sldata->probes->all_materials_updated = false; + color_p = compile_col; + metal_p = spec_p = rough_p = ½ + break; + } + case GPU_MAT_FAILED: + default: + color_p = error_col; + metal_p = spec_p = rough_p = ½ + break; + } + } + + /* Fallback to default shader */ + if (shgrp == NULL) { + bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0); + shgrp = EEVEE_default_shading_group_get(sldata, vedata, + ob, psys, md, + true, false, use_ssr, + sldata->lamps->shadow_method); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); + } + } + } + } +} + +void EEVEE_materials_cache_finish(EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + + /* Look-Dev */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + if (LOOK_DEV_OVERLAY_ENABLED(v3d)) { + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + EEVEE_LampsInfo *linfo = sldata->lamps; + struct Gwn_Batch *sphere = DRW_cache_sphere_get(); + static float mat1[4][4]; + static float color[3] = {0.8f, 0.8f, 0.8f}; + static float metallic_on = 1.0f; + static float metallic_off = 0.00f; + static float specular_off = 0.5f; + static float specular_on = 1.0f; + static float roughness_off = 0.05f; + static float roughness_on = 1.00f; + + float view_mat[4][4]; + DRW_viewport_matrix_get(view_mat, DRW_MAT_VIEWINV); + + DRWShadingGroup *shgrp = EEVEE_lookdev_shading_group_get(sldata, vedata, false, linfo->shadow_method); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", &metallic_on, 1); + DRW_shgroup_uniform_float(shgrp, "specular", &specular_on, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", &roughness_off, 1); + unit_m4(mat1); + mul_m4_m4m4(mat1, mat1, view_mat); + translate_m4(mat1, -1.5f, 0.0f, -5.0f); + DRW_shgroup_call_add(shgrp, sphere, mat1); + + shgrp = EEVEE_lookdev_shading_group_get(sldata, vedata, false, linfo->shadow_method); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", &metallic_off, 1); + DRW_shgroup_uniform_float(shgrp, "specular", &specular_off, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", &roughness_on, 1); + translate_m4(mat1, 3.0f, 0.0f, 0.0f); + DRW_shgroup_call_add(shgrp, sphere, mat1); + } + /* END */ + + BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN); + BLI_ghash_free(stl->g_data->hair_material_hash, NULL, NULL); +} + +void EEVEE_materials_free(void) +{ + for (int i = 0; i < VAR_MAT_MAX; ++i) { + DRW_SHADER_FREE_SAFE(e_data.default_lit[i]); + } + MEM_SAFE_FREE(e_data.frag_shader_lib); + MEM_SAFE_FREE(e_data.vert_shader_str); + MEM_SAFE_FREE(e_data.volume_shader_lib); + DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh); + DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh); + DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh); + DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh); + DRW_SHADER_FREE_SAFE(e_data.default_background); + DRW_SHADER_FREE_SAFE(e_data.default_studiolight_background); + DRW_SHADER_FREE_SAFE(e_data.update_noise_sh); + DRW_TEXTURE_FREE_SAFE(e_data.util_tex); + DRW_TEXTURE_FREE_SAFE(e_data.noise_tex); +} + +void EEVEE_draw_default_passes(EEVEE_PassList *psl) +{ + for (int i = 0; i < VAR_MAT_MAX; ++i) { + if (psl->default_pass[i]) { + DRW_draw_pass(psl->default_pass[i]); + } + } +} diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c new file mode 100644 index 00000000000..de9582611ec --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -0,0 +1,139 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_mist.c + * \ingroup draw_engine + * + * Implementation of Blender Mist pass. + * IMPORTANT: This is a "post process" of the Z depth so it will lack any transparent objects. + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_world_types.h" + +#include "BLI_string_utils.h" + +#include "eevee_private.h" + +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_effect_mist_frag_glsl[]; + +static struct { + struct GPUShader *mist_sh; +} e_data = {NULL}; /* Engine data */ + +void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + EEVEE_FramebufferList *fbl = vedata->fbl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_PrivateData *g_data = stl->g_data; + Scene *scene = draw_ctx->scene; + + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + if (e_data.mist_sh == NULL) { + char *frag_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_effect_mist_frag_glsl); + + e_data.mist_sh = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n"); + + MEM_freeN(frag_str); + } + + /* Create FrameBuffer. */ + DRW_texture_ensure_fullscreen_2D(&txl->mist_accum, GPU_R32F, 0); /* Should be enough precision for many samples. */ + + GPU_framebuffer_ensure_config(&fbl->mist_accum_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->mist_accum) + }); + + /* Clear texture. */ + GPU_framebuffer_bind(fbl->mist_accum_fb); + GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); + + /* Mist settings. */ + if (scene && scene->world) { + g_data->mist_start = scene->world->miststa; + g_data->mist_inv_dist = (scene->world->mistdist > 0.0f) ? 1.0f / scene->world->mistdist : 0.0f; + + switch (scene->world->mistype) { + case WO_MIST_QUADRATIC: + g_data->mist_falloff = 2.0f; + break; + case WO_MIST_LINEAR: + g_data->mist_falloff = 1.0f; + break; + case WO_MIST_INVERSE_QUADRATIC: + g_data->mist_falloff = 0.5f; + break; + } + } + else { + float near = -sldata->common_data.view_vecs[0][2]; + float range = sldata->common_data.view_vecs[1][2]; + /* Fallback */ + g_data->mist_start = near; + g_data->mist_inv_dist = 1.0f / fabsf(range); + g_data->mist_falloff = 1.0f; + } + + /* XXX ??!! WHY? If not it does not match cycles. */ + g_data->mist_falloff *= 0.5f; + + /* Create Pass and shgroup. */ + psl->mist_accum_ps = DRW_pass_create("Mist Accum", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); +} + +void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + + if (fbl->mist_accum_fb != NULL) { + GPU_framebuffer_bind(fbl->mist_accum_fb); + DRW_draw_pass(psl->mist_accum_ps); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + +void EEVEE_mist_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.mist_sh); +} diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c new file mode 100644 index 00000000000..b2ea9ff4229 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -0,0 +1,215 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_motion_blur.c + * \ingroup draw_engine + * + * Gather all screen space effects technique such as Bloom, Motion Blur, DoF, SSAO, SSR, ... + */ + +#include "DRW_render.h" + +#include "BKE_global.h" /* for G.debug_value */ +#include "BKE_camera.h" +#include "BKE_object.h" +#include "BKE_animsys.h" +#include "BKE_screen.h" + +#include "DNA_anim_types.h" +#include "DNA_camera_types.h" +#include "DNA_screen_types.h" + +#include "ED_screen.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "eevee_private.h" +#include "GPU_texture.h" + +static struct { + /* Motion Blur */ + struct GPUShader *motion_blur_sh; +} e_data = {NULL}; /* Engine data */ + +extern char datatoc_effect_motion_blur_frag_glsl[]; + +static void eevee_motion_blur_camera_get_matrix_at_time( + Scene *scene, + ARegion *ar, RegionView3D *rv3d, View3D *v3d, + Object *camera, + float time, + float r_mat[4][4]) +{ + float obmat[4][4]; + + /* HACK */ + Object cam_cpy; Camera camdata_cpy; + memcpy(&cam_cpy, camera, sizeof(cam_cpy)); + memcpy(&camdata_cpy, camera->data, sizeof(camdata_cpy)); + cam_cpy.data = &camdata_cpy; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + + /* Past matrix */ + /* FIXME : This is a temporal solution that does not take care of parent animations */ + /* Recalc Anim manualy */ + BKE_animsys_evaluate_animdata(scene, &cam_cpy.id, cam_cpy.adt, time, ADT_RECALC_ALL); + BKE_animsys_evaluate_animdata(scene, &camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL); + BKE_object_where_is_calc_time(draw_ctx->depsgraph, scene, &cam_cpy, time); + + /* Compute winmat */ + CameraParams params; + BKE_camera_params_init(¶ms); + + if (v3d != NULL) { + BKE_camera_params_from_view3d(¶ms, draw_ctx->depsgraph, v3d, rv3d); + BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, 1.0f, 1.0f); + } + else { + BKE_camera_params_from_object(¶ms, &cam_cpy); + BKE_camera_params_compute_viewplane(¶ms, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp); + } + + BKE_camera_params_compute_matrix(¶ms); + + /* FIXME Should be done per view (MULTIVIEW) */ + normalize_m4_m4(obmat, cam_cpy.obmat); + invert_m4(obmat); + mul_m4_m4m4(r_mat, params.winmat, obmat); +} + +static void eevee_create_shader_motion_blur(void) +{ + e_data.motion_blur_sh = DRW_shader_create_fullscreen(datatoc_effect_motion_blur_frag_glsl, NULL); +} + +int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + Scene *scene = draw_ctx->scene; + + View3D *v3d = draw_ctx->v3d; + RegionView3D *rv3d = draw_ctx->rv3d; + ARegion *ar = draw_ctx->ar; + + if (scene_eval->eevee.flag & SCE_EEVEE_MOTION_BLUR_ENABLED) { + /* Update Motion Blur Matrices */ + if (camera) { + float persmat[4][4]; + float ctime = DEG_get_ctime(draw_ctx->depsgraph); + float delta = scene_eval->eevee.motion_blur_shutter; + Object *ob_camera_eval = DEG_get_evaluated_object(draw_ctx->depsgraph, camera); + + /* Current matrix */ + eevee_motion_blur_camera_get_matrix_at_time( + scene, + ar, rv3d, v3d, + ob_camera_eval, + ctime, + effects->current_ndc_to_world); + + /* Viewport Matrix */ + DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); + + /* Only continue if camera is not being keyed */ + if (DRW_state_is_image_render() || + compare_m4m4(persmat, effects->current_ndc_to_world, 0.0001f)) + { + /* Past matrix */ + eevee_motion_blur_camera_get_matrix_at_time( + scene, + ar, rv3d, v3d, + ob_camera_eval, + ctime - delta, + effects->past_world_to_ndc); + +#if 0 /* for future high quality blur */ + /* Future matrix */ + eevee_motion_blur_camera_get_matrix_at_time( + scene, + ar, rv3d, v3d, + ob_camera_eval, + ctime + delta, + effects->future_world_to_ndc); +#endif + invert_m4(effects->current_ndc_to_world); + + effects->motion_blur_samples = scene_eval->eevee.motion_blur_samples; + + if (!e_data.motion_blur_sh) { + eevee_create_shader_motion_blur(); + } + + return EFFECT_MOTION_BLUR | EFFECT_POST_BUFFER; + } + } + } + + return 0; +} + +void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + + if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) { + psl->motion_blur = DRW_pass_create("Motion Blur", DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.motion_blur_sh, psl->motion_blur); + DRW_shgroup_uniform_int(grp, "samples", &effects->motion_blur_samples, 1); + DRW_shgroup_uniform_mat4(grp, "currInvViewProjMatrix", effects->current_ndc_to_world); + DRW_shgroup_uniform_mat4(grp, "pastViewProjMatrix", effects->past_world_to_ndc); + DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_call_add(grp, quad, NULL); + } +} + +void EEVEE_motion_blur_draw(EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + /* Motion Blur */ + if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) { + GPU_framebuffer_bind(effects->target_buffer); + DRW_draw_pass(psl->motion_blur); + SWAP_BUFFERS(); + } +} + +void EEVEE_motion_blur_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.motion_blur_sh); +} diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c new file mode 100644 index 00000000000..f39fbe33a71 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -0,0 +1,305 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_occlusion.c + * \ingroup draw_engine + * + * Implementation of the screen space Ground Truth Ambient Occlusion. + */ + +#include "DRW_render.h" + +#include "BLI_string_utils.h" + +#include "DNA_anim_types.h" + +#include "DEG_depsgraph_query.h" + +#include "BKE_global.h" /* for G.debug_value */ + +#include "eevee_private.h" + +static struct { + /* Ground Truth Ambient Occlusion */ + struct GPUShader *gtao_sh; + struct GPUShader *gtao_layer_sh; + struct GPUShader *gtao_debug_sh; + struct GPUTexture *src_depth; +} e_data = {NULL}; /* Engine data */ + +extern char datatoc_ambient_occlusion_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_effect_gtao_frag_glsl[]; + +static void eevee_create_shader_occlusion(void) +{ + char *frag_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_effect_gtao_frag_glsl); + + e_data.gtao_sh = DRW_shader_create_fullscreen(frag_str, NULL); + e_data.gtao_layer_sh = DRW_shader_create_fullscreen(frag_str, "#define LAYERED_DEPTH\n"); + e_data.gtao_debug_sh = DRW_shader_create_fullscreen(frag_str, "#define DEBUG_AO\n"); + + MEM_freeN(frag_str); +} + +int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) { + const float *viewport_size = DRW_viewport_size_get(); + const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + /* Shaders */ + if (!e_data.gtao_sh) { + eevee_create_shader_occlusion(); + } + + common_data->ao_dist = scene_eval->eevee.gtao_distance; + common_data->ao_factor = scene_eval->eevee.gtao_factor; + common_data->ao_quality = 1.0f - scene_eval->eevee.gtao_quality; + + common_data->ao_settings = 1.0f; /* USE_AO */ + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_BENT_NORMALS) { + common_data->ao_settings += 2.0f; /* USE_BENT_NORMAL */ + } + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_BOUNCE) { + common_data->ao_settings += 4.0f; /* USE_DENOISE */ + } + + common_data->ao_bounce_fac = (scene_eval->eevee.flag & SCE_EEVEE_GTAO_BOUNCE) ? 1.0f : 0.0f; + + effects->gtao_horizons = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA8, + &draw_engine_eevee_type); + GPU_framebuffer_ensure_config(&fbl->gtao_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->gtao_horizons) + }); + + if (G.debug_value == 6) { + effects->gtao_horizons_debug = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA8, + &draw_engine_eevee_type); + GPU_framebuffer_ensure_config(&fbl->gtao_debug_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->gtao_horizons_debug) + }); + } + else { + effects->gtao_horizons_debug = NULL; + } + + return EFFECT_GTAO | EFFECT_NORMAL_BUFFER; + } + + /* Cleanup */ + effects->gtao_horizons = NULL; + GPU_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb); + common_data->ao_settings = 0.0f; + + return 0; +} + +void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = stl->effects; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + DRW_texture_ensure_fullscreen_2D(&txl->ao_accum, GPU_R32F, 0); /* Should be enough precision for many samples. */ + + GPU_framebuffer_ensure_config(&fbl->ao_accum_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->ao_accum) + }); + + /* Clear texture. */ + GPU_framebuffer_bind(fbl->ao_accum_fb); + GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); + + /* Accumulation pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; + psl->ao_accum_ps = DRW_pass_create("AO Accum", state); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_accum_ps); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); + DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + else { + /* Cleanup to release memory */ + DRW_TEXTURE_FREE_SAFE(txl->ao_accum); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->ao_accum_fb); + } +} + +void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + + if ((effects->enabled_effects & EFFECT_GTAO) != 0) { + /** Occlusion algorithm overview + * + * We separate the computation into 2 steps. + * + * - First we scan the neighborhood pixels to find the maximum horizon angle. + * We save this angle in a RG8 array texture. + * + * - Then we use this angle to compute occlusion with the shading normal at + * the shading stage. This let us do correct shadowing for each diffuse / specular + * lobe present in the shader using the correct normal. + **/ + psl->ao_horizon_search = DRW_pass_create("GTAO Horizon Search", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_sh, psl->ao_horizon_search); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->ao_horizon_search_layer = DRW_pass_create("GTAO Horizon Search Layer", DRW_STATE_WRITE_COLOR); + grp = DRW_shgroup_create(e_data.gtao_layer_sh, psl->ao_horizon_search_layer); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); + DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1); + DRW_shgroup_call_add(grp, quad, NULL); + + if (G.debug_value == 6) { + psl->ao_horizon_debug = DRW_pass_create("GTAO Horizon Debug", DRW_STATE_WRITE_COLOR); + grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_horizon_debug); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); + DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_call_add(grp, quad, NULL); + } + } +} + +void EEVEE_occlusion_compute( + EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & EFFECT_GTAO) != 0) { + DRW_stats_group_start("GTAO Horizon Scan"); + effects->ao_src_depth = depth_src; + effects->ao_depth_layer = layer; + + GPU_framebuffer_bind(fbl->gtao_fb); + + if (layer >= 0) { + DRW_draw_pass(psl->ao_horizon_search_layer); + } + else { + DRW_draw_pass(psl->ao_horizon_search); + } + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + + DRW_stats_group_end(); + } +} + +void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if (((effects->enabled_effects & EFFECT_GTAO) != 0) && (G.debug_value == 6)) { + DRW_stats_group_start("GTAO Debug"); + + GPU_framebuffer_bind(fbl->gtao_debug_fb); + DRW_draw_pass(psl->ao_horizon_debug); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + + DRW_stats_group_end(); + } +} + +void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + + if (fbl->ao_accum_fb != NULL) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + /* Update the min_max/horizon buffers so the refracion materials appear in it. */ + EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1); + EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1); + + GPU_framebuffer_bind(fbl->ao_accum_fb); + DRW_draw_pass(psl->ao_accum_ps); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + +void EEVEE_occlusion_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.gtao_sh); + DRW_SHADER_FREE_SAFE(e_data.gtao_layer_sh); + DRW_SHADER_FREE_SAFE(e_data.gtao_debug_sh); +} diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h new file mode 100644 index 00000000000..8aca79255b0 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -0,0 +1,991 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_private.h + * \ingroup DNA + */ + +#ifndef __EEVEE_PRIVATE_H__ +#define __EEVEE_PRIVATE_H__ + +struct Object; +struct EEVEE_BoundSphere; +struct EEVEE_ShadowCasterBuffer; +struct RenderLayer; +struct RenderResult; + +extern struct DrawEngineType draw_engine_eevee_type; + +/* Minimum UBO is 16384 bytes */ +#define MAX_PROBE 128 /* TODO : find size by dividing UBO max size by probe data size */ +#define MAX_GRID 64 /* TODO : find size by dividing UBO max size by grid data size */ +#define MAX_PLANAR 16 /* TODO : find size by dividing UBO max size by grid data size */ +#define MAX_LIGHT 128 /* TODO : find size by dividing UBO max size by light data size */ +#define MAX_CASCADE_NUM 4 +#define MAX_SHADOW 256 /* TODO : Make this depends on GL_MAX_ARRAY_TEXTURE_LAYERS */ +#define MAX_SHADOW_CASCADE 8 +#define MAX_SHADOW_CUBE (MAX_SHADOW - MAX_CASCADE_NUM * MAX_SHADOW_CASCADE) +#define MAX_BLOOM_STEP 16 + +/* Only define one of these. */ +// #define IRRADIANCE_SH_L2 +// #define IRRADIANCE_CUBEMAP +#define IRRADIANCE_HL2 + +#if defined(IRRADIANCE_SH_L2) +# define SHADER_IRRADIANCE "#define IRRADIANCE_SH_L2\n" +#elif defined(IRRADIANCE_CUBEMAP) +# define SHADER_IRRADIANCE "#define IRRADIANCE_CUBEMAP\n" +#elif defined(IRRADIANCE_HL2) +# define SHADER_IRRADIANCE "#define IRRADIANCE_HL2\n" +#endif + +#define SHADER_DEFINES \ + "#define EEVEE_ENGINE\n" \ + "#define MAX_PROBE " STRINGIFY(MAX_PROBE) "\n" \ + "#define MAX_GRID " STRINGIFY(MAX_GRID) "\n" \ + "#define MAX_PLANAR " STRINGIFY(MAX_PLANAR) "\n" \ + "#define MAX_LIGHT " STRINGIFY(MAX_LIGHT) "\n" \ + "#define MAX_SHADOW " STRINGIFY(MAX_SHADOW) "\n" \ + "#define MAX_SHADOW_CUBE " STRINGIFY(MAX_SHADOW_CUBE) "\n" \ + "#define MAX_SHADOW_CASCADE " STRINGIFY(MAX_SHADOW_CASCADE) "\n" \ + "#define MAX_CASCADE_NUM " STRINGIFY(MAX_CASCADE_NUM) "\n" \ + SHADER_IRRADIANCE + +#define SWAP_DOUBLE_BUFFERS() { \ + if (effects->swap_double_buffer) { \ + SWAP(struct GPUFrameBuffer *, fbl->main_fb, fbl->double_buffer_fb); \ + SWAP(struct GPUFrameBuffer *, fbl->main_color_fb, fbl->double_buffer_color_fb); \ + SWAP(GPUTexture *, txl->color, txl->color_double_buffer); \ + effects->swap_double_buffer = false; \ + } \ +} ((void)0) + +#define SWAP_BUFFERS() { \ + if (effects->target_buffer == fbl->effect_color_fb) { \ + SWAP_DOUBLE_BUFFERS(); \ + effects->source_buffer = txl->color_post; \ + effects->target_buffer = fbl->main_color_fb; \ + } \ + else { \ + SWAP_DOUBLE_BUFFERS(); \ + effects->source_buffer = txl->color; \ + effects->target_buffer = fbl->effect_color_fb; \ + } \ +} ((void)0) + +#define OVERLAY_ENABLED(v3d) ((v3d) && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) +#define LOOK_DEV_MODE_ENABLED(v3d) ((v3d) && (v3d->drawtype == OB_MATERIAL)) +#define LOOK_DEV_OVERLAY_ENABLED(v3d) (LOOK_DEV_MODE_ENABLED(v3d) && OVERLAY_ENABLED(v3d) && ((v3d->overlay.flag & V3D_OVERLAY_LOOK_DEV) > 0)) +#define USE_SCENE_LIGHT(v3d) ((!v3d) || (!LOOK_DEV_MODE_ENABLED(v3d)) || ((LOOK_DEV_MODE_ENABLED(v3d) && (v3d->shading.flag & V3D_SHADING_SCENE_LIGHT)))) + +/* World shader variations */ +enum { + VAR_WORLD_BACKGROUND = 0, + VAR_WORLD_PROBE = 1, + VAR_WORLD_VOLUME = 2, +}; + +/* Material shader variations */ +enum { + VAR_MAT_MESH = (1 << 0), + VAR_MAT_PROBE = (1 << 1), + VAR_MAT_HAIR = (1 << 2), + VAR_MAT_FLAT = (1 << 3), + VAR_MAT_BLEND = (1 << 4), + VAR_MAT_VSM = (1 << 5), + VAR_MAT_ESM = (1 << 6), + VAR_MAT_VOLUME = (1 << 7), + VAR_MAT_LOOKDEV = (1 << 8), + /* Max number of variation */ + /* IMPORTANT : Leave it last and set + * it's value accordingly. */ + VAR_MAT_MAX = (1 << 9), + /* These are options that are not counted in VAR_MAT_MAX + * because they are not cumulative with the others above. */ + VAR_MAT_CLIP = (1 << 10), + VAR_MAT_HASH = (1 << 11), + VAR_MAT_MULT = (1 << 12), + VAR_MAT_SHADOW = (1 << 13), + VAR_MAT_REFRACT = (1 << 14), + VAR_MAT_SSS = (1 << 15), + VAR_MAT_TRANSLUC = (1 << 16), + VAR_MAT_SSSALBED = (1 << 17), +}; + +typedef struct EEVEE_BoundSphere { + float center[3], radius; +} EEVEE_BoundSphere; + +typedef struct EEVEE_BoundBox { + float center[3], halfdim[3]; +} EEVEE_BoundBox; + +typedef struct EEVEE_PassList { + /* Shadows */ + struct DRWPass *shadow_pass; + struct DRWPass *shadow_cube_copy_pass; + struct DRWPass *shadow_cube_store_pass; + struct DRWPass *shadow_cascade_copy_pass; + struct DRWPass *shadow_cascade_store_pass; + + /* Probes */ + struct DRWPass *probe_background; + struct DRWPass *probe_glossy_compute; + struct DRWPass *probe_diffuse_compute; + struct DRWPass *probe_visibility_compute; + struct DRWPass *probe_grid_fill; + struct DRWPass *probe_display; + struct DRWPass *probe_planar_downsample_ps; + + /* Effects */ + struct DRWPass *ao_horizon_search; + struct DRWPass *ao_horizon_search_layer; + struct DRWPass *ao_horizon_debug; + struct DRWPass *ao_accum_ps; + struct DRWPass *mist_accum_ps; + struct DRWPass *motion_blur; + struct DRWPass *bloom_blit; + struct DRWPass *bloom_downsample_first; + struct DRWPass *bloom_downsample; + struct DRWPass *bloom_upsample; + struct DRWPass *bloom_resolve; + struct DRWPass *dof_down; + struct DRWPass *dof_scatter; + struct DRWPass *dof_resolve; + struct DRWPass *volumetric_world_ps; + struct DRWPass *volumetric_objects_ps; + struct DRWPass *volumetric_scatter_ps; + struct DRWPass *volumetric_integration_ps; + struct DRWPass *volumetric_resolve_ps; + struct DRWPass *ssr_raytrace; + struct DRWPass *ssr_resolve; + struct DRWPass *sss_blur_ps; + struct DRWPass *sss_resolve_ps; + struct DRWPass *sss_accum_ps; + struct DRWPass *color_downsample_ps; + struct DRWPass *color_downsample_cube_ps; + struct DRWPass *velocity_resolve; + struct DRWPass *taa_resolve; + + /* HiZ */ + struct DRWPass *minz_downlevel_ps; + struct DRWPass *maxz_downlevel_ps; + struct DRWPass *minz_downdepth_ps; + struct DRWPass *maxz_downdepth_ps; + struct DRWPass *minz_downdepth_layer_ps; + struct DRWPass *maxz_downdepth_layer_ps; + struct DRWPass *minz_copydepth_ps; + struct DRWPass *maxz_copydepth_ps; + + struct DRWPass *depth_pass; + struct DRWPass *depth_pass_cull; + struct DRWPass *depth_pass_clip; + struct DRWPass *depth_pass_clip_cull; + struct DRWPass *refract_depth_pass; + struct DRWPass *refract_depth_pass_cull; + struct DRWPass *refract_depth_pass_clip; + struct DRWPass *refract_depth_pass_clip_cull; + struct DRWPass *default_pass[VAR_MAT_MAX]; + struct DRWPass *sss_pass; + struct DRWPass *material_pass; + struct DRWPass *refract_pass; + struct DRWPass *transparent_pass; + struct DRWPass *background_pass; + struct DRWPass *update_noise_pass; + struct DRWPass *lookdev_pass; + struct DRWPass *hair_tf_pass; +} EEVEE_PassList; + +typedef struct EEVEE_FramebufferList { + /* Effects */ + struct GPUFrameBuffer *gtao_fb; + struct GPUFrameBuffer *gtao_debug_fb; + struct GPUFrameBuffer *downsample_fb; + struct GPUFrameBuffer *bloom_blit_fb; + struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP]; + struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP - 1]; + struct GPUFrameBuffer *sss_blur_fb; + struct GPUFrameBuffer *sss_resolve_fb; + struct GPUFrameBuffer *sss_clear_fb; + struct GPUFrameBuffer *sss_accum_fb; + struct GPUFrameBuffer *dof_down_fb; + struct GPUFrameBuffer *dof_scatter_fb; + struct GPUFrameBuffer *volumetric_fb; + struct GPUFrameBuffer *volumetric_scat_fb; + struct GPUFrameBuffer *volumetric_integ_fb; + struct GPUFrameBuffer *screen_tracing_fb; + struct GPUFrameBuffer *refract_fb; + struct GPUFrameBuffer *mist_accum_fb; + struct GPUFrameBuffer *ao_accum_fb; + struct GPUFrameBuffer *velocity_resolve_fb; + + struct GPUFrameBuffer *update_noise_fb; + + struct GPUFrameBuffer *planarref_fb; + struct GPUFrameBuffer *planar_downsample_fb; + + struct GPUFrameBuffer *main_fb; + struct GPUFrameBuffer *main_color_fb; + struct GPUFrameBuffer *effect_fb; + struct GPUFrameBuffer *effect_color_fb; + struct GPUFrameBuffer *double_buffer_fb; + struct GPUFrameBuffer *double_buffer_color_fb; + struct GPUFrameBuffer *double_buffer_depth_fb; +} EEVEE_FramebufferList; + +typedef struct EEVEE_TextureList { + /* Effects */ + struct GPUTexture *color_post; /* R16_G16_B16 */ + struct GPUTexture *mist_accum; + struct GPUTexture *ao_accum; + struct GPUTexture *sss_dir_accum; + struct GPUTexture *sss_col_accum; + struct GPUTexture *refract_color; + + struct GPUTexture *volume_prop_scattering; + struct GPUTexture *volume_prop_extinction; + struct GPUTexture *volume_prop_emission; + struct GPUTexture *volume_prop_phase; + struct GPUTexture *volume_scatter; + struct GPUTexture *volume_transmittance; + struct GPUTexture *volume_scatter_history; + struct GPUTexture *volume_transmittance_history; + + struct GPUTexture *planar_pool; + struct GPUTexture *planar_depth; + + struct GPUTexture *maxzbuffer; + + struct GPUTexture *color; /* R16_G16_B16 */ + struct GPUTexture *color_double_buffer; + struct GPUTexture *depth_double_buffer; +} EEVEE_TextureList; + +typedef struct EEVEE_StorageList { + /* Effects */ + struct EEVEE_EffectsInfo *effects; + + struct EEVEE_PrivateData *g_data; + +} EEVEE_StorageList; + +/* ************ LIGHT UBO ************* */ +typedef struct EEVEE_Light { + float position[3], dist; + float color[3], spec; + float spotsize, spotblend, radius, shadowid; + float rightvec[3], sizex; + float upvec[3], sizey; + float forwardvec[3], lamptype; +} EEVEE_Light; + +/* Special type for elliptic area lamps, matches lamps_lib.glsl */ +#define LAMPTYPE_AREA_ELLIPSE 100.0f + +typedef struct EEVEE_Shadow { + float near, far, bias, exp; + float shadow_start, data_start, multi_shadow_count, shadow_blur; + float contact_dist, contact_bias, contact_spread, contact_thickness; +} EEVEE_Shadow; + +typedef struct EEVEE_ShadowCube { + float position[3], pad; +} EEVEE_ShadowCube; + +typedef struct EEVEE_ShadowCascade { + float shadowmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */ + float split_start[4]; + float split_end[4]; +} EEVEE_ShadowCascade; + +typedef struct EEVEE_ShadowRender { + float position[3], pad; + float cube_texel_size; + float stored_texel_size; + float clip_near; + float clip_far; + int shadow_samples_ct; + float shadow_inv_samples_ct; +} EEVEE_ShadowRender; + +/* This is just a really long bitflag with special function to access it. */ +#define MAX_LIGHTBITS_FIELDS (MAX_LIGHT / 8) +typedef struct EEVEE_LightBits { + unsigned char fields[MAX_LIGHTBITS_FIELDS]; +} EEVEE_LightBits; + +typedef struct EEVEE_ShadowCaster { + struct EEVEE_LightBits bits; + struct EEVEE_BoundBox bbox; +} EEVEE_ShadowCaster; + +typedef struct EEVEE_ShadowCasterBuffer { + struct EEVEE_ShadowCaster *shadow_casters; + char *flags; + uint alloc_count; + uint count; +} EEVEE_ShadowCasterBuffer; + +/* ************ LIGHT DATA ************* */ +typedef struct EEVEE_LampsInfo { + int num_light, cache_num_light; + int num_cube_layer, cache_num_cube_layer; + int num_cascade_layer, cache_num_cascade_layer; + int gpu_cube_ct, gpu_cascade_ct, gpu_shadow_ct; + int cpu_cube_ct, cpu_cascade_ct; + int update_flag; + int shadow_cube_size, shadow_cascade_size, shadow_method; + bool shadow_high_bitdepth; + int shadow_cube_store_size; + int current_shadow_cascade; + int current_shadow_face; + uint shadow_instance_count; + float filter_size; + /* List of lights in the scene. */ + /* XXX This is fragile, can get out of sync quickly. */ + struct Object *light_ref[MAX_LIGHT]; + struct Object *shadow_cube_ref[MAX_SHADOW_CUBE]; + struct Object *shadow_cascade_ref[MAX_SHADOW_CASCADE]; + /* UBO Storage : data used by UBO */ + struct EEVEE_Light light_data[MAX_LIGHT]; + struct EEVEE_ShadowRender shadow_render_data; + struct EEVEE_Shadow shadow_data[MAX_SHADOW]; + struct EEVEE_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE]; + struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE]; + /* Lights tracking */ + int new_shadow_id[MAX_LIGHT]; /* To be able to convert old bitfield to new bitfield */ + struct EEVEE_BoundSphere shadow_bounds[MAX_LIGHT]; /* Tighly packed light bounds */ + /* Pointers only. */ + struct EEVEE_ShadowCasterBuffer *shcaster_frontbuffer; + struct EEVEE_ShadowCasterBuffer *shcaster_backbuffer; +} EEVEE_LampsInfo; + +/* EEVEE_LampsInfo->shadow_casters_flag */ +enum { + SHADOW_CASTER_PRUNED = (1 << 0), + SHADOW_CASTER_UPDATED = (1 << 1), +}; + +/* EEVEE_LampsInfo->update_flag */ +enum { + LIGHT_UPDATE_SHADOW_CUBE = (1 << 0), +}; + +/* ************ PROBE UBO ************* */ +typedef struct EEVEE_LightProbe { + float position[3], parallax_type; + float attenuation_fac; + float attenuation_type; + float pad3[2]; + float attenuationmat[4][4]; + float parallaxmat[4][4]; +} EEVEE_LightProbe; + +typedef struct EEVEE_LightGrid { + float mat[4][4]; + int resolution[3], offset; + float corner[3], attenuation_scale; + float increment_x[3], attenuation_bias; /* world space vector between 2 opposite cells */ + float increment_y[3], level_bias; + float increment_z[3], pad4; + float visibility_bias, visibility_bleed, visibility_range, pad5; +} EEVEE_LightGrid; + +typedef struct EEVEE_PlanarReflection { + float plane_equation[4]; + float clip_vec_x[3], attenuation_scale; + float clip_vec_y[3], attenuation_bias; + float clip_edge_x_pos, clip_edge_x_neg; + float clip_edge_y_pos, clip_edge_y_neg; + float facing_scale, facing_bias, pad[2]; + float reflectionmat[4][4]; +} EEVEE_PlanarReflection; + +/* ************ PROBE DATA ************* */ + +typedef struct EEVEE_LightProbeVisTest { + bool invert; + bool cached; /* Reuse last test results */ + struct Collection *collection; /* Skip test if NULL */ +} EEVEE_LightProbeVisTest; + +typedef struct EEVEE_LightProbesInfo { + int num_cube, cache_num_cube; + int num_grid, cache_num_grid; + int num_planar, cache_num_planar; + int total_irradiance_samples; /* Total for all grids */ + int cache_irradiance_size[3]; + int update_flag; + int updated_bounce; + int num_bounce; + int cubemap_res; + int target_size; + int grid_initialized; + struct World *prev_world; + int update_world; + bool prev_wo_sh_compiled; + bool do_cube_update; + bool all_materials_updated; + /* For rendering probes */ + float probemat[6][4][4]; + int layer; + float texel_size; + float padding_size; + float samples_ct; + float invsamples_ct; + float near_clip; + float far_clip; + float roughness; + float lodfactor; + float lod_rt_max, lod_cube_max, lod_planar_max; + float visibility_range; + float visibility_blur; + float intensity_fac; + int shres; + int studiolight_index; + float studiolight_rot_z; + /* List of probes in the scene. */ + /* XXX This is fragile, can get out of sync quickly. */ + struct Object *probes_cube_ref[MAX_PROBE]; + struct Object *probes_grid_ref[MAX_GRID]; + struct Object *probes_planar_ref[MAX_PLANAR]; + /* UBO Storage : data used by UBO */ + struct EEVEE_LightProbe probe_data[MAX_PROBE]; + struct EEVEE_LightGrid grid_data[MAX_GRID]; + struct EEVEE_PlanarReflection planar_data[MAX_PLANAR]; + /* Probe Visibility Collection */ + EEVEE_LightProbeVisTest vis_data; +} EEVEE_LightProbesInfo; + +/* EEVEE_LightProbesInfo->update_flag */ +enum { + PROBE_UPDATE_CUBE = (1 << 0), + PROBE_UPDATE_GRID = (1 << 1), + PROBE_UPDATE_ALL = 0xFFFFFF, +}; + +/* ************ EFFECTS DATA ************* */ + +typedef enum EEVEE_EffectsFlag { + EFFECT_MOTION_BLUR = (1 << 0), + EFFECT_BLOOM = (1 << 1), + EFFECT_DOF = (1 << 2), + EFFECT_VOLUMETRIC = (1 << 3), + EFFECT_SSR = (1 << 4), + EFFECT_DOUBLE_BUFFER = (1 << 5), /* Not really an effect but a feature */ + EFFECT_REFRACT = (1 << 6), + EFFECT_GTAO = (1 << 7), + EFFECT_TAA = (1 << 8), + EFFECT_POST_BUFFER = (1 << 9), /* Not really an effect but a feature */ + EFFECT_NORMAL_BUFFER = (1 << 10), /* Not really an effect but a feature */ + EFFECT_SSS = (1 << 11), + EFFECT_VELOCITY_BUFFER = (1 << 12), /* Not really an effect but a feature */ + EFFECT_TAA_REPROJECT = (1 << 13), /* should be mutually exclusive with EFFECT_TAA */ + EFFECT_DEPTH_DOUBLE_BUFFER = (1 << 14), /* Not really an effect but a feature */ +} EEVEE_EffectsFlag; + +typedef struct EEVEE_EffectsInfo { + EEVEE_EffectsFlag enabled_effects; + bool swap_double_buffer; + /* SSSS */ + int sss_sample_count; + bool sss_separate_albedo; + struct GPUTexture *sss_data; /* Textures from pool */ + struct GPUTexture *sss_albedo; + struct GPUTexture *sss_blur; + struct GPUTexture *sss_stencil; + /* Volumetrics */ + int volume_current_sample; + /* SSR */ + bool reflection_trace_full; + int ssr_neighbor_ofs; + int ssr_halfres_ofs[2]; + struct GPUTexture *ssr_normal_input; /* Textures from pool */ + struct GPUTexture *ssr_specrough_input; + struct GPUTexture *ssr_hit_output; + struct GPUTexture *ssr_pdf_output; + /* Temporal Anti Aliasing */ + int taa_reproject_sample; + int taa_current_sample; + int taa_render_sample; + int taa_total_sample; + float taa_alpha; + bool prev_drw_support; + float prev_drw_persmat[4][4]; + float overide_persmat[4][4]; + float overide_persinv[4][4]; + float overide_winmat[4][4]; + float overide_wininv[4][4]; + /* Ambient Occlusion */ + int ao_depth_layer; + struct GPUTexture *ao_src_depth; /* pointer copy */ + struct GPUTexture *gtao_horizons; /* Textures from pool */ + struct GPUTexture *gtao_horizons_debug; + /* Motion Blur */ + float current_ndc_to_world[4][4]; + float past_world_to_ndc[4][4]; + int motion_blur_samples; + /* Velocity Pass */ + float velocity_curr_persinv[4][4]; + float velocity_past_persmat[4][4]; + struct GPUTexture *velocity_tx; /* Texture from pool */ + /* Depth Of Field */ + float dof_near_far[2]; + float dof_params[3]; + float dof_bokeh[4]; + float dof_bokeh_sides[4]; + int dof_target_size[2]; + struct GPUTexture *dof_down_near; /* Textures from pool */ + struct GPUTexture *dof_down_far; + struct GPUTexture *dof_coc; + struct GPUTexture *dof_blur; + /* Other */ + float prev_persmat[4][4]; + /* Bloom */ + int bloom_iteration_ct; + float source_texel_size[2]; + float blit_texel_size[2]; + float downsamp_texel_size[MAX_BLOOM_STEP][2]; + float bloom_color[3]; + float bloom_clamp; + float bloom_sample_scale; + float bloom_curve_threshold[4]; + float unf_source_texel_size[2]; + struct GPUTexture *bloom_blit; /* Textures from pool */ + struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP]; + struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1]; + struct GPUTexture *unf_source_buffer; /* pointer copy */ + struct GPUTexture *unf_base_buffer; /* pointer copy */ + /* Not alloced, just a copy of a *GPUtexture in EEVEE_TextureList. */ + struct GPUTexture *source_buffer; /* latest updated texture */ + struct GPUFrameBuffer *target_buffer; /* next target to render to */ + struct GPUTexture *final_tx; /* Final color to transform to display color space. */ + struct GPUFrameBuffer *final_fb; /* Framebuffer with final_tx as attachement. */ +} EEVEE_EffectsInfo; + +/* ***************** COMMON DATA **************** */ + +/* Common uniform buffer containing all "constant" data over the whole drawing pipeline. */ +/* !! CAUTION !! + * - [i]vec3 need to be paded to [i]vec4 (even in ubo declaration). + * - Make sure that [i]vec4 start at a multiple of 16 bytes. + * - Arrays of vec2/vec3 are padded as arrays of vec4. + * - sizeof(bool) == sizeof(int) in GLSL so use int in C */ +typedef struct EEVEE_CommonUniformBuffer { + float prev_persmat[4][4]; /* mat4 */ + float view_vecs[2][4]; /* vec4[2] */ + float mip_ratio[10][4]; /* vec2[10] */ + /* Ambient Occlusion */ + /* -- 16 byte aligned -- */ + float ao_dist, pad1, ao_factor, pad2; /* vec4 */ + float ao_offset, ao_bounce_fac, ao_quality, ao_settings; /* vec4 */ + /* Volumetric */ + /* -- 16 byte aligned -- */ + int vol_tex_size[3], pad3; /* ivec3 */ + float vol_depth_param[3], pad4; /* vec3 */ + float vol_inv_tex_size[3], pad5; /* vec3 */ + float vol_jitter[3], pad6; /* vec3 */ + float vol_coord_scale[2], pad7[2]; /* vec2 */ + /* -- 16 byte aligned -- */ + float vol_history_alpha; /* float */ + float vol_light_clamp; /* float */ + float vol_shadow_steps; /* float */ + int vol_use_lights; /* bool */ + /* Screen Space Reflections */ + /* -- 16 byte aligned -- */ + float ssr_quality, ssr_thickness, ssr_pixelsize[2]; /* vec4 */ + float ssr_border_fac; /* float */ + float ssr_max_roughness; /* float */ + float ssr_firefly_fac; /* float */ + float ssr_brdf_bias; /* float */ + int ssr_toggle; /* bool */ + /* SubSurface Scattering */ + float sss_jitter_threshold; /* float */ + int sss_toggle; /* bool */ + /* Specular */ + int spec_toggle; /* bool */ + /* Lamps */ + int la_num_light; /* int */ + /* Probes */ + int prb_num_planar; /* int */ + int prb_num_render_cube; /* int */ + int prb_num_render_grid; /* int */ + int prb_irradiance_vis_size; /* int */ + float prb_lod_cube_max; /* float */ + float prb_lod_planar_max; /* float */ +} EEVEE_CommonUniformBuffer; + +/* ***************** CLIP PLANES DATA **************** */ + +typedef struct EEVEE_ClipPlanesUniformBuffer { + float clip_planes[1][4]; /* must be less than MAX_CLIP_PLANES */ +} EEVEE_ClipPlanesUniformBuffer; + +/* ************** SCENE LAYER DATA ************** */ +typedef struct EEVEE_ViewLayerData { + /* Lamps */ + struct EEVEE_LampsInfo *lamps; + + struct GPUUniformBuffer *light_ubo; + struct GPUUniformBuffer *shadow_ubo; + struct GPUUniformBuffer *shadow_render_ubo; + struct GPUUniformBuffer *shadow_samples_ubo; + + struct GPUFrameBuffer *shadow_cube_target_fb; + struct GPUFrameBuffer *shadow_cube_store_fb; + struct GPUFrameBuffer *shadow_cascade_target_fb; + struct GPUFrameBuffer *shadow_cascade_store_fb; + + struct GPUTexture *shadow_cube_target; + struct GPUTexture *shadow_cube_blur; + struct GPUTexture *shadow_cascade_target; + struct GPUTexture *shadow_cascade_blur; + struct GPUTexture *shadow_cube_pool; + struct GPUTexture *shadow_cascade_pool; + + struct EEVEE_ShadowCasterBuffer shcasters_buffers[2]; + + /* Probes */ + struct EEVEE_LightProbesInfo *probes; + + struct GPUUniformBuffer *probe_ubo; + struct GPUUniformBuffer *grid_ubo; + struct GPUUniformBuffer *planar_ubo; + + struct GPUFrameBuffer *probe_filter_fb; + struct GPUFrameBuffer *probe_face_fb[6]; + + struct GPUTexture *probe_rt; + struct GPUTexture *probe_depth_rt; + struct GPUTexture *probe_pool; + struct GPUTexture *irradiance_pool; + struct GPUTexture *irradiance_rt; + + /* Common Uniform Buffer */ + struct EEVEE_CommonUniformBuffer common_data; + struct GPUUniformBuffer *common_ubo; + + struct EEVEE_ClipPlanesUniformBuffer clip_data; + struct GPUUniformBuffer *clip_ubo; +} EEVEE_ViewLayerData; + +/* ************ OBJECT DATA ************ */ +typedef struct EEVEE_LightData { + short light_id, shadow_id; +} EEVEE_LightData; + +typedef struct EEVEE_ShadowCubeData { + short light_id, shadow_id, cube_id, layer_id; +} EEVEE_ShadowCubeData; + +typedef struct EEVEE_ShadowCascadeData { + short light_id, shadow_id, cascade_id, layer_id; + float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */ + float projmat[MAX_CASCADE_NUM][4][4]; + float viewmat[4][4], viewinv[4][4]; + float radius[MAX_CASCADE_NUM]; +} EEVEE_ShadowCascadeData; + +/* Theses are the structs stored inside Objects. + * It works with even if the object is in multiple layers + * because we don't get the same "Object *" for each layer. */ +typedef struct EEVEE_LampEngineData { + ObjectEngineData engine_data; + + bool need_update; + /* This needs to be out of the union to avoid undefined behaviour. */ + short prev_cube_shadow_id; + union { + struct EEVEE_LightData ld; + struct EEVEE_ShadowCubeData scd; + struct EEVEE_ShadowCascadeData scad; + } data; +} EEVEE_LampEngineData; + +typedef struct EEVEE_LightProbeEngineData { + ObjectEngineData engine_data; + + /* NOTE: need_full_update is set by dependency graph when the probe or it's + * object is updated. This triggers full probe update, including it's + * "progressive" GI refresh. + * + * need_update is always set to truth when need_full_update is tagged, but + * might also be forced to be kept truth during GI refresh stages. + * + * TODO(sergey): Is there a way to avoid two flags here, or at least make + * it more clear what's going on here? + */ + bool need_full_update; + bool need_update; + + bool ready_to_shade; + int updated_cells; + int updated_lvl; + int num_cell; + int max_lvl; + int probe_id; /* Only used for display data */ + float probe_size; /* Only used for display data */ + DRWMatrixState mats; /* For planar probes */ + float planer_eq_offset[4]; + struct ListBase captured_object_list; +} EEVEE_LightProbeEngineData; + +typedef struct EEVEE_ObjectEngineData { + ObjectEngineData engine_data; + + Object *ob; /* self reference */ + EEVEE_LightProbeVisTest *test_data; + bool ob_vis, ob_vis_dirty; + + bool need_update; + uint shadow_caster_id; +} EEVEE_ObjectEngineData; + +/* *********************************** */ + +typedef struct EEVEE_Data { + void *engine_type; + EEVEE_FramebufferList *fbl; + EEVEE_TextureList *txl; + EEVEE_PassList *psl; + EEVEE_StorageList *stl; +} EEVEE_Data; + +typedef struct EEVEE_PrivateData { + struct DRWShadingGroup *shadow_shgrp; + struct DRWShadingGroup *depth_shgrp; + struct DRWShadingGroup *depth_shgrp_cull; + struct DRWShadingGroup *depth_shgrp_clip; + struct DRWShadingGroup *depth_shgrp_clip_cull; + struct DRWShadingGroup *refract_depth_shgrp; + struct DRWShadingGroup *refract_depth_shgrp_cull; + struct DRWShadingGroup *refract_depth_shgrp_clip; + struct DRWShadingGroup *refract_depth_shgrp_clip_cull; + struct DRWShadingGroup *cube_display_shgrp; + struct DRWShadingGroup *planar_display_shgrp; + struct GHash *material_hash; + struct GHash *hair_material_hash; + float background_alpha; /* TODO find a better place for this. */ + /* For planar probes */ + float planar_texel_size[2]; + /* For double buffering */ + bool view_updated; + bool valid_double_buffer; + /* Render Matrices */ + float persmat[4][4], persinv[4][4]; + float viewmat[4][4], viewinv[4][4]; + float winmat[4][4], wininv[4][4]; + float studiolight_matrix[3][3]; + + /* Mist Settings */ + float mist_start, mist_inv_dist, mist_falloff; +} EEVEE_PrivateData; /* Transient data */ + +/* eevee_data.c */ +EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void); +EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void); +EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob); +EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob); +EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob); +EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob); +EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob); +EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob); + +/* eevee_materials.c */ +struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */ +void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl); +void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, bool *cast_shadow); +void EEVEE_materials_cache_finish(EEVEE_Data *vedata); +struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo); +struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo); +struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo); +struct GPUMaterial *EEVEE_material_mesh_get( + struct Scene *scene, Material *ma, EEVEE_Data *vedata, + bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method); +struct GPUMaterial *EEVEE_material_mesh_volume_get( + struct Scene *scene, Material *ma); +struct GPUMaterial *EEVEE_material_mesh_depth_get( + struct Scene *scene, Material *ma, bool use_hashed_alpha, bool is_shadow); +struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method); +void EEVEE_materials_free(void); +void EEVEE_draw_default_passes(EEVEE_PassList *psl); +void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]); + +/* eevee_lights.c */ +void EEVEE_lights_init(EEVEE_ViewLayerData *sldata); +void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, struct Object *ob); +void EEVEE_lights_cache_shcaster_add( + EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, struct Gwn_Batch *geom, Object *ob); +void EEVEE_lights_cache_shcaster_material_add( + EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, + struct GPUMaterial *gpumat, struct Gwn_Batch *geom, struct Object *ob, + float *alpha_threshold); +void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, struct Object *ob); +void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata); +void EEVEE_lights_update(EEVEE_ViewLayerData *sldata); +void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl); +void EEVEE_lights_free(void); + +/* eevee_lightprobes.c */ +bool EEVEE_lightprobes_obj_visibility_cb(bool vis_in, void *user_data); +bool EEVEE_lightprobes_all_probes_ready(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob); +void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_lightprobes_free(void); + +/* eevee_depth_of_field.c */ +int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera); +void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_depth_of_field_draw(EEVEE_Data *vedata); +void EEVEE_depth_of_field_free(void); + +/* eevee_bloom.c */ +int EEVEE_bloom_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_bloom_draw(EEVEE_Data *vedata); +void EEVEE_bloom_free(void); + +/* eevee_occlusion.c */ +int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer); +void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_occlusion_free(void); + +/* eevee_screen_raytrace.c */ +int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_refraction_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_reflection_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_screen_raytrace_free(void); + +/* eevee_subsurface.c */ +int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_subsurface_add_pass( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint sss_id, struct GPUUniformBuffer *sss_profile); +void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_subsurface_free(void); + +/* eevee_motion_blur.c */ +int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera); +void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_motion_blur_draw(EEVEE_Data *vedata); +void EEVEE_motion_blur_free(void); + +/* eevee_mist.c */ +void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);; +void EEVEE_mist_free(void); + +/* eevee_temporal_sampling.c */ +int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_temporal_sampling_matrices_calc( + EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], const double ht_point[2]); +void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata); +void EEVEE_temporal_sampling_free(void); + +/* eevee_volumes.c */ +int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample); +void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct Scene *scene, Object *ob); +void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_volumes_resolve(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_volumes_free_smoke_textures(void); +void EEVEE_volumes_free(void); + +/* eevee_effects.c */ +void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera); +void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer); +void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level); +void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level); +void EEVEE_effects_do_gtao(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_effects_free(void); + +/* eevee_render.c */ +void EEVEE_render_init(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph); +void EEVEE_render_cache(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *depsgraph); +void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct RenderLayer *render_layer, const struct rcti *rect); +void EEVEE_render_update_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer); + +/** eevee_lookdev.c */ +void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, DRWShadingGroup **grp, GPUShader *shader, DRWPass *pass, struct World *world, EEVEE_LightProbesInfo *pinfo); +void EEVEE_lookdev_draw_background(EEVEE_Data *vedata); + +/* Shadow Matrix */ +static const float texcomat[4][4] = { /* From NDC to TexCo */ + {0.5f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.5f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.5f, 0.0f}, + {0.5f, 0.5f, 0.5f, 1.0f} +}; + +/* Cubemap Matrices */ +static const float cubefacemat[6][4][4] = { + /* Pos X */ + {{0.0f, 0.0f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}, + /* Neg X */ + {{0.0f, 0.0f, 1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}, + /* Pos Y */ + {{1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, -1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}, + /* Neg Y */ + {{1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}, + /* Pos Z */ + {{1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, -1.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, -1.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}, + /* Neg Z */ + {{-1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, -1.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 1.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f}}, +}; + +#endif /* __EEVEE_PRIVATE_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c new file mode 100644 index 00000000000..6cb3fa259eb --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -0,0 +1,563 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_render.c + * \ingroup draw_engine + */ + +/** + * Render functions for final render outputs. + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_node_types.h" +#include "DNA_object_types.h" + +#include "BLI_rand.h" +#include "BLI_rect.h" + +#include "DEG_depsgraph_query.h" + +#include "GPU_framebuffer.h" +#include "GPU_glew.h" + +#include "RE_pipeline.h" + +#include "eevee_private.h" + +void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph) +{ + EEVEE_Data *vedata = (EEVEE_Data *)ved; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + Scene *scene = DEG_get_evaluated_scene(depsgraph); + + /* Init default FB and render targets: + * In render mode the default framebuffer is not generated + * because there is no viewport. So we need to manually create it or + * not use it. For code clarity we just allocate it make use of it. */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + /* TODO 32 bit depth */ + DRW_texture_ensure_fullscreen_2D(&dtxl->depth, GPU_DEPTH24_STENCIL8, 0); + DRW_texture_ensure_fullscreen_2D(&txl->color, GPU_RGBA32F, DRW_TEX_FILTER | DRW_TEX_MIPMAP); + + GPU_framebuffer_ensure_config(&dfbl->default_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(txl->color) + }); + GPU_framebuffer_ensure_config(&fbl->main_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(txl->color) + }); + GPU_framebuffer_ensure_config(&fbl->main_color_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->color) + }); + + /* Alloc transient data. */ + if (!stl->g_data) { + stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); + } + EEVEE_PrivateData *g_data = stl->g_data; + g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f; + g_data->valid_double_buffer = 0; + + /* Alloc common ubo data. */ + if (sldata->common_ubo == NULL) { + sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data); + } + if (sldata->clip_ubo == NULL) { + sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data); + } + + /* Set the pers & view matrix. */ + /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */ + struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); + float frame = BKE_scene_frame_get(scene); + RE_GetCameraWindow(engine->re, ob_camera_eval, frame, g_data->winmat); + RE_GetCameraModelMatrix(engine->re, ob_camera_eval, g_data->viewinv); + + invert_m4_m4(g_data->viewmat, g_data->viewinv); + mul_m4_m4m4(g_data->persmat, g_data->winmat, g_data->viewmat); + invert_m4_m4(g_data->persinv, g_data->persmat); + invert_m4_m4(g_data->wininv, g_data->winmat); + + DRW_viewport_matrix_override_set(g_data->persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(g_data->persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(g_data->winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(g_data->wininv, DRW_MAT_WININV); + DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV); + + /* EEVEE_effects_init needs to go first for TAA */ + EEVEE_effects_init(sldata, vedata, ob_camera_eval); + EEVEE_materials_init(sldata, stl, fbl); + EEVEE_lights_init(sldata); + EEVEE_lightprobes_init(sldata, vedata); + + /* INIT CACHE */ + EEVEE_bloom_cache_init(sldata, vedata); + EEVEE_depth_of_field_cache_init(sldata, vedata); + EEVEE_effects_cache_init(sldata, vedata); + EEVEE_lightprobes_cache_init(sldata, vedata); + EEVEE_lights_cache_init(sldata, vedata); + EEVEE_materials_cache_init(sldata, vedata); + EEVEE_motion_blur_cache_init(sldata, vedata); + EEVEE_occlusion_cache_init(sldata, vedata); + EEVEE_screen_raytrace_cache_init(sldata, vedata); + EEVEE_subsurface_cache_init(sldata, vedata); + EEVEE_temporal_sampling_cache_init(sldata, vedata); + EEVEE_volumes_cache_init(sldata, vedata); +} + +void EEVEE_render_cache( + void *vedata, struct Object *ob, + struct RenderEngine *engine, struct Depsgraph *UNUSED(depsgraph)) +{ + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + + char info[42]; + BLI_snprintf(info, sizeof(info), "Syncing %s", ob->id.name + 2); + RE_engine_update_stats(engine, NULL, info); + + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + bool cast_shadow; + + EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); + + if (cast_shadow) { + EEVEE_lights_cache_shcaster_object_add(sldata, ob); + } + } + else if (ob->type == OB_LIGHTPROBE) { + EEVEE_lightprobes_cache_add(sldata, ob); + } + else if (ob->type == OB_LAMP) { + EEVEE_lights_cache_add(sldata, ob); + } +} + +static void eevee_render_result_combined( + RenderLayer *rl, const char *viewname, const rcti *rect, + EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata)) +{ + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname); + + GPU_framebuffer_bind(vedata->stl->effects->final_fb); + GPU_framebuffer_read_color(vedata->stl->effects->final_fb, + rect->xmin, rect->ymin, + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), + 4, 0, rp->rect); +} + +static void eevee_render_result_subsurface( + RenderLayer *rl, const char *viewname, const rcti *rect, + EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata), int render_samples) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + + if (vedata->fbl->sss_accum_fb == NULL) { + /* SSS is not enabled. */ + return; + } + + if ((view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) != 0) { + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_COLOR, viewname); + + GPU_framebuffer_bind(vedata->fbl->sss_accum_fb); + GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb, + rect->xmin, rect->ymin, + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), + 3, 1, rp->rect); + + /* This is the accumulated color. Divide by the number of samples. */ + for (int i = 0; i < rp->rectx * rp->recty * 3; i++) { + rp->rect[i] /= (float)render_samples; + } + } + + if ((view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) != 0) { + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_DIRECT, viewname); + + GPU_framebuffer_bind(vedata->fbl->sss_accum_fb); + GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb, + rect->xmin, rect->ymin, + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), + 3, 0, rp->rect); + + /* This is the accumulated color. Divide by the number of samples. */ + for (int i = 0; i < rp->rectx * rp->recty * 3; i++) { + rp->rect[i] /= (float)render_samples; + } + } + + if ((view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) != 0) { + /* Do nothing as all the lighting is in the direct pass. + * TODO : Separate Direct from indirect lighting. */ + } +} + +static void eevee_render_result_normal( + RenderLayer *rl, const char *viewname, const rcti *rect, + EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata)) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + + /* Only read the center texel. */ + if (stl->effects->taa_current_sample > 1) + return; + + if ((view_layer->passflag & SCE_PASS_NORMAL) != 0) { + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_NORMAL, viewname); + + GPU_framebuffer_bind(vedata->fbl->main_fb); + GPU_framebuffer_read_color(vedata->fbl->main_fb, + rect->xmin, rect->ymin, + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), + 3, 1, rp->rect); + + /* Convert Eevee encoded normals to Blender normals. */ + for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) { + if (rp->rect[i] == 0.0f && rp->rect[i + 1] == 0.0f) { + /* If normal is not correct then do not produce NANs. */ + continue; + } + + float fenc[2]; + fenc[0] = rp->rect[i + 0] * 4.0f - 2.0f; + fenc[1] = rp->rect[i + 1] * 4.0f - 2.0f; + + float f = dot_v2v2(fenc, fenc); + float g = sqrtf(1.0f - f / 4.0f); + + rp->rect[i + 0] = fenc[0] * g; + rp->rect[i + 1] = fenc[1] * g; + rp->rect[i + 2] = 1.0f - f / 2.0f; + + mul_mat3_m4_v3(g_data->viewinv, &rp->rect[i]); + } + } +} + +static void eevee_render_result_z( + RenderLayer *rl, const char *viewname, const rcti *rect, + EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + + /* Only read the center texel. */ + if (stl->effects->taa_current_sample > 1) + return; + + if ((view_layer->passflag & SCE_PASS_Z) != 0) { + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname); + + GPU_framebuffer_bind(vedata->fbl->main_fb); + GPU_framebuffer_read_depth(vedata->fbl->main_fb, + rect->xmin, rect->ymin, + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), + rp->rect); + + bool is_persp = DRW_viewport_is_persp_get(); + + /* Convert ogl depth [0..1] to view Z [near..far] */ + for (int i = 0; i < rp->rectx * rp->recty; ++i) { + if (rp->rect[i] == 1.0f ) { + rp->rect[i] = 1e10f; /* Background */ + } + else { + if (is_persp) { + rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; + rp->rect[i] = g_data->winmat[3][2] / (rp->rect[i] + g_data->winmat[2][2]); + } + else { + rp->rect[i] = -common_data->view_vecs[0][2] + rp->rect[i] * -common_data->view_vecs[1][2]; + } + } + } + } +} + +static void eevee_render_result_mist( + RenderLayer *rl, const char *viewname, const rcti *rect, + EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata), int render_samples) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + + if ((view_layer->passflag & SCE_PASS_MIST) != 0) { + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_MIST, viewname); + + GPU_framebuffer_bind(vedata->fbl->mist_accum_fb); + GPU_framebuffer_read_color(vedata->fbl->mist_accum_fb, + rect->xmin, rect->ymin, + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), + 1, 0, rp->rect); + + /* This is the accumulated color. Divide by the number of samples. */ + for (int i = 0; i < rp->rectx * rp->recty; i++) { + rp->rect[i] /= (float)render_samples; + } + } +} + +static void eevee_render_result_occlusion( + RenderLayer *rl, const char *viewname, const rcti *rect, + EEVEE_Data *vedata, EEVEE_ViewLayerData *UNUSED(sldata), int render_samples) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + + if (vedata->fbl->ao_accum_fb == NULL) { + /* AO is not enabled. */ + return; + } + + if ((view_layer->passflag & SCE_PASS_AO) != 0) { + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_AO, viewname); + + GPU_framebuffer_bind(vedata->fbl->ao_accum_fb); + GPU_framebuffer_read_color(vedata->fbl->ao_accum_fb, + rect->xmin, rect->ymin, + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), + 3, 0, rp->rect); + + /* This is the accumulated color. Divide by the number of samples. */ + for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) { + rp->rect[i] = rp->rect[i + 1] = rp->rect[i + 2] = min_ff(1.0f, rp->rect[i] / (float)render_samples); + } + } +} + +static void eevee_render_draw_background(EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PassList *psl = vedata->psl; + + /* Prevent background to write to data buffers. + * NOTE : This also make sure the textures are bound + * to the right double buffer. */ + GPU_framebuffer_ensure_config(&fbl->main_fb, { + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_NONE + }); + GPU_framebuffer_bind(fbl->main_fb); + + DRW_draw_pass(psl->background_pass); + + GPU_framebuffer_ensure_config(&fbl->main_fb, { + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_TEXTURE(stl->effects->ssr_normal_input), + GPU_ATTACHMENT_TEXTURE(stl->effects->ssr_specrough_input), + GPU_ATTACHMENT_TEXTURE(stl->effects->sss_data), + GPU_ATTACHMENT_TEXTURE(stl->effects->sss_albedo) + }); + GPU_framebuffer_bind(fbl->main_fb); +} + +void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl, const rcti *rect) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + ViewLayer *view_layer = draw_ctx->view_layer; + const char *viewname = RE_GetActiveRenderView(engine->re); + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + EEVEE_PrivateData *g_data = stl->g_data; + + /* FINISH CACHE */ + EEVEE_materials_cache_finish(vedata); + EEVEE_lights_cache_finish(sldata); + EEVEE_lightprobes_cache_finish(sldata, vedata); + + /* Sort transparents before the loop. */ + DRW_pass_sort_shgroup_z(psl->transparent_pass); + + /* Push instances attribs to the GPU. */ + DRW_render_instance_buffer_finish(); + + if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR | + SCE_PASS_SUBSURFACE_DIRECT | + SCE_PASS_SUBSURFACE_INDIRECT)) != 0) + { + EEVEE_subsurface_output_init(sldata, vedata); + } + + if ((view_layer->passflag & SCE_PASS_MIST) != 0) { + EEVEE_mist_output_init(sldata, vedata); + } + + if ((view_layer->passflag & SCE_PASS_AO) != 0) { + EEVEE_occlusion_output_init(sldata, vedata); + } + + uint tot_sample = scene_eval->eevee.taa_render_samples; + uint render_samples = 0; + + if (RE_engine_test_break(engine)) { + return; + } + + while (render_samples < tot_sample && !RE_engine_test_break(engine)) { + float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float clear_depth = 1.0f; + uint clear_stencil = 0xFF; + uint primes[3] = {2, 3, 7}; + double offset[3] = {0.0, 0.0, 0.0}; + double r[3]; + + /* Restore winmat before jittering again. */ + copy_m4_m4(stl->effects->overide_winmat, g_data->winmat); + /* Copy previous persmat to UBO data */ + copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat); + + BLI_halton_3D(primes, offset, stl->effects->taa_current_sample, r); + EEVEE_update_noise(psl, fbl, r); + EEVEE_temporal_sampling_matrices_calc(stl->effects, g_data->viewmat, g_data->persmat, r); + EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1); + EEVEE_materials_init(sldata, stl, fbl); + + /* Set matrices. */ + DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV); + DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV); + + /* Refresh Probes */ + while (EEVEE_lightprobes_all_probes_ready(sldata, vedata) == false) { + RE_engine_update_stats(engine, NULL, "Updating Probes"); + EEVEE_lightprobes_refresh(sldata, vedata); + /* Refreshing probes can take some times, allow exit. */ + if (RE_engine_test_break(engine)) { + return; + } + } + EEVEE_lightprobes_refresh_planar(sldata, vedata); + DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data); + + char info[42]; + BLI_snprintf(info, sizeof(info), "Rendering %u / %u samples", render_samples + 1, tot_sample); + RE_engine_update_stats(engine, NULL, info); + + /* Refresh Shadows */ + EEVEE_draw_shadows(sldata, psl); + + GPU_framebuffer_bind(fbl->main_fb); + GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil); + /* Depth prepass */ + DRW_draw_pass(psl->depth_pass); + DRW_draw_pass(psl->depth_pass_cull); + /* Create minmax texture */ + EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1); + EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1); + EEVEE_volumes_compute(sldata, vedata); + /* Shading pass */ + eevee_render_draw_background(vedata); + GPU_framebuffer_bind(fbl->main_fb); + EEVEE_draw_default_passes(psl); + DRW_draw_pass(psl->material_pass); + EEVEE_subsurface_data_render(sldata, vedata); + /* Effects pre-transparency */ + EEVEE_subsurface_compute(sldata, vedata); + EEVEE_reflection_compute(sldata, vedata); + EEVEE_refraction_compute(sldata, vedata); + /* Opaque refraction */ + DRW_draw_pass(psl->refract_depth_pass); + DRW_draw_pass(psl->refract_depth_pass_cull); + DRW_draw_pass(psl->refract_pass); + /* Subsurface output */ + EEVEE_subsurface_output_accumulate(sldata, vedata); + /* Occlusion output */ + EEVEE_occlusion_output_accumulate(sldata, vedata); + /* Result NORMAL */ + eevee_render_result_normal(rl, viewname, rect, vedata, sldata); + /* Volumetrics Resolve Opaque */ + EEVEE_volumes_resolve(sldata, vedata); + /* Mist output */ + EEVEE_mist_output_accumulate(sldata, vedata); + /* Transparent */ + DRW_draw_pass(psl->transparent_pass); + /* Result Z */ + eevee_render_result_z(rl, viewname, rect, vedata, sldata); + /* Post Process */ + EEVEE_draw_effects(sldata, vedata); + + RE_engine_update_progress(engine, (float)(render_samples++) / (float)tot_sample); + } + + eevee_render_result_combined(rl, viewname, rect, vedata, sldata); + eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata, render_samples); + eevee_render_result_mist(rl, viewname, rect, vedata, sldata, render_samples); + eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata, render_samples); +} + +void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer) +{ + int type; + + RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); + +#define CHECK_PASS(name, channels, chanid) \ + if (view_layer->passflag & (SCE_PASS_ ## name)) { \ + if (channels == 4) type = SOCK_RGBA; \ + else if (channels == 3) type = SOCK_VECTOR; \ + else type = SOCK_FLOAT; \ + RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_ ## name, channels, chanid, type); \ + } + + CHECK_PASS(Z, 1, "Z"); + CHECK_PASS(MIST, 1, "Z"); + CHECK_PASS(NORMAL, 3, "XYZ"); + CHECK_PASS(AO, 3, "RGB"); + CHECK_PASS(SUBSURFACE_COLOR, 3, "RGB"); + CHECK_PASS(SUBSURFACE_DIRECT, 3, "RGB"); + +#undef CHECK_PASS +} diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c new file mode 100644 index 00000000000..74760b9c828 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -0,0 +1,325 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_screen_raytrace.c + * \ingroup draw_engine + * + * Screen space reflections and refractions techniques. + */ + +#include "DRW_render.h" + +#include "BLI_dynstr.h" +#include "BLI_string_utils.h" + +#include "DEG_depsgraph_query.h" + +#include "eevee_private.h" +#include "GPU_texture.h" + +/* SSR shader variations */ +enum { + SSR_RESOLVE = (1 << 0), + SSR_FULL_TRACE = (1 << 1), + SSR_AO = (1 << 3), + SSR_MAX_SHADER = (1 << 4), +}; + +static struct { + /* Screen Space Reflection */ + struct GPUShader *ssr_sh[SSR_MAX_SHADER]; + + /* Theses are just references, not actually allocated */ + struct GPUTexture *depth_src; + struct GPUTexture *color_src; +} e_data = {{NULL}}; /* Engine data */ + +extern char datatoc_ambient_occlusion_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_bsdf_sampling_lib_glsl[]; +extern char datatoc_octahedron_lib_glsl[]; +extern char datatoc_effect_ssr_frag_glsl[]; +extern char datatoc_lightprobe_lib_glsl[]; +extern char datatoc_raytrace_lib_glsl[]; + +static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options) +{ + if (e_data.ssr_sh[options] == NULL) { + char *ssr_shader_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_raytrace_lib_glsl, + datatoc_effect_ssr_frag_glsl); + + DynStr *ds_defines = BLI_dynstr_new(); + BLI_dynstr_appendf(ds_defines, SHADER_DEFINES); + if (options & SSR_RESOLVE) { + BLI_dynstr_appendf(ds_defines, "#define STEP_RESOLVE\n"); + } + else { + BLI_dynstr_appendf(ds_defines, "#define STEP_RAYTRACE\n"); + BLI_dynstr_appendf(ds_defines, "#define PLANAR_PROBE_RAYTRACE\n"); + } + if (options & SSR_FULL_TRACE) { + BLI_dynstr_appendf(ds_defines, "#define FULLRES\n"); + } + if (options & SSR_AO) { + BLI_dynstr_appendf(ds_defines, "#define SSR_AO\n"); + } + char *ssr_define_str = BLI_dynstr_get_cstring(ds_defines); + BLI_dynstr_free(ds_defines); + + e_data.ssr_sh[options] = DRW_shader_create_fullscreen(ssr_shader_str, ssr_define_str); + + MEM_freeN(ssr_shader_str); + MEM_freeN(ssr_define_str); + } + + return e_data.ssr_sh[options]; +} + +int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; + const float *viewport_size = DRW_viewport_size_get(); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + /* Compute pixel size, (shared with contact shadows) */ + copy_v2_v2(common_data->ssr_pixelsize, viewport_size); + invert_v2(common_data->ssr_pixelsize); + + if (scene_eval->eevee.flag & SCE_EEVEE_SSR_ENABLED) { + const bool use_refraction = (scene_eval->eevee.flag & SCE_EEVEE_SSR_REFRACTION) != 0; + + if (use_refraction) { + /* TODO: Opti: Could be shared. */ + DRW_texture_ensure_fullscreen_2D(&txl->refract_color, GPU_R11F_G11F_B10F, DRW_TEX_FILTER | DRW_TEX_MIPMAP); + + GPU_framebuffer_ensure_config(&fbl->refract_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->refract_color) + }); + } + + effects->reflection_trace_full = (scene_eval->eevee.flag & SCE_EEVEE_SSR_HALF_RESOLUTION) == 0; + common_data->ssr_thickness = scene_eval->eevee.ssr_thickness; + common_data->ssr_border_fac = scene_eval->eevee.ssr_border_fade; + common_data->ssr_firefly_fac = scene_eval->eevee.ssr_firefly_fac; + common_data->ssr_max_roughness = scene_eval->eevee.ssr_max_roughness; + common_data->ssr_quality = 1.0f - 0.95f * scene_eval->eevee.ssr_quality; + common_data->ssr_brdf_bias = 0.1f + common_data->ssr_quality * 0.6f; /* Range [0.1, 0.7]. */ + + if (common_data->ssr_firefly_fac < 1e-8f) { + common_data->ssr_firefly_fac = FLT_MAX; + } + + const int divisor = (effects->reflection_trace_full) ? 1 : 2; + int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor}; + int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + const bool high_qual_input = true; /* TODO dither low quality input */ + const GPUTextureFormat format = (high_qual_input) ? GPU_RGBA16F : GPU_RGBA8; + + /* MRT for the shading pass in order to output needed data for the SSR pass. */ + effects->ssr_specrough_input = DRW_texture_pool_query_2D(size_fs[0], size_fs[1], format, + &draw_engine_eevee_type); + + GPU_framebuffer_texture_attach(fbl->main_fb, effects->ssr_specrough_input, 2, 0); + + /* Raytracing output */ + effects->ssr_hit_output = DRW_texture_pool_query_2D(tracing_res[0], tracing_res[1], GPU_RG16I, + &draw_engine_eevee_type); + effects->ssr_pdf_output = DRW_texture_pool_query_2D(tracing_res[0], tracing_res[1], GPU_R16F, + &draw_engine_eevee_type); + + GPU_framebuffer_ensure_config(&fbl->screen_tracing_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->ssr_hit_output), + GPU_ATTACHMENT_TEXTURE(effects->ssr_pdf_output) + }); + + /* Enable double buffering to be able to read previous frame color */ + return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_DOUBLE_BUFFER | ((use_refraction) ? EFFECT_REFRACT : 0); + } + + /* Cleanup to release memory */ + GPU_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb); + effects->ssr_specrough_input = NULL; + effects->ssr_hit_output = NULL; + effects->ssr_pdf_output = NULL; + + return 0; +} + +void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; + + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + + if ((effects->enabled_effects & EFFECT_SSR) != 0) { + int options = (effects->reflection_trace_full) ? SSR_FULL_TRACE : 0; + options |= ((effects->enabled_effects & EFFECT_GTAO) != 0) ? SSR_AO : 0; + + struct GPUShader *trace_shader = eevee_effects_screen_raytrace_shader_get(options); + struct GPUShader *resolve_shader = eevee_effects_screen_raytrace_shader_get(SSR_RESOLVE | options); + + /** Screen space raytracing overview + * + * Following Frostbite stochastic SSR. + * + * - First pass Trace rays accross the depth buffer. The hit position and pdf are + * recorded in a RGBA16F render target for each ray (sample). + * + * - We downsample the previous frame color buffer. + * + * - For each final pixel, we gather neighboors rays and choose a color buffer + * mipmap for each ray using its pdf. (filtered importance sampling) + * We then evaluate the lighting from the probes and mix the results together. + */ + psl->ssr_raytrace = DRW_pass_create("SSR Raytrace", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(trace_shader, psl->ssr_raytrace); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); + DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); + DRW_shgroup_uniform_texture_ref(grp, "specroughBuffer", &effects->ssr_specrough_input); + DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); + DRW_shgroup_uniform_texture_ref(grp, "planarDepth", &vedata->txl->planar_depth); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + if (!effects->reflection_trace_full) { + DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1); + } + DRW_shgroup_call_add(grp, quad, NULL); + + psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); + grp = DRW_shgroup_create(resolve_shader, psl->ssr_resolve); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); + DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); + DRW_shgroup_uniform_texture_ref(grp, "specroughBuffer", &effects->ssr_specrough_input); + DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &sldata->probe_pool); + DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &vedata->txl->planar_pool); + DRW_shgroup_uniform_texture_ref(grp, "planarDepth", &vedata->txl->planar_depth); + DRW_shgroup_uniform_texture_ref(grp, "hitBuffer", &effects->ssr_hit_output); + DRW_shgroup_uniform_texture_ref(grp, "pdfBuffer", &effects->ssr_pdf_output); + DRW_shgroup_uniform_texture_ref(grp, "prevColorBuffer", &txl->color_double_buffer); + DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1); + if ((effects->enabled_effects & EFFECT_GTAO) != 0) { + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); + } + + DRW_shgroup_call_add(grp, quad, NULL); + } +} + +void EEVEE_refraction_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & EFFECT_REFRACT) != 0) { + GPU_framebuffer_blit(fbl->main_fb, 0, fbl->refract_fb, 0, GPU_COLOR_BIT); + EEVEE_downsample_buffer(vedata, txl->refract_color, 9); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + +void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; + + if (((effects->enabled_effects & EFFECT_SSR) != 0) && stl->g_data->valid_double_buffer) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + e_data.depth_src = dtxl->depth; + + DRW_stats_group_start("SSR"); + + /* Raytrace. */ + GPU_framebuffer_bind(fbl->screen_tracing_fb); + DRW_draw_pass(psl->ssr_raytrace); + + EEVEE_downsample_buffer(vedata, txl->color_double_buffer, 9); + + /* Resolve at fullres */ + int sample = (DRW_state_is_image_render()) ? effects->taa_render_sample : effects->taa_current_sample; + /* Doing a neighbor shift only after a few iteration. We wait for a prime number of cycles to avoid + * noise correlation. This reduces variance faster. */ + effects->ssr_neighbor_ofs = ((sample / 5) % 8) * 4; + switch ((sample / 11) % 4) { + case 0: + effects->ssr_halfres_ofs[0] = 0; + effects->ssr_halfres_ofs[1] = 0; + break; + case 1: + effects->ssr_halfres_ofs[0] = 0; + effects->ssr_halfres_ofs[1] = 1; + break; + case 2: + effects->ssr_halfres_ofs[0] = 1; + effects->ssr_halfres_ofs[1] = 0; + break; + case 4: + effects->ssr_halfres_ofs[0] = 1; + effects->ssr_halfres_ofs[1] = 1; + break; + } + GPU_framebuffer_bind(fbl->main_color_fb); + DRW_draw_pass(psl->ssr_resolve); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + DRW_stats_group_end(); + } +} + +void EEVEE_screen_raytrace_free(void) +{ + for (int i = 0; i < SSR_MAX_SHADER; ++i) { + DRW_SHADER_FREE_SAFE(e_data.ssr_sh[i]); + } +} diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c new file mode 100644 index 00000000000..6ee3b9cc286 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -0,0 +1,339 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_subsurface.c + * \ingroup draw_engine + * + * Screen space subsurface scattering technique. + */ + +#include "DRW_render.h" + +#include "BLI_string_utils.h" + +#include "DEG_depsgraph_query.h" + +#include "eevee_private.h" +#include "GPU_texture.h" + +static struct { + struct GPUShader *sss_sh[4]; +} e_data = {{NULL}}; /* Engine data */ + +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_effect_subsurface_frag_glsl[]; + +static void eevee_create_shader_subsurface(void) +{ + char *frag_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_effect_subsurface_frag_glsl); + + e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n"); + e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"); + e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n" + "#define USE_SEP_ALBEDO\n"); + e_data.sss_sh[3] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n" + "#define USE_SEP_ALBEDO\n" + "#define RESULT_ACCUM\n"); + + MEM_freeN(frag_str); +} + +int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + const float *viewport_size = DRW_viewport_size_get(); + const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + if (scene_eval->eevee.flag & SCE_EEVEE_SSS_ENABLED) { + effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2; + effects->sss_separate_albedo = (scene_eval->eevee.flag & SCE_EEVEE_SSS_SEPARATE_ALBEDO) != 0; + common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold; + + /* Force separate albedo for final render */ + if (DRW_state_is_image_render()) { + effects->sss_separate_albedo = true; + } + + /* Shaders */ + if (!e_data.sss_sh[0]) { + eevee_create_shader_subsurface(); + } + + /* NOTE : we need another stencil because the stencil buffer is on the same texture + * as the depth buffer we are sampling from. This could be avoided if the stencil is + * a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8. + * OR OpenGL 4.3 / ARB_ES3_compatibility if using a renderbuffer instead */ + effects->sss_stencil = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_DEPTH24_STENCIL8, + &draw_engine_eevee_type); + effects->sss_blur = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA16F, + &draw_engine_eevee_type); + effects->sss_data = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA16F, + &draw_engine_eevee_type); + + GPU_framebuffer_ensure_config(&fbl->sss_blur_fb, { + GPU_ATTACHMENT_TEXTURE(effects->sss_stencil), + GPU_ATTACHMENT_TEXTURE(effects->sss_blur) + }); + + GPU_framebuffer_ensure_config(&fbl->sss_resolve_fb, { + GPU_ATTACHMENT_TEXTURE(effects->sss_stencil), + GPU_ATTACHMENT_TEXTURE(txl->color) + }); + + GPU_framebuffer_ensure_config(&fbl->sss_clear_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(effects->sss_data) + }); + + if (effects->sss_separate_albedo) { + effects->sss_albedo = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, + &draw_engine_eevee_type); + } + else { + effects->sss_albedo = NULL; + } + return EFFECT_SSS; + } + + /* Cleanup to release memory */ + GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb); + effects->sss_stencil = NULL; + effects->sss_blur = NULL; + effects->sss_data = NULL; + + return 0; +} + +static void set_shgrp_stencil(void *UNUSED(userData), DRWShadingGroup *shgrp) +{ + DRW_shgroup_stencil_mask(shgrp, 255); +} + +void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + if (scene_eval->eevee.flag & SCE_EEVEE_SSS_ENABLED) { + DRW_texture_ensure_fullscreen_2D(&txl->sss_dir_accum, GPU_RGBA16F, 0); + DRW_texture_ensure_fullscreen_2D(&txl->sss_col_accum, GPU_RGBA16F, 0); + + GPU_framebuffer_ensure_config(&fbl->sss_accum_fb, { + GPU_ATTACHMENT_TEXTURE(effects->sss_stencil), + GPU_ATTACHMENT_TEXTURE(txl->sss_dir_accum), + GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum) + }); + + /* Clear texture. */ + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_bind(fbl->sss_accum_fb); + GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear); + + /* Make the opaque refraction pass mask the sss. */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | + DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL; + DRW_pass_state_set(vedata->psl->refract_pass, state); + DRW_pass_foreach_shgroup(vedata->psl->refract_pass, &set_shgrp_stencil, NULL); + } + else { + /* Cleanup to release memory */ + DRW_TEXTURE_FREE_SAFE(txl->sss_dir_accum); + DRW_TEXTURE_FREE_SAFE(txl->sss_col_accum); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb); + } +} + +void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & EFFECT_SSS) != 0) { + /** Screen Space SubSurface Scattering overview + * TODO + */ + psl->sss_blur_ps = DRW_pass_create("Blur Horiz", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL); + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE | DRW_STATE_STENCIL_EQUAL; + psl->sss_resolve_ps = DRW_pass_create("Blur Vert", state); + psl->sss_accum_ps = DRW_pass_create("Resolve Accum", state); + } +} + +void EEVEE_subsurface_add_pass( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint sss_id, struct GPUUniformBuffer *sss_profile) +{ + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_data); + DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_stencil_mask(grp, sss_id); + DRW_shgroup_call_add(grp, quad, NULL); + + struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1]; + grp = DRW_shgroup_create(sh, psl->sss_resolve_ps); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur); + DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_stencil_mask(grp, sss_id); + DRW_shgroup_call_add(grp, quad, NULL); + + if (effects->sss_separate_albedo) { + DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo); + } + + if (DRW_state_is_image_render()) { + grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_accum_ps); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur); + DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo); + DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_stencil_mask(grp, sss_id); + DRW_shgroup_call_add(grp, quad, NULL); + } +} + +void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & EFFECT_SSS) != 0) { + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + /* Clear sss_data texture only... can this be done in a more clever way? */ + GPU_framebuffer_bind(fbl->sss_clear_fb); + GPU_framebuffer_clear_color(fbl->sss_clear_fb, clear); + + GPU_framebuffer_ensure_config(&fbl->main_fb, { + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_TEXTURE(effects->sss_data), + GPU_ATTACHMENT_TEXTURE(effects->sss_albedo) + }); + + GPU_framebuffer_bind(fbl->main_fb); + DRW_draw_pass(psl->sss_pass); + + /* Restore */ + GPU_framebuffer_ensure_config(&fbl->main_fb, { + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_LEAVE, + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_NONE + }); + } +} + +void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & EFFECT_SSS) != 0) { + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + DRW_stats_group_start("SSS"); + + /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */ + GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT); + + /* 1. horizontal pass */ + GPU_framebuffer_bind(fbl->sss_blur_fb); + GPU_framebuffer_clear_color(fbl->sss_blur_fb, clear); + DRW_draw_pass(psl->sss_blur_ps); + + /* 2. vertical pass + Resolve */ + GPU_framebuffer_texture_attach(fbl->sss_resolve_fb, txl->color, 0, 0); + GPU_framebuffer_bind(fbl->sss_resolve_fb); + DRW_draw_pass(psl->sss_resolve_ps); + + GPU_framebuffer_bind(fbl->main_fb); + DRW_stats_group_end(); + } +} + +void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) { + /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */ + GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT); + + /* Only do vertical pass + Resolve */ + GPU_framebuffer_bind(fbl->sss_accum_fb); + DRW_draw_pass(psl->sss_accum_ps); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + +void EEVEE_subsurface_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.sss_sh[0]); + DRW_SHADER_FREE_SAFE(e_data.sss_sh[1]); + DRW_SHADER_FREE_SAFE(e_data.sss_sh[2]); + DRW_SHADER_FREE_SAFE(e_data.sss_sh[3]); +} diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c new file mode 100644 index 00000000000..7cd76669fe4 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -0,0 +1,387 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_temporal_sampling.c + * \ingroup draw_engine + * + * Temporal super sampling technique + */ + +#include "DRW_render.h" + +#include "ED_screen.h" + +#include "BLI_rand.h" +#include "BLI_string_utils.h" + +#include "DEG_depsgraph_query.h" + +#include "eevee_private.h" +#include "GPU_texture.h" + +#define FILTER_CDF_TABLE_SIZE 512 + +static struct { + /* Temporal Anti Aliasing */ + struct GPUShader *taa_resolve_sh; + struct GPUShader *taa_resolve_reproject_sh; + + /* Pixel filter table: Only blackman-harris for now. */ + float inverted_cdf[FILTER_CDF_TABLE_SIZE]; +} e_data = {NULL}; /* Engine data */ + +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_effect_temporal_aa_glsl[]; + +static void eevee_create_shader_temporal_sampling(void) +{ + char *frag_str = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_common_view_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_effect_temporal_aa_glsl); + + e_data.taa_resolve_sh = DRW_shader_create_fullscreen(frag_str, NULL); + e_data.taa_resolve_reproject_sh = DRW_shader_create_fullscreen(frag_str, "#define USE_REPROJECTION\n"); + + MEM_freeN(frag_str); +} + +static float UNUSED_FUNCTION(filter_box)(float UNUSED(x)) +{ + return 1.0f; +} + +static float filter_blackman_harris(float x) +{ + /* Hardcoded 1px footprint [-0.5..0.5]. We resize later. */ + const float width = 1.0f; + x = 2.0f * M_PI * (x / width + 0.5f); + return 0.35875f - 0.48829f * cosf(x) + 0.14128f * cosf(2.0f * x) - 0.01168f * cosf(3.0f * x); +} + +/* Compute cumulative distribution function of a discrete function. */ +static void compute_cdf(float (*func)(float x), float cdf[FILTER_CDF_TABLE_SIZE]) +{ + cdf[0] = 0.0f; + /* Actual CDF evaluation. */ + for (int u = 0; u < FILTER_CDF_TABLE_SIZE - 1; ++u) { + float x = (float)(u + 1) / (float)(FILTER_CDF_TABLE_SIZE - 1); + cdf[u + 1] = cdf[u] + func(x - 0.5f); /* [-0.5..0.5]. We resize later. */ + } + /* Normalize the CDF. */ + for (int u = 0; u < FILTER_CDF_TABLE_SIZE - 1; u++) { + cdf[u] /= cdf[FILTER_CDF_TABLE_SIZE - 1]; + } + /* Just to make sure. */ + cdf[FILTER_CDF_TABLE_SIZE - 1] = 1.0f; +} + +static void invert_cdf(const float cdf[FILTER_CDF_TABLE_SIZE], float invert_cdf[FILTER_CDF_TABLE_SIZE]) +{ + for (int u = 0; u < FILTER_CDF_TABLE_SIZE; u++) { + float x = (float)u / (float)(FILTER_CDF_TABLE_SIZE - 1); + for (int i = 0; i < FILTER_CDF_TABLE_SIZE; ++i) { + if (cdf[i] >= x) { + if (i == FILTER_CDF_TABLE_SIZE - 1) { + invert_cdf[u] = 1.0f; + } + else { + float t = (x - cdf[i]) / (cdf[i + 1] - cdf[i]); + invert_cdf[u] = ((float)i + t) / (float)(FILTER_CDF_TABLE_SIZE - 1); + } + break; + } + } + } +} + +/* Evaluate a discrete function table with linear interpolation. */ +static float eval_table(float *table, float x) +{ + CLAMP(x, 0.0f, 1.0f); + x = x * (FILTER_CDF_TABLE_SIZE - 1); + + int index = min_ii((int)(x), FILTER_CDF_TABLE_SIZE - 1); + int nindex = min_ii(index + 1, FILTER_CDF_TABLE_SIZE - 1); + float t = x - index; + + return (1.0f - t) * table[index] + t * table[nindex]; +} + +static void eevee_create_cdf_table_temporal_sampling(void) +{ + float *cdf_table = MEM_mallocN(sizeof(float) * FILTER_CDF_TABLE_SIZE, "Eevee Filter CDF table"); + + float filter_width = 2.0f; /* Use a 2 pixel footprint by default. */ + + { + /* Use blackman-harris filter. */ + filter_width *= 2.0f; + compute_cdf(filter_blackman_harris, cdf_table); + } + + invert_cdf(cdf_table, e_data.inverted_cdf); + + /* Scale and offset table. */ + for (int i = 0; i < FILTER_CDF_TABLE_SIZE; ++i) { + e_data.inverted_cdf[i] = (e_data.inverted_cdf[i] - 0.5f) * filter_width; + } + + MEM_freeN(cdf_table); +} + +void EEVEE_temporal_sampling_matrices_calc( + EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], const double ht_point[2]) +{ + const float *viewport_size = DRW_viewport_size_get(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + RenderData *rd = &scene->r; + + float filter_size = rd->gauss; /* Sigh.. Stupid legacy naming. */ + + float ofs_x = eval_table(e_data.inverted_cdf, (float)(ht_point[0])) * filter_size; + float ofs_y = eval_table(e_data.inverted_cdf, (float)(ht_point[1])) * filter_size; + + window_translate_m4( + effects->overide_winmat, persmat, + ofs_x / viewport_size[0], + ofs_y / viewport_size[1]); + + mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat); + invert_m4_m4(effects->overide_persinv, effects->overide_persmat); + invert_m4_m4(effects->overide_wininv, effects->overide_winmat); +} + +int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + // EEVEE_FramebufferList *fbl = vedata->fbl; + // EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; + int repro_flag = 0; + + if (!e_data.taa_resolve_sh) { + eevee_create_shader_temporal_sampling(); + eevee_create_cdf_table_temporal_sampling(); + } + + /* Reset for each "redraw". When rendering using ogl render, + * we accumulate the redraw inside the drawing loop in eevee_draw_background(). + * But we do NOT accumulate between "redraw" (as in full draw manager drawloop) + * because the opengl render already does that. */ + effects->taa_render_sample = 1; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + if (((scene_eval->eevee.taa_samples != 1) && + /* FIXME the motion blur camera evaluation is tagging view_updated + * thus making the TAA always reset and never stopping rendering. */ + (effects->enabled_effects & EFFECT_MOTION_BLUR) == 0) || + DRW_state_is_image_render()) + { + float persmat[4][4], viewmat[4][4]; + + if (!DRW_state_is_image_render() && + (scene_eval->eevee.flag & SCE_EEVEE_TAA_REPROJECTION)) + { + repro_flag = EFFECT_TAA_REPROJECT | EFFECT_VELOCITY_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER | EFFECT_DOUBLE_BUFFER | EFFECT_POST_BUFFER; + effects->taa_reproject_sample = ((effects->taa_reproject_sample + 1) % 16); + } + + /* Until we support reprojection, we need to make sure + * that the history buffer contains correct information. */ + bool view_is_valid = stl->g_data->valid_double_buffer; + + view_is_valid = view_is_valid && (stl->g_data->view_updated == false); + + if (draw_ctx->evil_C != NULL) { + struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C); + view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL); + } + + effects->taa_total_sample = scene_eval->eevee.taa_samples; + MAX2(effects->taa_total_sample, 0); + + DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_get(effects->overide_winmat, DRW_MAT_WIN); + /* The view is jittered by the oglrenderer. So avoid testing in this case. */ + if (!DRW_state_is_image_render()) { + view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN); + copy_m4_m4(effects->prev_drw_persmat, persmat); + } + + /* Prevent ghosting from probe data. */ + view_is_valid = view_is_valid && (effects->prev_drw_support == DRW_state_draw_support()); + effects->prev_drw_support = DRW_state_draw_support(); + + if (((effects->taa_total_sample == 0) || (effects->taa_current_sample < effects->taa_total_sample)) || + DRW_state_is_image_render()) + { + if (view_is_valid) { + /* OGL render already jitter the camera. */ + if (!DRW_state_is_image_render()) { + effects->taa_current_sample += 1; + repro_flag = 0; + + double ht_point[2]; + double ht_offset[2] = {0.0, 0.0}; + uint ht_primes[2] = {2, 3}; + + BLI_halton_2D(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point); + + EEVEE_temporal_sampling_matrices_calc(effects, viewmat, persmat, ht_point); + + DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(effects->overide_winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(effects->overide_wininv, DRW_MAT_WININV); + } + } + else { + effects->taa_current_sample = 1; + } + } + else { + effects->taa_current_sample = 1; + } + + return repro_flag | EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER | EFFECT_POST_BUFFER; + } + + effects->taa_current_sample = 1; + + return repro_flag; +} + +void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) { + struct GPUShader *sh = (effects->enabled_effects & EFFECT_TAA_REPROJECT) + ? e_data.taa_resolve_reproject_sh + : e_data.taa_resolve_sh; + + psl->taa_resolve = DRW_pass_create("Temporal AA Resolve", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->taa_resolve); + + DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->color_double_buffer); + DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &txl->color); + + if (effects->enabled_effects & EFFECT_TAA_REPROJECT) { + // DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + DRW_shgroup_uniform_texture_ref(grp, "velocityBuffer", &effects->velocity_tx); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + } + else { + DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1); + } + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } +} + +/* Special Swap */ +#define SWAP_BUFFER_TAA() do { \ + SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer_fb); \ + SWAP(struct GPUFrameBuffer *, fbl->effect_color_fb, fbl->double_buffer_color_fb); \ + SWAP(GPUTexture *, txl->color_post, txl->color_double_buffer); \ + effects->swap_double_buffer = false; \ + effects->source_buffer = txl->color_double_buffer; \ + effects->target_buffer = fbl->main_color_fb; \ +} while (0); + +void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) { + if ((effects->enabled_effects & EFFECT_TAA) != 0 && effects->taa_current_sample != 1) { + if (DRW_state_is_image_render()) { + /* See EEVEE_temporal_sampling_init() for more details. */ + effects->taa_alpha = 1.0f / (float)(effects->taa_render_sample); + } + else { + effects->taa_alpha = 1.0f / (float)(effects->taa_current_sample); + } + + GPU_framebuffer_bind(fbl->effect_color_fb); + DRW_draw_pass(psl->taa_resolve); + + /* Restore the depth from sample 1. */ + if (!DRW_state_is_image_render()) { + GPU_framebuffer_blit(fbl->double_buffer_depth_fb, 0, fbl->main_fb, 0, GPU_DEPTH_BIT); + } + + SWAP_BUFFER_TAA(); + } + else { + if (!DRW_state_is_image_render()) { + /* Do reprojection for noise reduction */ + /* TODO : do AA jitter if in only render view. */ + if ((effects->enabled_effects & EFFECT_TAA_REPROJECT) != 0 && + stl->g_data->valid_double_buffer) + { + GPU_framebuffer_bind(fbl->effect_color_fb); + DRW_draw_pass(psl->taa_resolve); + + SWAP_BUFFER_TAA(); + } + + /* Save the depth buffer for the next frame. + * This saves us from doing anything special + * in the other mode engines. */ + GPU_framebuffer_blit(fbl->main_fb, 0, fbl->double_buffer_depth_fb, 0, GPU_DEPTH_BIT); + } + } + + /* Make each loop count when doing a render. */ + if (DRW_state_is_image_render()) { + effects->taa_render_sample += 1; + effects->taa_current_sample += 1; + } + else { + if ((effects->taa_total_sample == 0) || + (effects->taa_current_sample < effects->taa_total_sample)) + { + DRW_viewport_request_redraw(); + } + } + } +} + +void EEVEE_temporal_sampling_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh); +} diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c new file mode 100644 index 00000000000..2d074eea522 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -0,0 +1,601 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_volumes.c + * \ingroup draw_engine + * + * Volumetric effects rendering using frostbite approach. + */ + +#include "DRW_render.h" + +#include "BLI_rand.h" +#include "BLI_string_utils.h" + +#include "DNA_object_force_types.h" +#include "DNA_smoke_types.h" +#include "DNA_world_types.h" + +#include "BKE_global.h" /* for G.debug_value */ +#include "BKE_modifier.h" +#include "BKE_mesh.h" +#include "BKE_object.h" + +#include "ED_screen.h" + +#include "DEG_depsgraph_query.h" + +#include "eevee_private.h" +#include "GPU_draw.h" +#include "GPU_texture.h" + +static struct { + char *volumetric_common_lib; + char *volumetric_common_lamps_lib; + + struct GPUShader *volumetric_clear_sh; + struct GPUShader *volumetric_scatter_sh; + struct GPUShader *volumetric_scatter_with_lamps_sh; + struct GPUShader *volumetric_integration_sh; + struct GPUShader *volumetric_resolve_sh; + + GPUTexture *color_src; + GPUTexture *depth_src; + + /* List of all smoke domains rendered within this frame. */ + ListBase smoke_domains; +} e_data = {NULL}; /* Engine data */ + +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_bsdf_direct_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_octahedron_lib_glsl[]; +extern char datatoc_irradiance_lib_glsl[]; +extern char datatoc_lamps_lib_glsl[]; +extern char datatoc_volumetric_frag_glsl[]; +extern char datatoc_volumetric_geom_glsl[]; +extern char datatoc_volumetric_vert_glsl[]; +extern char datatoc_volumetric_resolve_frag_glsl[]; +extern char datatoc_volumetric_scatter_frag_glsl[]; +extern char datatoc_volumetric_integration_frag_glsl[]; +extern char datatoc_volumetric_lib_glsl[]; +extern char datatoc_common_fullscreen_vert_glsl[]; + +static void eevee_create_shader_volumes(void) +{ + e_data.volumetric_common_lib = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_volumetric_lib_glsl); + + e_data.volumetric_common_lamps_lib = BLI_string_joinN( + datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_direct_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lamps_lib_glsl, + datatoc_volumetric_lib_glsl); + + e_data.volumetric_clear_sh = DRW_shader_create_with_lib( + datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, + datatoc_volumetric_frag_glsl, + e_data.volumetric_common_lib, + "#define VOLUMETRICS\n" + "#define CLEAR\n"); + e_data.volumetric_scatter_sh = DRW_shader_create_with_lib( + datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, + datatoc_volumetric_scatter_frag_glsl, + e_data.volumetric_common_lamps_lib, + SHADER_DEFINES + "#define VOLUMETRICS\n" + "#define VOLUME_SHADOW\n"); + e_data.volumetric_scatter_with_lamps_sh = DRW_shader_create_with_lib( + datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, + datatoc_volumetric_scatter_frag_glsl, + e_data.volumetric_common_lamps_lib, + SHADER_DEFINES + "#define VOLUMETRICS\n" + "#define VOLUME_LIGHTING\n" + "#define VOLUME_SHADOW\n"); + e_data.volumetric_integration_sh = DRW_shader_create_with_lib( + datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, + datatoc_volumetric_integration_frag_glsl, + e_data.volumetric_common_lib, NULL); + e_data.volumetric_resolve_sh = DRW_shader_create_with_lib( + datatoc_common_fullscreen_vert_glsl, NULL, + datatoc_volumetric_resolve_frag_glsl, + e_data.volumetric_common_lib, NULL); +} + +void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample) +{ + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + + double ht_point[3]; + double ht_offset[3] = {0.0, 0.0}; + uint ht_primes[3] = {3, 7, 2}; + + BLI_halton_3D(ht_primes, ht_offset, current_sample, ht_point); + + common_data->vol_jitter[0] = (float)ht_point[0]; + common_data->vol_jitter[1] = (float)ht_point[1]; + common_data->vol_jitter[2] = (float)ht_point[2]; +} + +int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + const float *viewport_size = DRW_viewport_size_get(); + + BLI_listbase_clear(&e_data.smoke_domains); + + if (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_ENABLED) { + + /* Shaders */ + if (!e_data.volumetric_scatter_sh) { + eevee_create_shader_volumes(); + } + + const int tile_size = scene_eval->eevee.volumetric_tile_size; + + /* Find Froxel Texture resolution. */ + int tex_size[3]; + + tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size)); + tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size)); + tex_size[2] = max_ii(scene_eval->eevee.volumetric_samples, 1); + + common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]); + common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]); + + /* TODO compute snap to maxZBuffer for clustered rendering */ + + if ((common_data->vol_tex_size[0] != tex_size[0]) || + (common_data->vol_tex_size[1] != tex_size[1]) || + (common_data->vol_tex_size[2] != tex_size[2])) + { + DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering); + DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction); + DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission); + DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase); + DRW_TEXTURE_FREE_SAFE(txl->volume_scatter); + DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance); + DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history); + DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb); + common_data->vol_tex_size[0] = tex_size[0]; + common_data->vol_tex_size[1] = tex_size[1]; + common_data->vol_tex_size[2] = tex_size[2]; + + common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]); + common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]); + common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]); + } + + /* Like frostbite's paper, 5% blend of the new frame. */ + common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f; + + if (txl->volume_prop_scattering == NULL) { + /* Volume properties: We evaluate all volumetric objects + * and store their final properties into each froxel */ + txl->volume_prop_scattering = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL); + txl->volume_prop_extinction = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL); + txl->volume_prop_emission = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL); + txl->volume_prop_phase = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + GPU_RG16F, DRW_TEX_FILTER, NULL); + + /* Volume scattering: We compute for each froxel the + * Scattered light towards the view. We also resolve temporal + * super sampling during this stage. */ + txl->volume_scatter = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL); + txl->volume_transmittance = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL); + + /* Final integration: We compute for each froxel the + * amount of scattered light and extinction coef at this + * given depth. We use theses textures as double buffer + * for the volumetric history. */ + txl->volume_scatter_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL); + txl->volume_transmittance_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL); + } + + /* Temporal Super sampling jitter */ + uint ht_primes[3] = {3, 7, 2}; + uint current_sample = 0; + + /* If TAA is in use do not use the history buffer. */ + bool do_taa = ((effects->enabled_effects & EFFECT_TAA) != 0); + + if (draw_ctx->evil_C != NULL) { + struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C); + do_taa = do_taa && (ED_screen_animation_no_scrub(wm) == NULL); + } + + if (do_taa) { + common_data->vol_history_alpha = 0.0f; + current_sample = effects->taa_current_sample - 1; + effects->volume_current_sample = -1; + } + else { + const uint max_sample = (ht_primes[0] * ht_primes[1] * ht_primes[2]); + current_sample = effects->volume_current_sample = (effects->volume_current_sample + 1) % max_sample; + if (current_sample != max_sample - 1) { + DRW_viewport_request_redraw(); + } + } + + EEVEE_volumes_set_jitter(sldata, current_sample); + + /* Framebuffer setup */ + GPU_framebuffer_ensure_config(&fbl->volumetric_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering), + GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction), + GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission), + GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase) + }); + GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->volume_scatter), + GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance) + }); + GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history), + GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_history) + }); + + float integration_start = scene_eval->eevee.volumetric_start; + float integration_end = scene_eval->eevee.volumetric_end; + common_data->vol_light_clamp = scene_eval->eevee.volumetric_light_clamp; + common_data->vol_shadow_steps = (float)scene_eval->eevee.volumetric_shadow_samples; + if ((scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_SHADOWS) == 0) { + common_data->vol_shadow_steps = 0; + } + + if (DRW_viewport_is_persp_get()) { + float sample_distribution = scene_eval->eevee.volumetric_sample_distribution; + sample_distribution = 4.0f * (1.00001f - sample_distribution); + + const float clip_start = common_data->view_vecs[0][2]; + /* Negate */ + float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f); + float far = integration_end = min_ff(-integration_end, near - 1e-4f); + + common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) / (far - near); + common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near; + common_data->vol_depth_param[2] = sample_distribution; + } + else { + const float clip_start = common_data->view_vecs[0][2]; + const float clip_end = clip_start + common_data->view_vecs[1][2]; + integration_start = min_ff(integration_end, clip_start); + integration_end = max_ff(-integration_end, clip_end); + + common_data->vol_depth_param[0] = integration_start; + common_data->vol_depth_param[1] = integration_end; + common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start); + } + + /* Disable clamp if equal to 0. */ + if (common_data->vol_light_clamp == 0.0) { + common_data->vol_light_clamp = FLT_MAX; + } + + common_data->vol_use_lights = (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_LIGHTS) != 0; + + return EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER; + } + + /* Cleanup to release memory */ + DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering); + DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction); + DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission); + DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase); + DRW_TEXTURE_FREE_SAFE(txl->volume_scatter); + DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance); + DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history); + DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb); + + return 0; +} + +void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + + if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + DRWShadingGroup *grp = NULL; + + /* Quick breakdown of the Volumetric rendering: + * + * The rendering is separated in 4 stages: + * + * - Material Parameters : we collect volume properties of + * all participating media in the scene and store them in + * a 3D texture aligned with the 3D frustum. + * This is done in 2 passes, one that clear the texture + * and/or evaluate the world volumes, and the 2nd one that + * additively render object volumes. + * + * - Light Scattering : the volume properties then are sampled + * and light scattering is evaluated for each cell of the + * volume texture. Temporal supersampling (if enabled) occurs here. + * + * - Volume Integration : the scattered light and extinction is + * integrated (accumulated) along the viewrays. The result is stored + * for every cell in another texture. + * + * - Fullscreen Resolve : From the previous stage, we get two + * 3D textures that contains integrated scatered light and extinction + * for "every" positions in the frustum. We only need to sample + * them and blend the scene color with thoses factors. This also + * work for alpha blended materials. + **/ + + /* World pass is not additive as it also clear the buffer. */ + psl->volumetric_world_ps = DRW_pass_create("Volumetric World", DRW_STATE_WRITE_COLOR); + + /* World Volumetric */ + struct World *wo = scene->world; + if (wo != NULL && wo->use_nodes && wo->nodetree) { + struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo); + + grp = DRW_shgroup_material_empty_tri_batch_create(mat, + psl->volumetric_world_ps, + common_data->vol_tex_size[2]); + + if (grp) { + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + } + } + + if (grp == NULL) { + /* If no world or volume material is present just clear the buffer with this drawcall */ + grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh, + psl->volumetric_world_ps, + common_data->vol_tex_size[2]); + + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + } + + /* Volumetric Objects */ + psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR | + DRW_STATE_ADDITIVE); + + struct GPUShader *scatter_sh = (common_data->vol_use_lights) ? e_data.volumetric_scatter_with_lamps_sh + : e_data.volumetric_scatter_sh; + psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR); + grp = DRW_shgroup_empty_tri_batch_create(scatter_sh, psl->volumetric_scatter_ps, + common_data->vol_tex_size[2]); + DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &sldata->irradiance_pool); + DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool); + DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool); + DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_prop_scattering); + DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_prop_extinction); + DRW_shgroup_uniform_texture_ref(grp, "volumeEmission", &txl->volume_prop_emission); + DRW_shgroup_uniform_texture_ref(grp, "volumePhase", &txl->volume_prop_phase); + DRW_shgroup_uniform_texture_ref(grp, "historyScattering", &txl->volume_scatter_history); + DRW_shgroup_uniform_texture_ref(grp, "historyTransmittance", &txl->volume_transmittance_history); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + + psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR); + grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh, + psl->volumetric_integration_ps, + common_data->vol_tex_size[2]); + DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter); + DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmittance); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + + psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR); + grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps); + DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter); + DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmittance); + DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src); + DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } +} + +void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Scene *scene, Object *ob) +{ + float *texcoloc = NULL; + float *texcosize = NULL; + struct ModifierData *md = NULL; + Material *ma = give_current_material(ob, 1); + + if (ma == NULL) { + return; + } + + struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma); + + DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]); + + /* If shader failed to compile or is currently compiling. */ + if (grp == NULL) { + return; + } + + /* Making sure it's updated. */ + invert_m4_m4(ob->imat, ob->obmat); + + BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize); + + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", ob->imat); + DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1); + DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1); + + /* Smoke Simulation */ + if (((ob->base_flag & BASE_FROMDUPLI) == 0) && + (md = modifiers_findByType(ob, eModifierType_Smoke)) && + (modifier_isEnabled(scene, md, eModifierMode_Realtime))) + { + SmokeModifierData *smd = (SmokeModifierData *)md; + SmokeDomainSettings *sds = smd->domain; + /* Don't show smoke before simulation starts, this could be made an option in the future. */ + const bool show_smoke = (CFRA >= sds->point_cache[0]->startframe); + + if (sds->fluid && show_smoke) { + if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { + GPU_create_smoke(smd, 0); + } + else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { + GPU_create_smoke(smd, 1); + } + BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd)); + } + + if (sds->tex != NULL) { + DRW_shgroup_uniform_texture_ref(grp, "sampdensity", &sds->tex); + } + if (sds->tex_flame != NULL) { + DRW_shgroup_uniform_texture_ref(grp, "sampflame", &sds->tex_flame); + } + + /* Output is such that 0..1 maps to 0..1000K */ + DRW_shgroup_uniform_vec2(grp, "unftemperature", &sds->flame_ignition, 1); + } +} + +void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { + DRW_stats_group_start("Volumetrics"); + + /* Step 1: Participating Media Properties */ + GPU_framebuffer_bind(fbl->volumetric_fb); + DRW_draw_pass(psl->volumetric_world_ps); + DRW_draw_pass(psl->volumetric_objects_ps); + + /* Step 2: Scatter Light */ + GPU_framebuffer_bind(fbl->volumetric_scat_fb); + DRW_draw_pass(psl->volumetric_scatter_ps); + + /* Step 3: Integration */ + GPU_framebuffer_bind(fbl->volumetric_integ_fb); + DRW_draw_pass(psl->volumetric_integration_ps); + + /* Swap volume history buffers */ + SWAP(struct GPUFrameBuffer *, fbl->volumetric_scat_fb, fbl->volumetric_integ_fb); + SWAP(GPUTexture *, txl->volume_scatter, txl->volume_scatter_history); + SWAP(GPUTexture *, txl->volume_transmittance, txl->volume_transmittance_history); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + + DRW_stats_group_end(); + } +} + +void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + e_data.color_src = txl->color; + e_data.depth_src = dtxl->depth; + + /* Step 4: Apply for opaque */ + GPU_framebuffer_bind(fbl->effect_color_fb); + DRW_draw_pass(psl->volumetric_resolve_ps); + + /* Swap the buffers and rebind depth to the current buffer */ + SWAP(GPUFrameBuffer *, fbl->main_fb, fbl->effect_fb); + SWAP(GPUFrameBuffer *, fbl->main_color_fb, fbl->effect_color_fb); + SWAP(GPUTexture *, txl->color, txl->color_post); + + /* Restore */ + GPU_framebuffer_texture_detach(fbl->effect_fb, dtxl->depth); + GPU_framebuffer_texture_attach(fbl->main_fb, dtxl->depth, 0, 0); + GPU_framebuffer_bind(fbl->main_fb); + } +} + +void EEVEE_volumes_free_smoke_textures(void) +{ + /* Free Smoke Textures after rendering */ + for (LinkData *link = e_data.smoke_domains.first; link; link = link->next) { + SmokeModifierData *smd = (SmokeModifierData *)link->data; + GPU_free_smoke(smd); + } + BLI_freelistN(&e_data.smoke_domains); +} + +void EEVEE_volumes_free(void) +{ + MEM_SAFE_FREE(e_data.volumetric_common_lib); + MEM_SAFE_FREE(e_data.volumetric_common_lamps_lib); + + DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh); + DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_sh); + DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_with_lamps_sh); + DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh); + DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh); +} diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl new file mode 100644 index 00000000000..9d27224b5c9 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl @@ -0,0 +1,282 @@ + +/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */ + +#if defined(MESH_SHADER) +# if !defined(USE_ALPHA_HASH) +# if !defined(USE_ALPHA_CLIP) +# if !defined(SHADOW_SHADER) +# if !defined(USE_MULTIPLY) +# if !defined(USE_ALPHA_BLEND) +# define ENABLE_DEFERED_AO +# endif +# endif +# endif +# endif +# endif +#endif + +#ifndef ENABLE_DEFERED_AO +# if defined(STEP_RESOLVE) +# define ENABLE_DEFERED_AO +# endif +#endif + +#define MAX_PHI_STEP 32 +#define MAX_SEARCH_ITER 32 +#define MAX_LOD 6.0 + +#ifndef UTIL_TEX +#define UTIL_TEX +uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) +#endif /* UTIL_TEX */ + +uniform sampler2D horizonBuffer; + +/* aoSettings flags */ +#define USE_AO 1 +#define USE_BENT_NORMAL 2 +#define USE_DENOISE 4 + +vec4 pack_horizons(vec4 v) { return v * 0.5 + 0.5; } +vec4 unpack_horizons(vec4 v) { return v * 2.0 - 1.0; } + +/* Returns maximum screen distance an AO ray can travel for a given view depth */ +vec2 get_max_dir(float view_depth) +{ + float homcco = ProjectionMatrix[2][3] * view_depth + ProjectionMatrix[3][3]; + float max_dist = aoDistance / homcco; + return vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * max_dist; +} + +vec2 get_ao_dir(float jitter) +{ + /* Only half a turn because we integrate in slices. */ + jitter *= M_PI; + return vec2(cos(jitter), sin(jitter)); +} + +void get_max_horizon_grouped(vec4 co1, vec4 co2, vec3 x, float lod, inout float h) +{ + co1 *= mipRatio[int(lod + 1.0)].xyxy; /* +1 because we are using half res top level */ + co2 *= mipRatio[int(lod + 1.0)].xyxy; /* +1 because we are using half res top level */ + + float depth1 = textureLod(maxzBuffer, co1.xy, floor(lod)).r; + float depth2 = textureLod(maxzBuffer, co1.zw, floor(lod)).r; + float depth3 = textureLod(maxzBuffer, co2.xy, floor(lod)).r; + float depth4 = textureLod(maxzBuffer, co2.zw, floor(lod)).r; + + vec4 len, s_h; + + vec3 s1 = get_view_space_from_depth(co1.xy, depth1); /* s View coordinate */ + vec3 omega_s1 = s1 - x; + len.x = length(omega_s1); + s_h.x = omega_s1.z / len.x; + + vec3 s2 = get_view_space_from_depth(co1.zw, depth2); /* s View coordinate */ + vec3 omega_s2 = s2 - x; + len.y = length(omega_s2); + s_h.y = omega_s2.z / len.y; + + vec3 s3 = get_view_space_from_depth(co2.xy, depth3); /* s View coordinate */ + vec3 omega_s3 = s3 - x; + len.z = length(omega_s3); + s_h.z = omega_s3.z / len.z; + + vec3 s4 = get_view_space_from_depth(co2.zw, depth4); /* s View coordinate */ + vec3 omega_s4 = s4 - x; + len.w = length(omega_s4); + s_h.w = omega_s4.z / len.w; + + /* Blend weight after half the aoDistance to fade artifacts */ + vec4 blend = saturate((1.0 - len / aoDistance) * 2.0); + + h = mix(h, max(h, s_h.x), blend.x); + h = mix(h, max(h, s_h.y), blend.y); + h = mix(h, max(h, s_h.z), blend.z); + h = mix(h, max(h, s_h.w), blend.w); +} + +vec2 search_horizon_sweep(vec2 t_phi, vec3 pos, vec2 uvs, float jitter, vec2 max_dir) +{ + max_dir *= max_v2(abs(t_phi)); + + /* Convert to pixel space. */ + t_phi /= vec2(textureSize(maxzBuffer, 0)); + + /* Avoid division by 0 */ + t_phi += vec2(1e-5); + + jitter *= 0.25; + + /* Compute end points */ + vec2 corner1 = min(vec2(1.0) - uvs, max_dir); /* Top right */ + vec2 corner2 = max(vec2(0.0) - uvs, -max_dir); /* Bottom left */ + vec2 iter1 = corner1 / t_phi; + vec2 iter2 = corner2 / t_phi; + + vec2 min_iter = max(-iter1, -iter2); + vec2 max_iter = max( iter1, iter2); + + vec2 times = vec2(-min_v2(min_iter), min_v2(max_iter)); + + vec2 h = vec2(-1.0); /* init at cos(pi) */ + + /* This is freaking sexy optimized. */ + for (float i = 0.0, ofs = 4.0, time = -1.0; + i < MAX_SEARCH_ITER && time > times.x; + i++, time -= ofs, ofs = min(exp2(MAX_LOD) * 4.0, ofs + ofs * aoQuality)) + { + vec4 t = max(times.xxxx, vec4(time) - (vec4(0.25, 0.5, 0.75, 1.0) - jitter) * ofs); + vec4 cos1 = uvs.xyxy + t_phi.xyxy * t.xxyy; + vec4 cos2 = uvs.xyxy + t_phi.xyxy * t.zzww; + float lod = min(MAX_LOD, max(i - jitter * 4.0, 0.0) * aoQuality); + get_max_horizon_grouped(cos1, cos2, pos, lod, h.y); + } + + for (float i = 0.0, ofs = 4.0, time = 1.0; + i < MAX_SEARCH_ITER && time < times.y; + i++, time += ofs, ofs = min(exp2(MAX_LOD) * 4.0, ofs + ofs * aoQuality)) + { + vec4 t = min(times.yyyy, vec4(time) + (vec4(0.25, 0.5, 0.75, 1.0) - jitter) * ofs); + vec4 cos1 = uvs.xyxy + t_phi.xyxy * t.xxyy; + vec4 cos2 = uvs.xyxy + t_phi.xyxy * t.zzww; + float lod = min(MAX_LOD, max(i - jitter * 4.0, 0.0) * aoQuality); + get_max_horizon_grouped(cos1, cos2, pos, lod, h.x); + } + + return h; +} + +void integrate_slice(vec3 normal, vec2 t_phi, vec2 horizons, inout float visibility, inout vec3 bent_normal) +{ + /* Projecting Normal to Plane P defined by t_phi and omega_o */ + vec3 np = vec3(t_phi.y, -t_phi.x, 0.0); /* Normal vector to Integration plane */ + vec3 t = vec3(-t_phi, 0.0); + vec3 n_proj = normal - np * dot(np, normal); + float n_proj_len = max(1e-16, length(n_proj)); + + float cos_n = clamp(n_proj.z / n_proj_len, -1.0, 1.0); + float n = sign(dot(n_proj, t)) * fast_acos(cos_n); /* Angle between view vec and normal */ + + /* (Slide 54) */ + vec2 h = fast_acos(horizons); + h.x = -h.x; + + /* Clamping thetas (slide 58) */ + h.x = n + max(h.x - n, -M_PI_2); + h.y = n + min(h.y - n, M_PI_2); + + /* Solving inner integral */ + vec2 h_2 = 2.0 * h; + vec2 vd = -cos(h_2 - n) + cos_n + h_2 * sin(n); + float vis = (vd.x + vd.y) * 0.25 * n_proj_len; + + visibility += vis; + + /* Finding Bent normal */ + float b_angle = (h.x + h.y) * 0.5; + /* The 0.5 factor below is here to equilibrate the accumulated vectors. + * (sin(b_angle) * -t_phi) will accumulate to (phi_step * result_nor.xy * 0.5). + * (cos(b_angle) * 0.5) will accumulate to (phi_step * result_nor.z * 0.5). */ + bent_normal += vec3(sin(b_angle) * -t_phi, cos(b_angle) * 0.5); +} + +void gtao_deferred( + vec3 normal, vec3 position, vec4 noise, float frag_depth, out float visibility, out vec3 bent_normal) +{ + /* Fetch early, hide latency! */ + vec4 horizons = texelFetch(horizonBuffer, ivec2(gl_FragCoord.xy), 0); + + vec4 dirs; + dirs.xy = get_ao_dir(noise.x * 0.5); + dirs.zw = get_ao_dir(noise.x * 0.5 + 0.5); + vec2 uvs = get_uvs_from_view(position); + + bent_normal = vec3(0.0); + visibility = 0.0; + + horizons = unpack_horizons(horizons); + + integrate_slice(normal, dirs.xy, horizons.xy, visibility, bent_normal); + integrate_slice(normal, dirs.zw, horizons.zw, visibility, bent_normal); + + visibility *= 0.5; /* We integrated 2 slices. */ + + bent_normal = normalize(bent_normal); +} + +void gtao(vec3 normal, vec3 position, vec4 noise, out float visibility, out vec3 bent_normal) +{ + vec2 uvs = get_uvs_from_view(position); + vec2 max_dir = get_max_dir(position.z); + vec2 dir = get_ao_dir(noise.x); + + bent_normal = vec3(0.0); + visibility = 0.0; + + /* Only trace in 2 directions. May lead to a darker result but since it's mostly for + * alpha blended objects that will have overdraw, we limit the performance impact. */ + vec2 horizons = search_horizon_sweep(dir, position, uvs, noise.y, max_dir); + integrate_slice(normal, dir, horizons, visibility, bent_normal); + + bent_normal = normalize(bent_normal); +} + +/* Multibounce approximation base on surface albedo. + * Page 78 in the .pdf version. */ +float gtao_multibounce(float visibility, vec3 albedo) +{ + if (aoBounceFac == 0.0) return visibility; + + /* Median luminance. Because Colored multibounce looks bad. */ + float lum = dot(albedo, vec3(0.3333)); + + float a = 2.0404 * lum - 0.3324; + float b = -4.7951 * lum + 0.6417; + float c = 2.7552 * lum + 0.6903; + + float x = visibility; + return max(x, ((x * a + b) * x + c) * x); +} + +/* Use the right occlusion */ +float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec4 rand, out vec3 bent_normal) +{ +#ifndef USE_REFRACTION + if ((int(aoSettings) & USE_AO) > 0) { + float visibility; + vec3 vnor = mat3(ViewMatrix) * N; + +#ifdef ENABLE_DEFERED_AO + gtao_deferred(vnor, vpos, rand, gl_FragCoord.z, visibility, bent_normal); +#else + gtao(vnor, vpos, rand, visibility, bent_normal); +#endif + + /* Prevent some problems down the road. */ + visibility = max(1e-3, visibility); + + if ((int(aoSettings) & USE_BENT_NORMAL) != 0) { + /* The bent normal will show the facet look of the mesh. Try to minimize this. */ + float mix_fac = visibility * visibility; + bent_normal = normalize(mix(bent_normal, vnor, mix_fac)); + + bent_normal = transform_direction(ViewMatrixInverse, bent_normal); + } + else { + bent_normal = N; + } + + /* Scale by user factor */ + visibility = pow(visibility, aoFactor); + + return min(visibility, user_occlusion); + } +#endif + + bent_normal = N; + return user_occlusion; +} diff --git a/source/blender/draw/engines/eevee/shaders/background_vert.glsl b/source/blender/draw/engines/eevee/shaders/background_vert.glsl new file mode 100644 index 00000000000..b81aae9bcda --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/background_vert.glsl @@ -0,0 +1,20 @@ + +in vec2 pos; + +out vec3 varposition; +out vec3 varnormal; +out vec3 viewPosition; + +#ifndef VOLUMETRICS +/* necessary for compilation*/ +out vec3 worldPosition; +out vec3 worldNormal; +out vec3 viewNormal; +#endif + +void main() +{ + gl_Position = vec4(pos, 1.0, 1.0); + varposition = viewPosition = vec3(pos, -1.0); + varnormal = normalize(-varposition); +} diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl new file mode 100644 index 00000000000..704b039e0f6 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -0,0 +1,827 @@ + +#define M_PI 3.14159265358979323846 /* pi */ +#define M_2PI 6.28318530717958647692 /* 2*pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_1_PI 0.318309886183790671538 /* 1/pi */ +#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */ +#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */ + +#define LUT_SIZE 64 + +/* Buffers */ +uniform sampler2D colorBuffer; +uniform sampler2D depthBuffer; +uniform sampler2D maxzBuffer; +uniform sampler2D minzBuffer; +uniform sampler2DArray planarDepth; + +#define cameraForward normalize(ViewMatrixInverse[2].xyz) +#define cameraPos ViewMatrixInverse[3].xyz +#define cameraVec ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward) +#define viewCameraVec ((ProjectionMatrix[3][3] == 0.0) ? normalize(-viewPosition) : vec3(0.0, 0.0, 1.0)) + +/* ------- Structures -------- */ + +/* ------ Lights ----- */ +struct LightData { + vec4 position_influence; /* w : InfluenceRadius */ + vec4 color_spec; /* w : Spec Intensity */ + vec4 spotdata_radius_shadow; /* x : spot size, y : spot blend, z : radius, w: shadow id */ + vec4 rightvec_sizex; /* xyz: Normalized up vector, w: area size X or spot scale X */ + vec4 upvec_sizey; /* xyz: Normalized right vector, w: area size Y or spot scale Y */ + vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Lamp Type */ +}; + +/* convenience aliases */ +#define l_color color_spec.rgb +#define l_spec color_spec.a +#define l_position position_influence.xyz +#define l_influence position_influence.w +#define l_sizex rightvec_sizex.w +#define l_sizey upvec_sizey.w +#define l_right rightvec_sizex.xyz +#define l_up upvec_sizey.xyz +#define l_forward forwardvec_type.xyz +#define l_type forwardvec_type.w +#define l_spot_size spotdata_radius_shadow.x +#define l_spot_blend spotdata_radius_shadow.y +#define l_radius spotdata_radius_shadow.z +#define l_shadowid spotdata_radius_shadow.w + +/* ------ Shadows ----- */ +#ifndef MAX_CASCADE_NUM +#define MAX_CASCADE_NUM 4 +#endif + +struct ShadowData { + vec4 near_far_bias_exp; + vec4 shadow_data_start_end; + vec4 contact_shadow_data; +}; + +struct ShadowCubeData { + vec4 position; +}; + +struct ShadowCascadeData { + mat4 shadowmat[MAX_CASCADE_NUM]; + vec4 split_start_distances; + vec4 split_end_distances; +}; + +/* convenience aliases */ +#define sh_near near_far_bias_exp.x +#define sh_far near_far_bias_exp.y +#define sh_bias near_far_bias_exp.z +#define sh_exp near_far_bias_exp.w +#define sh_bleed near_far_bias_exp.w +#define sh_tex_start shadow_data_start_end.x +#define sh_data_start shadow_data_start_end.y +#define sh_multi_nbr shadow_data_start_end.z +#define sh_blur shadow_data_start_end.w +#define sh_contact_dist contact_shadow_data.x +#define sh_contact_offset contact_shadow_data.y +#define sh_contact_spread contact_shadow_data.z +#define sh_contact_thickness contact_shadow_data.w + +/* ------- Convenience functions --------- */ + +vec3 mul(mat3 m, vec3 v) { return m * v; } +mat3 mul(mat3 m1, mat3 m2) { return m1 * m2; } +vec3 transform_direction(mat4 m, vec3 v) { return mat3(m) * v; } +vec3 transform_point(mat4 m, vec3 v) { return (m * vec4(v, 1.0)).xyz; } +vec3 project_point(mat4 m, vec3 v) { + vec4 tmp = m * vec4(v, 1.0); + return tmp.xyz / tmp.w; +} + +#define min3(a, b, c) min(a, min(b, c)) +#define min4(a, b, c, d) min(a, min3(b, c, d)) +#define min5(a, b, c, d, e) min(a, min4(b, c, d, e)) +#define min6(a, b, c, d, e, f) min(a, min5(b, c, d, e, f)) +#define min7(a, b, c, d, e, f, g) min(a, min6(b, c, d, e, f, g)) +#define min8(a, b, c, d, e, f, g, h) min(a, min7(b, c, d, e, f, g, h)) +#define min9(a, b, c, d, e, f, g, h, i) min(a, min8(b, c, d, e, f, g, h, i)) + +#define max3(a, b, c) max(a, max(b, c)) +#define max4(a, b, c, d) max(a, max3(b, c, d)) +#define max5(a, b, c, d, e) max(a, max4(b, c, d, e)) +#define max6(a, b, c, d, e, f) max(a, max5(b, c, d, e, f)) +#define max7(a, b, c, d, e, f, g) max(a, max6(b, c, d, e, f, g)) +#define max8(a, b, c, d, e, f, g, h) max(a, max7(b, c, d, e, f, g, h)) +#define max9(a, b, c, d, e, f, g, h, i) max(a, max8(b, c, d, e, f, g, h, i)) + +#define avg3(a, b, c) (a + b + c) * (1.0 / 3.0) +#define avg4(a, b, c, d) (a + b + c + d) * (1.0 / 4.0) +#define avg5(a, b, c, d, e) (a + b + c + d + e) * (1.0 / 5.0) +#define avg6(a, b, c, d, e, f) (a + b + c + d + e + f) * (1.0 / 6.0) +#define avg7(a, b, c, d, e, f, g) (a + b + c + d + e + f + g) * (1.0 / 7.0) +#define avg8(a, b, c, d, e, f, g, h) (a + b + c + d + e + f + g + h) * (1.0 / 8.0) +#define avg9(a, b, c, d, e, f, g, h, i) (a + b + c + d + e + f + g + h + i) * (1.0 / 9.0) + +float min_v2(vec2 v) { return min(v.x, v.y); } +float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); } +float max_v2(vec2 v) { return max(v.x, v.y); } +float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); } + +float sum(vec2 v) { return dot(vec2(1.0), v); } +float sum(vec3 v) { return dot(vec3(1.0), v); } +float sum(vec4 v) { return dot(vec4(1.0), v); } + +float saturate(float a) { return clamp(a, 0.0, 1.0); } +vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); } +vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); } +vec4 saturate(vec4 a) { return clamp(a, 0.0, 1.0); } + +float distance_squared(vec2 a, vec2 b) { a -= b; return dot(a, a); } +float distance_squared(vec3 a, vec3 b) { a -= b; return dot(a, a); } +float len_squared(vec3 a) { return dot(a, a); } + +float inverse_distance(vec3 V) { return max( 1 / length(V), 1e-8); } + +vec2 mip_ratio_interp(float mip) { + float low_mip = floor(mip); + return mix(mipRatio[int(low_mip)], mipRatio[int(low_mip + 1.0)], mip - low_mip); +} +/* ------- Fast Math ------- */ + +/* [Drobot2014a] Low Level Optimizations for GCN */ +float fast_sqrt(float v) +{ + return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1)); +} + +vec2 fast_sqrt(vec2 v) +{ + return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1)); +} + +/* [Eberly2014] GPGPU Programming for Games and Science */ +float fast_acos(float v) +{ + float res = -0.156583 * abs(v) + M_PI_2; + res *= fast_sqrt(1.0 - abs(v)); + return (v >= 0) ? res : M_PI - res; +} + +vec2 fast_acos(vec2 v) +{ + vec2 res = -0.156583 * abs(v) + M_PI_2; + res *= fast_sqrt(1.0 - abs(v)); + v.x = (v.x >= 0) ? res.x : M_PI - res.x; + v.y = (v.y >= 0) ? res.y : M_PI - res.y; + return v; +} + +float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal) +{ + return dot(planenormal, planeorigin - lineorigin); +} + +float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal) +{ + return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection); +} + +float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane) +{ + vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz)); + vec3 h = lineorigin - plane_co; + return -dot(plane.xyz, h) / dot(plane.xyz, linedirection); +} + +vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal) +{ + float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal); + return lineorigin + linedirection * dist; +} + +vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane) +{ + float dist = line_plane_intersect_dist(lineorigin, linedirection, plane); + return lineorigin + linedirection * dist; +} + +float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) +{ + /* aligned plane normal */ + vec3 L = planeorigin - lineorigin; + float diskdist = length(L); + vec3 planenormal = -normalize(L); + return -diskdist / dot(planenormal, linedirection); +} + +vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) +{ + float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin); + if (dist < 0) { + /* if intersection is behind we fake the intersection to be + * really far and (hopefully) not inside the radius of interest */ + dist = 1e16; + } + return lineorigin + linedirection * dist; +} + +float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection) +{ + float a = dot(linedirection, linedirection); + float b = dot(linedirection, lineorigin); + float c = dot(lineorigin, lineorigin) - 1; + + float dist = 1e15; + float determinant = b * b - a * c; + if (determinant >= 0) + dist = (sqrt(determinant) - b) / a; + + return dist; +} + +float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) +{ + /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ */ + vec3 firstplane = (vec3( 1.0) - lineorigin) / linedirection; + vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection; + vec3 furthestplane = max(firstplane, secondplane); + + return min_v3(furthestplane); +} + + +/* Return texture coordinates to sample Surface LUT */ +vec2 lut_coords(float cosTheta, float roughness) +{ + float theta = acos(cosTheta); + vec2 coords = vec2(roughness, theta / M_PI_2); + + /* scale and bias coordinates, for correct filtered lookup */ + return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE; +} + +/* -- Tangent Space conversion -- */ +vec3 tangent_to_world(vec3 vector, vec3 N, vec3 T, vec3 B) +{ + return T * vector.x + B * vector.y + N * vector.z; +} + +vec3 world_to_tangent(vec3 vector, vec3 N, vec3 T, vec3 B) +{ + return vec3( dot(T, vector), dot(B, vector), dot(N, vector)); +} + +void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B) +{ + vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0,0.0,1.0) : vec3(1.0,0.0,0.0); + T = normalize( cross(UpVector, N) ); + B = cross(N, T); +} + +/* ---- Opengl Depth conversion ---- */ + +float linear_depth(bool is_persp, float z, float zf, float zn) +{ + if (is_persp) { + return (zn * zf) / (z * (zn - zf) + zf); + } + else { + return (z * 2.0 - 1.0) * zf; + } +} + +float buffer_depth(bool is_persp, float z, float zf, float zn) +{ + if (is_persp) { + return (zf * (zn - z)) / (z * (zn - zf)); + } + else { + return (z / (zf * 2.0)) + 0.5; + } +} + +float get_view_z_from_depth(float depth) +{ + if (ProjectionMatrix[3][3] == 0.0) { + float d = 2.0 * depth - 1.0; + return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]); + } + else { + return viewVecs[0].z + depth * viewVecs[1].z; + } +} + +float get_depth_from_view_z(float z) +{ + if (ProjectionMatrix[3][3] == 0.0) { + float d = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2]; + return d * 0.5 + 0.5; + } + else { + return (z - viewVecs[0].z) / viewVecs[1].z; + } +} + +vec2 get_uvs_from_view(vec3 view) +{ + vec3 ndc = project_point(ProjectionMatrix, view); + return ndc.xy * 0.5 + 0.5; +} + +vec3 get_view_space_from_depth(vec2 uvcoords, float depth) +{ + if (ProjectionMatrix[3][3] == 0.0) { + return vec3(viewVecs[0].xy + uvcoords * viewVecs[1].xy, 1.0) * get_view_z_from_depth(depth); + } + else { + return viewVecs[0].xyz + vec3(uvcoords, depth) * viewVecs[1].xyz; + } +} + +vec3 get_world_space_from_depth(vec2 uvcoords, float depth) +{ + return (ViewMatrixInverse * vec4(get_view_space_from_depth(uvcoords, depth), 1.0)).xyz; +} + +vec3 get_specular_reflection_dominant_dir(vec3 N, vec3 V, float roughness) +{ + vec3 R = -reflect(V, N); + float smoothness = 1.0 - roughness; + float fac = smoothness * (sqrt(smoothness) + roughness); + return normalize(mix(N, R, fac)); +} + +float specular_occlusion(float NV, float AO, float roughness) +{ + return saturate(pow(NV + AO, roughness) - 1.0 + AO); +} + +/* --- Refraction utils --- */ + +float ior_from_f0(float f0) +{ + float f = sqrt(f0); + return (-f - 1.0) / (f - 1.0); +} + +float f0_from_ior(float eta) +{ + float A = (eta - 1.0) / (eta + 1.0); + return A * A; +} + +vec3 get_specular_refraction_dominant_dir(vec3 N, vec3 V, float roughness, float ior) +{ + /* TODO: This a bad approximation. Better approximation should fit + * the refracted vector and roughness into the best prefiltered reflection + * lobe. */ + /* Correct the IOR for ior < 1.0 to not see the abrupt delimitation or the TIR */ + ior = (ior < 1.0) ? mix(ior, 1.0, roughness) : ior; + float eta = 1.0 / ior; + + float NV = dot(N, -V); + + /* Custom Refraction. */ + float k = 1.0 - eta * eta * (1.0 - NV * NV); + k = max(0.0, k); /* Only this changes. */ + vec3 R = eta * -V - (eta * NV + sqrt(k)) * N; + + return R; +} + +float get_btdf_lut(sampler2DArray btdf_lut_tex, float NV, float roughness, float ior) +{ + const vec3 lut_scale_bias_texel_size = vec3((LUT_SIZE - 1.0), 0.5, 1.5) / LUT_SIZE; + + vec3 coords; + /* Try to compensate for the low resolution and interpolation error. */ + coords.x = (ior > 1.0) + ? (0.9 + lut_scale_bias_texel_size.z) + (0.1 - lut_scale_bias_texel_size.z) * f0_from_ior(ior) + : (0.9 + lut_scale_bias_texel_size.z) * ior * ior; + coords.y = 1.0 - saturate(NV); + coords.xy *= lut_scale_bias_texel_size.x; + coords.xy += lut_scale_bias_texel_size.y; + + const float lut_lvl_ofs = 4.0; /* First texture lvl of roughness. */ + const float lut_lvl_scale = 16.0; /* How many lvl of roughness in the lut. */ + + float mip = roughness * lut_lvl_scale; + float mip_floor = floor(mip); + + coords.z = lut_lvl_ofs + mip_floor + 1.0; + float btdf_high = textureLod(btdf_lut_tex, coords, 0.0).r; + + coords.z -= 1.0; + float btdf_low = textureLod(btdf_lut_tex, coords, 0.0).r; + + float btdf = (ior == 1.0) ? 1.0 : mix(btdf_low, btdf_high, mip - coords.z); + + return btdf; +} + +/* ---- Encode / Decode Normal buffer data ---- */ +/* From http://aras-p.info/texts/CompactNormalStorage.html + * Using Method #4: Spheremap Transform */ +vec2 normal_encode(vec3 n, vec3 view) +{ + float p = sqrt(n.z * 8.0 + 8.0); + return n.xy / p + 0.5; +} + +vec3 normal_decode(vec2 enc, vec3 view) +{ + vec2 fenc = enc * 4.0 - 2.0; + float f = dot(fenc, fenc); + float g = sqrt(1.0 - f / 4.0); + vec3 n; + n.xy = fenc*g; + n.z = 1 - f / 2; + return n; +} + +/* ---- RGBM (shared multiplier) encoding ---- */ +/* From http://iwasbeingirony.blogspot.fr/2010/06/difference-between-rgbm-and-rgbd.html */ + +/* Higher RGBM_MAX_RANGE gives imprecision issues in low intensity. */ +#define RGBM_MAX_RANGE 512.0 + +vec4 rgbm_encode(vec3 rgb) +{ + float maxRGB = max_v3(rgb); + float M = maxRGB / RGBM_MAX_RANGE; + M = ceil(M * 255.0) / 255.0; + return vec4(rgb / (M * RGBM_MAX_RANGE), M); +} + +vec3 rgbm_decode(vec4 data) +{ + return data.rgb * (data.a * RGBM_MAX_RANGE); +} + +/* ---- RGBE (shared exponent) encoding ---- */ +vec4 rgbe_encode(vec3 rgb) +{ + float maxRGB = max_v3(rgb); + float fexp = ceil(log2(maxRGB)); + return vec4(rgb / exp2(fexp), (fexp + 128.0) / 255.0); +} + +vec3 rgbe_decode(vec4 data) +{ + float fexp = data.a * 255.0 - 128.0; + return data.rgb * exp2(fexp); +} + +#if 1 +#define irradiance_encode rgbe_encode +#define irradiance_decode rgbe_decode +#else /* No ecoding (when using floating point format) */ +#define irradiance_encode(X) (X).rgbb +#define irradiance_decode(X) (X).rgb +#endif + +/* Irradiance Visibility Encoding */ +#if 1 +vec4 visibility_encode(vec2 accum, float range) +{ + accum /= range; + + vec4 data; + data.x = fract(accum.x); + data.y = floor(accum.x) / 255.0; + data.z = fract(accum.y); + data.w = floor(accum.y) / 255.0; + + return data; +} + +vec2 visibility_decode(vec4 data, float range) +{ + return (data.xz + data.yw * 255.0) * range; +} +#else /* No ecoding (when using floating point format) */ +vec4 visibility_encode(vec2 accum, float range) +{ + return accum.xyxy; +} + +vec2 visibility_decode(vec4 data, float range) +{ + return data.xy; +} +#endif + +/* Fresnel monochromatic, perfect mirror */ +float F_eta(float eta, float cos_theta) +{ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + float c = abs(cos_theta); + float g = eta * eta - 1.0 + c * c; + float result; + + if (g > 0.0) { + g = sqrt(g); + vec2 g_c = vec2(g) + vec2(c, -c); + float A = g_c.y / g_c.x; + A *= A; + g_c *= c; + float B = (g_c.y - 1.0) / (g_c.x + 1.0); + B *= B; + result = 0.5 * A * (1.0 + B); + } + else { + result = 1.0; /* TIR (no refracted component) */ + } + + return result; +} + +/* Fresnel */ +vec3 F_schlick(vec3 f0, float cos_theta) +{ + float fac = 1.0 - cos_theta; + float fac2 = fac * fac; + fac = fac2 * fac2 * fac; + + /* Unreal specular matching : if specular color is below 2% intensity, + * (using green channel for intensity) treat as shadowning */ + return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * fac + (1.0 - fac) * f0; +} + +/* Fresnel approximation for LTC area lights (not MRP) */ +vec3 F_area(vec3 f0, vec2 lut) +{ + vec2 fac = normalize(lut.xy); /* XXX FIXME this does not work!!! */ + + /* Unreal specular matching : if specular color is below 2% intensity, + * treat as shadowning */ + return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * fac.y + fac.x * f0; +} + +/* Fresnel approximation for IBL */ +vec3 F_ibl(vec3 f0, vec2 lut) +{ + /* Unreal specular matching : if specular color is below 2% intensity, + * treat as shadowning */ + return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * lut.y + lut.x * f0; +} + +/* GGX */ +float D_ggx_opti(float NH, float a2) +{ + float tmp = (NH * a2 - NH) * NH + 1.0; + return M_PI * tmp*tmp; /* Doing RCP and mul a2 at the end */ +} + +float G1_Smith_GGX(float NX, float a2) +{ + /* Using Brian Karis approach and refactoring by NX/NX + * this way the (2*NL)*(2*NV) in G = G1(V) * G1(L) gets canceled by the brdf denominator 4*NL*NV + * Rcp is done on the whole G later + * Note that this is not convenient for the transmition formula */ + return NX + sqrt(NX * (NX - NX * a2) + a2); + /* return 2 / (1 + sqrt(1 + a2 * (1 - NX*NX) / (NX*NX) ) ); /* Reference function */ +} + +float bsdf_ggx(vec3 N, vec3 L, vec3 V, float roughness) +{ + float a = roughness; + float a2 = a * a; + + vec3 H = normalize(L + V); + float NH = max(dot(N, H), 1e-8); + float NL = max(dot(N, L), 1e-8); + float NV = max(dot(N, V), 1e-8); + + float G = G1_Smith_GGX(NV, a2) * G1_Smith_GGX(NL, a2); /* Doing RCP at the end */ + float D = D_ggx_opti(NH, a2); + + /* Denominator is canceled by G1_Smith */ + /* bsdf = D * G / (4.0 * NL * NV); /* Reference function */ + return NL * a2 / (D * G); /* NL to Fit cycles Equation : line. 345 in bsdf_microfacet.h */ +} + +void accumulate_light(vec3 light, float fac, inout vec4 accum) +{ + accum += vec4(light, 1.0) * min(fac, (1.0 - accum.a)); +} + +/* ----------- Cone Apperture Approximation --------- */ + +/* Return a fitted cone angle given the input roughness */ +float cone_cosine(float r) +{ + /* Using phong gloss + * roughness = sqrt(2/(gloss+2)) */ + float gloss = -2 + 2 / (r * r); + /* Drobot 2014 in GPUPro5 */ + // return cos(2.0 * sqrt(2.0 / (gloss + 2))); + /* Uludag 2014 in GPUPro5 */ + // return pow(0.244, 1 / (gloss + 1)); + /* Jimenez 2016 in Practical Realtime Strategies for Accurate Indirect Occlusion*/ + return exp2(-3.32193 * r * r); +} + +/* --------- Closure ---------- */ +#ifdef VOLUMETRICS + +struct Closure { + vec3 absorption; + vec3 scatter; + vec3 emission; + float anisotropy; +}; + +#define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec3(0.0), 0.0) + +Closure closure_mix(Closure cl1, Closure cl2, float fac) +{ + Closure cl; + cl.absorption = mix(cl1.absorption, cl2.absorption, fac); + cl.scatter = mix(cl1.scatter, cl2.scatter, fac); + cl.emission = mix(cl1.emission, cl2.emission, fac); + cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac); + return cl; +} + +Closure closure_add(Closure cl1, Closure cl2) +{ + Closure cl; + cl.absorption = cl1.absorption + cl2.absorption; + cl.scatter = cl1.scatter + cl2.scatter; + cl.emission = cl1.emission + cl2.emission; + cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */ + return cl; +} + +#else /* VOLUMETRICS */ + +struct Closure { + vec3 radiance; + float opacity; +# ifdef USE_SSS + vec4 sss_data; +# ifdef USE_SSS_ALBEDO + vec3 sss_albedo; +# endif +# endif + vec4 ssr_data; + vec2 ssr_normal; + int ssr_id; +}; + +/* This is hacking ssr_id to tag transparent bsdf */ +#define TRANSPARENT_CLOSURE_FLAG -2 +#define REFRACT_CLOSURE_FLAG -3 +#define NO_SSR -999 + +# ifdef USE_SSS +# ifdef USE_SSS_ALBEDO +#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec3(0.0), vec4(0.0), vec2(0.0), -1) +# else +#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec4(0.0), vec2(0.0), -1) +# endif +# else +#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec2(0.0), -1) +# endif + +uniform int outputSsrId; + +Closure closure_mix(Closure cl1, Closure cl2, float fac) +{ + Closure cl; + + if (cl1.ssr_id == TRANSPARENT_CLOSURE_FLAG) { + cl1.radiance = cl2.radiance; + cl1.ssr_normal = cl2.ssr_normal; + cl1.ssr_data = cl2.ssr_data; + cl1.ssr_id = cl2.ssr_id; +# ifdef USE_SSS + cl1.sss_data = cl2.sss_data; +# ifdef USE_SSS_ALBEDO + cl1.sss_albedo = cl2.sss_albedo; +# endif +# endif + } + if (cl2.ssr_id == TRANSPARENT_CLOSURE_FLAG) { + cl2.radiance = cl1.radiance; + cl2.ssr_normal = cl1.ssr_normal; + cl2.ssr_data = cl1.ssr_data; + cl2.ssr_id = cl1.ssr_id; +# ifdef USE_SSS + cl2.sss_data = cl1.sss_data; +# ifdef USE_SSS_ALBEDO + cl2.sss_albedo = cl1.sss_albedo; +# endif +# endif + } + if (cl1.ssr_id == outputSsrId) { + cl.ssr_data = mix(cl1.ssr_data.xyzw, vec4(vec3(0.0), cl1.ssr_data.w), fac); /* do not blend roughness */ + cl.ssr_normal = cl1.ssr_normal; + cl.ssr_id = cl1.ssr_id; + } + else { + cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */ + cl.ssr_normal = cl2.ssr_normal; + cl.ssr_id = cl2.ssr_id; + } + cl.radiance = mix(cl1.radiance, cl2.radiance, fac); + cl.opacity = mix(cl1.opacity, cl2.opacity, fac); + +# ifdef USE_SSS + cl.sss_data.rgb = mix(cl1.sss_data.rgb, cl2.sss_data.rgb, fac); + cl.sss_data.a = (cl1.sss_data.a > 0.0) ? cl1.sss_data.a : cl2.sss_data.a; +# ifdef USE_SSS_ALBEDO + /* TODO Find a solution to this. Dither? */ + cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo; +# endif +# endif + + return cl; +} + +Closure closure_add(Closure cl1, Closure cl2) +{ + Closure cl = (cl1.ssr_id == outputSsrId) ? cl1 : cl2; +# ifdef USE_SSS + cl.sss_data = (cl1.sss_data.a > 0.0) ? cl1.sss_data : cl2.sss_data; +# ifdef USE_SSS_ALBEDO + /* TODO Find a solution to this. Dither? */ + cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo; +# endif +# endif + cl.radiance = cl1.radiance + cl2.radiance; + cl.opacity = saturate(cl1.opacity + cl2.opacity); + return cl; +} + +# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY) +layout(location = 0) out vec4 fragColor; +layout(location = 1) out vec4 ssrNormals; +layout(location = 2) out vec4 ssrData; +# ifdef USE_SSS +layout(location = 3) out vec4 sssData; +# ifdef USE_SSS_ALBEDO +layout(location = 4) out vec4 sssAlbedo; +# endif /* USE_SSS_ALBEDO */ +# endif /* USE_SSS */ + +Closure nodetree_exec(void); /* Prototype */ + +# if defined(USE_ALPHA_BLEND_VOLUMETRICS) +/* Prototype because this file is included before volumetric_lib.glsl */ +vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth); +# endif + +#define NODETREE_EXEC +void main() +{ + Closure cl = nodetree_exec(); +# ifndef USE_ALPHA_BLEND + /* Prevent alpha hash material writing into alpha channel. */ + cl.opacity = 1.0; +# endif + +# if defined(USE_ALPHA_BLEND_VOLUMETRICS) + /* XXX fragile, better use real viewport resolution */ + vec2 uvs = gl_FragCoord.xy / vec2(2 * textureSize(maxzBuffer, 0).xy); + fragColor = volumetric_resolve(vec4(cl.radiance, cl.opacity), uvs, gl_FragCoord.z); +# else + fragColor = vec4(cl.radiance, cl.opacity); +# endif + + ssrNormals = cl.ssr_normal.xyyy; + ssrData = cl.ssr_data; +# ifdef USE_SSS + sssData = cl.sss_data; +# ifdef USE_SSS_ALBEDO + sssAlbedo = cl.sss_albedo.rgbb; +# endif +# endif + + /* For Probe capture */ +# ifdef USE_SSS +# ifdef USE_SSS_ALBEDO + fragColor.rgb += cl.sss_data.rgb * cl.sss_albedo.rgb * float(!sssToggle); +# else + fragColor.rgb += cl.sss_data.rgb * float(!sssToggle); +# endif +# endif +} + +# endif /* MESH_SHADER && !SHADOW_SHADER */ + +#endif /* VOLUMETRICS */ + +Closure nodetree_exec(void); /* Prototype */ + +/* TODO find a better place */ +#ifdef USE_MULTIPLY + +out vec4 fragColor; + +#define NODETREE_EXEC +void main() +{ + Closure cl = nodetree_exec(); + fragColor = vec4(mix(vec3(1.0), cl.radiance, cl.opacity), 1.0); +} +#endif diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl new file mode 100644 index 00000000000..aad71b3e48e --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl @@ -0,0 +1,186 @@ +/* Bsdf direct light function */ +/* in other word, how materials react to scene lamps */ + +/* Naming convention + * V View vector (normalized) + * N World Normal (normalized) + * L Outgoing Light Vector (Surface to Light in World Space) (normalized) + * Ldist Distance from surface to the light + * W World Pos + */ + +/* ------------ Diffuse ------------- */ + +float direct_diffuse_point(vec3 N, vec4 l_vector) +{ + float dist = l_vector.w; + vec3 L = l_vector.xyz / dist; + float bsdf = max(0.0, dot(N, L)); + bsdf /= dist * dist; + return bsdf; +} + +/* infinitly far away point source, no decay */ +float direct_diffuse_sun(LightData ld, vec3 N) +{ + float bsdf = max(0.0, dot(N, -ld.l_forward)); + bsdf *= M_1_PI; /* Normalize */ + return bsdf; +} + +#ifdef USE_LTC +float direct_diffuse_sphere(LightData ld, vec3 N, vec4 l_vector) +{ + float NL = dot(N, l_vector.xyz / l_vector.w); + + return ltc_evaluate_disk_simple(ld.l_radius / l_vector.w, NL); +} + +float direct_diffuse_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector) +{ + vec3 corners[4]; + corners[0] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey); + corners[1] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey); + corners[2] = normalize(l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey); + corners[3] = normalize(l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey); + + return ltc_evaluate_quad(corners, N); +} + +float direct_diffuse_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector) +{ + vec3 points[3]; + points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; + points[1] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; + points[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; + + return ltc_evaluate_disk(N, V, mat3(1), points); +} + +float direct_diffuse_unit_disc(LightData ld, vec3 N, vec3 V) +{ + float NL = dot(N, -ld.l_forward); + + return ltc_evaluate_disk_simple(ld.l_radius, NL); +} +#endif + +/* ----------- GGx ------------ */ +vec3 direct_ggx_point(vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) +{ + roughness = max(1e-3, roughness); + float dist = l_vector.w; + vec3 L = l_vector.xyz / dist; + float bsdf = bsdf_ggx(N, L, V, roughness); + bsdf /= dist * dist; + + /* Fresnel */ + float VH = max(dot(V, normalize(V + L)), 0.0); + return F_schlick(f0, VH) * bsdf; +} + +vec3 direct_ggx_sun(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0) +{ + roughness = max(1e-3, roughness); + float bsdf = bsdf_ggx(N, -ld.l_forward, V, roughness); + float VH = dot(V, -ld.l_forward) * 0.5 + 0.5; + return F_schlick(f0, VH) * bsdf; +} + +#ifdef USE_LTC +vec3 direct_ggx_sphere(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) +{ + roughness = clamp(roughness, 0.0008, 0.999); /* Fix low roughness artifacts. */ + + vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); + vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; + vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; + mat3 ltc_mat = ltc_matrix(ltc_lut); + + /* Make orthonormal basis. */ + vec3 L = l_vector.xyz / l_vector.w; + vec3 Px, Py; + make_orthonormal_basis(L, Px, Py); + Px *= ld.l_radius; + Py *= ld.l_radius; + + vec3 points[3]; + points[0] = l_vector.xyz - Px - Py; + points[1] = l_vector.xyz + Px - Py; + points[2] = l_vector.xyz + Px + Py; + + float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); + bsdf *= brdf_lut.b; /* Bsdf intensity */ + + vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; + + return spec; +} + +vec3 direct_ggx_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) +{ + vec3 points[3]; + points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; + points[1] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; + points[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; + + vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); + vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; + vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; + mat3 ltc_mat = ltc_matrix(ltc_lut); + + float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); + bsdf *= brdf_lut.b; /* Bsdf intensity */ + + vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; + + return spec; +} + +vec3 direct_ggx_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) +{ + vec3 corners[4]; + corners[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey; + corners[1] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; + corners[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; + corners[3] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; + + vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); + vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; + vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; + mat3 ltc_mat = ltc_matrix(ltc_lut); + + ltc_transform_quad(N, V, ltc_mat, corners); + float bsdf = ltc_evaluate_quad(corners, vec3(0.0, 0.0, 1.0)); + bsdf *= brdf_lut.b; /* Bsdf intensity */ + + vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; + + return spec; +} + +vec3 direct_ggx_unit_disc(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0) +{ + roughness = clamp(roughness, 0.0004, 0.999); /* Fix low roughness artifacts. */ + + vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); + vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; + vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; + mat3 ltc_mat = ltc_matrix(ltc_lut); + + vec3 Px = ld.l_right * ld.l_radius; + vec3 Py = ld.l_up * ld.l_radius; + + vec3 points[3]; + points[0] = -ld.l_forward - Px - Py; + points[1] = -ld.l_forward + Px - Py; + points[2] = -ld.l_forward + Px + Py; + + float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); + bsdf *= brdf_lut.b; /* Bsdf intensity */ + + vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; + + return spec; +} +#endif diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl new file mode 100644 index 00000000000..7fb4ee51a96 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl @@ -0,0 +1,46 @@ + +out vec4 FragColor; + +void main() { + vec3 N, T, B, V; + + float NV = ( 1.0 - (clamp(gl_FragCoord.y / BRDF_LUT_SIZE, 1e-4, 0.9999))); + float sqrtRoughness = clamp(gl_FragCoord.x / BRDF_LUT_SIZE, 1e-4, 0.9999); + float a = sqrtRoughness * sqrtRoughness; + float a2 = a * a; + + N = vec3(0.0, 0.0, 1.0); + T = vec3(1.0, 0.0, 0.0); + B = vec3(0.0, 1.0, 0.0); + V = vec3(sqrt(1.0 - NV * NV), 0.0, NV); + + setup_noise(); + + /* Integrating BRDF */ + float brdf_accum = 0.0; + float fresnel_accum = 0.0; + for (float i = 0; i < sampleCount; i++) { + vec3 H = sample_ggx(i, a2, N, T, B); /* Microfacet normal */ + vec3 L = -reflect(V, H); + float NL = L.z; + + if (NL > 0.0) { + float NH = max(H.z, 0.0); + float VH = max(dot(V, H), 0.0); + + float G1_v = G1_Smith_GGX(NV, a2); + float G1_l = G1_Smith_GGX(NL, a2); + float G_smith = 4.0 * NV * NL / (G1_v * G1_l); /* See G1_Smith_GGX for explanations. */ + + float brdf = (G_smith * VH) / (NH * NV); + float Fc = pow(1.0 - VH, 5.0); + + brdf_accum += (1.0 - Fc) * brdf; + fresnel_accum += Fc * brdf; + } + } + brdf_accum /= sampleCount; + fresnel_accum /= sampleCount; + + FragColor = vec4(brdf_accum, fresnel_accum, 0.0, 1.0); +} diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl new file mode 100644 index 00000000000..cce9d59dc12 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl @@ -0,0 +1,107 @@ + +uniform sampler1D texHammersley; +uniform sampler2D texJitter; +uniform float sampleCount; +uniform float invSampleCount; + +vec2 jitternoise = vec2(0.0); + +#ifndef UTIL_TEX +#define UTIL_TEX +uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) +#endif /* UTIL_TEX */ + +void setup_noise(void) +{ + jitternoise = texelfetch_noise_tex(gl_FragCoord.xy).rg; /* Global variable */ +} + +#ifdef HAMMERSLEY_SIZE +vec3 hammersley_3d(float i, float invsamplenbr) +{ + vec3 Xi; /* Theta, cos(Phi), sin(Phi) */ + + Xi.x = i * invsamplenbr; /* i/samples */ + Xi.x = fract(Xi.x + jitternoise.x); + + int u = int(mod(i + jitternoise.y * HAMMERSLEY_SIZE, HAMMERSLEY_SIZE)); + + Xi.yz = texelFetch(texHammersley, u, 0).rg; + + return Xi; +} + +vec3 hammersley_3d(float i) +{ + return hammersley_3d(i, invSampleCount); +} +#endif + +/* -------------- BSDFS -------------- */ + +float pdf_ggx_reflect(float NH, float a2) +{ + return NH * a2 / D_ggx_opti(NH, a2); +} + +float pdf_hemisphere() +{ + return 0.5 * M_1_PI; +} + +vec3 sample_ggx(vec3 rand, float a2) +{ + /* Theta is the aperture angle of the cone */ + float z = sqrt( (1.0 - rand.x) / ( 1.0 + a2 * rand.x - rand.x ) ); /* cos theta */ + float r = sqrt(max(0.0, 1.0f - z*z)); /* sin theta */ + float x = r * rand.y; + float y = r * rand.z; + + /* Microfacet Normal */ + return vec3(x, y, z); +} + +vec3 sample_ggx(vec3 rand, float a2, vec3 N, vec3 T, vec3 B, out float NH) +{ + vec3 Ht = sample_ggx(rand, a2); + NH = Ht.z; + return tangent_to_world(Ht, N, T, B); +} + +#ifdef HAMMERSLEY_SIZE +vec3 sample_ggx(float nsample, float a2, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + vec3 Ht = sample_ggx(Xi, a2); + return tangent_to_world(Ht, N, T, B); +} + +vec3 sample_hemisphere(float nsample, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + + float z = Xi.x; /* cos theta */ + float r = sqrt(max(0.0, 1.0f - z*z)); /* sin theta */ + float x = r * Xi.y; + float y = r * Xi.z; + + vec3 Ht = vec3(x, y, z); + + return tangent_to_world(Ht, N, T, B); +} + +vec3 sample_cone(float nsample, float angle, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + + float z = cos(angle * Xi.x); /* cos theta */ + float r = sqrt(max(0.0, 1.0f - z*z)); /* sin theta */ + float x = r * Xi.y; + float y = r * Xi.z; + + vec3 Ht = vec3(x, y, z); + + return tangent_to_world(Ht, N, T, B); +} +#endif diff --git a/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl new file mode 100644 index 00000000000..5f0af6a6f5b --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl @@ -0,0 +1,59 @@ + +uniform float a2; + +out vec4 FragColor; + +void main() { + vec3 N, T, B, V; + + float x = gl_FragCoord.x / BRDF_LUT_SIZE; + float y = gl_FragCoord.y / BRDF_LUT_SIZE; + /* There is little variation if ior > 1.0 so we + * maximize LUT precision for ior < 1.0 */ + x = x * 1.1; + float ior = (x > 1.0) ? ior_from_f0((x-1.0) * 10.0) : sqrt(x); + float NV = (1.0 - (clamp(y, 1e-4, 0.9999))); + + N = vec3(0.0, 0.0, 1.0); + T = vec3(1.0, 0.0, 0.0); + B = vec3(0.0, 1.0, 0.0); + V = vec3(sqrt(1.0 - NV * NV), 0.0, NV); + + setup_noise(); + + /* Integrating BTDF */ + float btdf_accum = 0.0; + for (float i = 0.0; i < sampleCount; i++) { + vec3 H = sample_ggx(i, a2, N, T, B); /* Microfacet normal */ + + float VH = dot(V, H); + + /* Check if there is total internal reflections. */ + float c = abs(VH); + float g = ior * ior - 1.0 + c * c; + + float eta = 1.0/ior; + if (dot(H, V) < 0.0) { + H = -H; + eta = ior; + } + + vec3 L = refract(-V, H, eta); + float NL = -dot(N, L); + + if ((NL > 0.0) && (g > 0.0)) { + float LH = dot(L, H); + + float G1_l = NL * 2.0 / G1_Smith_GGX(NL, a2); /* Balancing the adjustments made in G1_Smith */ + + /* btdf = abs(VH*LH) * (ior*ior) * D * G(V) * G(L) / (Ht2 * NV) + * pdf = (VH * abs(LH)) * (ior*ior) * D * G(V) / (Ht2 * NV) */ + float btdf = G1_l * abs(VH*LH) / (VH * abs(LH)); + + btdf_accum += btdf; + } + } + btdf_accum /= sampleCount; + + FragColor = vec4(btdf_accum, 0.0, 0.0, 1.0); +} diff --git a/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl new file mode 100644 index 00000000000..d6abb7dc175 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl @@ -0,0 +1,55 @@ + +layout(std140) uniform common_block { + mat4 pastViewProjectionMatrix; + vec4 viewVecs[2]; + vec2 mipRatio[10]; /* To correct mip level texel mis-alignement */ + /* Ambient Occlusion */ + vec4 aoParameters[2]; + /* Volumetric */ + ivec4 volTexSize; + vec4 volDepthParameters; /* Parameters to the volume Z equation */ + vec4 volInvTexSize; + vec4 volJitter; + vec4 volCoordScale; /* To convert volume uvs to screen uvs */ + float volHistoryAlpha; + float volLightClamp; + float volShadowSteps; + bool volUseLights; + /* Screen Space Reflections */ + vec4 ssrParameters; + float ssrBorderFac; + float ssrMaxRoughness; + float ssrFireflyFac; + float ssrBrdfBias; + bool ssrToggle; + /* SubSurface Scattering */ + float sssJitterThreshold; + bool sssToggle; + /* Specular */ + bool specToggle; + /* Lamps */ + int laNumLight; + /* Probes */ + int prbNumPlanar; + int prbNumRenderCube; + int prbNumRenderGrid; + int prbIrradianceVisSize; + float prbLodCubeMax; + float prbLodPlanarMax; +}; + +/* aoParameters */ +#define aoDistance aoParameters[0].x +#define aoSamples aoParameters[0].y /* UNUSED */ +#define aoFactor aoParameters[0].z +#define aoInvSamples aoParameters[0].w /* UNUSED */ + +#define aoOffset aoParameters[1].x /* UNUSED */ +#define aoBounceFac aoParameters[1].y +#define aoQuality aoParameters[1].z +#define aoSettings aoParameters[1].w + +/* ssrParameters */ +#define ssrQuality ssrParameters.x +#define ssrThickness ssrParameters.y +#define ssrPixelSize ssrParameters.zw diff --git a/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl b/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl new file mode 100644 index 00000000000..7de27a9fda9 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl @@ -0,0 +1,267 @@ +/* Precomputed table of concentric samples. + * Generated using this algorithm http://l2program.co.uk/900/concentric-disk-sampling + * Sorted by radius then by rotation angle. + * This way it's better for cache usage and for + * easily restricting to a certain number of + * sample while still having a circular kernel. */ + +#define CONCENTRIC_SAMPLE_NUM 256 +const vec2 concentric[CONCENTRIC_SAMPLE_NUM] = +vec2[CONCENTRIC_SAMPLE_NUM]( + vec2(0.0441941738242, 0.0441941738242), + vec2(-0.0441941738242, -0.0441941738242), + vec2(-0.0441941738242, 0.0441941738242), + vec2(0.0441941738242, -0.0441941738242), + vec2(0.181111092429, 0.0485285709567), + vec2(0.132582521472, 0.132582521472), + vec2(-0.181111092429, 0.0485285709567), + vec2(0.0485285709567, 0.181111092429), + vec2(-0.181111092429, -0.0485285709567), + vec2(-0.0485285709567, 0.181111092429), + vec2(-0.132582521472, -0.132582521472), + vec2(-0.132582521472, 0.132582521472), + vec2(-0.0485285709567, -0.181111092429), + vec2(0.0485285709567, -0.181111092429), + vec2(0.132582521472, -0.132582521472), + vec2(0.181111092429, -0.0485285709567), + vec2(0.308652606436, 0.0488857703251), + vec2(0.278439538809, 0.141872031169), + vec2(0.220970869121, 0.220970869121), + vec2(-0.278439538809, 0.141872031169), + vec2(0.141872031169, 0.278439538809), + vec2(-0.308652606436, 0.0488857703251), + vec2(0.0488857703251, 0.308652606436), + vec2(-0.308652606436, -0.0488857703251), + vec2(-0.0488857703251, 0.308652606436), + vec2(-0.278439538809, -0.141872031169), + vec2(-0.141872031169, 0.278439538809), + vec2(-0.220970869121, -0.220970869121), + vec2(-0.220970869121, 0.220970869121), + vec2(-0.141872031169, -0.278439538809), + vec2(-0.0488857703251, -0.308652606436), + vec2(0.0488857703251, -0.308652606436), + vec2(0.141872031169, -0.278439538809), + vec2(0.220970869121, -0.220970869121), + vec2(0.278439538809, -0.141872031169), + vec2(0.308652606436, -0.0488857703251), + vec2(0.434749091828, 0.0489844582952), + vec2(0.41294895701, 0.144497089605), + vec2(0.370441837162, 0.232764033475), + vec2(0.309359216769, 0.309359216769), + vec2(-0.370441837162, 0.232764033475), + vec2(0.232764033475, 0.370441837162), + vec2(-0.41294895701, 0.144497089605), + vec2(0.144497089605, 0.41294895701), + vec2(-0.434749091828, 0.0489844582952), + vec2(0.0489844582952, 0.434749091828), + vec2(-0.434749091828, -0.0489844582952), + vec2(-0.0489844582952, 0.434749091828), + vec2(-0.41294895701, -0.144497089605), + vec2(-0.144497089605, 0.41294895701), + vec2(-0.370441837162, -0.232764033475), + vec2(-0.232764033475, 0.370441837162), + vec2(-0.309359216769, -0.309359216769), + vec2(-0.309359216769, 0.309359216769), + vec2(-0.232764033475, -0.370441837162), + vec2(-0.144497089605, -0.41294895701), + vec2(-0.0489844582952, -0.434749091828), + vec2(0.0489844582952, -0.434749091828), + vec2(0.144497089605, -0.41294895701), + vec2(0.232764033475, -0.370441837162), + vec2(0.309359216769, -0.309359216769), + vec2(0.370441837162, -0.232764033475), + vec2(0.41294895701, -0.144497089605), + vec2(0.434749091828, -0.0489844582952), + vec2(0.560359517677, 0.0490251052956), + vec2(0.543333277288, 0.14558571287), + vec2(0.509798130208, 0.237722772229), + vec2(0.460773024913, 0.322636745447), + vec2(0.397747564417, 0.397747564417), + vec2(-0.460773024913, 0.322636745447), + vec2(0.322636745447, 0.460773024913), + vec2(-0.509798130208, 0.237722772229), + vec2(0.237722772229, 0.509798130208), + vec2(-0.543333277288, 0.14558571287), + vec2(0.14558571287, 0.543333277288), + vec2(-0.560359517677, 0.0490251052956), + vec2(0.0490251052956, 0.560359517677), + vec2(-0.560359517677, -0.0490251052956), + vec2(-0.0490251052956, 0.560359517677), + vec2(-0.543333277288, -0.14558571287), + vec2(-0.14558571287, 0.543333277288), + vec2(-0.509798130208, -0.237722772229), + vec2(-0.237722772229, 0.509798130208), + vec2(-0.460773024913, -0.322636745447), + vec2(-0.322636745447, 0.460773024913), + vec2(-0.397747564417, -0.397747564417), + vec2(-0.397747564417, 0.397747564417), + vec2(-0.322636745447, -0.460773024913), + vec2(-0.237722772229, -0.509798130208), + vec2(-0.14558571287, -0.543333277288), + vec2(-0.0490251052956, -0.560359517677), + vec2(0.0490251052956, -0.560359517677), + vec2(0.14558571287, -0.543333277288), + vec2(0.237722772229, -0.509798130208), + vec2(0.322636745447, -0.460773024913), + vec2(0.397747564417, -0.397747564417), + vec2(0.460773024913, -0.322636745447), + vec2(0.509798130208, -0.237722772229), + vec2(0.543333277288, -0.14558571287), + vec2(0.560359517677, -0.0490251052956), + vec2(0.685748328795, 0.0490456884495), + vec2(0.671788470355, 0.146138636568), + vec2(0.644152935937, 0.240256623474), + vec2(0.603404305327, 0.32948367837), + vec2(0.550372103135, 0.412003395727), + vec2(0.486135912066, 0.486135912066), + vec2(-0.550372103135, 0.412003395727), + vec2(0.412003395727, 0.550372103135), + vec2(-0.603404305327, 0.32948367837), + vec2(0.32948367837, 0.603404305327), + vec2(-0.644152935937, 0.240256623474), + vec2(0.240256623474, 0.644152935937), + vec2(-0.671788470355, 0.146138636568), + vec2(0.146138636568, 0.671788470355), + vec2(-0.685748328795, 0.0490456884495), + vec2(0.0490456884495, 0.685748328795), + vec2(-0.685748328795, -0.0490456884495), + vec2(-0.0490456884495, 0.685748328795), + vec2(-0.671788470355, -0.146138636568), + vec2(-0.146138636568, 0.671788470355), + vec2(-0.644152935937, -0.240256623474), + vec2(-0.240256623474, 0.644152935937), + vec2(-0.603404305327, -0.32948367837), + vec2(-0.32948367837, 0.603404305327), + vec2(-0.550372103135, -0.412003395727), + vec2(-0.412003395727, 0.550372103135), + vec2(-0.486135912066, -0.486135912066), + vec2(-0.486135912066, 0.486135912066), + vec2(-0.412003395727, -0.550372103135), + vec2(-0.32948367837, -0.603404305327), + vec2(-0.240256623474, -0.644152935937), + vec2(-0.146138636568, -0.671788470355), + vec2(-0.0490456884495, -0.685748328795), + vec2(0.0490456884495, -0.685748328795), + vec2(0.146138636568, -0.671788470355), + vec2(0.240256623474, -0.644152935937), + vec2(0.32948367837, -0.603404305327), + vec2(0.412003395727, -0.550372103135), + vec2(0.486135912066, -0.486135912066), + vec2(0.550372103135, -0.412003395727), + vec2(0.603404305327, -0.32948367837), + vec2(0.644152935937, -0.240256623474), + vec2(0.671788470355, -0.146138636568), + vec2(0.685748328795, -0.0490456884495), + vec2(0.811017637806, 0.0490575291556), + vec2(0.799191174395, 0.146457218224), + vec2(0.775710704038, 0.241721231257), + vec2(0.740918624869, 0.33346040443), + vec2(0.695322283745, 0.420336974019), + vec2(0.639586577995, 0.501084084011), + vec2(0.574524259714, 0.574524259714), + vec2(-0.639586577995, 0.501084084011), + vec2(0.501084084011, 0.639586577995), + vec2(-0.695322283745, 0.420336974019), + vec2(0.420336974019, 0.695322283745), + vec2(-0.740918624869, 0.33346040443), + vec2(0.33346040443, 0.740918624869), + vec2(-0.775710704038, 0.241721231257), + vec2(0.241721231257, 0.775710704038), + vec2(-0.799191174395, 0.146457218224), + vec2(0.146457218224, 0.799191174395), + vec2(-0.811017637806, 0.0490575291556), + vec2(0.0490575291556, 0.811017637806), + vec2(-0.811017637806, -0.0490575291556), + vec2(-0.0490575291556, 0.811017637806), + vec2(-0.799191174395, -0.146457218224), + vec2(-0.146457218224, 0.799191174395), + vec2(-0.775710704038, -0.241721231257), + vec2(-0.241721231257, 0.775710704038), + vec2(-0.740918624869, -0.33346040443), + vec2(-0.33346040443, 0.740918624869), + vec2(-0.695322283745, -0.420336974019), + vec2(-0.420336974019, 0.695322283745), + vec2(-0.639586577995, -0.501084084011), + vec2(-0.501084084011, 0.639586577995), + vec2(-0.574524259714, -0.574524259714), + vec2(-0.574524259714, 0.574524259714), + vec2(-0.501084084011, -0.639586577995), + vec2(-0.420336974019, -0.695322283745), + vec2(-0.33346040443, -0.740918624869), + vec2(-0.241721231257, -0.775710704038), + vec2(-0.146457218224, -0.799191174395), + vec2(-0.0490575291556, -0.811017637806), + vec2(0.0490575291556, -0.811017637806), + vec2(0.146457218224, -0.799191174395), + vec2(0.241721231257, -0.775710704038), + vec2(0.33346040443, -0.740918624869), + vec2(0.420336974019, -0.695322283745), + vec2(0.501084084011, -0.639586577995), + vec2(0.574524259714, -0.574524259714), + vec2(0.639586577995, -0.501084084011), + vec2(0.695322283745, -0.420336974019), + vec2(0.740918624869, -0.33346040443), + vec2(0.775710704038, -0.241721231257), + vec2(0.799191174395, -0.146457218224), + vec2(0.811017637806, -0.0490575291556), + vec2(0.936215188832, 0.0490649589778), + vec2(0.925957819308, 0.146657310975), + vec2(0.905555462146, 0.242642854784), + vec2(0.875231649841, 0.335969952699), + vec2(0.835318616427, 0.425616093506), + vec2(0.786253657449, 0.510599095327), + vec2(0.728574338866, 0.589987866609), + vec2(0.662912607362, 0.662912607362), + vec2(-0.728574338866, 0.589987866609), + vec2(0.589987866609, 0.728574338866), + vec2(-0.786253657449, 0.510599095327), + vec2(0.510599095327, 0.786253657449), + vec2(-0.835318616427, 0.425616093506), + vec2(0.425616093506, 0.835318616427), + vec2(-0.875231649841, 0.335969952699), + vec2(0.335969952699, 0.875231649841), + vec2(-0.905555462146, 0.242642854784), + vec2(0.242642854784, 0.905555462146), + vec2(-0.925957819308, 0.146657310975), + vec2(0.146657310975, 0.925957819308), + vec2(-0.936215188832, 0.0490649589778), + vec2(0.0490649589778, 0.936215188832), + vec2(-0.936215188832, -0.0490649589778), + vec2(-0.0490649589778, 0.936215188832), + vec2(-0.925957819308, -0.146657310975), + vec2(-0.146657310975, 0.925957819308), + vec2(-0.905555462146, -0.242642854784), + vec2(-0.242642854784, 0.905555462146), + vec2(-0.875231649841, -0.335969952699), + vec2(-0.335969952699, 0.875231649841), + vec2(-0.835318616427, -0.425616093506), + vec2(-0.425616093506, 0.835318616427), + vec2(-0.786253657449, -0.510599095327), + vec2(-0.510599095327, 0.786253657449), + vec2(-0.728574338866, -0.589987866609), + vec2(-0.589987866609, 0.728574338866), + vec2(-0.662912607362, -0.662912607362), + vec2(-0.662912607362, 0.662912607362), + vec2(-0.589987866609, -0.728574338866), + vec2(-0.510599095327, -0.786253657449), + vec2(-0.425616093506, -0.835318616427), + vec2(-0.335969952699, -0.875231649841), + vec2(-0.242642854784, -0.905555462146), + vec2(-0.146657310975, -0.925957819308), + vec2(-0.0490649589778, -0.936215188832), + vec2(0.0490649589778, -0.936215188832), + vec2(0.146657310975, -0.925957819308), + vec2(0.242642854784, -0.905555462146), + vec2(0.335969952699, -0.875231649841), + vec2(0.425616093506, -0.835318616427), + vec2(0.510599095327, -0.786253657449), + vec2(0.589987866609, -0.728574338866), + vec2(0.662912607362, -0.662912607362), + vec2(0.728574338866, -0.589987866609), + vec2(0.786253657449, -0.510599095327), + vec2(0.835318616427, -0.425616093506), + vec2(0.875231649841, -0.335969952699), + vec2(0.905555462146, -0.242642854784), + vec2(0.925957819308, -0.146657310975), + vec2(0.936215188832, -0.0490649589778) +); diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl new file mode 100644 index 00000000000..fd1a10de548 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl @@ -0,0 +1,23 @@ + +uniform vec3 basecol; +uniform float metallic; +uniform float specular; +uniform float roughness; + +Closure nodetree_exec(void) +{ + vec3 dielectric = vec3(0.034) * specular * 2.0; + vec3 albedo = mix(basecol, vec3(0.0), metallic); + vec3 f0 = mix(dielectric, basecol, metallic); + vec3 N = (gl_FrontFacing) ? worldNormal : -worldNormal; + vec3 out_diff, out_spec, ssr_spec; + eevee_closure_default(N, albedo, f0, 1, roughness, 1.0, out_diff, out_spec, ssr_spec); + + Closure result = Closure(out_spec + out_diff * albedo, 1.0, vec4(ssr_spec, roughness), normal_encode(normalize(viewNormal), viewCameraVec), 0); + +#ifdef LOOKDEV + gl_FragDepth = 0.0; +#endif + + return result; +} diff --git a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl new file mode 100644 index 00000000000..1f0ef76da0c --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl @@ -0,0 +1,62 @@ + +#define M_PI 3.14159265358979323846 + +uniform float backgroundAlpha; +uniform mat4 ProjectionMatrix; +uniform mat4 ProjectionMatrixInverse; +uniform mat4 ViewMatrixInverse; +#ifdef LOOKDEV +uniform mat3 StudioLightMatrix; +uniform sampler2D image; +uniform float studioLightBackground = 1.0; +in vec3 viewPosition; +#endif +uniform vec3 color; + +out vec4 FragColor; + +void background_transform_to_world(vec3 viewvec, out vec3 worldvec) +{ + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + worldvec = (ViewMatrixInverse * co).xyz; +} + +float hypot(float x, float y) +{ + return sqrt(x * x + y * y); +} + +void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color) +{ + vec3 nco = normalize(co); + float u = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; + float v = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; + + /* Fix pole bleeding */ + float width = float(textureSize(ima, 0).x); + float texel_width = 1.0 / width; + v = clamp(v, texel_width, 1.0 - texel_width); + + /* Fix u = 0 seam */ + /* This is caused by texture filtering, since uv don't have smooth derivatives + * at u = 0 or 2PI, hardware filtering is using the smallest mipmap for certain + * texels. So we force the highest mipmap and don't do anisotropic filtering. */ + color = textureLod(ima, vec2(u, v), 0.0); +} + +void main() { +#ifdef LOOKDEV + vec3 worldvec; + vec4 background_color; + background_transform_to_world(viewPosition, worldvec); + node_tex_environment_equirectangular(StudioLightMatrix * worldvec, image, background_color); + background_color.rgb = mix(color, background_color.rgb, studioLightBackground); +#else + vec3 background_color = color; +#endif + + FragColor = vec4(clamp(background_color.rgb, vec3(0.0), vec3(1e10)), backgroundAlpha); +} diff --git a/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl new file mode 100644 index 00000000000..c3674c8f74c --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl @@ -0,0 +1,218 @@ +/* Original implementation by Keijiro Takahashi + * Blender integration by Clément Foucault + * + * Original License : + * + * Kino/Bloom v2 - Bloom filter for Unity + * + * Copyright (C) 2015, 2016 Keijiro Takahashi + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + **/ + +uniform sampler2D sourceBuffer; /* Buffer to filter */ +uniform vec2 sourceBufferTexelSize; + +/* Step Blit */ +uniform vec4 curveThreshold; +uniform float clampIntensity; + +/* Step Upsample */ +uniform sampler2D baseBuffer; /* Previous accumulation buffer */ +uniform vec2 baseBufferTexelSize; +uniform float sampleScale; + +/* Step Resolve */ +uniform vec3 bloomColor; + +in vec4 uvcoordsvar; + +out vec4 FragColor; + +/* -------------- Utils ------------- */ + +vec3 safe_color(vec3 c) +{ + /* Clamp to avoid black square artifacts if a pixel goes NaN. */ + return clamp(c, vec3(0.0), vec3(1e20)); /* 1e20 arbitrary. */ +} + +float brightness(vec3 c) +{ + return max(max(c.r, c.g), c.b); +} + +/* 3-tap median filter */ +vec3 median(vec3 a, vec3 b, vec3 c) +{ + return a + b + c - min(min(a, b), c) - max(max(a, b), c); +} + +/* ------------- Filters ------------ */ + +vec3 downsample_filter_high(sampler2D tex, vec2 uv, vec2 texelSize) +{ + /* Downsample with a 4x4 box filter + anti-flicker filter */ + vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1); + + vec3 s1 = textureLod(tex, uv + d.xy, 0.0).rgb; + vec3 s2 = textureLod(tex, uv + d.zy, 0.0).rgb; + vec3 s3 = textureLod(tex, uv + d.xw, 0.0).rgb; + vec3 s4 = textureLod(tex, uv + d.zw, 0.0).rgb; + + /* Karis's luma weighted average (using brightness instead of luma) */ + float s1w = 1.0 / (brightness(s1) + 1.0); + float s2w = 1.0 / (brightness(s2) + 1.0); + float s3w = 1.0 / (brightness(s3) + 1.0); + float s4w = 1.0 / (brightness(s4) + 1.0); + float one_div_wsum = 1.0 / (s1w + s2w + s3w + s4w); + + return (s1 * s1w + s2 * s2w + s3 * s3w + s4 * s4w) * one_div_wsum; +} + +vec3 downsample_filter(sampler2D tex, vec2 uv, vec2 texelSize) +{ + /* Downsample with a 4x4 box filter */ + vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1); + + vec3 s; + s = textureLod(tex, uv + d.xy, 0.0).rgb; + s += textureLod(tex, uv + d.zy, 0.0).rgb; + s += textureLod(tex, uv + d.xw, 0.0).rgb; + s += textureLod(tex, uv + d.zw, 0.0).rgb; + + return s * (1.0 / 4); +} + +vec3 upsample_filter_high(sampler2D tex, vec2 uv, vec2 texelSize) +{ + /* 9-tap bilinear upsampler (tent filter) */ + vec4 d = texelSize.xyxy * vec4(1, 1, -1, 0) * sampleScale; + + vec3 s; + s = textureLod(tex, uv - d.xy, 0.0).rgb; + s += textureLod(tex, uv - d.wy, 0.0).rgb * 2; + s += textureLod(tex, uv - d.zy, 0.0).rgb; + + s += textureLod(tex, uv + d.zw, 0.0).rgb * 2; + s += textureLod(tex, uv , 0.0).rgb * 4; + s += textureLod(tex, uv + d.xw, 0.0).rgb * 2; + + s += textureLod(tex, uv + d.zy, 0.0).rgb; + s += textureLod(tex, uv + d.wy, 0.0).rgb * 2; + s += textureLod(tex, uv + d.xy, 0.0).rgb; + + return s * (1.0 / 16.0); +} + +vec3 upsample_filter(sampler2D tex, vec2 uv, vec2 texelSize) +{ + /* 4-tap bilinear upsampler */ + vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1) * (sampleScale * 0.5); + + vec3 s; + s = textureLod(tex, uv + d.xy, 0.0).rgb; + s += textureLod(tex, uv + d.zy, 0.0).rgb; + s += textureLod(tex, uv + d.xw, 0.0).rgb; + s += textureLod(tex, uv + d.zw, 0.0).rgb; + + return s * (1.0 / 4.0); +} + +/* ----------- Steps ----------- */ + +vec4 step_blit(void) +{ + vec2 uv = uvcoordsvar.xy + sourceBufferTexelSize.xy * 0.5; + +#ifdef HIGH_QUALITY /* Anti flicker */ + vec3 d = sourceBufferTexelSize.xyx * vec3(1, 1, 0); + vec3 s0 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy, 0.0).rgb); + vec3 s1 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy - d.xz, 0.0).rgb); + vec3 s2 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy + d.xz, 0.0).rgb); + vec3 s3 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy - d.zy, 0.0).rgb); + vec3 s4 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy + d.zy, 0.0).rgb); + vec3 m = median(median(s0.rgb, s1, s2), s3, s4); +#else + vec3 s0 = safe_color(textureLod(sourceBuffer, uvcoordsvar.xy, 0.0).rgb); + vec3 m = s0.rgb; +#endif + + /* Pixel brightness */ + float br = brightness(m); + + /* Under-threshold part: quadratic curve */ + float rq = clamp(br - curveThreshold.x, 0, curveThreshold.y); + rq = curveThreshold.z * rq * rq; + + /* Combine and apply the brightness response curve. */ + m *= max(rq, br - curveThreshold.w) / max(1e-5, br); + + /* Clamp pixel intensity */ + br = max(1e-5, brightness(m)); + m *= 1.0 - max(0.0, br - clampIntensity) / br; + + return vec4(m, 1.0); +} + +vec4 step_downsample(void) +{ +#ifdef HIGH_QUALITY /* Anti flicker */ + vec3 sample = downsample_filter_high(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize); +#else + vec3 sample = downsample_filter(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize); +#endif + return vec4(sample, 1.0); +} + +vec4 step_upsample(void) +{ +#ifdef HIGH_QUALITY + vec3 blur = upsample_filter_high(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize); +#else + vec3 blur = upsample_filter(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize); +#endif + vec3 base = textureLod(baseBuffer, uvcoordsvar.xy, 0.0).rgb; + return vec4(base + blur, 1.0); +} + +vec4 step_resolve(void) +{ +#ifdef HIGH_QUALITY + vec3 blur = upsample_filter_high(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize); +#else + vec3 blur = upsample_filter(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize); +#endif + vec4 base = textureLod(baseBuffer, uvcoordsvar.xy, 0.0); + vec3 cout = base.rgb + blur * bloomColor; + return vec4(cout, base.a); +} + +void main(void) +{ +#if defined(STEP_BLIT) + FragColor = step_blit(); +#elif defined(STEP_DOWNSAMPLE) + FragColor = step_downsample(); +#elif defined(STEP_UPSAMPLE) + FragColor = step_upsample(); +#elif defined(STEP_RESOLVE) + FragColor = step_resolve(); +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl new file mode 100644 index 00000000000..34d92fab2c2 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl @@ -0,0 +1,222 @@ + +uniform mat4 ProjectionMatrix; + +uniform sampler2D colorBuffer; +uniform sampler2D depthBuffer; + +uniform vec3 dofParams; + +#define dof_aperturesize dofParams.x +#define dof_distance dofParams.y +#define dof_invsensorsize dofParams.z + +uniform vec4 bokehParams[2]; + +#define bokeh_rotation bokehParams[0].x +#define bokeh_ratio bokehParams[0].y +#define bokeh_maxsize bokehParams[0].z +#define bokeh_sides bokehParams[1] /* Polygon Bokeh shape number of sides (with precomputed vars) */ + +uniform vec2 nearFar; /* Near & far view depths values */ + +#define M_PI 3.1415926535897932384626433832795 +#define M_2PI 6.2831853071795864769252868 + +/* -------------- Utils ------------- */ + +/* divide by sensor size to get the normalized size */ +#define calculate_coc(zdepth) (dof_aperturesize * (dof_distance / zdepth - 1.0) * dof_invsensorsize) + +#define linear_depth(z) ((ProjectionMatrix[3][3] == 0.0) \ + ? (nearFar.x * nearFar.y) / (z * (nearFar.x - nearFar.y) + nearFar.y) \ + : (z * 2.0 - 1.0) * nearFar.y) + +#define weighted_sum(a, b, c, d, e) (a * e.x + b * e.y + c * e.z + d * e.w) + +float max_v4(vec4 v) { return max(max(v.x, v.y), max(v.z, v.w)); } + +#define THRESHOLD 0.0 + +#ifdef STEP_DOWNSAMPLE + +layout(location = 0) out vec4 nearColor; +layout(location = 1) out vec4 farColor; +layout(location = 2) out vec2 cocData; + +/* Downsample the color buffer to half resolution. + * Weight color samples by + * Compute maximum CoC for near and far blur. */ +void main(void) +{ + ivec4 uvs = ivec4(gl_FragCoord.xyxy) * 2 + ivec4(0, 0, 1, 1); + + /* custom downsampling */ + vec4 color1 = texelFetch(colorBuffer, uvs.xy, 0); + vec4 color2 = texelFetch(colorBuffer, uvs.zw, 0); + vec4 color3 = texelFetch(colorBuffer, uvs.zy, 0); + vec4 color4 = texelFetch(colorBuffer, uvs.xw, 0); + + /* Leverage SIMD by combining 4 depth samples into a vec4 */ + vec4 depth; + depth.r = texelFetch(depthBuffer, uvs.xy, 0).r; + depth.g = texelFetch(depthBuffer, uvs.zw, 0).r; + depth.b = texelFetch(depthBuffer, uvs.zy, 0).r; + depth.a = texelFetch(depthBuffer, uvs.xw, 0).r; + + vec4 zdepth = linear_depth(depth); + + /* Compute signed CoC for each depth samples */ + vec4 coc_near = calculate_coc(zdepth); + vec4 coc_far = -coc_near; + + /* now we need to write the near-far fields premultiplied by the coc */ + vec4 near_weights = step(THRESHOLD, coc_near); + vec4 far_weights = step(THRESHOLD, coc_far); + + /* now write output to weighted buffers. */ + nearColor = weighted_sum(color1, color2, color3, color4, near_weights); + farColor = weighted_sum(color1, color2, color3, color4, far_weights); + + /* Normalize the color (don't divide by 0.0) */ + nearColor /= max(1e-6, dot(near_weights, near_weights)); + farColor /= max(1e-6, dot(far_weights, far_weights)); + + float max_near_coc = max(max_v4(coc_near), 0.0); + float max_far_coc = max(max_v4(coc_far), 0.0); + + cocData = vec2(max_near_coc, max_far_coc); +} + +#elif defined(STEP_SCATTER) + +flat in vec4 color; +flat in float smoothFac; +flat in ivec2 edge; +/* coordinate used for calculating radius */ +in vec2 particlecoord; + +out vec4 fragColor; + +/* accumulate color in the near/far blur buffers */ +void main(void) +{ + /* Discard to avoid bleeding onto the next layer */ + if (int(gl_FragCoord.x) * edge.x + edge.y > 0) + discard; + + /* Circle Dof */ + float dist = length(particlecoord); + + /* Ouside of bokeh shape */ + if (dist > 1.0) + discard; + + /* Regular Polygon Dof */ + if (bokeh_sides.x > 0.0) { + /* Circle parametrization */ + float theta = atan(particlecoord.y, particlecoord.x) + bokeh_rotation; + + /* Optimized version of : + * float denom = theta - (M_2PI / bokeh_sides) * floor((bokeh_sides * theta + M_PI) / M_2PI); + * float r = cos(M_PI / bokeh_sides) / cos(denom); */ + float denom = theta - bokeh_sides.y * floor(bokeh_sides.z * theta + 0.5); + float r = bokeh_sides.w / cos(denom); + + /* Divide circle radial coord by the shape radius for angle theta. + * Giving us the new linear radius to the shape edge. */ + dist /= r; + + /* Ouside of bokeh shape */ + if (dist > 1.0) + discard; + } + + fragColor = color; + + /* Smooth the edges a bit. This effectively reduce the bokeh shape + * but does fade out the undersampling artifacts. */ + if (smoothFac < 1.0) { + fragColor *= smoothstep(1.0, smoothFac, dist); + } +} + +#elif defined(STEP_RESOLVE) + +#define MERGE_THRESHOLD 4.0 + +uniform sampler2D scatterBuffer; + +in vec4 uvcoordsvar; +out vec4 fragColor; + +vec4 upsample_filter(sampler2D tex, vec2 uv, vec2 texelSize) +{ + /* TODO FIXME: Clamp the sample position + * depending on the layer to avoid bleeding. + * This is not really noticeable so leaving it as is for now. */ + +#if 1 /* 9-tap bilinear upsampler (tent filter) */ + vec4 d = texelSize.xyxy * vec4(1, 1, -1, 0); + + vec4 s; + s = textureLod(tex, uv - d.xy, 0.0); + s += textureLod(tex, uv - d.wy, 0.0) * 2; + s += textureLod(tex, uv - d.zy, 0.0); + + s += textureLod(tex, uv + d.zw, 0.0) * 2; + s += textureLod(tex, uv , 0.0) * 4; + s += textureLod(tex, uv + d.xw, 0.0) * 2; + + s += textureLod(tex, uv + d.zy, 0.0); + s += textureLod(tex, uv + d.wy, 0.0) * 2; + s += textureLod(tex, uv + d.xy, 0.0); + + return s * (1.0 / 16.0); +#else + /* 4-tap bilinear upsampler */ + vec4 d = texelSize.xyxy * vec4(-1, -1, +1, +1) * 0.5; + + vec4 s; + s = textureLod(tex, uv + d.xy, 0.0); + s += textureLod(tex, uv + d.zy, 0.0); + s += textureLod(tex, uv + d.xw, 0.0); + s += textureLod(tex, uv + d.zw, 0.0); + + return s * (1.0 / 4.0); +#endif +} + +/* Combine the Far and Near color buffers */ +void main(void) +{ + vec2 uv = uvcoordsvar.xy; + /* Recompute Near / Far CoC per pixel */ + float depth = textureLod(depthBuffer, uv, 0.0).r; + float zdepth = linear_depth(depth); + float coc_signed = calculate_coc(zdepth); + float coc_far = max(-coc_signed, 0.0); + float coc_near = max(coc_signed, 0.0); + + vec2 texelSize = vec2(0.5, 1.0) / vec2(textureSize(scatterBuffer, 0)); + vec4 srccolor = textureLod(colorBuffer, uv, 0.0); + + vec2 near_uv = uv * vec2(0.5, 1.0); + vec2 far_uv = near_uv + vec2(0.5, 0.0); + vec4 farcolor = upsample_filter(scatterBuffer, far_uv, texelSize); + vec4 nearcolor = upsample_filter(scatterBuffer, near_uv, texelSize); + + float farweight = farcolor.a; + float nearweight = nearcolor.a; + + if (farcolor.a > 0.0) farcolor /= farcolor.a; + if (nearcolor.a > 0.0) nearcolor /= nearcolor.a; + + float mixfac = smoothstep(1.0, MERGE_THRESHOLD, abs(coc_signed)); + + float totalweight = nearweight + farweight; + farcolor = mix(srccolor, farcolor, mixfac); + nearcolor = mix(srccolor, nearcolor, mixfac); + fragColor = mix(farcolor, nearcolor, nearweight / max(1e-6, totalweight)); +} + +#endif diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl new file mode 100644 index 00000000000..6e43115d799 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl @@ -0,0 +1,106 @@ + +uniform vec4 bokehParams[2]; + +#define bokeh_rotation bokehParams[0].x +#define bokeh_ratio bokehParams[0].y +#define bokeh_maxsize bokehParams[0].z + +uniform sampler2D nearBuffer; +uniform sampler2D farBuffer; +uniform sampler2D cocBuffer; + +flat out vec4 color; +flat out float smoothFac; +flat out ivec2 edge; +out vec2 particlecoord; + +#define M_PI 3.1415926535897932384626433832795 + +/* Scatter pass, calculate a triangle covering the CoC. */ +void main() +{ + ivec2 tex_size = textureSize(cocBuffer, 0); + /* We render to a double width texture so compute + * the target texel size accordingly */ + vec2 texel_size = vec2(0.5, 1.0) / vec2(tex_size); + + int t_id = gl_VertexID / 3; /* Triangle Id */ + + ivec2 texelco = ivec2(0); + /* some math to get the target pixel */ + texelco.x = t_id % tex_size.x; + texelco.y = t_id / tex_size.x; + + vec2 cocs = texelFetch(cocBuffer, texelco, 0).rg; + + bool is_near = (cocs.x > cocs.y); + float coc = (is_near) ? cocs.x : cocs.y; + + /* Clamp to max size for performance */ + coc = min(coc, bokeh_maxsize); + + if (coc >= 1.0) { + if (is_near) { + color = texelFetch(nearBuffer, texelco, 0); + } + else { + color = texelFetch(farBuffer, texelco, 0); + } + /* find the area the pixel will cover and divide the color by it */ + color.a = 1.0 / (coc * coc * M_PI); + color.rgb *= color.a; + + /* Compute edge to discard fragment that does not belong to the other layer. */ + edge.x = (is_near) ? 1 : -1; + edge.y = (is_near) ? -tex_size.x + 1 : tex_size.x; + } + else { + /* Don't produce any fragments */ + color = vec4(0.0); + gl_Position = vec4(0.0, 0.0, 0.0, 1.0); + return; + } + + /* Generate Triangle : less memory fetches from a VBO */ + int v_id = gl_VertexID % 3; /* Vertex Id */ + + /* Extend to cover at least the unit circle */ + const float extend = (cos(M_PI / 4.0) + 1.0) * 2.0; + /* Crappy diagram + * ex 1 + * | \ + * | \ + * 1 | \ + * | \ + * | \ + * 0 | x \ + * | Circle \ + * | Origin \ + * -1 0 --------------- 2 + * -1 0 1 ex + **/ + gl_Position.x = float(v_id / 2) * extend - 1.0; /* int divisor round down */ + gl_Position.y = float(v_id % 2) * extend - 1.0; + gl_Position.z = 0.0; + gl_Position.w = 1.0; + + /* Generate Triangle */ + particlecoord = gl_Position.xy; + + gl_Position.xy *= coc * texel_size * vec2(bokeh_ratio, 1.0); + gl_Position.xy -= 1.0 - 0.5 * texel_size; /* NDC Bottom left */ + gl_Position.xy += (0.5 + vec2(texelco) * 2.0) * texel_size; + + /* Push far plane to left side. */ + gl_Position.x += (!is_near) ? 1.0 : 0.0; + + /* don't do smoothing for small sprites */ + if (coc > 3.0) { + smoothFac = 1.0 - 1.5 / coc; + } + else { + smoothFac = 1.0; + } + + int tex_width = textureSize(cocBuffer, 0).x; +} diff --git a/source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl new file mode 100644 index 00000000000..79f86cfae58 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl @@ -0,0 +1,30 @@ +/** + * Simple downsample shader. Takes the average of the 4 texels of lower mip. + **/ + +uniform samplerCube source; +uniform float texelSize; + +flat in int fFace; + +out vec4 FragColor; + +const vec3 maj_axes[6] = vec3[6](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3( 0.0, 0.0, 1.0), vec3( 0.0, 0.0, -1.0)); +const vec3 x_axis[6] = vec3[6](vec3(0.0, 0.0, -1.0), vec3( 0.0, 0.0, 1.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3( 1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0)); +const vec3 y_axis[6] = vec3[6](vec3(0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0), vec3( 0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0)); + +float brightness(vec3 c) +{ + return max(max(c.r, c.g), c.b); +} + +void main() +{ + vec2 uvs = gl_FragCoord.xy * texelSize; + + uvs = 2.0 * uvs - 1.0; + + vec3 cubevec = x_axis[fFace] * uvs.x + y_axis[fFace] * uvs.y + maj_axes[fFace]; + + FragColor = textureLod(source, cubevec, 0.0); +} diff --git a/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl new file mode 100644 index 00000000000..8f06e161a20 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl @@ -0,0 +1,37 @@ +/** + * Simple downsample shader. Takes the average of the 4 texels of lower mip. + **/ + +uniform sampler2D source; +uniform float fireflyFactor; + +out vec4 FragColor; + +float brightness(vec3 c) +{ + return max(max(c.r, c.g), c.b); +} + +void main() +{ +#if 0 + /* Reconstructing Target uvs like this avoid missing pixels if NPO2 */ + vec2 uvs = gl_FragCoord.xy * 2.0 / vec2(textureSize(source, 0)); + + FragColor = textureLod(source, uvs, 0.0); +#else + vec2 texel_size = 1.0 / vec2(textureSize(source, 0)); + vec2 uvs = gl_FragCoord.xy * 2.0 * texel_size; + vec4 ofs = texel_size.xyxy * vec4(0.75, 0.75, -0.75, -0.75); + + FragColor = textureLod(source, uvs + ofs.xy, 0.0); + FragColor += textureLod(source, uvs + ofs.xw, 0.0); + FragColor += textureLod(source, uvs + ofs.zy, 0.0); + FragColor += textureLod(source, uvs + ofs.zw, 0.0); + FragColor *= 0.25; + + /* Clamped brightness. */ + float luma = max(1e-8, brightness(FragColor.rgb)); + FragColor *= 1.0 - max(0.0, luma - fireflyFactor) / luma; +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl new file mode 100644 index 00000000000..b7bcf5c8a8b --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl @@ -0,0 +1,77 @@ +/** + * This shader only compute maximum horizon angles for each directions. + * The final integration is done at the resolve stage with the shading normal. + **/ + +uniform float rotationOffset; + +out vec4 FragColor; + +#ifdef DEBUG_AO +uniform sampler2D normalBuffer; + +void main() +{ + vec2 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xy; + vec2 uvs = saturate(gl_FragCoord.xy * texel_size); + + float depth = textureLod(depthBuffer, uvs, 0.0).r; + + vec3 viewPosition = get_view_space_from_depth(uvs, depth); + vec3 V = viewCameraVec; + vec3 normal = normal_decode(texture(normalBuffer, uvs).rg, V); + + vec3 bent_normal; + float visibility; + + vec4 noise = texelfetch_noise_tex(gl_FragCoord.xy); + + gtao_deferred(normal, viewPosition, noise, depth, visibility, bent_normal); + + /* Handle Background case. Prevent artifact due to uncleared Horizon Render Target. */ + FragColor = vec4((depth == 1.0) ? 0.0 : visibility); +} + +#else + +#ifdef LAYERED_DEPTH +uniform sampler2DArray depthBufferLayered; +uniform int layer; +# define gtao_depthBuffer depthBufferLayered +# define gtao_textureLod(a, b, c) textureLod(a, vec3(b, layer), c) + +#else +# define gtao_depthBuffer depthBuffer +# define gtao_textureLod(a, b, c) textureLod(a, b, c) + +#endif + +void main() +{ + vec2 uvs = saturate(gl_FragCoord.xy / vec2(textureSize(gtao_depthBuffer, 0).xy)); + float depth = gtao_textureLod(gtao_depthBuffer, uvs, 0.0).r; + + if (depth == 1.0) { + /* Do not trace for background */ + FragColor = vec4(0.0); + return; + } + + /* Avoid self shadowing. */ + depth = saturate(depth - 3e-6); /* Tweaked for 24bit depth buffer. */ + + vec3 viewPosition = get_view_space_from_depth(uvs, depth); + vec4 noise = texelfetch_noise_tex(gl_FragCoord.xy); + vec2 max_dir = get_max_dir(viewPosition.z); + vec4 dirs; + dirs.xy = get_ao_dir(noise.x * 0.5); + dirs.zw = get_ao_dir(noise.x * 0.5 + 0.5); + + /* Search in 4 directions. */ + FragColor.xy = search_horizon_sweep(dirs.xy, viewPosition, uvs, noise.y, max_dir); + FragColor.zw = search_horizon_sweep(dirs.zw, viewPosition, uvs, noise.y, max_dir); + + /* Resize output for integer texture. */ + FragColor = pack_horizons(FragColor); +} +#endif diff --git a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl new file mode 100644 index 00000000000..24dbb5436d9 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl @@ -0,0 +1,96 @@ +/** + * Shader that downsample depth buffer, + * saving min and max value of each texel in the above mipmaps. + * Adapted from http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/ + **/ + +#extension GL_ARB_texture_gather : enable + +#ifdef LAYERED +uniform sampler2DArray depthBuffer; +uniform int depthLayer; +#else +uniform sampler2D depthBuffer; +#endif + +#ifdef LAYERED +# define sampleLowerMip(t) texelFetch(depthBuffer, ivec3(t, depthLayer), 0).r +# define gatherLowerMip(t) textureGather(depthBuffer, vec3(t, depthLayer)) +#else +# define sampleLowerMip(t) texelFetch(depthBuffer, t, 0).r +# define gatherLowerMip(t) textureGather(depthBuffer, t) +#endif + +#ifdef MIN_PASS +#define minmax2(a, b) min(a, b) +#define minmax3(a, b, c) min(min(a, b), c) +#define minmax4(a, b, c, d) min(min(min(a, b), c), d) +#else /* MAX_PASS */ +#define minmax2(a, b) max(a, b) +#define minmax3(a, b, c) max(max(a, b), c) +#define minmax4(a, b, c, d) max(max(max(a, b), c), d) +#endif + +/* On some AMD card / driver conbination, it is needed otherwise, + * the shader does not write anything. */ +#if defined(GPU_INTEL) || defined(GPU_ATI) +out vec4 fragColor; +#endif + +void main() +{ + ivec2 texelPos = ivec2(gl_FragCoord.xy); + ivec2 mipsize = textureSize(depthBuffer, 0).xy; + +#ifndef COPY_DEPTH + texelPos *= 2; +#endif + +#ifdef COPY_DEPTH + float val = sampleLowerMip(texelPos); +#else + vec4 samp; +# ifdef GL_ARB_texture_gather + samp = gatherLowerMip(vec2(texelPos) / vec2(mipsize)); +# else + samp.x = sampleLowerMip(texelPos); + samp.y = sampleLowerMip(texelPos + ivec2(1, 0)); + samp.z = sampleLowerMip(texelPos + ivec2(1, 1)); + samp.w = sampleLowerMip(texelPos + ivec2(0, 1)); +# endif + + float val = minmax4(samp.x, samp.y, samp.z, samp.w); + + /* if we are reducing an odd-width texture then fetch the edge texels */ + if (((mipsize.x & 1) != 0) && (texelPos.x == mipsize.x - 3)) { + /* if both edges are odd, fetch the top-left corner texel */ + if (((mipsize.y & 1) != 0) && (texelPos.y == mipsize.y - 3)) { + samp.x = sampleLowerMip(texelPos + ivec2(2, 2)); + val = minmax2(val, samp.x); + } +# ifdef GL_ARB_texture_gather + samp = gatherLowerMip((vec2(texelPos) + vec2(1.0, 0.0)) / vec2(mipsize)); +# else + samp.y = sampleLowerMip(texelPos + ivec2(2, 0)); + samp.z = sampleLowerMip(texelPos + ivec2(2, 1)); +# endif + val = minmax3(val, samp.y, samp.z); + } + /* if we are reducing an odd-height texture then fetch the edge texels */ + if (((mipsize.y & 1) != 0) && (texelPos.y == mipsize.y - 3)) { +# ifdef GL_ARB_texture_gather + samp = gatherLowerMip((vec2(texelPos) + vec2(0.0, 1.0)) / vec2(mipsize)); +# else + samp.x = sampleLowerMip(texelPos + ivec2(0, 2)); + samp.y = sampleLowerMip(texelPos + ivec2(1, 2)); +# endif + val = minmax3(val, samp.x, samp.y); + } +#endif + +#if defined(GPU_INTEL) || defined(GPU_ATI) + /* Use color format instead of 24bit depth texture */ + fragColor = vec4(val); +#endif + gl_FragDepth = val; +} diff --git a/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl new file mode 100644 index 00000000000..fe38b2e9aac --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl @@ -0,0 +1,31 @@ +/* Convert depth to Mist factor */ +uniform vec3 mistSettings; + +#define mistStart mistSettings.x +#define mistInvDistance mistSettings.y +#define mistFalloff mistSettings.z + +out vec4 fragColor; + +void main() +{ + vec2 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xy; + vec2 uvs = gl_FragCoord.xy * texel_size; + + float depth = textureLod(depthBuffer, uvs, 0.0).r; + vec3 co = get_view_space_from_depth(uvs, depth); + + float zcor = (ProjectionMatrix[3][3] == 0.0) ? length(co) : -co.z; + + /* bring depth into 0..1 range */ + float mist = saturate((zcor - mistStart) * mistInvDistance); + + /* falloff */ + mist = pow(mist, mistFalloff); + + fragColor = vec4(mist); + + // if (mist > 0.999) fragColor = vec4(1.0); + // else if (mist > 0.0001) fragColor = vec4(0.5); + // else fragColor = vec4(0.0); +} diff --git a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl new file mode 100644 index 00000000000..73e284570cd --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl @@ -0,0 +1,65 @@ + +uniform sampler2D colorBuffer; +uniform sampler2D depthBuffer; + + +/* current frame */ +uniform mat4 currInvViewProjMatrix; + +/* past frame frame */ +uniform mat4 pastViewProjMatrix; + +in vec4 uvcoordsvar; + +out vec4 FragColor; + +#define MAX_SAMPLE 64 + +uniform int samples; + +float wang_hash_noise(uint s) +{ + uint seed = (uint(gl_FragCoord.x) * 1664525u + uint(gl_FragCoord.y)) + s; + + seed = (seed ^ 61u) ^ (seed >> 16u); + seed *= 9u; + seed = seed ^ (seed >> 4u); + seed *= 0x27d4eb2du; + seed = seed ^ (seed >> 15u); + + float value = float(seed); + value *= 1.0 / 4294967296.0; + return fract(value); +} + +void main() +{ + vec3 ndc_pos; + ndc_pos.xy = uvcoordsvar.xy; + ndc_pos.z = texture(depthBuffer, uvcoordsvar.xy).x; + + float inv_samples = 1.0 / float(samples); + float noise = 2.0 * wang_hash_noise(0u) * inv_samples; + + /* Normalize Device Coordinates are [-1, +1]. */ + ndc_pos = ndc_pos * 2.0 - 1.0; + + vec4 p = currInvViewProjMatrix * vec4(ndc_pos, 1.0); + vec3 world_pos = p.xyz / p.w; /* Perspective divide */ + + /* Now find where was this pixel position + * inside the past camera viewport */ + vec4 old_ndc = pastViewProjMatrix * vec4(world_pos, 1.0); + old_ndc.xyz /= old_ndc.w; /* Perspective divide */ + + vec2 motion = (ndc_pos.xy - old_ndc.xy) * 0.25; /* 0.25 fit cycles ref */ + + float inc = 2.0 * inv_samples; + float i = -1.0 + noise; + + FragColor = vec4(0.0); + for (int j = 0; j < samples && j < MAX_SAMPLE; j++) { + FragColor += textureLod(colorBuffer, uvcoordsvar.xy + motion * i, 0.0) * inv_samples; + i += inc; + } +} diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl new file mode 100644 index 00000000000..0f76f8e1b8c --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -0,0 +1,477 @@ + +/* Based on Stochastic Screen Space Reflections + * https://www.ea.com/frostbite/news/stochastic-screen-space-reflections */ + +#define MAX_MIP 9.0 + +uniform ivec2 halfresOffset; + +ivec2 encode_hit_data(vec2 hit_pos, bool has_hit, bool is_planar) +{ + ivec2 hit_data = ivec2(saturate(hit_pos) * 32767.0); /* 16bit signed int limit */ + hit_data.x *= (is_planar) ? -1 : 1; + hit_data.y *= (has_hit) ? 1 : -1; + return hit_data; +} + +vec2 decode_hit_data(vec2 hit_data, out bool has_hit, out bool is_planar) +{ + is_planar = (hit_data.x < 0); + has_hit = (hit_data.y > 0); + return vec2(abs(hit_data)) / 32767.0; /* 16bit signed int limit */ +} + +#ifdef STEP_RAYTRACE + +uniform sampler2D normalBuffer; +uniform sampler2D specroughBuffer; + +layout(location = 0) out ivec2 hitData; +layout(location = 1) out float pdfData; + +void do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, vec3 viewPosition, float a2, vec4 rand) +{ + float NH; + vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */ + float pdf = pdf_ggx_reflect(NH, a2); + + vec3 R = reflect(-V, H); + R = reflect(R, planeNormal); + + /* If ray is bad (i.e. going below the plane) regenerate. */ + if (dot(R, planeNormal) > 0.0) { + vec3 H = sample_ggx(rand.xzw * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */ + pdf = pdf_ggx_reflect(NH, a2); + + R = reflect(-V, H); + R = reflect(R, planeNormal); + } + + pdfData = min(1024e32, pdf); /* Theoretical limit of 16bit float */ + + /* Since viewspace hit position can land behind the camera in this case, + * we save the reflected view position (visualize it as the hit position + * below the reflection plane). This way it's garanted that the hit will + * be in front of the camera. That let us tag the bad rays with a negative + * sign in the Z component. */ + vec3 hit_pos = raycast(index, viewPosition, R * 1e16, 1e16, rand.y, ssrQuality, a2, false); + + hitData = encode_hit_data(hit_pos.xy, (hit_pos.z > 0.0), true); +} + +void do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 viewPosition, float a2, vec4 rand) +{ + float NH; + vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */ + float pdf = pdf_ggx_reflect(NH, a2); + + vec3 R = reflect(-V, H); + pdfData = min(1024e32, pdf); /* Theoretical limit of 16bit float */ + + vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, rand.y, ssrQuality, a2, true); + + hitData = encode_hit_data(hit_pos.xy, (hit_pos.z > 0.0), false); +} + +void main() +{ +#ifdef FULLRES + ivec2 fullres_texel = ivec2(gl_FragCoord.xy); + ivec2 halfres_texel = fullres_texel; +#else + ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2 + halfresOffset; + ivec2 halfres_texel = ivec2(gl_FragCoord.xy); +#endif + + float depth = texelFetch(depthBuffer, fullres_texel, 0).r; + + /* Default: not hits. */ + hitData = encode_hit_data(vec2(0.5), false, false); + pdfData = 0.0; + + /* Early out */ + /* We can't do discard because we don't clear the render target. */ + if (depth == 1.0) + return; + + vec2 uvs = vec2(fullres_texel) / vec2(textureSize(depthBuffer, 0)); + + /* Using view space */ + vec3 viewPosition = get_view_space_from_depth(uvs, depth); + vec3 V = viewCameraVec; + vec3 N = normal_decode(texelFetch(normalBuffer, fullres_texel, 0).rg, V); + + /* Retrieve pixel data */ + vec4 speccol_roughness = texelFetch(specroughBuffer, fullres_texel, 0).rgba; + + /* Early out */ + if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0) + return; + + float roughness = speccol_roughness.a; + float roughnessSquared = max(1e-3, roughness * roughness); + float a2 = roughnessSquared * roughnessSquared; + + /* Early out */ + if (roughness > ssrMaxRoughness + 0.2) + return; + + vec4 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0); + + /* Gives *perfect* reflection for very small roughness */ + if (roughness < 0.04) { + rand.xzw *= 0.0; + } + /* Importance sampling bias */ + rand.x = mix(rand.x, 0.0, ssrBrdfBias); + + vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition); + vec3 wN = transform_direction(ViewMatrixInverse, N); + + vec3 T, B; + make_orthonormal_basis(N, T, B); /* Generate tangent space */ + + /* Planar Reflections */ + for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; ++i) { + PlanarData pd = planars_data[i]; + + float fade = probe_attenuation_planar(pd, worldPosition, wN, 0.0); + + if (fade > 0.5) { + /* Find view vector / reflection plane intersection. */ + /* TODO optimize, use view space for all. */ + vec3 tracePosition = line_plane_intersect(worldPosition, cameraVec, pd.pl_plane_eq); + tracePosition = transform_point(ViewMatrix, tracePosition); + vec3 planeNormal = transform_direction(ViewMatrix, pd.pl_normal); + + do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand); + return; + } + } + + do_ssr(V, N, T, B, viewPosition, a2, rand); +} + +#else /* STEP_RESOLVE */ + +uniform sampler2D prevColorBuffer; /* previous frame */ +uniform sampler2D normalBuffer; +uniform sampler2D specroughBuffer; + +uniform isampler2D hitBuffer; +uniform sampler2D pdfBuffer; + +uniform int neighborOffset; + +const ivec2 neighbors[32] = ivec2[32]( + ivec2( 0, 0), ivec2( 1, 1), ivec2(-2, 0), ivec2( 0, -2), + ivec2( 0, 0), ivec2( 1, -1), ivec2(-2, 0), ivec2( 0, 2), + ivec2( 0, 0), ivec2(-1, -1), ivec2( 2, 0), ivec2( 0, 2), + ivec2( 0, 0), ivec2(-1, 1), ivec2( 2, 0), ivec2( 0, -2), + + ivec2( 0, 0), ivec2( 2, 2), ivec2(-2, 2), ivec2( 0, -1), + ivec2( 0, 0), ivec2( 2, -2), ivec2(-2, -2), ivec2( 0, 1), + ivec2( 0, 0), ivec2(-2, -2), ivec2(-2, 2), ivec2( 1, 0), + ivec2( 0, 0), ivec2( 2, 2), ivec2( 2, -2), ivec2(-1, 0) +); + +out vec4 fragColor; + +#if 0 /* Finish reprojection with motion vectors */ +vec3 get_motion_vector(vec3 pos) +{ +} + +/* http://bitsquid.blogspot.fr/2017/06/reprojecting-reflections_22.html */ +vec3 find_reflection_incident_point(vec3 cam, vec3 hit, vec3 pos, vec3 N) +{ + float d_cam = point_plane_projection_dist(cam, pos, N); + float d_hit = point_plane_projection_dist(hit, pos, N); + + if (d_hit < d_cam) { + /* Swap */ + float tmp = d_cam; + d_cam = d_hit; + d_hit = tmp; + } + + vec3 proj_cam = cam - (N * d_cam); + vec3 proj_hit = hit - (N * d_hit); + + return (proj_hit - proj_cam) * d_cam / (d_cam + d_hit) + proj_cam; +} +#endif + +float brightness(vec3 c) +{ + return max(max(c.r, c.g), c.b); +} + +vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N) +{ + /* TODO real reprojection with motion vectors, etc... */ + return project_point(pastViewProjectionMatrix, hit).xy * 0.5 + 0.5; +} + +float get_sample_depth(vec2 hit_co, bool is_planar, float planar_index) +{ + if (is_planar) { + return textureLod(planarDepth, vec3(hit_co, planar_index), 0.0).r; + } + else { + return textureLod(depthBuffer, hit_co, 0.0).r; + } +} + +vec3 get_hit_vector( + vec3 hit_pos, PlanarData pd, vec3 worldPosition, vec3 N, vec3 V, bool is_planar, + inout vec2 hit_co, inout float mask) +{ + vec3 hit_vec; + + if (is_planar) { + /* Reflect back the hit position to have it in non-reflected world space */ + vec3 trace_pos = line_plane_intersect(worldPosition, V, pd.pl_plane_eq); + hit_vec = hit_pos - trace_pos; + hit_vec = reflect(hit_vec, pd.pl_normal); + } + else { + /* Find hit position in previous frame. */ + mask = screen_border_mask(gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0))); + hit_co = get_reprojected_reflection(hit_pos, worldPosition, N); + hit_vec = hit_pos - worldPosition; + } + + mask = min(mask, screen_border_mask(hit_co)); + return hit_vec; +} + +vec3 get_scene_color(vec2 ref_uvs, float mip, float planar_index, bool is_planar) +{ + if (is_planar) { + return textureLod(probePlanars, vec3(ref_uvs, planar_index), min(mip, prbLodPlanarMax)).rgb; + } + else { + return textureLod(prevColorBuffer, ref_uvs, mip).rgb; + } +} + +vec4 get_ssr_samples( + vec4 hit_pdf, ivec4 hit_data[2], + PlanarData pd, float planar_index, vec3 worldPosition, vec3 N, vec3 V, + float roughnessSquared, float cone_tan, vec2 source_uvs, + inout float weight_acc) +{ + bvec4 is_planar, has_hit; + vec4 hit_co[2]; + hit_co[0].xy = decode_hit_data(hit_data[0].xy, has_hit.x, is_planar.x); + hit_co[0].zw = decode_hit_data(hit_data[0].zw, has_hit.y, is_planar.y); + hit_co[1].xy = decode_hit_data(hit_data[1].xy, has_hit.z, is_planar.z); + hit_co[1].zw = decode_hit_data(hit_data[1].zw, has_hit.w, is_planar.w); + + vec4 hit_depth; + hit_depth.x = get_sample_depth(hit_co[0].xy, is_planar.x, planar_index); + hit_depth.y = get_sample_depth(hit_co[0].zw, is_planar.y, planar_index); + hit_depth.z = get_sample_depth(hit_co[1].xy, is_planar.z, planar_index); + hit_depth.w = get_sample_depth(hit_co[1].zw, is_planar.w, planar_index); + + /* Hit position in view space. */ + vec3 hit_view[4]; + hit_view[0] = get_view_space_from_depth(hit_co[0].xy, hit_depth.x); + hit_view[1] = get_view_space_from_depth(hit_co[0].zw, hit_depth.y); + hit_view[2] = get_view_space_from_depth(hit_co[1].xy, hit_depth.z); + hit_view[3] = get_view_space_from_depth(hit_co[1].zw, hit_depth.w); + + vec4 homcoord = vec4(hit_view[0].z, hit_view[1].z, hit_view[2].z, hit_view[3].z); + homcoord = ProjectionMatrix[2][3] * homcoord + ProjectionMatrix[3][3]; + + /* Hit position in world space. */ + vec3 hit_pos[4]; + hit_pos[0] = transform_point(ViewMatrixInverse, hit_view[0]); + hit_pos[1] = transform_point(ViewMatrixInverse, hit_view[1]); + hit_pos[2] = transform_point(ViewMatrixInverse, hit_view[2]); + hit_pos[3] = transform_point(ViewMatrixInverse, hit_view[3]); + + /* Get actual hit vector and hit coordinate (from last frame). */ + vec4 mask = vec4(1.0); + hit_pos[0] = get_hit_vector(hit_pos[0], pd, worldPosition, N, V, is_planar.x, hit_co[0].xy, mask.x); + hit_pos[1] = get_hit_vector(hit_pos[1], pd, worldPosition, N, V, is_planar.y, hit_co[0].zw, mask.y); + hit_pos[2] = get_hit_vector(hit_pos[2], pd, worldPosition, N, V, is_planar.z, hit_co[1].xy, mask.z); + hit_pos[3] = get_hit_vector(hit_pos[3], pd, worldPosition, N, V, is_planar.w, hit_co[1].zw, mask.w); + + vec4 hit_dist; + hit_dist.x = length(hit_pos[0]); + hit_dist.y = length(hit_pos[1]); + hit_dist.z = length(hit_pos[2]); + hit_dist.w = length(hit_pos[3]); + hit_dist = max(vec4(1e-8), hit_dist); + + /* Normalize */ + hit_pos[0] /= hit_dist.x; + hit_pos[1] /= hit_dist.y; + hit_pos[2] /= hit_dist.z; + hit_pos[3] /= hit_dist.w; + + /* Compute cone footprint in screen space. */ + vec4 cone_footprint = hit_dist * cone_tan; + cone_footprint = ssrBrdfBias * 0.5 * cone_footprint * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord; + + /* Estimate a cone footprint to sample a corresponding mipmap level. */ + vec4 mip = log2(cone_footprint * max_v2(vec2(textureSize(depthBuffer, 0)))); + mip = clamp(mip, 0.0, MAX_MIP); + + /* Correct UVs for mipmaping mis-alignment */ + hit_co[0].xy *= mip_ratio_interp(mip.x); + hit_co[0].zw *= mip_ratio_interp(mip.y); + hit_co[1].xy *= mip_ratio_interp(mip.z); + hit_co[1].zw *= mip_ratio_interp(mip.w); + + /* Slide 54 */ + vec4 bsdf; + bsdf.x = bsdf_ggx(N, hit_pos[0], V, roughnessSquared); + bsdf.y = bsdf_ggx(N, hit_pos[1], V, roughnessSquared); + bsdf.z = bsdf_ggx(N, hit_pos[2], V, roughnessSquared); + bsdf.w = bsdf_ggx(N, hit_pos[3], V, roughnessSquared); + + vec4 weight = step(1e-8, hit_pdf) * bsdf / max(vec4(1e-8), hit_pdf); + + vec3 sample[4]; + sample[0] = get_scene_color(hit_co[0].xy, mip.x, planar_index, is_planar.x); + sample[1] = get_scene_color(hit_co[0].zw, mip.y, planar_index, is_planar.y); + sample[2] = get_scene_color(hit_co[1].xy, mip.z, planar_index, is_planar.z); + sample[3] = get_scene_color(hit_co[1].zw, mip.w, planar_index, is_planar.w); + + /* Clamped brightness. */ + vec4 luma; + luma.x = brightness(sample[0]); + luma.y = brightness(sample[1]); + luma.z = brightness(sample[2]); + luma.w = brightness(sample[3]); + luma = max(vec4(1e-8), luma); + luma = 1.0 - max(vec4(0.0), luma - ssrFireflyFac) / luma; + + sample[0] *= luma.x; + sample[1] *= luma.y; + sample[2] *= luma.z; + sample[3] *= luma.w; + + /* Protection against NaNs in the history buffer. + * This could be removed if some previous pass has already + * sanitized the input. */ + if (any(isnan(sample[0]))) { + sample[0] = vec3(0.0); weight.x = 0.0; + } + if (any(isnan(sample[1]))) { + sample[1] = vec3(0.0); weight.y = 0.0; + } + if (any(isnan(sample[2]))) { + sample[2] = vec3(0.0); weight.z = 0.0; + } + if (any(isnan(sample[3]))) { + sample[3] = vec3(0.0); weight.w = 0.0; + } + + weight_acc += sum(weight); + + /* Do not add light if ray has failed. */ + vec4 accum; + accum = vec4(sample[0], mask.x) * weight.x * float(has_hit.x); + accum += vec4(sample[1], mask.y) * weight.y * float(has_hit.y); + accum += vec4(sample[2], mask.z) * weight.z * float(has_hit.z); + accum += vec4(sample[3], mask.w) * weight.w * float(has_hit.w); + return accum; +} + +void main() +{ + ivec2 fullres_texel = ivec2(gl_FragCoord.xy); +#ifdef FULLRES + ivec2 halfres_texel = fullres_texel; +#else + ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0); +#endif + vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0)); + + float depth = textureLod(depthBuffer, uvs, 0.0).r; + + /* Early out */ + if (depth == 1.0) + discard; + + /* Using world space */ + vec3 viewPosition = get_view_space_from_depth(uvs, depth); /* Needed for viewCameraVec */ + vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition); + vec3 V = cameraVec; + vec3 vN = normal_decode(texelFetch(normalBuffer, fullres_texel, 0).rg, viewCameraVec); + vec3 N = transform_direction(ViewMatrixInverse, vN); + vec4 speccol_roughness = texelFetch(specroughBuffer, fullres_texel, 0).rgba; + + /* Early out */ + if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0) + discard; + + /* TODO optimize with textureGather */ + /* Doing these fetches early to hide latency. */ + vec4 hit_pdf; + hit_pdf.x = texelFetch(pdfBuffer, halfres_texel + neighbors[0 + neighborOffset], 0).r; + hit_pdf.y = texelFetch(pdfBuffer, halfres_texel + neighbors[1 + neighborOffset], 0).r; + hit_pdf.z = texelFetch(pdfBuffer, halfres_texel + neighbors[2 + neighborOffset], 0).r; + hit_pdf.w = texelFetch(pdfBuffer, halfres_texel + neighbors[3 + neighborOffset], 0).r; + + ivec4 hit_data[2]; + hit_data[0].xy = texelFetch(hitBuffer, halfres_texel + neighbors[0 + neighborOffset], 0).rg; + hit_data[0].zw = texelFetch(hitBuffer, halfres_texel + neighbors[1 + neighborOffset], 0).rg; + hit_data[1].xy = texelFetch(hitBuffer, halfres_texel + neighbors[2 + neighborOffset], 0).rg; + hit_data[1].zw = texelFetch(hitBuffer, halfres_texel + neighbors[3 + neighborOffset], 0).rg; + + /* Find Planar Reflections affecting this pixel */ + PlanarData pd; + float planar_index; + for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; ++i) { + pd = planars_data[i]; + + float fade = probe_attenuation_planar(pd, worldPosition, N, 0.0); + + if (fade > 0.5) { + planar_index = float(i); + break; + } + } + + float roughness = speccol_roughness.a; + float roughnessSquared = max(1e-3, roughness * roughness); + + vec4 spec_accum = vec4(0.0); + + /* Resolve SSR */ + float cone_cos = cone_cosine(roughnessSquared); + float cone_tan = sqrt(1 - cone_cos * cone_cos) / cone_cos; + cone_tan *= mix(saturate(dot(N, -V) * 2.0), 1.0, roughness); /* Elongation fit */ + + vec2 source_uvs = project_point(pastViewProjectionMatrix, worldPosition).xy * 0.5 + 0.5; + + vec4 ssr_accum = vec4(0.0); + float weight_acc = 0.0; + + if (roughness < ssrMaxRoughness + 0.2) { + ssr_accum += get_ssr_samples(hit_pdf, hit_data, pd, planar_index, worldPosition, N, V, + roughnessSquared, cone_tan, source_uvs, weight_acc); + } + + /* Compute SSR contribution */ + if (weight_acc > 0.0) { + ssr_accum /= weight_acc; + /* fade between 0.5 and 1.0 roughness */ + ssr_accum.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness); + accumulate_light(ssr_accum.rgb, ssr_accum.a, spec_accum); + } + + /* If SSR contribution is not 1.0, blend with cubemaps */ + if (spec_accum.a < 1.0) { + fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum); + } + + fragColor = vec4(spec_accum.rgb * speccol_roughness.rgb, 1.0); +} + +#endif diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl new file mode 100644 index 00000000000..5ecf6323255 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -0,0 +1,99 @@ + +/* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */ + +#define MAX_SSS_SAMPLES 65 +layout(std140) uniform sssProfile { + vec4 kernel[MAX_SSS_SAMPLES]; + vec4 radii_max_radius; + int sss_samples; +}; + +uniform sampler2D depthBuffer; +uniform sampler2D sssData; +uniform sampler2D sssAlbedo; + +#ifndef UTIL_TEX +#define UTIL_TEX +uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) +#endif /* UTIL_TEX */ + +layout(location = 0) out vec4 FragColor; +#ifdef RESULT_ACCUM +layout(location = 1) out vec4 sssColor; +#endif + +float get_view_z_from_depth(float depth) +{ + if (ProjectionMatrix[3][3] == 0.0) { + float d = 2.0 * depth - 1.0; + return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]); + } + else { + return viewVecs[0].z + depth * viewVecs[1].z; + } +} + +#define LUT_SIZE 64 +#define M_PI_2 1.5707963267948966 /* pi/2 */ +#define M_2PI 6.2831853071795865 /* 2*pi */ + +void main(void) +{ + vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO precompute */ + vec2 uvs = gl_FragCoord.xy * pixel_size; + vec4 sss_data = texture(sssData, uvs).rgba; + float depth_view = get_view_z_from_depth(texture(depthBuffer, uvs).r); + + float rand = texelfetch_noise_tex(gl_FragCoord.xy).r; +#ifdef FIRST_PASS + float angle = M_2PI * rand + M_PI_2; + vec2 dir = vec2(1.0, 0.0); +#else /* SECOND_PASS */ + float angle = M_2PI * rand; + vec2 dir = vec2(0.0, 1.0); +#endif + vec2 dir_rand = vec2(cos(angle), sin(angle)); + + /* Compute kernel bounds in 2D. */ + float homcoord = ProjectionMatrix[2][3] * depth_view + ProjectionMatrix[3][3]; + vec2 scale = vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * sss_data.aa / homcoord; + vec2 finalStep = scale * radii_max_radius.w; + finalStep *= 0.5; /* samples range -1..1 */ + + /* Center sample */ + vec3 accum = sss_data.rgb * kernel[0].rgb; + + for (int i = 1; i < sss_samples && i < MAX_SSS_SAMPLES; i++) { + vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > sssJitterThreshold) ? dir : dir_rand); + vec3 color = texture(sssData, sample_uv).rgb; + float sample_depth = texture(depthBuffer, sample_uv).r; + sample_depth = get_view_z_from_depth(sample_depth); + + /* Depth correction factor. */ + float depth_delta = depth_view - sample_depth; + float s = clamp(1.0 - exp(-(depth_delta * depth_delta) / (2.0 * sss_data.a)), 0.0, 1.0); + + /* Out of view samples. */ + if (any(lessThan(sample_uv, vec2(0.0))) || any(greaterThan(sample_uv, vec2(1.0)))) { + s = 1.0; + } + + accum += kernel[i].rgb * mix(color, sss_data.rgb, s); + } + +#ifdef FIRST_PASS + FragColor = vec4(accum, sss_data.a); +#else /* SECOND_PASS */ +# ifdef USE_SEP_ALBEDO +# ifdef RESULT_ACCUM + FragColor = vec4(accum, 1.0); + sssColor = texture(sssAlbedo, uvs); +# else + FragColor = vec4(accum * texture(sssAlbedo, uvs).rgb, 1.0); +# endif +# else + FragColor = vec4(accum, 1.0); +# endif +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl new file mode 100644 index 00000000000..e118777f6c8 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl @@ -0,0 +1,111 @@ + +uniform sampler2D colorHistoryBuffer; +uniform sampler2D velocityBuffer; + +out vec4 FragColor; + +vec4 safe_color(vec4 c) +{ + /* Clamp to avoid black square artifacts if a pixel goes NaN. */ + return clamp(c, vec4(0.0), vec4(1e20)); /* 1e20 arbitrary. */ +} + +#ifdef USE_REPROJECTION + +/** + * Adapted from https://casual-effects.com/g3d/G3D10/data-files/shader/Film/Film_temporalAA.pix + * which is adapted from https://github.com/gokselgoktas/temporal-anti-aliasing/blob/master/Assets/Resources/Shaders/TemporalAntiAliasing.cginc + * which is adapted from https://github.com/playdeadgames/temporal + * Optimization by Stubbesaurus and epsilon adjustment to avoid division by zero. + * + * This can cause 3x3 blocks of color when there is a thin edge of a similar color that + * is varying in intensity. + */ +vec3 clip_to_aabb(vec3 color, vec3 minimum, vec3 maximum, vec3 average) +{ + /* note: only clips towards aabb center (but fast!) */ + vec3 center = 0.5 * (maximum + minimum); + vec3 extents = 0.5 * (maximum - minimum); + vec3 dist = color - center; + vec3 ts = abs(extents) / max(abs(dist), vec3(0.0001)); + float t = saturate(min_v3(ts)); + return center + dist * t; +} + +/** + * Vastly based on https://github.com/playdeadgames/temporal + */ +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + float depth = texelFetch(depthBuffer, texel, 0).r; + vec2 motion = texelFetch(velocityBuffer, texel, 0).rg; + + /* Decode from unsigned normalized 16bit texture. */ + motion = motion * 2.0 - 1.0; + + /* Compute pixel position in previous frame. */ + vec2 screen_res = vec2(textureSize(colorBuffer, 0).xy); + vec2 uv = gl_FragCoord.xy / screen_res; + vec2 uv_history = uv - motion; + + ivec2 texel_history = ivec2(uv_history * screen_res); + vec4 color_history = textureLod(colorHistoryBuffer, uv_history, 0.0); + + /* Color bounding box clamping. 3x3 neighborhood. */ + vec4 c02 = texelFetchOffset(colorBuffer, texel, 0, ivec2(-1, 1)); + vec4 c12 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 0, 1)); + vec4 c22 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 1, 1)); + vec4 c01 = texelFetchOffset(colorBuffer, texel, 0, ivec2(-1, 0)); + vec4 c11 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 0, 0)); + vec4 c21 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 1, 0)); + vec4 c00 = texelFetchOffset(colorBuffer, texel, 0, ivec2(-1, -1)); + vec4 c10 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 0, -1)); + vec4 c20 = texelFetchOffset(colorBuffer, texel, 0, ivec2( 1, -1)); + + vec4 color = c11; + + /* AABB minmax */ + vec4 min_col = min9(c02, c12, c22, c01, c11, c21, c00, c10, c20); + vec4 max_col = max9(c02, c12, c22, c01, c11, c21, c00, c10, c20); + vec4 avg_col = avg9(c02, c12, c22, c01, c11, c21, c00, c10, c20); + + /* bias the color aabb toward the center (rounding the shape) */ + vec4 min_center = min5(c12, c01, c11, c21, c10); + vec4 max_center = max5(c12, c01, c11, c21, c10); + vec4 avg_center = avg5(c12, c01, c11, c21, c10); + min_col = (min_col + min_center) * 0.5; + max_col = (max_col + max_center) * 0.5; + avg_col = (avg_col + avg_center) * 0.5; + + /* Clip color toward the center of the neighborhood colors AABB box. */ + color_history.rgb = clip_to_aabb(color_history.rgb, min_col.rgb, max_col.rgb, avg_col.rgb); + + /* Luminance weighting. */ + /* TODO correct luminance */ + float lum0 = dot(color.rgb, vec3(0.333)); + float lum1 = dot(color_history.rgb, vec3(0.333)); + float diff = abs(lum0 - lum1) / max(lum0, max(lum1, 0.2)); + float weight = 1.0 - diff; + float alpha = mix(0.04, 0.12, weight * weight); + + color_history = mix(color_history, color, alpha); + + bool out_of_view = any(greaterThanEqual(abs(uv_history - 0.5), vec2(0.5))); + color_history = (out_of_view) ? color : color_history; + + FragColor = safe_color(color_history); +} + +#else + +uniform float alpha; + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + vec4 color = texelFetch(colorBuffer, texel, 0); + vec4 color_history = texelFetch(colorHistoryBuffer, texel, 0); + FragColor = safe_color(mix(color_history, color, alpha)); +} +#endif diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl new file mode 100644 index 00000000000..8324c25225c --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl @@ -0,0 +1,22 @@ + +uniform mat4 currPersinv; +uniform mat4 pastPersmat; + +out vec2 outData; + +void main() +{ + /* Extract pixel motion vector from camera movement. */ + ivec2 texel = ivec2(gl_FragCoord.xy); + vec2 uv = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0).xy); + + float depth = texelFetch(depthBuffer, texel, 0).r; + + vec3 world_position = project_point(currPersinv, vec3(uv, depth) * 2.0 - 1.0); + vec2 uv_history = project_point(pastPersmat, world_position).xy * 0.5 + 0.5; + + outData = uv - uv_history; + + /* Encode to unsigned normalized 16bit texture. */ + outData = outData * 0.5 + 0.5; +} diff --git a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl new file mode 100644 index 00000000000..132cc16fcbd --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl @@ -0,0 +1,177 @@ + +uniform sampler2DArray irradianceGrid; + +#define IRRADIANCE_LIB + +#ifdef IRRADIANCE_CUBEMAP +struct IrradianceData { + vec3 color; +}; +#elif defined(IRRADIANCE_SH_L2) +struct IrradianceData { + vec3 shcoefs[9]; +}; +#else /* defined(IRRADIANCE_HL2) */ +struct IrradianceData { + vec3 cubesides[3]; +}; +#endif + +IrradianceData load_irradiance_cell(int cell, vec3 N) +{ + /* Keep in sync with diffuse_filter_probe() */ + +#if defined(IRRADIANCE_CUBEMAP) + + #define AMBIANT_CUBESIZE 8 + ivec2 cell_co = ivec2(AMBIANT_CUBESIZE); + int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x; + cell_co.x *= cell % cell_per_row; + cell_co.y *= cell / cell_per_row; + + vec2 texelSize = 1.0 / vec2(AMBIANT_CUBESIZE); + + vec2 uvs = mapping_octahedron(N, texelSize); + uvs *= vec2(AMBIANT_CUBESIZE) / vec2(textureSize(irradianceGrid, 0)); + uvs += vec2(cell_co) / vec2(textureSize(irradianceGrid, 0)); + + IrradianceData ir; + ir.color = texture(irradianceGrid, vec3(uvs, 0.0)).rgb; + +#elif defined(IRRADIANCE_SH_L2) + + ivec2 cell_co = ivec2(3, 3); + int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x; + cell_co.x *= cell % cell_per_row; + cell_co.y *= cell / cell_per_row; + + ivec3 ofs = ivec3(0, 1, 2); + + IrradianceData ir; + ir.shcoefs[0] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xx, 0), 0).rgb; + ir.shcoefs[1] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yx, 0), 0).rgb; + ir.shcoefs[2] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zx, 0), 0).rgb; + ir.shcoefs[3] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xy, 0), 0).rgb; + ir.shcoefs[4] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yy, 0), 0).rgb; + ir.shcoefs[5] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zy, 0), 0).rgb; + ir.shcoefs[6] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xz, 0), 0).rgb; + ir.shcoefs[7] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yz, 0), 0).rgb; + ir.shcoefs[8] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zz, 0), 0).rgb; + +#else /* defined(IRRADIANCE_HL2) */ + + ivec2 cell_co = ivec2(3, 2); + int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x; + cell_co.x *= cell % cell_per_row; + cell_co.y *= cell / cell_per_row; + + ivec3 is_negative = ivec3(step(0.0, -N)); + + IrradianceData ir; + ir.cubesides[0] = irradiance_decode(texelFetch(irradianceGrid, ivec3(cell_co + ivec2(0, is_negative.x), 0), 0)); + ir.cubesides[1] = irradiance_decode(texelFetch(irradianceGrid, ivec3(cell_co + ivec2(1, is_negative.y), 0), 0)); + ir.cubesides[2] = irradiance_decode(texelFetch(irradianceGrid, ivec3(cell_co + ivec2(2, is_negative.z), 0), 0)); + +#endif + + return ir; +} + +float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed_bias, float range) +{ + /* Keep in sync with diffuse_filter_probe() */ + ivec2 cell_co = ivec2(prbIrradianceVisSize); + ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / prbIrradianceVisSize; + cell_co.x *= (cell % cell_per_row_col.x); + cell_co.y *= (cell / cell_per_row_col.x) % cell_per_row_col.y; + float layer = 1.0 + float((cell / cell_per_row_col.x) / cell_per_row_col.y); + + vec2 texel_size = 1.0 / vec2(textureSize(irradianceGrid, 0).xy); + vec2 co = vec2(cell_co) * texel_size; + + vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(prbIrradianceVisSize))); + uv *= vec2(prbIrradianceVisSize) * texel_size; + + vec4 data = texture(irradianceGrid, vec3(co + uv, layer)); + + /* Decoding compressed data */ + vec2 moments = visibility_decode(data, range); + + /* Doing chebishev test */ + float variance = abs(moments.x * moments.x - moments.y); + variance = max(variance, bias / 10.0); + + float d = dist - moments.x; + float p_max = variance / (variance + d * d); + + /* Increase contrast in the weight by squaring it */ + p_max *= p_max; + + /* Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] */ + p_max = clamp((p_max - bleed_bias) / (1.0 - bleed_bias), 0.0, 1.0); + + return (dist <= moments.x) ? 1.0 : p_max; +} + +/* http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ */ +vec3 spherical_harmonics_L1(vec3 N, vec3 shcoefs[4]) +{ + vec3 sh = vec3(0.0); + + sh += 0.282095 * shcoefs[0]; + + sh += -0.488603 * N.z * shcoefs[1]; + sh += 0.488603 * N.y * shcoefs[2]; + sh += -0.488603 * N.x * shcoefs[3]; + + return sh; +} + +vec3 spherical_harmonics_L2(vec3 N, vec3 shcoefs[9]) +{ + vec3 sh = vec3(0.0); + + sh += 0.282095 * shcoefs[0]; + + sh += -0.488603 * N.z * shcoefs[1]; + sh += 0.488603 * N.y * shcoefs[2]; + sh += -0.488603 * N.x * shcoefs[3]; + + sh += 1.092548 * N.x * N.z * shcoefs[4]; + sh += -1.092548 * N.z * N.y * shcoefs[5]; + sh += 0.315392 * (3.0 * N.y * N.y - 1.0) * shcoefs[6]; + sh += -1.092548 * N.x * N.y * shcoefs[7]; + sh += 0.546274 * (N.x * N.x - N.z * N.z) * shcoefs[8]; + + return sh; +} + +vec3 hl2_basis(vec3 N, vec3 cubesides[3]) +{ + vec3 irradiance = vec3(0.0); + + vec3 n_squared = N * N; + + irradiance += n_squared.x * cubesides[0]; + irradiance += n_squared.y * cubesides[1]; + irradiance += n_squared.z * cubesides[2]; + + return irradiance; +} + +vec3 compute_irradiance(vec3 N, IrradianceData ird) +{ +#if defined(IRRADIANCE_CUBEMAP) + return ird.color; +#elif defined(IRRADIANCE_SH_L2) + return spherical_harmonics_L2(N, ird.shcoefs); +#else /* defined(IRRADIANCE_HL2) */ + return hl2_basis(N, ird.cubesides); +#endif +} + +vec3 irradiance_from_cell_get(int cell, vec3 ir_dir) +{ + IrradianceData ir_data = load_irradiance_cell(cell, ir_dir); + return compute_irradiance(ir_dir, ir_data); +} diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl new file mode 100644 index 00000000000..0e6f976187a --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl @@ -0,0 +1,436 @@ + +uniform sampler2DArray shadowCubeTexture; +uniform sampler2DArray shadowCascadeTexture; + +#define LAMPS_LIB + +layout(std140) uniform shadow_block { + ShadowData shadows_data[MAX_SHADOW]; + ShadowCubeData shadows_cube_data[MAX_SHADOW_CUBE]; + ShadowCascadeData shadows_cascade_data[MAX_SHADOW_CASCADE]; +}; + +layout(std140) uniform light_block { + LightData lights_data[MAX_LIGHT]; +}; + +/* type */ +#define POINT 0.0 +#define SUN 1.0 +#define SPOT 2.0 +#define HEMI 3.0 +#define AREA_RECT 4.0 +/* Used to define the area lamp shape, doesn't directly correspond to a Blender lamp type. */ +#define AREA_ELLIPSE 100.0 + +#if defined(SHADOW_VSM) +#define ShadowSample vec2 +#define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).rg +#define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).rg +#elif defined(SHADOW_ESM) +#define ShadowSample float +#define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).r +#define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).r +#else +#define ShadowSample float +#define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).r +#define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).r +#endif + +#if defined(SHADOW_VSM) +#define get_depth_delta(s) (dist - s.x) +#else +#define get_depth_delta(s) (dist - s) +#endif + +/* ----------------------------------------------------------- */ +/* ----------------------- Shadow tests ---------------------- */ +/* ----------------------------------------------------------- */ + +#if defined(SHADOW_VSM) + +float shadow_test(ShadowSample moments, float dist, ShadowData sd) +{ + float p = 0.0; + + if (dist <= moments.x) + p = 1.0; + + float variance = moments.y - (moments.x * moments.x); + variance = max(variance, sd.sh_bias / 10.0); + + float d = moments.x - dist; + float p_max = variance / (variance + d * d); + + /* Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] */ + p_max = clamp((p_max - sd.sh_bleed) / (1.0 - sd.sh_bleed), 0.0, 1.0); + + return max(p, p_max); +} + +#elif defined(SHADOW_ESM) + +float shadow_test(ShadowSample z, float dist, ShadowData sd) +{ + return saturate(exp(sd.sh_exp * (z - dist + sd.sh_bias))); +} + +#else + +float shadow_test(ShadowSample z, float dist, ShadowData sd) +{ + return step(0, z - dist + sd.sh_bias); +} + +#endif + +/* ----------------------------------------------------------- */ +/* ----------------------- Shadow types ---------------------- */ +/* ----------------------------------------------------------- */ + +float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W) +{ + vec3 cubevec = W - scd.position.xyz; + float dist = length(cubevec); + + /* If fragment is out of shadowmap range, do not occlude */ + /* XXX : we check radial distance against a cubeface distance. + * We loose quite a bit of valid area. */ + if (dist > sd.sh_far) + return 1.0; + + cubevec /= dist; + + ShadowSample s = sample_cube(cubevec, texid); + return shadow_test(s, dist, sd); +} + +float evaluate_cascade(ShadowData sd, mat4 shadowmat, vec3 W, float range, float texid) +{ + vec4 shpos = shadowmat * vec4(W, 1.0); + float dist = shpos.z * range; + + ShadowSample s = sample_cascade(shpos.xy, texid); + float vis = shadow_test(s, dist, sd); + + /* If fragment is out of shadowmap range, do not occlude */ + if (shpos.z < 1.0 && shpos.z > 0.0) { + return vis; + } + else { + return 1.0; + } +} + +float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W) +{ + vec4 view_z = vec4(dot(W - cameraPos, cameraForward)); + vec4 weights = smoothstep(scd.split_end_distances, scd.split_start_distances.yzwx, view_z); + weights.yzw -= weights.xyz; + + vec4 vis = vec4(1.0); + float range = abs(sd.sh_far - sd.sh_near); /* Same factor as in get_cascade_world_distance(). */ + + /* Branching using (weights > 0.0) is reaally slooow on intel so avoid it for now. */ + /* TODO OPTI: Only do 2 samples and blend. */ + vis.x = evaluate_cascade(sd, scd.shadowmat[0], W, range, texid + 0); + vis.y = evaluate_cascade(sd, scd.shadowmat[1], W, range, texid + 1); + vis.z = evaluate_cascade(sd, scd.shadowmat[2], W, range, texid + 2); + vis.w = evaluate_cascade(sd, scd.shadowmat[3], W, range, texid + 3); + + float weight_sum = dot(vec4(1.0), weights); + if (weight_sum > 0.9999) { + float vis_sum = dot(vec4(1.0), vis * weights); + return vis_sum / weight_sum; + } + else { + float vis_sum = dot(vec4(1.0), vis * step(0.001, weights)); + return mix(1.0, vis_sum, weight_sum); + } +} + +/* ----------------------------------------------------------- */ +/* --------------------- Light Functions --------------------- */ +/* ----------------------------------------------------------- */ +#define MAX_MULTI_SHADOW 4 + +float light_visibility(LightData ld, vec3 W, +#ifndef VOLUMETRICS + vec3 viewPosition, + vec3 viewNormal, +#endif + vec4 l_vector) +{ + float vis = 1.0; + + if (ld.l_type == SPOT) { + float z = dot(ld.l_forward, l_vector.xyz); + vec3 lL = l_vector.xyz / z; + float x = dot(ld.l_right, lL) / ld.l_sizex; + float y = dot(ld.l_up, lL) / ld.l_sizey; + + float ellipse = inversesqrt(1.0 + x * x + y * y); + + float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend); + + vis *= spotmask; + vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); + } + else if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { + vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); + } + +#if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW) + /* shadowing */ + if (ld.l_shadowid >= 0.0) { + ShadowData data = shadows_data[int(ld.l_shadowid)]; + + if (ld.l_type == SUN) { + /* TODO : MSM */ + // for (int i = 0; i < MAX_MULTI_SHADOW; ++i) { + vis *= shadow_cascade( + data, shadows_cascade_data[int(data.sh_data_start)], + data.sh_tex_start, W); + // } + } + else { + /* TODO : MSM */ + // for (int i = 0; i < MAX_MULTI_SHADOW; ++i) { + vis *= shadow_cubemap( + data, shadows_cube_data[int(data.sh_data_start)], + data.sh_tex_start, W); + // } + } + +#ifndef VOLUMETRICS + /* Only compute if not already in shadow. */ + if ((vis > 0.001) && (data.sh_contact_dist > 0.0)) { + vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0); + float trace_distance = (ld.l_type != SUN) ? min(data.sh_contact_dist, l_vector.w) : data.sh_contact_dist; + + vec3 T, B; + make_orthonormal_basis(L.xyz / L.w, T, B); + + vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); + rand.zw *= fast_sqrt(rand.y) * data.sh_contact_spread; + + /* We use the full l_vector.xyz so that the spread is minimize + * if the shading point is further away from the light source */ + vec3 ray_dir = L.xyz + T * rand.z + B * rand.w; + ray_dir = transform_direction(ViewMatrix, ray_dir); + ray_dir = normalize(ray_dir); + + vec3 ray_ori = viewPosition; + + float bias = 0.5; /* Constant Bias */ + bias += 1.0 - abs(dot(viewNormal, ray_dir)); /* Angle dependant bias */ + bias *= gl_FrontFacing ? data.sh_contact_offset : -data.sh_contact_offset; + + vec3 nor_bias = viewNormal * bias; + ray_ori += nor_bias; + + ray_dir *= trace_distance; + ray_dir -= nor_bias; + + vec3 hit_pos = raycast(-1, ray_ori, ray_dir, data.sh_contact_thickness, rand.x, + 0.1, 0.001, false); + + if (hit_pos.z > 0.0) { + hit_pos = get_view_space_from_depth(hit_pos.xy, hit_pos.z); + float hit_dist = distance(viewPosition, hit_pos); + float dist_ratio = hit_dist / trace_distance; + return vis * saturate(dist_ratio * dist_ratio * dist_ratio); + } + } +#endif + } +#endif + + return vis; +} + +float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector) +{ +#ifdef USE_LTC + if (ld.l_type == SUN) { + return direct_diffuse_unit_disc(ld, N, V); + } + else if (ld.l_type == AREA_RECT) { + return direct_diffuse_rectangle(ld, N, V, l_vector); + } + else if (ld.l_type == AREA_ELLIPSE) { + return direct_diffuse_ellipse(ld, N, V, l_vector); + } + else { + return direct_diffuse_sphere(ld, N, l_vector); + } +#else + if (ld.l_type == SUN) { + return direct_diffuse_sun(ld, N); + } + else { + return direct_diffuse_point(N, l_vector); + } +#endif +} + +vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) +{ +#ifdef USE_LTC + if (ld.l_type == SUN) { + return direct_ggx_unit_disc(ld, N, V, roughness, f0); + } + else if (ld.l_type == AREA_RECT) { + return direct_ggx_rectangle(ld, N, V, l_vector, roughness, f0); + } + else if (ld.l_type == AREA_ELLIPSE) { + return direct_ggx_ellipse(ld, N, V, l_vector, roughness, f0); + } + else { + return direct_ggx_sphere(ld, N, V, l_vector, roughness, f0); + } +#else + if (ld.l_type == SUN) { + return direct_ggx_sun(ld, N, V, roughness, f0); + } + else { + return direct_ggx_point(N, V, l_vector, roughness, f0); + } +#endif +} + +#define MAX_SSS_SAMPLES 65 +#define SSS_LUT_SIZE 64.0 +#define SSS_LUT_SCALE ((SSS_LUT_SIZE - 1.0) / float(SSS_LUT_SIZE)) +#define SSS_LUT_BIAS (0.5 / float(SSS_LUT_SIZE)) +layout(std140) uniform sssProfile { + vec4 kernel[MAX_SSS_SAMPLES]; + vec4 radii_max_radius; + int sss_samples; +}; + +uniform sampler1D sssTexProfile; + +vec3 sss_profile(float s) { + s /= radii_max_radius.w; + return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb; +} + +vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) +{ +#if !defined(USE_TRANSLUCENCY) || defined(VOLUMETRICS) + return vec3(0.0); +#else + vec3 vis = vec3(1.0); + + /* Only shadowed light can produce translucency */ + if (ld.l_shadowid >= 0.0) { + ShadowData data = shadows_data[int(ld.l_shadowid)]; + float delta; + + vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0); + + vec3 T, B; + make_orthonormal_basis(L.xyz / L.w, T, B); + + vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); + rand.zw *= fast_sqrt(rand.y) * data.sh_blur; + + /* We use the full l_vector.xyz so that the spread is minimize + * if the shading point is further away from the light source */ + W = W + T * rand.z + B * rand.w; + + if (ld.l_type == SUN) { + ShadowCascadeData scd = shadows_cascade_data[int(data.sh_data_start)]; + vec4 view_z = vec4(dot(W - cameraPos, cameraForward)); + + vec4 weights = step(scd.split_end_distances, view_z); + float id = abs(4.0 - dot(weights, weights)); + + if (id > 3.0) { + return vec3(0.0); + } + + float range = abs(data.sh_far - data.sh_near); /* Same factor as in get_cascade_world_distance(). */ + + vec4 shpos = scd.shadowmat[int(id)] * vec4(W, 1.0); + float dist = shpos.z * range; + + if (shpos.z > 1.0 || shpos.z < 0.0) { + return vec3(0.0); + } + + ShadowSample s = sample_cascade(shpos.xy, data.sh_tex_start + id); + delta = get_depth_delta(s); + } + else { + vec3 cubevec = W - shadows_cube_data[int(data.sh_data_start)].position.xyz; + float dist = length(cubevec); + + /* If fragment is out of shadowmap range, do not occlude */ + /* XXX : we check radial distance against a cubeface distance. + * We loose quite a bit of valid area. */ + if (dist < data.sh_far) { + cubevec /= dist; + + ShadowSample s = sample_cube(cubevec, data.sh_tex_start); + delta = get_depth_delta(s); + } + } + + /* XXX : Removing Area Power. */ + /* TODO : put this out of the shader. */ + float falloff; + if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { + vis *= (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); + if (ld.l_type == AREA_ELLIPSE) { + vis *= M_PI * 0.25; + } + vis *= 0.3 * 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ + vis /= (l_vector.w * l_vector.w); + falloff = dot(N, l_vector.xyz / l_vector.w); + } + else if (ld.l_type == SUN) { + vis *= (4.0f * ld.l_radius * ld.l_radius * M_2PI) * (1.0 / 12.5); /* Removing area light power*/ + vis *= M_2PI * 0.78; /* Matching cycles with point light. */ + vis *= 0.082; /* XXX ad hoc, empirical */ + falloff = dot(N, -ld.l_forward); + } + else { + vis *= (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0); + vis *= 1.5; /* XXX ad hoc, empirical */ + vis /= (l_vector.w * l_vector.w); + falloff = dot(N, l_vector.xyz / l_vector.w); + } + // vis *= M_1_PI; /* Normalize */ + + /* Applying profile */ + vis *= sss_profile(abs(delta) / scale); + + /* No transmittance at grazing angle (hide artifacts) */ + vis *= saturate(falloff * 2.0); + + if (ld.l_type == SPOT) { + float z = dot(ld.l_forward, l_vector.xyz); + vec3 lL = l_vector.xyz / z; + float x = dot(ld.l_right, lL) / ld.l_sizex; + float y = dot(ld.l_up, lL) / ld.l_sizey; + + float ellipse = inversesqrt(1.0 + x * x + y * y); + + float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend); + + vis *= spotmask; + vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); + } + else if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { + vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); + } + } + else { + vis = vec3(0.0); + } + + return vis; +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl new file mode 100644 index 00000000000..d10f4bc0d42 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl @@ -0,0 +1,15 @@ + +flat in int pid; +in vec3 worldNormal; +in vec3 worldPosition; + +out vec4 FragColor; + +void main() +{ + vec3 V = (ProjectionMatrix[3][3] == 0.0) /* if perspective */ + ? normalize(cameraPos - worldPosition) + : cameraForward; + vec3 N = normalize(worldNormal); + FragColor = vec4(textureLod_octahedron(probeCubes, vec4(reflect(-V, N), pid), 0.0, prbLodCubeMax).rgb, 1.0); +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl new file mode 100644 index 00000000000..b0a6cbe1707 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl @@ -0,0 +1,26 @@ + +in vec3 pos; + +/* Instance attrib */ +in int probe_id; +in vec3 probe_location; +in float sphere_size; + +flat out int pid; +out vec3 worldNormal; +out vec3 worldPosition; + +void main() +{ + pid = probe_id; + + /* While this is not performant, we do this to + * match the object mode engine instancing shader. */ + mat4 offsetmat = mat4(1.0); /* Identity */ + offsetmat[3].xyz = probe_location; + + vec4 wpos = offsetmat * vec4(pos * sphere_size, 1.0); + worldPosition = wpos.xyz; + gl_Position = ViewProjectionMatrix * wpos; + worldNormal = normalize(pos); +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl new file mode 100644 index 00000000000..14fd6d3dff5 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl @@ -0,0 +1,198 @@ + +uniform samplerCube probeHdr; +uniform int probeSize; +uniform float lodFactor; +uniform float lodMax; +uniform float intensityFac; + +in vec3 worldPosition; + +out vec4 FragColor; + +#define M_4PI 12.5663706143591729 + +const mat3 CUBE_ROTATIONS[6] = mat3[]( + mat3(vec3( 0.0, 0.0, -1.0), + vec3( 0.0, -1.0, 0.0), + vec3(-1.0, 0.0, 0.0)), + mat3(vec3( 0.0, 0.0, 1.0), + vec3( 0.0, -1.0, 0.0), + vec3( 1.0, 0.0, 0.0)), + mat3(vec3( 1.0, 0.0, 0.0), + vec3( 0.0, 0.0, 1.0), + vec3( 0.0, -1.0, 0.0)), + mat3(vec3( 1.0, 0.0, 0.0), + vec3( 0.0, 0.0, -1.0), + vec3( 0.0, 1.0, 0.0)), + mat3(vec3( 1.0, 0.0, 0.0), + vec3( 0.0, -1.0, 0.0), + vec3( 0.0, 0.0, -1.0)), + mat3(vec3(-1.0, 0.0, 0.0), + vec3( 0.0, -1.0, 0.0), + vec3( 0.0, 0.0, 1.0))); + +vec3 get_cubemap_vector(vec2 co, int face) +{ + return normalize(CUBE_ROTATIONS[face] * vec3(co * 2.0 - 1.0, 1.0)); +} + +float area_element(float x, float y) +{ + return atan(x * y, sqrt(x * x + y * y + 1)); +} + +float texel_solid_angle(vec2 co, float halfpix) +{ + vec2 v1 = (co - vec2(halfpix)) * 2.0 - 1.0; + vec2 v2 = (co + vec2(halfpix)) * 2.0 - 1.0; + + return area_element(v1.x, v1.y) - area_element(v1.x, v2.y) - area_element(v2.x, v1.y) + area_element(v2.x, v2.y); +} + +vec3 octahedral_to_cubemap_proj(vec2 co) +{ + co = co * 2.0 - 1.0; + + vec2 abs_co = abs(co); + vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y)); + + if ( abs_co.x + abs_co.y > 1.0 ) { + v.xy = (abs(co.yx) - 1.0) * -sign(co.xy); + } + + return v; +} + +void main() +{ +#if defined(IRRADIANCE_SH_L2) + float pixstep = 1.0 / probeSize; + float halfpix = pixstep / 2.0; + + /* Downside: leaks negative values, very bandwidth consuming */ + int comp = int(gl_FragCoord.x) % 3 + (int(gl_FragCoord.y) % 3) * 3; + + float weight_accum = 0.0; + vec3 sh = vec3(0.0); + + for (int face = 0; face < 6; ++face) { + for (float x = halfpix; x < 1.0; x += pixstep) { + for (float y = halfpix; y < 1.0; y += pixstep) { + float weight, coef; + vec2 facecoord = vec2(x,y); + vec3 cubevec = get_cubemap_vector(facecoord, face); + + if (comp == 0) { + coef = 0.282095; + } + else if (comp == 1) { + coef = -0.488603 * cubevec.z * 2.0 / 3.0; + } + else if (comp == 2) { + coef = 0.488603 * cubevec.y * 2.0 / 3.0; + } + else if (comp == 3) { + coef = -0.488603 * cubevec.x * 2.0 / 3.0; + } + else if (comp == 4) { + coef = 1.092548 * cubevec.x * cubevec.z * 1.0 / 4.0; + } + else if (comp == 5) { + coef = -1.092548 * cubevec.z * cubevec.y * 1.0 / 4.0; + } + else if (comp == 6) { + coef = 0.315392 * (3.0 * cubevec.y * cubevec.y - 1.0) * 1.0 / 4.0; + } + else if (comp == 7) { + coef = 1.092548 * cubevec.x * cubevec.y * 1.0 / 4.0; + } + else { /* (comp == 8) */ + coef = 0.546274 * (cubevec.x * cubevec.x - cubevec.z * cubevec.z) * 1.0 / 4.0; + } + + weight = texel_solid_angle(facecoord, halfpix); + + vec4 sample = textureLod(probeHdr, cubevec, lodMax); + sh += sample.rgb * coef * weight; + weight_accum += weight; + } + } + } + sh *= M_4PI / weight_accum; + + FragColor = vec4(sh, 1.0); +#else +#if defined(IRRADIANCE_CUBEMAP) + /* Downside: Need lots of memory for storage, distortion due to octahedral mapping */ + const vec2 map_size = vec2(16.0); + const vec2 texelSize = 1.0 / map_size; + vec2 uvs = mod(gl_FragCoord.xy, map_size) * texelSize; + const float paddingSize = 1.0; + + /* Add a N pixel border to ensure filtering is correct + * for N mipmap levels. */ + uvs += uvs * texelSize * paddingSize * 2.0; + uvs -= texelSize * paddingSize; + + /* edge mirroring : only mirror if directly adjacent + * (not diagonally adjacent) */ + vec2 m = abs(uvs - 0.5) + 0.5; + vec2 f = floor(m); + if (f.x - f.y != 0.0) { + uvs = 1.0 - uvs; + } + + /* clamp to [0-1] */ + uvs = fract(uvs); + + /* get cubemap vector */ + vec3 cubevec = octahedral_to_cubemap_proj(uvs); + +#elif defined(IRRADIANCE_HL2) + /* Downside: very very low resolution (6 texels), bleed lighting because of interpolation */ + int x = int(gl_FragCoord.x) % 3; + int y = int(gl_FragCoord.y) % 2; + + vec3 cubevec = vec3(1.0, 0.0, 0.0); + + if (x == 1) { + cubevec = cubevec.yxy; + } + else if (x == 2) { + cubevec = cubevec.yyx; + } + + if (y == 1) { + cubevec = -cubevec; + } +#endif + + vec3 N, T, B, V; + + N = normalize(cubevec); + + make_orthonormal_basis(N, T, B); /* Generate tangent space */ + + /* Integrating Envmap */ + float weight = 0.0; + vec3 out_radiance = vec3(0.0); + for (float i = 0; i < sampleCount; i++) { + vec3 L = sample_hemisphere(i, N, T, B); /* Microfacet normal */ + float NL = dot(N, L); + + if (NL > 0.0) { + /* Coarse Approximation of the mapping distortion + * Unit Sphere -> Cubemap Face */ + const float dist = 4.0 * M_PI / 6.0; + float pdf = pdf_hemisphere(); + /* http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html : Equation 13 */ + float lod = clamp(lodFactor - 0.5 * log2(pdf * dist), 0.0, lodMax) ; + + out_radiance += textureLod(probeHdr, L, lod).rgb * NL; + weight += NL; + } + } + + FragColor = irradiance_encode(intensityFac * out_radiance / weight); +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl new file mode 100644 index 00000000000..e4199e6a5ed --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl @@ -0,0 +1,87 @@ + +uniform samplerCube probeHdr; +uniform float roughnessSquared; +uniform float texelSize; +uniform float lodFactor; +uniform float lodMax; +uniform float paddingSize; +uniform float intensityFac; + +in vec3 worldPosition; + +out vec4 FragColor; + +vec3 octahedral_to_cubemap_proj(vec2 co) +{ + co = co * 2.0 - 1.0; + + vec2 abs_co = abs(co); + vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y)); + + if ( abs_co.x + abs_co.y > 1.0 ) { + v.xy = (abs(co.yx) - 1.0) * -sign(co.xy); + } + + return v; +} + +void main() { + vec2 uvs = gl_FragCoord.xy * texelSize; + + /* Add a N pixel border to ensure filtering is correct + * for N mipmap levels. */ + uvs += uvs * texelSize * paddingSize * 2.0; + uvs -= texelSize * paddingSize; + + /* edge mirroring : only mirror if directly adjacent + * (not diagonally adjacent) */ + vec2 m = abs(uvs - 0.5) + 0.5; + vec2 f = floor(m); + if (f.x - f.y != 0.0) { + uvs = 1.0 - uvs; + } + + /* clamp to [0-1] */ + uvs = fract(uvs); + + /* get cubemap vector */ + vec3 cubevec = octahedral_to_cubemap_proj(uvs); + + vec3 N, T, B, V; + + vec3 R = normalize(cubevec); + + /* Isotropic assumption */ + N = V = R; + + make_orthonormal_basis(N, T, B); /* Generate tangent space */ + + /* Noise to dither the samples */ + /* Note : ghosting is better looking than noise. */ + // setup_noise(); + + /* Integrating Envmap */ + float weight = 0.0; + vec3 out_radiance = vec3(0.0); + for (float i = 0; i < sampleCount; i++) { + vec3 H = sample_ggx(i, roughnessSquared, N, T, B); /* Microfacet normal */ + vec3 L = -reflect(V, H); + float NL = dot(N, L); + + if (NL > 0.0) { + float NH = max(1e-8, dot(N, H)); /* cosTheta */ + + /* Coarse Approximation of the mapping distortion + * Unit Sphere -> Cubemap Face */ + const float dist = 4.0 * M_PI / 6.0; + float pdf = pdf_ggx_reflect(NH, roughnessSquared); + /* http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html : Equation 13 */ + float lod = clamp(lodFactor - 0.5 * log2(pdf * dist), 0.0, lodMax) ; + + out_radiance += textureLod(probeHdr, L, lod).rgb * NL; + weight += NL; + } + } + + FragColor = vec4(intensityFac * out_radiance / weight, 1.0); +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl new file mode 100644 index 00000000000..211fa8f0ce8 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl @@ -0,0 +1,88 @@ + +uniform samplerCube probeDepth; +uniform int outputSize; +uniform float lodFactor; +uniform float storedTexelSize; +uniform float lodMax; +uniform float nearClip; +uniform float farClip; +uniform float visibilityRange; +uniform float visibilityBlur; + +out vec4 FragColor; + +vec3 octahedral_to_cubemap_proj(vec2 co) +{ + co = co * 2.0 - 1.0; + + vec2 abs_co = abs(co); + vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y)); + + if ( abs_co.x + abs_co.y > 1.0 ) { + v.xy = (abs(co.yx) - 1.0) * -sign(co.xy); + } + + return v; +} + +float linear_depth(float z) +{ + return (nearClip * farClip) / (z * (nearClip - farClip) + farClip); +} + +float get_world_distance(float depth, vec3 cos) +{ + float is_background = step(1.0, depth); + depth = linear_depth(depth); + depth += 1e1 * is_background; + cos = normalize(abs(cos)); + float cos_vec = max(cos.x, max(cos.y, cos.z)); + return depth / cos_vec; +} + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy) % ivec2(outputSize); + + vec3 cos; + + cos.xy = (vec2(texel) + 0.5) * storedTexelSize; + + /* add a 2 pixel border to ensure filtering is correct */ + cos.xy *= 1.0 + storedTexelSize * 2.0; + cos.xy -= storedTexelSize; + + float pattern = 1.0; + + /* edge mirroring : only mirror if directly adjacent + * (not diagonally adjacent) */ + vec2 m = abs(cos.xy - 0.5) + 0.5; + vec2 f = floor(m); + if (f.x - f.y != 0.0) { + cos.xy = 1.0 - cos.xy; + } + + /* clamp to [0-1] */ + cos.xy = fract(cos.xy); + + /* get cubemap vector */ + cos = normalize(octahedral_to_cubemap_proj(cos.xy)); + + vec3 T, B; + make_orthonormal_basis(cos, T, B); /* Generate tangent space */ + + vec2 accum = vec2(0.0); + + for (float i = 0; i < sampleCount; i++) { + vec3 sample = sample_cone(i, M_PI_2 * visibilityBlur, cos, T, B); + float depth = texture(probeDepth, sample).r; + depth = get_world_distance(depth, sample); + accum += vec2(depth, depth * depth); + } + + accum *= invSampleCount; + accum = abs(accum); + + /* Encode to normalized RGBA 8 */ + FragColor = visibility_encode(accum, visibilityRange); +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl new file mode 100644 index 00000000000..2ce37d867b7 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl @@ -0,0 +1,34 @@ + +layout(triangles) in; +layout(triangle_strip, max_vertices=3) out; + +uniform int Layer; + +in vec4 vPos[]; +flat in int face[]; +flat out int fFace; + +out vec3 worldPosition; +out vec3 viewPosition; /* Required. otherwise generate linking error. */ +out vec3 worldNormal; /* Required. otherwise generate linking error. */ +out vec3 viewNormal; /* Required. otherwise generate linking error. */ + +const vec3 maj_axes[6] = vec3[6](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3( 0.0, 0.0, 1.0), vec3( 0.0, 0.0, -1.0)); +const vec3 x_axis[6] = vec3[6](vec3(0.0, 0.0, -1.0), vec3( 0.0, 0.0, 1.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3( 1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0)); +const vec3 y_axis[6] = vec3[6](vec3(0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0), vec3( 0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0)); + +void main() { + fFace = face[0]; + gl_Layer = Layer + fFace; + + for (int v = 0; v < 3; ++v) { + gl_Position = vPos[v]; + worldPosition = x_axis[fFace] * vPos[v].x + y_axis[fFace] * vPos[v].y + maj_axes[fFace]; +#ifdef ATTRIB + pass_attrib(v); +#endif + EmitVertex(); + } + + EndPrimitive(); +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl new file mode 100644 index 00000000000..d333ad34bb0 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl @@ -0,0 +1,11 @@ + +flat in int cellOffset; +in vec3 worldNormal; + +out vec4 FragColor; + +void main() +{ + IrradianceData ir_data = load_irradiance_cell(cellOffset, worldNormal); + FragColor = vec4(compute_irradiance(worldNormal, ir_data), 1.0); +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl new file mode 100644 index 00000000000..a017a791e41 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl @@ -0,0 +1,32 @@ + +in vec3 pos; + +uniform float sphere_size; +uniform int offset; +uniform ivec3 grid_resolution; +uniform vec3 corner; +uniform vec3 increment_x; +uniform vec3 increment_y; +uniform vec3 increment_z; + +flat out int cellOffset; +out vec3 worldNormal; + +void main() +{ + vec3 ls_cell_location; + /* Keep in sync with update_irradiance_probe */ + ls_cell_location.z = float(gl_InstanceID % grid_resolution.z); + ls_cell_location.y = float((gl_InstanceID / grid_resolution.z) % grid_resolution.y); + ls_cell_location.x = float(gl_InstanceID / (grid_resolution.z * grid_resolution.y)); + + cellOffset = offset + gl_InstanceID; + + vec3 ws_cell_location = corner + + (increment_x * ls_cell_location.x + + increment_y * ls_cell_location.y + + increment_z * ls_cell_location.z); + + gl_Position = ViewProjectionMatrix * vec4(pos * 0.02 * sphere_size + ws_cell_location, 1.0); + worldNormal = normalize(pos); +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl new file mode 100644 index 00000000000..ced8e7f4f01 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl @@ -0,0 +1,20 @@ +uniform sampler2DArray irradianceGrid; + +out vec4 FragColor; + +void main() +{ +#if defined(IRRADIANCE_SH_L2) + const ivec2 data_size = ivec2(3, 3); +#elif defined(IRRADIANCE_CUBEMAP) + const ivec2 data_size = ivec2(8, 8); +#elif defined(IRRADIANCE_HL2) + const ivec2 data_size = ivec2(3, 2); +#endif + ivec2 coord = ivec2(gl_FragCoord.xy) % data_size; + FragColor = texelFetch(irradianceGrid, ivec3(coord, 0), 0); + + if (any(greaterThanEqual(ivec2(gl_FragCoord.xy), data_size))) { + FragColor = vec4(0.0, 0.0, 0.0, 1.0); + } +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl new file mode 100644 index 00000000000..0ffc0cc4b49 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -0,0 +1,300 @@ +/* ----------- Uniforms --------- */ + +uniform sampler2DArray probePlanars; +uniform sampler2DArray probeCubes; + +/* ----------- Structures --------- */ + +struct CubeData { + vec4 position_type; + vec4 attenuation_fac_type; + mat4 influencemat; + mat4 parallaxmat; +}; + +#define PROBE_PARALLAX_BOX 1.0 +#define PROBE_ATTENUATION_BOX 1.0 + +#define p_position position_type.xyz +#define p_parallax_type position_type.w +#define p_atten_fac attenuation_fac_type.x +#define p_atten_type attenuation_fac_type.y + +struct PlanarData { + vec4 plane_equation; + vec4 clip_vec_x_fade_scale; + vec4 clip_vec_y_fade_bias; + vec4 clip_edges; + vec4 facing_scale_bias; + mat4 reflectionmat; /* transform world space into reflection texture space */ +}; + +#define pl_plane_eq plane_equation +#define pl_normal plane_equation.xyz +#define pl_facing_scale facing_scale_bias.x +#define pl_facing_bias facing_scale_bias.y +#define pl_fade_scale clip_vec_x_fade_scale.w +#define pl_fade_bias clip_vec_y_fade_bias.w +#define pl_clip_pos_x clip_vec_x_fade_scale.xyz +#define pl_clip_pos_y clip_vec_y_fade_bias.xyz +#define pl_clip_edges clip_edges + +struct GridData { + mat4 localmat; + ivec4 resolution_offset; + vec4 ws_corner_atten_scale; /* world space corner position */ + vec4 ws_increment_x_atten_bias; /* world space vector between 2 opposite cells */ + vec4 ws_increment_y_lvl_bias; + vec4 ws_increment_z; + vec4 vis_bias_bleed_range; +}; + +#define g_corner ws_corner_atten_scale.xyz +#define g_atten_scale ws_corner_atten_scale.w +#define g_atten_bias ws_increment_x_atten_bias.w +#define g_level_bias ws_increment_y_lvl_bias.w +#define g_increment_x ws_increment_x_atten_bias.xyz +#define g_increment_y ws_increment_y_lvl_bias.xyz +#define g_increment_z ws_increment_z.xyz +#define g_resolution resolution_offset.xyz +#define g_offset resolution_offset.w +#define g_vis_bias vis_bias_bleed_range.x +#define g_vis_bleed vis_bias_bleed_range.y +#define g_vis_range vis_bias_bleed_range.z + +#ifndef MAX_PROBE +#define MAX_PROBE 1 +#endif +#ifndef MAX_GRID +#define MAX_GRID 1 +#endif +#ifndef MAX_PLANAR +#define MAX_PLANAR 1 +#endif + +#ifndef UTIL_TEX +#define UTIL_TEX +uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) +#endif /* UTIL_TEX */ + +layout(std140) uniform probe_block { + CubeData probes_data[MAX_PROBE]; +}; + +layout(std140) uniform grid_block { + GridData grids_data[MAX_GRID]; +}; + +layout(std140) uniform planar_block { + PlanarData planars_data[MAX_PLANAR]; +}; + +/* ----------- Functions --------- */ + +float probe_attenuation_cube(CubeData pd, vec3 W) +{ + vec3 localpos = transform_point(pd.influencemat, W); + + float fac; + if (pd.p_atten_type == PROBE_ATTENUATION_BOX) { + vec3 axes_fac = saturate(pd.p_atten_fac - pd.p_atten_fac * abs(localpos)); + fac = min_v3(axes_fac); + } + else { + fac = saturate(pd.p_atten_fac - pd.p_atten_fac * length(localpos)); + } + + return fac; +} + +float probe_attenuation_planar(PlanarData pd, vec3 W, vec3 N, float roughness) +{ + /* Normal Facing */ + float fac = saturate(dot(pd.pl_normal, N) * pd.pl_facing_scale + pd.pl_facing_bias); + + /* Distance from plane */ + fac *= saturate(abs(dot(pd.pl_plane_eq, vec4(W, 1.0))) * pd.pl_fade_scale + pd.pl_fade_bias); + + /* Fancy fast clipping calculation */ + vec2 dist_to_clip; + dist_to_clip.x = dot(pd.pl_clip_pos_x, W); + dist_to_clip.y = dot(pd.pl_clip_pos_y, W); + /* compare and add all tests */ + fac *= step(2.0, dot(step(pd.pl_clip_edges, dist_to_clip.xxyy), vec2(-1.0, 1.0).xyxy)); + + /* Decrease influence for high roughness */ + fac *= saturate(1.0 - roughness * 10.0); + + return fac; +} + +float probe_attenuation_grid(GridData gd, vec3 W, out vec3 localpos) +{ + localpos = transform_point(gd.localmat, W); + + float fade = min(1.0, min_v3(1.0 - abs(localpos))); + return saturate(fade * gd.g_atten_scale + gd.g_atten_bias); +} + +vec3 probe_evaluate_cube(float id, CubeData cd, vec3 W, vec3 R, float roughness) +{ + /* Correct reflection ray using parallax volume intersection. */ + vec3 localpos = transform_point(cd.parallaxmat, W); + vec3 localray = transform_direction(cd.parallaxmat, R); + + float dist; + if (cd.p_parallax_type == PROBE_PARALLAX_BOX) { + dist = line_unit_box_intersect_dist(localpos, localray); + } + else { + dist = line_unit_sphere_intersect_dist(localpos, localray); + } + + /* Use Distance in WS directly to recover intersection */ + vec3 intersection = W + R * dist - cd.p_position; + + /* From Frostbite PBR Course + * Distance based roughness + * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */ + float original_roughness = roughness; + float linear_roughness = sqrt(roughness); + float distance_roughness = saturate(dist * linear_roughness / length(intersection)); + linear_roughness = mix(distance_roughness, linear_roughness, linear_roughness); + roughness = linear_roughness * linear_roughness; + + float fac = saturate(original_roughness * 2.0 - 1.0); + R = mix(intersection, R, fac * fac); + + return textureLod_octahedron(probeCubes, vec4(R, id), roughness * prbLodCubeMax, prbLodCubeMax).rgb; +} + +vec3 probe_evaluate_world_spec(vec3 R, float roughness) +{ + return textureLod_octahedron(probeCubes, vec4(R, 0.0), roughness * prbLodCubeMax, prbLodCubeMax).rgb; +} + +vec3 probe_evaluate_planar( + float id, PlanarData pd, vec3 W, vec3 N, vec3 V, + float roughness, inout float fade) +{ + /* Find view vector / reflection plane intersection. */ + vec3 point_on_plane = line_plane_intersect(W, V, pd.pl_plane_eq); + + /* How far the pixel is from the plane. */ + float ref_depth = 1.0; /* TODO parameter */ + + /* Compute distorded reflection vector based on the distance to the reflected object. + * In other words find intersection between reflection vector and the sphere center + * around point_on_plane. */ + vec3 proj_ref = reflect(reflect(-V, N) * ref_depth, pd.pl_normal); + + /* Final point in world space. */ + vec3 ref_pos = point_on_plane + proj_ref; + + /* Reproject to find texture coords. */ + vec4 refco = ViewProjectionMatrix * vec4(ref_pos, 1.0); + refco.xy /= refco.w; + + /* TODO: If we support non-ssr planar reflection, we should blur them with gaussian + * and chose the right mip depending on the cone footprint after projection */ + vec3 sample = textureLod(probePlanars, vec3(refco.xy * 0.5 + 0.5, id), 0.0).rgb; + + return sample; +} + +void fallback_cubemap( + vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum) +{ + /* Specular probes */ + vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared); + + vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); + vec3 bent_normal; +#ifdef SSR_AO + float final_ao = occlusion_compute(N, viewPosition, 1.0, rand, bent_normal); + final_ao = specular_occlusion(dot(N, V), final_ao, roughness); +#else + const float final_ao = 1.0; +#endif + + /* Starts at 1 because 0 is world probe */ + for (int i = 1; i < MAX_PROBE && i < prbNumRenderCube && spec_accum.a < 0.999; ++i) { + CubeData cd = probes_data[i]; + + float fade = probe_attenuation_cube(cd, W); + + if (fade > 0.0) { + vec3 spec = final_ao * probe_evaluate_cube(float(i), cd, W, spec_dir, roughness); + accumulate_light(spec, fade, spec_accum); + } + } + + /* World Specular */ + if (spec_accum.a < 0.999) { + vec3 spec = final_ao * probe_evaluate_world_spec(spec_dir, roughness); + accumulate_light(spec, 1.0, spec_accum); + } +} + +#ifdef IRRADIANCE_LIB +vec3 probe_evaluate_grid(GridData gd, vec3 W, vec3 N, vec3 localpos) +{ + localpos = localpos * 0.5 + 0.5; + localpos = localpos * vec3(gd.g_resolution) - 0.5; + + vec3 localpos_floored = floor(localpos); + vec3 trilinear_weight = fract(localpos); + + float weight_accum = 0.0; + vec3 irradiance_accum = vec3(0.0); + + /* For each neighboor cells */ + for (int i = 0; i < 8; ++i) { + ivec3 offset = ivec3(i, i >> 1, i >> 2) & ivec3(1); + vec3 cell_cos = clamp(localpos_floored + vec3(offset), vec3(0.0), vec3(gd.g_resolution) - 1.0); + + /* Keep in sync with update_irradiance_probe */ + ivec3 icell_cos = ivec3(gd.g_level_bias * floor(cell_cos / gd.g_level_bias)); + int cell = gd.g_offset + icell_cos.z + + icell_cos.y * gd.g_resolution.z + + icell_cos.x * gd.g_resolution.z * gd.g_resolution.y; + + vec3 color = irradiance_from_cell_get(cell, N); + + /* We need this because we render probes in world space (so we need light vector in WS). + * And rendering them in local probe space is too much problem. */ + vec3 ws_cell_location = gd.g_corner + + (gd.g_increment_x * cell_cos.x + + gd.g_increment_y * cell_cos.y + + gd.g_increment_z * cell_cos.z); + + vec3 ws_point_to_cell = ws_cell_location - W; + float ws_dist_point_to_cell = length(ws_point_to_cell); + vec3 ws_light = ws_point_to_cell / ws_dist_point_to_cell; + + vec3 trilinear = mix(1 - trilinear_weight, trilinear_weight, offset); + float weight = trilinear.x * trilinear.y * trilinear.z; + + /* Precomputed visibility */ + weight *= load_visibility_cell(cell, ws_light, ws_dist_point_to_cell, gd.g_vis_bias, gd.g_vis_bleed, gd.g_vis_range); + + /* Smooth backface test */ + weight *= sqrt(max(0.002, dot(ws_light, N))); + + /* Avoid zero weight */ + weight = max(0.00001, weight); + + weight_accum += weight; + irradiance_accum += color * weight; + } + + return irradiance_accum / weight_accum; +} + +vec3 probe_evaluate_world_diff(vec3 N) +{ + return irradiance_from_cell_get(0, N); +} + +#endif /* IRRADIANCE_LIB */ diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl new file mode 100644 index 00000000000..3808b59761f --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl @@ -0,0 +1,14 @@ + +uniform sampler2DArray probePlanars; + +in vec3 worldPosition; +flat in int probeIdx; + +out vec4 FragColor; + +void main() +{ + vec4 refco = ViewProjectionMatrix * vec4(worldPosition, 1.0); + refco.xy /= refco.w; + FragColor = vec4(textureLod(probePlanars, vec3(refco.xy * 0.5 + 0.5, float(probeIdx)), 0.0).rgb, 1.0); +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl new file mode 100644 index 00000000000..a71a3bef1e1 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl @@ -0,0 +1,15 @@ + +in vec3 pos; + +in int probe_id; +in mat4 probe_mat; + +out vec3 worldPosition; +flat out int probeIdx; + +void main() +{ + gl_Position = ViewProjectionMatrix * probe_mat * vec4(pos, 1.0); + worldPosition = (probe_mat * vec4(pos, 1.0)).xyz; + probeIdx = probe_id; +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl new file mode 100644 index 00000000000..d629195b815 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_frag.glsl @@ -0,0 +1,40 @@ +/** + * Simple downsample shader. Takes the average of the 4 texels of lower mip. + **/ + +uniform sampler2DArray source; +uniform float fireflyFactor; + +in vec2 uvs; +flat in float layer; + +out vec4 FragColor; + +float brightness(vec3 c) +{ + return max(max(c.r, c.g), c.b); +} + +void main() +{ +#if 0 + /* Reconstructing Target uvs like this avoid missing pixels if NPO2 */ + vec2 uvs = gl_FragCoord.xy * 2.0 / vec2(textureSize(source, 0)); + + FragColor = textureLod(source, vec3(uvs, layer), 0.0); +#else + vec2 texel_size = 1.0 / vec2(textureSize(source, 0)); + vec2 uvs = gl_FragCoord.xy * 2.0 * texel_size; + vec4 ofs = texel_size.xyxy * vec4(0.75, 0.75, -0.75, -0.75); + + FragColor = textureLod(source, vec3(uvs + ofs.xy, layer), 0.0); + FragColor += textureLod(source, vec3(uvs + ofs.xw, layer), 0.0); + FragColor += textureLod(source, vec3(uvs + ofs.zy, layer), 0.0); + FragColor += textureLod(source, vec3(uvs + ofs.zw, layer), 0.0); + FragColor *= 0.25; + + /* Clamped brightness. */ + float luma = max(1e-8, brightness(FragColor.rgb)); + FragColor *= 1.0 - max(0.0, luma - fireflyFactor) / luma; +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl new file mode 100644 index 00000000000..721cc8789a0 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl @@ -0,0 +1,24 @@ + +layout(triangles) in; +layout(triangle_strip, max_vertices=3) out; + +in int instance[]; +in vec2 vPos[]; + +flat out float layer; + +void main() { + gl_Layer = instance[0]; + layer = float(instance[0]); + + gl_Position = vec4(vPos[0], 0.0, 1.0); + EmitVertex(); + + gl_Position = vec4(vPos[1], 0.0, 1.0); + EmitVertex(); + + gl_Position = vec4(vPos[2], 0.0, 1.0); + EmitVertex(); + + EndPrimitive(); +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl new file mode 100644 index 00000000000..d682e39d8ad --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl @@ -0,0 +1,10 @@ + +in vec2 pos; + +out int instance; +out vec2 vPos; + +void main() { + instance = gl_InstanceID; + vPos = pos; +} diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_vert.glsl new file mode 100644 index 00000000000..bbb77af673a --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_vert.glsl @@ -0,0 +1,10 @@ + +in vec3 pos; + +out vec4 vPos; +flat out int face; + +void main() { + vPos = vec4(pos, 1.0); + face = gl_InstanceID; +} diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl new file mode 100644 index 00000000000..accecaacbde --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -0,0 +1,493 @@ + +#ifndef LIT_SURFACE_UNIFORM +#define LIT_SURFACE_UNIFORM + +uniform float refractionDepth; + +#ifndef UTIL_TEX +#define UTIL_TEX +uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) +#endif /* UTIL_TEX */ + +in vec3 worldPosition; +in vec3 viewPosition; + +#ifdef USE_FLAT_NORMAL +flat in vec3 worldNormal; +flat in vec3 viewNormal; +#else +in vec3 worldNormal; +in vec3 viewNormal; +#endif + +#ifdef HAIR_SHADER +in vec3 hairTangent; /* world space */ +in float hairThickTime; +in float hairThickness; +in float hairTime; + +uniform int hairThicknessRes = 1; +#endif + +#endif /* LIT_SURFACE_UNIFORM */ + +/** AUTO CONFIG + * We include the file multiple times each time with a different configuration. + * This leads to a lot of deadcode. Better idea would be to only generate the one needed. + */ +#if !defined(SURFACE_DEFAULT) + #define SURFACE_DEFAULT + #define CLOSURE_NAME eevee_closure_default + #define CLOSURE_DIFFUSE + #define CLOSURE_GLOSSY +#endif /* SURFACE_DEFAULT */ + +#if !defined(SURFACE_PRINCIPLED) && !defined(CLOSURE_NAME) + #define SURFACE_PRINCIPLED + #define CLOSURE_NAME eevee_closure_principled + #define CLOSURE_DIFFUSE + #define CLOSURE_GLOSSY + #define CLOSURE_CLEARCOAT + #define CLOSURE_REFRACTION + #define CLOSURE_SUBSURFACE +#endif /* SURFACE_PRINCIPLED */ + +#if !defined(SURFACE_DIFFUSE) && !defined(CLOSURE_NAME) + #define SURFACE_DIFFUSE + #define CLOSURE_NAME eevee_closure_diffuse + #define CLOSURE_DIFFUSE +#endif /* SURFACE_DIFFUSE */ + +#if !defined(SURFACE_SUBSURFACE) && !defined(CLOSURE_NAME) + #define SURFACE_SUBSURFACE + #define CLOSURE_NAME eevee_closure_subsurface + #define CLOSURE_DIFFUSE + #define CLOSURE_SUBSURFACE +#endif /* SURFACE_SUBSURFACE */ + +#if !defined(SURFACE_GLOSSY) && !defined(CLOSURE_NAME) + #define SURFACE_GLOSSY + #define CLOSURE_NAME eevee_closure_glossy + #define CLOSURE_GLOSSY +#endif /* SURFACE_GLOSSY */ + +#if !defined(SURFACE_REFRACT) && !defined(CLOSURE_NAME) + #define SURFACE_REFRACT + #define CLOSURE_NAME eevee_closure_refraction + #define CLOSURE_REFRACTION +#endif /* SURFACE_REFRACT */ + +#if !defined(SURFACE_GLASS) && !defined(CLOSURE_NAME) + #define SURFACE_GLASS + #define CLOSURE_NAME eevee_closure_glass + #define CLOSURE_GLOSSY + #define CLOSURE_REFRACTION +#endif /* SURFACE_GLASS */ + +/* Safety : CLOSURE_CLEARCOAT implies CLOSURE_GLOSSY */ +#ifdef CLOSURE_CLEARCOAT + #ifndef CLOSURE_GLOSSY + #define CLOSURE_GLOSSY + #endif +#endif /* CLOSURE_CLEARCOAT */ + +void CLOSURE_NAME( + vec3 N +#ifdef CLOSURE_DIFFUSE + , vec3 albedo +#endif +#ifdef CLOSURE_GLOSSY + , vec3 f0, int ssr_id +#endif +#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION) + , float roughness +#endif +#ifdef CLOSURE_CLEARCOAT + , vec3 C_N, float C_intensity, float C_roughness +#endif +#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE) + , float ao +#endif +#ifdef CLOSURE_SUBSURFACE + , float sss_scale +#endif +#ifdef CLOSURE_REFRACTION + , float ior +#endif +#ifdef CLOSURE_DIFFUSE + , out vec3 out_diff +#endif +#ifdef CLOSURE_SUBSURFACE + , out vec3 out_trans +#endif +#ifdef CLOSURE_GLOSSY + , out vec3 out_spec +#endif +#ifdef CLOSURE_REFRACTION + , out vec3 out_refr +#endif +#ifdef CLOSURE_GLOSSY + , out vec3 ssr_spec +#endif + ) +{ +#ifdef CLOSURE_DIFFUSE + out_diff = vec3(0.0); +#endif + +#ifdef CLOSURE_SUBSURFACE + out_trans = vec3(0.0); +#endif + +#ifdef CLOSURE_GLOSSY + out_spec = vec3(0.0); +#endif + +#ifdef CLOSURE_REFRACTION + out_refr = vec3(0.0); +#endif + + /* Zero length vectors cause issues, see: T51979. */ + float len = length(N); + if (isnan(len)) { + return; + } + N /= len; + +#ifdef CLOSURE_CLEARCOAT + len = length(C_N); + if (isnan(len)) { + return; + } + C_N /= len; +#endif + +#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION) + roughness = clamp(roughness, 1e-8, 0.9999); + float roughnessSquared = roughness * roughness; +#endif + +#ifdef CLOSURE_CLEARCOAT + C_roughness = clamp(C_roughness, 1e-8, 0.9999); + float C_roughnessSquared = C_roughness * C_roughness; +#endif + + vec3 V = cameraVec; + + vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); + +#ifdef HAIR_SHADER + if (hairThicknessRes == 1) { + /* Random normal distribution on the hair surface. */ + vec3 T = normalize(worldNormal); /* meh, TODO fix worldNormal misnaming. */ + vec3 B = normalize(cross(V, T)); + N = cross(T, B); /* Normal facing view */ + /* We want a cosine distribution. */ + float cos_theta = rand.x * 2.0 - 1.0; + float sin_theta = sqrt(max(0.0, 1.0f - cos_theta*cos_theta));; + N = N * sin_theta + B * cos_theta; + +# ifdef CLOSURE_GLOSSY + /* Hair random normal does not work with SSR :(. + * It just create self reflection feedback (which is beautifful btw) + * but not correct. */ + ssr_id = NO_SSR; /* Force bypass */ +# endif + } + else { + vec3 T = normalize(cross(hairTangent, worldNormal)); + /* We want a cosine distribution. */ + float cos_theta = hairThickTime / hairThickness; + float sin_theta = sqrt(max(0.0, 1.0f - cos_theta*cos_theta));; + N = normalize(hairTangent * cos_theta + T * sin_theta); + } +#endif + + /* ---------------------------------------------------------------- */ + /* -------------------- SCENE LAMPS LIGHTING ---------------------- */ + /* ---------------------------------------------------------------- */ + + for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) { + LightData ld = lights_data[i]; + + vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */ + l_vector.xyz = ld.l_position - worldPosition; + l_vector.w = length(l_vector.xyz); + + vec3 l_color_vis = ld.l_color * light_visibility(ld, worldPosition, viewPosition, viewNormal, l_vector); + + #ifdef CLOSURE_DIFFUSE + out_diff += l_color_vis * light_diffuse(ld, N, V, l_vector); + #endif + + #ifdef CLOSURE_SUBSURFACE + out_trans += ld.l_color * light_translucent(ld, worldPosition, -N, l_vector, sss_scale); + #endif + + #ifdef CLOSURE_GLOSSY + out_spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0) * ld.l_spec; + #endif + + #ifdef CLOSURE_CLEARCOAT + out_spec += l_color_vis * light_specular(ld, C_N, V, l_vector, C_roughnessSquared, f0) * C_intensity * ld.l_spec; + #endif + } + + + /* ---------------------------------------------------------------- */ + /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */ + /* ---------------------------------------------------------------- */ + + /* Accumulate incomming light from all sources until accumulator is full. Then apply Occlusion and BRDF. */ +#ifdef CLOSURE_GLOSSY + vec4 spec_accum = vec4(0.0); +#endif + +#ifdef CLOSURE_CLEARCOAT + vec4 C_spec_accum = vec4(0.0); +#endif + +#ifdef CLOSURE_REFRACTION + vec4 refr_accum = vec4(0.0); +#endif + +#ifdef CLOSURE_GLOSSY + /* ---------------------------- */ + /* Planar Reflections */ + /* ---------------------------- */ + + for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar && spec_accum.a < 0.999; ++i) { + PlanarData pd = planars_data[i]; + + /* Fade on geometric normal. */ + float fade = probe_attenuation_planar(pd, worldPosition, worldNormal, roughness); + + if (fade > 0.0) { + if (!(ssrToggle && ssr_id == outputSsrId)) { + vec3 spec = probe_evaluate_planar(float(i), pd, worldPosition, N, V, roughness, fade); + accumulate_light(spec, fade, spec_accum); + } + + #ifdef CLOSURE_CLEARCOAT + vec3 C_spec = probe_evaluate_planar(float(i), pd, worldPosition, C_N, V, C_roughness, fade); + accumulate_light(C_spec, fade, C_spec_accum); + #endif + + } + } +#endif + + +#ifdef CLOSURE_GLOSSY + vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared); +#endif + +#ifdef CLOSURE_CLEARCOAT + vec3 C_spec_dir = get_specular_reflection_dominant_dir(C_N, V, C_roughnessSquared); +#endif + +#ifdef CLOSURE_REFRACTION + /* Refract the view vector using the depth heuristic. + * Then later Refract a second time the already refracted + * ray using the inverse ior. */ + float final_ior = (refractionDepth > 0.0) ? 1.0 / ior : ior; + vec3 refr_V = (refractionDepth > 0.0) ? -refract(-V, N, final_ior) : V; + vec3 refr_pos = (refractionDepth > 0.0) ? line_plane_intersect(worldPosition, refr_V, worldPosition - N * refractionDepth, N) : worldPosition; + vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior); +#endif + + +#ifdef CLOSURE_REFRACTION + /* ---------------------------- */ + /* Screen Space Refraction */ + /* ---------------------------- */ + #ifdef USE_REFRACTION + if (ssrToggle && roughness < ssrMaxRoughness + 0.2) { + /* Find approximated position of the 2nd refraction event. */ + vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition; + vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand); + trans.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness); + accumulate_light(trans.rgb, trans.a, refr_accum); + } + #endif + +#endif + + + /* ---------------------------- */ + /* Specular probes */ + /* ---------------------------- */ +#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION) + + #ifdef CLOSURE_REFRACTION + #define ACCUM refr_accum + #else + #define ACCUM spec_accum + #endif + + /* Starts at 1 because 0 is world probe */ + for (int i = 1; ACCUM.a < 0.999 && i < prbNumRenderCube && i < MAX_PROBE; ++i) { + CubeData cd = probes_data[i]; + + float fade = probe_attenuation_cube(cd, worldPosition); + + if (fade > 0.0) { + + #ifdef CLOSURE_GLOSSY + if (!(ssrToggle && ssr_id == outputSsrId)) { + vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness); + accumulate_light(spec, fade, spec_accum); + } + #endif + + #ifdef CLOSURE_CLEARCOAT + vec3 C_spec = probe_evaluate_cube(float(i), cd, worldPosition, C_spec_dir, C_roughness); + accumulate_light(C_spec, fade, C_spec_accum); + #endif + + #ifdef CLOSURE_REFRACTION + vec3 trans = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared); + accumulate_light(trans, fade, refr_accum); + #endif + } + } + + #undef ACCUM + + /* ---------------------------- */ + /* World Probe */ + /* ---------------------------- */ + #ifdef CLOSURE_GLOSSY + if (spec_accum.a < 0.999) { + if (!(ssrToggle && ssr_id == outputSsrId)) { + vec3 spec = probe_evaluate_world_spec(spec_dir, roughness); + accumulate_light(spec, 1.0, spec_accum); + } + + #ifdef CLOSURE_CLEARCOAT + vec3 C_spec = probe_evaluate_world_spec(C_spec_dir, C_roughness); + accumulate_light(C_spec, 1.0, C_spec_accum); + #endif + + } + #endif + + #ifdef CLOSURE_REFRACTION + if (refr_accum.a < 0.999) { + vec3 trans = probe_evaluate_world_spec(refr_dir, roughnessSquared); + accumulate_light(trans, 1.0, refr_accum); + } + #endif +#endif /* Specular probes */ + + + /* ---------------------------- */ + /* Ambient Occlusion */ + /* ---------------------------- */ +#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE) + vec3 bent_normal; + float final_ao = occlusion_compute(N, viewPosition, ao, rand, bent_normal); +#endif + + + /* ---------------------------- */ + /* Specular Output */ + /* ---------------------------- */ + float NV = dot(N, V); +#ifdef CLOSURE_GLOSSY + vec2 uv = lut_coords(NV, roughness); + vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg; + + /* This factor is outputed to be used by SSR in order + * to match the intensity of the regular reflections. */ + ssr_spec = F_ibl(f0, brdf_lut); + float spec_occlu = specular_occlusion(NV, final_ao, roughness); + + /* The SSR pass recompute the occlusion to not apply it to the SSR */ + if (ssrToggle && ssr_id == outputSsrId) { + spec_occlu = 1.0; + } + + out_spec += spec_accum.rgb * ssr_spec * spec_occlu * float(specToggle); + +# ifdef HAIR_SHADER + /* Hack: Overide spec color so that ssr will not be computed + * even if ssr_id match the active ssr. */ + ssr_spec = vec3(0.0); +# endif +#endif + +#ifdef CLOSURE_REFRACTION + float btdf = get_btdf_lut(utilTex, NV, roughness, ior); + + out_refr += refr_accum.rgb * btdf; +#endif + +#ifdef CLOSURE_CLEARCOAT + NV = dot(C_N, V); + vec2 C_uv = lut_coords(NV, C_roughness); + vec2 C_brdf_lut = texture(utilTex, vec3(C_uv, 1.0)).rg; + vec3 C_fresnel = F_ibl(vec3(0.04), brdf_lut) * specular_occlusion(NV, final_ao, C_roughness); + + out_spec += C_spec_accum.rgb * C_fresnel * float(specToggle) * C_intensity; +#endif + + /* ---------------------------------------------------------------- */ + /* ---------------- DIFFUSE ENVIRONMENT LIGHTING ------------------ */ + /* ---------------------------------------------------------------- */ + + /* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */ +#ifdef CLOSURE_DIFFUSE + vec4 diff_accum = vec4(0.0); + + /* ---------------------------- */ + /* Irradiance Grids */ + /* ---------------------------- */ + /* Start at 1 because 0 is world irradiance */ + for (int i = 1; i < MAX_GRID && i < prbNumRenderGrid && diff_accum.a < 0.999; ++i) { + GridData gd = grids_data[i]; + + vec3 localpos; + float fade = probe_attenuation_grid(gd, worldPosition, localpos); + + if (fade > 0.0) { + vec3 diff = probe_evaluate_grid(gd, worldPosition, bent_normal, localpos); + accumulate_light(diff, fade, diff_accum); + } + } + + /* ---------------------------- */ + /* World Diffuse */ + /* ---------------------------- */ + if (diff_accum.a < 0.999 && prbNumRenderGrid > 0) { + vec3 diff = probe_evaluate_world_diff(bent_normal); + accumulate_light(diff, 1.0, diff_accum); + } + + out_diff += diff_accum.rgb * gtao_multibounce(final_ao, albedo); +#endif +} + +/* Cleanup for next configuration */ +#undef CLOSURE_NAME + +#ifdef CLOSURE_DIFFUSE + #undef CLOSURE_DIFFUSE +#endif + +#ifdef CLOSURE_GLOSSY + #undef CLOSURE_GLOSSY +#endif + +#ifdef CLOSURE_CLEARCOAT + #undef CLOSURE_CLEARCOAT +#endif + +#ifdef CLOSURE_REFRACTION + #undef CLOSURE_REFRACTION +#endif + +#ifdef CLOSURE_SUBSURFACE + #undef CLOSURE_SUBSURFACE +#endif
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl new file mode 100644 index 00000000000..d643ebb73dd --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl @@ -0,0 +1,68 @@ + +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; +uniform mat4 ModelViewMatrix; +uniform mat3 WorldNormalMatrix; +#ifndef ATTRIB +uniform mat3 NormalMatrix; +uniform mat4 ModelMatrixInverse; +#endif + +#ifndef HAIR_SHADER +in vec3 pos; +in vec3 nor; +#endif + +out vec3 worldPosition; +out vec3 viewPosition; + +/* Used for planar reflections */ +/* keep in sync with EEVEE_ClipPlanesUniformBuffer */ +layout(std140) uniform clip_block { + vec4 ClipPlanes[1]; +}; + +#ifdef USE_FLAT_NORMAL +flat out vec3 worldNormal; +flat out vec3 viewNormal; +#else +out vec3 worldNormal; +out vec3 viewNormal; +#endif + +#ifdef HAIR_SHADER +out vec3 hairTangent; +out float hairThickTime; +out float hairThickness; +out float hairTime; +#endif + +void main() +{ +#ifdef HAIR_SHADER + vec3 pos, nor; + hair_get_pos_tan_nor_time( + (ProjectionMatrix[3][3] == 0.0), + ViewMatrixInverse[3].xyz, ViewMatrixInverse[2].xyz, + pos, nor, hairTangent, hairTime, hairThickness, hairThickTime); + + gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); + viewPosition = (ViewMatrix * vec4(pos, 1.0)).xyz; + worldPosition = pos; + worldNormal = nor; + viewNormal = normalize(mat3(ViewMatrixInverse) * nor); +#else + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz; + worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz; + worldNormal = normalize(WorldNormalMatrix * nor); + viewNormal = normalize(NormalMatrix * nor); +#endif + + /* Used for planar reflections */ + gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), ClipPlanes[0]); + +#ifdef ATTRIB + pass_attrib(pos); +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl new file mode 100644 index 00000000000..5c62cb19152 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl @@ -0,0 +1,322 @@ +/** + * Adapted from : + * Real-Time Polygonal-Light Shading with Linearly Transformed Cosines. + * Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. + * ACM Transactions on Graphics (Proceedings of ACM SIGGRAPH 2016) 35(4), 2016. + * Project page: https://eheitzresearch.wordpress.com/415-2/ + **/ + +#define USE_LTC + +#ifndef UTIL_TEX +#define UTIL_TEX +uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) +#endif /* UTIL_TEX */ + +/* Diffuse *clipped* sphere integral. */ +float diffuse_sphere_integral_lut(float avg_dir_z, float form_factor) +{ + vec2 uv = vec2(avg_dir_z * 0.5 + 0.5, form_factor); + uv = uv * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE; + + return texture(utilTex, vec3(uv, 1.0)).w; +} + +float diffuse_sphere_integral_cheap(float avg_dir_z, float form_factor) +{ + return max((form_factor * form_factor + avg_dir_z) / (form_factor + 1.0), 0.0); +} + +/** + * An extended version of the implementation from + * "How to solve a cubic equation, revisited" + * http://momentsingraphics.de/?p=105 + **/ +vec3 solve_cubic(vec4 coefs) +{ + /* Normalize the polynomial */ + coefs.xyz /= coefs.w; + /* Divide middle coefficients by three */ + coefs.yz /= 3.0; + + float A = coefs.w; + float B = coefs.z; + float C = coefs.y; + float D = coefs.x; + + /* Compute the Hessian and the discriminant */ + vec3 delta = vec3( + -coefs.z*coefs.z + coefs.y, + -coefs.y*coefs.z + coefs.x, + dot(vec2(coefs.z, -coefs.y), coefs.xy) + ); + + /* Discriminant */ + float discr = dot(vec2(4.0 * delta.x, -delta.y), delta.zy); + + vec2 xlc, xsc; + + /* Algorithm A */ + { + float A_a = 1.0; + float C_a = delta.x; + float D_a = -2.0 * B * delta.x + delta.y; + + /* Take the cubic root of a normalized complex number */ + float theta = atan(sqrt(discr), -D_a) / 3.0; + + float x_1a = 2.0 * sqrt(-C_a) * cos(theta); + float x_3a = 2.0 * sqrt(-C_a) * cos(theta + (2.0 / 3.0) * M_PI); + + float xl; + if ((x_1a + x_3a) > 2.0 * B) { + xl = x_1a; + } + else { + xl = x_3a; + } + + xlc = vec2(xl - B, A); + } + + /* Algorithm D */ + { + float A_d = D; + float C_d = delta.z; + float D_d = -D * delta.y + 2.0 * C * delta.z; + + /* Take the cubic root of a normalized complex number */ + float theta = atan(D * sqrt(discr), -D_d) / 3.0; + + float x_1d = 2.0 * sqrt(-C_d) * cos(theta); + float x_3d = 2.0 * sqrt(-C_d) * cos(theta + (2.0 / 3.0) * M_PI); + + float xs; + if (x_1d + x_3d < 2.0 * C) + xs = x_1d; + else + xs = x_3d; + + xsc = vec2(-D, xs + C); + } + + float E = xlc.y * xsc.y; + float F = -xlc.x * xsc.y - xlc.y * xsc.x; + float G = xlc.x * xsc.x; + + vec2 xmc = vec2(C * F - B * G, -B * F + C * E); + + vec3 root = vec3(xsc.x / xsc.y, + xmc.x / xmc.y, + xlc.x / xlc.y); + + if (root.x < root.y && root.x < root.z) { + root.xyz = root.yxz; + } + else if (root.z < root.x && root.z < root.y) { + root.xyz = root.xzy; + } + + return root; +} + +/* from Real-Time Area Lighting: a Journey from Research to Production + * Stephen Hill and Eric Heitz */ +vec3 edge_integral_vec(vec3 v1, vec3 v2) +{ + float x = dot(v1, v2); + float y = abs(x); + + float a = 0.8543985 + (0.4965155 + 0.0145206 * y) * y; + float b = 3.4175940 + (4.1616724 + y) * y; + float v = a / b; + + float theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt(max(1.0 - x * x, 1e-7)) - v; + + return cross(v1, v2) * theta_sintheta; +} + +mat3 ltc_matrix(vec4 lut) +{ + /* load inverse matrix */ + mat3 Minv = mat3( + vec3( 1, 0, lut.y), + vec3( 0, lut.z, 0), + vec3(lut.w, 0, lut.x) + ); + + return Minv; +} + +void ltc_transform_quad(vec3 N, vec3 V, mat3 Minv, inout vec3 corners[4]) +{ + /* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */ + V = normalize(V + 1e-8); + + /* construct orthonormal basis around N */ + vec3 T1, T2; + T1 = normalize(V - N * dot(N, V)); + T2 = cross(N, T1); + + /* rotate area light in (T1, T2, R) basis */ + Minv = Minv * transpose(mat3(T1, T2, N)); + + /* Apply LTC inverse matrix. */ + corners[0] = normalize(Minv * corners[0]); + corners[1] = normalize(Minv * corners[1]); + corners[2] = normalize(Minv * corners[2]); + corners[3] = normalize(Minv * corners[3]); +} + +/* If corners have already pass through ltc_transform_quad(), then N **MUST** be vec3(0.0, 0.0, 1.0), + * corresponding to the Up axis of the shading basis. */ +float ltc_evaluate_quad(vec3 corners[4], vec3 N) +{ + /* Approximation using a sphere of the same solid angle than the quad. + * Finding the clipped sphere diffuse integral is easier than clipping the quad. */ + vec3 avg_dir; + avg_dir = edge_integral_vec(corners[0], corners[1]); + avg_dir += edge_integral_vec(corners[1], corners[2]); + avg_dir += edge_integral_vec(corners[2], corners[3]); + avg_dir += edge_integral_vec(corners[3], corners[0]); + + float form_factor = length(avg_dir); + float avg_dir_z = dot(N, avg_dir / form_factor); + +#if 1 /* use tabulated horizon-clipped sphere */ + return form_factor * diffuse_sphere_integral_lut(avg_dir_z, form_factor); +#else /* Less accurate version, a bit cheaper. */ + return form_factor * diffuse_sphere_integral_cheap(avg_dir_z, form_factor); +#endif +} + +/* If disk does not need to be transformed and is already front facing. */ +float ltc_evaluate_disk_simple(float disk_radius, float NL) +{ + float r_sqr = disk_radius * disk_radius; + float one_r_sqr = 1.0 + r_sqr; + float form_factor = r_sqr * inversesqrt(one_r_sqr * one_r_sqr); + +#if 1 /* use tabulated horizon-clipped sphere */ + return form_factor * diffuse_sphere_integral_lut(NL, form_factor); +#else /* Less accurate version, a bit cheaper. */ + return form_factor * diffuse_sphere_integral_cheap(NL, form_factor); +#endif +} + +/* disk_points are WS vectors from the shading point to the disk "bounding domain" */ +float ltc_evaluate_disk(vec3 N, vec3 V, mat3 Minv, vec3 disk_points[3]) +{ + /* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */ + V = normalize(V + 1e-8); + + /* construct orthonormal basis around N */ + vec3 T1, T2; + T1 = normalize(V - N * dot(V, N)); + T2 = cross(N, T1); + + /* rotate area light in (T1, T2, R) basis */ + mat3 R = transpose(mat3(T1, T2, N)); + + /* Intermediate step: init ellipse. */ + vec3 L_[3]; + L_[0] = mul(R, disk_points[0]); + L_[1] = mul(R, disk_points[1]); + L_[2] = mul(R, disk_points[2]); + + vec3 C = 0.5 * (L_[0] + L_[2]); + vec3 V1 = 0.5 * (L_[1] - L_[2]); + vec3 V2 = 0.5 * (L_[1] - L_[0]); + + /* Transform ellipse by Minv. */ + C = Minv * C; + V1 = Minv * V1; + V2 = Minv * V2; + + /* Compute eigenvectors of new ellipse. */ + + float d11 = dot(V1, V1); + float d22 = dot(V2, V2); + float d12 = dot(V1, V2); + float a, b; /* Eigenvalues */ + const float threshold = 0.0007; /* Can be adjusted. Fix artifacts. */ + if (abs(d12) / sqrt(d11 * d22) > threshold) { + float tr = d11 + d22; + float det = -d12 * d12 + d11 * d22; + + /* use sqrt matrix to solve for eigenvalues */ + det = sqrt(det); + float u = 0.5 * sqrt(tr - 2.0 * det); + float v = 0.5 * sqrt(tr + 2.0 * det); + float e_max = (u + v); + float e_min = (u - v); + e_max *= e_max; + e_min *= e_min; + + vec3 V1_, V2_; + if (d11 > d22) { + V1_ = d12 * V1 + (e_max - d11) * V2; + V2_ = d12 * V1 + (e_min - d11) * V2; + } + else { + V1_ = d12 * V2 + (e_max - d22) * V1; + V2_ = d12 * V2 + (e_min - d22) * V1; + } + + a = 1.0 / e_max; + b = 1.0 / e_min; + V1 = normalize(V1_); + V2 = normalize(V2_); + } + else { + a = 1.0 / d11; + b = 1.0 / d22; + V1 *= sqrt(a); + V2 *= sqrt(b); + } + + /* Now find front facing ellipse with same solid angle. */ + + vec3 V3 = normalize(cross(V1, V2)); + if (dot(C, V3) < 0.0) + V3 *= -1.0; + + float L = dot(V3, C); + float x0 = dot(V1, C) / L; + float y0 = dot(V2, C) / L; + + a *= L*L; + b *= L*L; + + float c0 = a * b; + float c1 = a * b * (1.0 + x0 * x0 + y0 * y0) - a - b; + float c2 = 1.0 - a * (1.0 + x0 * x0) - b * (1.0 + y0 * y0); + float c3 = 1.0; + + vec3 roots = solve_cubic(vec4(c0, c1, c2, c3)); + float e1 = roots.x; + float e2 = roots.y; + float e3 = roots.z; + + vec3 avg_dir = vec3(a * x0 / (a - e2), b * y0 / (b - e2), 1.0); + + mat3 rotate = mat3(V1, V2, V3); + + avg_dir = rotate * avg_dir; + avg_dir = normalize(avg_dir); + + /* L1, L2 are the extends of the front facing ellipse. */ + float L1 = sqrt(-e2/e3); + float L2 = sqrt(-e2/e1); + + /* Find the sphere and compute lighting. */ + float form_factor = max(0.0, L1 * L2 * inversesqrt((1.0 + L1 * L1) * (1.0 + L2 * L2))); + +#if 1 /* use tabulated horizon-clipped sphere */ + return form_factor * diffuse_sphere_integral_lut(avg_dir.z, form_factor); +#else /* Less accurate version, a bit cheaper. */ + return form_factor * diffuse_sphere_integral_cheap(avg_dir.z, form_factor); +#endif +} + diff --git a/source/blender/draw/engines/eevee/shaders/octahedron_lib.glsl b/source/blender/draw/engines/eevee/shaders/octahedron_lib.glsl new file mode 100644 index 00000000000..631b325ae37 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/octahedron_lib.glsl @@ -0,0 +1,38 @@ + +vec2 mapping_octahedron(vec3 cubevec, vec2 texel_size) +{ + /* projection onto octahedron */ + cubevec /= dot( vec3(1), abs(cubevec) ); + + /* out-folding of the downward faces */ + if ( cubevec.z < 0.0 ) { + cubevec.xy = (1.0 - abs(cubevec.yx)) * sign(cubevec.xy); + } + + /* mapping to [0;1]ˆ2 texture space */ + vec2 uvs = cubevec.xy * (0.5) + 0.5; + + /* edge filtering fix */ + uvs *= 1.0 - 2.0 * texel_size; + uvs += texel_size; + + return uvs; +} + +vec4 textureLod_octahedron(sampler2DArray tex, vec4 cubevec, float lod, float lod_max) +{ + vec2 texelSize = 1.0 / vec2(textureSize(tex, int(lod_max))); + + vec2 uvs = mapping_octahedron(cubevec.xyz, texelSize); + + return textureLod(tex, vec3(uvs, cubevec.w), lod); +} + +vec4 texture_octahedron(sampler2DArray tex, vec4 cubevec) +{ + vec2 texelSize = 1.0 / vec2(textureSize(tex, 0)); + + vec2 uvs = mapping_octahedron(cubevec.xyz, texelSize); + + return texture(tex, vec3(uvs, cubevec.w)); +} diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl new file mode 100644 index 00000000000..1c0e65f0613 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl @@ -0,0 +1,87 @@ + +#ifdef USE_ALPHA_HASH + +/* From the paper "Hashed Alpha Testing" by Chris Wyman and Morgan McGuire */ +float hash(vec2 a) { + return fract(1e4 * sin(17.0 * a.x + 0.1 * a.y) * (0.1 + abs(sin(13.0 * a.y + a.x)))); +} + +float hash3d(vec3 a) { + return hash(vec2(hash(a.xy), a.z)); +} + +uniform float hashAlphaOffset; + +float hashed_alpha_threshold(vec3 co) +{ + const float hash_scale = 1.0; /* Roughly in pixel */ + + /* Find the discretized derivatives of our coordinates. */ + float max_deriv = max(length(dFdx(co)), length(dFdy(co))); + float pix_scale = 1.0 / (hash_scale * max_deriv); + + /* Find two nearest log-discretized noise scales. */ + float pix_scale_log = log2(pix_scale); + vec2 pix_scales; + pix_scales.x = exp2(floor(pix_scale_log)); + pix_scales.y = exp2(ceil(pix_scale_log)); + + /* Compute alpha thresholds at our two noise scales. */ + vec2 alpha; + alpha.x = hash3d(floor(pix_scales.x * co)); + alpha.y = hash3d(floor(pix_scales.y * co)); + + /* Factor to interpolate lerp with. */ + float fac = fract(log2(pix_scale)); + + /* Interpolate alpha threshold from noise at two scales. */ + float x = mix(alpha.x, alpha.y, fac); + + /* Pass into CDF to compute uniformly distrib threshold. */ + float a = min(fac, 1.0 - fac); + float one_a = 1.0 - a; + float denom = 1.0 / (2 * a * one_a); + float one_x = (1 - x); + vec3 cases = vec3( + (x * x) * denom, + (x - 0.5 * a) / one_a, + 1.0 - (one_x * one_x * denom) + ); + + /* Find our final, uniformly distributed alpha threshold. */ + float threshold = (x < one_a) ? ((x < a) ? cases.x : cases.y) : cases.z; + + /* Avoids threshold == 0. */ + threshold = clamp(threshold, 1.0e-6, 1.0); + + /* Jitter the threshold for TAA accumulation. */ + return fract(threshold + hashAlphaOffset); +} + +#endif + +#ifdef USE_ALPHA_CLIP +uniform float alphaThreshold; +#endif + +void main() +{ + /* For now do nothing. + * In the future, output object motion blur. */ + +#if defined(USE_ALPHA_HASH) || defined(USE_ALPHA_CLIP) +#define NODETREE_EXEC + + Closure cl = nodetree_exec(); + +#if defined(USE_ALPHA_HASH) + /* Hashed Alpha Testing */ + if (cl.opacity < hashed_alpha_threshold(worldPosition)) + discard; +#elif defined(USE_ALPHA_CLIP) + /* Alpha clip */ + if (cl.opacity <= alphaThreshold) + discard; +#endif +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl new file mode 100644 index 00000000000..1ed4f5f6500 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl @@ -0,0 +1,35 @@ + +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; + +/* keep in sync with DRWManager.view_data */ +layout(std140) uniform clip_block { + vec4 ClipPlanes[1]; +}; + +#ifndef HAIR_SHADER +in vec3 pos; +#endif + +void main() +{ +#ifdef HAIR_SHADER + float time, thick_time, thickness; + vec3 pos, nor, binor; + hair_get_pos_tan_nor_time( + (ProjectionMatrix[3][3] == 0.0), + ViewMatrixInverse[3].xyz, ViewMatrixInverse[2].xyz, + pos, nor, binor, time, thickness, thick_time); + + gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); + vec4 worldPosition = vec4(pos, 1.0); +#else + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec4 worldPosition = (ModelMatrix * vec4(pos, 1.0)); +#endif + +#ifdef CLIP_PLANES + gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), ClipPlanes[0]); +#endif + /* TODO motion vectors */ +} diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl new file mode 100644 index 00000000000..d035a4329b1 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -0,0 +1,240 @@ +#define MAX_STEP 256 + +float sample_depth(vec2 uv, int index, float lod) +{ +#ifdef PLANAR_PROBE_RAYTRACE + if (index > -1) { + return textureLod(planarDepth, vec3(uv, index), 0.0).r; + } + else { +#endif + /* Correct UVs for mipmaping mis-alignment */ + /* + 1.0 because we are using half res maxzBuffer + * and mipRatio starts at on mip 0. */ + int mip = int(lod + 1.0); + uv *= mipRatio[mip]; + return textureLod(maxzBuffer, uv, lod).r; +#ifdef PLANAR_PROBE_RAYTRACE + } +#endif +} + +vec4 sample_depth_grouped(vec4 uv1, vec4 uv2, int index, float lod) +{ + vec4 depths; +#ifdef PLANAR_PROBE_RAYTRACE + if (index > -1) { + depths.x = textureLod(planarDepth, vec3(uv1.xy, index), 0.0).r; + depths.y = textureLod(planarDepth, vec3(uv1.zw, index), 0.0).r; + depths.z = textureLod(planarDepth, vec3(uv2.xy, index), 0.0).r; + depths.w = textureLod(planarDepth, vec3(uv2.zw, index), 0.0).r; + } + else { +#endif + depths.x = textureLod(maxzBuffer, uv1.xy, lod).r; + depths.y = textureLod(maxzBuffer, uv1.zw, lod).r; + depths.z = textureLod(maxzBuffer, uv2.xy, lod).r; + depths.w = textureLod(maxzBuffer, uv2.zw, lod).r; +#ifdef PLANAR_PROBE_RAYTRACE + } +#endif + return depths; +} + +float refine_isect(float prev_delta, float curr_delta) +{ + /** + * Simplification of 2D intersection : + * r0 = (0.0, prev_ss_ray.z); + * r1 = (1.0, curr_ss_ray.z); + * d0 = (0.0, prev_hit_depth_sample); + * d1 = (1.0, curr_hit_depth_sample); + * vec2 r = r1 - r0; + * vec2 d = d1 - d0; + * vec2 isect = ((d * cross(r1, r0)) - (r * cross(d1, d0))) / cross(r,d); + * + * We only want isect.x to know how much stride we need. So it simplifies : + * + * isect_x = (cross(r1, r0) - cross(d1, d0)) / cross(r,d); + * isect_x = (prev_ss_ray.z - prev_hit_depth_sample.z) / cross(r,d); + */ + return saturate(prev_delta / (prev_delta - curr_delta)); +} + +void prepare_raycast( + vec3 ray_origin, vec3 ray_dir, float thickness, out vec4 ss_step, out vec4 ss_ray, out float max_time) +{ + /* Negate the ray direction if it goes towards the camera. + * This way we don't need to care if the projected point + * is behind the near plane. */ + float z_sign = -sign(ray_dir.z); + vec3 ray_end = ray_origin + z_sign * ray_dir; + + /* Project into screen space. */ + vec4 ss_start, ss_end; + ss_start.xyz = project_point(ProjectionMatrix, ray_origin); + ss_end.xyz = project_point(ProjectionMatrix, ray_end); + + /* We interpolate the ray Z + thickness values to check if depth is within threshold. */ + ray_origin.z -= thickness; + ray_end.z -= thickness; + ss_start.w = project_point(ProjectionMatrix, ray_origin).z; + ss_end.w = project_point(ProjectionMatrix, ray_end).z; + + /* XXX This is a hack a better method is welcome ! */ + /* We take the delta between the offseted depth and the depth and substract it from the ray depth. + * This will change the world space thickness appearance a bit but we can have negative + * values without worries. We cannot do this in viewspace because of the perspective division. */ + ss_start.w = 2.0 * ss_start.z - ss_start.w; + ss_end.w = 2.0 * ss_end.z - ss_end.w; + + ss_step = ss_end - ss_start; + max_time = length(ss_step.xyz); + ss_step = z_sign * ss_step / length(ss_step.xyz); + + /* If the line is degenerate, make it cover at least one pixel + * to not have to handle zero-pixel extent as a special case later */ + ss_step.xy += vec2((dot(ss_step.xy, ss_step.xy) < 0.000001) ? 0.001 : 0.0); + + /* Make ss_step cover one pixel. */ + ss_step /= max(abs(ss_step.x), abs(ss_step.y)); + ss_step *= (abs(ss_step.x) > abs(ss_step.y)) ? ssrPixelSize.x : ssrPixelSize.y; + + /* Clip to segment's end. */ + max_time /= length(ss_step.xyz); + + /* Clipping to frustum sides. */ + max_time = min(max_time, line_unit_box_intersect_dist(ss_start.xyz, ss_step.xyz)); + + /* Convert to texture coords. Z component included + * since this is how it's stored in the depth buffer. + * 4th component how far we are on the ray */ + ss_ray = ss_start * 0.5 + 0.5; + ss_step *= 0.5; + + ss_ray.xy += 0.5 * ssrPixelSize * 2.0; /* take the center of the texel. * 2 because halfres. */ +} + +/* See times_and_deltas. */ +#define curr_time times_and_deltas.x +#define prev_time times_and_deltas.y +#define curr_delta times_and_deltas.z +#define prev_delta times_and_deltas.w + +// #define GROUPED_FETCHES /* is still slower, need to see where is the bottleneck. */ +/* Return the hit position, and negate the z component (making it positive) if not hit occured. */ +/* __ray_dir__ is the ray direction premultiplied by it's maximum length */ +vec3 raycast( + int index, vec3 ray_origin, vec3 ray_dir, float thickness, float ray_jitter, + float trace_quality, float roughness, const bool discard_backface) +{ + vec4 ss_step, ss_start; + float max_time; + prepare_raycast(ray_origin, ray_dir, thickness, ss_step, ss_start, max_time); + + float max_trace_time = max(0.001, max_time - 0.01); + +#ifdef GROUPED_FETCHES + ray_jitter *= 0.25; +#endif + + /* x : current_time, y: previous_time, z: current_delta, w: previous_delta */ + vec4 times_and_deltas = vec4(0.0); + + float ray_time = 0.0; + float depth_sample = sample_depth(ss_start.xy, index, 0.0); + curr_delta = depth_sample - ss_start.z; + + float lod_fac = saturate(fast_sqrt(roughness) * 2.0 - 0.4); + bool hit = false; + float iter; + for (iter = 1.0; !hit && (ray_time < max_time) && (iter < MAX_STEP); iter++) { + /* Minimum stride of 2 because we are using half res minmax zbuffer. */ + float stride = max(1.0, iter * trace_quality) * 2.0; + float lod = log2(stride * 0.5 * trace_quality) * lod_fac; + ray_time += stride; + + /* Save previous values. */ + times_and_deltas.xyzw = times_and_deltas.yxwz; + +#ifdef GROUPED_FETCHES + stride *= 4.0; + vec4 jit_stride = mix(vec4(2.0), vec4(stride), vec4(0.0, 0.25, 0.5, 0.75) + ray_jitter); + + vec4 times = min(vec4(ray_time) + jit_stride, vec4(max_trace_time)); + + vec4 uv1 = ss_start.xyxy + ss_step.xyxy * times.xxyy; + vec4 uv2 = ss_start.xyxy + ss_step.xyxy * times.zzww; + + vec4 depth_samples = sample_depth_grouped(uv1, uv2, index, lod); + + vec4 ray_z = ss_start.zzzz + ss_step.zzzz * times.xyzw; + vec4 ray_w = ss_start.wwww + ss_step.wwww * vec4(prev_time, times.xyz); + + vec4 deltas = depth_samples - ray_z; + /* Same as component wise (curr_delta <= 0.0) && (prev_w <= depth_sample). */ + bvec4 test = equal(step(deltas, vec4(0.0)) * step(ray_w, depth_samples), vec4(1.0)); + hit = any(test); + + if (hit) { + vec2 m = vec2(1.0, 0.0); /* Mask */ + + vec4 ret_times_and_deltas = times.wzzz * m.xxyy + deltas.wwwz * m.yyxx; + ret_times_and_deltas = (test.z) ? times.zyyy * m.xxyy + deltas.zzzy * m.yyxx : ret_times_and_deltas; + ret_times_and_deltas = (test.y) ? times.yxxx * m.xxyy + deltas.yyyx * m.yyxx : ret_times_and_deltas; + times_and_deltas = (test.x) ? times.xxxx * m.xyyy + deltas.xxxx * m.yyxy + times_and_deltas.yyww * m.yxyx : ret_times_and_deltas; + + depth_sample = depth_samples.w; + depth_sample = (test.z) ? depth_samples.z : depth_sample; + depth_sample = (test.y) ? depth_samples.y : depth_sample; + depth_sample = (test.x) ? depth_samples.x : depth_sample; + } + else { + curr_time = times.w; + curr_delta = deltas.w; + } +#else + float jit_stride = mix(2.0, stride, ray_jitter); + + curr_time = min(ray_time + jit_stride, max_trace_time); + vec4 ss_ray = ss_start + ss_step * curr_time; + + depth_sample = sample_depth(ss_ray.xy, index, lod); + + float prev_w = ss_start.w + ss_step.w * prev_time; + curr_delta = depth_sample - ss_ray.z; + hit = (curr_delta <= 0.0) && (prev_w <= depth_sample); +#endif + } + + if (discard_backface) { + /* Discard backface hits */ + hit = hit && (prev_delta > 0.0); + } + + /* Reject hit if background. */ + hit = hit && (depth_sample != 1.0); + + curr_time = (hit) ? mix(prev_time, curr_time, refine_isect(prev_delta, curr_delta)) : curr_time; + ray_time = (hit) ? curr_time : ray_time; + + /* Clip to frustum. */ + ray_time = max(0.001, min(ray_time, max_time - 1.5)); + + vec4 ss_ray = ss_start + ss_step * ray_time; + + /* Tag Z if ray failed. */ + ss_ray.z *= (hit) ? 1.0 : -1.0; + return ss_ray.xyz; +} + +float screen_border_mask(vec2 hit_co) +{ + const float margin = 0.003; + float atten = ssrBorderFac + margin; /* Screen percentage */ + hit_co = smoothstep(margin, atten, hit_co) * (1 - smoothstep(1.0 - atten, 1.0 - margin, hit_co)); + + float screenfade = hit_co.x * hit_co.y; + + return screenfade; +} diff --git a/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl new file mode 100644 index 00000000000..4ae22b480f1 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl @@ -0,0 +1,208 @@ +/* Copy the depth only shadowmap into another texture while converting + * to linear depth (or other storage method) and doing a 3x3 box filter. */ + +layout(std140) uniform shadow_render_block { + vec4 lampPosition; + float cubeTexelSize; + float storedTexelSize; + float nearClip; + float farClip; + int shadowSampleCount; + float shadowInvSampleCount; +}; + +#ifdef CSM +uniform sampler2DArray shadowTexture; +uniform int cascadeId; +#else +uniform samplerCube shadowTexture; +uniform int faceId; +#endif +uniform float shadowFilterSize; + +out vec4 FragColor; + +float linear_depth(float z) +{ + return (nearClip * farClip) / (z * (nearClip - farClip) + farClip); +} + +vec4 linear_depth(vec4 z) +{ + return (nearClip * farClip) / (z * (nearClip - farClip) + farClip); +} + +#ifdef CSM +vec4 get_world_distance(vec4 depths, vec3 cos[4]) +{ + /* Background case */ + vec4 is_background = step(vec4(0.99999), depths); + depths *= abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */ + depths += 1e1 * is_background; + return depths; +} + +float get_world_distance(float depth, vec3 cos) +{ + /* Background case */ + float is_background = step(0.9999, depth); + depth *= abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */ + depth += 1e1 * is_background; + return depth; +} +#else /* CUBEMAP */ +vec4 get_world_distance(vec4 depths, vec3 cos[4]) +{ + vec4 is_background = step(vec4(1.0), depths); + depths = linear_depth(depths); + depths += vec4(1e1) * is_background; + cos[0] = normalize(abs(cos[0])); + cos[1] = normalize(abs(cos[1])); + cos[2] = normalize(abs(cos[2])); + cos[3] = normalize(abs(cos[3])); + vec4 cos_vec; + cos_vec.x = max(cos[0].x, max(cos[0].y, cos[0].z)); + cos_vec.y = max(cos[1].x, max(cos[1].y, cos[1].z)); + cos_vec.z = max(cos[2].x, max(cos[2].y, cos[2].z)); + cos_vec.w = max(cos[3].x, max(cos[3].y, cos[3].z)); + return depths / cos_vec; +} + +float get_world_distance(float depth, vec3 cos) +{ + float is_background = step(1.0, depth); + depth = linear_depth(depth); + depth += 1e1 * is_background; + cos = normalize(abs(cos)); + float cos_vec = max(cos.x, max(cos.y, cos.z)); + return depth / cos_vec; +} +#endif + +/* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */ +float ln_space_prefilter(float w0, float x, float w1, float y) +{ + return x + log(w0 + w1 * exp(y - x)); +} + +#define SAMPLE_WEIGHT 0.11111 + +#ifdef ESM +void prefilter(vec4 depths, inout float accum) +{ + accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.x); + accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.y); + accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.z); + accum = ln_space_prefilter(1.0, accum, SAMPLE_WEIGHT, depths.w); +} +#else /* VSM */ +void prefilter(vec4 depths, inout vec2 accum) +{ + vec4 depths_sqr = depths * depths; + accum += vec2(dot(vec4(1.0), depths), dot(vec4(1.0), depths_sqr)) * SAMPLE_WEIGHT; +} +#endif + +#ifdef CSM +vec3 get_texco(vec2 uvs, vec2 ofs) +{ + return vec3(uvs + ofs, float(cascadeId)); +} +#else /* CUBEMAP */ +const vec3 minorAxisX[6] = vec3[6]( + vec3(0.0f, 0.0f, -1.0f), + vec3(0.0f, 0.0f, 1.0f), + vec3(1.0f, 0.0f, 0.0f), + vec3(1.0f, 0.0f, 0.0f), + vec3(1.0f, 0.0f, 0.0f), + vec3(-1.0f, 0.0f, 0.0f) +); + +const vec3 minorAxisY[6] = vec3[6]( + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, 0.0f, 1.0f), + vec3(0.0f, 0.0f, -1.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f) +); + +const vec3 majorAxis[6] = vec3[6]( + vec3(1.0f, 0.0f, 0.0f), + vec3(-1.0f, 0.0f, 0.0f), + vec3(0.0f, 1.0f, 0.0f), + vec3(0.0f, -1.0f, 0.0f), + vec3(0.0f, 0.0f, 1.0f), + vec3(0.0f, 0.0f, -1.0f) +); + +vec3 get_texco(vec2 uvs, vec2 ofs) +{ + uvs += ofs; + return majorAxis[faceId] + uvs.x * minorAxisX[faceId] + uvs.y * minorAxisY[faceId]; +} +#endif + +void main() { + /* Copy the depth only shadowmap into another texture while converting + * to linear depth and do a 3x3 box blur. */ + +#ifdef CSM + vec2 uvs = gl_FragCoord.xy * storedTexelSize; +#else /* CUBEMAP */ + vec2 uvs = gl_FragCoord.xy * cubeTexelSize * 2.0 - 1.0; +#endif + + /* Center texel */ + vec3 co = get_texco(uvs, vec2(0.0)); + float depth = texture(shadowTexture, co).r; + depth = get_world_distance(depth, co); + + if (shadowFilterSize == 0.0) { +#ifdef ESM + FragColor = vec4(depth); +#else /* VSM */ + FragColor = vec2(depth, depth * depth).xyxy; +#endif + return; + } + +#ifdef ESM + float accum = ln_space_prefilter(0.0, 0.0, SAMPLE_WEIGHT, depth); +#else /* VSM */ + vec2 accum = vec2(depth, depth * depth) * SAMPLE_WEIGHT; +#endif + +#ifdef CSM + vec3 ofs = vec3(1.0, 0.0, -1.0) * shadowFilterSize; +#else /* CUBEMAP */ + vec3 ofs = vec3(1.0, 0.0, -1.0) * shadowFilterSize; +#endif + + vec3 cos[4]; + cos[0] = get_texco(uvs, ofs.zz); + cos[1] = get_texco(uvs, ofs.yz); + cos[2] = get_texco(uvs, ofs.xz); + cos[3] = get_texco(uvs, ofs.zy); + + vec4 depths; + depths.x = texture(shadowTexture, cos[0]).r; + depths.y = texture(shadowTexture, cos[1]).r; + depths.z = texture(shadowTexture, cos[2]).r; + depths.w = texture(shadowTexture, cos[3]).r; + depths = get_world_distance(depths, cos); + prefilter(depths, accum); + + cos[0] = get_texco(uvs, ofs.xy); + cos[1] = get_texco(uvs, ofs.zx); + cos[2] = get_texco(uvs, ofs.yx); + cos[3] = get_texco(uvs, ofs.xx); + depths.x = texture(shadowTexture, cos[0]).r; + depths.y = texture(shadowTexture, cos[1]).r; + depths.z = texture(shadowTexture, cos[2]).r; + depths.w = texture(shadowTexture, cos[3]).r; + depths = get_world_distance(depths, cos); + prefilter(depths, accum); + + FragColor = vec2(accum).xyxy; +} diff --git a/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl new file mode 100644 index 00000000000..160fcee4c73 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl @@ -0,0 +1,4 @@ + +void main() { + /* Do nothing */ +} diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl new file mode 100644 index 00000000000..b40155be454 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl @@ -0,0 +1,243 @@ + +layout(std140) uniform shadow_render_block { + vec4 lampPosition; + float cubeTexelSize; + float storedTexelSize; + float nearClip; + float farClip; + int shadowSampleCount; + float shadowInvSampleCount; +}; + +#ifdef CSM +uniform sampler2DArray shadowTexture; +uniform int cascadeId; +#else +uniform samplerCube shadowTexture; +#endif +uniform float shadowFilterSize; + +out vec4 FragColor; + +vec3 octahedral_to_cubemap_proj(vec2 co) +{ + co = co * 2.0 - 1.0; + + vec2 abs_co = abs(co); + vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y)); + + if ( abs_co.x + abs_co.y > 1.0 ) { + v.xy = (abs(co.yx) - 1.0) * -sign(co.xy); + } + + return v; +} + +/* Marco Salvi's GDC 2008 presentation about shadow maps pre-filtering techniques slide 24 */ +float ln_space_prefilter(float w0, float x, float w1, float y) +{ + return x + log(w0 + w1 * exp(y - x)); +} + +vec4 ln_space_prefilter(float w0, vec4 x, float w1, vec4 y) +{ + return x + log(w0 + w1 * exp(y - x)); +} + +#ifdef CSM +vec3 get_texco(vec3 cos, const vec2 ofs) +{ + cos.xy += ofs * shadowFilterSize; + return cos; +} +#else /* CUBEMAP */ +/* global vars */ +vec3 T = vec3(0.0); +vec3 B = vec3(0.0); + +void make_orthonormal_basis(vec3 N) +{ + vec3 UpVector = (abs(N.z) < 0.999) ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + T = normalize(cross(UpVector, N)); + B = cross(N, T); +} + +vec3 get_texco(vec3 cos, const vec2 ofs) +{ + return cos + ofs.x * T + ofs.y * B; +} + +#endif + +#ifdef ESM +void grouped_samples_accum( + vec3 cos, + const vec2 co1, const vec2 co2, const vec2 co3, const vec2 co4, + inout vec4 accum) +{ + vec4 depths; + depths.x = texture(shadowTexture, get_texco(cos, co1)).r; + depths.y = texture(shadowTexture, get_texco(cos, co2)).r; + depths.z = texture(shadowTexture, get_texco(cos, co3)).r; + depths.w = texture(shadowTexture, get_texco(cos, co4)).r; + + accum = ln_space_prefilter(1.0, accum, shadowInvSampleCount, depths); +} +#else /* VSM */ +void grouped_samples_accum( + vec3 cos, + const vec2 co1, const vec2 co2, const vec2 co3, const vec2 co4, + inout vec2 accum) +{ + vec4 depths1, depths2; + depths1.xy = texture(shadowTexture, get_texco(cos, co1)).rg; + depths1.zw = texture(shadowTexture, get_texco(cos, co2)).rg; + depths2.xy = texture(shadowTexture, get_texco(cos, co3)).rg; + depths2.zw = texture(shadowTexture, get_texco(cos, co4)).rg; + + accum += depths1.xy + depths1.zw + depths2.xy + depths2.zw; +} +#endif + +void main() { + vec3 cos; + + cos.xy = gl_FragCoord.xy * storedTexelSize; + +#ifdef CSM + cos.z = float(cascadeId); +#else /* CUBEMAP */ + /* add a 2 pixel border to ensure filtering is correct */ + cos.xy *= 1.0 + storedTexelSize * 2.0; + cos.xy -= storedTexelSize; + + float pattern = 1.0; + + /* edge mirroring : only mirror if directly adjacent + * (not diagonally adjacent) */ + vec2 m = abs(cos.xy - 0.5) + 0.5; + vec2 f = floor(m); + if (f.x - f.y != 0.0) { + cos.xy = 1.0 - cos.xy; + } + + /* clamp to [0-1] */ + cos.xy = fract(cos.xy); + + /* get cubemap vector */ + cos = normalize(octahedral_to_cubemap_proj(cos.xy)); + make_orthonormal_basis(cos); + + T *= shadowFilterSize; + B *= shadowFilterSize; +#endif + +#ifdef ESM + /* disc blur in log space. */ + vec4 accum = vec4(0.0); + vec4 depths; + depths.x = texture(shadowTexture, get_texco(cos, concentric[0])).r; + depths.y = texture(shadowTexture, get_texco(cos, concentric[1])).r; + depths.z = texture(shadowTexture, get_texco(cos, concentric[2])).r; + depths.w = texture(shadowTexture, get_texco(cos, concentric[3])).r; + accum = ln_space_prefilter(0.0, accum, shadowInvSampleCount, depths); + +#else /* VSM */ + vec2 accum = vec2(0.0); + grouped_samples_accum(cos, concentric[0], concentric[1], concentric[2], concentric[3], accum); +#endif + + /** + * Making the `grouped_samples_accum` be called within a loop would be + * the most conventional solution, however in some older gpus, transverse the huge + * `const vec2 concentric[]` array with variable indices is extremely slow. + * The solution is to use constant indices to access the array. + */ + if (shadowSampleCount > 4) { + grouped_samples_accum(cos, concentric[4], concentric[5], concentric[6], concentric[7], accum); + grouped_samples_accum(cos, concentric[8], concentric[9], concentric[10], concentric[11], accum); + grouped_samples_accum(cos, concentric[12], concentric[13], concentric[14], concentric[15], accum); + } + if (shadowSampleCount > 16) { + grouped_samples_accum(cos, concentric[16], concentric[17], concentric[18], concentric[19], accum); + grouped_samples_accum(cos, concentric[20], concentric[21], concentric[22], concentric[23], accum); + grouped_samples_accum(cos, concentric[24], concentric[25], concentric[26], concentric[27], accum); + grouped_samples_accum(cos, concentric[28], concentric[29], concentric[30], concentric[31], accum); + grouped_samples_accum(cos, concentric[32], concentric[33], concentric[34], concentric[35], accum); + } + if (shadowSampleCount > 36) { + grouped_samples_accum(cos, concentric[36], concentric[37], concentric[38], concentric[39], accum); + grouped_samples_accum(cos, concentric[40], concentric[41], concentric[42], concentric[43], accum); + grouped_samples_accum(cos, concentric[44], concentric[45], concentric[46], concentric[47], accum); + grouped_samples_accum(cos, concentric[48], concentric[49], concentric[50], concentric[51], accum); + grouped_samples_accum(cos, concentric[52], concentric[53], concentric[54], concentric[55], accum); + grouped_samples_accum(cos, concentric[56], concentric[57], concentric[58], concentric[59], accum); + grouped_samples_accum(cos, concentric[60], concentric[61], concentric[62], concentric[63], accum); + } + if (shadowSampleCount > 64) { + grouped_samples_accum(cos, concentric[64], concentric[65], concentric[66], concentric[67], accum); + grouped_samples_accum(cos, concentric[68], concentric[69], concentric[70], concentric[71], accum); + grouped_samples_accum(cos, concentric[72], concentric[73], concentric[74], concentric[75], accum); + grouped_samples_accum(cos, concentric[76], concentric[77], concentric[78], concentric[79], accum); + grouped_samples_accum(cos, concentric[80], concentric[81], concentric[82], concentric[83], accum); + grouped_samples_accum(cos, concentric[84], concentric[85], concentric[86], concentric[87], accum); + grouped_samples_accum(cos, concentric[88], concentric[89], concentric[90], concentric[91], accum); + grouped_samples_accum(cos, concentric[92], concentric[93], concentric[94], concentric[95], accum); + grouped_samples_accum(cos, concentric[96], concentric[97], concentric[98], concentric[99], accum); + } + if (shadowSampleCount > 100) { + grouped_samples_accum(cos, concentric[100], concentric[101], concentric[102], concentric[103], accum); + grouped_samples_accum(cos, concentric[104], concentric[105], concentric[106], concentric[107], accum); + grouped_samples_accum(cos, concentric[108], concentric[109], concentric[110], concentric[111], accum); + grouped_samples_accum(cos, concentric[112], concentric[113], concentric[114], concentric[115], accum); + grouped_samples_accum(cos, concentric[116], concentric[117], concentric[118], concentric[119], accum); + grouped_samples_accum(cos, concentric[120], concentric[121], concentric[122], concentric[123], accum); + grouped_samples_accum(cos, concentric[124], concentric[125], concentric[126], concentric[127], accum); + grouped_samples_accum(cos, concentric[128], concentric[129], concentric[130], concentric[131], accum); + grouped_samples_accum(cos, concentric[132], concentric[133], concentric[134], concentric[135], accum); + grouped_samples_accum(cos, concentric[136], concentric[137], concentric[138], concentric[139], accum); + grouped_samples_accum(cos, concentric[140], concentric[141], concentric[142], concentric[143], accum); + } + if (shadowSampleCount > 144) { + grouped_samples_accum(cos, concentric[144], concentric[145], concentric[146], concentric[147], accum); + grouped_samples_accum(cos, concentric[148], concentric[149], concentric[150], concentric[151], accum); + grouped_samples_accum(cos, concentric[152], concentric[153], concentric[154], concentric[155], accum); + grouped_samples_accum(cos, concentric[156], concentric[157], concentric[158], concentric[159], accum); + grouped_samples_accum(cos, concentric[160], concentric[161], concentric[162], concentric[163], accum); + grouped_samples_accum(cos, concentric[164], concentric[165], concentric[166], concentric[167], accum); + grouped_samples_accum(cos, concentric[168], concentric[169], concentric[170], concentric[171], accum); + grouped_samples_accum(cos, concentric[172], concentric[173], concentric[174], concentric[175], accum); + grouped_samples_accum(cos, concentric[176], concentric[177], concentric[178], concentric[179], accum); + grouped_samples_accum(cos, concentric[180], concentric[181], concentric[182], concentric[183], accum); + grouped_samples_accum(cos, concentric[184], concentric[185], concentric[186], concentric[187], accum); + grouped_samples_accum(cos, concentric[188], concentric[189], concentric[190], concentric[191], accum); + grouped_samples_accum(cos, concentric[192], concentric[193], concentric[194], concentric[195], accum); + } + if (shadowSampleCount > 196) { + grouped_samples_accum(cos, concentric[196], concentric[197], concentric[198], concentric[199], accum); + grouped_samples_accum(cos, concentric[200], concentric[201], concentric[202], concentric[203], accum); + grouped_samples_accum(cos, concentric[204], concentric[205], concentric[206], concentric[207], accum); + grouped_samples_accum(cos, concentric[208], concentric[209], concentric[210], concentric[211], accum); + grouped_samples_accum(cos, concentric[212], concentric[213], concentric[114], concentric[215], accum); + grouped_samples_accum(cos, concentric[216], concentric[217], concentric[218], concentric[219], accum); + grouped_samples_accum(cos, concentric[220], concentric[221], concentric[222], concentric[223], accum); + grouped_samples_accum(cos, concentric[224], concentric[225], concentric[226], concentric[227], accum); + grouped_samples_accum(cos, concentric[228], concentric[229], concentric[230], concentric[231], accum); + grouped_samples_accum(cos, concentric[232], concentric[233], concentric[234], concentric[235], accum); + grouped_samples_accum(cos, concentric[236], concentric[237], concentric[238], concentric[239], accum); + grouped_samples_accum(cos, concentric[240], concentric[241], concentric[242], concentric[243], accum); + grouped_samples_accum(cos, concentric[244], concentric[245], concentric[246], concentric[247], accum); + grouped_samples_accum(cos, concentric[248], concentric[249], concentric[250], concentric[251], accum); + grouped_samples_accum(cos, concentric[252], concentric[253], concentric[254], concentric[255], accum); + } + +#ifdef ESM + accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.y); + accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.z); + accum.x = ln_space_prefilter(1.0, accum.x, 1.0, accum.w); + FragColor = accum.xxxx; + +#else /* VSM */ + FragColor = accum.xyxy * shadowInvSampleCount; +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl new file mode 100644 index 00000000000..6b6479089f6 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl @@ -0,0 +1,33 @@ + +uniform mat4 ModelViewProjectionMatrix; +#ifdef MESH_SHADER +uniform mat4 ModelMatrix; +uniform mat4 ModelViewMatrix; +uniform mat3 WorldNormalMatrix; +# ifndef ATTRIB +uniform mat3 NormalMatrix; +# endif +#endif + +in vec3 pos; +in vec3 nor; + +#ifdef MESH_SHADER +out vec3 worldPosition; +out vec3 viewPosition; +out vec3 worldNormal; +out vec3 viewNormal; +#endif + +void main() { + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); +#ifdef MESH_SHADER + viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz; + worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz; + viewNormal = normalize(NormalMatrix * nor); + worldNormal = normalize(WorldNormalMatrix * nor); +#ifdef ATTRIB + pass_attrib(pos); +#endif +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl new file mode 100644 index 00000000000..6c7bfeb6b82 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl @@ -0,0 +1,72 @@ +/* ------------ Refraction ------------ */ + +#define BTDF_BIAS 0.85 + +vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float roughnessSquared, vec4 rand) +{ + float a2 = max(5e-6, roughnessSquared * roughnessSquared); + + /* Importance sampling bias */ + rand.x = mix(rand.x, 0.0, BTDF_BIAS); + + vec3 T, B; + float NH; + make_orthonormal_basis(N, T, B); + vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */ + float pdf = pdf_ggx_reflect(NH, a2); + + /* If ray is bad (i.e. going below the plane) regenerate. */ + if (F_eta(ior, dot(H, V)) < 1.0) { + H = sample_ggx(rand.xzw * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */ + pdf = pdf_ggx_reflect(NH, a2); + } + + vec3 vV = viewCameraVec; + float eta = 1.0/ior; + if (dot(H, V) < 0.0) { + H = -H; + eta = ior; + } + + vec3 R = refract(-V, H, 1.0 / ior); + + R = transform_direction(ViewMatrix, R); + + vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, rand.y, ssrQuality, roughnessSquared, false); + + if ((hit_pos.z > 0.0) && (F_eta(ior, dot(H, V)) < 1.0)) { + hit_pos = get_view_space_from_depth(hit_pos.xy, hit_pos.z); + float hit_dist = distance(hit_pos, viewPosition); + + float cone_cos = cone_cosine(roughnessSquared); + float cone_tan = sqrt(1 - cone_cos * cone_cos) / cone_cos; + + /* Empirical fit for refraction. */ + /* TODO find a better fit or precompute inside the LUT. */ + cone_tan *= 0.5 * fast_sqrt(f0_from_ior((ior < 1.0) ? 1.0 / ior : ior)); + + float cone_footprint = hit_dist * cone_tan; + + /* find the offset in screen space by multiplying a point + * in camera space at the depth of the point by the projection matrix. */ + float homcoord = ProjectionMatrix[2][3] * hit_pos.z + ProjectionMatrix[3][3]; + /* UV space footprint */ + cone_footprint = BTDF_BIAS * 0.5 * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * cone_footprint / homcoord; + + vec2 hit_uvs = project_point(ProjectionMatrix, hit_pos).xy * 0.5 + 0.5; + + /* Texel footprint */ + vec2 texture_size = vec2(textureSize(colorBuffer, 0).xy); + float mip = clamp(log2(cone_footprint * max(texture_size.x, texture_size.y)), 0.0, 9.0); + + /* Correct UVs for mipmaping mis-alignment */ + hit_uvs *= mip_ratio_interp(mip); + + vec3 spec = textureLod(colorBuffer, hit_uvs, mip).xyz; + float mask = screen_border_mask(hit_uvs); + + return vec4(spec, mask); + } + + return vec4(0.0); +} diff --git a/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl b/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl new file mode 100644 index 00000000000..2907f25782f --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl @@ -0,0 +1,18 @@ + +uniform sampler2D blueNoise; +uniform vec3 offsets; + +out vec4 FragColor; + +#define M_2PI 6.28318530717958647692 + +void main(void) +{ + vec3 blue_noise = texelFetch(blueNoise, ivec2(gl_FragCoord.xy), 0).xyz; + + float noise = fract(blue_noise.y + offsets.z); + FragColor.x = fract(blue_noise.x + offsets.x); + FragColor.y = fract(blue_noise.z + offsets.y); + FragColor.z = cos(noise * M_2PI); + FragColor.w = sin(noise * M_2PI); +} diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl new file mode 100644 index 00000000000..3a293647f84 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl @@ -0,0 +1,63 @@ + +/* Based on Frosbite Unified Volumetric. + * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ + +#define NODETREE_EXEC + +#ifdef MESH_SHADER +uniform mat4 volumeObjectMatrix; +uniform vec3 volumeOrcoLoc; +uniform vec3 volumeOrcoSize; +#endif + +flat in int slice; + +/* Warning: theses are not attributes, theses are global vars. */ +vec3 worldPosition = vec3(0.0); +vec3 viewPosition = vec3(0.0); +vec3 viewNormal = vec3(0.0); +#ifdef MESH_SHADER +vec3 volumeObjectLocalCoord = vec3(0.0); +#endif + +layout(location = 0) out vec4 volumeScattering; +layout(location = 1) out vec4 volumeExtinction; +layout(location = 2) out vec4 volumeEmissive; +layout(location = 3) out vec4 volumePhase; + +/* Store volumetric properties into the froxel textures. */ + +void main() +{ + ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice); + vec3 ndc_cell = volume_to_ndc((vec3(volume_cell) + volJitter.xyz) * volInvTexSize.xyz); + + viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z); + worldPosition = transform_point(ViewMatrixInverse, viewPosition); +#ifdef MESH_SHADER + volumeObjectLocalCoord = transform_point(volumeObjectMatrix, worldPosition); + volumeObjectLocalCoord = (volumeObjectLocalCoord - volumeOrcoLoc + volumeOrcoSize) / (volumeOrcoSize * 2.0); + + if (any(lessThan(volumeObjectLocalCoord, vec3(0.0))) || + any(greaterThan(volumeObjectLocalCoord, vec3(1.0)))) + discard; +#endif + +#ifdef CLEAR + Closure cl = CLOSURE_DEFAULT; +#else + Closure cl = nodetree_exec(); +#endif + + volumeScattering = vec4(cl.scatter, 1.0); + volumeExtinction = vec4(max(vec3(1e-4), cl.absorption + cl.scatter), 1.0); + volumeEmissive = vec4(cl.emission, 1.0); + + /* Do not add phase weight if no scattering. */ + if (all(equal(cl.scatter, vec3(0.0)))) { + volumePhase = vec4(0.0); + } + else { + volumePhase = vec4(cl.anisotropy, vec3(1.0)); + } +} diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl new file mode 100644 index 00000000000..208e8165689 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl @@ -0,0 +1,52 @@ + +#ifdef MESH_SHADER +/* TODO tight slices */ +layout(triangles) in; +layout(triangle_strip, max_vertices=3) out; +#else /* World */ +layout(triangles) in; +layout(triangle_strip, max_vertices=3) out; +#endif + +in vec4 vPos[]; + +flat out int slice; + +#ifdef MESH_SHADER +/* TODO tight slices */ +void main() { + gl_Layer = slice = int(vPos[0].z); + + gl_Position = vPos[0].xyww; + EmitVertex(); + + gl_Position = vPos[1].xyww; + EmitVertex(); + + gl_Position = vPos[2].xyww; + EmitVertex(); + + EndPrimitive(); +} + +#else /* World */ + +/* This is just a pass-through geometry shader that send the geometry + * to the layer corresponding to it's depth. */ + +void main() { + gl_Layer = slice = int(vPos[0].z); + + gl_Position = vPos[0].xyww; + EmitVertex(); + + gl_Position = vPos[1].xyww; + EmitVertex(); + + gl_Position = vPos[2].xyww; + EmitVertex(); + + EndPrimitive(); +} + +#endif diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl new file mode 100644 index 00000000000..c5c97b97734 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl @@ -0,0 +1,63 @@ + +/* Based on Frosbite Unified Volumetric. + * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ + +/* Step 3 : Integrate for each froxel the final amount of light + * scattered back to the viewer and the amout of transmittance. */ + +uniform sampler3D volumeScattering; /* Result of the scatter step */ +uniform sampler3D volumeExtinction; + +flat in int slice; + +layout(location = 0) out vec4 finalScattering; +layout(location = 1) out vec4 finalTransmittance; + +void main() +{ + /* Start with full transmittance and no scattered light. */ + finalScattering = vec4(0.0); + finalTransmittance = vec4(1.0); + + vec3 tex_size = vec3(textureSize(volumeScattering, 0).xyz); + + /* Compute view ray. */ + vec2 uvs = gl_FragCoord.xy / tex_size.xy; + vec3 ndc_cell = volume_to_ndc(vec3(uvs, 1e-5)); + vec3 view_cell = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z); + + /* Ortho */ + float prev_ray_len = view_cell.z; + float orig_ray_len = 1.0; + + /* Persp */ + if (ProjectionMatrix[3][3] == 0.0) { + prev_ray_len = length(view_cell); + orig_ray_len = prev_ray_len / view_cell.z; + } + + /* Without compute shader and arbitrary write we need to + * accumulate from the beginning of the ray for each cell. */ + float integration_end = float(slice); + for (int i = 0; i < slice; ++i) { + ivec3 volume_cell = ivec3(gl_FragCoord.xy, i); + + vec4 Lscat = texelFetch(volumeScattering, volume_cell, 0); + vec4 s_extinction = texelFetch(volumeExtinction, volume_cell, 0); + + float cell_depth = volume_z_to_view_z((float(i) + 1.0) / tex_size.z); + float ray_len = orig_ray_len * cell_depth; + + /* Evaluate Scattering */ + float s_len = abs(ray_len - prev_ray_len); + prev_ray_len = ray_len; + vec4 Tr = exp(-s_extinction * s_len); + + /* integrate along the current step segment */ + Lscat = (Lscat - Lscat * Tr) / s_extinction; + /* accumulate and also take into account the transmittance from previous steps */ + finalScattering += finalTransmittance * Lscat; + + finalTransmittance *= Tr; + } +} diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl new file mode 100644 index 00000000000..5f641c5d490 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl @@ -0,0 +1,153 @@ + +/* Based on Frosbite Unified Volumetric. + * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ + +/* Volume slice to view space depth. */ +float volume_z_to_view_z(float z) +{ + if (ProjectionMatrix[3][3] == 0.0) { + /* Exponential distribution */ + return (exp2(z / volDepthParameters.z) - volDepthParameters.x) / volDepthParameters.y; + } + else { + /* Linear distribution */ + return mix(volDepthParameters.x, volDepthParameters.y, z); + } +} + +float view_z_to_volume_z(float depth) +{ + if (ProjectionMatrix[3][3] == 0.0) { + /* Exponential distribution */ + return volDepthParameters.z * log2(depth * volDepthParameters.y + volDepthParameters.x); + } + else { + /* Linear distribution */ + return (depth - volDepthParameters.x) * volDepthParameters.z; + } +} + +/* Volume texture normalized coordinates to NDC (special range [0, 1]). */ +vec3 volume_to_ndc(vec3 cos) +{ + cos.z = volume_z_to_view_z(cos.z); + cos.z = get_depth_from_view_z(cos.z); + cos.xy /= volCoordScale.xy; + return cos; +} + +vec3 ndc_to_volume(vec3 cos) +{ + cos.z = get_view_z_from_depth(cos.z); + cos.z = view_z_to_volume_z(cos.z); + cos.xy *= volCoordScale.xy; + return cos; +} + +float phase_function_isotropic() +{ + return 1.0 / (4.0 * M_PI); +} + +float phase_function(vec3 v, vec3 l, float g) +{ + /* Henyey-Greenstein */ + float cos_theta = dot(v, l); + g = clamp(g, -1.0 + 1e-3, 1.0 - 1e-3); + float sqr_g = g * g; + return (1- sqr_g) / max(1e-8, 4.0 * M_PI * pow(1 + sqr_g - 2 * g * cos_theta, 3.0 / 2.0)); +} + +#ifdef LAMPS_LIB +vec3 light_volume(LightData ld, vec4 l_vector) +{ + float power; + /* TODO : Area lighting ? */ + /* XXX : Removing Area Power. */ + /* TODO : put this out of the shader. */ + /* See eevee_light_setup(). */ + if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { + power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); + if (ld.l_type == AREA_ELLIPSE) { + power *= M_PI * 0.25; + } + power *= 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ + } + else if (ld.l_type == SUN) { + power = (4.0f * ld.l_radius * ld.l_radius * M_2PI) * (1.0 / 12.5); /* Removing area light power*/ + power *= M_2PI * 0.78; /* Matching cycles with point light. */ + } + else { + power = (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0); + } + + /* OPTI: find a better way than calculating this on the fly */ + float lum = dot(ld.l_color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */ + vec3 tint = (lum > 0.0) ? ld.l_color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */ + + power /= (l_vector.w * l_vector.w); + + lum = min(lum * power, volLightClamp); + + return tint * lum; +} + +#define VOLUMETRIC_SHADOW_MAX_STEP 32.0 + +vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction) +{ + /* Waiting for proper volume shadowmaps and out of frustum shadow map. */ + vec3 ndc = project_point(ViewProjectionMatrix, wpos); + vec3 volume_co = ndc_to_volume(ndc * 0.5 + 0.5); + + /* Let the texture be clamped to edge. This reduce visual glitches. */ + return texture(volume_extinction, volume_co).rgb; +} + +vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D volume_extinction) +{ +#if defined(VOLUME_SHADOW) + /* Heterogeneous volume shadows */ + float dd = l_vector.w / volShadowSteps; + vec3 L = l_vector.xyz * l_vector.w; + vec3 shadow = vec3(1.0); + for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volShadowSteps - 0.1); s += 1.0) { + vec3 pos = ray_wpos + L * (s / volShadowSteps); + vec3 s_extinction = participating_media_extinction(pos, volume_extinction); + shadow *= exp(-s_extinction * dd); + } + return shadow; +#else + return vec3(1.0); +#endif /* VOLUME_SHADOW */ +} +#endif + +#ifdef IRRADIANCE_LIB +vec3 irradiance_volumetric(vec3 wpos) +{ +#ifdef IRRADIANCE_HL2 + IrradianceData ir_data = load_irradiance_cell(0, vec3(1.0)); + vec3 irradiance = ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2]; + ir_data = load_irradiance_cell(0, vec3(-1.0)); + irradiance += ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2]; + irradiance *= 0.16666666; /* 1/6 */ + return irradiance; +#else + return vec3(0.0); +#endif +} +#endif + +uniform sampler3D inScattering; +uniform sampler3D inTransmittance; + +vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth) +{ + vec3 volume_cos = ndc_to_volume(vec3(frag_uvs, frag_depth)); + + vec3 scattering = texture(inScattering, volume_cos).rgb; + vec3 transmittance = texture(inTransmittance, volume_cos).rgb; + + return vec4(scene_color.rgb * transmittance + scattering, scene_color.a); +} diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl new file mode 100644 index 00000000000..0115b2cb99e --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl @@ -0,0 +1,21 @@ + +/* Based on Frosbite Unified Volumetric. + * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ + +/* Step 4 : Apply final integration on top of the scene color. + * Note that we do the blending ourself instead of relying + * on hardware blending which would require 2 pass. */ + +uniform sampler2D inSceneColor; +uniform sampler2D inSceneDepth; + +out vec4 FragColor; + +void main() +{ + vec2 uvs = gl_FragCoord.xy / vec2(textureSize(inSceneDepth, 0)); + vec4 scene_color = texture(inSceneColor, uvs); + float scene_depth = texture(inSceneDepth, uvs).r; + + FragColor = volumetric_resolve(scene_color, uvs, scene_depth); +} diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl new file mode 100644 index 00000000000..fcbb6661b14 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl @@ -0,0 +1,75 @@ + +/* Based on Frosbite Unified Volumetric. + * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ + +/* Step 2 : Evaluate all light scattering for each froxels. + * Also do the temporal reprojection to fight aliasing artifacts. */ + +uniform sampler3D volumeScattering; +uniform sampler3D volumeExtinction; +uniform sampler3D volumeEmission; +uniform sampler3D volumePhase; + +uniform sampler3D historyScattering; +uniform sampler3D historyTransmittance; + +flat in int slice; + +layout(location = 0) out vec4 outScattering; +layout(location = 1) out vec4 outTransmittance; + +void main() +{ + ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice); + + /* Emission */ + outScattering = texelFetch(volumeEmission, volume_cell, 0); + outTransmittance = texelFetch(volumeExtinction, volume_cell, 0); + vec3 s_scattering = texelFetch(volumeScattering, volume_cell, 0).rgb; + vec3 volume_ndc = volume_to_ndc((vec3(volume_cell) + volJitter.xyz) * volInvTexSize.xyz); + vec3 worldPosition = get_world_space_from_depth(volume_ndc.xy, volume_ndc.z); + vec3 wdir = cameraVec; + + vec2 phase = texelFetch(volumePhase, volume_cell, 0).rg; + float s_anisotropy = phase.x / max(1.0, phase.y); + + /* Environment : Average color. */ + outScattering.rgb += irradiance_volumetric(worldPosition) * s_scattering * phase_function_isotropic(); + +#ifdef VOLUME_LIGHTING /* Lights */ + for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) { + + LightData ld = lights_data[i]; + + vec4 l_vector; + l_vector.xyz = (ld.l_type == SUN) ? -ld.l_forward : ld.l_position - worldPosition; + l_vector.w = length(l_vector.xyz); + + float Vis = light_visibility(ld, worldPosition, l_vector); + + vec3 Li = light_volume(ld, l_vector) * light_volume_shadow(ld, worldPosition, l_vector, volumeExtinction); + + outScattering.rgb += Li * Vis * s_scattering * phase_function(-wdir, l_vector.xyz / l_vector.w, s_anisotropy); + } +#endif + + /* Temporal supersampling */ + /* Note : this uses the cell non-jittered position (texel center). */ + vec3 curr_ndc = volume_to_ndc(vec3(gl_FragCoord.xy, float(slice) + 0.5) * volInvTexSize.xyz); + vec3 wpos = get_world_space_from_depth(curr_ndc.xy, curr_ndc.z); + vec3 prev_ndc = project_point(pastViewProjectionMatrix, wpos); + vec3 prev_volume = ndc_to_volume(prev_ndc * 0.5 + 0.5); + + if ((volHistoryAlpha > 0.0) && all(greaterThan(prev_volume, vec3(0.0))) && all(lessThan(prev_volume, vec3(1.0)))) { + vec4 h_Scattering = texture(historyScattering, prev_volume); + vec4 h_Transmittance = texture(historyTransmittance, prev_volume); + outScattering = mix(outScattering, h_Scattering, volHistoryAlpha); + outTransmittance = mix(outTransmittance, h_Transmittance, volHistoryAlpha); + } + + /* Catch NaNs */ + if (any(isnan(outScattering)) || any(isnan(outTransmittance))) { + outScattering = vec4(0.0); + outTransmittance = vec4(1.0); + } +} diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl new file mode 100644 index 00000000000..a99acd41fbd --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl @@ -0,0 +1,27 @@ + +out vec4 vPos; + +void main() +{ + /* Generate Triangle : less memory fetches from a VBO */ + int v_id = gl_VertexID % 3; /* Vertex Id */ + int t_id = gl_VertexID / 3; /* Triangle Id */ + + /* Crappy diagram + * ex 1 + * | \ + * | \ + * 1 | \ + * | \ + * | \ + * 0 | \ + * | \ + * | \ + * -1 0 --------------- 2 + * -1 0 1 ex + **/ + vPos.x = float(v_id / 2) * 4.0 - 1.0; /* int divisor round down */ + vPos.y = float(v_id % 2) * 4.0 - 1.0; + vPos.z = float(t_id); + vPos.w = 1.0; +} diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c new file mode 100644 index 00000000000..2917805d233 --- /dev/null +++ b/source/blender/draw/engines/external/external_engine.c @@ -0,0 +1,234 @@ +/* + * Copyright 2017, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file external_engine.c + * \ingroup draw_engine + * + * Base engine for external render engines. + * We use it for depth and non-mesh objects. + */ + +#include "DRW_render.h" + +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" + +#include "BKE_icons.h" +#include "BKE_idprop.h" +#include "BKE_main.h" + +#include "ED_view3d.h" +#include "ED_screen.h" + +#include "GPU_glew.h" +#include "GPU_matrix.h" +#include "GPU_shader.h" +#include "GPU_viewport.h" + +#include "external_engine.h" +/* Shaders */ + +#define EXTERNAL_ENGINE "BLENDER_EXTERNAL" + +/* *********** LISTS *********** */ + +/* GPUViewport.storage + * Is freed everytime the viewport engine changes */ +typedef struct EXTERNAL_Storage { + int dummy; +} EXTERNAL_Storage; + +typedef struct EXTERNAL_StorageList { + struct EXTERNAL_Storage *storage; + struct EXTERNAL_PrivateData *g_data; +} EXTERNAL_StorageList; + +typedef struct EXTERNAL_FramebufferList { + struct GPUFrameBuffer *default_fb; +} EXTERNAL_FramebufferList; + +typedef struct EXTERNAL_TextureList { + /* default */ + struct GPUTexture *depth; +} EXTERNAL_TextureList; + +typedef struct EXTERNAL_PassList { + struct DRWPass *depth_pass; +} EXTERNAL_PassList; + +typedef struct EXTERNAL_Data { + void *engine_type; + EXTERNAL_FramebufferList *fbl; + EXTERNAL_TextureList *txl; + EXTERNAL_PassList *psl; + EXTERNAL_StorageList *stl; + char info[GPU_INFO_SIZE]; +} EXTERNAL_Data; + +/* *********** STATIC *********** */ + +static struct { + /* Depth Pre Pass */ + struct GPUShader *depth_sh; +} e_data = {NULL}; /* Engine data */ + +typedef struct EXTERNAL_PrivateData { + DRWShadingGroup *depth_shgrp; +} EXTERNAL_PrivateData; /* Transient data */ + +/* Functions */ + +static void external_engine_init(void *UNUSED(vedata)) +{ + /* Depth prepass */ + if (!e_data.depth_sh) { + e_data.depth_sh = DRW_shader_create_3D_depth_only(); + } +} + +static void external_cache_init(void *vedata) +{ + EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl; + EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + /* Depth Pass */ + { + psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); + stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass); + } +} + +static void external_cache_populate(void *vedata, Object *ob) +{ + EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl; + + if (!DRW_object_is_renderable(ob)) + return; + + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + /* Depth Prepass */ + DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat); + } +} + +static void external_cache_finish(void *UNUSED(vedata)) +{ +} + +static void external_draw_scene_do(void *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + RegionView3D *rv3d = draw_ctx->rv3d; + ARegion *ar = draw_ctx->ar; + RenderEngineType *type; + + DRW_state_reset_ex(DRW_STATE_DEFAULT & ~DRW_STATE_DEPTH_LESS_EQUAL); + + /* Create render engine. */ + if (!rv3d->render_engine) { + RenderEngineType *engine_type = draw_ctx->engine_type; + + if (!(engine_type->view_update && engine_type->view_draw)) { + return; + } + + RenderEngine *engine = RE_engine_create_ex(engine_type, true); + engine->tile_x = scene->r.tilex; + engine->tile_y = scene->r.tiley; + engine_type->view_update(engine, draw_ctx->evil_C); + rv3d->render_engine = engine; + } + + /* Rendered draw. */ + gpuPushProjectionMatrix(); + ED_region_pixelspace(ar); + + /* Render result draw. */ + type = rv3d->render_engine->type; + type->view_draw(rv3d->render_engine, draw_ctx->evil_C); + + gpuPopProjectionMatrix(); + + /* Set render info. */ + EXTERNAL_Data *data = vedata; + if (rv3d->render_engine->text[0] != '\0') { + BLI_strncpy(data->info, rv3d->render_engine->text, sizeof(data->info)); + } + else { + data->info[0] = '\0'; + } +} + +static void external_draw_scene(void *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl; + + /* Will be NULL during OpenGL render. + * OpenGL render is used for quick preview (thumbnails or sequencer preview) + * where using the rendering engine to preview doesn't make so much sense. */ + if (draw_ctx->evil_C) { + external_draw_scene_do(vedata); + } + DRW_draw_pass(psl->depth_pass); +} + +static void external_engine_free(void) +{ + /* All shaders are builtin. */ +} + +static const DrawEngineDataSize external_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data); + +DrawEngineType draw_engine_external_type = { + NULL, NULL, + N_("External"), + &external_data_size, + &external_engine_init, + &external_engine_free, + &external_cache_init, + &external_cache_populate, + &external_cache_finish, + NULL, + &external_draw_scene, + NULL, + NULL, + NULL, +}; + +/* Note: currently unused, we should not register unless we want to see this when debugging the view. */ + +RenderEngineType DRW_engine_viewport_external_type = { + NULL, NULL, + EXTERNAL_ENGINE, N_("External"), RE_INTERNAL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &draw_engine_external_type, + {NULL, NULL, NULL} +}; + +#undef EXTERNAL_ENGINE diff --git a/source/blender/draw/engines/external/external_engine.h b/source/blender/draw/engines/external/external_engine.h new file mode 100644 index 00000000000..1789fb67efe --- /dev/null +++ b/source/blender/draw/engines/external/external_engine.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file external_engine.h + * \ingroup draw_engine + */ + +#ifndef __EXTERNAL_ENGINE_H__ +#define __EXTERNAL_ENGINE_H__ + +extern RenderEngineType DRW_engine_viewport_external_type; + +#endif /* __EXTERNAL_ENGINE_H__ */ diff --git a/source/blender/draw/engines/workbench/shaders/workbench_background_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_background_lib.glsl new file mode 100644 index 00000000000..fda2fc85460 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_background_lib.glsl @@ -0,0 +1,3 @@ +vec3 background_color(WorldData world_data, float y) { + return mix(world_data.background_color_low, world_data.background_color_high, y).xyz + bayer_dither_noise(); +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl new file mode 100644 index 00000000000..4e44f6e1914 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl @@ -0,0 +1,10 @@ +void main() +{ + vec2 p= vec2(floor(gl_FragCoord.x), floor(gl_FragCoord.y)); + vec2 test = mod(p, 2.0); + if (mod(test.x + test.y, 2.0)==0.0) { + discard; + } else { + gl_FragDepth = 1.0; + } +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl new file mode 100644 index 00000000000..88b715f55a8 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -0,0 +1,71 @@ +#define NO_OBJECT_ID uint(0) +#define EPSILON 0.00001 +/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ +#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0)) +const vec4 dither_mat4x4[4] = vec4[4]( + vec4( P(0.0), P(8.0), P(2.0), P(10.0)), + vec4(P(12.0), P(4.0), P(14.0), P(6.0)), + vec4( P(3.0), P(11.0), P(1.0), P(9.0)), + vec4(P(15.0), P(7.0), P(13.0), P(5.0)) +); + +float bayer_dither_noise() { + ivec2 tx1 = ivec2(gl_FragCoord.xy) % 4; + ivec2 tx2 = ivec2(gl_FragCoord.xy) % 2; + return dither_mat4x4[tx1.x][tx1.y]; +} + +/* From http://aras-p.info/texts/CompactNormalStorage.html + * Using Method #4: Spheremap Transform */ +vec3 normal_decode(vec2 enc) +{ + vec2 fenc = enc.xy * 4.0 - 2.0; + float f = dot(fenc, fenc); + float g = sqrt(1.0 - f / 4.0); + vec3 n; + n.xy = fenc*g; + n.z = 1 - f / 2; + return n; +} + +/* From http://aras-p.info/texts/CompactNormalStorage.html + * Using Method #4: Spheremap Transform */ +vec2 normal_encode(vec3 n) +{ + float p = sqrt(n.z * 8.0 + 8.0); + return vec2(n.xy / p + 0.5); +} + +void fresnel(vec3 I, vec3 N, float ior, out float kr) +{ + float cosi = clamp(dot(I, N), -1.0, 1.0); + float etai = 1.0; + float etat = ior; + if (cosi > 0) { + etat = 1.0; + etai = ior; + } + + // Compute sini using Snell's law + float sint = etai / etat * sqrt(max(0.0, 1.0 - cosi * cosi)); + // Total internal reflection + if (sint >= 1) { + kr = 1; + } + else { + float cost = sqrt(max(0.0, 1.0 - sint * sint)); + cosi = abs(cosi); + float Rs = ((etat * cosi) - (etai * cost)) / ((etat * cosi) + (etai * cost)); + float Rp = ((etai * cosi) - (etat * cost)) / ((etai * cosi) + (etat * cost)); + kr = (Rs * Rs + Rp * Rp) / 2; + } + // As a consequence of the conservation of energy, transmittance is given by: + // kt = 1 - kr; +} + +vec4 calculate_transparent_accum(vec4 premultiplied) { + float a = min(1.0, premultiplied.a) * 8.0 + 0.01; + float b = -gl_FragCoord.z * 0.95 + 1.0; + float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2); + return premultiplied * w; +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl new file mode 100644 index 00000000000..c826a5b82fa --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl @@ -0,0 +1,13 @@ +struct WorldData { + vec4 diffuse_light_x_pos; + vec4 diffuse_light_x_neg; + vec4 diffuse_light_y_pos; + vec4 diffuse_light_y_neg; + vec4 diffuse_light_z_pos; + vec4 diffuse_light_z_neg; + vec4 background_color_low; + vec4 background_color_high; + vec4 object_outline_color; + vec4 light_direction_vs; + float specular_sharpness; +}; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl new file mode 100644 index 00000000000..7374dfbe79e --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl @@ -0,0 +1,98 @@ +out vec4 fragColor; + +uniform usampler2D objectId; +uniform sampler2D colorBuffer; +uniform sampler2D normalBuffer; +/* normalBuffer contains viewport normals */ +uniform vec2 invertedViewportSize; +uniform float shadowMultiplier; +uniform float lightMultiplier; +uniform float shadowShift = 0.1; +uniform mat3 normalWorldMatrix; + + +layout(std140) uniform world_block { + WorldData world_data; +}; + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; + uint object_id = texelFetch(objectId, texel, 0).r; + +#ifndef V3D_SHADING_OBJECT_OUTLINE + if (object_id == NO_OBJECT_ID) { + fragColor = vec4(background_color(world_data, uv_viewport.y), 0.0); + return; + } +#else /* !V3D_SHADING_OBJECT_OUTLINE */ + float object_outline = calculate_object_outline(objectId, texel, object_id); + + if (object_id == NO_OBJECT_ID) { + vec3 background = background_color(world_data, uv_viewport.y); + if (object_outline == 0.0) { + fragColor = vec4(background, 0.0); + } + else { + fragColor = vec4(mix(world_data.object_outline_color.rgb, background, object_outline), 1.0-object_outline); + } + return; + } +#endif /* !V3D_SHADING_OBJECT_OUTLINE */ + + vec4 diffuse_color = texelFetch(colorBuffer, texel, 0); +/* Do we need normals */ +#ifdef NORMAL_VIEWPORT_PASS_ENABLED +#ifdef WORKBENCH_ENCODE_NORMALS + vec3 normal_viewport = normal_decode(texelFetch(normalBuffer, texel, 0).rg); + if (diffuse_color.a == 1.0) { + normal_viewport = -normal_viewport; + } +#else /* WORKBENCH_ENCODE_NORMALS */ + vec3 normal_viewport = texelFetch(normalBuffer, texel, 0).rgb; +#endif /* WORKBENCH_ENCODE_NORMALS */ +#endif + + +#ifdef V3D_LIGHTING_STUDIO + #ifdef STUDIOLIGHT_ORIENTATION_CAMERA + vec3 diffuse_light = get_camera_diffuse_light(world_data, normal_viewport); + #endif + + #ifdef STUDIOLIGHT_ORIENTATION_WORLD + vec3 normal_world = normalWorldMatrix * normal_viewport; + vec3 diffuse_light = get_world_diffuse_light(world_data, normal_world); + #endif + + vec3 specular_color = get_world_specular_light(world_data, normal_viewport, vec3(0.0, 0.0, 1.0)); + vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color; + +#else /* V3D_LIGHTING_STUDIO */ + #ifdef V3D_SHADING_SPECULAR_HIGHLIGHT + vec3 specular_color = get_world_specular_light(world_data, normal_viewport, vec3(0.0, 0.0, 1.0)); + vec3 shaded_color = diffuse_color.rgb + specular_color; + + #else /* V3D_SHADING_SPECULAR_HIGHLIGHT */ + vec3 shaded_color = diffuse_color.rgb; + + #endif /* V3D_SHADING_SPECULAR_HIGHLIGHT */ + +#endif /* V3D_LIGHTING_STUDIO */ + +#ifdef V3D_SHADING_SHADOW + float shadow_mix = step(-shadowShift, dot(normal_viewport, world_data.light_direction_vs.xyz)); + float light_multiplier; + light_multiplier = mix(lightMultiplier, shadowMultiplier, shadow_mix); + +#else /* V3D_SHADING_SHADOW */ + float light_multiplier = 1.0; +#endif /* V3D_SHADING_SHADOW */ + + shaded_color *= light_multiplier; + +#ifdef V3D_SHADING_OBJECT_OUTLINE + shaded_color = mix(world_data.object_outline_color.rgb, shaded_color, object_outline); +#endif /* V3D_SHADING_OBJECT_OUTLINE */ + fragColor = vec4(shaded_color, 1.0); +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl new file mode 100644 index 00000000000..12d6296655d --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl @@ -0,0 +1,42 @@ +out vec4 fragColor; + +uniform usampler2D objectId; +uniform sampler2D transparentAccum; +#ifdef WORKBENCH_REVEALAGE_ENABLED +uniform sampler2D transparentRevealage; +#endif +uniform vec2 invertedViewportSize; + +layout(std140) uniform world_block { + WorldData world_data; +}; + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; + uint object_id = texelFetch(objectId, texel, 0).r; + vec4 transparent_accum = texelFetch(transparentAccum, texel, 0); +#ifdef WORKBENCH_REVEALAGE_ENABLED + float transparent_revealage = texelFetch(transparentRevealage, texel, 0).r; +#endif + vec4 color; + +#ifdef V3D_SHADING_OBJECT_OUTLINE + float outline = calculate_object_outline(objectId, texel, object_id); +#else /* V3D_SHADING_OBJECT_OUTLINE */ + float outline = 1.0; +#endif /* V3D_SHADING_OBJECT_OUTLINE */ + + if (object_id == NO_OBJECT_ID) { + color = vec4(background_color(world_data, uv_viewport.y), 0.0); + } else { +#ifdef WORKBENCH_REVEALAGE_ENABLED + color = vec4((transparent_accum.xyz / max(transparent_accum.a, EPSILON)) * (1.0 - transparent_revealage), 1.0); +#else + color = vec4(transparent_accum.xyz / max(transparent_accum.a, EPSILON), 1.0); +#endif + } + + fragColor = vec4(mix(world_data.object_outline_color.rgb, color.xyz, outline), 1.0); +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl new file mode 100644 index 00000000000..450cb3e680b --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_depth_frag.glsl @@ -0,0 +1,8 @@ +uniform int object_id = 0; +layout(location=0) out uint objectId; + +void main() +{ + objectId = uint(object_id); +} + diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl new file mode 100644 index 00000000000..d0e3305cc70 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -0,0 +1,59 @@ +uniform vec4 color = vec4(0.0, 0.0, 1.0, 1.0); +#ifdef OB_TEXTURE +uniform sampler2D image; +#endif +uniform mat3 normalWorldMatrix; + +#ifdef NORMAL_VIEWPORT_PASS_ENABLED +in vec3 normal_viewport; +#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ +#ifdef OB_TEXTURE +in vec2 uv_interp; +#endif + +layout(std140) uniform world_block { + WorldData world_data; +}; + +layout(location=0) out vec4 transparentAccum; + + +void main() +{ + vec4 diffuse_color; +#ifdef OB_SOLID + diffuse_color = color; +#endif /* OB_SOLID */ +#ifdef OB_TEXTURE + diffuse_color = texture(image, uv_interp); +#endif /* OB_TEXTURE */ + +#ifdef V3D_LIGHTING_STUDIO +#ifdef STUDIOLIGHT_ORIENTATION_CAMERA + vec3 diffuse_light = get_camera_diffuse_light(world_data, normal_viewport); +#endif +#ifdef STUDIOLIGHT_ORIENTATION_WORLD + vec3 normal_world = normalWorldMatrix * normal_viewport; + vec3 diffuse_light = get_world_diffuse_light(world_data, normal_world); +#endif + + vec3 specular_color = get_world_specular_light(world_data, normal_viewport, vec3(0.0, 0.0, 1.0)); + vec3 shaded_color = diffuse_light * diffuse_color.rgb + specular_color; + +#else /* V3D_LIGHTING_STUDIO */ + #ifdef V3D_SHADING_SPECULAR_HIGHLIGHT + vec3 specular_color = get_world_specular_light(world_data, normal_viewport, vec3(0.0, 0.0, 1.0)); + vec3 shaded_color = diffuse_color.rgb + specular_color; + + #else /* V3D_SHADING_SPECULAR_HIGHLIGHT */ + vec3 shaded_color = diffuse_color.rgb; + + #endif /* V3D_SHADING_SPECULAR_HIGHLIGHT */ + +#endif /* V3D_LIGHTING_STUDIO */ + + float alpha = 0.5 ; + vec4 premultiplied = vec4(shaded_color.rgb * alpha, alpha); + transparentAccum = calculate_transparent_accum(premultiplied); +} + diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl new file mode 100644 index 00000000000..da87fe8f542 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl @@ -0,0 +1,7 @@ +layout(location=0) out float transparentRevealage; + +void main() +{ + transparentRevealage = 0.5; +} + diff --git a/source/blender/draw/engines/workbench/shaders/workbench_object_outline_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_object_outline_lib.glsl new file mode 100644 index 00000000000..3e925ba023f --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_object_outline_lib.glsl @@ -0,0 +1,12 @@ +#define OBJECT_OUTLINE_OFFSET 1 + +float calculate_object_outline(usampler2D objectId, ivec2 texel, uint object_id) +{ + uvec4 oid_offset = uvec4( + texelFetchOffset(objectId, texel, 0, ivec2(0, OBJECT_OUTLINE_OFFSET)).r, + texelFetchOffset(objectId, texel, 0, ivec2(0, -OBJECT_OUTLINE_OFFSET)).r, + texelFetchOffset(objectId, texel, 0, ivec2(-OBJECT_OUTLINE_OFFSET, 0)).r, + texelFetchOffset(objectId, texel, 0, ivec2( OBJECT_OUTLINE_OFFSET, 0)).r); + + return dot(vec4(equal(uvec4(object_id), oid_offset)), vec4(0.25)); +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl new file mode 100644 index 00000000000..2cc0ff3723d --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -0,0 +1,48 @@ +uniform int object_id = 0; +uniform vec3 object_color = vec3(1.0, 0.0, 1.0); +#ifdef OB_TEXTURE +uniform sampler2D image; +#endif + +#ifdef NORMAL_VIEWPORT_PASS_ENABLED +in vec3 normal_viewport; +#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ +#ifdef OB_TEXTURE +in vec2 uv_interp; +#endif /* OB_TEXTURE */ + +layout(location=0) out uint objectId; +layout(location=1) out vec4 diffuseColor; +#ifdef NORMAL_VIEWPORT_PASS_ENABLED + #ifdef WORKBENCH_ENCODE_NORMALS +layout(location=2) out vec2 normalViewport; + #else /* WORKBENCH_ENCODE_NORMALS */ +layout(location=2) out vec3 normalViewport; + #endif /* WORKBENCH_ENCODE_NORMALS */ +#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ + +void main() +{ + objectId = uint(object_id); +#ifdef OB_SOLID + diffuseColor = vec4(object_color, 0.0); +#endif /* OB_SOLID */ +#ifdef OB_TEXTURE + diffuseColor = texture(image, uv_interp); +#endif /* OB_TEXTURE */ + +#ifdef NORMAL_VIEWPORT_PASS_ENABLED + #ifdef WORKBENCH_ENCODE_NORMALS + if (!gl_FrontFacing) { + normalViewport = normal_encode(normalize(-normal_viewport)); + diffuseColor.a = 1.0; + } + else { + normalViewport = normal_encode(normalize(normal_viewport)); + diffuseColor.a = 0.0; + } + #else /* WORKBENCH_ENCODE_NORMALS */ + normalViewport = normal_viewport; + #endif /* WORKBENCH_ENCODE_NORMALS */ +#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl new file mode 100644 index 00000000000..f2df117d897 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -0,0 +1,30 @@ +uniform mat4 ModelViewProjectionMatrix; +#ifdef NORMAL_VIEWPORT_PASS_ENABLED +uniform mat3 NormalMatrix; +#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ + +in vec3 pos; +#ifdef NORMAL_VIEWPORT_PASS_ENABLED +in vec3 nor; +#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ +#ifdef OB_TEXTURE +in vec2 uv; +#endif + +#ifdef NORMAL_VIEWPORT_PASS_ENABLED +out vec3 normal_viewport; +#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ +#ifdef OB_TEXTURE +out vec2 uv_interp; +#endif + +void main() +{ +#ifdef OB_TEXTURE + uv_interp = uv; +#endif +#ifdef NORMAL_VIEWPORT_PASS_ENABLED + normal_viewport = normalize(NormalMatrix * nor); +#endif /* NORMAL_VIEWPORT_PASS_ENABLED */ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl new file mode 100644 index 00000000000..32b31718cf8 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl @@ -0,0 +1,80 @@ +#extension GL_ARB_gpu_shader5 : enable + +#ifdef GL_ARB_gpu_shader5 +#define USE_INVOC_EXT +#endif + +#ifdef DOUBLE_MANIFOLD +# ifdef USE_INVOC_EXT +# define invoc_ct 4 +# else +# define vert_ct 12 +# endif +#else +# ifdef USE_INVOC_EXT +# define invoc_ct 2 +# else +# define vert_ct 6 +# endif +#endif + +#ifdef USE_INVOC_EXT +layout(triangles, invocations = invoc_ct) in; +layout(triangle_strip, max_vertices = 3) out; +#else +layout(triangles) in; +layout(triangle_strip, max_vertices = vert_ct) out; +#endif + +uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57); + +in VertexData { + vec3 pos; /* local position */ + vec4 frontPosition; /* final ndc position */ + vec4 backPosition; +} vData[]; + +vec4 get_pos(int v, bool backface) +{ + return (backface) ? vData[v].backPosition : vData[v].frontPosition; +} + +void emit_cap(const bool front) +{ + if (front) { + gl_Position = vData[0].frontPosition; EmitVertex(); + gl_Position = vData[1].frontPosition; EmitVertex(); + gl_Position = vData[2].frontPosition; EmitVertex(); + } + else { + gl_Position = vData[0].backPosition; EmitVertex(); + gl_Position = vData[2].backPosition; EmitVertex(); + gl_Position = vData[1].backPosition; EmitVertex(); + } + EndPrimitive(); +} + +void main() +{ + vec3 v10 = vData[0].pos - vData[1].pos; + vec3 v12 = vData[2].pos - vData[1].pos; + + vec3 n = cross(v12, v10); + float facing = dot(n, lightDirection); + + bool backface = facing > 0.0; + + if (!backface) { +#ifdef USE_INVOC_EXT + bool do_front = (gl_InvocationID & 1) == 0; + emit_cap(do_front); +#else + emit_cap(true); + emit_cap(false); +# ifdef DOUBLE_MANIFOLD + emit_cap(true); + emit_cap(false); +# endif +#endif + } +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl new file mode 100644 index 00000000000..ceb33e77f2b --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl @@ -0,0 +1,14 @@ + +out vec4 fragColor; + +void main() +{ + const float intensity = 0.25; +#ifdef SHADOW_PASS + fragColor = vec4((gl_FrontFacing) ? vec3(intensity, -intensity, 0.0) + : vec3(-intensity, intensity, 0.0), 1.0); +#else + fragColor = vec4((gl_FrontFacing) ? vec3(intensity, intensity, -intensity) + : vec3(-intensity, -intensity, intensity), 1.0); +#endif +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl new file mode 100644 index 00000000000..5a31aa34932 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl @@ -0,0 +1,118 @@ +#extension GL_ARB_gpu_shader5 : enable + +#ifdef GL_ARB_gpu_shader5 +#define USE_INVOC_EXT +#endif + +#ifdef DOUBLE_MANIFOLD +# ifdef USE_INVOC_EXT +# define invoc_ct 2 +# else +# define vert_ct 8 +# endif +#else +# ifdef USE_INVOC_EXT +# define invoc_ct 1 +# else +# define vert_ct 4 +# endif +#endif + +#ifdef USE_INVOC_EXT +layout(lines_adjacency, invocations = invoc_ct) in; +layout(triangle_strip, max_vertices = 4) out; +#else +layout(lines_adjacency) in; +layout(triangle_strip, max_vertices = vert_ct) out; +#endif + +uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57); + +in VertexData { + vec3 pos; /* local position */ + vec4 frontPosition; /* final ndc position */ + vec4 backPosition; +} vData[]; + +#define DEGENERATE_THRESHOLD 1e-12 + +#define len_sqr(a) dot(a, a) + +void extrude_edge(bool invert) +{ + /* Reverse order if backfacing the light. */ + ivec2 idx = (invert) ? ivec2(1, 2) : ivec2(2, 1); + gl_Position = vData[idx.x].frontPosition; EmitVertex(); + gl_Position = vData[idx.y].frontPosition; EmitVertex(); + gl_Position = vData[idx.x].backPosition; EmitVertex(); + gl_Position = vData[idx.y].backPosition; EmitVertex(); + EndPrimitive(); +} + +void main() +{ + vec3 v10 = vData[0].pos - vData[1].pos; + vec3 v12 = vData[2].pos - vData[1].pos; + vec3 v13 = vData[3].pos - vData[1].pos; + +#ifdef DEGENERATE_THRESHOLD + vec3 v20 = vData[0].pos - vData[2].pos; + vec3 v23 = vData[3].pos - vData[2].pos; + + vec4 edges_lensqr = vec4(len_sqr(v10), len_sqr(v13), len_sqr(v20), len_sqr(v23)); + bvec4 degen_edges = lessThan(edges_lensqr, vec4(DEGENERATE_THRESHOLD)); + + /* Both triangles are degenerate, abort. */ + if (any(degen_edges.xz) && any(degen_edges.yw)) + return; +#endif + + vec3 n1 = cross(v12, v10); + vec3 n2 = cross(v13, v12); + vec2 facing = vec2(dot(n1, lightDirection), + dot(n2, lightDirection)); + + /* WATCH: maybe unpredictable in some cases. */ + bool is_manifold = any(notEqual(vData[0].pos, vData[3].pos)); + + bvec2 backface = greaterThan(facing, vec2(0.0)); + +#ifdef DEGENERATE_THRESHOLD +# ifndef DOUBLE_MANIFOLD + /* If the mesh is known to be manifold and we don't use double count, + * only create an quad if the we encounter a facing geom. */ + if ((any(degen_edges.xz) && backface.y) || + (any(degen_edges.yw) && backface.x)) + return; +# endif + + /* If one of the 2 triangles is degenerate, replace edge by a non-manifold one. */ + backface.x = (any(degen_edges.xz)) ? !backface.y : backface.x; + backface.y = (any(degen_edges.yw)) ? !backface.x : backface.y; + is_manifold = (any(degen_edges)) ? false : is_manifold; +#endif + + /* If both faces face the same direction it's not an outline edge. */ + if (backface.x == backface.y) + return; + +#ifdef USE_INVOC_EXT + if (gl_InvocationID == 0) { + extrude_edge(backface.x); + } + else if (is_manifold) { +# ifdef DOUBLE_MANIFOLD + /* Increment/Decrement twice for manifold edges. */ + extrude_edge(backface.x); +# endif + } +#else + extrude_edge(backface.x); + if (is_manifold) { +# ifdef DOUBLE_MANIFOLD + /* Increment/Decrement twice for manifold edges. */ + extrude_edge(backface.x); +# endif + } +#endif +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl new file mode 100644 index 00000000000..3a61bf0a286 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl @@ -0,0 +1,20 @@ +#define INFINITE 1000.0 + +uniform mat4 ModelViewProjectionMatrix; + +uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57); + +in vec3 pos; + +out VertexData { + vec3 pos; /* local position */ + vec4 frontPosition; /* final ndc position */ + vec4 backPosition; +} vData; + +void main() +{ + vData.pos = pos; + vData.frontPosition = ModelViewProjectionMatrix * vec4(pos, 1.0); + vData.backPosition = ModelViewProjectionMatrix * vec4(pos + lightDirection * INFINITE, 1.0); +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl new file mode 100644 index 00000000000..7d1084c78b4 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl @@ -0,0 +1,36 @@ +vec3 get_world_diffuse_light(WorldData world_data, vec3 N) +{ + vec4 result = world_data.diffuse_light_x_pos * clamp(N.x, 0.0, 1.0); + result = mix(result, world_data.diffuse_light_x_neg, clamp(-N.x, 0.0, 1.0)); + result = mix(result, world_data.diffuse_light_y_pos, clamp(-N.y, 0.0, 1.0)); + result = mix(result, world_data.diffuse_light_y_neg, clamp(N.y, 0.0, 1.0)); + result = mix(result, world_data.diffuse_light_z_pos, clamp(N.z, 0.0, 1.0)); + return mix(result, world_data.diffuse_light_z_neg, clamp(-N.z, 0.0, 1.0)).xyz; +} + +vec3 get_camera_diffuse_light(WorldData world_data, vec3 N) +{ + vec4 result = world_data.diffuse_light_x_pos * clamp(N.x, 0.0, 1.0); + result = mix(result, world_data.diffuse_light_x_neg, clamp(-N.x, 0.0, 1.0)); + result = mix(result, world_data.diffuse_light_z_pos, clamp( N.y, 0.0, 1.0)); + result = mix(result, world_data.diffuse_light_z_neg, clamp(-N.y, 0.0, 1.0)); + result = mix(result, world_data.diffuse_light_y_pos, pow(clamp( N.z, 0.0, 1.0), 2.0)); + result = mix(result, world_data.diffuse_light_y_neg, clamp(-N.z, 0.0, 1.0)); + return result.rgb; +} + +/* N And I are in View Space. */ +vec3 get_world_specular_light(WorldData world_data, vec3 N, vec3 I) +{ +#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT + vec3 reflection_vector = reflect(I, N); + vec3 specular_light = vec3(0.1); + /* Simple frontal specular highlights. */ + float specular_influence = pow(max(0.0, dot(world_data.light_direction_vs.xyz, reflection_vector)), world_data.specular_sharpness); + vec3 specular_color = specular_light * specular_influence; + +#else /* V3D_SHADING_SPECULAR_HIGHLIGHT */ + vec3 specular_color = vec3(0.0); +#endif /* V3D_SHADING_SPECULAR_HIGHLIGHT */ + return specular_color; +} diff --git a/source/blender/draw/engines/workbench/solid_mode.c b/source/blender/draw/engines/workbench/solid_mode.c new file mode 100644 index 00000000000..1e49d1ae573 --- /dev/null +++ b/source/blender/draw/engines/workbench/solid_mode.c @@ -0,0 +1,96 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file solid_mode.c + * \ingroup draw_engine + * + * Simple engine for drawing color and/or depth. + * When we only need simple studio shaders. + */ + +#include "DRW_render.h" + +#include "GPU_shader.h" + +#include "workbench_private.h" + +/* Functions */ + +static void workbench_solid_engine_init(void *vedata) +{ + WORKBENCH_Data *data = vedata; + workbench_deferred_engine_init(data); +} + +static void workbench_solid_cache_init(void *vedata) +{ + + WORKBENCH_Data *data = vedata; + workbench_deferred_cache_init(data); +} + +static void workbench_solid_cache_populate(void *vedata, Object *ob) +{ + WORKBENCH_Data *data = vedata; + workbench_deferred_solid_cache_populate(data, ob); +} + +static void workbench_solid_cache_finish(void *vedata) +{ + WORKBENCH_Data *data = vedata; + workbench_deferred_cache_finish(data); +} + +static void workbench_solid_draw_background(void *vedata) +{ + WORKBENCH_Data *data = vedata; + workbench_deferred_draw_background(data); +} + +static void workbench_solid_draw_scene(void *vedata) +{ + WORKBENCH_Data *data = vedata; + workbench_deferred_draw_scene(data); +} + +static void workbench_solid_engine_free(void) +{ + workbench_deferred_engine_free(); +} + +static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data); + +DrawEngineType draw_engine_workbench_solid = { + NULL, NULL, + N_("Workbench"), + &workbench_data_size, + &workbench_solid_engine_init, + &workbench_solid_engine_free, + &workbench_solid_cache_init, + &workbench_solid_cache_populate, + &workbench_solid_cache_finish, + &workbench_solid_draw_background, + &workbench_solid_draw_scene, + NULL, + NULL, + NULL, +}; + diff --git a/source/blender/draw/engines/workbench/transparent_mode.c b/source/blender/draw/engines/workbench/transparent_mode.c new file mode 100644 index 00000000000..c5d3db4b390 --- /dev/null +++ b/source/blender/draw/engines/workbench/transparent_mode.c @@ -0,0 +1,96 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file transparent_mode.c + * \ingroup draw_engine + * + * Simple engine for drawing color and/or depth. + * When we only need simple studio shaders. + */ + +#include "DRW_render.h" + +#include "GPU_shader.h" + +#include "workbench_private.h" + +/* Functions */ + +static void workbench_transparent_engine_init(void *vedata) +{ + WORKBENCH_Data *data = vedata; + workbench_forward_engine_init(data); +} + +static void workbench_transparent_cache_init(void *vedata) +{ + + WORKBENCH_Data *data = vedata; + workbench_forward_cache_init(data); +} + +static void workbench_transparent_cache_populate(void *vedata, Object *ob) +{ + WORKBENCH_Data *data = vedata; + workbench_forward_cache_populate(data, ob); +} + +static void workbench_transparent_cache_finish(void *vedata) +{ + WORKBENCH_Data *data = vedata; + workbench_forward_cache_finish(data); +} + +static void workbench_transparent_draw_background(void *vedata) +{ + WORKBENCH_Data *data = vedata; + workbench_forward_draw_background(data); +} + +static void workbench_transparent_draw_scene(void *vedata) +{ + WORKBENCH_Data *data = vedata; + workbench_forward_draw_scene(data); +} + +static void workbench_transparent_engine_free(void) +{ + workbench_forward_engine_free(); +} + +static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data); + +DrawEngineType draw_engine_workbench_transparent = { + NULL, NULL, + N_("Workbench"), + &workbench_data_size, + &workbench_transparent_engine_init, + &workbench_transparent_engine_free, + &workbench_transparent_cache_init, + &workbench_transparent_cache_populate, + &workbench_transparent_cache_finish, + &workbench_transparent_draw_background, + &workbench_transparent_draw_scene, + NULL, + NULL, + NULL, +}; + diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c new file mode 100644 index 00000000000..19bec9734e5 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -0,0 +1,76 @@ +#include "workbench_private.h" + +#include "UI_resources.h" + +void workbench_private_data_init(WORKBENCH_PrivateData *wpd) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + wpd->material_hash = BLI_ghash_ptr_new(__func__); + + View3D *v3d = draw_ctx->v3d; + if (v3d) { + wpd->shading = v3d->shading; + wpd->drawtype = v3d->drawtype; + wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light, 0); + } + else { + memset(&wpd->shading, 0, sizeof(wpd->shading)); + wpd->shading.light = V3D_LIGHTING_STUDIO; + wpd->shading.shadow_intensity = 0.5; + copy_v3_fl(wpd->shading.single_color, 0.8f); + wpd->drawtype = OB_SOLID; + wpd->studio_light = BKE_studiolight_findindex(0); + } + wpd->shadow_multiplier = 1.0 - wpd->shading.shadow_intensity; + + WORKBENCH_UBO_World *wd = &wpd->world_data; + UI_GetThemeColor3fv(UI_GetThemeValue(TH_SHOW_BACK_GRAD) ? TH_LOW_GRAD : TH_HIGH_GRAD, wd->background_color_low); + UI_GetThemeColor3fv(TH_HIGH_GRAD, wd->background_color_high); + + /* XXX: Really quick conversion to avoid washed out background. + * Needs to be adressed properly (color managed using ocio). */ + srgb_to_linearrgb_v3_v3(wd->background_color_high, wd->background_color_high); + srgb_to_linearrgb_v3_v3(wd->background_color_low, wd->background_color_low); + + studiolight_update_world(wpd->studio_light, wd); + + copy_v3_v3(wd->object_outline_color, wpd->shading.object_outline_color); + wd->object_outline_color[3] = 1.0f; + wd->specular_sharpness = 100.0f - scene->display.roughness * 100.0f; + + wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data); +} + +void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, float light_direction[3]) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + +#if 0 + if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) { + BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_LIGHT_DIRECTION_CALCULATED); + float rot_matrix[3][3]; + axis_angle_to_mat3_single(rot_matrix, 'Z', wpd->shading.studiolight_rot_z); + mul_v3_m3v3(e_data.display.light_direction, rot_matrix, wpd->studio_light->light_direction); + } + else { +#else + { +#endif + copy_v3_v3(light_direction, scene->display.light_direction); + negate_v3(light_direction); + } + + float view_matrix[4][4]; + DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW); + mul_v3_mat3_m4v3(wpd->world_data.light_direction_vs, view_matrix, light_direction); + wpd->world_data.light_direction_vs[3] = 0.0; + DRW_uniformbuffer_update(wpd->world_ubo, &wpd->world_data); +} + +void workbench_private_data_free(WORKBENCH_PrivateData *wpd) +{ + BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN); + DRW_UBO_FREE_SAFE(wpd->world_ubo); +} diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c new file mode 100644 index 00000000000..e7655eee940 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -0,0 +1,659 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file workbench_deferred.c + * \ingroup draw_engine + */ + +#include "workbench_private.h" + +#include "BIF_gl.h" + +#include "BLI_alloca.h" +#include "BLI_dynstr.h" +#include "BLI_utildefines.h" + +#include "BKE_node.h" +#include "BKE_particle.h" + +#include "DNA_image_types.h" +#include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_node_types.h" + +#include "ED_uvedit.h" + +#include "GPU_shader.h" +#include "GPU_texture.h" + + +/* *********** STATIC *********** */ + +// #define DEBUG_SHADOW_VOLUME + +#ifdef DEBUG_SHADOW_VOLUME +# include "draw_debug.h" +#endif + +static struct { + struct GPUShader *prepass_sh_cache[MAX_SHADERS]; + struct GPUShader *composite_sh_cache[MAX_SHADERS]; + struct GPUShader *shadow_fail_sh; + struct GPUShader *shadow_fail_manifold_sh; + struct GPUShader *shadow_pass_sh; + struct GPUShader *shadow_pass_manifold_sh; + struct GPUShader *shadow_caps_sh; + struct GPUShader *shadow_caps_manifold_sh; + + struct GPUTexture *object_id_tx; /* ref only, not alloced */ + struct GPUTexture *color_buffer_tx; /* ref only, not alloced */ + struct GPUTexture *normal_buffer_tx; /* ref only, not alloced */ + struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ + + SceneDisplay display; /* world light direction for shadows */ + float light_direction_vs[3]; + int next_object_id; + float normal_world_matrix[3][3]; +} e_data = {{NULL}}; + +/* Shaders */ +extern char datatoc_workbench_prepass_vert_glsl[]; +extern char datatoc_workbench_prepass_frag_glsl[]; +extern char datatoc_workbench_deferred_composite_frag_glsl[]; + +extern char datatoc_workbench_shadow_vert_glsl[]; +extern char datatoc_workbench_shadow_geom_glsl[]; +extern char datatoc_workbench_shadow_caps_geom_glsl[]; +extern char datatoc_workbench_shadow_debug_frag_glsl[]; + +extern char datatoc_workbench_background_lib_glsl[]; +extern char datatoc_workbench_common_lib_glsl[]; +extern char datatoc_workbench_data_lib_glsl[]; +extern char datatoc_workbench_object_outline_lib_glsl[]; +extern char datatoc_workbench_world_light_lib_glsl[]; + +static char *workbench_build_composite_frag(WORKBENCH_PrivateData *wpd) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl); + + if ((wpd->shading.light & V3D_LIGHTING_STUDIO) || (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT)) { + BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl); + } + if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) { + BLI_dynstr_append(ds, datatoc_workbench_object_outline_lib_glsl); + } + + BLI_dynstr_append(ds, datatoc_workbench_deferred_composite_frag_glsl); + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} + +static char *workbench_build_prepass_frag(void) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_prepass_frag_glsl); + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} + +static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, int drawtype) +{ + if (e_data.prepass_sh_cache[index] == NULL) { + char *defines = workbench_material_build_defines(wpd, drawtype); + char *composite_frag = workbench_build_composite_frag(wpd); + char *prepass_frag = workbench_build_prepass_frag(); + e_data.prepass_sh_cache[index] = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, prepass_frag, defines); + if (drawtype == OB_SOLID) { + e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); + } + MEM_freeN(prepass_frag); + MEM_freeN(composite_frag); + MEM_freeN(defines); + } +} + +static void select_deferred_shaders(WORKBENCH_PrivateData *wpd) +{ + int index_solid = workbench_material_get_shader_index(wpd, OB_SOLID); + int index_texture = workbench_material_get_shader_index(wpd, OB_TEXTURE); + + ensure_deferred_shaders(wpd, index_solid, OB_SOLID); + ensure_deferred_shaders(wpd, index_texture, OB_TEXTURE); + + wpd->prepass_solid_sh = e_data.prepass_sh_cache[index_solid]; + wpd->prepass_texture_sh = e_data.prepass_sh_cache[index_texture]; + wpd->composite_sh = e_data.composite_sh_cache[index_solid]; +} + +/* Functions */ + + +static void workbench_init_object_data(ObjectEngineData *engine_data) +{ + WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)engine_data; + data->object_id = e_data.next_object_id++; + data->shadow_bbox_dirty = true; +} + +void workbench_deferred_engine_init(WORKBENCH_Data *vedata) +{ + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + if (!e_data.next_object_id) { + memset(e_data.prepass_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); + memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); + e_data.next_object_id = 1; +#ifdef DEBUG_SHADOW_VOLUME + const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl; +#else + const char *shadow_frag = NULL; +#endif + e_data.shadow_pass_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_PASS\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_pass_manifold_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_PASS\n"); + e_data.shadow_fail_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_fail_manifold_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n"); + e_data.shadow_caps_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_caps_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_caps_manifold_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_caps_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n"); + } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + workbench_private_data_init(stl->g_data); + + { + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R32UI, &draw_engine_workbench_solid); + e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid); + e_data.composite_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid); + + if (NORMAL_ENCODING_ENABLED()) { + e_data.normal_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RG16, &draw_engine_workbench_solid); + } + else { + e_data.normal_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA32F, &draw_engine_workbench_solid); + } + + GPU_framebuffer_ensure_config(&fbl->prepass_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), + GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx), + GPU_ATTACHMENT_TEXTURE(e_data.normal_buffer_tx), + }); + GPU_framebuffer_ensure_config(&fbl->composite_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), + }); + } + + /* Prepass */ + { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + psl->prepass_pass = DRW_pass_create("Prepass", state); + } +} + +void workbench_deferred_engine_free() +{ + for (int index = 0; index < MAX_SHADERS; index++) { + DRW_SHADER_FREE_SAFE(e_data.prepass_sh_cache[index]); + DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); + } + DRW_SHADER_FREE_SAFE(e_data.shadow_pass_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_pass_manifold_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_fail_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_fail_manifold_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_caps_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_caps_manifold_sh); +} + +static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp) +{ + DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &e_data.color_buffer_tx); + DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); + if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx); + } + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + + workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix); +} + +void workbench_deferred_cache_init(WORKBENCH_Data *vedata) +{ + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + DRWShadingGroup *grp; + const DRWContextState *draw_ctx = DRW_context_state_get(); + static float light_multiplier = 1.0f; + + + Scene *scene = draw_ctx->scene; + + select_deferred_shaders(wpd); + /* Deferred Mix Pass */ + { + workbench_private_data_get_light_direction(wpd, e_data.display.light_direction); + + e_data.display.shadow_shift = scene->display.shadow_shift; + copy_v3_v3(e_data.light_direction_vs, wpd->world_data.light_direction_vs); + + if (SHADOW_ENABLED(wpd)) { + psl->composite_pass = DRW_pass_create( + "Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL); + grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); + workbench_composite_uniforms(wpd, grp); + DRW_shgroup_stencil_mask(grp, 0x00); + DRW_shgroup_uniform_float(grp, "lightMultiplier", &light_multiplier, 1); + DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1); + DRW_shgroup_uniform_float(grp, "shadowShift", &scene->display.shadow_shift, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + + /* Stencil Shadow passes. */ +#ifdef DEBUG_SHADOW_VOLUME + DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; + DRWState depth_fail_state = DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; +#else + DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS; + DRWState depth_fail_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL; +#endif + psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Pass", depth_pass_state); + psl->shadow_depth_pass_mani_pass = DRW_pass_create("Shadow Pass Mani", depth_pass_state); + psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Fail", depth_fail_state); + psl->shadow_depth_fail_mani_pass = DRW_pass_create("Shadow Fail Mani", depth_fail_state); + psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Fail Caps", depth_fail_state); + psl->shadow_depth_fail_caps_mani_pass = DRW_pass_create("Shadow Fail Caps Mani", depth_fail_state); + +#ifndef DEBUG_SHADOW_VOLUME + grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); + + psl->composite_shadow_pass = DRW_pass_create("Composite Shadow", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL); + grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_shadow_pass); + DRW_shgroup_stencil_mask(grp, 0x00); + workbench_composite_uniforms(wpd, grp); + DRW_shgroup_uniform_float(grp, "lightMultiplier", &wpd->shadow_multiplier, 1); + DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1); + DRW_shgroup_uniform_float(grp, "shadowShift", &scene->display.shadow_shift, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); +#endif + + studiolight_update_light(wpd, e_data.display.light_direction); + } + else { + psl->composite_pass = DRW_pass_create( + "Composite", DRW_STATE_WRITE_COLOR); + grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); + workbench_composite_uniforms(wpd, grp); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + } +} + +static WORKBENCH_MaterialData *get_or_create_material_data( + WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) +{ + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_MaterialData *material; + WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_object_engine_data_ensure( + ob, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL); + WORKBENCH_MaterialData material_template; + + /* Solid */ + workbench_material_get_solid_color(wpd, ob, mat, material_template.color); + material_template.object_id = engine_object_data->object_id; + material_template.drawtype = drawtype; + material_template.ima = ima; + uint hash = workbench_material_get_hash(&material_template); + + material = BLI_ghash_lookup(wpd->material_hash, SET_UINT_IN_POINTER(hash)); + if (material == NULL) { + material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); + material->shgrp = DRW_shgroup_create( + drawtype == OB_SOLID ? wpd->prepass_solid_sh : wpd->prepass_texture_sh, psl->prepass_pass); + DRW_shgroup_stencil_mask(material->shgrp, 0xFF); + material->object_id = engine_object_data->object_id; + copy_v4_v4(material->color, material_template.color); + switch (drawtype) { + case OB_SOLID: + DRW_shgroup_uniform_vec3(material->shgrp, "object_color", material->color, 1); + break; + + case OB_TEXTURE: + { + GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false); + DRW_shgroup_uniform_texture(material->shgrp, "image", tex); + break; + } + } + DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1); + BLI_ghash_insert(wpd->material_hash, SET_UINT_IN_POINTER(hash), material); + } + return material; +} + +static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *ob) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + if (ob == draw_ctx->object_edit) { + return; + } + for (ParticleSystem *psys = ob->particlesystem.first; psys != NULL; psys = psys->next) { + if (!psys_check_enabled(ob, psys, false)) { + continue; + } + if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + return; + } + ParticleSettings *part = psys->part; + const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + + static float mat[4][4]; + unit_m4(mat); + + if (draw_as == PART_DRAW_PATH) { + struct Gwn_Batch *geom = DRW_cache_particles_get_hair(ob, psys, NULL); + WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, NULL, NULL, OB_SOLID); + DRW_shgroup_call_add(material->shgrp, geom, mat); + } + } +} + +void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) +{ + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + + if (!DRW_object_is_renderable(ob)) + return; + + if (ob->type == OB_MESH) { + workbench_cache_populate_particles(vedata, ob); + } + + WORKBENCH_MaterialData *material; + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool is_active = (ob == draw_ctx->obact); + const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; + bool is_drawn = false; + if (!is_sculpt_mode && wpd->drawtype == OB_TEXTURE && ob->type == OB_MESH) { + const Mesh *me = ob->data; + if (me->mloopuv) { + const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL; + if (materials_len > 0 && geom_array) { + for (int i = 0; i < materials_len; i++) { + Material *mat = give_current_material(ob, i + 1); + Image *image; + ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); + /* use OB_SOLID when no texture could be determined */ + int mat_drawtype = OB_SOLID; + if (image) { + mat_drawtype = OB_TEXTURE; + } + material = get_or_create_material_data(vedata, ob, mat, image, mat_drawtype); + DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); + } + is_drawn = true; + } + } + } + + /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */ + if (!is_drawn) { + if ((wpd->shading.color_type != V3D_SHADING_MATERIAL_COLOR) || is_sculpt_mode) { + /* No material split needed */ + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + material = get_or_create_material_data(vedata, ob, NULL, NULL, OB_SOLID); + if (is_sculpt_mode) { + DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); + } + else { + DRW_shgroup_call_object_add(material->shgrp, geom, ob); + } + } + } + else { /* MATERIAL colors */ + const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + for (int i = 0; i < materials_len; i++) { + gpumat_array[i] = NULL; + } + + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, NULL, NULL, NULL); + if (mat_geom) { + for (int i = 0; i < materials_len; ++i) { + Material *mat = give_current_material(ob, i + 1); + material = get_or_create_material_data(vedata, ob, mat, NULL, OB_SOLID); + DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + } + } + } + } + + if (SHADOW_ENABLED(wpd) && (ob->display.flag & OB_SHOW_SHADOW) > 0) { + bool is_manifold; + struct Gwn_Batch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold); + if (geom_shadow) { + if (is_sculpt_mode) { + /* Currently unsupported in sculpt mode. We could revert to the slow + * method in this case but i'm not sure if it's a good idea given that + * sculped meshes are heavy to begin with. */ + // DRW_shgroup_call_sculpt_add(wpd->shadow_shgrp, ob, ob->obmat); + } + else { + WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_object_engine_data_ensure( + ob, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL); + + if (studiolight_object_cast_visible_shadow(wpd, ob, engine_object_data)) { + + invert_m4_m4(ob->imat, ob->obmat); + mul_v3_mat3_m4v3(engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction); + + DRWShadingGroup *grp; + bool use_shadow_pass_technique = !studiolight_camera_in_object_shadow(wpd, ob, engine_object_data); + + /* Unless we expose a parameter to the user, it's better to use the depth pass technique if the object is + * non manifold. Exposing a switch to the user to force depth fail in this case can be beneficial for + * planes and non-closed terrains. */ + if (!is_manifold) { + use_shadow_pass_technique = true; + } + + if (use_shadow_pass_technique) { + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); +#ifdef DEBUG_SHADOW_VOLUME + DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){1.0f, 0.0f, 0.0f, 1.0f}); +#endif + } + else { + /* TODO(fclem): only use caps if they are in the view frustum. */ + const bool need_caps = true; + if (need_caps) { + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_call_add(grp, DRW_cache_object_surface_get(ob), ob->obmat); + } + + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); +#ifdef DEBUG_SHADOW_VOLUME + DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){0.0f, 1.0f, 0.0f, 1.0f}); +#endif + } + } + } + } + } + } +} + +void workbench_deferred_cache_finish(WORKBENCH_Data *UNUSED(vedata)) +{ +} + +void workbench_deferred_draw_background(WORKBENCH_Data *vedata) +{ + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PrivateData *wpd = stl->g_data; + const float clear_depth = 1.0f; + const float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + uint clear_stencil = 0xFF; + + DRW_stats_group_start("Clear Background"); + GPU_framebuffer_bind(fbl->prepass_fb); + int clear_bits = GPU_DEPTH_BIT | GPU_COLOR_BIT; + SET_FLAG_FROM_TEST(clear_bits, SHADOW_ENABLED(wpd), GPU_STENCIL_BIT); + GPU_framebuffer_clear(fbl->prepass_fb, clear_bits, clear_color, clear_depth, clear_stencil); + DRW_stats_group_end(); +} + +void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) +{ + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PrivateData *wpd = stl->g_data; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + /* clear in background */ + GPU_framebuffer_bind(fbl->prepass_fb); + DRW_draw_pass(psl->prepass_pass); + if (SHADOW_ENABLED(wpd)) { +#ifdef DEBUG_SHADOW_VOLUME + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->composite_pass); +#else + GPU_framebuffer_bind(dfbl->depth_only_fb); +#endif + DRW_draw_pass(psl->shadow_depth_pass_pass); + DRW_draw_pass(psl->shadow_depth_pass_mani_pass); + DRW_draw_pass(psl->shadow_depth_fail_pass); + DRW_draw_pass(psl->shadow_depth_fail_mani_pass); + DRW_draw_pass(psl->shadow_depth_fail_caps_pass); + DRW_draw_pass(psl->shadow_depth_fail_caps_mani_pass); +#ifndef DEBUG_SHADOW_VOLUME + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->composite_pass); + DRW_draw_pass(psl->composite_shadow_pass); +#endif + } + else { + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->composite_pass); + } + + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_transform_to_display(e_data.composite_buffer_tx); + + workbench_private_data_free(wpd); +} diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c new file mode 100644 index 00000000000..26ae1c289c8 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -0,0 +1,47 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file workbench_engine.c + * \ingroup draw_engine + * + * Simple engine for drawing color and/or depth. + * When we only need simple flat shaders. + */ + +#include "DRW_render.h" + +#include "workbench_engine.h" +/* Shaders */ + +#define WORKBENCH_ENGINE "BLENDER_WORKBENCH" + + +/* Note: currently unused, we may want to register so we can see this when debugging the view. */ +RenderEngineType DRW_engine_viewport_workbench_type = { + NULL, NULL, + WORKBENCH_ENGINE, N_("Workbench"), RE_INTERNAL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &draw_engine_workbench_solid, + {NULL, NULL, NULL} +}; + + +#undef WORKBENCH_ENGINE diff --git a/source/blender/draw/engines/workbench/workbench_engine.h b/source/blender/draw/engines/workbench/workbench_engine.h new file mode 100644 index 00000000000..a7f168db093 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_engine.h @@ -0,0 +1,33 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file workbench_engine.h + * \ingroup draw_engine + */ + +#ifndef __WORKBENCH_ENGINE_H__ +#define __WORKBENCH_ENGINE_H__ + +extern DrawEngineType draw_engine_workbench_solid; +extern DrawEngineType draw_engine_workbench_transparent; +extern RenderEngineType DRW_engine_viewport_workbench_type; + +#endif /* __WORKBENCH_ENGINE_H__ */ diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c new file mode 100644 index 00000000000..4ba6ee3fdc9 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -0,0 +1,565 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file workbench_forward.c + * \ingroup draw_engine + */ + +#include "workbench_private.h" + +#include "BIF_gl.h" + +#include "BLI_alloca.h" +#include "BLI_dynstr.h" +#include "BLI_utildefines.h" + +#include "BKE_node.h" +#include "BKE_particle.h" + +#include "DNA_image_types.h" +#include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_node_types.h" + +#include "ED_uvedit.h" + +#include "GPU_shader.h" +#include "GPU_texture.h" + +#include "UI_resources.h" + +/* *********** STATIC *********** */ +static struct { + struct GPUShader *composite_sh_cache[MAX_SHADERS]; + struct GPUShader *transparent_accum_sh_cache[MAX_SHADERS]; + struct GPUShader *transparent_revealage_sh; + struct GPUShader *object_outline_sh; + struct GPUShader *depth_sh; + struct GPUShader *checker_depth_sh; + + struct GPUTexture *object_id_tx; /* ref only, not alloced */ + struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */ +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */ +#endif + struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ + int next_object_id; + float normal_world_matrix[3][3]; +} e_data = {{NULL}}; + +/* Shaders */ +extern char datatoc_workbench_forward_composite_frag_glsl[]; +extern char datatoc_workbench_forward_depth_frag_glsl[]; +extern char datatoc_workbench_forward_transparent_accum_frag_glsl[]; +#ifdef WORKBENCH_REVEALAGE_ENABLED +extern char datatoc_workbench_forward_transparent_revealage_frag_glsl[]; +#endif +extern char datatoc_workbench_data_lib_glsl[]; +extern char datatoc_workbench_background_lib_glsl[]; +extern char datatoc_workbench_checkerboard_depth_frag_glsl[]; +extern char datatoc_workbench_object_outline_lib_glsl[]; +extern char datatoc_workbench_prepass_vert_glsl[]; +extern char datatoc_workbench_common_lib_glsl[]; +extern char datatoc_workbench_world_light_lib_glsl[]; + +/* static functions */ +static char *workbench_build_forward_depth_frag(void) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_forward_depth_frag_glsl); + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} + +static char *workbench_build_forward_transparent_accum_frag(void) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_forward_transparent_accum_frag_glsl); + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} + +#ifdef WORKBENCH_REVEALAGE_ENABLED +static char *workbench_build_forward_transparent_revealage_frag(void) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_forward_transparent_revealage_frag_glsl); + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} +#endif + +static char *workbench_build_forward_composite_frag(void) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_object_outline_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_forward_composite_frag_glsl); + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} + +static void workbench_init_object_data(ObjectEngineData *engine_data) +{ + WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)engine_data; + data->object_id = e_data.next_object_id++; +} + +static WORKBENCH_MaterialData *get_or_create_material_data( + WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) +{ + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = stl->g_data; + WORKBENCH_MaterialData *material; + WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_object_engine_data_ensure( + ob, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL); + WORKBENCH_MaterialData material_template; + DRWShadingGroup *grp; + + /* Solid */ + workbench_material_get_solid_color(wpd, ob, mat, material_template.color); + material_template.object_id = engine_object_data->object_id; + material_template.drawtype = drawtype; + material_template.ima = ima; + uint hash = workbench_material_get_hash(&material_template); + + material = BLI_ghash_lookup(wpd->material_hash, SET_UINT_IN_POINTER(hash)); + if (material == NULL) { + material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); + + /* transparent accum */ + grp = DRW_shgroup_create( + drawtype == OB_SOLID ? wpd->transparent_accum_sh : wpd->transparent_accum_texture_sh, + psl->transparent_accum_pass); + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix); + copy_v4_v4(material->color, material_template.color); + switch (drawtype) { + case OB_SOLID: + DRW_shgroup_uniform_vec4(grp, "color", material->color, 1); + break; + + case OB_TEXTURE: + { + GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false); + DRW_shgroup_uniform_texture(grp, "image", tex); + break; + } + } + material->shgrp = grp; + + /* Depth */ + material->shgrp_object_outline = DRW_shgroup_create(e_data.object_outline_sh, psl->object_outline_pass); + material->object_id = engine_object_data->object_id; + DRW_shgroup_uniform_int(material->shgrp_object_outline, "object_id", &material->object_id, 1); + BLI_ghash_insert(wpd->material_hash, SET_UINT_IN_POINTER(hash), material); + } + return material; +} + +static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, int drawtype) +{ + if (e_data.composite_sh_cache[index] == NULL && drawtype == OB_SOLID) { + char *defines = workbench_material_build_defines(wpd, drawtype); + char *composite_frag = workbench_build_forward_composite_frag(); + e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); + MEM_freeN(composite_frag); + MEM_freeN(defines); + } + + if (e_data.transparent_accum_sh_cache[index] == NULL) { + char *defines = workbench_material_build_defines(wpd, drawtype); + char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag(); + e_data.transparent_accum_sh_cache[index] = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, transparent_accum_frag, defines); + MEM_freeN(transparent_accum_frag); + + MEM_freeN(defines); + } +} + +static void select_forward_shaders(WORKBENCH_PrivateData *wpd) +{ + int index_solid = workbench_material_get_shader_index(wpd, OB_SOLID); + int index_texture = workbench_material_get_shader_index(wpd, OB_TEXTURE); + + ensure_forward_shaders(wpd, index_solid, OB_SOLID); + ensure_forward_shaders(wpd, index_texture, OB_TEXTURE); + + wpd->composite_sh = e_data.composite_sh_cache[index_solid]; + wpd->transparent_accum_sh = e_data.transparent_accum_sh_cache[index_solid]; + wpd->transparent_accum_texture_sh = e_data.transparent_accum_sh_cache[index_texture]; +} + +/* public functions */ +void workbench_forward_engine_init(WORKBENCH_Data *vedata) +{ + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_StorageList *stl = vedata->stl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + DRWShadingGroup *grp; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + WORKBENCH_PrivateData *wpd = stl->g_data; + workbench_private_data_init(wpd); + float light_direction[3]; + workbench_private_data_get_light_direction(wpd, light_direction); + + if (!e_data.next_object_id) { + e_data.next_object_id = 1; + memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); + memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); + + char *defines = workbench_material_build_defines(wpd, OB_SOLID); + char *forward_depth_frag = workbench_build_forward_depth_frag(); + e_data.object_outline_sh = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, forward_depth_frag, defines); + +#ifdef WORKBENCH_REVEALAGE_ENABLED + char *forward_transparent_revealage_frag = workbench_build_forward_transparent_revealage_frag(); + e_data.transparent_revealage_sh = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, forward_transparent_revealage_frag, defines); + MEM_freeN(forward_transparent_revealage_frag); +#endif + + e_data.depth_sh = DRW_shader_create_3D_depth_only(); + e_data.checker_depth_sh = DRW_shader_create_fullscreen( + datatoc_workbench_checkerboard_depth_frag_glsl, NULL); + MEM_freeN(forward_depth_frag); + MEM_freeN(defines); + } + select_forward_shaders(wpd); + + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + e_data.object_id_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_R32UI, &draw_engine_workbench_transparent); + e_data.transparent_accum_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); +#ifdef WORKBENCH_REVEALAGE_ENABLED + e_data.transparent_revealage_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_R16F, &draw_engine_workbench_transparent); +#endif + e_data.composite_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); + GPU_framebuffer_ensure_config(&fbl->object_outline_fb, { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), + }); + GPU_framebuffer_ensure_config(&fbl->transparent_accum_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx), + }); + +#ifdef WORKBENCH_REVEALAGE_ENABLED + GPU_framebuffer_ensure_config(&fbl->transparent_revealage_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.transparent_revealage_tx), + }); +#endif + + GPU_framebuffer_ensure_config(&fbl->composite_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), + }); + const float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + DRW_stats_group_start("Clear Buffers"); + GPU_framebuffer_bind(fbl->transparent_accum_fb); + GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); + +#ifdef WORKBENCH_REVEALAGE_ENABLED + const float clear_color1[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + GPU_framebuffer_bind(fbl->transparent_revealage_fb); + GPU_framebuffer_clear_color(fbl->transparent_revealage_fb, clear_color1); +#endif + GPU_framebuffer_bind(fbl->object_outline_fb); + GPU_framebuffer_clear_color_depth(fbl->object_outline_fb, clear_color, 1.0f); + DRW_stats_group_end(); + + /* Treansparecy Accum */ + { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL; + psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state); + } + +#ifdef WORKBENCH_REVEALAGE_ENABLED + /* Treansparecy Revealage */ + { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSPARENT_REVEALAGE; + psl->transparent_revealage_pass = DRW_pass_create("Transparent Revealage", state); + grp = DRW_shgroup_create(e_data.transparent_revealage_sh, psl->transparent_revealage_pass); + wpd->transparent_revealage_shgrp = grp; + } +#endif + + /* Depth */ + { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; + psl->object_outline_pass = DRW_pass_create("Object Outline Pass", state); + } + /* Composite */ + { + int state = DRW_STATE_WRITE_COLOR; + psl->composite_pass = DRW_pass_create("Composite", state); + + grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); + DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); + DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.transparent_accum_tx); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.transparent_revealage_tx); +#endif + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + /* Checker Depth */ + { + int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS; + psl->checker_depth_pass = DRW_pass_create("Checker Depth", state); + grp = DRW_shgroup_create(e_data.checker_depth_sh, psl->checker_depth_pass); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } +} + +void workbench_forward_engine_free() +{ + for (int index = 0; index < MAX_SHADERS; index++) { + DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); + DRW_SHADER_FREE_SAFE(e_data.transparent_accum_sh_cache[index]); + } +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_SHADER_FREE_SAFE(e_data.transparent_revealage_sh); +#endif + DRW_SHADER_FREE_SAFE(e_data.object_outline_sh); + DRW_SHADER_FREE_SAFE(e_data.checker_depth_sh); +} + +void workbench_forward_cache_init(WORKBENCH_Data *UNUSED(vedata)) +{ +} + +static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, Object *ob) +{ +#ifdef WORKBENCH_REVEALAGE_ENABLED + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; +#endif + const DRWContextState *draw_ctx = DRW_context_state_get(); + if (ob == draw_ctx->object_edit) { + return; + } + for (ParticleSystem *psys = ob->particlesystem.first; psys != NULL; psys = psys->next) { + if (!psys_check_enabled(ob, psys, false)) { + continue; + } + if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + return; + } + ParticleSettings *part = psys->part; + const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + + static float mat[4][4]; + unit_m4(mat); + + if (draw_as == PART_DRAW_PATH) { + struct Gwn_Batch *geom = DRW_cache_particles_get_hair(ob, psys, NULL); + WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, NULL, NULL, OB_SOLID); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_add(wpd->transparent_revealage_shgrp, geom, mat); +#endif + DRW_shgroup_call_add(material->shgrp_object_outline, geom, mat); + DRW_shgroup_call_add(material->shgrp, geom, mat); + } + } +} + +void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) +{ + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; + + if (!DRW_object_is_renderable(ob)) + return; + + if (ob->type == OB_MESH) { + workbench_forward_cache_populate_particles(vedata, ob); + } + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool is_active = (ob == draw_ctx->obact); + const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0; + bool is_drawn = false; + + WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, NULL, NULL, OB_SOLID); + if (!is_sculpt_mode && wpd->drawtype == OB_TEXTURE && ob->type == OB_MESH) { + const Mesh *me = ob->data; + if (me->mloopuv) { + const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL; + if (materials_len > 0 && geom_array) { + for (int i = 0; i < materials_len; i++) { + Material *mat = give_current_material(ob, i + 1); + Image *image; + ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); + /* use OB_SOLID when no texture could be determined */ + int mat_drawtype = OB_SOLID; + if (image) { + mat_drawtype = OB_TEXTURE; + } + material = get_or_create_material_data(vedata, ob, mat, image, mat_drawtype); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, geom_array[i], ob); +#endif + DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); + DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); + } + is_drawn = true; + } + } + } + + /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */ + if (!is_drawn) { + if ((wpd->shading.color_type != V3D_SHADING_MATERIAL_COLOR) || is_sculpt_mode) { + /* No material split needed */ + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + if (is_sculpt_mode) { +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_sculpt_add(wpd->transparent_revealage_shgrp, ob, ob->obmat); +#endif + DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); + DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); + } + else { +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, geom, ob); +#endif + DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob); + DRW_shgroup_call_object_add(material->shgrp, geom, ob); + } + } + } + else { + const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + for (int i = 0; i < materials_len; i++) { + gpumat_array[i] = NULL; + } + + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, NULL, NULL, NULL); + if (mat_geom) { + for (int i = 0; i < materials_len; ++i) { + Material *mat = give_current_material(ob, i + 1); + material = get_or_create_material_data(vedata, ob, mat, NULL, OB_SOLID); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, mat_geom[i], ob); +#endif + DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob); + DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + } + } + } + } + } +} + +void workbench_forward_cache_finish(WORKBENCH_Data *UNUSED(vedata)) +{ +} + +void workbench_forward_draw_background(WORKBENCH_Data *UNUSED(vedata)) +{ + const float clear_depth = 1.0f; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DRW_stats_group_start("Clear Background"); + GPU_framebuffer_bind(dfbl->default_fb); + GPU_framebuffer_clear_depth(dfbl->default_fb, clear_depth); + DRW_stats_group_end(); +} + +void workbench_forward_draw_scene(WORKBENCH_Data *vedata) +{ + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PrivateData *wpd = stl->g_data; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + /* Write Depth + Object ID */ + GPU_framebuffer_bind(fbl->object_outline_fb); + DRW_draw_pass(psl->object_outline_pass); + + /* Shade */ + GPU_framebuffer_bind(fbl->transparent_accum_fb); + DRW_draw_pass(psl->transparent_accum_pass); +#ifdef WORKBENCH_REVEALAGE_ENABLED + GPU_framebuffer_bind(fbl->transparent_revealage_fb); + DRW_draw_pass(psl->transparent_revealage_pass); +#endif + /* Composite */ + GPU_framebuffer_bind(fbl->composite_fb); + DRW_draw_pass(psl->composite_pass); + + /* Color correct */ + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_transform_to_display(e_data.composite_buffer_tx); + + GPU_framebuffer_bind(dfbl->depth_only_fb); + DRW_draw_pass(psl->checker_depth_pass); + + workbench_private_data_free(wpd); +} diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c new file mode 100644 index 00000000000..fb9b73c48b0 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -0,0 +1,137 @@ + + +#include "workbench_private.h" + +#include "BLI_dynstr.h" + +#define HSV_SATURATION 0.5 +#define HSV_VALUE 0.9 + +void workbench_material_get_solid_color(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, float *color) +{ + /* When in OB_TEXTURE always uyse V3D_SHADING_MATERIAL_COLOR as fallback when no texture could be determined */ + int color_type = wpd->drawtype == OB_SOLID ? wpd->shading.color_type : V3D_SHADING_MATERIAL_COLOR; + static float default_color[] = {0.8f, 0.8f, 0.8f, 1.0f}; + color[3] = 1.0f; + if (DRW_object_is_paint_mode(ob) || color_type == V3D_SHADING_SINGLE_COLOR) { + copy_v3_v3(color, wpd->shading.single_color); + } + else if (color_type == V3D_SHADING_RANDOM_COLOR) { + uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name); + if (ob->id.lib) { + hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name); + } + float offset = fmodf((hash / 100000.0) * M_GOLDEN_RATION_CONJUGATE, 1.0); + + float hsv[3] = {offset, HSV_SATURATION, HSV_VALUE}; + hsv_to_rgb_v(hsv, color); + } + else { + /* V3D_SHADING_MATERIAL_COLOR */ + if (mat) { + copy_v3_v3(color, &mat->r); + } + else { + copy_v3_v3(color, default_color); + } + } +} + +char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, int drawtype) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) { + BLI_dynstr_appendf(ds, "#define V3D_SHADING_OBJECT_OUTLINE\n"); + } + if (wpd->shading.flag & V3D_SHADING_SHADOW) { + BLI_dynstr_appendf(ds, "#define V3D_SHADING_SHADOW\n"); + } + if (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) { + BLI_dynstr_appendf(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n"); + } + if (wpd->shading.light & V3D_LIGHTING_STUDIO) { + BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_STUDIO\n"); + if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) { + BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_WORLD\n"); + } + else { + BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_CAMERA\n"); + } + } + if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) { + BLI_dynstr_appendf(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n"); + } + switch (drawtype) { + case OB_SOLID: + BLI_dynstr_appendf(ds, "#define OB_SOLID\n"); + break; + case OB_TEXTURE: + BLI_dynstr_appendf(ds, "#define OB_TEXTURE\n"); + break; + } + + if (NORMAL_ENCODING_ENABLED()) { + BLI_dynstr_appendf(ds, "#define WORKBENCH_ENCODE_NORMALS\n"); + } + +#ifdef WORKBENCH_REVEALAGE_ENABLED + BLI_dynstr_appendf(ds, "#define WORKBENCH_REVEALAGE_ENABLED\n"); +#endif + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} + +uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template) +{ + /* TODO: make a C-string with settings and hash the string */ + uint input[4]; + uint result; + float *color = material_template->color; + input[0] = (uint)(color[0] * 512); + input[1] = (uint)(color[1] * 512); + input[2] = (uint)(color[2] * 512); + input[3] = material_template->object_id; + result = BLI_ghashutil_uinthash_v4_murmur(input); + + if (material_template->drawtype == OB_TEXTURE) { + /* add texture reference */ + result += BLI_ghashutil_inthash_p_murmur(material_template->ima); + } + return result; +} + +int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype) +{ + const int DRAWOPTIONS_MASK = V3D_SHADING_OBJECT_OUTLINE | V3D_SHADING_SHADOW | V3D_SHADING_SPECULAR_HIGHLIGHT; + int index = (wpd->shading.flag & DRAWOPTIONS_MASK); + index = (index << 2) + wpd->shading.light; + index = (index << 2); + /* set the drawtype flag + 0 = OB_SOLID, + 1 = OB_TEXTURE + 2 = STUDIOLIGHT_ORIENTATION_WORLD + */ + SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD, 2); + SET_FLAG_FROM_TEST(index, drawtype == OB_TEXTURE, 1); + return index; +} + +void workbench_material_set_normal_world_matrix( + DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]) +{ + if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) { + float view_matrix_inverse[4][4]; + float rot_matrix[4][4]; + float matrix[4][4]; + axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z); + DRW_viewport_matrix_get(view_matrix_inverse, DRW_MAT_VIEWINV); + mul_m4_m4m4(matrix, rot_matrix, view_matrix_inverse); + copy_m3_m4(persistent_matrix, matrix); + DRW_shgroup_uniform_mat3(grp, "normalWorldMatrix", persistent_matrix); + } +} diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h new file mode 100644 index 00000000000..54cf82c59bb --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -0,0 +1,221 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file workbench_private.h + * \ingroup draw_engine + */ + +#ifndef __WORKBENCH_PRIVATE_H__ +#define __WORKBENCH_PRIVATE_H__ + + +#include "BKE_studiolight.h" + +#include "DNA_image_types.h" +#include "DNA_view3d_types.h" + +#include "DRW_render.h" + + +#define WORKBENCH_ENGINE "BLENDER_WORKBENCH" +#define M_GOLDEN_RATION_CONJUGATE 0.618033988749895 +#define MAX_SHADERS 512 + + +#define OBJECT_ID_PASS_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) +#define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW) +#define SPECULAR_HIGHLIGHT_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) +#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (wpd->shading.light & V3D_LIGHTING_STUDIO || SHADOW_ENABLED(wpd) || SPECULAR_HIGHLIGHT_ENABLED (wpd)) +#define NORMAL_ENCODING_ENABLED() (true) +#define WORKBENCH_REVEALAGE_ENABLED +#define STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd) (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD) + + +typedef struct WORKBENCH_FramebufferList { + /* Deferred render buffers */ + struct GPUFrameBuffer *prepass_fb; + struct GPUFrameBuffer *composite_fb; + + /* Forward render buffers */ + struct GPUFrameBuffer *object_outline_fb; + struct GPUFrameBuffer *transparent_accum_fb; + +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct GPUFrameBuffer *transparent_revealage_fb; +#endif +} WORKBENCH_FramebufferList; + +typedef struct WORKBENCH_StorageList { + struct WORKBENCH_PrivateData *g_data; +} WORKBENCH_StorageList; + +typedef struct WORKBENCH_PassList { + /* deferred rendering */ + struct DRWPass *prepass_pass; + struct DRWPass *shadow_depth_pass_pass; + struct DRWPass *shadow_depth_pass_mani_pass; + struct DRWPass *shadow_depth_fail_pass; + struct DRWPass *shadow_depth_fail_mani_pass; + struct DRWPass *shadow_depth_fail_caps_pass; + struct DRWPass *shadow_depth_fail_caps_mani_pass; + struct DRWPass *composite_pass; + struct DRWPass *composite_shadow_pass; + + /* forward rendering */ + struct DRWPass *transparent_accum_pass; +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct DRWPass *transparent_revealage_pass; +#endif + struct DRWPass *object_outline_pass; + struct DRWPass *depth_pass; + struct DRWPass *checker_depth_pass; +} WORKBENCH_PassList; + +typedef struct WORKBENCH_Data { + void *engine_type; + WORKBENCH_FramebufferList *fbl; + DRWViewportEmptyList *txl; + WORKBENCH_PassList *psl; + WORKBENCH_StorageList *stl; +} WORKBENCH_Data; + +typedef struct WORKBENCH_UBO_World { + float diffuse_light_x_pos[4]; + float diffuse_light_x_neg[4]; + float diffuse_light_y_pos[4]; + float diffuse_light_y_neg[4]; + float diffuse_light_z_pos[4]; + float diffuse_light_z_neg[4]; + float background_color_low[4]; + float background_color_high[4]; + float object_outline_color[4]; + float light_direction_vs[4]; + float specular_sharpness; + float pad[3]; +} WORKBENCH_UBO_World; +BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_World, 16) + +typedef struct WORKBENCH_PrivateData { + struct GHash *material_hash; + struct GPUShader *prepass_solid_sh; + struct GPUShader *prepass_texture_sh; + struct GPUShader *composite_sh; + struct GPUShader *transparent_accum_sh; + struct GPUShader *transparent_accum_texture_sh; + View3DShading shading; + StudioLight *studio_light; + int drawtype; + struct GPUUniformBuffer *world_ubo; + struct DRWShadingGroup *shadow_shgrp; + struct DRWShadingGroup *depth_shgrp; +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct DRWShadingGroup *transparent_revealage_shgrp; +#endif + WORKBENCH_UBO_World world_data; + float shadow_multiplier; + float cached_shadow_direction[3]; + float shadow_mat[4][4]; + float shadow_inv[4][4]; + float shadow_near_corners[4][3]; /* Near plane corners in shadow space. */ + float shadow_near_min[3]; /* min and max of shadow_near_corners. allow fast test */ + float shadow_near_max[3]; + float shadow_near_sides[2][4]; /* This is a parallelogram, so only 2 normal and distance to the edges. */ + bool shadow_changed; +} WORKBENCH_PrivateData; /* Transient data */ + +typedef struct WORKBENCH_MaterialData { + /* Solid color */ + float color[4]; + int object_id; + int drawtype; + Image *ima; + + /* Linked shgroup for drawing */ + DRWShadingGroup *shgrp; + /* forward rendering */ + DRWShadingGroup *shgrp_object_outline; +} WORKBENCH_MaterialData; + +typedef struct WORKBENCH_ObjectData { + struct ObjectEngineData *next, *prev; + struct DrawEngineType *engine_type; + /* Only nested data, NOT the engine data itself. */ + ObjectEngineDataFreeCb free; + /* Accumulated recalc flags, which corresponds to ID->recalc flags. */ + int recalc; + /* Shadow direction in local object space. */ + float shadow_dir[3]; + float shadow_min[3], shadow_max[3]; /* Min, max in shadow space */ + BoundBox shadow_bbox; + bool shadow_bbox_dirty; + + int object_id; +} WORKBENCH_ObjectData; + +/* workbench_engine.c */ +void workbench_solid_materials_init(WORKBENCH_Data *vedata); +void workbench_solid_materials_cache_init(WORKBENCH_Data *vedata); +void workbench_solid_materials_cache_populate(WORKBENCH_Data *vedata, Object *ob); +void workbench_solid_materials_cache_finish(WORKBENCH_Data *vedata); +void workbench_solid_materials_draw_scene(WORKBENCH_Data *vedata); +void workbench_solid_materials_free(void); + +/* workbench_deferred.c */ +void workbench_deferred_engine_init(WORKBENCH_Data *vedata); +void workbench_deferred_engine_free(void); +void workbench_deferred_draw_background(WORKBENCH_Data *vedata); +void workbench_deferred_draw_scene(WORKBENCH_Data *vedata); +void workbench_deferred_cache_init(WORKBENCH_Data *vedata); +void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob); +void workbench_deferred_cache_finish(WORKBENCH_Data *vedata); + +/* workbench_forward.c */ +void workbench_forward_engine_init(WORKBENCH_Data *vedata); +void workbench_forward_engine_free(void); +void workbench_forward_draw_background(WORKBENCH_Data *vedata); +void workbench_forward_draw_scene(WORKBENCH_Data *vedata); +void workbench_forward_cache_init(WORKBENCH_Data *vedata); +void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob); +void workbench_forward_cache_finish(WORKBENCH_Data *vedata); + +/* workbench_materials.c */ +char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, int drawtype); +void workbench_material_get_solid_color(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, float *color); +uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template); +int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype); +void workbench_material_set_normal_world_matrix( + DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]); + +/* workbench_studiolight.c */ +void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd); +void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]); +bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); +bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); + +/* workbench_data.c */ +void workbench_private_data_init(WORKBENCH_PrivateData *wpd); +void workbench_private_data_free(WORKBENCH_PrivateData *wpd); +void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, float light_direction[3]); + +extern DrawEngineType draw_engine_workbench_solid; +extern DrawEngineType draw_engine_workbench_transparent; + +#endif diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c new file mode 100644 index 00000000000..4db89717b2a --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_studiolight.c @@ -0,0 +1,181 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file workbench_studiolight.c + * \ingroup draw_engine + */ +#include "BKE_studiolight.h" + +#include "DRW_engine.h" +#include "workbench_private.h" + +#include "BKE_object.h" + +#include "BLI_math.h" +#include "BKE_global.h" + +void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd) +{ + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED); + + copy_v3_v3(wd->diffuse_light_x_pos, sl->diffuse_light[STUDIOLIGHT_X_POS]); + copy_v3_v3(wd->diffuse_light_x_neg, sl->diffuse_light[STUDIOLIGHT_X_NEG]); + copy_v3_v3(wd->diffuse_light_y_pos, sl->diffuse_light[STUDIOLIGHT_Y_POS]); + copy_v3_v3(wd->diffuse_light_y_neg, sl->diffuse_light[STUDIOLIGHT_Y_NEG]); + copy_v3_v3(wd->diffuse_light_z_pos, sl->diffuse_light[STUDIOLIGHT_Z_POS]); + copy_v3_v3(wd->diffuse_light_z_neg, sl->diffuse_light[STUDIOLIGHT_Z_NEG]); +} + +static void compute_parallel_lines_nor_and_dist(const float v1[2], const float v2[2], const float v3[2], float r_line[2]) +{ + sub_v2_v2v2(r_line, v2, v1); + /* Find orthogonal vector. */ + SWAP(float, r_line[0], r_line[1]); + r_line[0] = -r_line[0]; + /* Edge distances. */ + r_line[2] = dot_v2v2(r_line, v1); + r_line[3] = dot_v2v2(r_line, v3); + /* Make sure r_line[2] is the minimum. */ + if (r_line[2] > r_line[3]) { + SWAP(float, r_line[2], r_line[3]); + } +} + +void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]) +{ + wpd->shadow_changed = !compare_v3v3(wpd->cached_shadow_direction, light_direction, 1e-5f); + + if (wpd->shadow_changed) { + float up[3] = {0.0f, 0.0f, 1.0f}; + unit_m4(wpd->shadow_mat); + + /* TODO fix singularity. */ + copy_v3_v3(wpd->shadow_mat[2], light_direction); + cross_v3_v3v3(wpd->shadow_mat[0], wpd->shadow_mat[2], up); + normalize_v3(wpd->shadow_mat[0]); + cross_v3_v3v3(wpd->shadow_mat[1], wpd->shadow_mat[2], wpd->shadow_mat[0]); + + invert_m4_m4(wpd->shadow_inv, wpd->shadow_mat); + + copy_v3_v3(wpd->cached_shadow_direction, light_direction); + + } + + BoundBox frustum_corners; + DRW_culling_frustum_corners_get(&frustum_corners); + + mul_v3_mat3_m4v3(wpd->shadow_near_corners[0], wpd->shadow_inv, frustum_corners.vec[0]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[1], wpd->shadow_inv, frustum_corners.vec[3]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[2], wpd->shadow_inv, frustum_corners.vec[7]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[3], wpd->shadow_inv, frustum_corners.vec[4]); + + INIT_MINMAX(wpd->shadow_near_min, wpd->shadow_near_max); + for (int i = 0; i < 4; ++i) { + minmax_v3v3_v3(wpd->shadow_near_min, wpd->shadow_near_max, wpd->shadow_near_corners[i]); + } + + compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[0], wpd->shadow_near_corners[1], wpd->shadow_near_corners[2], wpd->shadow_near_sides[0]); + compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[1], wpd->shadow_near_corners[2], wpd->shadow_near_corners[0], wpd->shadow_near_sides[1]); +} + +static BoundBox *studiolight_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +{ + if ((oed->shadow_bbox_dirty) || (wpd->shadow_changed)) { + float tmp_mat[4][4]; + mul_m4_m4m4(tmp_mat, wpd->shadow_inv, ob->obmat); + + /* Get AABB in shadow space. */ + INIT_MINMAX(oed->shadow_min, oed->shadow_max); + + /* From object space to shadow space */ + BoundBox *bbox = BKE_object_boundbox_get(ob); + for (int i = 0; i < 8; ++i) { + float corner[3]; + mul_v3_m4v3(corner, tmp_mat, bbox->vec[i]); + minmax_v3v3_v3(oed->shadow_min, oed->shadow_max, corner); + } + /* Extend towards infinity. */ + oed->shadow_max[2] += 1e4; + + /* Get extended AABB in world space. */ + BKE_boundbox_init_from_minmax(&oed->shadow_bbox, oed->shadow_min, oed->shadow_max); + for (int i = 0; i < 8; ++i) { + mul_m4_v3(wpd->shadow_mat, oed->shadow_bbox.vec[i]); + } + } + + return &oed->shadow_bbox; +} + +bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +{ + BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed); + return DRW_culling_box_test(shadow_bbox); +} + +bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +{ + /* Just to be sure the min, max are updated. */ + studiolight_object_shadow_bbox_get(wpd, ob, oed); + + /* Test if near plane is in front of the shadow. */ + if (oed->shadow_min[2] > wpd->shadow_near_max[2]) { + return false; + } + + /* Separation Axis Theorem test */ + + /* Test bbox sides first (faster) */ + if ((oed->shadow_min[0] > wpd->shadow_near_max[0]) || + (oed->shadow_max[0] < wpd->shadow_near_min[0]) || + (oed->shadow_min[1] > wpd->shadow_near_max[1]) || + (oed->shadow_max[1] < wpd->shadow_near_min[1])) + { + return false; + } + + /* Test projected near rectangle sides */ + float pts[4][2] = { + {oed->shadow_min[0], oed->shadow_min[1]}, + {oed->shadow_min[0], oed->shadow_max[1]}, + {oed->shadow_max[0], oed->shadow_min[1]}, + {oed->shadow_max[0], oed->shadow_max[1]} + }; + + for (int i = 0; i < 2; ++i) { + float min_dst = FLT_MAX, max_dst = -FLT_MAX; + for (int j = 0; j < 4; ++j) { + float dst = dot_v2v2(wpd->shadow_near_sides[i], pts[j]); + /* Do min max */ + if (min_dst > dst) min_dst = dst; + if (max_dst < dst) max_dst = dst; + } + + if ((wpd->shadow_near_sides[i][2] > max_dst) || + (wpd->shadow_near_sides[i][3] < min_dst)) + { + return false; + } + } + + /* No separation axis found. Both shape intersect. */ + return true; +} diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h new file mode 100644 index 00000000000..44fb71a231b --- /dev/null +++ b/source/blender/draw/intern/DRW_render.h @@ -0,0 +1,560 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file DRW_render.h + * \ingroup draw + */ + +/* This is the Render Functions used by Realtime engines to draw with OpenGL */ + +#ifndef __DRW_RENDER_H__ +#define __DRW_RENDER_H__ + +#include "BLI_listbase.h" +#include "BLI_math_matrix.h" +#include "BLI_math_vector.h" +#include "BLI_string.h" + +#include "BKE_context.h" +#include "BKE_layer.h" +#include "BKE_material.h" +#include "BKE_scene.h" + +#include "BLT_translation.h" + +#include "DNA_object_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_scene_types.h" + +#include "GPU_framebuffer.h" +#include "GPU_texture.h" +#include "GPU_shader.h" + +#include "draw_common.h" +#include "draw_cache.h" +#include "draw_view.h" + +#include "draw_manager_profiling.h" + +#include "MEM_guardedalloc.h" + +#include "RE_engine.h" + +#include "DEG_depsgraph.h" + +struct rcti; +struct bContext; +struct GPUFrameBuffer; +struct GPUShader; +struct GPUMaterial; +struct GPUTexture; +struct GPUUniformBuffer; +struct Object; +struct Gwn_Batch; +struct DefaultFramebufferList; +struct DefaultTextureList; +struct DRWTextStore; +struct LampEngineData; +struct ParticleSystem; +struct RenderEngineType; +struct ViewportEngineData; +struct ViewportEngineData_Info; + +typedef struct DRWUniform DRWUniform; +typedef struct DRWInterface DRWInterface; +typedef struct DRWPass DRWPass; +typedef struct DRWShadingGroup DRWShadingGroup; + +/* TODO Put it somewhere else? */ +typedef struct BoundSphere { + float center[3], radius; +} BoundSphere; + +/* declare members as empty (unused) */ +typedef char DRWViewportEmptyList; + +#define DRW_VIEWPORT_LIST_SIZE(list) \ + (sizeof(list) == sizeof(DRWViewportEmptyList) ? 0 : ((sizeof(list)) / sizeof(void *))) + +/* Unused members must be either pass list or 'char *' when not usd. */ +#define DRW_VIEWPORT_DATA_SIZE(ty) { \ + DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->fbl)), \ + DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->txl)), \ + DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->psl)), \ + DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->stl)) \ +} + +/* Use of multisample framebuffers. */ +#define MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl) { \ + if (dfbl->multisample_fb != NULL) { \ + DRW_stats_query_start("Multisample Blit"); \ + GPU_framebuffer_bind(dfbl->multisample_fb); \ + /* TODO clear only depth but need to do alpha to coverage for transparencies. */ \ + GPU_framebuffer_clear_color_depth(dfbl->multisample_fb, (const float[4]){0.0f}, 1.0f); \ + DRW_stats_query_end(); \ + } \ +} + +#define MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl) { \ + if (dfbl->multisample_fb != NULL) { \ + DRW_stats_query_start("Multisample Resolve"); \ + GPU_framebuffer_bind(dfbl->default_fb); \ + DRW_multisamples_resolve(dtxl->multisample_depth, dtxl->multisample_color); \ + DRW_stats_query_end(); \ + } \ +} + + + +typedef struct DrawEngineDataSize { + int fbl_len; + int txl_len; + int psl_len; + int stl_len; +} DrawEngineDataSize; + +typedef struct DrawEngineType { + struct DrawEngineType *next, *prev; + + char idname[32]; + + const DrawEngineDataSize *vedata_size; + + void (*engine_init)(void *vedata); + void (*engine_free)(void); + + void (*cache_init)(void *vedata); + void (*cache_populate)(void *vedata, struct Object *ob); + void (*cache_finish)(void *vedata); + + void (*draw_background)(void *vedata); + void (*draw_scene)(void *vedata); + + void (*view_update)(void *vedata); + void (*id_update)(void *vedata, struct ID *id); + + void (*render_to_image)( + void *vedata, struct RenderEngine *engine, + struct RenderLayer *layer, const struct rcti *rect); +} DrawEngineType; + +#ifndef __DRW_ENGINE_H__ +/* Buffer and textures used by the viewport by default */ +typedef struct DefaultFramebufferList { + struct GPUFrameBuffer *default_fb; + struct GPUFrameBuffer *color_only_fb; + struct GPUFrameBuffer *depth_only_fb; + struct GPUFrameBuffer *multisample_fb; +} DefaultFramebufferList; + +typedef struct DefaultTextureList { + struct GPUTexture *color; + struct GPUTexture *depth; + struct GPUTexture *multisample_color; + struct GPUTexture *multisample_depth; +} DefaultTextureList; +#endif + +/* Textures */ +typedef enum { + DRW_TEX_FILTER = (1 << 0), + DRW_TEX_WRAP = (1 << 1), + DRW_TEX_COMPARE = (1 << 2), + DRW_TEX_MIPMAP = (1 << 3), +} DRWTextureFlag; + +/* Textures from DRW_texture_pool_query_* have the options + * DRW_TEX_FILTER for color float textures, and no options + * for depth textures and integer textures. */ +struct GPUTexture *DRW_texture_pool_query_2D(int w, int h, GPUTextureFormat format, DrawEngineType *engine_type); + +struct GPUTexture *DRW_texture_create_1D( + int w, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels); +struct GPUTexture *DRW_texture_create_2D( + int w, int h, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels); +struct GPUTexture *DRW_texture_create_2D_array( + int w, int h, int d, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels); +struct GPUTexture *DRW_texture_create_3D( + int w, int h, int d, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels); +struct GPUTexture *DRW_texture_create_cube( + int w, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels); + +void DRW_texture_ensure_fullscreen_2D( + struct GPUTexture **tex, GPUTextureFormat format, DRWTextureFlag flags); +void DRW_texture_ensure_2D( + struct GPUTexture **tex, int w, int h, GPUTextureFormat format, DRWTextureFlag flags); + +void DRW_texture_generate_mipmaps(struct GPUTexture *tex); +void DRW_texture_free(struct GPUTexture *tex); +#define DRW_TEXTURE_FREE_SAFE(tex) do { \ + if (tex != NULL) { \ + DRW_texture_free(tex); \ + tex = NULL; \ + } \ +} while (0) + +/* UBOs */ +struct GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data); +void DRW_uniformbuffer_update(struct GPUUniformBuffer *ubo, const void *data); +void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo); +#define DRW_UBO_FREE_SAFE(ubo) do { \ + if (ubo != NULL) { \ + DRW_uniformbuffer_free(ubo); \ + ubo = NULL; \ + } \ +} while (0) + +void DRW_transform_to_display(struct GPUTexture *tex); +void DRW_multisamples_resolve( + struct GPUTexture *src_depth, struct GPUTexture *src_color); + +/* Shaders */ +struct GPUShader *DRW_shader_create( + const char *vert, const char *geom, const char *frag, const char *defines); +struct GPUShader *DRW_shader_create_with_lib( + const char *vert, const char *geom, const char *frag, const char *lib, const char *defines); +struct GPUShader *DRW_shader_create_with_transform_feedback( + const char *vert, const char *geom, const char *defines, + const GPUShaderTFBType prim_type, const char **varying_names, const int varying_count); +struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines); +struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines); +struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines); +struct GPUShader *DRW_shader_create_3D_depth_only(void); +struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, int options); +struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, const void *engine_type, int options); +struct GPUMaterial *DRW_shader_create_from_world( + struct Scene *scene, struct World *wo, const void *engine_type, int options, + const char *vert, const char *geom, const char *frag_lib, const char *defines); +struct GPUMaterial *DRW_shader_create_from_material( + struct Scene *scene, struct Material *ma, const void *engine_type, int options, + const char *vert, const char *geom, const char *frag_lib, const char *defines); +void DRW_shader_free(struct GPUShader *shader); +#define DRW_SHADER_FREE_SAFE(shader) do { \ + if (shader != NULL) { \ + DRW_shader_free(shader); \ + shader = NULL; \ + } \ +} while (0) + +/* Batches */ + +typedef enum { + DRW_STATE_WRITE_DEPTH = (1 << 0), + DRW_STATE_WRITE_COLOR = (1 << 1), + DRW_STATE_DEPTH_ALWAYS = (1 << 2), + DRW_STATE_DEPTH_LESS = (1 << 3), + DRW_STATE_DEPTH_LESS_EQUAL = (1 << 4), + DRW_STATE_DEPTH_EQUAL = (1 << 5), + DRW_STATE_DEPTH_GREATER = (1 << 6), + DRW_STATE_DEPTH_GREATER_EQUAL = (1 << 7), + DRW_STATE_CULL_BACK = (1 << 8), + DRW_STATE_CULL_FRONT = (1 << 9), + DRW_STATE_WIRE = (1 << 10), + DRW_STATE_POINT = (1 << 11), + DRW_STATE_STIPPLE_2 = (1 << 12), + DRW_STATE_STIPPLE_3 = (1 << 13), + DRW_STATE_STIPPLE_4 = (1 << 14), + DRW_STATE_BLEND = (1 << 15), + DRW_STATE_ADDITIVE = (1 << 16), + DRW_STATE_MULTIPLY = (1 << 17), + DRW_STATE_TRANSMISSION = (1 << 18), + DRW_STATE_CLIP_PLANES = (1 << 19), + DRW_STATE_ADDITIVE_FULL = (1 << 20), /* Same as DRW_STATE_ADDITIVE but let alpha accumulate without premult. */ + DRW_STATE_BLEND_PREMUL = (1 << 21), /* Use that if color is already premult by alpha. */ + DRW_STATE_WIRE_SMOOTH = (1 << 22), + DRW_STATE_TRANS_FEEDBACK = (1 << 23), + DRW_STATE_TRANSPARENT_REVEALAGE = (1 << 24), + + DRW_STATE_WRITE_STENCIL = (1 << 27), + DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (1 << 28), + DRW_STATE_WRITE_STENCIL_SHADOW_FAIL = (1 << 29), + DRW_STATE_STENCIL_EQUAL = (1 << 30), + DRW_STATE_STENCIL_NEQUAL = (1 << 31), +} DRWState; +#define DRW_STATE_DEFAULT (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL) + +typedef enum { + DRW_ATTRIB_INT, + DRW_ATTRIB_FLOAT, +} DRWAttribType; + +typedef struct DRWInstanceAttribFormat { + char name[32]; + DRWAttribType type; + int components; +} DRWInstanceAttribFormat; + +struct Gwn_VertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize); +#define DRW_shgroup_instance_format(format, ...) do { \ + if (format == NULL) { \ + DRWInstanceAttribFormat drw_format[] = __VA_ARGS__;\ + format = DRW_shgroup_instance_format_array(drw_format, (sizeof(drw_format) / sizeof(DRWInstanceAttribFormat))); \ + } \ +} while (0) + +DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass); +DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass); +DRWShadingGroup *DRW_shgroup_material_instance_create( + struct GPUMaterial *material, DRWPass *pass, struct Gwn_Batch *geom, struct Object *ob, + struct Gwn_VertFormat *format); +DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial *material, DRWPass *pass, int size); +DRWShadingGroup *DRW_shgroup_instance_create( + struct GPUShader *shader, DRWPass *pass, struct Gwn_Batch *geom, struct Gwn_VertFormat *format); +DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass); +DRWShadingGroup *DRW_shgroup_line_batch_create_with_format( + struct GPUShader *shader, DRWPass *pass, struct Gwn_VertFormat *format); +DRWShadingGroup *DRW_shgroup_line_batch_create( + struct GPUShader *shader, DRWPass *pass); +DRWShadingGroup *DRW_shgroup_empty_tri_batch_create( + struct GPUShader *shader, DRWPass *pass, int size); +DRWShadingGroup *DRW_shgroup_transform_feedback_create( + struct GPUShader *shader, DRWPass *pass, struct Gwn_VertBuf *tf_target); + + +typedef void (DRWCallGenerateFn)( + DRWShadingGroup *shgroup, + void (*draw_fn)(DRWShadingGroup *shgroup, struct Gwn_Batch *geom), + void *user_data); + +/* return final visibility */ +typedef bool (DRWCallVisibilityFn)( + bool vis_in, + void *user_data); + +void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batch); + +void DRW_shgroup_free(struct DRWShadingGroup *shgroup); +void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4]); +void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup, unsigned int point_count, float (*obmat)[4]); +void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup, unsigned int line_count, float (*obmat)[4]); +void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, unsigned int tria_count, float (*obmat)[4]); +void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, struct Object *ob, bool bypass_culling); +#define DRW_shgroup_call_object_add(shgroup, geom, ob) DRW_shgroup_call_object_add_ex(shgroup, geom, ob, false) +#define DRW_shgroup_call_object_add_no_cull(shgroup, geom, ob) DRW_shgroup_call_object_add_ex(shgroup, geom, ob, true) +void DRW_shgroup_call_object_add_with_callback( + DRWShadingGroup *shgroup, struct Gwn_Batch *geom, struct Object *ob, + DRWCallVisibilityFn *callback, void *user_data); +/* Used for drawing a batch with instancing without instance attribs. */ +void DRW_shgroup_call_instances_add( + DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4], uint *count); +void DRW_shgroup_call_object_instances_add( + DRWShadingGroup *shgroup, struct Gwn_Batch *geom, struct Object *ob, uint *count); +void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, struct Object *ob, float (*obmat)[4]); +void DRW_shgroup_call_generate_add( + DRWShadingGroup *shgroup, DRWCallGenerateFn *geometry_fn, void *user_data, float (*obmat)[4]); +void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *attr[], uint attr_len); +#define DRW_shgroup_call_dynamic_add(shgroup, ...) do { \ + const void *array[] = {__VA_ARGS__}; \ + DRW_shgroup_call_dynamic_add_array(shgroup, array, (sizeof(array) / sizeof(*array))); \ +} while (0) + +uint DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup); + +void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state); +void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state); +void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask); + +void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex); +void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex); +void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo); +void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo); +void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, struct GPUTexture **tex); +void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize); +void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize); +void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize); +void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize); +void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize); +void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize); +/* Boolean are expected to be 4bytes longs for opengl! */ +void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize); +void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize); +void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize); +void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize); +void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float (*value)[3]); +void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float (*value)[4]); +/* Store value instead of referencing it. */ +void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value); +void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value); +void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value); + +/* Passes */ +DRWPass *DRW_pass_create(const char *name, DRWState state); +void DRW_pass_state_set(DRWPass *pass, DRWState state); +void DRW_pass_state_add(DRWPass *pass, DRWState state); +void DRW_pass_state_remove(DRWPass *pass, DRWState state); +void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData); +void DRW_pass_sort_shgroup_z(DRWPass *pass); + +/* Viewport */ +typedef enum { + DRW_MAT_PERS = 0, + DRW_MAT_PERSINV, + DRW_MAT_VIEW, + DRW_MAT_VIEWINV, + DRW_MAT_WIN, + DRW_MAT_WININV, + + DRW_MAT_COUNT, // Don't use this. +} DRWViewportMatrixType; + +typedef struct DRWMatrixState { + float mat[DRW_MAT_COUNT][4][4]; +} DRWMatrixState; + +void DRW_viewport_init(const bContext *C); +void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type); +void DRW_viewport_matrix_get_all(DRWMatrixState *state); +void DRW_viewport_matrix_override_set(const float mat[4][4], DRWViewportMatrixType type); +void DRW_viewport_matrix_override_set_all(DRWMatrixState *state); +void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type); +void DRW_viewport_matrix_override_unset_all(void); + +/* Thoses are in viewspace so negative if in persp. + * Extract near and far clip distance from the projection matrix. */ +float DRW_viewport_near_distance_get(void); +float DRW_viewport_far_distance_get(void); + +const float *DRW_viewport_size_get(void); +const float *DRW_viewport_invert_size_get(void); +const float *DRW_viewport_screenvecs_get(void); +const float *DRW_viewport_pixelsize_get(void); +bool DRW_viewport_is_persp_get(void); + +struct DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void); +struct DefaultTextureList *DRW_viewport_texture_list_get(void); + +void DRW_viewport_request_redraw(void); + +void DRW_render_to_image(struct RenderEngine *engine, struct Depsgraph *depsgraph); +void DRW_render_object_iter( + void *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph, + void (*callback)(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *depsgraph)); +void DRW_render_instance_buffer_finish(void); + +/* ViewLayers */ +void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type); +void **DRW_view_layer_engine_data_ensure_ex( + struct ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)); +void **DRW_view_layer_engine_data_ensure( + DrawEngineType *engine_type, void (*callback)(void *storage)); + +/* Objects */ +ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type); +ObjectEngineData *DRW_object_engine_data_ensure( + Object *ob, + DrawEngineType *engine_type, + size_t size, + ObjectEngineDataInitCb init_cb, + ObjectEngineDataFreeCb free_cb); +struct LampEngineData *DRW_lamp_engine_data_ensure(Object *ob, struct RenderEngineType *engine_type); +void DRW_lamp_engine_data_free(struct LampEngineData *led); + +/* Settings */ +bool DRW_object_is_renderable(struct Object *ob); +bool DRW_check_object_visible_within_active_context(struct Object *ob); +bool DRW_object_is_flat_normal(const struct Object *ob); +int DRW_object_is_mode_shade(const struct Object *ob); +int DRW_object_is_paint_mode(const struct Object *ob); + +bool DRW_check_psys_visible_within_active_context(struct Object *object, struct ParticleSystem *psys); + +/* Draw commands */ +void DRW_draw_pass(DRWPass *pass); +void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group); + +void DRW_draw_text_cache_queue(struct DRWTextStore *dt); + +void DRW_draw_callbacks_pre_scene(void); +void DRW_draw_callbacks_post_scene(void); + +int DRW_draw_region_engine_info_offset(void); +void DRW_draw_region_engine_info(void); + +void DRW_state_reset_ex(DRWState state); +void DRW_state_reset(void); +void DRW_state_lock(DRWState state); + +void DRW_state_invert_facing(void); + +void DRW_state_clip_planes_count_set(uint plane_ct); +void DRW_state_clip_planes_reset(void); + +/* Culling, return true if object is inside view frustum. */ +bool DRW_culling_sphere_test(BoundSphere *bsphere); +bool DRW_culling_box_test(BoundBox *bbox); +bool DRW_culling_plane_test(float plane[4]); + +void DRW_culling_frustum_corners_get(BoundBox *corners); + +/* Selection */ +void DRW_select_load_id(uint id); + +/* Draw State */ +void DRW_state_dfdy_factors_get(float dfdyfac[2]); +bool DRW_state_is_fbo(void); +bool DRW_state_is_select(void); +bool DRW_state_is_depth(void); +bool DRW_state_is_image_render(void); +bool DRW_state_is_scene_render(void); +bool DRW_state_is_opengl_render(void); +bool DRW_state_show_text(void); +bool DRW_state_draw_support(void); +bool DRW_state_draw_background(void); + +enum eDepsObjectIteratorMode DRW_iterator_mode_get(void); + +struct DRWTextStore *DRW_state_text_cache_get(void); + +/* Avoid too many lookups while drawing */ +typedef struct DRWContextState { + + struct ARegion *ar; /* 'CTX_wm_region(C)' */ + struct RegionView3D *rv3d; /* 'CTX_wm_region_view3d(C)' */ + struct View3D *v3d; /* 'CTX_wm_view3d(C)' */ + + struct Scene *scene; /* 'CTX_data_scene(C)' */ + struct ViewLayer *view_layer; /* 'CTX_data_view_layer(C)' */ + + /* Use 'object_edit' for edit-mode */ + struct Object *obact; /* 'OBACT' */ + + struct RenderEngineType *engine_type; + + struct Depsgraph *depsgraph; + + eObjectMode object_mode; + + /* Last resort (some functions take this as an arg so we can't easily avoid). + * May be NULL when used for selection or depth buffer. */ + const struct bContext *evil_C; + + /* ---- */ + + /* Cache: initialized by 'drw_context_state_init'. */ + struct Object *object_pose; + struct Object *object_edit; + +} DRWContextState; + +const DRWContextState *DRW_context_state_get(void); + +#endif /* __DRW_RENDER_H__ */ diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c new file mode 100644 index 00000000000..ed9bb6f8ca9 --- /dev/null +++ b/source/blender/draw/intern/draw_armature.c @@ -0,0 +1,1742 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_armature.c + * \ingroup draw + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "DNA_anim_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" +#include "DNA_object_types.h" + +#include "DRW_render.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_dlrbTree.h" +#include "BLI_utildefines.h" + +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_global.h" +#include "BKE_modifier.h" +#include "BKE_nla.h" +#include "BKE_curve.h" + +#include "BIF_gl.h" + +#include "ED_armature.h" +#include "ED_keyframes_draw.h" + +#include "GPU_select.h" + +#include "UI_resources.h" + +#include "draw_common.h" +#include "draw_manager_text.h" + +#define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var)) +#define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag)) + +#define PT_DEFAULT_RAD 0.05f /* radius of the point batch. */ + +/* For now just match 2.7x where possible. */ +// #define USE_SOLID_COLOR + +/* Reset for drawing each armature object */ +static struct { + /* Current armature object */ + Object *ob; + /* Reset when changing current_armature */ + DRWShadingGroup *bone_octahedral_solid; + DRWShadingGroup *bone_octahedral_wire; + DRWShadingGroup *bone_octahedral_outline; + DRWShadingGroup *bone_box_solid; + DRWShadingGroup *bone_box_wire; + DRWShadingGroup *bone_box_outline; + DRWShadingGroup *bone_wire; + DRWShadingGroup *bone_stick; + DRWShadingGroup *bone_envelope_solid; + DRWShadingGroup *bone_envelope_distance; + DRWShadingGroup *bone_envelope_wire; + DRWShadingGroup *bone_point_solid; + DRWShadingGroup *bone_point_wire; + DRWShadingGroup *bone_axes; + DRWShadingGroup *lines_relationship; + DRWShadingGroup *lines_ik; + DRWShadingGroup *lines_ik_no_target; + DRWShadingGroup *lines_ik_spline; + + DRWArmaturePasses passes; +} g_data = {NULL}; + + +/** + * Follow `TH_*` naming except for mixed colors. + */ +static struct { + float select_color[4]; + float edge_select_color[4]; + float bone_select_color[4]; /* tint */ + float wire_color[4]; + float wire_edit_color[4]; + float bone_solid_color[4]; + float bone_active_unselect_color[4]; /* mix */ + float bone_pose_color[4]; + float bone_pose_active_color[4]; + float bone_pose_active_unselect_color[4]; /* mix */ + float text_hi_color[4]; + float text_color[4]; + float vertex_select_color[4]; + float vertex_color[4]; + + /* not a theme, this is an override */ + const float *const_color; + float const_wire; +} g_theme; + + +/* -------------------------------------------------------------------- */ + +/** \name Shader Groups (DRW_shgroup) + * \{ */ + +/* Octahedral */ +static void drw_shgroup_bone_octahedral( + const float (*bone_mat)[4], + const float bone_color[4], const float hint_color[4], const float outline_color[4]) +{ + if (g_data.bone_octahedral_outline == NULL) { + struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_get(); + g_data.bone_octahedral_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom); + } + if (g_data.bone_octahedral_solid == NULL) { + struct Gwn_Batch *geom = DRW_cache_bone_octahedral_get(); + g_data.bone_octahedral_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom); + } + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_solid, final_bonemat, bone_color, hint_color); + if (outline_color[3] > 0.0f) { + DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_outline, final_bonemat, outline_color); + } +} + +/* Box / B-Bone */ +static void drw_shgroup_bone_box( + const float (*bone_mat)[4], + const float bone_color[4], const float hint_color[4], const float outline_color[4]) +{ + if (g_data.bone_box_wire == NULL) { + struct Gwn_Batch *geom = DRW_cache_bone_box_wire_get(); + g_data.bone_box_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom); + } + if (g_data.bone_box_solid == NULL) { + struct Gwn_Batch *geom = DRW_cache_bone_box_get(); + g_data.bone_box_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom); + } + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, final_bonemat, bone_color, hint_color); + if (outline_color[3] > 0.0f) { + DRW_shgroup_call_dynamic_add(g_data.bone_box_outline, final_bonemat, outline_color); + } +} + +/* Wire */ +static void drw_shgroup_bone_wire(const float (*bone_mat)[4], const float color[4]) +{ + if (g_data.bone_wire == NULL) { + g_data.bone_wire = shgroup_dynlines_flat_color(g_data.passes.bone_wire); + } + float head[3], tail[3]; + mul_v3_m4v3(head, g_data.ob->obmat, bone_mat[3]); + DRW_shgroup_call_dynamic_add(g_data.bone_wire, head, color); + + add_v3_v3v3(tail, bone_mat[3], bone_mat[1]); + mul_m4_v3(g_data.ob->obmat, tail); + DRW_shgroup_call_dynamic_add(g_data.bone_wire, tail, color); +} + +/* Stick */ +static void drw_shgroup_bone_stick( + const float (*bone_mat)[4], + const float col_wire[4], const float col_bone[4], const float col_head[4], const float col_tail[4]) +{ + if (g_data.bone_stick == NULL) { + g_data.bone_stick = shgroup_instance_bone_stick(g_data.passes.bone_wire); + } + float final_bonemat[4][4], tail[4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + add_v3_v3v3(tail, final_bonemat[3], final_bonemat[1]); + DRW_shgroup_call_dynamic_add(g_data.bone_stick, final_bonemat[3], tail, col_wire, col_bone, col_head, col_tail); +} + + +/* Envelope */ +static void drw_shgroup_bone_envelope_distance( + const float (*bone_mat)[4], + const float *radius_head, const float *radius_tail, const float *distance) +{ + if (g_data.passes.bone_envelope != NULL) { + if (g_data.bone_envelope_distance == NULL) { + g_data.bone_envelope_distance = shgroup_instance_bone_envelope_distance(g_data.passes.bone_envelope); + /* passes.bone_envelope should have the DRW_STATE_CULL_FRONT state enabled. */ + } + float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f}; + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + /* We need matrix mul because we need shear applied. */ + /* NOTE: could be done in shader if that becomes a bottleneck. */ + mul_m4_v4(final_bonemat, head_sphere); + mul_m4_v4(final_bonemat, tail_sphere); + head_sphere[3] = *radius_head; + head_sphere[3] += *distance; + tail_sphere[3] = *radius_tail; + tail_sphere[3] += *distance; + DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, head_sphere, tail_sphere, final_bonemat[0]); + } +} + +static void drw_shgroup_bone_envelope( + const float (*bone_mat)[4], + const float bone_color[4], const float hint_color[4], const float outline_color[4], + const float *radius_head, const float *radius_tail) +{ + if (g_data.bone_point_wire == NULL) { + g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire); + } + if (g_data.bone_point_solid == NULL) { + g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(g_data.passes.bone_solid); + } + if (g_data.bone_envelope_wire == NULL) { + g_data.bone_envelope_wire = shgroup_instance_bone_envelope_outline(g_data.passes.bone_wire); + } + if (g_data.bone_envelope_solid == NULL) { + g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.passes.bone_solid); + /* We can have a lot of overdraw if we don't do this. Also envelope are not subject to + * inverted matrix. */ + DRW_shgroup_state_enable(g_data.bone_envelope_solid, DRW_STATE_CULL_BACK); + } + + float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f}; + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + mul_m4_v4(final_bonemat, head_sphere); + mul_m4_v4(final_bonemat, tail_sphere); + head_sphere[3] = *radius_head; + tail_sphere[3] = *radius_tail; + + if (head_sphere[3] < 0.0f) { + /* Draw Tail only */ + float tmp[4][4] = {{0.0f}}; + tmp[0][0] = tmp[1][1] = tmp[2][2] = tail_sphere[3] / PT_DEFAULT_RAD; + tmp[3][3] = 1.0f; + copy_v3_v3(tmp[3], tail_sphere); + DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color); + if (outline_color[3] > 0.0f) { + DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color); + } + } + else if (tail_sphere[3] < 0.0f) { + /* Draw Head only */ + float tmp[4][4] = {{0.0f}}; + tmp[0][0] = tmp[1][1] = tmp[2][2] = head_sphere[3] / PT_DEFAULT_RAD; + tmp[3][3] = 1.0f; + copy_v3_v3(tmp[3], head_sphere); + DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color); + if (outline_color[3] > 0.0f) { + DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color); + } + } + else { + /* Draw Body */ + float tmp_sphere[4]; + float len = len_v3v3(tail_sphere, head_sphere); + float fac_head = (len - head_sphere[3]) / len; + float fac_tail = (len - tail_sphere[3]) / len; + + /* Small epsilon to avoid problem with float precison in shader. */ + if (len > (tail_sphere[3] + head_sphere[3]) + 1e-8f) { + + copy_v4_v4(tmp_sphere, head_sphere); + interp_v4_v4v4(head_sphere, tail_sphere, head_sphere, fac_head); + interp_v4_v4v4(tail_sphere, tmp_sphere, tail_sphere, fac_tail); + DRW_shgroup_call_dynamic_add( + g_data.bone_envelope_solid, head_sphere, tail_sphere, bone_color, hint_color, final_bonemat[0]); + if (outline_color[3] > 0.0f) { + DRW_shgroup_call_dynamic_add( + g_data.bone_envelope_wire, head_sphere, tail_sphere, outline_color, final_bonemat[0]); + } + } + else { + float tmp[4][4] = {{0.0f}}; + float fac = max_ff(fac_head, 1.0f - fac_tail); + interp_v4_v4v4(tmp_sphere, tail_sphere, head_sphere, clamp_f(fac, 0.0f, 1.0f)); + tmp[0][0] = tmp[1][1] = tmp[2][2] = tmp_sphere[3] / PT_DEFAULT_RAD; + tmp[3][3] = 1.0f; + copy_v3_v3(tmp[3], tmp_sphere); + DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color); + if (outline_color[3] > 0.0f) { + DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color); + } + } + } +} + +/* Custom (geometry) */ + +static void drw_shgroup_bone_custom_solid( + const float (*bone_mat)[4], + const float bone_color[4], const float hint_color[4], const float outline_color[4], + Object *custom) +{ + /* grr, not re-using instances! */ + struct Gwn_Batch *geom = DRW_cache_object_surface_get(custom); + if (geom) { + DRWShadingGroup *shgrp_geom_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom); + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, bone_color, hint_color); + } + + geom = DRW_cache_object_edge_detection_get(custom, NULL); + if (geom && outline_color[3] > 0.0f) { + DRWShadingGroup *shgrp_geom_wire = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom); + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, outline_color); + } +} + +static void drw_shgroup_bone_custom_wire( + const float (*bone_mat)[4], + const float color[4], Object *custom) +{ + /* grr, not re-using instances! */ + struct Gwn_Batch *geom = DRW_cache_object_wire_outline_get(custom); + if (geom) { + DRWShadingGroup *shgrp_geom_wire = shgroup_instance_wire(g_data.passes.bone_wire, geom); + float final_bonemat[4][4], final_color[4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + copy_v3_v3(final_color, color); + final_color[3] = 1.0f; /* hack */ + DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, final_color); + } +} + +/* Head and tail sphere */ +static void drw_shgroup_bone_point( + const float (*bone_mat)[4], + const float bone_color[4], const float hint_color[4], const float outline_color[4]) +{ + if (g_data.bone_point_wire == NULL) { + g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire); + } + if (g_data.bone_point_solid == NULL) { + g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(g_data.passes.bone_solid); + } + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, final_bonemat, bone_color, hint_color); + if (outline_color[3] > 0.0f) { + DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, final_bonemat, outline_color); + } +} + +/* Axes */ +static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const float color[4]) +{ + if (g_data.bone_axes == NULL) { + g_data.bone_axes = shgroup_instance_bone_axes(g_data.passes.bone_axes); + } + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + DRW_shgroup_call_dynamic_add(g_data.bone_axes, final_bonemat, color); +} + +/* Relationship lines */ +static void drw_shgroup_bone_relationship_lines(const float start[3], const float end[3]) +{ + if (g_data.lines_relationship == NULL) { + g_data.lines_relationship = shgroup_dynlines_dashed_uniform_color( + g_data.passes.relationship_lines, g_theme.wire_color); + } + /* reverse order to have less stipple overlap */ + float v[3]; + mul_v3_m4v3(v, g_data.ob->obmat, end); + DRW_shgroup_call_dynamic_add(g_data.lines_relationship, v); + mul_v3_m4v3(v, g_data.ob->obmat, start); + DRW_shgroup_call_dynamic_add(g_data.lines_relationship, v); +} + +static void drw_shgroup_bone_ik_lines(const float start[3], const float end[3]) +{ + if (g_data.lines_ik == NULL) { + static float fcolor[4] = {0.8f, 0.5f, 0.0f, 1.0f}; /* add theme! */ + g_data.lines_ik = shgroup_dynlines_dashed_uniform_color(g_data.passes.relationship_lines, fcolor); + } + /* reverse order to have less stipple overlap */ + float v[3]; + mul_v3_m4v3(v, g_data.ob->obmat, end); + DRW_shgroup_call_dynamic_add(g_data.lines_ik, v); + mul_v3_m4v3(v, g_data.ob->obmat, start); + DRW_shgroup_call_dynamic_add(g_data.lines_ik, v); +} + +static void drw_shgroup_bone_ik_no_target_lines(const float start[3], const float end[3]) +{ + if (g_data.lines_ik_no_target == NULL) { + static float fcolor[4] = {0.8f, 0.8f, 0.2f, 1.0f}; /* add theme! */ + g_data.lines_ik_no_target = shgroup_dynlines_dashed_uniform_color(g_data.passes.relationship_lines, fcolor); + } + /* reverse order to have less stipple overlap */ + DRW_shgroup_call_dynamic_add(g_data.lines_ik_no_target, end); + DRW_shgroup_call_dynamic_add(g_data.lines_ik_no_target, start); +} + +static void drw_shgroup_bone_ik_spline_lines(const float start[3], const float end[3]) +{ + if (g_data.lines_ik_spline == NULL) { + static float fcolor[4] = {0.8f, 0.8f, 0.2f, 1.0f}; /* add theme! */ + g_data.lines_ik_spline = shgroup_dynlines_dashed_uniform_color(g_data.passes.relationship_lines, fcolor); + } + /* reverse order to have less stipple overlap */ + DRW_shgroup_call_dynamic_add(g_data.lines_ik_spline, end); + DRW_shgroup_call_dynamic_add(g_data.lines_ik_spline, start); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Drawing Theme Helpers + * + * Note, this section is duplicate of code in 'drawarmature.c'. + * + * \{ */ + +/* global here is reset before drawing each bone */ +struct { + const ThemeWireColor *bcolor; +} g_color; + +/* values of colCode for set_pchan_color */ +enum { + PCHAN_COLOR_NORMAL = 0, /* normal drawing */ + PCHAN_COLOR_SOLID, /* specific case where "solid" color is needed */ + PCHAN_COLOR_CONSTS, /* "constraint" colors (which may/may-not be suppressed) */ + + PCHAN_COLOR_SPHEREBONE_BASE, /* for the 'stick' of sphere (envelope) bones */ + PCHAN_COLOR_SPHEREBONE_END, /* for the ends of sphere (envelope) bones */ + PCHAN_COLOR_LINEBONE /* for the middle of line-bones */ +}; + +/* This function sets the color-set for coloring a certain bone */ +static void set_pchan_colorset(Object *ob, bPoseChannel *pchan) +{ + bPose *pose = (ob) ? ob->pose : NULL; + bArmature *arm = (ob) ? ob->data : NULL; + bActionGroup *grp = NULL; + short color_index = 0; + + /* sanity check */ + if (ELEM(NULL, ob, arm, pose, pchan)) { + g_color.bcolor = NULL; + return; + } + + /* only try to set custom color if enabled for armature */ + if (arm->flag & ARM_COL_CUSTOM) { + /* currently, a bone can only use a custom color set if it's group (if it has one), + * has been set to use one + */ + if (pchan->agrp_index) { + grp = (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1)); + if (grp) + color_index = grp->customCol; + } + } + + /* bcolor is a pointer to the color set to use. If NULL, then the default + * color set (based on the theme colors for 3d-view) is used. + */ + if (color_index > 0) { + bTheme *btheme = UI_GetTheme(); + g_color.bcolor = &btheme->tarm[(color_index - 1)]; + } + else if (color_index == -1) { + /* use the group's own custom color set (grp is always != NULL here) */ + g_color.bcolor = &grp->cs; + } + else { + g_color.bcolor = NULL; + } +} + +/* This function is for brightening/darkening a given color (like UI_GetThemeColorShade3ubv()) */ +static void cp_shade_color3ub(unsigned char cp[3], const int offset) +{ + int r, g, b; + + r = offset + (int) cp[0]; + CLAMP(r, 0, 255); + g = offset + (int) cp[1]; + CLAMP(g, 0, 255); + b = offset + (int) cp[2]; + CLAMP(b, 0, 255); + + cp[0] = r; + cp[1] = g; + cp[2] = b; +} + +static void cp_shade_color3f(float cp[3], const float offset) +{ + add_v3_fl(cp, offset); + CLAMP(cp[0], 0, 255); + CLAMP(cp[1], 0, 255); + CLAMP(cp[2], 0, 255); +} + + +/* This function sets the gl-color for coloring a certain bone (based on bcolor) */ +static bool set_pchan_color(short colCode, const int boneflag, const short constflag, float r_color[4]) +{ + float *fcolor = r_color; + const ThemeWireColor *bcolor = g_color.bcolor; + + switch (colCode) { + case PCHAN_COLOR_NORMAL: + { + if (bcolor) { + unsigned char cp[4] = {255}; + + if (boneflag & BONE_DRAW_ACTIVE) { + copy_v3_v3_char((char *)cp, bcolor->active); + if (!(boneflag & BONE_SELECTED)) { + cp_shade_color3ub(cp, -80); + } + } + else if (boneflag & BONE_SELECTED) { + copy_v3_v3_char((char *)cp, bcolor->select); + } + else { + /* a bit darker than solid */ + copy_v3_v3_char((char *)cp, bcolor->solid); + cp_shade_color3ub(cp, -50); + } + + rgb_uchar_to_float(fcolor, cp); + } + else { + if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) { + UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor); + } + else if (boneflag & BONE_DRAW_ACTIVE) { + UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor); + } + else if (boneflag & BONE_SELECTED) { + UI_GetThemeColor4fv(TH_BONE_POSE, fcolor); + } + else { + UI_GetThemeColor4fv(TH_WIRE, fcolor); + } + } + + return true; + } + case PCHAN_COLOR_SOLID: + { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + + if (bcolor) { + float solid_bcolor[3]; + rgb_uchar_to_float(solid_bcolor, (unsigned char *)bcolor->solid); + interp_v3_v3v3(fcolor, fcolor, solid_bcolor, 1.0f); + } + + return true; + } + case PCHAN_COLOR_CONSTS: + { + if ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) { + unsigned char cp[4]; + if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 80); + else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 80); + else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 80); + else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 80); + else { + return false; + } + + rgba_uchar_to_float(fcolor, cp); + + return true; + } + return false; + } + case PCHAN_COLOR_SPHEREBONE_BASE: + { + if (bcolor) { + unsigned char cp[4] = {255}; + + if (boneflag & BONE_DRAW_ACTIVE) { + copy_v3_v3_char((char *)cp, bcolor->active); + } + else if (boneflag & BONE_SELECTED) { + copy_v3_v3_char((char *)cp, bcolor->select); + } + else { + copy_v3_v3_char((char *)cp, bcolor->solid); + } + + rgb_uchar_to_float(fcolor, cp); + } + else { + if (boneflag & BONE_DRAW_ACTIVE) { + UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor); + } + else if (boneflag & BONE_SELECTED) { + UI_GetThemeColor4fv(TH_BONE_POSE, fcolor); + } + else { + UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor); + } + } + + return true; + } + case PCHAN_COLOR_SPHEREBONE_END: + { + if (bcolor) { + unsigned char cp[4] = {255}; + + if (boneflag & BONE_DRAW_ACTIVE) { + copy_v3_v3_char((char *)cp, bcolor->active); + cp_shade_color3ub(cp, 10); + } + else if (boneflag & BONE_SELECTED) { + copy_v3_v3_char((char *)cp, bcolor->select); + cp_shade_color3ub(cp, -30); + } + else { + copy_v3_v3_char((char *)cp, bcolor->solid); + cp_shade_color3ub(cp, -30); + } + + rgb_uchar_to_float(fcolor, cp); + } + else { + if (boneflag & BONE_DRAW_ACTIVE) { + UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor); + } + else if (boneflag & BONE_SELECTED) { + UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor); + } + else { + UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor); + } + } + break; + } + case PCHAN_COLOR_LINEBONE: + { + /* inner part in background color or constraint */ + if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) { + unsigned char cp[4]; + if (constflag & PCHAN_HAS_TARGET) rgba_char_args_set((char *)cp, 255, 150, 0, 255); + else if (constflag & PCHAN_HAS_IK) rgba_char_args_set((char *)cp, 255, 255, 0, 255); + else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 255); + else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 255); + else if (constflag) UI_GetThemeColor4ubv(TH_BONE_POSE, cp); /* PCHAN_HAS_ACTION */ + + rgb_uchar_to_float(fcolor, cp); + } + else { + if (bcolor) { + const char *cp = bcolor->solid; + rgb_uchar_to_float(fcolor, (unsigned char *)cp); + fcolor[3] = 204.f / 255.f; + } + else { + UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor); + } + } + + return true; + } + } + + return false; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Drawing Color Helpers + * \{ */ + +/** See: 'set_pchan_color'*/ +static void update_color(const Object *ob, const float const_color[4]) +{ + g_theme.const_color = const_color; + g_theme.const_wire = ((ob->base_flag & BASE_SELECTED) != 0) ? 1.5f : 0.0f; + +#define NO_ALPHA(c) (((c)[3] = 1.0f), (c)) + + UI_GetThemeColor3fv(TH_SELECT, NO_ALPHA(g_theme.select_color)); + UI_GetThemeColor3fv(TH_EDGE_SELECT, NO_ALPHA(g_theme.edge_select_color)); + UI_GetThemeColorShade3fv(TH_EDGE_SELECT, -20, NO_ALPHA(g_theme.bone_select_color)); + UI_GetThemeColor3fv(TH_WIRE, NO_ALPHA(g_theme.wire_color)); + UI_GetThemeColor3fv(TH_WIRE_EDIT, NO_ALPHA(g_theme.wire_edit_color)); + UI_GetThemeColor3fv(TH_BONE_SOLID, NO_ALPHA(g_theme.bone_solid_color)); + UI_GetThemeColorBlendShade3fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, NO_ALPHA(g_theme.bone_active_unselect_color)); + UI_GetThemeColor3fv(TH_BONE_POSE, NO_ALPHA(g_theme.bone_pose_color)); + UI_GetThemeColor3fv(TH_BONE_POSE_ACTIVE, NO_ALPHA(g_theme.bone_pose_active_color)); + UI_GetThemeColorBlendShade3fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, NO_ALPHA(g_theme.bone_pose_active_unselect_color)); + UI_GetThemeColor3fv(TH_TEXT_HI, NO_ALPHA(g_theme.text_hi_color)); + UI_GetThemeColor3fv(TH_TEXT, NO_ALPHA(g_theme.text_color)); + UI_GetThemeColor3fv(TH_VERTEX_SELECT, NO_ALPHA(g_theme.vertex_select_color)); + UI_GetThemeColor3fv(TH_VERTEX, NO_ALPHA(g_theme.vertex_color)); + +#undef NO_ALPHA +} + +static const float *get_bone_solid_color( + const EditBone *UNUSED(eBone), const bPoseChannel *pchan, const bArmature *arm, + const int boneflag, const short constflag) +{ + if (g_theme.const_color) + return g_theme.bone_solid_color; + + if (arm->flag & ARM_POSEMODE) { + static float disp_color[4]; + copy_v4_v4(disp_color, pchan->draw_data->solid_color); + set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag, disp_color); + return disp_color; + } + + return g_theme.bone_solid_color; +} + +static const float *get_bone_solid_with_consts_color( + const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm, + const int boneflag, const short constflag) +{ + if (g_theme.const_color) + return g_theme.bone_solid_color; + + const float *col = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag); + + static float consts_color[4]; + if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag, consts_color)) { + interp_v3_v3v3(consts_color, col, consts_color, 0.5f); + } + else { + copy_v4_v4(consts_color, col); + } + return consts_color; +} + +static float get_bone_wire_thickness(int boneflag) +{ + if (g_theme.const_color) + return g_theme.const_wire; + else if (boneflag & (BONE_DRAW_ACTIVE | BONE_SELECTED)) + return 2.0f; + else + return 1.0f; +} + +static const float *get_bone_wire_color( + const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm, + const int boneflag, const short constflag) +{ + static float disp_color[4]; + + if (g_theme.const_color) { + copy_v3_v3(disp_color, g_theme.const_color); + } + else if (eBone) { + if (boneflag & BONE_SELECTED) { + if (boneflag & BONE_DRAW_ACTIVE) { + copy_v3_v3(disp_color, g_theme.edge_select_color); + } + else { + copy_v3_v3(disp_color, g_theme.bone_select_color); + } + } + else { + if (boneflag & BONE_DRAW_ACTIVE) { + copy_v3_v3(disp_color, g_theme.bone_active_unselect_color); + } + else { + copy_v3_v3(disp_color, g_theme.wire_edit_color); + } + } + } + else if (arm->flag & ARM_POSEMODE) { + copy_v4_v4(disp_color, pchan->draw_data->wire_color); + set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag, disp_color); + } + else { + copy_v3_v3(disp_color, g_theme.vertex_color); + } + + disp_color[3] = get_bone_wire_thickness(boneflag); + + return disp_color; +} + +#define HINT_MUL 0.5f +#define HINT_SHADE 0.2f + +static void bone_hint_color_shade(float hint_color[4], const float color[4]) +{ + mul_v3_v3fl(hint_color, color, HINT_MUL); + cp_shade_color3f(hint_color, -HINT_SHADE); + hint_color[3] = 1.0f; +} + +static const float *get_bone_hint_color( + const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm, + const int boneflag, const short constflag) +{ + static float hint_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + + if (g_theme.const_color) { + bone_hint_color_shade(hint_color, g_theme.bone_solid_color); + } + else { + const float *wire_color = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + bone_hint_color_shade(hint_color, wire_color); + } + + return hint_color; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Helper Utils + * \{ */ + +static void pchan_draw_data_init(bPoseChannel *pchan) +{ + if (pchan->draw_data != NULL) { + if (pchan->draw_data->bbone_matrix_len != pchan->bone->segments) { + MEM_SAFE_FREE(pchan->draw_data); + } + } + + if (pchan->draw_data == NULL) { + pchan->draw_data = MEM_mallocN(sizeof(*pchan->draw_data) + sizeof(Mat4) * pchan->bone->segments, __func__); + pchan->draw_data->bbone_matrix_len = pchan->bone->segments; + } +} + +static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel *pchan) +{ + float s[4][4], ebmat[4][4]; + float length; + float (*bone_mat)[4]; + float (*disp_mat)[4]; + float (*disp_tail_mat)[4]; + + /* TODO : This should be moved to depsgraph or armature refresh + * and not be tight to the draw pass creation. + * This would refresh armature without invalidating the draw cache */ + if (pchan) { + length = pchan->bone->length; + bone_mat = pchan->pose_mat; + disp_mat = pchan->disp_mat; + disp_tail_mat = pchan->disp_tail_mat; + } + else { + eBone->length = len_v3v3(eBone->tail, eBone->head); + ED_armature_ebone_to_mat4(eBone, ebmat); + + length = eBone->length; + bone_mat = ebmat; + disp_mat = eBone->disp_mat; + disp_tail_mat = eBone->disp_tail_mat; + } + + scale_m4_fl(s, length); + mul_m4_m4m4(disp_mat, bone_mat, s); + copy_m4_m4(disp_tail_mat, disp_mat); + translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f); +} + +/* XXX Direct copy from drawarmature.c... This is ugly! */ +/* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings + * + * This assumes that prev/next bones don't have any impact (since they should all still be in the "straight" + * position here anyway), and that we can simply apply the bbone settings to get the desired effect... + */ +static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_SUBDIV][4][4]) +{ + float h1[3], h2[3], length, hlength1, hlength2, roll1 = 0.0f, roll2 = 0.0f; + float mat3[3][3]; + float data[MAX_BBONE_SUBDIV + 1][4], *fp; + int a; + + length = ebone->length; + + hlength1 = ebone->ease1 * length * 0.390464f; /* 0.5f * sqrt(2) * kappa, the handle length for near-perfect circles */ + hlength2 = ebone->ease2 * length * 0.390464f; + + /* find the handle points, since this is inside bone space, the + * first point = (0, 0, 0) + * last point = (0, length, 0) + * + * we also just apply all the "extra effects", since they're the whole reason we're doing this... + */ + h1[0] = ebone->curveInX; + h1[1] = hlength1; + h1[2] = ebone->curveInY; + roll1 = ebone->roll1; + + h2[0] = ebone->curveOutX; + h2[1] = -hlength2; + h2[2] = ebone->curveOutY; + roll2 = ebone->roll2; + + /* make curve */ + if (ebone->segments > MAX_BBONE_SUBDIV) + ebone->segments = MAX_BBONE_SUBDIV; + + BKE_curve_forward_diff_bezier(0.0f, h1[0], h2[0], 0.0f, data[0], MAX_BBONE_SUBDIV, 4 * sizeof(float)); + BKE_curve_forward_diff_bezier(0.0f, h1[1], length + h2[1], length, data[0] + 1, MAX_BBONE_SUBDIV, 4 * sizeof(float)); + BKE_curve_forward_diff_bezier(0.0f, h1[2], h2[2], 0.0f, data[0] + 2, MAX_BBONE_SUBDIV, 4 * sizeof(float)); + BKE_curve_forward_diff_bezier(roll1, roll1 + 0.390464f * (roll2 - roll1), roll2 - 0.390464f * (roll2 - roll1), roll2, data[0] + 3, MAX_BBONE_SUBDIV, 4 * sizeof(float)); + + equalize_bbone_bezier(data[0], ebone->segments); /* note: does stride 4! */ + + /* make transformation matrices for the segments for drawing */ + for (a = 0, fp = data[0]; a < ebone->segments; a++, fp += 4) { + sub_v3_v3v3(h1, fp + 4, fp); + vec_roll_to_mat3(h1, fp[3], mat3); /* fp[3] is roll */ + + copy_m4_m3(result_array[a], mat3); + copy_v3_v3(result_array[a][3], fp); + + /* "extra" scale facs... */ + { + const int num_segments = ebone->segments; + + const float scaleFactorIn = 1.0f + (ebone->scaleIn - 1.0f) * ((float)(num_segments - a) / (float)num_segments); + const float scaleFactorOut = 1.0f + (ebone->scaleOut - 1.0f) * ((float)(a + 1) / (float)num_segments); + + const float scalefac = scaleFactorIn * scaleFactorOut; + float bscalemat[4][4], bscale[3]; + + bscale[0] = scalefac; + bscale[1] = 1.0f; + bscale[2] = scalefac; + + size_to_mat4(bscalemat, bscale); + + /* Note: don't multiply by inverse scale mat here, + * as it causes problems with scaling shearing and breaking segment chains */ + mul_m4_series(result_array[a], result_array[a], bscalemat); + } + } +} + +static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pchan) +{ + float s[4][4], ebmat[4][4]; + float length, xwidth, zwidth; + float (*bone_mat)[4]; + short bbone_segments; + + /* TODO : This should be moved to depsgraph or armature refresh + * and not be tight to the draw pass creation. + * This would refresh armature without invalidating the draw cache */ + if (pchan) { + length = pchan->bone->length; + xwidth = pchan->bone->xwidth; + zwidth = pchan->bone->zwidth; + bone_mat = pchan->pose_mat; + bbone_segments = pchan->bone->segments; + } + else { + eBone->length = len_v3v3(eBone->tail, eBone->head); + ED_armature_ebone_to_mat4(eBone, ebmat); + + length = eBone->length; + xwidth = eBone->xwidth; + zwidth = eBone->zwidth; + bone_mat = ebmat; + bbone_segments = eBone->segments; + } + + size_to_mat4(s, (const float[3]){xwidth, length / bbone_segments, zwidth}); + + /* Compute BBones segment matrices... */ + /* Note that we need this even for one-segment bones, because box drawing need specific weirdo matrix for the box, + * that we cannot use to draw end points & co. */ + if (pchan) { + Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix; + if (bbone_segments > 1) { + b_bone_spline_setup(pchan, 0, bbones_mat); + + for (int i = bbone_segments; i--; bbones_mat++) { + mul_m4_m4m4(bbones_mat->mat, bbones_mat->mat, s); + mul_m4_m4m4(bbones_mat->mat, bone_mat, bbones_mat->mat); + } + } + else { + mul_m4_m4m4(bbones_mat->mat, bone_mat, s); + } + } + else { + float (*bbones_mat)[4][4] = eBone->disp_bbone_mat; + + if (bbone_segments > 1) { + ebone_spline_preview(eBone, bbones_mat); + + for (int i = bbone_segments; i--; bbones_mat++) { + mul_m4_m4m4(*bbones_mat, *bbones_mat, s); + mul_m4_m4m4(*bbones_mat, bone_mat, *bbones_mat); + } + } + else { + mul_m4_m4m4(*bbones_mat, bone_mat, s); + } + } + + /* Grrr... We need default display matrix to draw end points, axes, etc. :( */ + draw_bone_update_disp_matrix_default(eBone, pchan); +} + +static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan) +{ + float s[4][4]; + float length; + float (*bone_mat)[4]; + float (*disp_mat)[4]; + float (*disp_tail_mat)[4]; + + /* See TODO above */ + length = PCHAN_CUSTOM_DRAW_SIZE(pchan); + bone_mat = pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat; + disp_mat = pchan->disp_mat; + disp_tail_mat = pchan->disp_tail_mat; + + scale_m4_fl(s, length); + mul_m4_m4m4(disp_mat, bone_mat, s); + copy_m4_m4(disp_tail_mat, disp_mat); + translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f); +} + +static void draw_axes(EditBone *eBone, bPoseChannel *pchan) +{ + float final_col[4]; + const float *col = (g_theme.const_color) ? g_theme.const_color : + (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? g_theme.text_hi_color : g_theme.text_color; + copy_v4_v4(final_col, col); + /* Mix with axes color. */ + final_col[3] = (g_theme.const_color) ? 1.0 : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? 0.3 : 0.8; + drw_shgroup_bone_axes(BONE_VAR(eBone, pchan, disp_mat), final_col); +} + +static void draw_points( + const EditBone *eBone, const bPoseChannel *pchan, const bArmature *arm, + const int boneflag, const short constflag, + const int select_id) +{ + float col_solid_root[4], col_solid_tail[4], col_wire_root[4], col_wire_tail[4]; + float col_hint_root[4], col_hint_tail[4]; + + copy_v4_v4(col_solid_root, g_theme.bone_solid_color); + copy_v4_v4(col_solid_tail, g_theme.bone_solid_color); + copy_v4_v4(col_wire_root, (g_theme.const_color) ? g_theme.const_color : g_theme.vertex_color); + copy_v4_v4(col_wire_tail, (g_theme.const_color) ? g_theme.const_color : g_theme.vertex_color); + + const bool is_envelope_draw = (arm->drawtype == ARM_ENVELOPE); + static const float envelope_ignore = -1.0f; + + col_wire_tail[3] = col_wire_root[3] = get_bone_wire_thickness(boneflag); + + /* Edit bone points can be selected */ + if (eBone) { + if (eBone->flag & BONE_ROOTSEL) { + copy_v3_v3(col_wire_root, g_theme.vertex_select_color); + } + if (eBone->flag & BONE_TIPSEL) { + copy_v3_v3(col_wire_tail, g_theme.vertex_select_color); + } + } + else if (arm->flag & ARM_POSEMODE) { + const float *solid_color = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag); + const float *wire_color = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + copy_v4_v4(col_wire_tail, wire_color); + copy_v4_v4(col_wire_root, wire_color); + copy_v4_v4(col_solid_tail, solid_color); + copy_v4_v4(col_solid_root, solid_color); + } + + bone_hint_color_shade(col_hint_root, (g_theme.const_color) ? col_solid_root : col_wire_root); + bone_hint_color_shade(col_hint_tail, (g_theme.const_color) ? col_solid_tail : col_wire_tail); + + /* Draw root point if we are not connected and parent are not hidden */ + if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) { + if (select_id != -1) { + DRW_select_load_id(select_id | BONESEL_ROOT); + } + + if (eBone) { + if (!((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))) { + if (is_envelope_draw) { + drw_shgroup_bone_envelope( + eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root, + &eBone->rad_head, &envelope_ignore); + } + else { + drw_shgroup_bone_point(eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root); + } + } + } + else { + Bone *bone = pchan->bone; + if (!((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) { + if (is_envelope_draw) { + drw_shgroup_bone_envelope( + pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root, + &bone->rad_head, &envelope_ignore); + } + else { + drw_shgroup_bone_point(pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root); + } + } + } + } + + /* Draw tip point */ + if (select_id != -1) { + DRW_select_load_id(select_id | BONESEL_TIP); + } + + if (is_envelope_draw) { + const float *rad_tail = eBone ? &eBone->rad_tail : &pchan->bone->rad_tail; + drw_shgroup_bone_envelope( + BONE_VAR(eBone, pchan, disp_mat), col_solid_tail, col_hint_tail, col_wire_tail, + &envelope_ignore, rad_tail); + } + else { + drw_shgroup_bone_point(BONE_VAR(eBone, pchan, disp_tail_mat), col_solid_tail, col_hint_tail, col_wire_tail); + } + + if (select_id != -1) { + DRW_select_load_id(-1); + } +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Draw Bones + * \{ */ + +static void draw_bone_custom_shape( + EditBone *eBone, bPoseChannel *pchan, bArmature *arm, + const int boneflag, const short constflag, + const int select_id) +{ + const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag); + const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag); + const float (*disp_mat)[4] = pchan->disp_mat; + + if (select_id != -1) { + DRW_select_load_id(select_id | BONESEL_BONE); + } + + if ((boneflag & BONE_DRAWWIRE) == 0) { + drw_shgroup_bone_custom_solid(disp_mat, col_solid, col_hint, col_wire, pchan->custom); + } + else { + drw_shgroup_bone_custom_wire(disp_mat, col_wire, pchan->custom); + } + + if (select_id != -1) { + DRW_select_load_id(-1); + } +} + +static void draw_bone_envelope( + EditBone *eBone, bPoseChannel *pchan, bArmature *arm, + const int boneflag, const short constflag, + const int select_id) +{ + const float *col_solid = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag); + const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag); + + float *rad_head, *rad_tail, *distance; + if (eBone) { + rad_tail = &eBone->rad_tail; + distance = &eBone->dist; + rad_head = (eBone->parent && (boneflag & BONE_CONNECTED)) ? &eBone->parent->rad_tail : &eBone->rad_head; + } + else { + rad_tail = &pchan->bone->rad_tail; + distance = &pchan->bone->dist; + rad_head = (pchan->parent && (boneflag & BONE_CONNECTED)) ? &pchan->parent->bone->rad_tail : &pchan->bone->rad_head; + } + + if ((select_id == -1) && + (boneflag & BONE_NO_DEFORM) == 0 && + ((boneflag & BONE_SELECTED) || (eBone && (boneflag & (BONE_ROOTSEL | BONE_TIPSEL))))) + { + drw_shgroup_bone_envelope_distance(BONE_VAR(eBone, pchan, disp_mat), rad_head, rad_tail, distance); + } + + if (select_id != -1) { + DRW_select_load_id(select_id | BONESEL_BONE); + } + + drw_shgroup_bone_envelope( + BONE_VAR(eBone, pchan, disp_mat), col_solid, col_hint, col_wire, + rad_head, rad_tail); + + if (select_id != -1) { + DRW_select_load_id(-1); + } + + draw_points(eBone, pchan, arm, boneflag, constflag, select_id); +} + +static void draw_bone_line( + EditBone *eBone, bPoseChannel *pchan, bArmature *arm, + const int boneflag, const short constflag, const int select_id) +{ + const float *col_bone = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag); + const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + const float no_display[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + const float *col_head = no_display; + const float *col_tail = col_bone; + + if (eBone) { + if (eBone->flag & BONE_TIPSEL) { + col_tail = g_theme.vertex_select_color; + } + if (boneflag & BONE_SELECTED) { + col_bone = g_theme.edge_select_color; + } + col_wire = g_theme.wire_color; + } + + /* Draw root point if we are not connected and parent are not hidden */ + if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) { + if (eBone && !(eBone->parent && !EBONE_VISIBLE(arm, eBone->parent))) { + col_head = (eBone->flag & BONE_ROOTSEL) ? g_theme.vertex_select_color : col_bone; + } + else if (pchan) { + Bone *bone = pchan->bone; + if (!(bone->parent && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) { + col_head = col_bone; + } + } + } + + if (g_theme.const_color != NULL) { + col_wire = no_display; /* actually shrink the display. */ + col_bone = col_head = col_tail = g_theme.const_color; + } + + if (select_id == -1) { + /* Not in selection mode, draw everything at once. */ + drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, col_bone, col_head, col_tail); + } + else { + /* In selection mode, draw bone, root and tip separatly. */ + DRW_select_load_id(select_id | BONESEL_BONE); + drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, col_bone, no_display, no_display); + + if (col_head[3] > 0.0f) { + DRW_select_load_id(select_id | BONESEL_ROOT); + drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, no_display, col_head, no_display); + } + + DRW_select_load_id(select_id | BONESEL_TIP); + drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, no_display, no_display, col_tail); + + DRW_select_load_id(-1); + } +} + +static void draw_bone_wire( + EditBone *eBone, bPoseChannel *pchan, bArmature *arm, + const int boneflag, const short constflag, + const int select_id) +{ + const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + + if (select_id != -1) { + DRW_select_load_id(select_id | BONESEL_BONE); + } + + if (pchan) { + Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix; + BLI_assert(bbones_mat != NULL); + + for (int i = pchan->bone->segments; i--; bbones_mat++) { + drw_shgroup_bone_wire(bbones_mat->mat, col_wire); + } + } + else if (eBone) { + for (int i = 0; i < eBone->segments; i++) { + drw_shgroup_bone_wire(eBone->disp_bbone_mat[i], col_wire); + } + } + + if (select_id != -1) { + DRW_select_load_id(-1); + } + + if (eBone) { + draw_points(eBone, pchan, arm, boneflag, constflag, select_id); + } +} + +static void draw_bone_box( + EditBone *eBone, bPoseChannel *pchan, bArmature *arm, + const int boneflag, const short constflag, + const int select_id) +{ + const float *col_solid = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag); + const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag); + + if (select_id != -1) { + DRW_select_load_id(select_id | BONESEL_BONE); + } + + if (pchan) { + Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix; + BLI_assert(bbones_mat != NULL); + + for (int i = pchan->bone->segments; i--; bbones_mat++) { + drw_shgroup_bone_box(bbones_mat->mat, col_solid, col_hint, col_wire); + } + } + else if (eBone) { + for (int i = 0; i < eBone->segments; i++) { + drw_shgroup_bone_box(eBone->disp_bbone_mat[i], col_solid, col_hint, col_wire); + } + } + + if (select_id != -1) { + DRW_select_load_id(-1); + } + + if (eBone) { + draw_points(eBone, pchan, arm, boneflag, constflag, select_id); + } +} + +static void draw_bone_octahedral( + EditBone *eBone, bPoseChannel *pchan, bArmature *arm, + const int boneflag, const short constflag, + const int select_id) +{ + const float *col_solid = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag); + const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag); + + if (select_id != -1) { + DRW_select_load_id(select_id | BONESEL_BONE); + } + + drw_shgroup_bone_octahedral(BONE_VAR(eBone, pchan, disp_mat), col_solid, col_hint, col_wire); + + if (select_id != -1) { + DRW_select_load_id(-1); + } + + draw_points(eBone, pchan, arm, boneflag, constflag, select_id); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Draw Relationships + * \{ */ + +static void pchan_draw_ik_lines(bPoseChannel *pchan, const bool only_temp, const int constflag) +{ + bConstraint *con; + bPoseChannel *parchan; + float *line_start = NULL, *line_end = NULL; + + for (con = pchan->constraints.first; con; con = con->next) { + if (con->enforce == 0.0f) + continue; + + switch (con->type) { + case CONSTRAINT_TYPE_KINEMATIC: + { + bKinematicConstraint *data = (bKinematicConstraint *)con->data; + int segcount = 0; + + /* if only_temp, only draw if it is a temporary ik-chain */ + if (only_temp && !(data->flag & CONSTRAINT_IK_TEMP)) + continue; + + /* exclude tip from chain? */ + parchan = ((data->flag & CONSTRAINT_IK_TIP) == 0) ? pchan->parent : pchan; + line_start = parchan->pose_tail; + + /* Find the chain's root */ + while (parchan->parent) { + segcount++; + if (segcount == data->rootbone || segcount > 255) { + break; /* 255 is weak */ + } + parchan = parchan->parent; + } + + if (parchan) { + line_end = parchan->pose_head; + + if (constflag & PCHAN_HAS_TARGET) + drw_shgroup_bone_ik_lines(line_start, line_end); + else + drw_shgroup_bone_ik_no_target_lines(line_start, line_end); + } + break; + } + case CONSTRAINT_TYPE_SPLINEIK: + { + bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; + int segcount = 0; + + parchan = pchan; + line_start = parchan->pose_tail; + + /* Find the chain's root */ + while (parchan->parent) { + segcount++; + /* FIXME: revise the breaking conditions */ + if (segcount == data->chainlen || segcount > 255) break; /* 255 is weak */ + parchan = parchan->parent; + } + /* Only draw line in case our chain is more than one bone long! */ + if (parchan != pchan) { /* XXX revise the breaking conditions to only stop at the tail? */ + line_end = parchan->pose_head; + drw_shgroup_bone_ik_spline_lines(line_start, line_end); + } + break; + } + } + } +} + +static void draw_bone_relations( + EditBone *ebone, bPoseChannel *pchan, bArmature *arm, + const int boneflag, const short constflag, const bool do_relations) +{ + if (g_data.passes.relationship_lines) { + if (ebone && ebone->parent) { + if ((boneflag & BONE_CONNECTED) == 0) { + drw_shgroup_bone_relationship_lines(ebone->head, ebone->parent->tail); + } + } + else if (pchan && pchan->parent) { + /* Only draw if bone or its parent is selected - reduces viewport complexity with complex rigs */ + if ((boneflag & BONE_SELECTED) || + (pchan->parent->bone && (pchan->parent->bone->flag & BONE_SELECTED))) + { + if ((boneflag & BONE_CONNECTED) == 0) { + drw_shgroup_bone_relationship_lines(pchan->pose_head, pchan->parent->pose_tail); + } + } + + /* Draw a line to IK root bone if bone is selected. */ + if (arm->flag & ARM_POSEMODE) { + if (constflag & (PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK)) { + if (boneflag & BONE_SELECTED) { + pchan_draw_ik_lines(pchan, !do_relations, constflag); + } + } + } + } + } +} +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Main Draw Loops + * \{ */ + +static void draw_armature_edit(Object *ob) +{ + EditBone *eBone; + bArmature *arm = ob->data; + int index; + const bool is_select = DRW_state_is_select(); + + update_color(ob, NULL); + + const bool show_text = DRW_state_show_text(); + const bool show_relations = true; /* TODO get value from overlays settings. */ + + for (eBone = arm->edbo->first, index = ob->select_color; eBone; eBone = eBone->next, index += 0x10000) { + if (eBone->layer & arm->layer) { + if ((eBone->flag & BONE_HIDDEN_A) == 0) { + const int select_id = is_select ? index : (uint)-1; + + const short constflag = 0; + + /* catch exception for bone with hidden parent */ + int boneflag = eBone->flag; + if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) { + boneflag &= ~BONE_CONNECTED; + } + + /* set temporary flag for drawing bone as active, but only if selected */ + if (eBone == arm->act_edbone) { + boneflag |= BONE_DRAW_ACTIVE; + } + + draw_bone_relations(eBone, NULL, arm, boneflag, constflag, show_relations); + + if (arm->drawtype == ARM_ENVELOPE) { + draw_bone_update_disp_matrix_default(eBone, NULL); + draw_bone_envelope(eBone, NULL, arm, boneflag, constflag, select_id); + } + else if (arm->drawtype == ARM_LINE) { + draw_bone_update_disp_matrix_default(eBone, NULL); + draw_bone_line(eBone, NULL, arm, boneflag, constflag, select_id); + } + else if (arm->drawtype == ARM_WIRE) { + draw_bone_update_disp_matrix_bbone(eBone, NULL); + draw_bone_wire(eBone, NULL, arm, boneflag, constflag, select_id); + } + else if (arm->drawtype == ARM_B_BONE) { + draw_bone_update_disp_matrix_bbone(eBone, NULL); + draw_bone_box(eBone, NULL, arm, boneflag, constflag, select_id); + } + else { + draw_bone_update_disp_matrix_default(eBone, NULL); + draw_bone_octahedral(eBone, NULL, arm, boneflag, constflag, select_id); + } + + /* Draw names of bone */ + if (show_text && (arm->flag & ARM_DRAWNAMES)) { + unsigned char color[4]; + UI_GetThemeColor4ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color); + + float vec[3]; + mid_v3_v3v3(vec, eBone->head, eBone->tail); + mul_m4_v3(ob->obmat, vec); + + struct DRWTextStore *dt = DRW_text_cache_ensure(); + DRW_text_cache_add( + dt, vec, eBone->name, strlen(eBone->name), + 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color); + } + + /* Draw additional axes */ + if (arm->flag & ARM_DRAWAXES) { + draw_axes(eBone, NULL); + } + } + } + } +} + +/* if const_color is NULL do pose mode coloring */ +static void draw_armature_pose(Object *ob, const float const_color[4]) +{ + bArmature *arm = ob->data; + bPoseChannel *pchan; + int index = -1; + Bone *bone; + + update_color(ob, const_color); + + /* We can't safely draw non-updated pose, might contain NULL bone pointers... */ + if (ob->pose->flag & POSE_RECALC) { + BKE_pose_rebuild(ob, arm); + } + + // if (!(base->flag & OB_FROMDUPLI)) // TODO + { + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if ((draw_ctx->object_mode & OB_MODE_POSE) || (ob == draw_ctx->object_pose)) { + arm->flag |= ARM_POSEMODE; + } + + if (arm->flag & ARM_POSEMODE) { + index = ob->select_color; + } + } + + const bool is_pose_select = (arm->flag & ARM_POSEMODE) && DRW_state_is_select(); + const bool show_text = DRW_state_show_text(); + const bool show_relations = true; /* TODO get value from overlays settings. */ + + /* being set below */ + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + bone = pchan->bone; + + /* bone must be visible */ + if ((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) { + if (bone->layer & arm->layer) { + const int select_id = is_pose_select ? index : (uint)-1; + + const short constflag = pchan->constflag; + + pchan_draw_data_init(pchan); + + if (const_color) { + /* keep color */ + } + else { + /* set color-set to use */ + set_pchan_colorset(ob, pchan); + } + + int boneflag = bone->flag; + /* catch exception for bone with hidden parent */ + boneflag = bone->flag; + if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) { + boneflag &= ~BONE_CONNECTED; + } + + /* set temporary flag for drawing bone as active, but only if selected */ + if (bone == arm->act_bone) + boneflag |= BONE_DRAW_ACTIVE; + + draw_bone_relations(NULL, pchan, arm, boneflag, constflag, show_relations); + + if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) { + draw_bone_update_disp_matrix_custom(pchan); + draw_bone_custom_shape(NULL, pchan, arm, boneflag, constflag, select_id); + } + else if (arm->drawtype == ARM_ENVELOPE) { + draw_bone_update_disp_matrix_default(NULL, pchan); + draw_bone_envelope(NULL, pchan, arm, boneflag, constflag, select_id); + } + else if (arm->drawtype == ARM_LINE) { + draw_bone_update_disp_matrix_default(NULL, pchan); + draw_bone_line(NULL, pchan, arm, boneflag, constflag, select_id); + } + else if (arm->drawtype == ARM_WIRE) { + draw_bone_update_disp_matrix_bbone(NULL, pchan); + draw_bone_wire(NULL, pchan, arm, boneflag, constflag, select_id); + } + else if (arm->drawtype == ARM_B_BONE) { + draw_bone_update_disp_matrix_bbone(NULL, pchan); + draw_bone_box(NULL, pchan, arm, boneflag, constflag, select_id); + } + else { + draw_bone_update_disp_matrix_default(NULL, pchan); + draw_bone_octahedral(NULL, pchan, arm, boneflag, constflag, select_id); + } + + /* Draw names of bone */ + if (show_text && (arm->flag & ARM_DRAWNAMES)) { + unsigned char color[4]; + UI_GetThemeColor4ubv((arm->flag & ARM_POSEMODE) && + (bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, color); + float vec[3]; + mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail); + mul_m4_v3(ob->obmat, vec); + + struct DRWTextStore *dt = DRW_text_cache_ensure(); + DRW_text_cache_add( + dt, vec, pchan->name, strlen(pchan->name), + 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color); + } + + /* Draw additional axes */ + if (arm->flag & ARM_DRAWAXES) { + draw_axes(NULL, pchan); + } + } + } + if (is_pose_select) { + index += 0x10000; + } + } + + arm->flag &= ~ARM_POSEMODE; +} + +/** + * This function set the object space to use for all subsequent `DRW_shgroup_bone_*` calls. + */ +static void drw_shgroup_armature(Object *ob, DRWArmaturePasses passes) +{ + memset(&g_data, 0x0, sizeof(g_data)); + g_data.ob = ob; + g_data.passes = passes; + memset(&g_color, 0x0, sizeof(g_color)); +} + +void DRW_shgroup_armature_object(Object *ob, ViewLayer *view_layer, DRWArmaturePasses passes) +{ + float *color; + DRW_object_wire_theme_get(ob, view_layer, &color); + passes.bone_envelope = NULL; /* Don't do envelope distance in object mode. */ + drw_shgroup_armature(ob, passes); + draw_armature_pose(ob, color); +} + +void DRW_shgroup_armature_pose(Object *ob, DRWArmaturePasses passes) +{ + drw_shgroup_armature(ob, passes); + draw_armature_pose(ob, NULL); +} + +void DRW_shgroup_armature_edit(Object *ob, DRWArmaturePasses passes) +{ + drw_shgroup_armature(ob, passes); + draw_armature_edit(ob); +} + +/** \} */ diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c new file mode 100644 index 00000000000..b08735860c9 --- /dev/null +++ b/source/blender/draw/intern/draw_cache.c @@ -0,0 +1,3155 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_cache.c + * \ingroup draw + */ + + +#include "DNA_scene_types.h" +#include "DNA_mesh_types.h" +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_particle_types.h" +#include "DNA_modifier_types.h" +#include "DNA_lattice_types.h" + +#include "UI_resources.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "GPU_batch.h" + +#include "draw_cache.h" +#include "draw_cache_impl.h" + +/* Batch's only (free'd as an array) */ +static struct DRWShapeCache { + Gwn_Batch *drw_single_vertice; + Gwn_Batch *drw_cursor; + Gwn_Batch *drw_cursor_only_circle; + Gwn_Batch *drw_fullscreen_quad; + Gwn_Batch *drw_quad; + Gwn_Batch *drw_sphere; + Gwn_Batch *drw_screenspace_circle; + Gwn_Batch *drw_plain_axes; + Gwn_Batch *drw_single_arrow; + Gwn_Batch *drw_cube; + Gwn_Batch *drw_circle; + Gwn_Batch *drw_square; + Gwn_Batch *drw_line; + Gwn_Batch *drw_line_endpoints; + Gwn_Batch *drw_empty_sphere; + Gwn_Batch *drw_empty_cone; + Gwn_Batch *drw_arrows; + Gwn_Batch *drw_axis_names; + Gwn_Batch *drw_image_plane; + Gwn_Batch *drw_image_plane_wire; + Gwn_Batch *drw_field_wind; + Gwn_Batch *drw_field_force; + Gwn_Batch *drw_field_vortex; + Gwn_Batch *drw_field_tube_limit; + Gwn_Batch *drw_field_cone_limit; + Gwn_Batch *drw_lamp; + Gwn_Batch *drw_lamp_shadows; + Gwn_Batch *drw_lamp_sunrays; + Gwn_Batch *drw_lamp_area_square; + Gwn_Batch *drw_lamp_area_disk; + Gwn_Batch *drw_lamp_hemi; + Gwn_Batch *drw_lamp_spot; + Gwn_Batch *drw_lamp_spot_square; + Gwn_Batch *drw_speaker; + Gwn_Batch *drw_lightprobe_cube; + Gwn_Batch *drw_lightprobe_planar; + Gwn_Batch *drw_lightprobe_grid; + Gwn_Batch *drw_bone_octahedral; + Gwn_Batch *drw_bone_octahedral_wire; + Gwn_Batch *drw_bone_box; + Gwn_Batch *drw_bone_box_wire; + Gwn_Batch *drw_bone_wire_wire; + Gwn_Batch *drw_bone_envelope; + Gwn_Batch *drw_bone_envelope_outline; + Gwn_Batch *drw_bone_point; + Gwn_Batch *drw_bone_point_wire; + Gwn_Batch *drw_bone_stick; + Gwn_Batch *drw_bone_arrows; + Gwn_Batch *drw_camera; + Gwn_Batch *drw_camera_frame; + Gwn_Batch *drw_camera_tria; + Gwn_Batch *drw_camera_focus; + Gwn_Batch *drw_particle_cross; + Gwn_Batch *drw_particle_circle; + Gwn_Batch *drw_particle_axis; +} SHC = {NULL}; + +void DRW_shape_cache_free(void) +{ + uint i = sizeof(SHC) / sizeof(Gwn_Batch *); + Gwn_Batch **batch = (Gwn_Batch **)&SHC; + while (i--) { + GWN_BATCH_DISCARD_SAFE(*batch); + batch++; + } +} + + +/* -------------------------------------------------------------------- */ + +/** \name Helper functions + * \{ */ + +static void UNUSED_FUNCTION(add_fancy_edge)( + Gwn_VertBuf *vbo, uint pos_id, uint n1_id, uint n2_id, + uint *v_idx, const float co1[3], const float co2[3], + const float n1[3], const float n2[3]) +{ + GWN_vertbuf_attr_set(vbo, n1_id, *v_idx, n1); + GWN_vertbuf_attr_set(vbo, n2_id, *v_idx, n2); + GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co1); + + GWN_vertbuf_attr_set(vbo, n1_id, *v_idx, n1); + GWN_vertbuf_attr_set(vbo, n2_id, *v_idx, n2); + GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, co2); +} + +#if 0 /* UNUSED */ +static void add_lat_lon_vert( + Gwn_VertBuf *vbo, uint pos_id, uint nor_id, + uint *v_idx, const float rad, const float lat, const float lon) +{ + float pos[3], nor[3]; + nor[0] = sinf(lat) * cosf(lon); + nor[1] = cosf(lat); + nor[2] = sinf(lat) * sinf(lon); + mul_v3_v3fl(pos, nor, rad); + + GWN_vertbuf_attr_set(vbo, nor_id, *v_idx, nor); + GWN_vertbuf_attr_set(vbo, pos_id, (*v_idx)++, pos); +} +#endif + +static Gwn_VertBuf *fill_arrows_vbo(const float scale) +{ + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + /* Line */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 6 * 3); + + float v1[3] = {0.0, 0.0, 0.0}; + float v2[3] = {0.0, 0.0, 0.0}; + float vtmp1[3], vtmp2[3]; + + for (int axis = 0; axis < 3; axis++) { + const int arrow_axis = (axis == 0) ? 1 : 0; + + v2[axis] = 1.0f; + mul_v3_v3fl(vtmp1, v1, scale); + mul_v3_v3fl(vtmp2, v2, scale); + GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 0, vtmp1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 1, vtmp2); + + v1[axis] = 0.85f; + v1[arrow_axis] = -0.08f; + mul_v3_v3fl(vtmp1, v1, scale); + mul_v3_v3fl(vtmp2, v2, scale); + GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 2, vtmp1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 3, vtmp2); + + v1[arrow_axis] = 0.08f; + mul_v3_v3fl(vtmp1, v1, scale); + mul_v3_v3fl(vtmp2, v2, scale); + GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 4, vtmp1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 6 + 5, vtmp2); + + /* reset v1 & v2 to zero */ + v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f; + } + + return vbo; +} + +static Gwn_VertBuf *sphere_wire_vbo(const float rad) +{ +#define NSEGMENTS 32 + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2 * 3); + + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = rad * cosf(angle); + p[i][1] = rad * sinf(angle); + } + + for (int axis = 0; axis < 3; ++axis) { + for (int i = 0; i < NSEGMENTS; ++i) { + for (int j = 0; j < 2; ++j) { + float cv[2], v[3]; + + cv[0] = p[(i + j) % NSEGMENTS][0]; + cv[1] = p[(i + j) % NSEGMENTS][1]; + + if (axis == 0) + v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f; + else if (axis == 1) + v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; + else + v[0] = 0.0f, v[1] = cv[0], v[2] = cv[1]; + + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + j + (NSEGMENTS * 2 * axis), v); + } + } + } + + return vbo; +#undef NSEGMENTS +} + +/* Quads */ +/* Use this one for rendering fullscreen passes. For 3D objects use DRW_cache_quad_get(). */ +Gwn_Batch *DRW_cache_fullscreen_quad_get(void) +{ + if (!SHC.drw_fullscreen_quad) { + /* Use a triangle instead of a real quad */ + /* https://www.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau - slide 14 */ + float pos[3][2] = {{-1.0f, -1.0f}, { 3.0f, -1.0f}, {-1.0f, 3.0f}}; + float uvs[3][2] = {{ 0.0f, 0.0f}, { 2.0f, 0.0f}, { 0.0f, 2.0f}}; + + /* Position Only 2D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, uvs; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 3); + + for (int i = 0; i < 3; ++i) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]); + GWN_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]); + } + + SHC.drw_fullscreen_quad = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_fullscreen_quad; +} + +/* Just a regular quad with 4 vertices. */ +Gwn_Batch *DRW_cache_quad_get(void) +{ + if (!SHC.drw_quad) { + float pos[4][2] = {{-1.0f, -1.0f}, { 1.0f, -1.0f}, {1.0f, 1.0f}, {-1.0f, 1.0f}}; + float uvs[4][2] = {{ 0.0f, 0.0f}, { 1.0f, 0.0f}, {1.0f, 1.0f}, { 0.0f, 1.0f}}; + + /* Position Only 2D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, uvs; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.uvs = GWN_vertformat_attr_add(&format, "uvs", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 4); + + for (int i = 0; i < 4; ++i) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, i, pos[i]); + GWN_vertbuf_attr_set(vbo, attr_id.uvs, i, uvs[i]); + } + + SHC.drw_quad = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_quad; +} + +/* Sphere */ +Gwn_Batch *DRW_cache_sphere_get(void) +{ + if (!SHC.drw_sphere) { + SHC.drw_sphere = gpu_batch_sphere(32, 24); + } + return SHC.drw_sphere; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Common + * \{ */ + +Gwn_Batch *DRW_cache_cube_get(void) +{ + if (!SHC.drw_cube) { + const GLfloat verts[8][3] = { + {-1.0f, -1.0f, -1.0f}, + {-1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f}, + {-1.0f, 1.0f, 1.0f}, + { 1.0f, -1.0f, -1.0f}, + { 1.0f, -1.0f, 1.0f}, + { 1.0f, 1.0f, -1.0f}, + { 1.0f, 1.0f, 1.0f} + }; + + const GLubyte indices[24] = {0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 24); + + for (int i = 0; i < 24; ++i) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, i, verts[indices[i]]); + } + + SHC.drw_cube = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_cube; +} + +Gwn_Batch *DRW_cache_circle_get(void) +{ +#define CIRCLE_RESOL 64 + if (!SHC.drw_circle) { + float v[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL); + + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[1] = 0.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v); + } + + SHC.drw_circle = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_circle; +#undef CIRCLE_RESOL +} + +Gwn_Batch *DRW_cache_square_get(void) +{ + if (!SHC.drw_square) { + float p[4][3] = {{ 1.0f, 0.0f, 1.0f}, + { 1.0f, 0.0f, -1.0f}, + {-1.0f, 0.0f, -1.0f}, + {-1.0f, 0.0f, 1.0f}}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 8); + + for (int i = 0; i < 4; i++) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 2, p[i % 4]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 2 + 1, p[(i + 1) % 4]); + } + + SHC.drw_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_square; +} + +Gwn_Batch *DRW_cache_single_line_get(void) +{ + /* Z axis line */ + if (!SHC.drw_line) { + float v1[3] = {0.0f, 0.0f, 0.0f}; + float v2[3] = {0.0f, 0.0f, 1.0f}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 2); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v2); + + SHC.drw_line = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_line; +} + +Gwn_Batch *DRW_cache_single_line_endpoints_get(void) +{ + /* Z axis line */ + if (!SHC.drw_line_endpoints) { + float v1[3] = {0.0f, 0.0f, 0.0f}; + float v2[3] = {0.0f, 0.0f, 1.0f}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 2); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v2); + + SHC.drw_line_endpoints = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_line_endpoints; +} + +Gwn_Batch *DRW_cache_screenspace_circle_get(void) +{ +#define CIRCLE_RESOL 32 + if (!SHC.drw_screenspace_circle) { + float v[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL + 1); + + for (int a = 0; a <= CIRCLE_RESOL; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v); + } + + SHC.drw_screenspace_circle = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_screenspace_circle; +#undef CIRCLE_RESOL +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Common Object API + * \{ */ + +Gwn_Batch *DRW_cache_object_wire_outline_get(Object *ob) +{ + switch (ob->type) { + case OB_MESH: + return DRW_cache_mesh_wire_outline_get(ob); + + /* TODO, should match 'DRW_cache_object_surface_get' */ + default: + return NULL; + } +} + +/* Returns a buffer texture. */ +Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold) +{ + switch (ob->type) { + case OB_MESH: + return DRW_cache_mesh_edge_detection_get(ob, r_is_manifold); + + /* TODO, should match 'DRW_cache_object_surface_get' */ + default: + return NULL; + } +} + +Gwn_Batch *DRW_cache_object_surface_get(Object *ob) +{ + switch (ob->type) { + case OB_MESH: + return DRW_cache_mesh_surface_get(ob); + case OB_CURVE: + return DRW_cache_curve_surface_get(ob); + case OB_SURF: + return DRW_cache_surf_surface_get(ob); + case OB_FONT: + return DRW_cache_text_surface_get(ob); + case OB_MBALL: + return DRW_cache_mball_surface_get(ob); + default: + return NULL; + } +} + +Gwn_Batch **DRW_cache_object_surface_material_get( + struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, + char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count) +{ + if (auto_layer_names != NULL) { + *auto_layer_names = NULL; + *auto_layer_is_srgb = NULL; + *auto_layer_count = 0; + } + + switch (ob->type) { + case OB_MESH: + return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len, + auto_layer_names, auto_layer_is_srgb, auto_layer_count); + case OB_CURVE: + return DRW_cache_curve_surface_shaded_get(ob, gpumat_array, gpumat_array_len); + case OB_SURF: + return DRW_cache_surf_surface_shaded_get(ob, gpumat_array, gpumat_array_len); + case OB_FONT: + return DRW_cache_text_surface_shaded_get(ob, gpumat_array, gpumat_array_len); + default: + return NULL; + } +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Empties + * \{ */ + +Gwn_Batch *DRW_cache_plain_axes_get(void) +{ + if (!SHC.drw_plain_axes) { + int axis; + float v1[3] = {0.0f, 0.0f, 0.0f}; + float v2[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 6); + + for (axis = 0; axis < 3; axis++) { + v1[axis] = 1.0f; + v2[axis] = -1.0f; + + GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 2, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, axis * 2 + 1, v2); + + /* reset v1 & v2 to zero for next axis */ + v1[axis] = v2[axis] = 0.0f; + } + + SHC.drw_plain_axes = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_plain_axes; +} + +Gwn_Batch *DRW_cache_single_arrow_get(void) +{ + if (!SHC.drw_single_arrow) { + float v1[3] = {0.0f, 0.0f, 1.0f}, v2[3], v3[3]; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + /* Square Pyramid */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 12); + + v2[0] = 0.035f; v2[1] = 0.035f; + v3[0] = -0.035f; v3[1] = 0.035f; + v2[2] = v3[2] = 0.75f; + + for (int sides = 0; sides < 4; sides++) { + if (sides % 2 == 1) { + v2[0] = -v2[0]; + v3[1] = -v3[1]; + } + else { + v2[1] = -v2[1]; + v3[0] = -v3[0]; + } + + GWN_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 0, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 1, v2); + GWN_vertbuf_attr_set(vbo, attr_id.pos, sides * 3 + 2, v3); + } + + SHC.drw_single_arrow = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_single_arrow; +} + +Gwn_Batch *DRW_cache_empty_sphere_get(void) +{ + if (!SHC.drw_empty_sphere) { + Gwn_VertBuf *vbo = sphere_wire_vbo(1.0f); + SHC.drw_empty_sphere = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_empty_sphere; +} + +Gwn_Batch *DRW_cache_empty_cone_get(void) +{ +#define NSEGMENTS 8 + if (!SHC.drw_empty_cone) { + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = cosf(angle); + p[i][1] = sinf(angle); + } + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 4); + + for (int i = 0; i < NSEGMENTS; ++i) { + float cv[2], v[3]; + cv[0] = p[(i) % NSEGMENTS][0]; + cv[1] = p[(i) % NSEGMENTS][1]; + + /* cone sides */ + v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v); + v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v); + + /* end ring */ + v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 2, v); + cv[0] = p[(i + 1) % NSEGMENTS][0]; + cv[1] = p[(i + 1) % NSEGMENTS][1]; + v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1]; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v); + } + + SHC.drw_empty_cone = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_empty_cone; +#undef NSEGMENTS +} + +Gwn_Batch *DRW_cache_arrows_get(void) +{ + if (!SHC.drw_arrows) { + Gwn_VertBuf *vbo = fill_arrows_vbo(1.0f); + + SHC.drw_arrows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_arrows; +} + +Gwn_Batch *DRW_cache_axis_names_get(void) +{ + if (!SHC.drw_axis_names) { + const float size = 0.1f; + float v1[3], v2[3]; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + /* Using 3rd component as axis indicator */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + /* Line */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 14); + + /* X */ + copy_v3_fl3(v1, -size, size, 0.0f); + copy_v3_fl3(v2, size, -size, 0.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v2); + + copy_v3_fl3(v1, size, size, 0.0f); + copy_v3_fl3(v2, -size, -size, 0.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 3, v2); + + /* Y */ + copy_v3_fl3(v1, -size + 0.25f * size, size, 1.0f); + copy_v3_fl3(v2, 0.0f, 0.0f, 1.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 4, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 5, v2); + + copy_v3_fl3(v1, size - 0.25f * size, size, 1.0f); + copy_v3_fl3(v2, -size + 0.25f * size, -size, 1.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 6, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 7, v2); + + /* Z */ + copy_v3_fl3(v1, -size, size, 2.0f); + copy_v3_fl3(v2, size, size, 2.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 8, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 9, v2); + + copy_v3_fl3(v1, size, size, 2.0f); + copy_v3_fl3(v2, -size, -size, 2.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 10, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 11, v2); + + copy_v3_fl3(v1, -size, -size, 2.0f); + copy_v3_fl3(v2, size, -size, 2.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 12, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 13, v2); + + SHC.drw_axis_names = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_axis_names; +} + +Gwn_Batch *DRW_cache_image_plane_get(void) +{ + if (!SHC.drw_image_plane) { + const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, texCoords; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.texCoords = GWN_vertformat_attr_add(&format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 4); + for (uint j = 0; j < 4; j++) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]); + GWN_vertbuf_attr_set(vbo, attr_id.texCoords, j, quad[j]); + } + SHC.drw_image_plane = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_image_plane; +} + +Gwn_Batch *DRW_cache_image_plane_wire_get(void) +{ + if (!SHC.drw_image_plane_wire) { + const float quad[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 4); + for (uint j = 0; j < 4; j++) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, j, quad[j]); + } + SHC.drw_image_plane_wire = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_image_plane_wire; +} + +/* Force Field */ +Gwn_Batch *DRW_cache_field_wind_get(void) +{ +#define CIRCLE_RESOL 32 + if (!SHC.drw_field_wind) { + float v[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 4); + + for (int i = 0; i < 4; i++) { + float z = 0.05f * (float)i; + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[2] = z; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2, v); + + v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[2] = z; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v); + } + } + + SHC.drw_field_wind = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_field_wind; +#undef CIRCLE_RESOL +} + +Gwn_Batch *DRW_cache_field_force_get(void) +{ +#define CIRCLE_RESOL 32 + if (!SHC.drw_field_force) { + float v[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 3); + + for (int i = 0; i < 3; i++) { + float radius = 1.0f + 0.5f * (float)i; + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[2] = 0.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2, v); + + v[0] = radius * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[1] = radius * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[2] = 0.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * CIRCLE_RESOL * 2 + a * 2 + 1, v); + } + } + + SHC.drw_field_force = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_field_force; +#undef CIRCLE_RESOL +} + +Gwn_Batch *DRW_cache_field_vortex_get(void) +{ +#define SPIRAL_RESOL 32 + if (!SHC.drw_field_vortex) { + float v[3] = {0.0f, 0.0f, 0.0f}; + uint v_idx = 0; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, SPIRAL_RESOL * 2 + 1); + + for (int a = SPIRAL_RESOL; a > -1; a--) { + v[0] = sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL); + v[1] = cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v); + } + + for (int a = 1; a <= SPIRAL_RESOL; a++) { + v[0] = -sinf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL); + v[1] = -cosf((2.0f * M_PI * a) / ((float)SPIRAL_RESOL)) * (a / (float)SPIRAL_RESOL); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v); + } + + SHC.drw_field_vortex = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_field_vortex; +#undef SPIRAL_RESOL +} + +Gwn_Batch *DRW_cache_field_tube_limit_get(void) +{ +#define CIRCLE_RESOL 32 + if (!SHC.drw_field_tube_limit) { + float v[3] = {0.0f, 0.0f, 0.0f}; + uint v_idx = 0; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8); + + /* Caps */ + for (int i = 0; i < 2; i++) { + float z = (float)i * 2.0f - 1.0f; + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[2] = z; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v); + + v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[2] = z; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v); + } + } + /* Side Edges */ + for (int a = 0; a < 4; a++) { + for (int i = 0; i < 2; i++) { + float z = (float)i * 2.0f - 1.0f; + v[0] = sinf((2.0f * M_PI * a) / 4.0f); + v[1] = cosf((2.0f * M_PI * a) / 4.0f); + v[2] = z; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v); + } + } + + SHC.drw_field_tube_limit = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_field_tube_limit; +#undef CIRCLE_RESOL +} + +Gwn_Batch *DRW_cache_field_cone_limit_get(void) +{ +#define CIRCLE_RESOL 32 + if (!SHC.drw_field_cone_limit) { + float v[3] = {0.0f, 0.0f, 0.0f}; + uint v_idx = 0; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 + 8); + + /* Caps */ + for (int i = 0; i < 2; i++) { + float z = (float)i * 2.0f - 1.0f; + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[2] = z; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v); + + v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[2] = z; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v); + } + } + /* Side Edges */ + for (int a = 0; a < 4; a++) { + for (int i = 0; i < 2; i++) { + float z = (float)i * 2.0f - 1.0f; + v[0] = z * sinf((2.0f * M_PI * a) / 4.0f); + v[1] = z * cosf((2.0f * M_PI * a) / 4.0f); + v[2] = z; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v); + } + } + + SHC.drw_field_cone_limit = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_field_cone_limit; +#undef CIRCLE_RESOL +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Lamps + * \{ */ + +Gwn_Batch *DRW_cache_lamp_get(void) +{ +#define NSEGMENTS 8 + if (!SHC.drw_lamp) { + float v[2]; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2); + + for (int a = 0; a < NSEGMENTS * 2; a += 2) { + v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2)); + v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v); + + v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2)); + v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v); + } + + SHC.drw_lamp = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp; +#undef NSEGMENTS +} + +Gwn_Batch *DRW_cache_lamp_shadows_get(void) +{ +#define NSEGMENTS 10 + if (!SHC.drw_lamp_shadows) { + float v[2]; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2); + + for (int a = 0; a < NSEGMENTS * 2; a += 2) { + v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2)); + v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v); + + v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2)); + v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v); + } + + SHC.drw_lamp_shadows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp_shadows; +#undef NSEGMENTS +} + +Gwn_Batch *DRW_cache_lamp_sunrays_get(void) +{ + if (!SHC.drw_lamp_sunrays) { + float v[2], v1[2], v2[2]; + + /* Position Only 2D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 32); + + for (int a = 0; a < 8; a++) { + v[0] = sinf((2.0f * M_PI * a) / 8.0f); + v[1] = cosf((2.0f * M_PI * a) / 8.0f); + + mul_v2_v2fl(v1, v, 1.6f); + mul_v2_v2fl(v2, v, 1.9f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 1, v2); + + mul_v2_v2fl(v1, v, 2.2f); + mul_v2_v2fl(v2, v, 2.5f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 2, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 3, v2); + } + + SHC.drw_lamp_sunrays = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp_sunrays; +} + +Gwn_Batch *DRW_cache_lamp_area_square_get(void) +{ + if (!SHC.drw_lamp_area_square) { + float v1[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 8); + + v1[0] = v1[1] = 0.5f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1); + v1[0] = -0.5f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, 1, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2, v1); + v1[1] = -0.5f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, 3, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 4, v1); + v1[0] = 0.5f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, 5, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 6, v1); + v1[1] = 0.5f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, 7, v1); + + SHC.drw_lamp_area_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp_area_square; +} + +Gwn_Batch *DRW_cache_lamp_area_disk_get(void) +{ +#define NSEGMENTS 32 + if (!SHC.drw_lamp_area_disk) { + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 2 * NSEGMENTS); + + float v[3] = {0.0f, 0.5f, 0.0f}; + GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v); + for (int a = 1; a < NSEGMENTS; a++) { + v[0] = 0.5f * sinf(2.0f * (float)M_PI * a / NSEGMENTS); + v[1] = 0.5f * cosf(2.0f * (float)M_PI * a / NSEGMENTS); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * a - 1, v); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * a, v); + } + copy_v3_fl3(v, 0.0f, 0.5f, 0.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, (2 * NSEGMENTS) - 1, v); + + SHC.drw_lamp_area_disk = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp_area_disk; +#undef NSEGMENTS +} + +Gwn_Batch *DRW_cache_lamp_hemi_get(void) +{ +#define CIRCLE_RESOL 32 + if (!SHC.drw_lamp_hemi) { + float v[3]; + int vidx = 0; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL * 2 * 2 - 6 * 2 * 2); + + /* XZ plane */ + for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2); + v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f; + v[1] = 0.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + + v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2); + v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f; + v[1] = 0.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + } + + /* XY plane */ + for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) { + v[2] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)) - 1.0f; + v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[0] = 0.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + + v[2] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)) - 1.0f; + v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[0] = 0.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + } + + /* YZ plane full circle */ + /* lease v[2] as it is */ + const float rad = cosf((2.0f * M_PI * 3) / ((float)CIRCLE_RESOL)); + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[1] = rad * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[0] = rad * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + + v[1] = rad * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[0] = rad * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + } + + + SHC.drw_lamp_hemi = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp_hemi; +#undef CIRCLE_RESOL +} + + +Gwn_Batch *DRW_cache_lamp_spot_get(void) +{ +#define NSEGMENTS 32 + if (!SHC.drw_lamp_spot) { + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + float n[NSEGMENTS][3]; + float neg[NSEGMENTS][3]; + float half_angle = 2 * M_PI / ((float)NSEGMENTS * 2); + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = cosf(angle); + p[i][1] = sinf(angle); + + n[i][0] = cosf(angle - half_angle); + n[i][1] = sinf(angle - half_angle); + n[i][2] = cosf(M_PI / 16.0f); /* slope of the cone */ + normalize_v3(n[i]); /* necessary ? */ + negate_v3_v3(neg[i], n[i]); + } + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, n1, n2; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 4); + + for (int i = 0; i < NSEGMENTS; ++i) { + float cv[2], v[3]; + cv[0] = p[i % NSEGMENTS][0]; + cv[1] = p[i % NSEGMENTS][1]; + + /* cone sides */ + v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4, v); + v[0] = 0.0f, v[1] = 0.0f, v[2] = 0.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 1, v); + + GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4, n[(i) % NSEGMENTS]); + GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 1, n[(i) % NSEGMENTS]); + GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4, n[(i + 1) % NSEGMENTS]); + GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 1, n[(i + 1) % NSEGMENTS]); + + /* end ring */ + v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 2, v); + cv[0] = p[(i + 1) % NSEGMENTS][0]; + cv[1] = p[(i + 1) % NSEGMENTS][1]; + v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f; + GWN_vertbuf_attr_set(vbo, attr_id.pos, i * 4 + 3, v); + + GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 2, n[(i) % NSEGMENTS]); + GWN_vertbuf_attr_set(vbo, attr_id.n1, i * 4 + 3, n[(i) % NSEGMENTS]); + GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 2, neg[(i) % NSEGMENTS]); + GWN_vertbuf_attr_set(vbo, attr_id.n2, i * 4 + 3, neg[(i) % NSEGMENTS]); + } + + SHC.drw_lamp_spot = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp_spot; +#undef NSEGMENTS +} + +Gwn_Batch *DRW_cache_lamp_spot_square_get(void) +{ + if (!SHC.drw_lamp_spot_square) { + float p[5][3] = {{ 0.0f, 0.0f, 0.0f}, + { 1.0f, 1.0f, -1.0f}, + { 1.0f, -1.0f, -1.0f}, + {-1.0f, -1.0f, -1.0f}, + {-1.0f, 1.0f, -1.0f}}; + + uint v_idx = 0; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 16); + + /* piramid sides */ + for (int i = 1; i <= 4; ++i) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[0]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[i]); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[(i % 4) + 1]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, p[((i + 1) % 4) + 1]); + } + + SHC.drw_lamp_spot_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp_spot_square; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Speaker + * \{ */ + +Gwn_Batch *DRW_cache_speaker_get(void) +{ + if (!SHC.drw_speaker) { + float v[3]; + const int segments = 16; + int vidx = 0; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 3 * segments * 2 + 4 * 4); + + for (int j = 0; j < 3; j++) { + float z = 0.25f * j - 0.125f; + float r = (j == 0 ? 0.5f : 0.25f); + + copy_v3_fl3(v, r, 0.0f, z); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + for (int i = 1; i < segments; i++) { + float x = cosf(2.f * (float)M_PI * i / segments) * r; + float y = sinf(2.f * (float)M_PI * i / segments) * r; + copy_v3_fl3(v, x, y, z); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + } + copy_v3_fl3(v, r, 0.0f, z); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + } + + for (int j = 0; j < 4; j++) { + float x = (((j + 1) % 2) * (j - 1)) * 0.5f; + float y = ((j % 2) * (j - 2)) * 0.5f; + for (int i = 0; i < 3; i++) { + if (i == 1) { + x *= 0.5f; + y *= 0.5f; + } + + float z = 0.25f * i - 0.125f; + copy_v3_fl3(v, x, y, z); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + if (i == 1) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, v); + } + } + } + + SHC.drw_speaker = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_speaker; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Probe + * \{ */ + +Gwn_Batch *DRW_cache_lightprobe_cube_get(void) +{ + if (!SHC.drw_lightprobe_cube) { + int v_idx = 0; + const float sin_pi_3 = 0.86602540378f; + const float cos_pi_3 = 0.5f; + float v[7][3] = { + {0.0f, 1.0f, 0.0f}, + {sin_pi_3, cos_pi_3, 0.0f}, + {sin_pi_3, -cos_pi_3, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {-sin_pi_3, -cos_pi_3, 0.0f}, + {-sin_pi_3, cos_pi_3, 0.0f}, + {0.0f, 0.0f, 0.0f}, + }; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, (6 + 3) * 2); + + for (int i = 0; i < 6; ++i) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 6]); + } + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]); + + SHC.drw_lightprobe_cube = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lightprobe_cube; +} + +Gwn_Batch *DRW_cache_lightprobe_grid_get(void) +{ + if (!SHC.drw_lightprobe_grid) { + int v_idx = 0; + const float sin_pi_3 = 0.86602540378f; + const float cos_pi_3 = 0.5f; + const float v[7][3] = { + {0.0f, 1.0f, 0.0f}, + {sin_pi_3, cos_pi_3, 0.0f}, + {sin_pi_3, -cos_pi_3, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {-sin_pi_3, -cos_pi_3, 0.0f}, + {-sin_pi_3, cos_pi_3, 0.0f}, + {0.0f, 0.0f, 0.0f}, + }; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, (6 * 2 + 3) * 2); + + for (int i = 0; i < 6; ++i) { + float tmp_v1[3], tmp_v2[3], tmp_tr[3]; + copy_v3_v3(tmp_v1, v[i]); + copy_v3_v3(tmp_v2, v[(i + 1) % 6]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2); + + /* Internal wires. */ + for (int j = 1; j < 2; ++j) { + mul_v3_v3fl(tmp_tr, v[(i / 2) * 2 + 1], -0.5f * j); + add_v3_v3v3(tmp_v1, v[i], tmp_tr); + add_v3_v3v3(tmp_v2, v[(i + 1) % 6], tmp_tr); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, tmp_v2); + } + } + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[1]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[5]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[3]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[6]); + + SHC.drw_lightprobe_grid = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lightprobe_grid; +} + +Gwn_Batch *DRW_cache_lightprobe_planar_get(void) +{ + if (!SHC.drw_lightprobe_planar) { + int v_idx = 0; + const float sin_pi_3 = 0.86602540378f; + float v[4][3] = { + {0.0f, 0.5f, 0.0f}, + {sin_pi_3, 0.0f, 0.0f}, + {0.0f, -0.5f, 0.0f}, + {-sin_pi_3, 0.0f, 0.0f}, + }; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 4 * 2); + + for (int i = 0; i < 4; ++i) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[i]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, v[(i + 1) % 4]); + } + + SHC.drw_lightprobe_planar = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lightprobe_planar; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Armature Bones + * \{ */ + +static const float bone_octahedral_verts[6][3] = { + { 0.0f, 0.0f, 0.0f}, + { 0.1f, 0.1f, 0.1f}, + { 0.1f, 0.1f, -0.1f}, + {-0.1f, 0.1f, -0.1f}, + {-0.1f, 0.1f, 0.1f}, + { 0.0f, 1.0f, 0.0f} +}; + +static const float bone_octahedral_smooth_normals[6][3] = { + { 0.0f, -1.0f, 0.0f}, +#if 0 /* creates problems for outlines when scaled */ + { 0.943608f * M_SQRT1_2, -0.331048f, 0.943608f * M_SQRT1_2}, + { 0.943608f * M_SQRT1_2, -0.331048f, -0.943608f * M_SQRT1_2}, + {-0.943608f * M_SQRT1_2, -0.331048f, -0.943608f * M_SQRT1_2}, + {-0.943608f * M_SQRT1_2, -0.331048f, 0.943608f * M_SQRT1_2}, +#else + { M_SQRT1_2, 0.0f, M_SQRT1_2}, + { M_SQRT1_2, 0.0f, -M_SQRT1_2}, + {-M_SQRT1_2, 0.0f, -M_SQRT1_2}, + {-M_SQRT1_2, 0.0f, M_SQRT1_2}, +#endif + { 0.0f, 1.0f, 0.0f} +}; + +#if 0 /* UNUSED */ + +static const uint bone_octahedral_wire[24] = { + 0, 1, 1, 5, 5, 3, 3, 0, + 0, 4, 4, 5, 5, 2, 2, 0, + 1, 2, 2, 3, 3, 4, 4, 1, +}; + +/* aligned with bone_octahedral_wire + * Contains adjacent normal index */ +static const uint bone_octahedral_wire_adjacent_face[24] = { + 0, 3, 4, 7, 5, 6, 1, 2, + 2, 3, 6, 7, 4, 5, 0, 1, + 0, 4, 1, 5, 2, 6, 3, 7, +}; +#endif + +static const uint bone_octahedral_solid_tris[8][3] = { + {2, 1, 0}, /* bottom */ + {3, 2, 0}, + {4, 3, 0}, + {1, 4, 0}, + + {5, 1, 2}, /* top */ + {5, 2, 3}, + {5, 3, 4}, + {5, 4, 1} +}; + +/** + * Store indices of generated verts from bone_octahedral_solid_tris to define adjacency infos. + * Example: triangle {2, 1, 0} is adjacent to {3, 2, 0}, {1, 4, 0} and {5, 1, 2}. + * {2, 1, 0} becomes {0, 1, 2} + * {3, 2, 0} becomes {3, 4, 5} + * {1, 4, 0} becomes {9, 10, 11} + * {5, 1, 2} becomes {12, 13, 14} + * According to opengl specification it becomes (starting from + * the first vertex of the first face aka. vertex 2): + * {0, 12, 1, 10, 2, 3} + **/ +static const uint bone_octahedral_wire_lines_adjacency[12][4] = { + { 0, 1, 2, 6}, { 0, 12, 1, 6}, { 0, 3, 12, 6}, { 0, 2, 3, 6}, + { 1, 6, 2, 3}, { 1, 12, 6, 3}, { 1, 0, 12, 3}, { 1, 2, 0, 3}, + { 2, 0, 1, 12}, { 2, 3, 0, 12}, { 2, 6, 3, 12}, { 2, 1, 6, 12}, +}; + +#if 0 /* UNUSED */ +static const uint bone_octahedral_solid_tris_adjacency[8][6] = { + { 0, 12, 1, 10, 2, 3}, + { 3, 15, 4, 1, 5, 6}, + { 6, 18, 7, 4, 8, 9}, + { 9, 21, 10, 7, 11, 0}, + + {12, 22, 13, 2, 14, 17}, + {15, 13, 16, 5, 17, 20}, + {18, 16, 19, 8, 20, 23}, + {21, 19, 22, 11, 23, 14}, +}; +#endif + +/* aligned with bone_octahedral_solid_tris */ +static const float bone_octahedral_solid_normals[8][3] = { + { M_SQRT1_2, -M_SQRT1_2, 0.00000000f}, + {-0.00000000f, -M_SQRT1_2, -M_SQRT1_2}, + {-M_SQRT1_2, -M_SQRT1_2, 0.00000000f}, + { 0.00000000f, -M_SQRT1_2, M_SQRT1_2}, + { 0.99388373f, 0.11043154f, -0.00000000f}, + { 0.00000000f, 0.11043154f, -0.99388373f}, + {-0.99388373f, 0.11043154f, 0.00000000f}, + { 0.00000000f, 0.11043154f, 0.99388373f} +}; + +Gwn_Batch *DRW_cache_bone_octahedral_get(void) +{ + if (!SHC.drw_bone_octahedral) { + uint v_idx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, nor, snor; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.snor = GWN_vertformat_attr_add(&format, "snor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + /* Vertices */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 24); + + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 3; ++j) { + GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]); + GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][j]]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][j]]); + } + } + + SHC.drw_bone_octahedral = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, + GWN_BATCH_OWNS_VBO); + } + return SHC.drw_bone_octahedral; +} + +Gwn_Batch *DRW_cache_bone_octahedral_wire_get(void) +{ + if (!SHC.drw_bone_octahedral_wire) { + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, 12, 24); + + for (int i = 0; i < 12; i++) { + GWN_indexbuf_add_line_adj_verts(&elb, + bone_octahedral_wire_lines_adjacency[i][0], + bone_octahedral_wire_lines_adjacency[i][1], + bone_octahedral_wire_lines_adjacency[i][2], + bone_octahedral_wire_lines_adjacency[i][3]); + } + + /* HACK Reuse vertex buffer. */ + Gwn_Batch *pos_nor_batch = DRW_cache_bone_octahedral_get(); + + SHC.drw_bone_octahedral_wire = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GWN_indexbuf_build(&elb), + GWN_BATCH_OWNS_INDEX); + } + return SHC.drw_bone_octahedral_wire; +} + +/* XXX TODO move that 1 unit cube to more common/generic place? */ +static const float bone_box_verts[8][3] = { + { 1.0f, 0.0f, 1.0f}, + { 1.0f, 0.0f, -1.0f}, + {-1.0f, 0.0f, -1.0f}, + {-1.0f, 0.0f, 1.0f}, + { 1.0f, 1.0f, 1.0f}, + { 1.0f, 1.0f, -1.0f}, + {-1.0f, 1.0f, -1.0f}, + {-1.0f, 1.0f, 1.0f} +}; + +static const float bone_box_smooth_normals[8][3] = { + { M_SQRT3, -M_SQRT3, M_SQRT3}, + { M_SQRT3, -M_SQRT3, -M_SQRT3}, + {-M_SQRT3, -M_SQRT3, -M_SQRT3}, + {-M_SQRT3, -M_SQRT3, M_SQRT3}, + { M_SQRT3, M_SQRT3, M_SQRT3}, + { M_SQRT3, M_SQRT3, -M_SQRT3}, + {-M_SQRT3, M_SQRT3, -M_SQRT3}, + {-M_SQRT3, M_SQRT3, M_SQRT3}, +}; + +#if 0 /* UNUSED */ +static const uint bone_box_wire[24] = { + 0, 1, 1, 2, 2, 3, 3, 0, + 4, 5, 5, 6, 6, 7, 7, 4, + 0, 4, 1, 5, 2, 6, 3, 7, +}; + +/* aligned with bone_octahedral_wire + * Contains adjacent normal index */ +static const uint bone_box_wire_adjacent_face[24] = { + 0, 2, 0, 4, 1, 6, 1, 8, + 3, 10, 5, 10, 7, 11, 9, 11, + 3, 8, 2, 5, 4, 7, 6, 9, +}; +#endif + +static const uint bone_box_solid_tris[12][3] = { + {0, 2, 1}, /* bottom */ + {0, 3, 2}, + + {0, 1, 5}, /* sides */ + {0, 5, 4}, + + {1, 2, 6}, + {1, 6, 5}, + + {2, 3, 7}, + {2, 7, 6}, + + {3, 0, 4}, + {3, 4, 7}, + + {4, 5, 6}, /* top */ + {4, 6, 7}, +}; + +/** + * Store indices of generated verts from bone_box_solid_tris to define adjacency infos. + * See bone_octahedral_solid_tris for more infos. + **/ +static const uint bone_box_wire_lines_adjacency[12][4] = { + { 4, 2, 0, 11}, { 0, 1, 2, 8}, { 2, 4, 1, 14}, { 1, 0, 4, 20}, /* bottom */ + { 0, 8, 11, 14}, { 2, 14, 8, 20}, { 1, 20, 14, 11}, { 4, 11, 20, 8}, /* top */ + { 20, 0, 11, 2}, { 11, 2, 8, 1}, { 8, 1, 14, 4}, { 14, 4, 20, 0}, /* sides */ +}; + +#if 0 /* UNUSED */ +static const uint bone_box_solid_tris_adjacency[12][6] = { + { 0, 5, 1, 14, 2, 8}, + { 3, 26, 4, 20, 5, 1}, + + { 6, 2, 7, 16, 8, 11}, + { 9, 7, 10, 32, 11, 24}, + + {12, 0, 13, 22, 14, 17}, + {15, 13, 16, 30, 17, 6}, + + {18, 3, 19, 28, 20, 23}, + {21, 19, 22, 33, 23, 12}, + + {24, 4, 25, 10, 26, 29}, + {27, 25, 28, 34, 29, 18}, + + {30, 9, 31, 15, 32, 35}, + {33, 31, 34, 21, 35, 27}, +}; +#endif + +/* aligned with bone_box_solid_tris */ +static const float bone_box_solid_normals[12][3] = { + { 0.0f, -1.0f, 0.0f}, + { 0.0f, -1.0f, 0.0f}, + + { 1.0f, 0.0f, 0.0f}, + { 1.0f, 0.0f, 0.0f}, + + { 0.0f, 0.0f, -1.0f}, + { 0.0f, 0.0f, -1.0f}, + + {-1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + + { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f, 1.0f}, + + { 0.0f, 1.0f, 0.0f}, + { 0.0f, 1.0f, 0.0f}, +}; + +Gwn_Batch *DRW_cache_bone_box_get(void) +{ + if (!SHC.drw_bone_box) { + uint v_idx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, nor, snor; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.snor = GWN_vertformat_attr_add(&format, "snor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + /* Vertices */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 36); + + for (int i = 0; i < 12; i++) { + for (int j = 0; j < 3; j++) { + GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_box_solid_normals[i]); + GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_box_smooth_normals[bone_box_solid_tris[i][j]]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]); + } + } + + SHC.drw_bone_box = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, + GWN_BATCH_OWNS_VBO); + } + return SHC.drw_bone_box; +} + +Gwn_Batch *DRW_cache_bone_box_wire_get(void) +{ + if (!SHC.drw_bone_box_wire) { + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, 12, 36); + + for (int i = 0; i < 12; i++) { + GWN_indexbuf_add_line_adj_verts(&elb, + bone_box_wire_lines_adjacency[i][0], + bone_box_wire_lines_adjacency[i][1], + bone_box_wire_lines_adjacency[i][2], + bone_box_wire_lines_adjacency[i][3]); + } + + /* HACK Reuse vertex buffer. */ + Gwn_Batch *pos_nor_batch = DRW_cache_bone_box_get(); + + SHC.drw_bone_box_wire = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GWN_indexbuf_build(&elb), + GWN_BATCH_OWNS_INDEX); + } + return SHC.drw_bone_box_wire; +} + +/* Helpers for envelope bone's solid sphere-with-hidden-equatorial-cylinder. + * Note that here we only encode head/tail in forth component of the vector. */ +static void benv_lat_lon_to_co(const float lat, const float lon, float r_nor[3]) +{ + r_nor[0] = sinf(lat) * cosf(lon); + r_nor[1] = sinf(lat) * sinf(lon); + r_nor[2] = cosf(lat); +} + +Gwn_Batch *DRW_cache_bone_envelope_solid_get(void) +{ + if (!SHC.drw_bone_envelope) { + const int lon_res = 24; + const int lat_res = 24; + const float lon_inc = 2.0f * M_PI / lon_res; + const float lat_inc = M_PI / lat_res; + uint v_idx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + /* Vertices */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, ((lat_res + 1) * 2) * lon_res * 1); + + float lon = 0.0f; + for (int i = 0; i < lon_res; i++, lon += lon_inc) { + float lat = 0.0f; + float co1[3], co2[3]; + + /* Note: the poles are duplicated on purpose, to restart the strip. */ + + /* 1st sphere */ + for (int j = 0; j < lat_res; j++, lat += lat_inc) { + benv_lat_lon_to_co(lat, lon, co1); + benv_lat_lon_to_co(lat, lon + lon_inc, co2); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2); + } + + /* Closing the loop */ + benv_lat_lon_to_co(M_PI, lon, co1); + benv_lat_lon_to_co(M_PI, lon + lon_inc, co2); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2); + } + + SHC.drw_bone_envelope = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_bone_envelope; +} + +Gwn_Batch *DRW_cache_bone_envelope_outline_get(void) +{ + if (!SHC.drw_bone_envelope_outline) { +# define CIRCLE_RESOL 64 + float v0[2], v1[2], v2[2]; + const float radius = 1.0f; + + /* Position Only 2D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos0, pos1, pos2; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos0 = GWN_vertformat_attr_add(&format, "pos0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.pos1 = GWN_vertformat_attr_add(&format, "pos1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.pos2 = GWN_vertformat_attr_add(&format, "pos2", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, (CIRCLE_RESOL + 1) * 2); + + v0[0] = radius * sinf((2.0f * M_PI * -2) / ((float)CIRCLE_RESOL)); + v0[1] = radius * cosf((2.0f * M_PI * -2) / ((float)CIRCLE_RESOL)); + v1[0] = radius * sinf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL)); + v1[1] = radius * cosf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL)); + + /* Output 4 verts for each position. See shader for explanation. */ + uint v = 0; + for (int a = 0; a < CIRCLE_RESOL; a++) { + v2[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v2[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos1, v, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos1, v, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2); + copy_v2_v2(v0, v1); + copy_v2_v2(v1, v2); + } + v2[0] = 0.0f; + v2[1] = radius; + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos1, v, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos1, v, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos2, v++, v2); + + SHC.drw_bone_envelope_outline = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); +# undef CIRCLE_RESOL + } + return SHC.drw_bone_envelope_outline; +} + +Gwn_Batch *DRW_cache_bone_point_get(void) +{ + if (!SHC.drw_bone_point) { +#if 0 /* old style geometry sphere */ + const int lon_res = 16; + const int lat_res = 8; + const float rad = 0.05f; + const float lon_inc = 2 * M_PI / lon_res; + const float lat_inc = M_PI / lat_res; + uint v_idx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, nor; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + /* Vertices */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, (lat_res - 1) * lon_res * 6); + + float lon = 0.0f; + for (int i = 0; i < lon_res; i++, lon += lon_inc) { + float lat = 0.0f; + for (int j = 0; j < lat_res; j++, lat += lat_inc) { + if (j != lat_res - 1) { /* Pole */ + add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc); + add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon); + add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon); + } + + if (j != 0) { /* Pole */ + add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon + lon_inc); + add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat + lat_inc, lon + lon_inc); + add_lat_lon_vert(vbo, attr_id.pos, attr_id.nor, &v_idx, rad, lat, lon); + } + } + } + + SHC.drw_bone_point = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO); +#else +# define CIRCLE_RESOL 64 + float v[2]; + const float radius = 0.05f; + + /* Position Only 2D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL); + + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v); + } + + SHC.drw_bone_point = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO); +# undef CIRCLE_RESOL +#endif + } + return SHC.drw_bone_point; +} + +Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void) +{ + if (!SHC.drw_bone_point_wire) { +#if 0 /* old style geometry sphere */ + Gwn_VertBuf *vbo = sphere_wire_vbo(0.05f); + SHC.drw_bone_point_wire = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); +#else +# define CIRCLE_RESOL 64 + float v0[2], v1[2]; + const float radius = 0.05f; + + /* Position Only 2D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos0, pos1; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos0 = GWN_vertformat_attr_add(&format, "pos0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.pos1 = GWN_vertformat_attr_add(&format, "pos1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, (CIRCLE_RESOL + 1) * 2); + + v0[0] = radius * sinf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL)); + v0[1] = radius * cosf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL)); + + uint v = 0; + for (int a = 0; a < CIRCLE_RESOL; a++) { + v1[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v1[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1); + copy_v2_v2(v0, v1); + } + v1[0] = 0.0f; + v1[1] = radius; + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1); + + SHC.drw_bone_point_wire = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); +# undef CIRCLE_RESOL +#endif + } + return SHC.drw_bone_point_wire; +} + +/* keep in sync with armature_stick_vert.glsl */ +#define COL_WIRE (1 << 0) +#define COL_HEAD (1 << 1) +#define COL_TAIL (1 << 2) +#define COL_BONE (1 << 3) + +#define POS_HEAD (1 << 4) +#define POS_TAIL (1 << 5) +#define POS_BONE (1 << 6) + +Gwn_Batch *DRW_cache_bone_stick_get(void) +{ + if (!SHC.drw_bone_stick) { +#define CIRCLE_RESOL 12 + uint v = 0; + uint flag; + const float radius = 2.0f; /* head/tail radius */ + float pos[2]; + + /* Position Only 2D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, flag; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.flag = GWN_vertformat_attr_add(&format, "flag", GWN_COMP_U32, 1, GWN_FETCH_INT); + } + + const uint vcount = (CIRCLE_RESOL + 1) * 2 + 6; + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vcount); + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init_ex(&elb, GWN_PRIM_TRI_FAN, (CIRCLE_RESOL + 2) * 2 + 6 + 2, vcount, true); + + /* head/tail points */ + for (int i = 0; i < 2; ++i) { + /* center vertex */ + copy_v2_fl(pos, 0.0f); + flag = (i == 0) ? POS_HEAD : POS_TAIL; + flag |= (i == 0) ? COL_HEAD : COL_TAIL; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, pos); + GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag); + GWN_indexbuf_add_generic_vert(&elb, v++); + /* circle vertices */ + flag |= COL_WIRE; + for (int a = 0; a < CIRCLE_RESOL; a++) { + pos[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + pos[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, pos); + GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag); + GWN_indexbuf_add_generic_vert(&elb, v++); + } + /* Close the circle */ + GWN_indexbuf_add_generic_vert(&elb, v - CIRCLE_RESOL); + + GWN_indexbuf_add_primitive_restart(&elb); + } + + /* Bone rectangle */ + pos[0] = 0.0f; + for (int i = 0; i < 6; ++i) { + pos[1] = (i == 0 || i == 3) ? 0.0f : ((i < 3) ? 1.0f : -1.0f); + flag = ((i < 2 || i > 4) ? POS_HEAD : POS_TAIL) | + ((i == 0 || i == 3) ? 0 : COL_WIRE) | COL_BONE | POS_BONE; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, pos); + GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag); + GWN_indexbuf_add_generic_vert(&elb, v++); + } + + SHC.drw_bone_stick = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, GWN_indexbuf_build(&elb), GWN_BATCH_OWNS_VBO); +#undef CIRCLE_RESOL + } + return SHC.drw_bone_stick; +} + +static void set_bone_axis_vert( + Gwn_VertBuf *vbo, uint axis, uint pos, uint col, + uint *v, const float *a, const float *p, const float *c) +{ + GWN_vertbuf_attr_set(vbo, axis, *v, a); + GWN_vertbuf_attr_set(vbo, pos, *v, p); + GWN_vertbuf_attr_set(vbo, col, *v, c); + *v += 1; +} + +#define S_X 0.0215f +#define S_Y 0.025f +static float x_axis_name[4][2] = { + { 0.9f * S_X, 1.0f * S_Y}, {-1.0f * S_X, -1.0f * S_Y}, + {-0.9f * S_X, 1.0f * S_Y}, { 1.0f * S_X, -1.0f * S_Y} +}; +#define X_LEN (sizeof(x_axis_name) / (sizeof(float) * 2)) +#undef S_X +#undef S_Y + +#define S_X 0.0175f +#define S_Y 0.025f +static float y_axis_name[6][2] = { + {-1.0f * S_X, 1.0f * S_Y}, { 0.0f * S_X, -0.1f * S_Y}, + { 1.0f * S_X, 1.0f * S_Y}, { 0.0f * S_X, -0.1f * S_Y}, + { 0.0f * S_X, -0.1f * S_Y}, { 0.0f * S_X, -1.0f * S_Y} +}; +#define Y_LEN (sizeof(y_axis_name) / (sizeof(float) * 2)) +#undef S_X +#undef S_Y + +#define S_X 0.02f +#define S_Y 0.025f +static float z_axis_name[10][2] = { + {-0.95f * S_X, 1.00f * S_Y}, { 0.95f * S_X, 1.00f * S_Y}, + { 0.95f * S_X, 1.00f * S_Y}, { 0.95f * S_X, 0.90f * S_Y}, + { 0.95f * S_X, 0.90f * S_Y}, {-1.00f * S_X, -0.90f * S_Y}, + {-1.00f * S_X, -0.90f * S_Y}, {-1.00f * S_X, -1.00f * S_Y}, + {-1.00f * S_X, -1.00f * S_Y}, { 1.00f * S_X, -1.00f * S_Y} +}; +#define Z_LEN (sizeof(z_axis_name) / (sizeof(float) * 2)) +#undef S_X +#undef S_Y + +#define S_X 0.007f +#define S_Y 0.007f +static float axis_marker[8][2] = { +#if 0 /* square */ + {-1.0f * S_X, 1.0f * S_Y}, { 1.0f * S_X, 1.0f * S_Y}, + { 1.0f * S_X, 1.0f * S_Y}, { 1.0f * S_X, -1.0f * S_Y}, + { 1.0f * S_X, -1.0f * S_Y}, {-1.0f * S_X, -1.0f * S_Y}, + {-1.0f * S_X, -1.0f * S_Y}, {-1.0f * S_X, 1.0f * S_Y} +#else /* diamond */ + {-S_X, 0.f}, { 0.f, S_Y}, + { 0.f, S_Y}, { S_X, 0.f}, + { S_X, 0.f}, { 0.f, -S_Y}, + { 0.f, -S_Y}, {-S_X, 0.f} +#endif +}; +#define MARKER_LEN (sizeof(axis_marker) / (sizeof(float) * 2)) +#define MARKER_FILL_LAYER 6 +#undef S_X +#undef S_Y + +#define S_X 0.0007f +#define S_Y 0.0007f +#define O_X 0.001f +#define O_Y -0.001f +static float axis_name_shadow[8][2] = { + {-S_X + O_X, S_Y + O_Y}, { S_X + O_X, S_Y + O_Y}, + { S_X + O_X, S_Y + O_Y}, { S_X + O_X, -S_Y + O_Y}, + { S_X + O_X, -S_Y + O_Y}, {-S_X + O_X, -S_Y + O_Y}, + {-S_X + O_X, -S_Y + O_Y}, {-S_X + O_X, S_Y + O_Y} +}; +// #define SHADOW_RES (sizeof(axis_name_shadow) / (sizeof(float) * 2)) +#define SHADOW_RES 0 +#undef O_X +#undef O_Y +#undef S_X +#undef S_Y + +Gwn_Batch *DRW_cache_bone_arrows_get(void) +{ + if (!SHC.drw_bone_arrows) { + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint axis, pos, col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.axis = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + attr_id.pos = GWN_vertformat_attr_add(&format, "screenPos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.col = GWN_vertformat_attr_add(&format, "colorAxis", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + /* Line */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, (2 + MARKER_LEN * MARKER_FILL_LAYER) * 3 + + (X_LEN + Y_LEN + Z_LEN) * (1 + SHADOW_RES)); + + uint v = 0; + + for (int axis = 0; axis < 3; axis++) { + float pos[2] = {0.0f, 0.0f}; + float c[3] = {0.0f, 0.0f, 0.0f}; + float a = 0.0f; + /* center to axis line */ + set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col, &v, &a, pos, c); + c[axis] = 0.5f; + a = axis + 0.25f; + set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col, &v, &a, pos, c); + + /* Axis end marker */ + for (int j = 1; j < MARKER_FILL_LAYER + 1; ++j) { + for (int i = 0; i < MARKER_LEN; ++i) { + float tmp[2]; + mul_v2_v2fl(tmp, axis_marker[i], j / (float)MARKER_FILL_LAYER); + set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col, + &v, &a, tmp, c); + } + } + + a = axis + 0.31f; + /* Axis name */ + int axis_v_ct; + float (*axis_verts)[2]; + if (axis == 0) { + axis_verts = x_axis_name; + axis_v_ct = X_LEN; + } + else if (axis == 1) { + axis_verts = y_axis_name; + axis_v_ct = Y_LEN; + } + else { + axis_verts = z_axis_name; + axis_v_ct = Z_LEN; + } + + /* Axis name shadows */ + copy_v3_fl(c, 0.0f); + c[axis] = 0.3f; + for (int j = 0; j < SHADOW_RES; ++j) { + for (int i = 0; i < axis_v_ct; ++i) { + float tmp[2]; + add_v2_v2v2(tmp, axis_verts[i], axis_name_shadow[j]); + set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col, + &v, &a, tmp, c); + } + } + + /* Axis name */ + copy_v3_fl(c, 0.1f); + c[axis] = 1.0f; + for (int i = 0; i < axis_v_ct; ++i) { + set_bone_axis_vert(vbo, attr_id.axis, attr_id.pos, attr_id.col, + &v, &a, axis_verts[i], c); + } + } + + SHC.drw_bone_arrows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_bone_arrows; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Camera + * \{ */ + +/** + * We could make these more generic functions. + * although filling 1d lines is not common. + * + * \note Use x coordinate to identify the vertex the vertex shader take care to place it appropriately. + */ + +static const float camera_coords_frame_bounds[5] = { + 0.0f, /* center point */ + 1.0f, /* + X + Y */ + 2.0f, /* + X - Y */ + 3.0f, /* - X - Y */ + 4.0f, /* - X + Y */ +}; + +static const float camera_coords_frame_tri[3] = { + 5.0f, /* tria + X */ + 6.0f, /* tria - X */ + 7.0f, /* tria + Y */ +}; + +/** Draw a loop of lines. */ +static void camera_fill_lines_loop_fl_v1( + Gwn_VertBufRaw *pos_step, + const float *coords, const uint coords_len) +{ + for (uint i = 0, i_prev = coords_len - 1; i < coords_len; i_prev = i++) { + *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i_prev]; + *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i]; + } +} + +/** Fan lines out from the first vertex. */ +static void camera_fill_lines_fan_fl_v1( + Gwn_VertBufRaw *pos_step, + const float *coords, const uint coords_len) +{ + for (uint i = 1; i < coords_len; i++) { + *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[0]; + *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i]; + } +} + +/** Simply fill the array. */ +static void camera_fill_array_fl_v1( + Gwn_VertBufRaw *pos_step, + const float *coords, const uint coords_len) +{ + for (uint i = 0; i < coords_len; i++) { + *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i]; + } +} + + +Gwn_Batch *DRW_cache_camera_get(void) +{ + if (!SHC.drw_camera) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + } + + /* Vertices */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + const int vbo_len_capacity = 22; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + Gwn_VertBufRaw pos_step; + GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); + + /* camera cone (from center to frame) */ + camera_fill_lines_fan_fl_v1(&pos_step, camera_coords_frame_bounds, ARRAY_SIZE(camera_coords_frame_bounds)); + + /* camera frame (skip center) */ + camera_fill_lines_loop_fl_v1(&pos_step, &camera_coords_frame_bounds[1], ARRAY_SIZE(camera_coords_frame_bounds) - 1); + + /* camera triangle (above the frame) */ + camera_fill_lines_loop_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri)); + + BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step)); + + SHC.drw_camera = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_camera; +} + +Gwn_Batch *DRW_cache_camera_frame_get(void) +{ + if (!SHC.drw_camera_frame) { + + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + } + + /* Vertices */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + const int vbo_len_capacity = 8; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + Gwn_VertBufRaw pos_step; + GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); + + /* camera frame (skip center) */ + camera_fill_lines_loop_fl_v1(&pos_step, &camera_coords_frame_bounds[1], ARRAY_SIZE(camera_coords_frame_bounds) - 1); + + BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step)); + + SHC.drw_camera_frame = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_camera_frame; +} + +Gwn_Batch *DRW_cache_camera_tria_get(void) +{ + if (!SHC.drw_camera_tria) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + } + + /* Vertices */ + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + const int vbo_len_capacity = 3; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + Gwn_VertBufRaw pos_step; + GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); + + /* camera triangle (above the frame) */ + camera_fill_array_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri)); + + BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step)); + + SHC.drw_camera_tria = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_camera_tria; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Object Mode Helpers + * \{ */ + +/* Object Center */ +Gwn_Batch *DRW_cache_single_vert_get(void) +{ + if (!SHC.drw_single_vertice) { + float v1[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 1); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v1); + + SHC.drw_single_vertice = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_single_vertice; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Meshes + * \{ */ + +Gwn_Batch *DRW_cache_mesh_surface_overlay_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_all_triangles(me); +} + +void DRW_cache_mesh_wire_overlay_get( + Object *ob, + Gwn_Batch **r_tris, Gwn_Batch **r_ledges, Gwn_Batch **r_lverts) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + + *r_tris = DRW_mesh_batch_cache_get_overlay_triangles(me); + *r_ledges = DRW_mesh_batch_cache_get_overlay_loose_edges(me); + *r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me); +} + +void DRW_cache_mesh_normals_overlay_get( + Object *ob, + Gwn_Batch **r_tris, Gwn_Batch **r_ledges, Gwn_Batch **r_lverts) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + + *r_tris = DRW_mesh_batch_cache_get_overlay_triangles_nor(me); + *r_ledges = DRW_mesh_batch_cache_get_overlay_loose_edges_nor(me); + *r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me); +} + +Gwn_Batch *DRW_cache_face_centers_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + + return DRW_mesh_batch_cache_get_overlay_facedots(me); +} + +Gwn_Batch *DRW_cache_mesh_wire_outline_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_fancy_edges(me); +} + +Gwn_Batch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_edge_detection(me, r_is_manifold); +} + +Gwn_Batch *DRW_cache_mesh_surface_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_triangles_with_normals(me); +} + +Gwn_Batch *DRW_cache_mesh_surface_weights_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(me, ob->actdef - 1); +} + +Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(me); +} + +/* Return list of batches */ +Gwn_Batch **DRW_cache_mesh_surface_shaded_get( + Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, + char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_surface_shaded(me, gpumat_array, gpumat_array_len, + auto_layer_names, auto_layer_is_srgb, auto_layer_count); +} + +/* Return list of batches */ +Gwn_Batch **DRW_cache_mesh_surface_texpaint_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_surface_texpaint(me); +} + +Gwn_Batch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_surface_texpaint_single(me); +} + +Gwn_Batch *DRW_cache_mesh_surface_verts_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_points_with_normals(me); +} + +Gwn_Batch *DRW_cache_mesh_edges_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_all_edges(me); +} + +Gwn_Batch *DRW_cache_mesh_verts_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_all_verts(me); +} + +Gwn_Batch *DRW_cache_mesh_edges_paint_overlay_get(Object *ob, bool use_wire, bool use_sel) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_weight_overlay_edges(me, use_wire, use_sel); +} + +Gwn_Batch *DRW_cache_mesh_faces_weight_overlay_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_weight_overlay_faces(me); +} + +Gwn_Batch *DRW_cache_mesh_verts_weight_overlay_get(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + return DRW_mesh_batch_cache_get_weight_overlay_verts(me); +} + +void DRW_cache_mesh_sculpt_coords_ensure(Object *ob) +{ + BLI_assert(ob->type == OB_MESH); + + Mesh *me = ob->data; + DRW_mesh_cache_sculpt_coords_ensure(me); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Curve + * \{ */ + +Gwn_Batch *DRW_cache_curve_edge_wire_get(Object *ob) +{ + BLI_assert(ob->type == OB_CURVE); + + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_wire_edge(cu, ob->curve_cache); +} + +Gwn_Batch *DRW_cache_curve_edge_normal_get(Object *ob, float normal_size) +{ + BLI_assert(ob->type == OB_CURVE); + + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_normal_edge(cu, ob->curve_cache, normal_size); +} + +Gwn_Batch *DRW_cache_curve_edge_overlay_get(Object *ob) +{ + BLI_assert(ob->type == OB_CURVE); + + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_overlay_edges(cu); +} + +Gwn_Batch *DRW_cache_curve_vert_overlay_get(Object *ob) +{ + BLI_assert(ob->type == OB_CURVE); + + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_overlay_verts(cu); +} + +Gwn_Batch *DRW_cache_curve_surface_get(Object *ob) +{ + BLI_assert(ob->type == OB_CURVE); + + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache); +} + +/* Return list of batches */ +Gwn_Batch **DRW_cache_curve_surface_shaded_get( + Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len) +{ + BLI_assert(ob->type == OB_CURVE); + + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name MetaBall + * \{ */ + +Gwn_Batch *DRW_cache_mball_surface_get(Object *ob) +{ + BLI_assert(ob->type == OB_MBALL); + return DRW_metaball_batch_cache_get_triangles_with_normals(ob); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Font + * \{ */ + +Gwn_Batch *DRW_cache_text_edge_wire_get(Object *ob) +{ + BLI_assert(ob->type == OB_FONT); + + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_wire_edge(cu, ob->curve_cache); +} + +Gwn_Batch *DRW_cache_text_surface_get(Object *ob) +{ + BLI_assert(ob->type == OB_FONT); + struct Curve *cu = ob->data; + if (cu->editfont && (cu->flag & CU_FAST)) { + return NULL; + } + return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache); +} + +Gwn_Batch **DRW_cache_text_surface_shaded_get( + Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len) +{ + BLI_assert(ob->type == OB_FONT); + struct Curve *cu = ob->data; + if (cu->editfont && (cu->flag & CU_FAST)) { + return NULL; + } + return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len); +} + +Gwn_Batch *DRW_cache_text_cursor_overlay_get(Object *ob) +{ + BLI_assert(ob->type == OB_FONT); + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_overlay_cursor(cu); +} + +Gwn_Batch *DRW_cache_text_select_overlay_get(Object *ob) +{ + BLI_assert(ob->type == OB_FONT); + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_overlay_select(cu); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Surface + * \{ */ + +Gwn_Batch *DRW_cache_surf_surface_get(Object *ob) +{ + BLI_assert(ob->type == OB_SURF); + + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache); +} + +/* Return list of batches */ +Gwn_Batch **DRW_cache_surf_surface_shaded_get( + Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len) +{ + BLI_assert(ob->type == OB_SURF); + + struct Curve *cu = ob->data; + return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Lattice + * \{ */ + +Gwn_Batch *DRW_cache_lattice_verts_get(Object *ob) +{ + BLI_assert(ob->type == OB_LATTICE); + + struct Lattice *lt = ob->data; + return DRW_lattice_batch_cache_get_all_verts(lt); +} + +Gwn_Batch *DRW_cache_lattice_wire_get(Object *ob, bool use_weight) +{ + BLI_assert(ob->type == OB_LATTICE); + + Lattice *lt = ob->data; + int actdef = -1; + + if (use_weight && ob->defbase.first && lt->editlatt->latt->dvert) { + actdef = ob->actdef - 1; + } + + return DRW_lattice_batch_cache_get_all_edges(lt, use_weight, actdef); +} + +Gwn_Batch *DRW_cache_lattice_vert_overlay_get(Object *ob) +{ + BLI_assert(ob->type == OB_LATTICE); + + struct Lattice *lt = ob->data; + return DRW_lattice_batch_cache_get_overlay_verts(lt); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Particles + * \{ */ + +Gwn_Batch *DRW_cache_particles_get_hair(Object *object, ParticleSystem *psys, ModifierData *md) +{ + return DRW_particles_batch_cache_get_hair(object, psys, md); +} + +Gwn_Batch *DRW_cache_particles_get_dots(Object *object, ParticleSystem *psys) +{ + return DRW_particles_batch_cache_get_dots(object, psys); +} + +Gwn_Batch *DRW_cache_particles_get_edit_strands( + Object *object, + ParticleSystem *psys, + struct PTCacheEdit *edit) +{ + return DRW_particles_batch_cache_get_edit_strands(object, psys, edit); +} + +Gwn_Batch *DRW_cache_particles_get_edit_inner_points( + Object *object, + ParticleSystem *psys, + struct PTCacheEdit *edit) +{ + return DRW_particles_batch_cache_get_edit_inner_points(object, psys, edit); +} + +Gwn_Batch *DRW_cache_particles_get_edit_tip_points( + Object *object, + ParticleSystem *psys, + struct PTCacheEdit *edit) +{ + return DRW_particles_batch_cache_get_edit_tip_points(object, psys, edit); +} + +Gwn_Batch *DRW_cache_particles_get_prim(int type) +{ + switch (type) { + case PART_DRAW_CROSS: + if (!SHC.drw_particle_cross) { + static Gwn_VertFormat format = { 0 }; + static unsigned pos_id, axis_id; + + if (format.attrib_ct == 0) { + pos_id = GWN_vertformat_attr_add(&format, "inst_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + axis_id = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 6); + + /* X axis */ + float co[3] = {-1.0f, 0.0f, 0.0f}; + int axis = -1; + GWN_vertbuf_attr_set(vbo, pos_id, 0, co); + GWN_vertbuf_attr_set(vbo, axis_id, 0, &axis); + + co[0] = 1.0f; + GWN_vertbuf_attr_set(vbo, pos_id, 1, co); + GWN_vertbuf_attr_set(vbo, axis_id, 1, &axis); + + /* Y axis */ + co[0] = 0.0f; + co[1] = -1.0f; + GWN_vertbuf_attr_set(vbo, pos_id, 2, co); + GWN_vertbuf_attr_set(vbo, axis_id, 2, &axis); + + co[1] = 1.0f; + GWN_vertbuf_attr_set(vbo, pos_id, 3, co); + GWN_vertbuf_attr_set(vbo, axis_id, 3, &axis); + + /* Z axis */ + co[1] = 0.0f; + co[2] = -1.0f; + GWN_vertbuf_attr_set(vbo, pos_id, 4, co); + GWN_vertbuf_attr_set(vbo, axis_id, 4, &axis); + + co[2] = 1.0f; + GWN_vertbuf_attr_set(vbo, pos_id, 5, co); + GWN_vertbuf_attr_set(vbo, axis_id, 5, &axis); + + SHC.drw_particle_cross = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + + return SHC.drw_particle_cross; + case PART_DRAW_AXIS: + if (!SHC.drw_particle_axis) { + static Gwn_VertFormat format = { 0 }; + static unsigned pos_id, axis_id; + + if (format.attrib_ct == 0) { + pos_id = GWN_vertformat_attr_add(&format, "inst_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + axis_id = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 6); + + /* X axis */ + float co[3] = {0.0f, 0.0f, 0.0f}; + int axis = 0; + GWN_vertbuf_attr_set(vbo, pos_id, 0, co); + GWN_vertbuf_attr_set(vbo, axis_id, 0, &axis); + + co[0] = 1.0f; + GWN_vertbuf_attr_set(vbo, pos_id, 1, co); + GWN_vertbuf_attr_set(vbo, axis_id, 1, &axis); + + /* Y axis */ + co[0] = 0.0f; + axis = 1; + GWN_vertbuf_attr_set(vbo, pos_id, 2, co); + GWN_vertbuf_attr_set(vbo, axis_id, 2, &axis); + + co[1] = 1.0f; + GWN_vertbuf_attr_set(vbo, pos_id, 3, co); + GWN_vertbuf_attr_set(vbo, axis_id, 3, &axis); + + /* Z axis */ + co[1] = 0.0f; + axis = 2; + GWN_vertbuf_attr_set(vbo, pos_id, 4, co); + GWN_vertbuf_attr_set(vbo, axis_id, 4, &axis); + + co[2] = 1.0f; + GWN_vertbuf_attr_set(vbo, pos_id, 5, co); + GWN_vertbuf_attr_set(vbo, axis_id, 5, &axis); + + SHC.drw_particle_axis = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + + return SHC.drw_particle_axis; + case PART_DRAW_CIRC: +#define CIRCLE_RESOL 32 + if (!SHC.drw_particle_circle) { + float v[3] = {0.0f, 0.0f, 0.0f}; + int axis = -1; + + static Gwn_VertFormat format = { 0 }; + static unsigned pos_id, axis_id; + + if (format.attrib_ct == 0) { + pos_id = GWN_vertformat_attr_add(&format, "inst_pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + axis_id = GWN_vertformat_attr_add(&format, "axis", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL); + + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[2] = 0.0f; + GWN_vertbuf_attr_set(vbo, pos_id, a, v); + GWN_vertbuf_attr_set(vbo, axis_id, a, &axis); + } + + SHC.drw_particle_circle = GWN_batch_create_ex(GWN_PRIM_LINE_LOOP, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + + return SHC.drw_particle_circle; +#undef CIRCLE_RESOL + default: + BLI_assert(false); + break; + } + + return NULL; +} + +/* 3D cursor */ +Gwn_Batch *DRW_cache_cursor_get(bool crosshair_lines) +{ + Gwn_Batch **drw_cursor = crosshair_lines ? &SHC.drw_cursor : &SHC.drw_cursor_only_circle; + + if (*drw_cursor == NULL) { + const float f5 = 0.25f; + const float f10 = 0.5f; + const float f20 = 1.0f; + + const int segments = 16; + const int vert_ct = segments + 8; + const int index_ct = vert_ct + 5; + + unsigned char red[3] = {255, 0, 0}; + unsigned char white[3] = {255, 255, 255}; + + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, color; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.color = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + } + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init_ex(&elb, GWN_PRIM_LINE_STRIP, index_ct, vert_ct, true); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vert_ct); + + int v = 0; + for (int i = 0; i < segments; ++i) { + float angle = (float)(2 * M_PI) * ((float)i / (float)segments); + float x = f10 * cosf(angle); + float y = f10 * sinf(angle); + + if (i % 2 == 0) + GWN_vertbuf_attr_set(vbo, attr_id.color, v, red); + else + GWN_vertbuf_attr_set(vbo, attr_id.color, v, white); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){x, y}); + GWN_indexbuf_add_generic_vert(&elb, v++); + } + GWN_indexbuf_add_generic_vert(&elb, 0); + + if (crosshair_lines) { + unsigned char crosshair_color[3]; + UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color); + + GWN_indexbuf_add_primitive_restart(&elb); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){-f20, 0}); + GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color); + GWN_indexbuf_add_generic_vert(&elb, v++); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){-f5, 0}); + GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color); + GWN_indexbuf_add_generic_vert(&elb, v++); + + GWN_indexbuf_add_primitive_restart(&elb); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){+f5, 0}); + GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color); + GWN_indexbuf_add_generic_vert(&elb, v++); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){+f20, 0}); + GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color); + GWN_indexbuf_add_generic_vert(&elb, v++); + + GWN_indexbuf_add_primitive_restart(&elb); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, -f20}); + GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color); + GWN_indexbuf_add_generic_vert(&elb, v++); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, -f5}); + GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color); + GWN_indexbuf_add_generic_vert(&elb, v++); + + GWN_indexbuf_add_primitive_restart(&elb); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, +f5}); + GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color); + GWN_indexbuf_add_generic_vert(&elb, v++); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, (const float[2]){0, +f20}); + GWN_vertbuf_attr_set(vbo, attr_id.color, v, crosshair_color); + GWN_indexbuf_add_generic_vert(&elb, v++); + } + + Gwn_IndexBuf *ibo = GWN_indexbuf_build(&elb); + + *drw_cursor = GWN_batch_create_ex(GWN_PRIM_LINE_STRIP, vbo, ibo, GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); + } + return *drw_cursor; +} diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h new file mode 100644 index 00000000000..1fd6b22c221 --- /dev/null +++ b/source/blender/draw/intern/draw_cache.h @@ -0,0 +1,187 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_cache.h + * \ingroup draw + */ + +#ifndef __DRAW_CACHE_H__ +#define __DRAW_CACHE_H__ + +struct Gwn_Batch; +struct GPUMaterial; +struct ModifierData; +struct Object; +struct PTCacheEdit; + +void DRW_shape_cache_free(void); + +/* 3D cursor */ +struct Gwn_Batch *DRW_cache_cursor_get(bool crosshair_lines); + +/* Common Shapes */ +struct Gwn_Batch *DRW_cache_fullscreen_quad_get(void); +struct Gwn_Batch *DRW_cache_quad_get(void); +struct Gwn_Batch *DRW_cache_sphere_get(void); +struct Gwn_Batch *DRW_cache_single_vert_get(void); +struct Gwn_Batch *DRW_cache_single_line_get(void); +struct Gwn_Batch *DRW_cache_single_line_endpoints_get(void); +struct Gwn_Batch *DRW_cache_screenspace_circle_get(void); + +/* Common Object */ +struct Gwn_Batch *DRW_cache_object_wire_outline_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_object_edge_detection_get(struct Object *ob, bool *r_is_manifold); +struct Gwn_Batch *DRW_cache_object_surface_get(struct Object *ob); +struct Gwn_Batch **DRW_cache_object_surface_material_get( + struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, + char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count); + +/* Empties */ +struct Gwn_Batch *DRW_cache_plain_axes_get(void); +struct Gwn_Batch *DRW_cache_single_arrow_get(void); +struct Gwn_Batch *DRW_cache_cube_get(void); +struct Gwn_Batch *DRW_cache_circle_get(void); +struct Gwn_Batch *DRW_cache_square_get(void); +struct Gwn_Batch *DRW_cache_empty_sphere_get(void); +struct Gwn_Batch *DRW_cache_empty_cone_get(void); +struct Gwn_Batch *DRW_cache_arrows_get(void); +struct Gwn_Batch *DRW_cache_axis_names_get(void); +struct Gwn_Batch *DRW_cache_image_plane_get(void); +struct Gwn_Batch *DRW_cache_image_plane_wire_get(void); + +/* Force Field */ +struct Gwn_Batch *DRW_cache_field_wind_get(void); +struct Gwn_Batch *DRW_cache_field_force_get(void); +struct Gwn_Batch *DRW_cache_field_vortex_get(void); +struct Gwn_Batch *DRW_cache_field_tube_limit_get(void); +struct Gwn_Batch *DRW_cache_field_cone_limit_get(void); + +/* Lamps */ +struct Gwn_Batch *DRW_cache_lamp_get(void); +struct Gwn_Batch *DRW_cache_lamp_shadows_get(void); +struct Gwn_Batch *DRW_cache_lamp_sunrays_get(void); +struct Gwn_Batch *DRW_cache_lamp_area_square_get(void); +struct Gwn_Batch *DRW_cache_lamp_area_disk_get(void); +struct Gwn_Batch *DRW_cache_lamp_hemi_get(void); +struct Gwn_Batch *DRW_cache_lamp_spot_get(void); +struct Gwn_Batch *DRW_cache_lamp_spot_square_get(void); + +/* Camera */ +struct Gwn_Batch *DRW_cache_camera_get(void); +struct Gwn_Batch *DRW_cache_camera_frame_get(void); +struct Gwn_Batch *DRW_cache_camera_tria_get(void); + +/* Speaker */ +struct Gwn_Batch *DRW_cache_speaker_get(void); + +/* Probe */ +struct Gwn_Batch *DRW_cache_lightprobe_cube_get(void); +struct Gwn_Batch *DRW_cache_lightprobe_grid_get(void); +struct Gwn_Batch *DRW_cache_lightprobe_planar_get(void); + +/* Bones */ +struct Gwn_Batch *DRW_cache_bone_octahedral_get(void); +struct Gwn_Batch *DRW_cache_bone_octahedral_wire_get(void); +struct Gwn_Batch *DRW_cache_bone_box_get(void); +struct Gwn_Batch *DRW_cache_bone_box_wire_get(void); +struct Gwn_Batch *DRW_cache_bone_envelope_solid_get(void); +struct Gwn_Batch *DRW_cache_bone_envelope_outline_get(void); +struct Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void); +struct Gwn_Batch *DRW_cache_bone_point_get(void); +struct Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void); +struct Gwn_Batch *DRW_cache_bone_stick_get(void); +struct Gwn_Batch *DRW_cache_bone_arrows_get(void); + +/* Meshes */ +struct Gwn_Batch *DRW_cache_mesh_surface_overlay_get(struct Object *ob); +void DRW_cache_mesh_wire_overlay_get( + struct Object *ob, + struct Gwn_Batch **r_tris, struct Gwn_Batch **r_ledges, struct Gwn_Batch **r_lverts); +void DRW_cache_mesh_normals_overlay_get( + struct Object *ob, + struct Gwn_Batch **r_tris, struct Gwn_Batch **r_ledges, struct Gwn_Batch **r_lverts); +struct Gwn_Batch *DRW_cache_face_centers_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_wire_outline_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_edge_detection_get(struct Object *ob, bool *r_is_manifold); +struct Gwn_Batch *DRW_cache_mesh_surface_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_surface_weights_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_surface_verts_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_edges_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_verts_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_edges_paint_overlay_get(struct Object *ob, bool use_wire, bool use_sel); +struct Gwn_Batch *DRW_cache_mesh_faces_weight_overlay_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_verts_weight_overlay_get(struct Object *ob); +struct Gwn_Batch **DRW_cache_mesh_surface_shaded_get( + struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, + char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count); +struct Gwn_Batch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob); + +void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob); + +/* Curve */ +struct Gwn_Batch *DRW_cache_curve_surface_get(struct Object *ob); +struct Gwn_Batch **DRW_cache_curve_surface_shaded_get( + struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len); +struct Gwn_Batch *DRW_cache_curve_surface_verts_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_curve_edge_wire_get(struct Object *ob); +/* edit-mode */ +struct Gwn_Batch *DRW_cache_curve_edge_normal_get(struct Object *ob, float normal_size); +struct Gwn_Batch *DRW_cache_curve_edge_overlay_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_curve_vert_overlay_get(struct Object *ob); + +/* Font */ +struct Gwn_Batch *DRW_cache_text_edge_wire_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_text_surface_get(struct Object *ob); +struct Gwn_Batch **DRW_cache_text_surface_shaded_get( + struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len); +/* edit-mode */ +struct Gwn_Batch *DRW_cache_text_cursor_overlay_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_text_select_overlay_get(struct Object *ob); + +/* Surface */ +struct Gwn_Batch *DRW_cache_surf_surface_get(struct Object *ob); +struct Gwn_Batch **DRW_cache_surf_surface_shaded_get( + struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len); + +/* Lattice */ +struct Gwn_Batch *DRW_cache_lattice_verts_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_lattice_wire_get(struct Object *ob, bool use_weight); +struct Gwn_Batch *DRW_cache_lattice_vert_overlay_get(struct Object *ob); + +/* Particles */ +struct Gwn_Batch *DRW_cache_particles_get_hair( + struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); +struct Gwn_Batch *DRW_cache_particles_get_dots( + struct Object *object, struct ParticleSystem *psys); +struct Gwn_Batch *DRW_cache_particles_get_edit_strands( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_cache_particles_get_edit_inner_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_cache_particles_get_edit_tip_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_cache_particles_get_prim(int type); + +/* Metaball */ +struct Gwn_Batch *DRW_cache_mball_surface_get(struct Object *ob); + +#endif /* __DRAW_CACHE_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h new file mode 100644 index 00000000000..f77dafc9b31 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -0,0 +1,139 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_cache_impl.h + * \ingroup draw + */ + +#ifndef __DRAW_CACHE_IMPL_H__ +#define __DRAW_CACHE_IMPL_H__ + +struct CurveCache; +struct GPUMaterial; +struct Gwn_Batch; +struct Gwn_IndexBuf; +struct Gwn_VertBuf; +struct ListBase; +struct ModifierData; +struct ParticleSystem; +struct PTCacheEdit; + +struct Curve; +struct Lattice; +struct Mesh; +struct MetaBall; + +/* Expose via BKE callbacks */ +void DRW_mball_batch_cache_dirty(struct MetaBall *mb, int mode); +void DRW_mball_batch_cache_free(struct MetaBall *mb); + +void DRW_curve_batch_cache_dirty(struct Curve *cu, int mode); +void DRW_curve_batch_cache_free(struct Curve *cu); + +void DRW_mesh_batch_cache_dirty(struct Mesh *me, int mode); +void DRW_mesh_batch_cache_free(struct Mesh *me); + +void DRW_lattice_batch_cache_dirty(struct Lattice *lt, int mode); +void DRW_lattice_batch_cache_free(struct Lattice *lt); + +void DRW_particle_batch_cache_dirty(struct ParticleSystem *psys, int mode); +void DRW_particle_batch_cache_free(struct ParticleSystem *psys); + +/* Curve */ +struct Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(struct Curve *cu, struct CurveCache *ob_curve_cache); +struct Gwn_Batch *DRW_curve_batch_cache_get_normal_edge( + struct Curve *cu, struct CurveCache *ob_curve_cache, float normal_size); +struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(struct Curve *cu); +struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu); + +struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals( + struct Curve *cu, struct CurveCache *ob_curve_cache); +struct Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded( + struct Curve *cu, struct CurveCache *ob_curve_cache, + struct GPUMaterial **gpumat_array, uint gpumat_array_len); + +/* Metaball */ +struct Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob); + +/* Curve (Font) */ +struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu); +struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(struct Curve *cu); + +/* DispList */ +struct Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(struct ListBase *lb); +struct Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(struct ListBase *lb); +struct Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material( + struct ListBase *lb, uint gpumat_array_len); +struct Gwn_Batch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material( + struct ListBase *lb, uint gpumat_array_len); + +/* Lattice */ +struct Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt, bool use_weight, const int actdef); +struct Gwn_Batch *DRW_lattice_batch_cache_get_all_verts(struct Lattice *lt); +struct Gwn_Batch *DRW_lattice_batch_cache_get_overlay_verts(struct Lattice *lt); + +/* Mesh */ + +struct Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded( + struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len, + char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count); +struct Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(struct Mesh *me, bool use_wire, bool use_sel); +struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_verts(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_all_edges(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(struct Mesh *me, int defgroup); +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide, uint select_id_offset); +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide); +struct Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me, bool *r_is_manifold); +struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me); +/* edit-mesh selection (use generic function for faces) */ +struct Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me, uint select_id_offset); +struct Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me, uint select_id_offset); +struct Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, uint select_id_offset); + +void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me); + +/* Particles */ +struct Gwn_Batch *DRW_particles_batch_cache_get_hair( + struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); +struct Gwn_Batch *DRW_particles_batch_cache_get_dots( + struct Object *object, struct ParticleSystem *psys); +struct Gwn_Batch *DRW_particles_batch_cache_get_edit_strands( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); + +#endif /* __DRAW_CACHE_IMPL_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c new file mode 100644 index 00000000000..3939ea062e9 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_curve.c @@ -0,0 +1,1118 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file draw_cache_impl_curve.c + * \ingroup draw + * + * \brief Curve API for render engines + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math_vector.h" + +#include "DNA_curve_types.h" + +#include "BKE_curve.h" + +#include "BKE_font.h" + +#include "GPU_batch.h" + +#include "UI_resources.h" + +#include "draw_cache_impl.h" /* own include */ + +#define SELECT 1 +#define ACTIVE_NURB 1 << 7 /* last char bite */ +#define HANDLE_SEL_OFFSET (TH_HANDLE_SEL_FREE - TH_HANDLE_FREE) + +/* Used as values of `color_id` in `edit_curve_overlay_handle_geom.glsl` */ +enum { + COLOR_NURB_ULINE_ID = TH_HANDLE_SEL_AUTOCLAMP - TH_HANDLE_FREE + 1, + COLOR_NURB_SEL_ULINE_ID, + COLOR_ACTIVE_SPLINE, + + TOT_HANDLE_COL, +}; + +/** + * TODO + * - Ensure `CurveCache`, `SEQUENCER_DAG_WORKAROUND`. + * - Check number of verts/edges to see if cache is valid. + * - Check if 'overlay.edges' can use single attribyte per edge, not 2 (for selection drawing). + */ + +static void curve_batch_cache_clear(Curve *cu); + +/* ---------------------------------------------------------------------- */ +/* Curve Interface, direct access to basic data. */ + +static void curve_render_overlay_verts_edges_len_get( + ListBase *lb, bool hide_handles, + int *r_vert_len, int *r_edge_len) +{ + BLI_assert(r_vert_len || r_edge_len); + int vert_len = 0; + int edge_len = 0; + for (Nurb *nu = lb->first; nu; nu = nu->next) { + if (nu->bezt) { + vert_len += hide_handles ? nu->pntsu : (nu->pntsu * 3); + /* 2x handles per point*/ + edge_len += 2 * nu->pntsu; + } + else if (nu->bp) { + vert_len += nu->pntsu; + /* segments between points */ + edge_len += nu->pntsu - 1; + } + } + if (r_vert_len) { + *r_vert_len = vert_len; + } + if (r_edge_len) { + *r_edge_len = edge_len; + } +} + +static void curve_render_wire_verts_edges_len_get( + const CurveCache *ob_curve_cache, + int *r_vert_len, int *r_edge_len) +{ + BLI_assert(r_vert_len || r_edge_len); + int vert_len = 0; + int edge_len = 0; + for (const BevList *bl = ob_curve_cache->bev.first; bl; bl = bl->next) { + if (bl->nr > 0) { + const bool is_cyclic = bl->poly != -1; + + /* verts */ + vert_len += bl->nr; + + /* edges */ + edge_len += bl->nr; + if (!is_cyclic) { + edge_len -= 1; + } + } + } + if (r_vert_len) { + *r_vert_len = vert_len; + } + if (r_edge_len) { + *r_edge_len = edge_len; + } +} + +static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache) +{ + int normal_len = 0; + const BevList *bl; + const Nurb *nu; + for (bl = ob_curve_cache->bev.first, nu = lb->first; nu && bl; bl = bl->next, nu = nu->next) { + int nr = bl->nr; + int skip = nu->resolu / 16; +#if 0 + while (nr-- > 0) { /* accounts for empty bevel lists */ + normal_len += 1; + nr -= skip; + } +#else + /* Same as loop above */ + normal_len += (nr / (skip + 1)) + ((nr % (skip + 1)) != 0); +#endif + } + return normal_len; +} + +/* ---------------------------------------------------------------------- */ +/* Curve Interface, indirect, partially cached access to complex data. */ + +typedef struct CurveRenderData { + int types; + + struct { + int vert_len; + int edge_len; + } overlay; + + struct { + int vert_len; + int edge_len; + } wire; + + /* edit mode normal's */ + struct { + /* 'edge_len == len * 2' + * 'vert_len == len * 3' */ + int len; + } normal; + + struct { + EditFont *edit_font; + } text; + + bool hide_handles; + bool hide_normals; + + /* borrow from 'Object' */ + CurveCache *ob_curve_cache; + + /* borrow from 'Curve' */ + ListBase *nurbs; + + /* edit, index in nurb list */ + int actnu; + /* edit, index in active nurb (BPoint or BezTriple) */ + int actvert; +} CurveRenderData; + +enum { + /* Wire center-line */ + CU_DATATYPE_WIRE = 1 << 0, + /* Edit-mode verts and optionally handles */ + CU_DATATYPE_OVERLAY = 1 << 1, + /* Edit-mode normals */ + CU_DATATYPE_NORMAL = 1 << 2, + /* Geometry */ + CU_DATATYPE_SURFACE = 1 << 3, + /* Text */ + CU_DATATYPE_TEXT_SELECT = 1 << 4, +}; + +/* + * ob_curve_cache can be NULL, only needed for CU_DATATYPE_WIRE + */ +static CurveRenderData *curve_render_data_create(Curve *cu, CurveCache *ob_curve_cache, const int types) +{ + CurveRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__); + rdata->types = types; + ListBase *nurbs; + + rdata->hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0; + rdata->hide_normals = (cu->drawflag & CU_HIDE_NORMALS) != 0; + + rdata->actnu = cu->actnu; + rdata->actvert = cu->actvert; + + rdata->ob_curve_cache = ob_curve_cache; + + if (types & CU_DATATYPE_WIRE) { + curve_render_wire_verts_edges_len_get( + rdata->ob_curve_cache, + &rdata->wire.vert_len, &rdata->wire.edge_len); + } + + if (cu->editnurb) { + EditNurb *editnurb = cu->editnurb; + nurbs = &editnurb->nurbs; + + if (types & CU_DATATYPE_OVERLAY) { + curve_render_overlay_verts_edges_len_get( + nurbs, rdata->hide_handles, + &rdata->overlay.vert_len, + rdata->hide_handles ? NULL : &rdata->overlay.edge_len); + + rdata->actnu = cu->actnu; + rdata->actvert = cu->actvert; + } + if (types & CU_DATATYPE_NORMAL) { + rdata->normal.len = curve_render_normal_len_get(nurbs, rdata->ob_curve_cache); + } + } + else { + nurbs = &cu->nurb; + } + + rdata->nurbs = nurbs; + + rdata->text.edit_font = cu->editfont; + + return rdata; +} + +static void curve_render_data_free(CurveRenderData *rdata) +{ +#if 0 + if (rdata->loose_verts) { + MEM_freeN(rdata->loose_verts); + } +#endif + MEM_freeN(rdata); +} + +static int curve_render_data_overlay_verts_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_OVERLAY); + return rdata->overlay.vert_len; +} + +static int curve_render_data_overlay_edges_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_OVERLAY); + return rdata->overlay.edge_len; +} + +static int curve_render_data_wire_verts_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_WIRE); + return rdata->wire.vert_len; +} + +static int curve_render_data_wire_edges_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_WIRE); + return rdata->wire.edge_len; +} + +static int curve_render_data_normal_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_NORMAL); + return rdata->normal.len; +} + +enum { + VFLAG_VERTEX_SELECTED = 1 << 0, + VFLAG_VERTEX_ACTIVE = 1 << 1, +}; + +/* ---------------------------------------------------------------------- */ +/* Curve Gwn_Batch Cache */ + +typedef struct CurveBatchCache { + /* center-line */ + struct { + Gwn_VertBuf *verts; + Gwn_VertBuf *edges; + Gwn_Batch *batch; + Gwn_IndexBuf *elem; + } wire; + + /* normals */ + struct { + Gwn_VertBuf *verts; + Gwn_VertBuf *edges; + Gwn_Batch *batch; + Gwn_IndexBuf *elem; + } normal; + + /* control handles and vertices */ + struct { + Gwn_Batch *edges; + Gwn_Batch *verts; + } overlay; + + struct { + Gwn_VertBuf *verts; + Gwn_IndexBuf *triangles_in_order; + Gwn_Batch **shaded_triangles; + Gwn_Batch *batch; + int mat_len; + } surface; + + /* 3d text */ + struct { + Gwn_Batch *select; + Gwn_Batch *cursor; + } text; + + /* settings to determine if cache is invalid */ + bool is_dirty; + + bool hide_handles; + bool hide_normals; + + float normal_size; + + bool is_editmode; +} CurveBatchCache; + +/* Gwn_Batch cache management. */ + +static bool curve_batch_cache_valid(Curve *cu) +{ + CurveBatchCache *cache = cu->batch_cache; + + if (cache == NULL) { + return false; + } + + if (cache->is_dirty) { + return false; + } + + if (cache->is_editmode != ((cu->editnurb != NULL) || (cu->editfont != NULL))) { + return false; + } + + if (cache->is_editmode) { + if (cu->editnurb) { + if ((cache->hide_handles != ((cu->drawflag & CU_HIDE_HANDLES) != 0))) { + return false; + } + else if ((cache->hide_normals != ((cu->drawflag & CU_HIDE_NORMALS) != 0))) { + return false; + } + } + else if (cu->editfont) { + /* TODO */ + } + } + + return true; +} + +static void curve_batch_cache_init(Curve *cu) +{ + CurveBatchCache *cache = cu->batch_cache; + + if (!cache) { + cache = cu->batch_cache = MEM_callocN(sizeof(*cache), __func__); + } + else { + memset(cache, 0, sizeof(*cache)); + } + + cache->hide_handles = (cu->drawflag & CU_HIDE_HANDLES) != 0; + cache->hide_normals = (cu->drawflag & CU_HIDE_NORMALS) != 0; + +#if 0 + ListBase *nurbs; + if (cu->editnurb) { + EditNurb *editnurb = cu->editnurb; + nurbs = &editnurb->nurbs; + } + else { + nurbs = &cu->nurb; + } +#endif + + cache->is_editmode = (cu->editnurb != NULL) || (cu->editfont != NULL); + + cache->is_dirty = false; +} + +static CurveBatchCache *curve_batch_cache_get(Curve *cu) +{ + if (!curve_batch_cache_valid(cu)) { + curve_batch_cache_clear(cu); + curve_batch_cache_init(cu); + } + return cu->batch_cache; +} + +void DRW_curve_batch_cache_dirty(Curve *cu, int mode) +{ + CurveBatchCache *cache = cu->batch_cache; + if (cache == NULL) { + return; + } + switch (mode) { + case BKE_CURVE_BATCH_DIRTY_ALL: + cache->is_dirty = true; + break; + case BKE_CURVE_BATCH_DIRTY_SELECT: + /* editnurb */ + GWN_BATCH_DISCARD_SAFE(cache->overlay.verts); + GWN_BATCH_DISCARD_SAFE(cache->overlay.edges); + + /* editfont */ + GWN_BATCH_DISCARD_SAFE(cache->text.select); + GWN_BATCH_DISCARD_SAFE(cache->text.cursor); + break; + default: + BLI_assert(0); + } +} + +static void curve_batch_cache_clear(Curve *cu) +{ + CurveBatchCache *cache = cu->batch_cache; + if (!cache) { + return; + } + + GWN_BATCH_DISCARD_SAFE(cache->overlay.verts); + GWN_BATCH_DISCARD_SAFE(cache->overlay.edges); + + GWN_VERTBUF_DISCARD_SAFE(cache->surface.verts); + GWN_INDEXBUF_DISCARD_SAFE(cache->surface.triangles_in_order); + if (cache->surface.shaded_triangles) { + for (int i = 0; i < cache->surface.mat_len; ++i) { + GWN_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]); + } + } + MEM_SAFE_FREE(cache->surface.shaded_triangles); + GWN_BATCH_DISCARD_SAFE(cache->surface.batch); + + /* don't own vbo & elems */ + GWN_BATCH_DISCARD_SAFE(cache->wire.batch); + GWN_VERTBUF_DISCARD_SAFE(cache->wire.verts); + GWN_VERTBUF_DISCARD_SAFE(cache->wire.edges); + GWN_INDEXBUF_DISCARD_SAFE(cache->wire.elem); + + /* don't own vbo & elems */ + GWN_BATCH_DISCARD_SAFE(cache->normal.batch); + GWN_VERTBUF_DISCARD_SAFE(cache->normal.verts); + GWN_VERTBUF_DISCARD_SAFE(cache->normal.edges); + GWN_INDEXBUF_DISCARD_SAFE(cache->normal.elem); + + /* 3d text */ + GWN_BATCH_DISCARD_SAFE(cache->text.cursor); + GWN_BATCH_DISCARD_SAFE(cache->text.select); +} + +void DRW_curve_batch_cache_free(Curve *cu) +{ + curve_batch_cache_clear(cu); + MEM_SAFE_FREE(cu->batch_cache); +} + +/* -------------------------------------------------------------------- */ + +/** \name Private Curve Cache API + * \{ */ + +/* Gwn_Batch cache usage. */ +static Gwn_VertBuf *curve_batch_cache_get_wire_verts(CurveRenderData *rdata, CurveBatchCache *cache) +{ + BLI_assert(rdata->types & CU_DATATYPE_WIRE); + BLI_assert(rdata->ob_curve_cache != NULL); + + if (cache->wire.verts == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + const int vert_len = curve_render_data_wire_verts_len_get(rdata); + + Gwn_VertBuf *vbo = cache->wire.verts = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vert_len); + int vbo_len_used = 0; + for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) { + if (bl->nr > 0) { + const int i_end = vbo_len_used + bl->nr; + for (const BevPoint *bevp = bl->bevpoints; vbo_len_used < i_end; vbo_len_used++, bevp++) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bevp->vec); + } + } + } + BLI_assert(vbo_len_used == vert_len); + } + + return cache->wire.verts; +} + +static Gwn_IndexBuf *curve_batch_cache_get_wire_edges(CurveRenderData *rdata, CurveBatchCache *cache) +{ + BLI_assert(rdata->types & CU_DATATYPE_WIRE); + BLI_assert(rdata->ob_curve_cache != NULL); + + if (cache->wire.edges == NULL) { + const int vert_len = curve_render_data_wire_verts_len_get(rdata); + const int edge_len = curve_render_data_wire_edges_len_get(rdata); + int edge_len_used = 0; + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len); + + int i = 0; + for (const BevList *bl = rdata->ob_curve_cache->bev.first; bl; bl = bl->next) { + if (bl->nr > 0) { + const bool is_cyclic = bl->poly != -1; + const int i_end = i + (bl->nr); + int i_prev; + if (is_cyclic) { + i_prev = i + (bl->nr - 1); + } + else { + i_prev = i; + i += 1; + } + for (; i < i_end; i_prev = i++) { + GWN_indexbuf_add_line_verts(&elb, i_prev, i); + edge_len_used += 1; + } + } + } + + if (rdata->hide_handles) { + BLI_assert(edge_len_used <= edge_len); + } + else { + BLI_assert(edge_len_used == edge_len); + } + + cache->wire.elem = GWN_indexbuf_build(&elb); + } + + return cache->wire.elem; +} + +static Gwn_VertBuf *curve_batch_cache_get_normal_verts(CurveRenderData *rdata, CurveBatchCache *cache) +{ + BLI_assert(rdata->types & CU_DATATYPE_NORMAL); + BLI_assert(rdata->ob_curve_cache != NULL); + + if (cache->normal.verts == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + const int normal_len = curve_render_data_normal_len_get(rdata); + const int vert_len = normal_len * 3; + + Gwn_VertBuf *vbo = cache->normal.verts = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vert_len); + int vbo_len_used = 0; + + const BevList *bl; + const Nurb *nu; + + for (bl = rdata->ob_curve_cache->bev.first, nu = rdata->nurbs->first; + nu && bl; + bl = bl->next, nu = nu->next) + { + const BevPoint *bevp = bl->bevpoints; + int nr = bl->nr; + int skip = nu->resolu / 16; + + while (nr-- > 0) { /* accounts for empty bevel lists */ + const float fac = bevp->radius * cache->normal_size; + float vec_a[3]; /* Offset perpendicular to the curve */ + float vec_b[3]; /* Delta along the curve */ + + vec_a[0] = fac; + vec_a[1] = 0.0f; + vec_a[2] = 0.0f; + + mul_qt_v3(bevp->quat, vec_a); + madd_v3_v3fl(vec_a, bevp->dir, -fac); + + reflect_v3_v3v3(vec_b, vec_a, bevp->dir); + negate_v3(vec_b); + + add_v3_v3(vec_a, bevp->vec); + add_v3_v3(vec_b, bevp->vec); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_a); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, bevp->vec); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, vec_b); + + bevp += skip + 1; + nr -= skip; + } + } + BLI_assert(vbo_len_used == vert_len); + } + + return cache->normal.verts; +} + +static Gwn_IndexBuf *curve_batch_cache_get_normal_edges(CurveRenderData *rdata, CurveBatchCache *cache) +{ + BLI_assert(rdata->types & CU_DATATYPE_NORMAL); + BLI_assert(rdata->ob_curve_cache != NULL); + + if (cache->normal.edges == NULL) { + const int normal_len = curve_render_data_normal_len_get(rdata); + const int vert_len = normal_len * 3; + const int edge_len = normal_len * 2; + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len); + + int vbo_len_used = 0; + for (int i = 0; i < normal_len; i++) { + GWN_indexbuf_add_line_verts(&elb, vbo_len_used + 0, vbo_len_used + 1); + GWN_indexbuf_add_line_verts(&elb, vbo_len_used + 1, vbo_len_used + 2); + vbo_len_used += 3; + } + + BLI_assert(vbo_len_used == vert_len); + + cache->normal.elem = GWN_indexbuf_build(&elb); + } + + return cache->normal.elem; +} + +static void curve_batch_cache_create_overlay_batches(Curve *cu) +{ + /* Since CU_DATATYPE_OVERLAY is slow to generate, generate them all at once */ + int options = CU_DATATYPE_OVERLAY; + + CurveBatchCache *cache = curve_batch_cache_get(cu); + CurveRenderData *rdata = curve_render_data_create(cu, NULL, options); + + if (cache->overlay.verts == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, data; } attr_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + const int vbo_len_capacity = curve_render_data_overlay_verts_len_get(rdata); + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + int i = 0; + for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next) { + if (nu->bezt) { + int a = 0; + for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { + if (bezt->hide == false) { + const bool is_active = (i == rdata->actvert); + char vflag; + + if (rdata->hide_handles) { + vflag = (bezt->f2 & SELECT) ? + (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0; + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]); + GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag); + vbo_len_used += 1; + } + else { + for (int j = 0; j < 3; j++) { + vflag = ((&bezt->f1)[j] & SELECT) ? + (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0; + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j]); + GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag); + vbo_len_used += 1; + } + } + } + i += 1; + } + } + else if (nu->bp) { + int a = 0; + for (const BPoint *bp = nu->bp; a < nu->pntsu; a++, bp++) { + if (bp->hide == false) { + const bool is_active = (i == rdata->actvert); + char vflag; + vflag = (bp->f1 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0; + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp->vec); + GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag); + vbo_len_used += 1; + } + i += 1; + } + } + i += nu->pntsu; + } + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + + cache->overlay.verts = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + + + if ((cache->overlay.edges == NULL) && (rdata->hide_handles == false)) { + /* Note: we could reference indices to vertices (above) */ + + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, data; } attr_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + const int edge_len = curve_render_data_overlay_edges_len_get(rdata); + const int vbo_len_capacity = edge_len * 2; + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + int i = 0; + for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next, i++) { + const bool is_active_nurb = (i == cu->actnu); + + if (nu->bezt) { + int a = 0; + for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { + if (bezt->hide == false) { + char col_id; + + for (int j = 0; j < 2; j += 1) { + /* same vertex twice, only check different selection */ + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]); + vbo_len_used += 1; + + col_id = (&bezt->h1)[j]; + if ((&bezt->f1)[j * 2] & SELECT) { + col_id += HANDLE_SEL_OFFSET; + } + if (is_active_nurb) { + col_id |= ACTIVE_NURB; + } + + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j * 2]); + GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &col_id); + vbo_len_used += 1; + } + } + } + } + else if (nu->bp) { + int a = 1; + for (const BPoint *bp_prev = nu->bp, *bp_curr = &nu->bp[1]; a < nu->pntsu; a++, bp_prev = bp_curr++) { + if ((bp_prev->hide == false) && (bp_curr->hide == false)) { + char col_id = ((bp_prev->f1 & SELECT) && (bp_curr->f1 & SELECT)) ? COLOR_NURB_SEL_ULINE_ID : COLOR_NURB_ULINE_ID; + + if (is_active_nurb) { + col_id |= ACTIVE_NURB; + } + + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_prev->vec); + vbo_len_used += 1; + + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_curr->vec); + GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &col_id); + vbo_len_used += 1; + + } + } + } + } + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + + cache->overlay.edges = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + + curve_render_data_free(rdata); +} + +static Gwn_Batch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata, CurveBatchCache *cache) +{ + BLI_assert(rdata->types & CU_DATATYPE_SURFACE); + if (cache->surface.batch == NULL) { + ListBase *lb = &rdata->ob_curve_cache->disp; + + if (cache->surface.verts == NULL) { + cache->surface.verts = DRW_displist_vertbuf_calc_pos_with_normals(lb); + } + if (cache->surface.triangles_in_order == NULL) { + cache->surface.triangles_in_order = DRW_displist_indexbuf_calc_triangles_in_order(lb); + } + cache->surface.batch = GWN_batch_create( + GWN_PRIM_TRIS, cache->surface.verts, cache->surface.triangles_in_order); + } + + return cache->surface.batch; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Private Object/Font Cache API + * \{ */ + + +static Gwn_Batch *curve_batch_cache_get_overlay_select(CurveRenderData *rdata, CurveBatchCache *cache) +{ + BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT); + if (cache->text.select == NULL) { + EditFont *ef = rdata->text.edit_font; + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + const int vbo_len_capacity = ef->selboxes_len * 6; + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + float box[4][3]; + + /* fill in xy below */ + box[0][2] = box[1][2] = box[2][2] = box[3][2] = 0.001; + + for (int i = 0; i < ef->selboxes_len; i++) { + EditFontSelBox *sb = &ef->selboxes[i]; + + float selboxw; + if (i + 1 != ef->selboxes_len) { + if (ef->selboxes[i + 1].y == sb->y) + selboxw = ef->selboxes[i + 1].x - sb->x; + else + selboxw = sb->w; + } + else { + selboxw = sb->w; + } + + if (sb->rot == 0.0f) { + copy_v2_fl2(box[0], sb->x, sb->y); + copy_v2_fl2(box[1], sb->x + selboxw, sb->y); + copy_v2_fl2(box[2], sb->x + selboxw, sb->y + sb->h); + copy_v2_fl2(box[3], sb->x, sb->y + sb->h); + } + else { + float mat[2][2]; + + angle_to_mat2(mat, sb->rot); + + copy_v2_fl2(box[0], sb->x, sb->y); + + copy_v2_fl2(box[1], selboxw, 0.0f); + mul_m2v2(mat, box[1]); + add_v2_v2(box[1], &sb->x); + + copy_v2_fl2(box[2], selboxw, sb->h); + mul_m2v2(mat, box[2]); + add_v2_v2(box[2], &sb->x); + + copy_v2_fl2(box[3], 0.0f, sb->h); + mul_m2v2(mat, box[3]); + add_v2_v2(box[3], &sb->x); + } + + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[1]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[0]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[2]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used++, box[3]); + } + BLI_assert(vbo_len_used == vbo_len_capacity); + cache->text.select = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return cache->text.select; +} + +static Gwn_Batch *curve_batch_cache_get_overlay_cursor(CurveRenderData *rdata, CurveBatchCache *cache) +{ + BLI_assert(rdata->types & CU_DATATYPE_TEXT_SELECT); + if (cache->text.cursor == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + const int vbo_len_capacity = 4; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + for (int i = 0; i < 4; i++) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->text.edit_font->textcurs[i]); + } + cache->text.cursor = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return cache->text.cursor; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Public Object/Curve API + * \{ */ + +Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(Curve *cu, CurveCache *ob_curve_cache) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + + if (cache->wire.batch == NULL) { + /* create batch from Curve */ + CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_WIRE); + + cache->wire.batch = GWN_batch_create( + GWN_PRIM_LINES, + curve_batch_cache_get_wire_verts(rdata, cache), + curve_batch_cache_get_wire_edges(rdata, cache)); + + curve_render_data_free(rdata); + } + return cache->wire.batch; +} + +Gwn_Batch *DRW_curve_batch_cache_get_normal_edge(Curve *cu, CurveCache *ob_curve_cache, float normal_size) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + + if (cache->normal.batch != NULL) { + cache->normal_size = normal_size; + if (cache->normal_size != normal_size) { + GWN_BATCH_DISCARD_SAFE(cache->normal.batch); + GWN_VERTBUF_DISCARD_SAFE(cache->normal.edges); + } + } + cache->normal_size = normal_size; + + if (cache->normal.batch == NULL) { + /* create batch from Curve */ + CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_NORMAL); + + cache->normal.batch = GWN_batch_create( + GWN_PRIM_LINES, + curve_batch_cache_get_normal_verts(rdata, cache), + curve_batch_cache_get_normal_edges(rdata, cache)); + + curve_render_data_free(rdata); + cache->normal_size = normal_size; + } + return cache->normal.batch; +} + +Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + + if (cache->overlay.edges == NULL) { + curve_batch_cache_create_overlay_batches(cu); + } + + return cache->overlay.edges; +} + +Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + + if (cache->overlay.verts == NULL) { + curve_batch_cache_create_overlay_batches(cu); + } + + return cache->overlay.verts; +} + +Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals( + struct Curve *cu, struct CurveCache *ob_curve_cache) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + + if (cache->surface.batch == NULL) { + CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE); + + curve_batch_cache_get_pos_and_normals(rdata, cache); + + curve_render_data_free(rdata); + } + + return cache->surface.batch; +} + +Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded( + struct Curve *cu, struct CurveCache *ob_curve_cache, + struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + + if (cache->surface.mat_len != gpumat_array_len) { + /* TODO: deduplicate code */ + if (cache->surface.shaded_triangles) { + for (int i = 0; i < cache->surface.mat_len; ++i) { + GWN_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]); + } + } + MEM_SAFE_FREE(cache->surface.shaded_triangles); + } + + if (cache->surface.shaded_triangles == NULL) { + CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE); + ListBase *lb = &rdata->ob_curve_cache->disp; + + cache->surface.mat_len = gpumat_array_len; + if (cu->flag & CU_UV_ORCO) { + cache->surface.shaded_triangles = DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material( + lb, gpumat_array_len); + } + else { + cache->surface.shaded_triangles = MEM_mallocN( + sizeof(*cache->surface.shaded_triangles) * gpumat_array_len, __func__); + Gwn_IndexBuf **el = DRW_displist_indexbuf_calc_triangles_in_order_split_by_material( + lb, gpumat_array_len); + + if (cache->surface.verts == NULL) { + cache->surface.verts = DRW_displist_vertbuf_calc_pos_with_normals(lb); + } + + for (int i = 0; i < gpumat_array_len; ++i) { + cache->surface.shaded_triangles[i] = GWN_batch_create_ex( + GWN_PRIM_TRIS, cache->surface.verts, el[i], GWN_BATCH_OWNS_INDEX); + } + + MEM_freeN(el); /* Save `el` in cache? */ + } + + curve_render_data_free(rdata); + } + + return cache->surface.shaded_triangles; +} + + +/* -------------------------------------------------------------------- */ + +/** \name Public Object/Font API + * \{ */ + +Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + + if (cache->text.select == NULL) { + CurveRenderData *rdata = curve_render_data_create(cu, NULL, CU_DATATYPE_TEXT_SELECT); + + curve_batch_cache_get_overlay_select(rdata, cache); + + curve_render_data_free(rdata); + } + + return cache->text.select; +} + +Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + + if (cache->text.cursor == NULL) { + CurveRenderData *rdata = curve_render_data_create(cu, NULL, CU_DATATYPE_TEXT_SELECT); + + curve_batch_cache_get_overlay_cursor(rdata, cache); + + curve_render_data_free(rdata); + } + + return cache->text.cursor; +} + +/** \} */ diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c new file mode 100644 index 00000000000..3eecff024a1 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -0,0 +1,399 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file draw_cache_impl_displist.c + * \ingroup draw + * + * \brief DispList API for render engines + * + * \note DispList may be removed soon! This is a utility for object types that use render. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_alloca.h" +#include "BLI_utildefines.h" +#include "BLI_math_vector.h" + +#include "DNA_curve_types.h" + +#include "BKE_displist.h" + +#include "GPU_batch.h" + +#include "draw_cache_impl.h" /* own include */ + +static int dl_vert_len(const DispList *dl) +{ + switch (dl->type) { + case DL_INDEX3: + case DL_INDEX4: + return dl->nr; + case DL_SURF: + return dl->parts * dl->nr; + } + return 0; +} + +static int dl_tri_len(const DispList *dl) +{ + switch (dl->type) { + case DL_INDEX3: + return dl->parts; + case DL_INDEX4: + return dl->parts * 2; + case DL_SURF: + return dl->totindex * 2; + } + return 0; +} + +/* see: displist_get_allverts */ +static int curve_render_surface_vert_len_get(const ListBase *lb) +{ + int vert_len = 0; + for (const DispList *dl = lb->first; dl; dl = dl->next) { + vert_len += dl_vert_len(dl); + } + return vert_len; +} + +static int curve_render_surface_tri_len_get(const ListBase *lb) +{ + int tri_len = 0; + for (const DispList *dl = lb->first; dl; dl = dl->next) { + tri_len += dl_tri_len(dl); + } + return tri_len; +} + +static void displist_indexbufbuilder_set(Gwn_IndexBufBuilder *elb, const DispList *dl, const int ofs) +{ + if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { + const int *idx = dl->index; + if (dl->type == DL_INDEX3) { + const int i_end = dl->parts; + for (int i = 0; i < i_end; i++, idx += 3) { + GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs); + } + } + else if (dl->type == DL_SURF) { + const int i_end = dl->totindex; + for (int i = 0; i < i_end; i++, idx += 4) { + GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs); + GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[3] + ofs, idx[2] + ofs); + } + } + else { + BLI_assert(dl->type == DL_INDEX4); + const int i_end = dl->parts; + for (int i = 0; i < i_end; i++, idx += 4) { + GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs); + + if (idx[2] != idx[3]) { + GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs); + } + } + } + } +} + +Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb) +{ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, nor; } attr_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, curve_render_surface_vert_len_get(lb)); + + BKE_displist_normals_add(lb); + + int vbo_len_used = 0; + for (const DispList *dl = lb->first; dl; dl = dl->next) { + const bool ndata_is_single = dl->type == DL_INDEX3; + if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { + const float *fp_co = dl->verts; + const float *fp_no = dl->nors; + const int vbo_end = vbo_len_used + dl_vert_len(dl); + while (vbo_len_used < vbo_end) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, fp_co); + if (fp_no) { + GWN_vertbuf_attr_set(vbo, attr_id.nor, vbo_len_used, fp_no); + if (ndata_is_single == false) { + fp_no += 3; + } + } + fp_co += 3; + vbo_len_used += 1; + } + } + } + + return vbo; +} + +Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb) +{ + const int tri_len = curve_render_surface_tri_len_get(lb); + const int vert_len = curve_render_surface_vert_len_get(lb); + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len); + + int ofs = 0; + for (const DispList *dl = lb->first; dl; dl = dl->next) { + displist_indexbufbuilder_set(&elb, dl, ofs); + ofs += dl_vert_len(dl); + } + + return GWN_indexbuf_build(&elb); +} + +Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(ListBase *lb, uint gpumat_array_len) +{ + Gwn_IndexBuf **shaded_triangles_in_order = MEM_callocN( + sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__); + Gwn_IndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len); + + const int tri_len = curve_render_surface_tri_len_get(lb); + const int vert_len = curve_render_surface_vert_len_get(lb); + int i; + + /* Init each index buffer builder */ + for (i = 0; i < gpumat_array_len; i++) { + GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, tri_len, vert_len); + } + + /* calc each index buffer builder */ + int ofs = 0; + for (const DispList *dl = lb->first; dl; dl = dl->next) { + displist_indexbufbuilder_set(&elb[dl->col], dl, ofs); + ofs += dl_vert_len(dl); + } + + /* build each indexbuf */ + for (i = 0; i < gpumat_array_len; i++) { + shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]); + } + + return shaded_triangles_in_order; +} + +static void displist_vertbuf_attr_set_tri_pos_normals_and_uv( + Gwn_VertBufRaw *pos_step, Gwn_VertBufRaw *nor_step, Gwn_VertBufRaw *uv_step, + const float v1[3], const float v2[3], const float v3[3], + const float n1[3], const float n2[3], const float n3[3], + const float uv1[2], const float uv2[2], const float uv3[2]) +{ + copy_v3_v3(GWN_vertbuf_raw_step(pos_step), v1); + copy_v3_v3(GWN_vertbuf_raw_step(nor_step), n1); + copy_v2_v2(GWN_vertbuf_raw_step(uv_step), uv1); + + copy_v3_v3(GWN_vertbuf_raw_step(pos_step), v2); + copy_v3_v3(GWN_vertbuf_raw_step(nor_step), n2); + copy_v2_v2(GWN_vertbuf_raw_step(uv_step), uv2); + + copy_v3_v3(GWN_vertbuf_raw_step(pos_step), v3); + copy_v3_v3(GWN_vertbuf_raw_step(nor_step), n3); + copy_v2_v2(GWN_vertbuf_raw_step(uv_step), uv3); +} + +Gwn_Batch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(ListBase *lb, uint gpumat_array_len) +{ + static Gwn_VertFormat shaded_triangles_format = { 0 }; + static struct { uint pos, nor, uv; } attr_id; + + if (shaded_triangles_format.attrib_ct == 0) { + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&shaded_triangles_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.nor = GWN_vertformat_attr_add(&shaded_triangles_format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.uv = GWN_vertformat_attr_add(&shaded_triangles_format, "u", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + Gwn_Batch **shaded_triangles = MEM_mallocN(sizeof(*shaded_triangles) * gpumat_array_len, __func__); + + Gwn_VertBuf **vbo = BLI_array_alloca(vbo, gpumat_array_len); + uint *vbo_len_capacity = BLI_array_alloca(vbo_len_capacity, gpumat_array_len); + + Gwn_VertBufRaw *pos_step, *nor_step, *uv_step; + pos_step = BLI_array_alloca(pos_step, gpumat_array_len); + nor_step = BLI_array_alloca(nor_step, gpumat_array_len); + uv_step = BLI_array_alloca(uv_step, gpumat_array_len); + + /* Create each vertex buffer */ + for (int i = 0; i < gpumat_array_len; i++) { + vbo[i] = GWN_vertbuf_create_with_format(&shaded_triangles_format); + vbo_len_capacity[i] = 0; + } + + /* Calc `vbo_len_capacity` */ + for (const DispList *dl = lb->first; dl; dl = dl->next) { + vbo_len_capacity[dl->col] += dl_tri_len(dl) * 3; + } + + /* Alloc each vertex buffer and get each raw data */ + for (int i = 0; i < gpumat_array_len; i++) { + GWN_vertbuf_data_alloc(vbo[i], vbo_len_capacity[i]); + GWN_vertbuf_attr_get_raw_data(vbo[i], attr_id.pos, &pos_step[i]); + GWN_vertbuf_attr_get_raw_data(vbo[i], attr_id.nor, &nor_step[i]); + GWN_vertbuf_attr_get_raw_data(vbo[i], attr_id.uv, &uv_step[i]); + } + + BKE_displist_normals_add(lb); + + for (const DispList *dl = lb->first; dl; dl = dl->next) { + if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { + const int col = dl->col; + const float(*verts)[3] = (float(*)[3])dl->verts; + const float(*nors)[3] = (float(*)[3])dl->nors; + const int *idx = dl->index; + float uv[4][2]; + + if (dl->type == DL_INDEX3) { + const float x_max = (float)(dl->nr - 1); + uv[0][1] = uv[1][1] = uv[2][1] = 0.0f; + const int i_end = dl->parts; + for (int i = 0; i < i_end; i++, idx += 3) { + uv[0][0] = idx[0] / x_max; + uv[1][0] = idx[2] / x_max; + uv[2][0] = idx[1] / x_max; + + displist_vertbuf_attr_set_tri_pos_normals_and_uv( + &pos_step[col], &nor_step[col], &uv_step[col], + verts[idx[0]], verts[idx[2]], verts[idx[1]], + dl->nors, dl->nors, dl->nors, + uv[0], uv[1], uv[2]); + } + } + else if (dl->type == DL_SURF) { + uint quad[4]; + for (int a = 0; a < dl->parts; a++) { + if ((dl->flag & DL_CYCL_V) == 0 && a == dl->parts - 1) { + break; + } + + int b; + if (dl->flag & DL_CYCL_U) { + quad[0] = dl->nr * a; + quad[3] = quad[0] + dl->nr - 1; + quad[1] = quad[0] + dl->nr; + quad[2] = quad[3] + dl->nr; + b = 0; + } + else { + quad[3] = dl->nr * a; + quad[0] = quad[3] + 1; + quad[2] = quad[3] + dl->nr; + quad[1] = quad[0] + dl->nr; + b = 1; + } + if ((dl->flag & DL_CYCL_V) && a == dl->parts - 1) { + quad[1] -= dl->parts * dl->nr; + quad[2] -= dl->parts * dl->nr; + } + + for (; b < dl->nr; b++) { + int orco_sizeu = dl->nr - 1; + int orco_sizev = dl->parts - 1; + + /* exception as handled in convertblender.c too */ + if (dl->flag & DL_CYCL_U) { + orco_sizeu++; + } + if (dl->flag & DL_CYCL_V) { + orco_sizev++; + } + + for (int i = 0; i < 4; i++) { + /* find uv based on vertex index into grid array */ + uv[i][0] = (quad[i] / dl->nr) / (float)orco_sizev; + uv[i][1] = (quad[i] % dl->nr) / (float)orco_sizeu; + + /* cyclic correction */ + if ((i == 1 || i == 2) && uv[i][0] == 0.0f) { + uv[i][0] = 1.0f; + } + if ((i == 0 || i == 1) && uv[i][1] == 0.0f) { + uv[i][1] = 1.0f; + } + } + + displist_vertbuf_attr_set_tri_pos_normals_and_uv( + &pos_step[col], &nor_step[col], &uv_step[col], + verts[quad[0]], verts[quad[1]], verts[quad[2]], + nors[quad[0]], nors[quad[1]], nors[quad[2]], + uv[0], uv[1], uv[2]); + + displist_vertbuf_attr_set_tri_pos_normals_and_uv( + &pos_step[col], &nor_step[col], &uv_step[col], + verts[quad[0]], verts[quad[2]], verts[quad[3]], + nors[quad[0]], nors[quad[2]], nors[quad[3]], + uv[0], uv[2], uv[3]); + + quad[2] = quad[1]; + quad[1]++; + quad[3] = quad[0]; + quad[0]++; + } + } + } + else { + BLI_assert(dl->type == DL_INDEX4); + uv[0][0] = uv[0][1] = uv[1][0] = uv[3][1] = 0.0f; + uv[1][1] = uv[2][0] = uv[2][1] = uv[3][0] = 1.0f; + + const int i_end = dl->parts; + for (int i = 0; i < i_end; i++, idx += 4) { + displist_vertbuf_attr_set_tri_pos_normals_and_uv( + &pos_step[col], &nor_step[col], &uv_step[col], + verts[idx[0]], verts[idx[1]], verts[idx[2]], + nors[idx[0]], nors[idx[1]], nors[idx[2]], + uv[0], uv[1], uv[2]); + + if (idx[2] != idx[3]) { + displist_vertbuf_attr_set_tri_pos_normals_and_uv( + &pos_step[col], &nor_step[col], &uv_step[col], + verts[idx[0]], verts[idx[2]], verts[idx[3]], + nors[idx[0]], nors[idx[2]], nors[idx[3]], + uv[0], uv[2], uv[3]); + } + } + } + } + } + + for (int i = 0; i < gpumat_array_len; i++) { + uint vbo_len_used = GWN_vertbuf_raw_used(&pos_step[i]); + if (vbo_len_capacity[i] != vbo_len_used) { + GWN_vertbuf_data_resize(vbo[i], vbo_len_used); + } + shaded_triangles[i] = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo[i], NULL, GWN_BATCH_OWNS_VBO); + } + + return shaded_triangles; +} diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c new file mode 100644 index 00000000000..6046d9854fb --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_lattice.c @@ -0,0 +1,584 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file draw_cache_impl_lattice.c + * \ingroup draw + * + * \brief Lattice API for render engines + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math_vector.h" + +#include "DNA_curve_types.h" +#include "DNA_lattice_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_userdef_types.h" + +#include "BKE_lattice.h" +#include "BKE_deform.h" +#include "BKE_colorband.h" + +#include "GPU_batch.h" + +#include "draw_cache_impl.h" /* own include */ + +#define SELECT 1 + +/** + * TODO + * - 'DispList' is currently not used + * (we could avoid using since it will be removed) + */ + +static void lattice_batch_cache_clear(Lattice *lt); + +/* ---------------------------------------------------------------------- */ +/* Lattice Interface, direct access to basic data. */ + +static int vert_len_calc(int u, int v, int w) +{ + if (u <= 0 || v <= 0 || w <= 0) { + return 0; + } + return u * v * w; +} + +static int edge_len_calc(int u, int v, int w) +{ + if (u <= 0 || v <= 0 || w <= 0) { + return 0; + } + return (((((u - 1) * v) + + ((v - 1) * u)) * w) + + ((w - 1) * (u * v))); +} + +static int lattice_render_verts_len_get(Lattice *lt) +{ + if (lt->editlatt) { + lt = lt->editlatt->latt; + } + + const int u = lt->pntsu; + const int v = lt->pntsv; + const int w = lt->pntsw; + + if ((lt->flag & LT_OUTSIDE) == 0) { + return vert_len_calc(u, v, w); + } + else { + /* TODO remove internal coords */ + return vert_len_calc(u, v, w); + } +} + +static int lattice_render_edges_len_get(Lattice *lt) +{ + if (lt->editlatt) { + lt = lt->editlatt->latt; + } + + const int u = lt->pntsu; + const int v = lt->pntsv; + const int w = lt->pntsw; + + if ((lt->flag & LT_OUTSIDE) == 0) { + return edge_len_calc(u, v, w); + } + else { + /* TODO remove internal coords */ + return edge_len_calc(u, v, w); + } +} + +/* ---------------------------------------------------------------------- */ +/* Lattice Interface, indirect, partially cached access to complex data. */ + +typedef struct LatticeRenderData { + int types; + + int vert_len; + int edge_len; + + struct { + int u_len, v_len, w_len; + } dims; + bool show_only_outside; + + struct EditLatt *edit_latt; + BPoint *bp; + + int actbp; + + struct MDeformVert *dvert; +} LatticeRenderData; + +enum { + LR_DATATYPE_VERT = 1 << 0, + LR_DATATYPE_EDGE = 1 << 1, + LR_DATATYPE_OVERLAY = 1 << 2, +}; + +static LatticeRenderData *lattice_render_data_create(Lattice *lt, const int types) +{ + LatticeRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__); + rdata->types = types; + + if (lt->editlatt) { + EditLatt *editlatt = lt->editlatt; + lt = editlatt->latt; + + rdata->edit_latt = editlatt; + + rdata->dvert = lt->dvert; + + if (types & (LR_DATATYPE_VERT)) { + rdata->vert_len = lattice_render_verts_len_get(lt); + } + if (types & (LR_DATATYPE_EDGE)) { + rdata->edge_len = lattice_render_edges_len_get(lt); + } + if (types & LR_DATATYPE_OVERLAY) { + rdata->actbp = lt->actbp; + } + } + else { + rdata->dvert = NULL; + + if (types & (LR_DATATYPE_VERT)) { + rdata->vert_len = lattice_render_verts_len_get(lt); + } + if (types & (LR_DATATYPE_EDGE)) { + rdata->edge_len = lattice_render_edges_len_get(lt); + /*no edge data */ + } + } + + rdata->bp = lt->def; + + rdata->dims.u_len = lt->pntsu; + rdata->dims.v_len = lt->pntsv; + rdata->dims.w_len = lt->pntsw; + + rdata->show_only_outside = (lt->flag & LT_OUTSIDE) != 0; + rdata->actbp = lt->actbp; + + return rdata; +} + +static void lattice_render_data_free(LatticeRenderData *rdata) +{ +#if 0 + if (rdata->loose_verts) { + MEM_freeN(rdata->loose_verts); + } +#endif + MEM_freeN(rdata); +} + +static int lattice_render_data_verts_len_get(const LatticeRenderData *rdata) +{ + BLI_assert(rdata->types & LR_DATATYPE_VERT); + return rdata->vert_len; +} + +static int lattice_render_data_edges_len_get(const LatticeRenderData *rdata) +{ + BLI_assert(rdata->types & LR_DATATYPE_EDGE); + return rdata->edge_len; +} + +static const BPoint *lattice_render_data_vert_bpoint(const LatticeRenderData *rdata, const int vert_idx) +{ + BLI_assert(rdata->types & LR_DATATYPE_VERT); + return &rdata->bp[vert_idx]; +} + +/* TODO, move into shader? */ +static void rgb_from_weight(float r_rgb[3], const float weight) +{ + const float blend = ((weight / 2.0f) + 0.5f); + + if (weight <= 0.25f) { /* blue->cyan */ + r_rgb[0] = 0.0f; + r_rgb[1] = blend * weight * 4.0f; + r_rgb[2] = blend; + } + else if (weight <= 0.50f) { /* cyan->green */ + r_rgb[0] = 0.0f; + r_rgb[1] = blend; + r_rgb[2] = blend * (1.0f - ((weight - 0.25f) * 4.0f)); + } + else if (weight <= 0.75f) { /* green->yellow */ + r_rgb[0] = blend * ((weight - 0.50f) * 4.0f); + r_rgb[1] = blend; + r_rgb[2] = 0.0f; + } + else if (weight <= 1.0f) { /* yellow->red */ + r_rgb[0] = blend; + r_rgb[1] = blend * (1.0f - ((weight - 0.75f) * 4.0f)); + r_rgb[2] = 0.0f; + } + else { + /* exceptional value, unclamped or nan, + * avoid uninitialized memory use */ + r_rgb[0] = 1.0f; + r_rgb[1] = 0.0f; + r_rgb[2] = 1.0f; + } +} + +static void lattice_render_data_weight_col_get(const LatticeRenderData *rdata, const int vert_idx, + const int actdef, float r_col[4]) +{ + if (actdef > -1) { + float weight = defvert_find_weight(rdata->dvert + vert_idx, actdef); + + if (U.flag & USER_CUSTOM_RANGE) { + BKE_colorband_evaluate(&U.coba_weight, weight, r_col); + } + else { + rgb_from_weight(r_col, weight); + } + + r_col[3] = 1.0f; + } + else { + zero_v4(r_col); + } +} + +enum { + VFLAG_VERTEX_SELECTED = 1 << 0, + VFLAG_VERTEX_ACTIVE = 1 << 1, +}; + +/* ---------------------------------------------------------------------- */ +/* Lattice Gwn_Batch Cache */ + +typedef struct LatticeBatchCache { + Gwn_VertBuf *pos; + Gwn_IndexBuf *edges; + + Gwn_Batch *all_verts; + Gwn_Batch *all_edges; + + Gwn_Batch *overlay_verts; + + /* settings to determine if cache is invalid */ + bool is_dirty; + + struct { + int u_len, v_len, w_len; + } dims; + bool show_only_outside; + + bool is_editmode; +} LatticeBatchCache; + +/* Gwn_Batch cache management. */ + +static bool lattice_batch_cache_valid(Lattice *lt) +{ + LatticeBatchCache *cache = lt->batch_cache; + + if (cache == NULL) { + return false; + } + + if (cache->is_editmode != (lt->editlatt != NULL)) { + return false; + } + + if (cache->is_dirty) { + return false; + } + else { + if ((cache->dims.u_len != lt->pntsu) || + (cache->dims.v_len != lt->pntsv) || + (cache->dims.w_len != lt->pntsw) || + ((cache->show_only_outside != ((lt->flag & LT_OUTSIDE) != 0)))) + { + return false; + } + } + + return true; +} + +static void lattice_batch_cache_init(Lattice *lt) +{ + LatticeBatchCache *cache = lt->batch_cache; + + if (!cache) { + cache = lt->batch_cache = MEM_callocN(sizeof(*cache), __func__); + } + else { + memset(cache, 0, sizeof(*cache)); + } + + cache->dims.u_len = lt->pntsu; + cache->dims.v_len = lt->pntsv; + cache->dims.w_len = lt->pntsw; + cache->show_only_outside = (lt->flag & LT_OUTSIDE) != 0; + + cache->is_editmode = lt->editlatt != NULL; + + cache->is_dirty = false; +} + +static LatticeBatchCache *lattice_batch_cache_get(Lattice *lt) +{ + if (!lattice_batch_cache_valid(lt)) { + lattice_batch_cache_clear(lt); + lattice_batch_cache_init(lt); + } + return lt->batch_cache; +} + +void DRW_lattice_batch_cache_dirty(Lattice *lt, int mode) +{ + LatticeBatchCache *cache = lt->batch_cache; + if (cache == NULL) { + return; + } + switch (mode) { + case BKE_LATTICE_BATCH_DIRTY_ALL: + cache->is_dirty = true; + break; + case BKE_LATTICE_BATCH_DIRTY_SELECT: + /* TODO Separate Flag vbo */ + GWN_BATCH_DISCARD_SAFE(cache->overlay_verts); + break; + default: + BLI_assert(0); + } +} + +static void lattice_batch_cache_clear(Lattice *lt) +{ + LatticeBatchCache *cache = lt->batch_cache; + if (!cache) { + return; + } + + GWN_BATCH_DISCARD_SAFE(cache->all_verts); + GWN_BATCH_DISCARD_SAFE(cache->all_edges); + GWN_BATCH_DISCARD_SAFE(cache->overlay_verts); + + GWN_VERTBUF_DISCARD_SAFE(cache->pos); + GWN_INDEXBUF_DISCARD_SAFE(cache->edges); +} + +void DRW_lattice_batch_cache_free(Lattice *lt) +{ + lattice_batch_cache_clear(lt); + MEM_SAFE_FREE(lt->batch_cache); +} + +/* Gwn_Batch cache usage. */ +static Gwn_VertBuf *lattice_batch_cache_get_pos(LatticeRenderData *rdata, LatticeBatchCache *cache, + bool use_weight, const int actdef) +{ + BLI_assert(rdata->types & LR_DATATYPE_VERT); + + if (cache->pos == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, col; } attr_id; + + GWN_vertformat_clear(&format); + + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + if (use_weight) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + } + + const int vert_len = lattice_render_data_verts_len_get(rdata); + + cache->pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(cache->pos, vert_len); + for (int i = 0; i < vert_len; ++i) { + const BPoint *bp = lattice_render_data_vert_bpoint(rdata, i); + GWN_vertbuf_attr_set(cache->pos, attr_id.pos, i, bp->vec); + + if (use_weight) { + float w_col[4]; + lattice_render_data_weight_col_get(rdata, i, actdef, w_col); + + GWN_vertbuf_attr_set(cache->pos, attr_id.col, i, w_col); + } + } + } + + return cache->pos; +} + +static Gwn_IndexBuf *lattice_batch_cache_get_edges(LatticeRenderData *rdata, LatticeBatchCache *cache) +{ + BLI_assert(rdata->types & (LR_DATATYPE_VERT | LR_DATATYPE_EDGE)); + + if (cache->edges == NULL) { + const int vert_len = lattice_render_data_verts_len_get(rdata); + const int edge_len = lattice_render_data_edges_len_get(rdata); + int edge_len_real = 0; + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len); + +#define LATT_INDEX(u, v, w) \ + ((((w) * rdata->dims.v_len + (v)) * rdata->dims.u_len) + (u)) + + for (int w = 0; w < rdata->dims.w_len; w++) { + int wxt = (w == 0 || w == rdata->dims.w_len - 1); + for (int v = 0; v < rdata->dims.v_len; v++) { + int vxt = (v == 0 || v == rdata->dims.v_len - 1); + for (int u = 0; u < rdata->dims.u_len; u++) { + int uxt = (u == 0 || u == rdata->dims.u_len - 1); + + if (w && ((uxt || vxt) || !rdata->show_only_outside)) { + GWN_indexbuf_add_line_verts(&elb, LATT_INDEX(u, v, w - 1), LATT_INDEX(u, v, w)); + BLI_assert(edge_len_real <= edge_len); + edge_len_real++; + } + if (v && ((uxt || wxt) || !rdata->show_only_outside)) { + GWN_indexbuf_add_line_verts(&elb, LATT_INDEX(u, v - 1, w), LATT_INDEX(u, v, w)); + BLI_assert(edge_len_real <= edge_len); + edge_len_real++; + } + if (u && ((vxt || wxt) || !rdata->show_only_outside)) { + GWN_indexbuf_add_line_verts(&elb, LATT_INDEX(u - 1, v, w), LATT_INDEX(u, v, w)); + BLI_assert(edge_len_real <= edge_len); + edge_len_real++; + } + } + } + } + +#undef LATT_INDEX + + if (rdata->show_only_outside) { + BLI_assert(edge_len_real <= edge_len); + } + else { + BLI_assert(edge_len_real == edge_len); + } + + cache->edges = GWN_indexbuf_build(&elb); + } + + return cache->edges; +} + +static void lattice_batch_cache_create_overlay_batches(Lattice *lt) +{ + /* Since LR_DATATYPE_OVERLAY is slow to generate, generate them all at once */ + int options = LR_DATATYPE_VERT | LR_DATATYPE_OVERLAY; + + LatticeBatchCache *cache = lattice_batch_cache_get(lt); + LatticeRenderData *rdata = lattice_render_data_create(lt, options); + + if (cache->overlay_verts == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, data; } attr_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_U8, 1, GWN_FETCH_INT); + } + + const int vert_len = lattice_render_data_verts_len_get(rdata); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vert_len); + for (int i = 0; i < vert_len; ++i) { + const BPoint *bp = lattice_render_data_vert_bpoint(rdata, i); + + char vflag = 0; + if (bp->f1 & SELECT) { + if (i == rdata->actbp) { + vflag |= VFLAG_VERTEX_ACTIVE; + } + else { + vflag |= VFLAG_VERTEX_SELECTED; + } + } + + GWN_vertbuf_attr_set(vbo, attr_id.pos, i, bp->vec); + GWN_vertbuf_attr_set(vbo, attr_id.data, i, &vflag); + } + + cache->overlay_verts = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + + lattice_render_data_free(rdata); +} + +Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(Lattice *lt, bool use_weight, const int actdef) +{ + LatticeBatchCache *cache = lattice_batch_cache_get(lt); + + if (cache->all_edges == NULL) { + /* create batch from Lattice */ + LatticeRenderData *rdata = lattice_render_data_create(lt, LR_DATATYPE_VERT | LR_DATATYPE_EDGE); + + cache->all_edges = GWN_batch_create(GWN_PRIM_LINES, lattice_batch_cache_get_pos(rdata, cache, use_weight, actdef), + lattice_batch_cache_get_edges(rdata, cache)); + + lattice_render_data_free(rdata); + } + + return cache->all_edges; +} + +Gwn_Batch *DRW_lattice_batch_cache_get_all_verts(Lattice *lt) +{ + LatticeBatchCache *cache = lattice_batch_cache_get(lt); + + if (cache->all_verts == NULL) { + LatticeRenderData *rdata = lattice_render_data_create(lt, LR_DATATYPE_VERT); + + cache->all_verts = GWN_batch_create(GWN_PRIM_POINTS, lattice_batch_cache_get_pos(rdata, cache, false, -1), NULL); + + lattice_render_data_free(rdata); + } + + return cache->all_verts; +} + +Gwn_Batch *DRW_lattice_batch_cache_get_overlay_verts(Lattice *lt) +{ + LatticeBatchCache *cache = lattice_batch_cache_get(lt); + + if (cache->overlay_verts == NULL) { + lattice_batch_cache_create_overlay_batches(lt); + } + + return cache->overlay_verts; +} diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c new file mode 100644 index 00000000000..e1b66a85ca2 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -0,0 +1,4228 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file draw_cache_impl_mesh.c + * \ingroup draw + * + * \brief Mesh API for render engines + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math_vector.h" +#include "BLI_math_bits.h" +#include "BLI_string.h" +#include "BLI_alloca.h" +#include "BLI_edgehash.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" + +#include "BKE_customdata.h" +#include "BKE_deform.h" +#include "BKE_DerivedMesh.h" +#include "BKE_editmesh.h" +#include "BKE_editmesh_tangent.h" +#include "BKE_mesh.h" +#include "BKE_mesh_tangent.h" +#include "BKE_colorband.h" + +#include "bmesh.h" + +#include "GPU_batch.h" +#include "GPU_draw.h" +#include "GPU_material.h" +#include "GPU_texture.h" + +#include "DRW_render.h" + +#include "draw_cache_impl.h" /* own include */ + +static void mesh_batch_cache_clear(Mesh *me); + +/* ---------------------------------------------------------------------- */ + +/** \name Mesh/BMesh Interface (direct access to basic data). + * \{ */ + +static int mesh_render_verts_len_get(Mesh *me) +{ + return me->edit_btmesh ? me->edit_btmesh->bm->totvert : me->totvert; +} + +static int mesh_render_edges_len_get(Mesh *me) +{ + return me->edit_btmesh ? me->edit_btmesh->bm->totedge : me->totedge; +} + +static int mesh_render_looptri_len_get(Mesh *me) +{ + return me->edit_btmesh ? me->edit_btmesh->tottri : poly_to_tri_count(me->totpoly, me->totloop); +} + +static int mesh_render_polys_len_get(Mesh *me) +{ + return me->edit_btmesh ? me->edit_btmesh->bm->totface : me->totpoly; +} + +static int mesh_render_mat_len_get(Mesh *me) +{ + return MAX2(1, me->totcol); +} + +static int UNUSED_FUNCTION(mesh_render_loops_len_get)(Mesh *me) +{ + return me->edit_btmesh ? me->edit_btmesh->bm->totloop : me->totloop; +} + +/** \} */ + + +/* ---------------------------------------------------------------------- */ + +/** \name Mesh/BMesh Interface (indirect, partially cached access to complex data). + * \{ */ + +typedef struct EdgeAdjacentPolys { + int count; + int face_index[2]; +} EdgeAdjacentPolys; + +typedef struct EdgeDrawAttr { + unsigned char v_flag; + unsigned char e_flag; + unsigned char crease; + unsigned char bweight; +} EdgeDrawAttr; + +typedef struct MeshRenderData { + int types; + + int vert_len; + int edge_len; + int tri_len; + int loop_len; + int poly_len; + int mat_len; + int loose_vert_len; + int loose_edge_len; + + BMEditMesh *edit_bmesh; + struct EditMeshData *edit_data; + + MVert *mvert; + MEdge *medge; + MLoop *mloop; + MPoly *mpoly; + float (*orco)[3]; /* vertex coordinates normalized to bounding box */ + bool is_orco_allocated; + MDeformVert *dvert; + MLoopUV *mloopuv; + MLoopCol *mloopcol; + float (*loop_normals)[3]; + + /* CustomData 'cd' cache for efficient access. */ + struct { + struct { + MLoopUV **uv; + int uv_len; + int uv_active; + + MLoopCol **vcol; + int vcol_len; + int vcol_active; + + float (**tangent)[4]; + int tangent_len; + int tangent_active; + + bool *auto_vcol; + } layers; + + /* Custom-data offsets (only needed for BMesh access) */ + struct { + int crease; + int bweight; + int *uv; + int *vcol; + } offset; + + struct { + char (*auto_mix)[32]; + char (*uv)[32]; + char (*vcol)[32]; + char (*tangent)[32]; + } uuid; + + /* for certain cases we need an output loop-data storage (bmesh tangents) */ + struct { + CustomData ldata; + /* grr, special case variable (use in place of 'dm->tangent_mask') */ + short tangent_mask; + } output; + } cd; + + BMVert *eve_act; + BMEdge *eed_act; + BMFace *efa_act; + + /* Data created on-demand (usually not for bmesh-based data). */ + EdgeAdjacentPolys *edges_adjacent_polys; + MLoopTri *mlooptri; + int *loose_edges; + int *loose_verts; + + float (*poly_normals)[3]; + float (*vert_weight_color)[3]; + char (*vert_color)[3]; + Gwn_PackedNormal *poly_normals_pack; + Gwn_PackedNormal *vert_normals_pack; + bool *edge_select_bool; +} MeshRenderData; + +enum { + MR_DATATYPE_VERT = 1 << 0, + MR_DATATYPE_EDGE = 1 << 1, + MR_DATATYPE_LOOPTRI = 1 << 2, + MR_DATATYPE_LOOP = 1 << 3, + MR_DATATYPE_POLY = 1 << 4, + MR_DATATYPE_OVERLAY = 1 << 5, + MR_DATATYPE_SHADING = 1 << 6, + MR_DATATYPE_DVERT = 1 << 7, + MR_DATATYPE_LOOPCOL = 1 << 8, + MR_DATATYPE_LOOPUV = 1 << 9, +}; + +/** + * These functions look like they would be slow but they will typically return true on the first iteration. + * Only false when all attached elements are hidden. + */ +static bool bm_vert_has_visible_edge(const BMVert *v) +{ + const BMEdge *e_iter, *e_first; + + e_iter = e_first = v->e; + do { + if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) { + return true; + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); + return false; +} + +static bool bm_edge_has_visible_face(const BMEdge *e) +{ + const BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) { + return true; + } + } while ((l_iter = l_iter->radial_next) != l_first); + return false; +} + + +static void mesh_cd_calc_used_gpu_layers( + CustomData *UNUSED(cd_vdata), uchar cd_vused[CD_NUMTYPES], + CustomData *cd_ldata, ushort cd_lused[CD_NUMTYPES], + struct GPUMaterial **gpumat_array, int gpumat_array_len) +{ + /* See: DM_vertex_attributes_from_gpu for similar logic */ + GPUVertexAttribs gattribs = {{{0}}}; + + for (int i = 0; i < gpumat_array_len; i++) { + GPUMaterial *gpumat = gpumat_array[i]; + if (gpumat) { + GPU_material_vertex_attributes(gpumat, &gattribs); + for (int j = 0; j < gattribs.totlayer; j++) { + const char *name = gattribs.layer[j].name; + int type = gattribs.layer[j].type; + int layer = -1; + + if (type == CD_AUTO_FROM_NAME) { + /* We need to deduct what exact layer is used. + * + * We do it based on the specified name. + */ + if (name[0] != '\0') { + layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name); + type = CD_MTFACE; + + if (layer == -1) { + layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name); + type = CD_MCOL; + } +#if 0 /* Tangents are always from UV's - this will never happen. */ + if (layer == -1) { + layer = CustomData_get_named_layer(cd_ldata, CD_TANGENT, name); + type = CD_TANGENT; + } +#endif + if (layer == -1) { + continue; + } + } + else { + /* Fall back to the UV layer, which matches old behavior. */ + type = CD_MTFACE; + } + } + + switch (type) { + case CD_MTFACE: + { + if (layer == -1) { + layer = (name[0] != '\0') ? + CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) : + CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); + } + if (layer != -1) { + cd_lused[CD_MLOOPUV] |= (1 << layer); + } + break; + } + case CD_TANGENT: + { + if (layer == -1) { + layer = (name[0] != '\0') ? + CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) : + CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); + } + if (layer != -1) { + cd_lused[CD_TANGENT] |= (1 << layer); + } + else { + /* no UV layers at all => requesting orco */ + cd_lused[CD_TANGENT] |= DM_TANGENT_MASK_ORCO; + cd_vused[CD_ORCO] |= 1; + } + break; + } + case CD_MCOL: + { + if (layer == -1) { + layer = (name[0] != '\0') ? + CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) : + CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL); + } + if (layer != -1) { + cd_lused[CD_MLOOPCOL] |= (1 << layer); + } + break; + } + case CD_ORCO: + { + cd_vused[CD_ORCO] |= 1; + break; + } + } + } + } + } +} + + +static void mesh_render_calc_normals_loop_and_poly(const Mesh *me, const float split_angle, MeshRenderData *rdata) +{ + BLI_assert((me->flag & ME_AUTOSMOOTH) != 0); + + int totloop = me->totloop; + int totpoly = me->totpoly; + float (*loop_normals)[3] = MEM_mallocN(sizeof(*loop_normals) * totloop, __func__); + float (*poly_normals)[3] = MEM_mallocN(sizeof(*poly_normals) * totpoly, __func__); + short (*clnors)[2] = CustomData_get_layer(&me->ldata, CD_CUSTOMLOOPNORMAL); + + BKE_mesh_calc_normals_poly( + me->mvert, NULL, me->totvert, + me->mloop, me->mpoly, totloop, totpoly, poly_normals, false); + + BKE_mesh_normals_loop_split( + me->mvert, me->totvert, me->medge, me->totedge, + me->mloop, loop_normals, totloop, me->mpoly, poly_normals, totpoly, + true, split_angle, NULL, clnors, NULL); + + rdata->loop_len = totloop; + rdata->poly_len = totpoly; + rdata->loop_normals = loop_normals; + rdata->poly_normals = poly_normals; +} + + +/** + * TODO(campbell): 'gpumat_array' may include materials linked to the object. + * While not default, object materials should be supported. + * Although this only impacts the data thats generated, not the materials that display. + */ +static MeshRenderData *mesh_render_data_create_ex( + Mesh *me, const int types, + struct GPUMaterial **gpumat_array, uint gpumat_array_len) +{ + MeshRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__); + rdata->types = types; + rdata->mat_len = mesh_render_mat_len_get(me); + + CustomData_reset(&rdata->cd.output.ldata); + + const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0; + const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI; + + if (me->edit_btmesh) { + BMEditMesh *embm = me->edit_btmesh; + BMesh *bm = embm->bm; + + rdata->edit_bmesh = embm; + rdata->edit_data = me->runtime.edit_data; + + int bm_ensure_types = 0; + if (types & MR_DATATYPE_VERT) { + rdata->vert_len = bm->totvert; + bm_ensure_types |= BM_VERT; + } + if (types & MR_DATATYPE_EDGE) { + rdata->edge_len = bm->totedge; + bm_ensure_types |= BM_EDGE; + } + if (types & MR_DATATYPE_LOOPTRI) { + BKE_editmesh_tessface_calc(embm); + int tottri = embm->tottri; + rdata->mlooptri = MEM_mallocN(sizeof(*rdata->mlooptri) * embm->tottri, __func__); + for (int index = 0; index < tottri ; index ++ ) { + BMLoop **bmtri = embm->looptris[index]; + MLoopTri *mtri = &rdata->mlooptri[index]; + mtri->tri[0] = BM_elem_index_get(bmtri[0]); + mtri->tri[1] = BM_elem_index_get(bmtri[1]); + mtri->tri[2] = BM_elem_index_get(bmtri[2]); + } + rdata->tri_len = tottri; + } + if (types & MR_DATATYPE_LOOP) { + int totloop = bm->totloop; + if (is_auto_smooth) { + rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * totloop, __func__); + BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1); + } + rdata->loop_len = totloop; + bm_ensure_types |= BM_LOOP; + } + if (types & MR_DATATYPE_POLY) { + rdata->poly_len = bm->totface; + bm_ensure_types |= BM_FACE; + } + if (types & MR_DATATYPE_OVERLAY) { + rdata->efa_act = BM_mesh_active_face_get(bm, false, true); + rdata->eed_act = BM_mesh_active_edge_get(bm); + rdata->eve_act = BM_mesh_active_vert_get(bm); + rdata->cd.offset.crease = CustomData_get_offset(&bm->edata, CD_CREASE); + rdata->cd.offset.bweight = CustomData_get_offset(&bm->edata, CD_BWEIGHT); + } + if (types & (MR_DATATYPE_DVERT)) { + bm_ensure_types |= BM_VERT; + } + if (rdata->edit_data != NULL) { + bm_ensure_types |= BM_VERT; + } + + BM_mesh_elem_index_ensure(bm, bm_ensure_types); + BM_mesh_elem_table_ensure(bm, bm_ensure_types & ~BM_LOOP); + if (types & MR_DATATYPE_OVERLAY) { + rdata->loose_vert_len = rdata->loose_edge_len = 0; + + int *lverts = rdata->loose_verts = MEM_mallocN(rdata->vert_len * sizeof(int), "Loose Vert"); + int *ledges = rdata->loose_edges = MEM_mallocN(rdata->edge_len * sizeof(int), "Loose Edges"); + + { + BLI_assert((bm->elem_table_dirty & BM_VERT) == 0); + BMVert **vtable = bm->vtable; + for (int i = 0; i < bm->totvert; i++) { + const BMVert *eve = vtable[i]; + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + /* Loose vert */ + if (eve->e == NULL || !bm_vert_has_visible_edge(eve)) { + lverts[rdata->loose_vert_len++] = i; + } + } + } + } + + { + BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0); + BMEdge **etable = bm->etable; + for (int i = 0; i < bm->totedge; i++) { + const BMEdge *eed = etable[i]; + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + /* Loose edge */ + if (eed->l == NULL || !bm_edge_has_visible_face(eed)) { + ledges[rdata->loose_edge_len++] = i; + } + } + } + } + + rdata->loose_verts = MEM_reallocN(rdata->loose_verts, rdata->loose_vert_len * sizeof(int)); + rdata->loose_edges = MEM_reallocN(rdata->loose_edges, rdata->loose_edge_len * sizeof(int)); + } + } + else { + if (types & (MR_DATATYPE_VERT)) { + rdata->vert_len = me->totvert; + rdata->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); + } + if (types & (MR_DATATYPE_EDGE)) { + rdata->edge_len = me->totedge; + rdata->medge = CustomData_get_layer(&me->edata, CD_MEDGE); + } + if (types & MR_DATATYPE_LOOPTRI) { + const int tri_len = rdata->tri_len = poly_to_tri_count(me->totpoly, me->totloop); + rdata->mlooptri = MEM_mallocN(sizeof(*rdata->mlooptri) * tri_len, __func__); + BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, rdata->mlooptri); + } + if (types & MR_DATATYPE_LOOP) { + rdata->loop_len = me->totloop; + rdata->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); + + if (is_auto_smooth) { + mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata); + } + } + if (types & MR_DATATYPE_POLY) { + rdata->poly_len = me->totpoly; + rdata->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); + } + if (types & MR_DATATYPE_DVERT) { + rdata->vert_len = me->totvert; + rdata->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); + } + if (types & MR_DATATYPE_LOOPCOL) { + rdata->loop_len = me->totloop; + rdata->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); + } + if (types & MR_DATATYPE_LOOPUV) { + rdata->loop_len = me->totloop; + rdata->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); + } + } + + if (types & MR_DATATYPE_SHADING) { + CustomData *cd_vdata, *cd_ldata; + + if (me->edit_btmesh) { + BMesh *bm = me->edit_btmesh->bm; + cd_vdata = &bm->vdata; + cd_ldata = &bm->ldata; + } + else { + cd_vdata = &me->vdata; + cd_ldata = &me->ldata; + } + + /* Add edge/poly if we need them */ + uchar cd_vused[CD_NUMTYPES] = {0}; + ushort cd_lused[CD_NUMTYPES] = {0}; + + mesh_cd_calc_used_gpu_layers( + cd_vdata, cd_vused, + cd_ldata, cd_lused, + gpumat_array, gpumat_array_len); + + + rdata->cd.layers.uv_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); + rdata->cd.layers.vcol_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL); + rdata->cd.layers.tangent_active = rdata->cd.layers.uv_active; + +#define CD_VALIDATE_ACTIVE_LAYER(active_index, used) \ + if ((active_index != -1) && (used & (1 << active_index)) == 0) { \ + active_index = -1; \ + } ((void)0) + + CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.uv_active, cd_lused[CD_MLOOPUV]); + CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.tangent_active, cd_lused[CD_TANGENT]); + CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.vcol_active, cd_lused[CD_MLOOPCOL]); + +#undef CD_VALIDATE_ACTIVE_LAYER + + rdata->is_orco_allocated = false; + if (cd_vused[CD_ORCO] & 1) { + rdata->orco = CustomData_get_layer(cd_vdata, CD_ORCO); + /* If orco is not available compute it ourselves */ + if (!rdata->orco) { + rdata->is_orco_allocated = true; + if (me->edit_btmesh) { + BMesh *bm = me->edit_btmesh->bm; + rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh"); + BLI_assert((bm->elem_table_dirty & BM_VERT) == 0); + BMVert **vtable = bm->vtable; + for (int i = 0; i < bm->totvert; i++) { + copy_v3_v3(rdata->orco[i], vtable[i]->co); + } + BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0); + } + else { + rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh"); + MVert *mvert = rdata->mvert; + for (int a = 0; a < rdata->vert_len; a++, mvert++) { + copy_v3_v3(rdata->orco[a], mvert->co); + } + BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0); + } + } + } + else { + rdata->orco = NULL; + } + + /* don't access mesh directly, instead use vars taken from BMesh or Mesh */ +#define me DONT_USE_THIS +#ifdef me /* quiet warning */ +#endif + struct { + uint uv_len; + uint vcol_len; + } cd_layers_src = { + .uv_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPUV), + .vcol_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPCOL), + }; + + rdata->cd.layers.uv_len = count_bits_i(cd_lused[CD_MLOOPUV]); + rdata->cd.layers.tangent_len = count_bits_i(cd_lused[CD_TANGENT]); + rdata->cd.layers.vcol_len = count_bits_i(cd_lused[CD_MLOOPCOL]); + + rdata->cd.layers.uv = MEM_mallocN(sizeof(*rdata->cd.layers.uv) * rdata->cd.layers.uv_len, __func__); + rdata->cd.layers.vcol = MEM_mallocN(sizeof(*rdata->cd.layers.vcol) * rdata->cd.layers.vcol_len, __func__); + rdata->cd.layers.tangent = MEM_mallocN(sizeof(*rdata->cd.layers.tangent) * rdata->cd.layers.tangent_len, __func__); + + rdata->cd.uuid.uv = MEM_mallocN(sizeof(*rdata->cd.uuid.uv) * rdata->cd.layers.uv_len, __func__); + rdata->cd.uuid.vcol = MEM_mallocN(sizeof(*rdata->cd.uuid.vcol) * rdata->cd.layers.vcol_len, __func__); + rdata->cd.uuid.tangent = MEM_mallocN(sizeof(*rdata->cd.uuid.tangent) * rdata->cd.layers.tangent_len, __func__); + + rdata->cd.offset.uv = MEM_mallocN(sizeof(*rdata->cd.offset.uv) * rdata->cd.layers.uv_len, __func__); + rdata->cd.offset.vcol = MEM_mallocN(sizeof(*rdata->cd.offset.vcol) * rdata->cd.layers.vcol_len, __func__); + + /* Allocate max */ + rdata->cd.layers.auto_vcol = MEM_callocN( + sizeof(*rdata->cd.layers.auto_vcol) * rdata->cd.layers.vcol_len, __func__); + rdata->cd.uuid.auto_mix = MEM_mallocN( + sizeof(*rdata->cd.uuid.auto_mix) * (rdata->cd.layers.vcol_len + rdata->cd.layers.uv_len), __func__); + + /* XXX FIXME XXX */ + /* We use a hash to identify each data layer based on its name. + * Gawain then search for this name in the current shader and bind if it exists. + * NOTE : This is prone to hash collision. + * One solution to hash collision would be to format the cd layer name + * to a safe glsl var name, but without name clash. + * NOTE 2 : Replicate changes to code_generate_vertex_new() in gpu_codegen.c */ + if (rdata->cd.layers.vcol_len != 0) { + for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.vcol_len; i_src++, i_dst++) { + if ((cd_lused[CD_MLOOPCOL] & (1 << i_src)) == 0) { + i_dst--; + if (rdata->cd.layers.vcol_active >= i_src) { + rdata->cd.layers.vcol_active--; + } + } + else { + const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i_src); + uint hash = BLI_ghashutil_strhash_p(name); + BLI_snprintf(rdata->cd.uuid.vcol[i_dst], sizeof(*rdata->cd.uuid.vcol), "c%u", hash); + rdata->cd.layers.vcol[i_dst] = CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i_src); + if (rdata->edit_bmesh) { + rdata->cd.offset.vcol[i_dst] = CustomData_get_n_offset( + &rdata->edit_bmesh->bm->ldata, CD_MLOOPCOL, i_src); + } + + /* Gather number of auto layers. */ + /* We only do vcols that are not overridden by uvs */ + if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, name) == -1) { + BLI_snprintf( + rdata->cd.uuid.auto_mix[rdata->cd.layers.uv_len + i_dst], + sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash); + rdata->cd.layers.auto_vcol[i_dst] = true; + } + } + } + } + + /* Start Fresh */ + CustomData_free_layers(cd_ldata, CD_TANGENT, rdata->loop_len); + CustomData_free_layers(cd_ldata, CD_MLOOPTANGENT, rdata->loop_len); + + if (rdata->cd.layers.uv_len != 0) { + for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) { + if ((cd_lused[CD_MLOOPUV] & (1 << i_src)) == 0) { + i_dst--; + if (rdata->cd.layers.uv_active >= i_src) { + rdata->cd.layers.uv_active--; + } + } + else { + const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src); + uint hash = BLI_ghashutil_strhash_p(name); + + BLI_snprintf(rdata->cd.uuid.uv[i_dst], sizeof(*rdata->cd.uuid.uv), "u%u", hash); + rdata->cd.layers.uv[i_dst] = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i_src); + if (rdata->edit_bmesh) { + rdata->cd.offset.uv[i_dst] = CustomData_get_n_offset( + &rdata->edit_bmesh->bm->ldata, CD_MLOOPUV, i_src); + } + BLI_snprintf(rdata->cd.uuid.auto_mix[i_dst], sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash); + } + } + } + + if (rdata->cd.layers.tangent_len != 0) { + + /* -------------------------------------------------------------------- */ + /* Pre-calculate tangents into 'rdata->cd.output.ldata' */ + + BLI_assert(!CustomData_has_layer(&rdata->cd.output.ldata, CD_TANGENT)); + + /* Tangent Names */ + char tangent_names[MAX_MTFACE][MAX_NAME]; + for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) { + if ((cd_lused[CD_TANGENT] & (1 << i_src)) == 0) { + i_dst--; + } + else { + BLI_strncpy( + tangent_names[i_dst], + CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src), MAX_NAME); + } + } + + /* If tangent from orco is requested, decrement tangent_len */ + int actual_tangent_len = (cd_lused[CD_TANGENT] & DM_TANGENT_MASK_ORCO) ? + rdata->cd.layers.tangent_len - 1 : rdata->cd.layers.tangent_len; + if (rdata->edit_bmesh) { + BMEditMesh *em = rdata->edit_bmesh; + BMesh *bm = em->bm; + + if (is_auto_smooth && rdata->loop_normals == NULL) { + /* Should we store the previous array of `loop_normals` in somewhere? */ + rdata->loop_len = bm->totloop; + rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * rdata->loop_len, __func__); + BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1); + } + + bool calc_active_tangent = false; + + BKE_editmesh_loop_tangent_calc( + em, calc_active_tangent, + tangent_names, actual_tangent_len, + rdata->poly_normals, rdata->loop_normals, + rdata->orco, + &rdata->cd.output.ldata, bm->totloop, + &rdata->cd.output.tangent_mask); + } + else { +#undef me + + if (is_auto_smooth && rdata->loop_normals == NULL) { + /* Should we store the previous array of `loop_normals` in CustomData? */ + mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata); + } + + bool calc_active_tangent = false; + + BKE_mesh_calc_loop_tangent_ex( + me->mvert, + me->mpoly, me->totpoly, + me->mloop, + rdata->mlooptri, rdata->tri_len, + cd_ldata, + calc_active_tangent, + tangent_names, actual_tangent_len, + rdata->poly_normals, rdata->loop_normals, + rdata->orco, + &rdata->cd.output.ldata, me->totloop, + &rdata->cd.output.tangent_mask); + + /* If we store tangents in the mesh, set temporary. */ +#if 0 + CustomData_set_layer_flag(cd_ldata, CD_TANGENT, CD_FLAG_TEMPORARY); +#endif + +#define me DONT_USE_THIS +#ifdef me /* quiet warning */ +#endif + } + + /* End tangent calculation */ + /* -------------------------------------------------------------------- */ + + BLI_assert(CustomData_number_of_layers(&rdata->cd.output.ldata, CD_TANGENT) == rdata->cd.layers.tangent_len); + + int i_dst = 0; + for (int i_src = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) { + if ((cd_lused[CD_TANGENT] & (1 << i_src)) == 0) { + i_dst--; + if (rdata->cd.layers.tangent_active >= i_src) { + rdata->cd.layers.tangent_active--; + } + } + else { + const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i_src); + uint hash = BLI_ghashutil_strhash_p(name); + + BLI_snprintf(rdata->cd.uuid.tangent[i_dst], sizeof(*rdata->cd.uuid.tangent), "t%u", hash); + + /* Done adding tangents. */ + + /* note: BKE_editmesh_loop_tangent_calc calculates 'CD_TANGENT', + * not 'CD_MLOOPTANGENT' (as done below). It's OK, they're compatible. */ + + /* note: normally we'd use 'i_src' here, but 'i_dst' is in sync with 'rdata->cd.output' */ + rdata->cd.layers.tangent[i_dst] = CustomData_get_layer_n(&rdata->cd.output.ldata, CD_TANGENT, i_dst); + if (rdata->tri_len != 0) { + BLI_assert(rdata->cd.layers.tangent[i_dst] != NULL); + } + } + } + if (cd_lused[CD_TANGENT] & DM_TANGENT_MASK_ORCO) { + const char *name = CustomData_get_layer_name(&rdata->cd.output.ldata, CD_TANGENT, i_dst); + uint hash = BLI_ghashutil_strhash_p(name); + BLI_snprintf(rdata->cd.uuid.tangent[i_dst], sizeof(*rdata->cd.uuid.tangent), "t%u", hash); + + rdata->cd.layers.tangent[i_dst] = CustomData_get_layer_n(&rdata->cd.output.ldata, CD_TANGENT, i_dst); + } + } + +#undef me + } + + return rdata; +} + +static void mesh_render_data_free(MeshRenderData *rdata) +{ + if (rdata->is_orco_allocated) { + MEM_SAFE_FREE(rdata->orco); + } + MEM_SAFE_FREE(rdata->cd.offset.uv); + MEM_SAFE_FREE(rdata->cd.offset.vcol); + MEM_SAFE_FREE(rdata->cd.uuid.auto_mix); + MEM_SAFE_FREE(rdata->cd.uuid.uv); + MEM_SAFE_FREE(rdata->cd.uuid.vcol); + MEM_SAFE_FREE(rdata->cd.uuid.tangent); + MEM_SAFE_FREE(rdata->cd.layers.uv); + MEM_SAFE_FREE(rdata->cd.layers.vcol); + MEM_SAFE_FREE(rdata->cd.layers.tangent); + MEM_SAFE_FREE(rdata->cd.layers.auto_vcol); + MEM_SAFE_FREE(rdata->loose_verts); + MEM_SAFE_FREE(rdata->loose_edges); + MEM_SAFE_FREE(rdata->edges_adjacent_polys); + MEM_SAFE_FREE(rdata->mlooptri); + MEM_SAFE_FREE(rdata->loop_normals); + MEM_SAFE_FREE(rdata->poly_normals); + MEM_SAFE_FREE(rdata->poly_normals_pack); + MEM_SAFE_FREE(rdata->vert_normals_pack); + MEM_SAFE_FREE(rdata->vert_weight_color); + MEM_SAFE_FREE(rdata->edge_select_bool); + MEM_SAFE_FREE(rdata->vert_color); + + CustomData_free(&rdata->cd.output.ldata, rdata->loop_len); + + MEM_freeN(rdata); +} + +static MeshRenderData *mesh_render_data_create(Mesh *me, const int types) +{ + return mesh_render_data_create_ex(me, types, NULL, 0); +} + +/** \} */ + + +/* ---------------------------------------------------------------------- */ + +/** \name Accessor Functions + * \{ */ + +static const char *mesh_render_data_uv_auto_layer_uuid_get(const MeshRenderData *rdata, int layer) +{ + BLI_assert(rdata->types & MR_DATATYPE_SHADING); + return rdata->cd.uuid.auto_mix[layer]; +} + +static const char *mesh_render_data_vcol_auto_layer_uuid_get(const MeshRenderData *rdata, int layer) +{ + BLI_assert(rdata->types & MR_DATATYPE_SHADING); + return rdata->cd.uuid.auto_mix[rdata->cd.layers.uv_len + layer]; +} + +static const char *mesh_render_data_uv_layer_uuid_get(const MeshRenderData *rdata, int layer) +{ + BLI_assert(rdata->types & MR_DATATYPE_SHADING); + return rdata->cd.uuid.uv[layer]; +} + +static const char *mesh_render_data_vcol_layer_uuid_get(const MeshRenderData *rdata, int layer) +{ + BLI_assert(rdata->types & MR_DATATYPE_SHADING); + return rdata->cd.uuid.vcol[layer]; +} + +static const char *mesh_render_data_tangent_layer_uuid_get(const MeshRenderData *rdata, int layer) +{ + BLI_assert(rdata->types & MR_DATATYPE_SHADING); + return rdata->cd.uuid.tangent[layer]; +} + +static int mesh_render_data_verts_len_get(const MeshRenderData *rdata) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + return rdata->vert_len; +} + +static int mesh_render_data_loose_verts_len_get(const MeshRenderData *rdata) +{ + BLI_assert(rdata->types & MR_DATATYPE_OVERLAY); + return rdata->loose_vert_len; +} + +static int mesh_render_data_edges_len_get(const MeshRenderData *rdata) +{ + BLI_assert(rdata->types & MR_DATATYPE_EDGE); + return rdata->edge_len; +} + +static int mesh_render_data_loose_edges_len_get(const MeshRenderData *rdata) +{ + BLI_assert(rdata->types & MR_DATATYPE_OVERLAY); + return rdata->loose_edge_len; +} + +static int mesh_render_data_looptri_len_get(const MeshRenderData *rdata) +{ + BLI_assert(rdata->types & MR_DATATYPE_LOOPTRI); + return rdata->tri_len; +} + +static int mesh_render_data_mat_len_get(const MeshRenderData *rdata) +{ + BLI_assert(rdata->types & MR_DATATYPE_POLY); + return rdata->mat_len; +} + +static int UNUSED_FUNCTION(mesh_render_data_loops_len_get)(const MeshRenderData *rdata) +{ + BLI_assert(rdata->types & MR_DATATYPE_LOOP); + return rdata->loop_len; +} + +static int mesh_render_data_polys_len_get(const MeshRenderData *rdata) +{ + BLI_assert(rdata->types & MR_DATATYPE_POLY); + return rdata->poly_len; +} + +/** \} */ + + +/* ---------------------------------------------------------------------- */ + +/** \name Internal Cache (Lazy Initialization) + * \{ */ + +/** Ensure #MeshRenderData.poly_normals_pack */ +static void mesh_render_data_ensure_poly_normals_pack(MeshRenderData *rdata) +{ + Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack; + if (pnors_pack == NULL) { + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter fiter; + BMFace *efa; + int i; + + pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__); + BM_ITER_MESH_INDEX(efa, &fiter, bm, BM_FACES_OF_MESH, i) { + pnors_pack[i] = GWN_normal_convert_i10_v3(efa->no); + } + } + else { + float (*pnors)[3] = rdata->poly_normals; + + if (!pnors) { + pnors = rdata->poly_normals = MEM_mallocN(sizeof(*pnors) * rdata->poly_len, __func__); + BKE_mesh_calc_normals_poly( + rdata->mvert, NULL, rdata->vert_len, + rdata->mloop, rdata->mpoly, rdata->loop_len, rdata->poly_len, pnors, true); + } + + pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__); + for (int i = 0; i < rdata->poly_len; i++) { + pnors_pack[i] = GWN_normal_convert_i10_v3(pnors[i]); + } + } + } +} + +/** Ensure #MeshRenderData.vert_normals_pack */ +static void mesh_render_data_ensure_vert_normals_pack(MeshRenderData *rdata) +{ + Gwn_PackedNormal *vnors_pack = rdata->vert_normals_pack; + if (vnors_pack == NULL) { + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter viter; + BMVert *eve; + int i; + + vnors_pack = rdata->vert_normals_pack = MEM_mallocN(sizeof(*vnors_pack) * rdata->vert_len, __func__); + BM_ITER_MESH_INDEX(eve, &viter, bm, BM_VERT, i) { + vnors_pack[i] = GWN_normal_convert_i10_v3(eve->no); + } + } + else { + /* data from mesh used directly */ + BLI_assert(0); + } + } +} + + +/** Ensure #MeshRenderData.vert_color */ +static void mesh_render_data_ensure_vert_color(MeshRenderData *rdata) +{ + char (*vcol)[3] = rdata->vert_color; + if (vcol == NULL) { + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL); + if (cd_loop_color_offset == -1) { + goto fallback; + } + + vcol = rdata->vert_color = MEM_mallocN(sizeof(*vcol) * rdata->loop_len, __func__); + + BMIter fiter; + BMFace *efa; + int i = 0; + + BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + const MLoopCol *lcol = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_color_offset); + vcol[i][0] = lcol->r; + vcol[i][1] = lcol->g; + vcol[i][2] = lcol->b; + i += 1; + } while ((l_iter = l_iter->next) != l_first); + } + BLI_assert(i == rdata->loop_len); + } + else { + if (rdata->mloopcol == NULL) { + goto fallback; + } + + vcol = rdata->vert_color = MEM_mallocN(sizeof(*vcol) * rdata->loop_len, __func__); + + for (int i = 0; i < rdata->loop_len; i++) { + vcol[i][0] = rdata->mloopcol[i].r; + vcol[i][1] = rdata->mloopcol[i].g; + vcol[i][2] = rdata->mloopcol[i].b; + } + } + } + return; + +fallback: + vcol = rdata->vert_color = MEM_mallocN(sizeof(*vcol) * rdata->loop_len, __func__); + + for (int i = 0; i < rdata->loop_len; i++) { + vcol[i][0] = 255; + vcol[i][1] = 255; + vcol[i][2] = 255; + } +} + +/* TODO, move into shader? */ +static void rgb_from_weight(float r_rgb[3], const float weight) +{ + const float blend = ((weight / 2.0f) + 0.5f); + + if (weight <= 0.25f) { /* blue->cyan */ + r_rgb[0] = 0.0f; + r_rgb[1] = blend * weight * 4.0f; + r_rgb[2] = blend; + } + else if (weight <= 0.50f) { /* cyan->green */ + r_rgb[0] = 0.0f; + r_rgb[1] = blend; + r_rgb[2] = blend * (1.0f - ((weight - 0.25f) * 4.0f)); + } + else if (weight <= 0.75f) { /* green->yellow */ + r_rgb[0] = blend * ((weight - 0.50f) * 4.0f); + r_rgb[1] = blend; + r_rgb[2] = 0.0f; + } + else if (weight <= 1.0f) { /* yellow->red */ + r_rgb[0] = blend; + r_rgb[1] = blend * (1.0f - ((weight - 0.75f) * 4.0f)); + r_rgb[2] = 0.0f; + } + else { + /* exceptional value, unclamped or nan, + * avoid uninitialized memory use */ + r_rgb[0] = 1.0f; + r_rgb[1] = 0.0f; + r_rgb[2] = 1.0f; + } +} + + +/** Ensure #MeshRenderData.vert_weight_color */ +static void mesh_render_data_ensure_vert_weight_color(MeshRenderData *rdata, const int defgroup) +{ + float (*vweight)[3] = rdata->vert_weight_color; + if (vweight == NULL) { + if (defgroup == -1) { + goto fallback; + } + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); + if (cd_dvert_offset == -1) { + goto fallback; + } + + BMIter viter; + BMVert *eve; + int i; + + vweight = rdata->vert_weight_color = MEM_mallocN(sizeof(*vweight) * rdata->vert_len, __func__); + BM_ITER_MESH_INDEX(eve, &viter, bm, BM_VERT, i) { + const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + float weight = defvert_find_weight(dvert, defgroup); + if (U.flag & USER_CUSTOM_RANGE) { + BKE_colorband_evaluate(&U.coba_weight, weight, vweight[i]); + } + else { + rgb_from_weight(vweight[i], weight); + } + } + } + else { + if (rdata->dvert == NULL) { + goto fallback; + } + + vweight = rdata->vert_weight_color = MEM_mallocN(sizeof(*vweight) * rdata->vert_len, __func__); + for (int i = 0; i < rdata->vert_len; i++) { + float weight = defvert_find_weight(&rdata->dvert[i], defgroup); + if (U.flag & USER_CUSTOM_RANGE) { + BKE_colorband_evaluate(&U.coba_weight, weight, vweight[i]); + } + else { + rgb_from_weight(vweight[i], weight); + } + } + } + } + return; + +fallback: + vweight = rdata->vert_weight_color = MEM_callocN(sizeof(*vweight) * rdata->vert_len, __func__); + + for (int i = 0; i < rdata->vert_len; i++) { + vweight[i][2] = 0.5f; + } +} + +/** Ensure #MeshRenderData.edge_select_bool */ +static void mesh_render_data_ensure_edge_select_bool(MeshRenderData *rdata, bool use_wire) +{ + bool *edge_select_bool = rdata->edge_select_bool; + if (edge_select_bool == NULL) { + edge_select_bool = rdata->edge_select_bool = + MEM_callocN(sizeof(*edge_select_bool) * rdata->edge_len, __func__); + + for (int i = 0; i < rdata->poly_len; i++) { + MPoly *poly = &rdata->mpoly[i]; + + if (poly->flag & ME_FACE_SEL) { + for (int j = 0; j < poly->totloop; j++) { + MLoop *loop = &rdata->mloop[poly->loopstart + j]; + if (use_wire) { + edge_select_bool[loop->e] = true; + } + else { + /* Not totally correct, will cause problems for edges with 3x faces. */ + edge_select_bool[loop->e] = !edge_select_bool[loop->e]; + } + } + } + } + } +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ + +/** \name Internal Cache Generation + * \{ */ + +static bool mesh_render_data_pnors_pcenter_select_get( + MeshRenderData *rdata, const int poly, + float r_pnors[3], float r_center[3], bool *r_selected) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + if (rdata->edit_bmesh) { + const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, poly); + if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + return false; + } + BM_face_calc_center_mean(efa, r_center); + copy_v3_v3(r_pnors, efa->no); + *r_selected = (BM_elem_flag_test(efa, BM_ELEM_SELECT) != 0) ? true : false; + } + else { + MVert *mvert = rdata->mvert; + const MPoly *mpoly = rdata->mpoly + poly; + const MLoop *mloop = rdata->mloop + mpoly->loopstart; + + BKE_mesh_calc_poly_center(mpoly, mloop, mvert, r_center); + BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, r_pnors); + + *r_selected = false; /* No selection if not in edit mode */ + } + + return true; +} + +static bool mesh_render_data_edge_vcos_manifold_pnors( + MeshRenderData *rdata, const int edge_index, + float **r_vco1, float **r_vco2, float **r_pnor1, float **r_pnor2, bool *r_is_manifold) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMEdge *eed = BM_edge_at_index(bm, edge_index); + if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + return false; + } + *r_vco1 = eed->v1->co; + *r_vco2 = eed->v2->co; + if (BM_edge_is_manifold(eed)) { + *r_pnor1 = eed->l->f->no; + *r_pnor2 = eed->l->radial_next->f->no; + *r_is_manifold = true; + } + else if (eed->l != NULL) { + *r_pnor1 = eed->l->f->no; + *r_pnor2 = eed->l->f->no; + *r_is_manifold = false; + } + else { + *r_pnor1 = eed->v1->no; + *r_pnor2 = eed->v1->no; + *r_is_manifold = false; + } + } + else { + MVert *mvert = rdata->mvert; + MEdge *medge = rdata->medge; + EdgeAdjacentPolys *eap = rdata->edges_adjacent_polys; + float (*pnors)[3] = rdata->poly_normals; + + if (!eap) { + const MLoop *mloop = rdata->mloop; + const MPoly *mpoly = rdata->mpoly; + const int poly_len = rdata->poly_len; + const bool do_pnors = (poly_len != 0 && pnors == NULL); + + eap = rdata->edges_adjacent_polys = MEM_mallocN(sizeof(*eap) * rdata->edge_len, __func__); + for (int i = 0; i < rdata->edge_len; i++) { + eap[i].count = 0; + eap[i].face_index[0] = -1; + eap[i].face_index[1] = -1; + } + if (do_pnors) { + pnors = rdata->poly_normals = MEM_mallocN(sizeof(*pnors) * poly_len, __func__); + } + + for (int i = 0; i < poly_len; i++, mpoly++) { + if (do_pnors) { + BKE_mesh_calc_poly_normal(mpoly, mloop + mpoly->loopstart, mvert, pnors[i]); + } + + const int loopend = mpoly->loopstart + mpoly->totloop; + for (int j = mpoly->loopstart; j < loopend; j++) { + const int edge_idx = mloop[j].e; + if (eap[edge_idx].count < 2) { + eap[edge_idx].face_index[eap[edge_idx].count] = i; + } + eap[edge_idx].count++; + } + } + } + BLI_assert(eap && (rdata->poly_len == 0 || pnors != NULL)); + + *r_vco1 = mvert[medge[edge_index].v1].co; + *r_vco2 = mvert[medge[edge_index].v2].co; + if (eap[edge_index].face_index[0] == -1) { + /* Edge has no poly... */ + *r_pnor1 = *r_pnor2 = mvert[medge[edge_index].v1].co; /* XXX mvert.no are shorts... :( */ + *r_is_manifold = false; + } + else { + *r_pnor1 = pnors[eap[edge_index].face_index[0]]; + + float nor[3], v1[3], v2[3], r_center[3]; + const MPoly *mpoly = rdata->mpoly + eap[edge_index].face_index[0]; + const MLoop *mloop = rdata->mloop + mpoly->loopstart; + + BKE_mesh_calc_poly_center(mpoly, mloop, mvert, r_center); + sub_v3_v3v3(v1, *r_vco2, *r_vco1); + sub_v3_v3v3(v2, r_center, *r_vco1); + cross_v3_v3v3(nor, v1, v2); + + if (dot_v3v3(nor, *r_pnor1) < 0.0) { + SWAP(float *, *r_vco1, *r_vco2); + } + + if (eap[edge_index].count == 2) { + BLI_assert(eap[edge_index].face_index[1] >= 0); + *r_pnor2 = pnors[eap[edge_index].face_index[1]]; + *r_is_manifold = true; + } + else { + *r_pnor2 = pnors[eap[edge_index].face_index[0]]; + *r_is_manifold = false; + } + } + } + + return true; +} + + +/* First 2 bytes are bit flags + * 3rd is for sharp edges + * 4rd is for creased edges */ +enum { + VFLAG_VERTEX_ACTIVE = 1 << 0, + VFLAG_VERTEX_SELECTED = 1 << 1, + VFLAG_FACE_ACTIVE = 1 << 2, + VFLAG_FACE_SELECTED = 1 << 3, +}; + +enum { + VFLAG_EDGE_EXISTS = 1 << 0, + VFLAG_EDGE_ACTIVE = 1 << 1, + VFLAG_EDGE_SELECTED = 1 << 2, + VFLAG_EDGE_SEAM = 1 << 3, + VFLAG_EDGE_SHARP = 1 << 4, + /* Beware to not go over 1 << 7 + * (see gpu_shader_edit_mesh_overlay_geom.glsl) */ +}; + +static unsigned char mesh_render_data_looptri_flag(MeshRenderData *rdata, const BMFace *efa) +{ + unsigned char fflag = 0; + + if (efa == rdata->efa_act) + fflag |= VFLAG_FACE_ACTIVE; + + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) + fflag |= VFLAG_FACE_SELECTED; + + return fflag; +} + +static void mesh_render_data_edge_flag( + const MeshRenderData *rdata, const BMEdge *eed, + EdgeDrawAttr *eattr) +{ + eattr->e_flag |= VFLAG_EDGE_EXISTS; + + if (eed == rdata->eed_act) + eattr->e_flag |= VFLAG_EDGE_ACTIVE; + + if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) + eattr->e_flag |= VFLAG_EDGE_SELECTED; + + if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) + eattr->e_flag |= VFLAG_EDGE_SEAM; + + if (!BM_elem_flag_test(eed, BM_ELEM_SMOOTH)) + eattr->e_flag |= VFLAG_EDGE_SHARP; + + /* Use a byte for value range */ + if (rdata->cd.offset.crease != -1) { + float crease = BM_ELEM_CD_GET_FLOAT(eed, rdata->cd.offset.crease); + if (crease > 0) { + eattr->crease = (char)(crease * 255.0f); + } + } + + /* Use a byte for value range */ + if (rdata->cd.offset.bweight != -1) { + float bweight = BM_ELEM_CD_GET_FLOAT(eed, rdata->cd.offset.bweight); + if (bweight > 0) { + eattr->bweight = (char)(bweight * 255.0f); + } + } +} + +static unsigned char mesh_render_data_vertex_flag(MeshRenderData *rdata, const BMVert *eve) +{ + + unsigned char vflag = 0; + + /* Current vertex */ + if (eve == rdata->eve_act) + vflag |= VFLAG_VERTEX_ACTIVE; + + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) + vflag |= VFLAG_VERTEX_SELECTED; + + return vflag; +} + +static void add_overlay_tri( + MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data, + const uint pos_id, const uint vnor_id, const uint lnor_id, const uint data_id, + const BMLoop **bm_looptri, const int base_vert_idx) +{ + unsigned char fflag; + unsigned char vflag; + + if (vbo_pos) { + /* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */ + if (rdata->edit_data && rdata->edit_data->vertexCos) { + for (uint i = 0; i < 3; i++) { + int vidx = BM_elem_index_get(bm_looptri[i]->v); + const float *pos = rdata->edit_data->vertexCos[vidx]; + GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos); + } + } + else { + for (uint i = 0; i < 3; i++) { + const float *pos = bm_looptri[i]->v->co; + GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos); + } + } + } + + if (vbo_nor) { + /* TODO real loop normal */ + Gwn_PackedNormal lnor = GWN_normal_convert_i10_v3(bm_looptri[0]->f->no); + for (uint i = 0; i < 3; i++) { + Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3(bm_looptri[i]->v->no); + GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor); + GWN_vertbuf_attr_set(vbo_nor, lnor_id, base_vert_idx + i, &lnor); + } + } + + if (vbo_data) { + fflag = mesh_render_data_looptri_flag(rdata, bm_looptri[0]->f); + uint i_prev = 1, i = 2; + for (uint i_next = 0; i_next < 3; i_next++) { + vflag = mesh_render_data_vertex_flag(rdata, bm_looptri[i]->v); + EdgeDrawAttr eattr = {0}; + if (bm_looptri[i_next] == bm_looptri[i_prev]->prev) { + mesh_render_data_edge_flag(rdata, bm_looptri[i_next]->e, &eattr); + } + eattr.v_flag = fflag | vflag; + GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr); + + i_prev = i; + i = i_next; + } + } +} + +static void add_overlay_loose_edge( + MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data, + const uint pos_id, const uint vnor_id, const uint data_id, + const BMEdge *eed, const int base_vert_idx) +{ + if (vbo_pos) { + /* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */ + if (rdata->edit_data && rdata->edit_data->vertexCos) { + for (uint i = 0; i < 2; i++) { + int vidx = BM_elem_index_get((&eed->v1)[i]); + const float *pos = rdata->edit_data->vertexCos[vidx]; + GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos); + } + } + else { + for (int i = 0; i < 2; ++i) { + const float *pos = (&eed->v1)[i]->co; + GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos); + } + } + } + + if (vbo_nor) { + for (int i = 0; i < 2; ++i) { + Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3((&eed->v1)[i]->no); + GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor); + } + } + + if (vbo_data) { + EdgeDrawAttr eattr = {0}; + mesh_render_data_edge_flag(rdata, eed, &eattr); + for (int i = 0; i < 2; ++i) { + eattr.v_flag = mesh_render_data_vertex_flag(rdata, (&eed->v1)[i]); + GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr); + } + } +} + +static void add_overlay_loose_vert( + MeshRenderData *rdata, Gwn_VertBuf *vbo_pos, Gwn_VertBuf *vbo_nor, Gwn_VertBuf *vbo_data, + const uint pos_id, const uint vnor_id, const uint data_id, + const BMVert *eve, const int base_vert_idx) +{ + if (vbo_pos) { + /* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */ + if (rdata->edit_data && rdata->edit_data->vertexCos) { + int vidx = BM_elem_index_get(eve); + const float *pos = rdata->edit_data->vertexCos[vidx]; + GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos); + } + else { + const float *pos = eve->co; + GWN_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx, pos); + } + } + + if (vbo_nor) { + Gwn_PackedNormal vnor = GWN_normal_convert_i10_v3(eve->no); + GWN_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx, &vnor); + } + + if (vbo_data) { + unsigned char vflag[4] = {0, 0, 0, 0}; + vflag[0] = mesh_render_data_vertex_flag(rdata, eve); + GWN_vertbuf_attr_set(vbo_data, data_id, base_vert_idx, vflag); + } +} + +/** \} */ + + +/* ---------------------------------------------------------------------- */ + +/** \name Mesh Gwn_Batch Cache + * \{ */ + +typedef struct MeshBatchCache { + Gwn_VertBuf *pos_in_order; + Gwn_VertBuf *nor_in_order; + Gwn_IndexBuf *edges_in_order; + Gwn_IndexBuf *edges_adjacency; /* Store edges with adjacent vertices. */ + Gwn_IndexBuf *triangles_in_order; + + Gwn_Batch *all_verts; + Gwn_Batch *all_edges; + Gwn_Batch *all_triangles; + + Gwn_VertBuf *pos_with_normals; + Gwn_VertBuf *tri_aligned_uv; /* Active UV layer (mloopuv) */ + + /** + * Other uses are all positions or loose elements. + * This stores all visible elements, needed for selection. + */ + Gwn_VertBuf *ed_fcenter_pos_with_nor_and_sel; + Gwn_VertBuf *ed_edge_pos; + Gwn_VertBuf *ed_vert_pos; + + Gwn_Batch *triangles_with_normals; + + /* Skip hidden (depending on paint select mode) */ + Gwn_Batch *triangles_with_weights; + Gwn_Batch *triangles_with_vert_colors; + /* Always skip hidden */ + Gwn_Batch *triangles_with_select_mask; + Gwn_Batch *triangles_with_select_id; + uint triangles_with_select_id_offset; + + Gwn_Batch *facedot_with_select_id; /* shares vbo with 'overlay_facedots' */ + Gwn_Batch *edges_with_select_id; + Gwn_Batch *verts_with_select_id; + + uint facedot_with_select_id_offset; + uint edges_with_select_id_offset; + uint verts_with_select_id_offset; + + Gwn_Batch *points_with_normals; + Gwn_Batch *fancy_edges; /* owns its vertex buffer (not shared) */ + + Gwn_Batch *edge_detection; + + /* Maybe have shaded_triangles_data split into pos_nor and uv_tangent + * to minimise data transfer for skinned mesh. */ + Gwn_VertFormat shaded_triangles_format; + Gwn_VertBuf *shaded_triangles_data; + Gwn_IndexBuf **shaded_triangles_in_order; + Gwn_Batch **shaded_triangles; + + /* Texture Paint.*/ + /* per-texture batch */ + Gwn_Batch **texpaint_triangles; + Gwn_Batch *texpaint_triangles_single; + + /* Edit Cage Mesh buffers */ + Gwn_VertBuf *ed_tri_pos; + Gwn_VertBuf *ed_tri_nor; /* LoopNor, VertNor */ + Gwn_VertBuf *ed_tri_data; + + Gwn_VertBuf *ed_ledge_pos; + Gwn_VertBuf *ed_ledge_nor; /* VertNor */ + Gwn_VertBuf *ed_ledge_data; + + Gwn_VertBuf *ed_lvert_pos; + Gwn_VertBuf *ed_lvert_nor; /* VertNor */ + Gwn_VertBuf *ed_lvert_data; + + Gwn_Batch *overlay_triangles; + Gwn_Batch *overlay_triangles_nor; /* GWN_PRIM_POINTS */ + Gwn_Batch *overlay_loose_edges; + Gwn_Batch *overlay_loose_edges_nor; /* GWN_PRIM_POINTS */ + Gwn_Batch *overlay_loose_verts; + Gwn_Batch *overlay_facedots; + + Gwn_Batch *overlay_weight_faces; + Gwn_Batch *overlay_weight_verts; + Gwn_Batch *overlay_paint_edges; + + /* arrays of bool uniform names (and value) that will be use to + * set srgb conversion for auto attribs.*/ + char *auto_layer_names; + int *auto_layer_is_srgb; + int auto_layer_ct; + + /* settings to determine if cache is invalid */ + bool is_maybe_dirty; + bool is_dirty; /* Instantly invalidates cache, skipping mesh check */ + int edge_len; + int tri_len; + int poly_len; + int vert_len; + int mat_len; + bool is_editmode; + + /* XXX, only keep for as long as sculpt mode uses shaded drawing. */ + bool is_sculpt_points_tag; + + /* Valid only if edges_adjacency is up to date. */ + bool is_manifold; +} MeshBatchCache; + +/* Gwn_Batch cache management. */ + +static bool mesh_batch_cache_valid(Mesh *me) +{ + MeshBatchCache *cache = me->runtime.batch_cache; + + if (cache == NULL) { + return false; + } + + /* XXX find another place for this */ + if (cache->mat_len != mesh_render_mat_len_get(me)) { + cache->is_maybe_dirty = true; + } + + if (cache->is_editmode != (me->edit_btmesh != NULL)) { + return false; + } + + if (cache->is_dirty) { + return false; + } + + if (cache->is_maybe_dirty == false) { + return true; + } + else { + if (cache->is_editmode) { + return false; + } + else if ((cache->vert_len != mesh_render_verts_len_get(me)) || + (cache->edge_len != mesh_render_edges_len_get(me)) || + (cache->tri_len != mesh_render_looptri_len_get(me)) || + (cache->poly_len != mesh_render_polys_len_get(me)) || + (cache->mat_len != mesh_render_mat_len_get(me))) + { + return false; + } + } + + return true; +} + +static void mesh_batch_cache_init(Mesh *me) +{ + MeshBatchCache *cache = me->runtime.batch_cache; + + if (!cache) { + cache = me->runtime.batch_cache = MEM_callocN(sizeof(*cache), __func__); + } + else { + memset(cache, 0, sizeof(*cache)); + } + + cache->is_editmode = me->edit_btmesh != NULL; + + if (cache->is_editmode == false) { + cache->edge_len = mesh_render_edges_len_get(me); + cache->tri_len = mesh_render_looptri_len_get(me); + cache->poly_len = mesh_render_polys_len_get(me); + cache->vert_len = mesh_render_verts_len_get(me); + } + + cache->mat_len = mesh_render_mat_len_get(me); + + cache->is_maybe_dirty = false; + cache->is_dirty = false; +} + +static MeshBatchCache *mesh_batch_cache_get(Mesh *me) +{ + if (!mesh_batch_cache_valid(me)) { + mesh_batch_cache_clear(me); + mesh_batch_cache_init(me); + } + return me->runtime.batch_cache; +} + +void DRW_mesh_batch_cache_dirty(Mesh *me, int mode) +{ + MeshBatchCache *cache = me->runtime.batch_cache; + if (cache == NULL) { + return; + } + switch (mode) { + case BKE_MESH_BATCH_DIRTY_MAYBE_ALL: + cache->is_maybe_dirty = true; + break; + case BKE_MESH_BATCH_DIRTY_SELECT: + GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_data); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); /* Contains select flag */ + GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos); + + GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles); + GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts); + GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges); + GWN_BATCH_DISCARD_SAFE(cache->overlay_facedots); + /* Edit mode selection. */ + GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id); + break; + case BKE_MESH_BATCH_DIRTY_ALL: + cache->is_dirty = true; + break; + case BKE_MESH_BATCH_DIRTY_SHADING: + /* TODO: This should only update UV and tangent data, + * and not free the entire cache. */ + cache->is_dirty = true; + break; + case BKE_MESH_BATCH_DIRTY_SCULPT_COORDS: + cache->is_sculpt_points_tag = true; + break; + default: + BLI_assert(0); + } +} + +/** + * This only clear the batches associated to the given vertex buffer. + **/ +static void mesh_batch_cache_clear_selective(Mesh *me, Gwn_VertBuf *vert) +{ + MeshBatchCache *cache = me->runtime.batch_cache; + if (!cache) { + return; + } + + BLI_assert(vert != NULL); + + if (cache->pos_with_normals == vert) { + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_normals); + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_weights); + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors); + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask); + GWN_BATCH_DISCARD_SAFE(cache->points_with_normals); + if (cache->shaded_triangles) { + for (int i = 0; i < cache->mat_len; ++i) { + GWN_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]); + } + } + MEM_SAFE_FREE(cache->shaded_triangles); + if (cache->texpaint_triangles) { + for (int i = 0; i < cache->mat_len; ++i) { + GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]); + } + } + MEM_SAFE_FREE(cache->texpaint_triangles); + GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single); + } + /* TODO: add the other ones if needed. */ + else { + /* Does not match any vertbuf in the batch cache! */ + BLI_assert(0); + } +} + +static void mesh_batch_cache_clear(Mesh *me) +{ + MeshBatchCache *cache = me->runtime.batch_cache; + if (!cache) { + return; + } + + GWN_BATCH_DISCARD_SAFE(cache->all_verts); + GWN_BATCH_DISCARD_SAFE(cache->all_edges); + GWN_BATCH_DISCARD_SAFE(cache->all_triangles); + + GWN_VERTBUF_DISCARD_SAFE(cache->pos_in_order); + GWN_INDEXBUF_DISCARD_SAFE(cache->edges_in_order); + GWN_INDEXBUF_DISCARD_SAFE(cache->triangles_in_order); + + GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_pos); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_nor); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_data); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_pos); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_nor); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_pos); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_nor); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data); + GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles); + GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor); + GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts); + GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges); + GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges_nor); + + GWN_BATCH_DISCARD_SAFE(cache->overlay_weight_faces); + GWN_BATCH_DISCARD_SAFE(cache->overlay_weight_verts); + GWN_BATCH_DISCARD_SAFE(cache->overlay_paint_edges); + GWN_BATCH_DISCARD_SAFE(cache->overlay_facedots); + + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_normals); + GWN_BATCH_DISCARD_SAFE(cache->points_with_normals); + GWN_VERTBUF_DISCARD_SAFE(cache->pos_with_normals); + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_weights); + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors); + GWN_VERTBUF_DISCARD_SAFE(cache->tri_aligned_uv); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos); + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask); + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id); + + GWN_BATCH_DISCARD_SAFE(cache->fancy_edges); + + GWN_INDEXBUF_DISCARD_SAFE(cache->edges_adjacency); + GWN_BATCH_DISCARD_SAFE(cache->edge_detection); + + GWN_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data); + if (cache->shaded_triangles_in_order) { + for (int i = 0; i < cache->mat_len; ++i) { + GWN_INDEXBUF_DISCARD_SAFE(cache->shaded_triangles_in_order[i]); + } + } + if (cache->shaded_triangles) { + for (int i = 0; i < cache->mat_len; ++i) { + GWN_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]); + } + } + + MEM_SAFE_FREE(cache->shaded_triangles_in_order); + MEM_SAFE_FREE(cache->shaded_triangles); + + MEM_SAFE_FREE(cache->auto_layer_names); + MEM_SAFE_FREE(cache->auto_layer_is_srgb); + + if (cache->texpaint_triangles) { + for (int i = 0; i < cache->mat_len; ++i) { + GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]); + } + } + MEM_SAFE_FREE(cache->texpaint_triangles); + + GWN_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single); + +} + +void DRW_mesh_batch_cache_free(Mesh *me) +{ + mesh_batch_cache_clear(me); + MEM_SAFE_FREE(me->runtime.batch_cache); +} + +/* Gwn_Batch cache usage. */ + +static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); +#define USE_COMP_MESH_DATA + + if (cache->shaded_triangles_data == NULL) { + const uint uv_len = rdata->cd.layers.uv_len; + const uint tangent_len = rdata->cd.layers.tangent_len; + const uint vcol_len = rdata->cd.layers.vcol_len; + const uint layers_combined_len = uv_len + vcol_len + tangent_len; + + if (layers_combined_len == 0) { + return NULL; + } + + Gwn_VertFormat *format = &cache->shaded_triangles_format; + + GWN_vertformat_clear(format); + + /* initialize vertex format */ + uint *layers_combined_id = BLI_array_alloca(layers_combined_id, layers_combined_len); + uint *uv_id = layers_combined_id; + uint *tangent_id = uv_id + uv_len; + uint *vcol_id = tangent_id + tangent_len; + + /* Not needed, just for sanity. */ + if (uv_len == 0) { uv_id = NULL; } + if (tangent_len == 0) { tangent_id = NULL; } + if (vcol_len == 0) { vcol_id = NULL; } + + /* Count number of auto layer and allocate big enough name buffer. */ + uint auto_names_len = 0; + uint auto_ofs = 0; + uint auto_id = 0; + cache->auto_layer_ct = 0; + for (uint i = 0; i < uv_len; i++) { + const char *attrib_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i); + auto_names_len += strlen(attrib_name) + 2; /* include null terminator and b prefix. */ + cache->auto_layer_ct++; + } + for (uint i = 0; i < vcol_len; i++) { + if (rdata->cd.layers.auto_vcol[i]) { + const char *attrib_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i); + auto_names_len += strlen(attrib_name) + 2; /* include null terminator and b prefix. */ + cache->auto_layer_ct++; + } + } + auto_names_len += 1; /* add an ultimate '\0' terminator */ + cache->auto_layer_names = MEM_callocN(auto_names_len * sizeof(char), "Auto layer name buf"); + cache->auto_layer_is_srgb = MEM_mallocN(cache->auto_layer_ct * sizeof(int), "Auto layer value buf"); + + for (uint i = 0; i < uv_len; i++) { + /* UV */ + const char *attrib_name = mesh_render_data_uv_layer_uuid_get(rdata, i); +#if defined(USE_COMP_MESH_DATA) && 0 /* these are clamped. Maybe use them as an option in the future */ + uv_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_I16, 2, GWN_FETCH_INT_TO_FLOAT_UNIT); +#else + uv_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_F32, 2, GWN_FETCH_FLOAT); +#endif + + /* Auto Name */ + attrib_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i); + GWN_vertformat_alias_add(format, attrib_name); + + /* +1 include null terminator. */ + auto_ofs += 1 + BLI_snprintf_rlen( + cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); + cache->auto_layer_is_srgb[auto_id++] = 0; /* tag as not srgb */ + + if (i == rdata->cd.layers.uv_active) { + GWN_vertformat_alias_add(format, "u"); + } + } + + for (uint i = 0; i < tangent_len; i++) { + const char *attrib_name = mesh_render_data_tangent_layer_uuid_get(rdata, i); + /* WATCH IT : only specifying 3 component instead of 4 (4th is sign). + * That may cause some problem but I could not make it to fail (fclem) */ +#ifdef USE_COMP_MESH_DATA + /* Tangents need more precision than 10_10_10 */ + tangent_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); +#else + tangent_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_F32, 3, GWN_FETCH_FLOAT); +#endif + + if (i == rdata->cd.layers.tangent_active) { + GWN_vertformat_alias_add(format, "t"); + } + } + + for (uint i = 0; i < vcol_len; i++) { + const char *attrib_name = mesh_render_data_vcol_layer_uuid_get(rdata, i); + vcol_id[i] = GWN_vertformat_attr_add(format, attrib_name, GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + /* Auto layer */ + if (rdata->cd.layers.auto_vcol[i]) { + attrib_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i); + + GWN_vertformat_alias_add(format, attrib_name); + + /* +1 include null terminator. */ + auto_ofs += 1 + BLI_snprintf_rlen( + cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); + cache->auto_layer_is_srgb[auto_id++] = 1; /* tag as srgb */ + } + + if (i == rdata->cd.layers.vcol_active) { + GWN_vertformat_alias_add(format, "c"); + } + } + + const uint tri_len = mesh_render_data_looptri_len_get(rdata); + + Gwn_VertBuf *vbo = cache->shaded_triangles_data = GWN_vertbuf_create_with_format(format); + + const int vbo_len_capacity = tri_len * 3; + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + Gwn_VertBufRaw *layers_combined_step = BLI_array_alloca(layers_combined_step, layers_combined_len); + + Gwn_VertBufRaw *uv_step = layers_combined_step; + Gwn_VertBufRaw *tangent_step = uv_step + uv_len; + Gwn_VertBufRaw *vcol_step = tangent_step + tangent_len; + + /* Not needed, just for sanity. */ + if (uv_len == 0) { uv_step = NULL; } + if (tangent_len == 0) { tangent_step = NULL; } + if (vcol_len == 0) { vcol_step = NULL; } + + for (uint i = 0; i < uv_len; i++) { + GWN_vertbuf_attr_get_raw_data(vbo, uv_id[i], &uv_step[i]); + } + for (uint i = 0; i < tangent_len; i++) { + GWN_vertbuf_attr_get_raw_data(vbo, tangent_id[i], &tangent_step[i]); + } + for (uint i = 0; i < vcol_len; i++) { + GWN_vertbuf_attr_get_raw_data(vbo, vcol_id[i], &vcol_step[i]); + } + + /* TODO deduplicate all verts and make use of Gwn_IndexBuf in + * mesh_batch_cache_get_triangles_in_order_split_by_material. */ + if (rdata->edit_bmesh) { + for (uint i = 0; i < tri_len; i++) { + const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { + continue; + } + /* UVs */ + for (uint j = 0; j < uv_len; j++) { + const uint layer_offset = rdata->cd.offset.uv[j]; + for (uint t = 0; t < 3; t++) { + const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->uv; + copy_v2_v2(GWN_vertbuf_raw_step(&uv_step[j]), elem); + } + } + /* TANGENTs */ + for (uint j = 0; j < tangent_len; j++) { + float (*layer_data)[4] = rdata->cd.layers.tangent[j]; + for (uint t = 0; t < 3; t++) { + const float *elem = layer_data[BM_elem_index_get(bm_looptri[t])]; + normal_float_to_short_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem); + } + } + /* VCOLs */ + for (uint j = 0; j < vcol_len; j++) { + const uint layer_offset = rdata->cd.offset.vcol[j]; + for (uint t = 0; t < 3; t++) { + const uchar *elem = &((MLoopCol *)BM_ELEM_CD_GET_VOID_P(bm_looptri[t], layer_offset))->r; + copy_v3_v3_uchar(GWN_vertbuf_raw_step(&vcol_step[j]), elem); + } + } + } + } + else { + for (uint i = 0; i < tri_len; i++) { + const MLoopTri *mlt = &rdata->mlooptri[i]; + + /* UVs */ + for (uint j = 0; j < uv_len; j++) { + const MLoopUV *layer_data = rdata->cd.layers.uv[j]; + for (uint t = 0; t < 3; t++) { + const float *elem = layer_data[mlt->tri[t]].uv; + copy_v2_v2(GWN_vertbuf_raw_step(&uv_step[j]), elem); + } + } + /* TANGENTs */ + for (uint j = 0; j < tangent_len; j++) { + float (*layer_data)[4] = rdata->cd.layers.tangent[j]; + for (uint t = 0; t < 3; t++) { + const float *elem = layer_data[mlt->tri[t]]; +#ifdef USE_COMP_MESH_DATA + normal_float_to_short_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem); +#else + copy_v3_v3(GWN_vertbuf_raw_step(&tangent_step[j]), elem); +#endif + } + } + /* VCOLs */ + for (uint j = 0; j < vcol_len; j++) { + const MLoopCol *layer_data = rdata->cd.layers.vcol[j]; + for (uint t = 0; t < 3; t++) { + const uchar *elem = &layer_data[mlt->tri[t]].r; + copy_v3_v3_uchar(GWN_vertbuf_raw_step(&vcol_step[j]), elem); + } + } + } + } + + vbo_len_used = GWN_vertbuf_raw_used(&layers_combined_step[0]); + +#ifndef NDEBUG + /* Check all layers are write aligned. */ + if (layers_combined_len > 1) { + for (uint i = 1; i < layers_combined_len; i++) { + BLI_assert(vbo_len_used == GWN_vertbuf_raw_used(&layers_combined_step[i])); + } + } +#endif + + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + +#undef USE_COMP_MESH_DATA + + return cache->shaded_triangles_data; +} + +static Gwn_VertBuf *mesh_batch_cache_get_tri_uv_active( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPUV)); + + if (cache->tri_aligned_uv == NULL) { + uint vidx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint uv; } attr_id; + if (format.attrib_ct == 0) { + attr_id.uv = GWN_vertformat_attr_add(&format, "uv", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } + + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + Gwn_VertBuf *vbo = cache->tri_aligned_uv = GWN_vertbuf_create_with_format(&format); + + const int vbo_len_capacity = tri_len * 3; + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + const MLoopUV *mloopuv = rdata->mloopuv; + + BMEditMesh *embm = rdata->edit_bmesh; + /* get uv's from active UVMap */ + if (rdata->edit_bmesh) { + /* edit mode */ + BMesh *bm = embm->bm; + + const int layer_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + for (uint i = 0; i < tri_len; i++) { + const BMLoop **bm_looptri = (const BMLoop **)embm->looptris[i]; + if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { + continue; + } + for (uint t = 0; t < 3; t++) { + const BMLoop *loop = bm_looptri[t]; + const int index = BM_elem_index_get(loop); + if (index != -1) { + const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(loop, layer_offset))->uv; + GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, elem); + } + } + } + } + else { + /* object mode */ + for (int i = 0; i < tri_len; i++) { + const MLoopTri *mlt = &rdata->mlooptri[i]; + GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[0]].uv); + GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[1]].uv); + GWN_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[2]].uv); + } + } + + vbo_len_used = vidx; + + BLI_assert(vbo_len_capacity == vbo_len_used); + UNUSED_VARS_NDEBUG(vbo_len_used); + } + + return cache->tri_aligned_uv; +} + +static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex( + MeshRenderData *rdata, const bool use_hide, + Gwn_VertBuf **r_vbo) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + if (*r_vbo == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, nor; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + } + + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + Gwn_VertBuf *vbo = *r_vbo = GWN_vertbuf_create_with_format(&format); + + const int vbo_len_capacity = tri_len * 3; + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + Gwn_VertBufRaw pos_step, nor_step; + GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); + GWN_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step); + + float (*lnors)[3] = rdata->loop_normals; + + if (rdata->edit_bmesh) { + Gwn_PackedNormal *pnors_pack, *vnors_pack; + + if (lnors == NULL) { + mesh_render_data_ensure_poly_normals_pack(rdata); + mesh_render_data_ensure_vert_normals_pack(rdata); + + pnors_pack = rdata->poly_normals_pack; + vnors_pack = rdata->vert_normals_pack; + } + + for (int i = 0; i < tri_len; i++) { + const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + const BMFace *bm_face = bm_looptri[0]->f; + + /* use_hide always for edit-mode */ + if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) { + continue; + } + + if (lnors) { + for (uint t = 0; t < 3; t++) { + const float *nor = lnors[BM_elem_index_get(bm_looptri[t])]; + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor); + } + } + else if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) { + for (uint t = 0; t < 3; t++) { + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = vnors_pack[BM_elem_index_get(bm_looptri[t]->v)]; + } + } + else { + const Gwn_PackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)]; + for (uint t = 0; t < 3; t++) { + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *snor_pack; + } + } + + /* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */ + if (rdata->edit_data && rdata->edit_data->vertexCos) { + for (uint t = 0; t < 3; t++) { + int vidx = BM_elem_index_get(bm_looptri[t]->v); + const float *pos = rdata->edit_data->vertexCos[vidx]; + copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), pos); + } + } + else { + for (uint t = 0; t < 3; t++) { + copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co); + } + } + } + } + else { + if (lnors == NULL) { + /* Use normals from vertex. */ + mesh_render_data_ensure_poly_normals_pack(rdata); + } + + for (int i = 0; i < tri_len; i++) { + const MLoopTri *mlt = &rdata->mlooptri[i]; + const MPoly *mp = &rdata->mpoly[mlt->poly]; + + if (use_hide && (mp->flag & ME_HIDE)) { + continue; + } + + const uint vtri[3] = { + rdata->mloop[mlt->tri[0]].v, + rdata->mloop[mlt->tri[1]].v, + rdata->mloop[mlt->tri[2]].v, + }; + + if (lnors) { + for (uint t = 0; t < 3; t++) { + const float *nor = lnors[mlt->tri[t]]; + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor); + } + } + else if (mp->flag & ME_SMOOTH) { + for (uint t = 0; t < 3; t++) { + const MVert *mv = &rdata->mvert[vtri[t]]; + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_s3(mv->no); + } + } + else { + const Gwn_PackedNormal *pnors_pack = &rdata->poly_normals_pack[mlt->poly]; + for (uint t = 0; t < 3; t++) { + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *pnors_pack; + } + } + + for (uint t = 0; t < 3; t++) { + const MVert *mv = &rdata->mvert[vtri[t]]; + copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), mv->co); + } + } + } + + vbo_len_used = GWN_vertbuf_raw_used(&pos_step); + BLI_assert(vbo_len_used == GWN_vertbuf_raw_used(&nor_step)); + + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + return *r_vbo; +} + +static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + return mesh_batch_cache_get_tri_pos_and_normals_ex( + rdata, false, + &cache->pos_with_normals); +} +static Gwn_VertBuf *mesh_create_tri_pos_and_normals_visible_only( + MeshRenderData *rdata) +{ + Gwn_VertBuf *vbo_dummy = NULL; + return mesh_batch_cache_get_tri_pos_and_normals_ex( + rdata, true, + &vbo_dummy); +} + +static Gwn_VertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + if (cache->ed_fcenter_pos_with_nor_and_sel == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, data; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.data = GWN_vertformat_attr_add(&format, "norAndFlag", GWN_COMP_I10, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + } + + const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata); + int vidx = 0; + + Gwn_VertBuf *vbo = cache->ed_fcenter_pos_with_nor_and_sel = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + for (int i = 0; i < vbo_len_capacity; ++i) { + float pcenter[3], pnor[3]; + bool selected = false; + + if (mesh_render_data_pnors_pcenter_select_get(rdata, i, pnor, pcenter, &selected)) { + + Gwn_PackedNormal nor = { .x = 0, .y = 0, .z = -511 }; + nor = GWN_normal_convert_i10_v3(pnor); + nor.w = selected ? 1 : 0; + GWN_vertbuf_attr_set(vbo, attr_id.data, vidx, &nor); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, pcenter); + + vidx += 1; + } + } + const int vbo_len_used = vidx; + BLI_assert(vbo_len_used <= vbo_len_capacity); + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return cache->ed_fcenter_pos_with_nor_and_sel; +} + +static Gwn_VertBuf *mesh_batch_cache_get_edges_visible( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE)); + + if (cache->ed_edge_pos == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, data; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2; + int vidx = 0; + + Gwn_VertBuf *vbo = cache->ed_edge_pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMEdge *eed; + + BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v1->co); + vidx += 1; + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v2->co); + vidx += 1; + } + } + } + else { + /* not yet done! */ + BLI_assert(0); + } + const int vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + UNUSED_VARS_NDEBUG(vbo_len_used); + } + + return cache->ed_edge_pos; +} + +static Gwn_VertBuf *mesh_batch_cache_get_verts_visible( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_vert_pos == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, data; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata); + uint vidx = 0; + + Gwn_VertBuf *vbo = cache->ed_vert_pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMVert *eve; + + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eve->co); + vidx += 1; + } + } + } + else { + for (int i = 0; i < vbo_len_capacity; i++) { + const MVert *mv = &rdata->mvert[i]; + if (!(mv->flag & ME_HIDE)) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, mv->co); + vidx += 1; + } + } + } + const uint vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + + UNUSED_VARS_NDEBUG(vbo_len_used); + } + + return cache->ed_vert_pos; +} + +static Gwn_VertBuf *mesh_create_facedot_select_id( + MeshRenderData *rdata, uint select_id_offset) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + Gwn_VertBuf *vbo; + { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata); + int vidx = 0; + + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + uint select_index = select_id_offset; + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMEdge *efa; + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + int select_id; + GPU_select_index_get(select_index, &select_id); + GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); + vidx += 1; + } + select_index += 1; + } + } + else { + /* not yet done! */ + BLI_assert(0); + } + const int vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return vbo; +} + +static Gwn_VertBuf *mesh_create_edges_select_id( + MeshRenderData *rdata, uint select_id_offset) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE)); + + Gwn_VertBuf *vbo; + { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2; + int vidx = 0; + + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + uint select_index = select_id_offset; + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMEdge *eed; + + BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + int select_id; + GPU_select_index_get(select_index, &select_id); + GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); + vidx += 1; + GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); + vidx += 1; + } + select_index += 1; + } + } + else { + /* not yet done! */ + BLI_assert(0); + } + const int vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return vbo; +} + +static Gwn_VertBuf *mesh_create_verts_select_id( + MeshRenderData *rdata, uint select_id_offset) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + Gwn_VertBuf *vbo; + { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata); + int vidx = 0; + + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + uint select_index = select_id_offset; + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMVert *eve; + + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + int select_id; + GPU_select_index_get(select_index, &select_id); + GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); + vidx += 1; + } + select_index += 1; + } + } + else { + for (int i = 0; i < vbo_len_capacity; i++) { + const MVert *mv = &rdata->mvert[i]; + if (!(mv->flag & ME_HIDE)) { + int select_id; + GPU_select_index_get(select_index, &select_id); + GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); + vidx += 1; + } + select_index += 1; + } + } + const int vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return vbo; +} + +static Gwn_VertBuf *mesh_create_tri_weights( + MeshRenderData *rdata, bool use_hide, int defgroup) +{ + BLI_assert( + rdata->types & + (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT)); + + Gwn_VertBuf *vbo; + { + uint cidx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + vbo = GWN_vertbuf_create_with_format(&format); + + const int tri_len = mesh_render_data_looptri_len_get(rdata); + const int vbo_len_capacity = tri_len * 3; + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + mesh_render_data_ensure_vert_weight_color(rdata, defgroup); + const float (*vert_weight_color)[3] = rdata->vert_weight_color; + + if (rdata->edit_bmesh) { + for (int i = 0; i < tri_len; i++) { + const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + /* Assume 'use_hide' */ + if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) { + for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { + const int v_index = BM_elem_index_get(ltri[tri_corner]->v); + GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]); + } + } + } + } + else { + for (int i = 0; i < tri_len; i++) { + const MLoopTri *mlt = &rdata->mlooptri[i]; + if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) { + for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { + const uint v_index = rdata->mloop[mlt->tri[tri_corner]].v; + GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_weight_color[v_index]); + } + } + } + } + vbo_len_used = cidx; + + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return vbo; +} + +static Gwn_VertBuf *mesh_create_tri_vert_colors( + MeshRenderData *rdata, bool use_hide) +{ + BLI_assert( + rdata->types & + (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL)); + + Gwn_VertBuf *vbo; + { + uint cidx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + } + + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + vbo = GWN_vertbuf_create_with_format(&format); + + const uint vbo_len_capacity = tri_len * 3; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + mesh_render_data_ensure_vert_color(rdata); + const char (*vert_color)[3] = rdata->vert_color; + + if (rdata->edit_bmesh) { + for (int i = 0; i < tri_len; i++) { + const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + /* Assume 'use_hide' */ + if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) { + for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { + const int l_index = BM_elem_index_get(ltri[tri_corner]); + GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]); + } + } + } + } + else { + for (int i = 0; i < tri_len; i++) { + const MLoopTri *mlt = &rdata->mlooptri[i]; + if (!(use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE))) { + for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { + const uint l_index = mlt->tri[tri_corner]; + GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, vert_color[l_index]); + } + } + } + } + const uint vbo_len_used = cidx; + + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return vbo; +} + +static Gwn_VertBuf *mesh_create_tri_select_id( + MeshRenderData *rdata, bool use_hide, uint select_id_offset) +{ + BLI_assert( + rdata->types & + (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + Gwn_VertBuf *vbo; + { + uint cidx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + vbo = GWN_vertbuf_create_with_format(&format); + + const int vbo_len_capacity = tri_len * 3; + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + if (rdata->edit_bmesh) { + for (int i = 0; i < tri_len; i++) { + const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + /* Assume 'use_hide' */ + if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) { + const int poly_index = BM_elem_index_get(ltri[0]->f); + int select_id; + GPU_select_index_get(poly_index + select_id_offset, &select_id); + for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { + GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id); + } + } + } + } + else { + for (int i = 0; i < tri_len; i++) { + const MLoopTri *mlt = &rdata->mlooptri[i]; + const int poly_index = mlt->poly; + if (!(use_hide && (rdata->mpoly[poly_index].flag & ME_HIDE))) { + int select_id; + GPU_select_index_get(poly_index + select_id_offset, &select_id); + for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { + GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id); + } + } + } + } + vbo_len_used = cidx; + + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + return vbo; +} + +static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->pos_in_order == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, nor; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + } + + Gwn_VertBuf *vbo = cache->pos_in_order = GWN_vertbuf_create_with_format(&format); + const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMVert *eve; + uint i; + + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + static short no_short[3]; + normal_float_to_short_v3(no_short, eve->no); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co); + GWN_vertbuf_attr_set(vbo, attr_id.nor, i, no_short); + } + BLI_assert(i == vbo_len_capacity); + } + else { + for (int i = 0; i < vbo_len_capacity; ++i) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co); + GWN_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no); + } + } + } + + return cache->pos_in_order; +} + +static Gwn_VertFormat *edit_mesh_overlay_pos_format(uint *r_pos_id) +{ + static Gwn_VertFormat format_pos = { 0 }; + static unsigned pos_id; + if (format_pos.attrib_ct == 0) { + pos_id = GWN_vertformat_attr_add(&format_pos, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + *r_pos_id = pos_id; + return &format_pos; +} + +static Gwn_VertFormat *edit_mesh_overlay_nor_format(uint *r_vnor_id, uint *r_lnor_id) +{ + static Gwn_VertFormat format_nor = { 0 }; + static Gwn_VertFormat format_nor_loop = { 0 }; + static unsigned vnor_id, vnor_loop_id, lnor_id; + if (format_nor.attrib_ct == 0) { + vnor_id = GWN_vertformat_attr_add(&format_nor, "vnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + vnor_loop_id = GWN_vertformat_attr_add(&format_nor_loop, "vnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + lnor_id = GWN_vertformat_attr_add(&format_nor_loop, "lnor", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + } + if (r_lnor_id) { + *r_vnor_id = vnor_loop_id; + *r_lnor_id = lnor_id; + return &format_nor_loop; + } + else { + *r_vnor_id = vnor_id; + return &format_nor; + } +} + +static Gwn_VertFormat *edit_mesh_overlay_data_format(uint *r_data_id) +{ + static Gwn_VertFormat format_flag = { 0 }; + static unsigned data_id; + if (format_flag.attrib_ct == 0) { + data_id = GWN_vertformat_attr_add(&format_flag, "data", GWN_COMP_U8, 4, GWN_FETCH_INT); + } + *r_data_id = data_id; + return &format_flag; +} + +static void mesh_batch_cache_create_overlay_tri_buffers( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI)); + + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + const int vbo_len_capacity = tri_len * 3; + int vbo_len_used = 0; + + /* Positions */ + Gwn_VertBuf *vbo_pos = NULL; + static struct { uint pos, vnor, lnor, data; } attr_id; + if (cache->ed_tri_pos == NULL) { + vbo_pos = cache->ed_tri_pos = + GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos)); + GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity); + } + + /* Normals */ + Gwn_VertBuf *vbo_nor = NULL; + if (cache->ed_tri_nor == NULL) { + vbo_nor = cache->ed_tri_nor = + GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, &attr_id.lnor)); + GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity); + } + + /* Data */ + Gwn_VertBuf *vbo_data = NULL; + if (cache->ed_tri_data == NULL) { + vbo_data = cache->ed_tri_data = + GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data)); + GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity); + } + + for (int i = 0; i < tri_len; i++) { + const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + if (!BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { + add_overlay_tri( + rdata, vbo_pos, vbo_nor, vbo_data, + attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data, + bm_looptri, vbo_len_used); + + vbo_len_used += 3; + } + } + + /* Finish */ + if (vbo_len_used != vbo_len_capacity) { + if (vbo_pos != NULL) { + GWN_vertbuf_data_resize(vbo_pos, vbo_len_used); + } + if (vbo_nor != NULL) { + GWN_vertbuf_data_resize(vbo_nor, vbo_len_used); + } + if (vbo_data != NULL) { + GWN_vertbuf_data_resize(vbo_data, vbo_len_used); + } + } +} + +static void mesh_batch_cache_create_overlay_ledge_buffers( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI)); + + const int ledge_len = mesh_render_data_loose_edges_len_get(rdata); + + const int vbo_len_capacity = ledge_len * 2; + int vbo_len_used = 0; + + /* Positions */ + Gwn_VertBuf *vbo_pos = NULL; + static struct { uint pos, vnor, data; } attr_id; + if (cache->ed_ledge_pos == NULL) { + vbo_pos = cache->ed_ledge_pos = + GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos)); + GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity); + } + + /* Normals */ + Gwn_VertBuf *vbo_nor = NULL; + if (cache->ed_ledge_nor == NULL) { + vbo_nor = cache->ed_ledge_nor = + GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL)); + GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity); + } + + /* Data */ + Gwn_VertBuf *vbo_data = NULL; + if (cache->ed_ledge_data == NULL) { + vbo_data = cache->ed_ledge_data = + GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data)); + GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity); + } + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + for (uint i = 0; i < ledge_len; i++) { + const BMEdge *eed = BM_edge_at_index(bm, rdata->loose_edges[i]); + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + add_overlay_loose_edge( + rdata, vbo_pos, vbo_nor, vbo_data, + attr_id.pos, attr_id.vnor, attr_id.data, + eed, vbo_len_used); + vbo_len_used += 2; + } + } + } + + /* Finish */ + if (vbo_len_used != vbo_len_capacity) { + if (vbo_pos != NULL) { + GWN_vertbuf_data_resize(vbo_pos, vbo_len_used); + } + if (vbo_nor != NULL) { + GWN_vertbuf_data_resize(vbo_nor, vbo_len_used); + } + if (vbo_data != NULL) { + GWN_vertbuf_data_resize(vbo_data, vbo_len_used); + } + } +} + +static void mesh_batch_cache_create_overlay_lvert_buffers( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI)); + + BMesh *bm = rdata->edit_bmesh->bm; + const int lvert_len = mesh_render_data_loose_verts_len_get(rdata); + + const int vbo_len_capacity = lvert_len; + int vbo_len_used = 0; + + static struct { uint pos, vnor, data; } attr_id; + + /* Positions */ + Gwn_VertBuf *vbo_pos = NULL; + if (cache->ed_lvert_pos == NULL) { + vbo_pos = cache->ed_lvert_pos = + GWN_vertbuf_create_with_format(edit_mesh_overlay_pos_format(&attr_id.pos)); + GWN_vertbuf_data_alloc(vbo_pos, vbo_len_capacity); + } + + /* Normals */ + Gwn_VertBuf *vbo_nor = NULL; + if (cache->ed_lvert_nor == NULL) { + vbo_nor = cache->ed_lvert_nor = + GWN_vertbuf_create_with_format(edit_mesh_overlay_nor_format(&attr_id.vnor, NULL)); + GWN_vertbuf_data_alloc(vbo_nor, vbo_len_capacity); + } + + /* Data */ + Gwn_VertBuf *vbo_data = NULL; + if (cache->ed_lvert_data == NULL) { + vbo_data = cache->ed_lvert_data = + GWN_vertbuf_create_with_format(edit_mesh_overlay_data_format(&attr_id.data)); + GWN_vertbuf_data_alloc(vbo_data, vbo_len_capacity); + } + + for (uint i = 0; i < lvert_len; i++) { + BMVert *eve = BM_vert_at_index(bm, rdata->loose_verts[i]); + add_overlay_loose_vert( + rdata, vbo_pos, vbo_nor, vbo_data, + attr_id.pos, attr_id.vnor, attr_id.data, + eve, vbo_len_used); + vbo_len_used += 1; + } + + /* Finish */ + if (vbo_len_used != vbo_len_capacity) { + if (vbo_pos != NULL) { + GWN_vertbuf_data_resize(vbo_pos, vbo_len_used); + } + if (vbo_nor != NULL) { + GWN_vertbuf_data_resize(vbo_nor, vbo_len_used); + } + if (vbo_data != NULL) { + GWN_vertbuf_data_resize(vbo_data, vbo_len_used); + } + } +} + +/* Position */ +static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_pos( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_tri_pos == NULL) { + mesh_batch_cache_create_overlay_tri_buffers(rdata, cache); + } + + return cache->ed_tri_pos; +} + +static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_pos( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_ledge_pos == NULL) { + mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache); + } + + return cache->ed_ledge_pos; +} + +static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_pos( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_lvert_pos == NULL) { + mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache); + } + + return cache->ed_lvert_pos; +} + +/* Normal */ +static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_nor( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_tri_nor == NULL) { + mesh_batch_cache_create_overlay_tri_buffers(rdata, cache); + } + + return cache->ed_tri_nor; +} + +static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_nor( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_ledge_nor == NULL) { + mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache); + } + + return cache->ed_ledge_nor; +} + +static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_nor( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_lvert_nor == NULL) { + mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache); + } + + return cache->ed_lvert_nor; +} + +/* Data */ +static Gwn_VertBuf *mesh_batch_cache_get_edit_tri_data( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_tri_data == NULL) { + mesh_batch_cache_create_overlay_tri_buffers(rdata, cache); + } + + return cache->ed_tri_data; +} + +static Gwn_VertBuf *mesh_batch_cache_get_edit_ledge_data( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_ledge_data == NULL) { + mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache); + } + + return cache->ed_ledge_data; +} + +static Gwn_VertBuf *mesh_batch_cache_get_edit_lvert_data( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_lvert_data == NULL) { + mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache); + } + + return cache->ed_lvert_data; +} + +static Gwn_IndexBuf *mesh_batch_cache_get_edges_in_order(MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE)); + + if (cache->edges_in_order == NULL) { + const int vert_len = mesh_render_data_verts_len_get(rdata); + const int edge_len = mesh_render_data_edges_len_get(rdata); + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES, edge_len, vert_len); + + BLI_assert(rdata->types & MR_DATATYPE_EDGE); + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter eiter; + BMEdge *eed; + BM_ITER_MESH(eed, &eiter, bm, BM_EDGES_OF_MESH) { + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + GWN_indexbuf_add_line_verts(&elb, BM_elem_index_get(eed->v1), BM_elem_index_get(eed->v2)); + } + } + } + else { + const MEdge *ed = rdata->medge; + for (int i = 0; i < edge_len; i++, ed++) { + GWN_indexbuf_add_line_verts(&elb, ed->v1, ed->v2); + } + } + cache->edges_in_order = GWN_indexbuf_build(&elb); + } + + return cache->edges_in_order; +} + +#define NO_EDGE INT_MAX +static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI)); + + if (cache->edges_adjacency == NULL) { + const int vert_len = mesh_render_data_verts_len_get(rdata); + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + cache->is_manifold = true; + + /* Allocate max but only used indices are sent to GPU. */ + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, tri_len * 3, vert_len); + + EdgeHash *eh = BLI_edgehash_new_ex(__func__, tri_len * 3); + /* Create edges for each pair of triangles sharing an edge. */ + for (int i = 0; i < tri_len; i++) { + for (int e = 0; e < 3; ++e) { + uint v0, v1, v2; + if (rdata->edit_bmesh) { + const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { + break; + } + v0 = BM_elem_index_get(bm_looptri[e]->v); + v1 = BM_elem_index_get(bm_looptri[(e + 1) % 3]->v); + v2 = BM_elem_index_get(bm_looptri[(e + 2) % 3]->v); + } + else { + MLoop *mloop = rdata->mloop; + MLoopTri *mlt = rdata->mlooptri + i; + v0 = mloop[mlt->tri[e]].v; + v1 = mloop[mlt->tri[(e + 1) % 3]].v; + v2 = mloop[mlt->tri[(e + 2) % 3]].v; + } + bool inv_indices = (v1 > v2); + void **pval; + bool value_is_init = BLI_edgehash_ensure_p(eh, v1, v2, &pval); + int v_data = GET_INT_FROM_POINTER(*pval); + if (!value_is_init || v_data == NO_EDGE) { + /* Save the winding order inside the sign bit. Because the + * edgehash sort the keys and we need to compare winding later. */ + int value = (int)v0 + 1; /* Int 0 cannot be signed */ + *pval = SET_INT_IN_POINTER((inv_indices) ? -value : value); + } + else { + /* HACK Tag as not used. Prevent overhead of BLI_edgehash_remove. */ + *pval = SET_INT_IN_POINTER(NO_EDGE); + bool inv_opposite = (v_data < 0); + uint v_opposite = (uint)abs(v_data) - 1; + + if (inv_opposite == inv_indices) { + /* Don't share edge if triangles have non matching winding. */ + GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0); + GWN_indexbuf_add_line_adj_verts(&elb, v_opposite, v1, v2, v_opposite); + cache->is_manifold = false; + } + else { + GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v_opposite); + } + } + } + } + /* Create edges for remaning non manifold edges. */ + EdgeHashIterator *ehi; + for (ehi = BLI_edgehashIterator_new(eh); + BLI_edgehashIterator_isDone(ehi) == false; + BLI_edgehashIterator_step(ehi)) + { + uint v1, v2; + int v_data = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); + if (v_data == NO_EDGE) { + continue; + } + BLI_edgehashIterator_getKey(ehi, &v1, &v2); + uint v0 = (uint)abs(v_data) - 1; + if (v_data < 0) { /* inv_opposite */ + SWAP(uint, v1, v2); + } + GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0); + cache->is_manifold = false; + } + BLI_edgehashIterator_free(ehi); + BLI_edgehash_free(eh, NULL); + + cache->edges_adjacency = GWN_indexbuf_build(&elb); + } + + return cache->edges_adjacency; + +} +#undef NO_EDGE + +static Gwn_IndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI)); + + if (cache->triangles_in_order == NULL) { + const int vert_len = mesh_render_data_verts_len_get(rdata); + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len); + + if (rdata->edit_bmesh) { + for (int i = 0; i < tri_len; ++i) { + const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) { + for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { + GWN_indexbuf_add_generic_vert(&elb, BM_elem_index_get(ltri[tri_corner]->v)); + } + } + } + } + else { + for (int i = 0; i < tri_len; ++i) { + const MLoopTri *mlt = &rdata->mlooptri[i]; + for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { + GWN_indexbuf_add_generic_vert(&elb, mlt->tri[tri_corner]); + } + } + } + cache->triangles_in_order = GWN_indexbuf_build(&elb); + } + + return cache->triangles_in_order; +} + +static Gwn_IndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_POLY)); + + if (cache->shaded_triangles_in_order == NULL) { + const int poly_len = mesh_render_data_polys_len_get(rdata); + const int tri_len = mesh_render_data_looptri_len_get(rdata); + const int mat_len = mesh_render_data_mat_len_get(rdata); + + int *mat_tri_len = MEM_callocN(sizeof(*mat_tri_len) * mat_len, __func__); + cache->shaded_triangles_in_order = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__); + Gwn_IndexBufBuilder *elb = MEM_callocN(sizeof(*elb) * mat_len, __func__); + + /* Note that polygons (not triangles) are used here. + * This OK because result is _guaranteed_ to be the same. */ + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter fiter; + BMFace *efa; + + BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0; + mat_tri_len[ma_id] += (efa->len - 2); + } + } + } + else { + for (uint i = 0; i < poly_len; i++) { + const MPoly *mp = &rdata->mpoly[i]; ; + const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0; + mat_tri_len[ma_id] += (mp->totloop - 2); + } + } + + /* Init ELBs. */ + for (int i = 0; i < mat_len; ++i) { + GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, mat_tri_len[i], tri_len * 3); + } + + /* Populate ELBs. */ + uint nidx = 0; + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter fiter; + BMFace *efa; + + BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0; + for (int j = 2; j < efa->len; j++) { + GWN_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2); + nidx += 3; + } + } + } + } + else { + for (uint i = 0; i < poly_len; i++) { + const MPoly *mp = &rdata->mpoly[i]; ; + const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0; + for (int j = 2; j < mp->totloop; j++) { + GWN_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2); + nidx += 3; + } + } + } + + /* Build ELBs. */ + for (int i = 0; i < mat_len; ++i) { + cache->shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]); + } + + MEM_freeN(mat_tri_len); + MEM_freeN(elb); + } + + return cache->shaded_triangles_in_order; +} + +static Gwn_VertBuf *mesh_create_edge_pos_with_sel( + MeshRenderData *rdata, bool use_wire, bool use_select_bool) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP)); + BLI_assert(rdata->edit_bmesh == NULL); + + Gwn_VertBuf *vbo; + { + uint vidx = 0, cidx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, sel; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.sel = GWN_vertformat_attr_add(&format, "select", GWN_COMP_U8, 1, GWN_FETCH_INT); + } + + const int edge_len = mesh_render_data_edges_len_get(rdata); + + vbo = GWN_vertbuf_create_with_format(&format); + + const int vbo_len_capacity = edge_len * 2; + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + if (use_select_bool) { + mesh_render_data_ensure_edge_select_bool(rdata, use_wire); + } + bool *edge_select_bool = use_select_bool ? rdata->edge_select_bool : NULL; + + for (int i = 0; i < edge_len; i++) { + const MEdge *ed = &rdata->medge[i]; + + uchar edge_vert_sel; + if (use_select_bool && edge_select_bool[i]) { + edge_vert_sel = true; + } + else if (use_wire) { + edge_vert_sel = false; + } + else { + continue; + } + + GWN_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel); + GWN_vertbuf_attr_set(vbo, attr_id.sel, cidx++, &edge_vert_sel); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v1].co); + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, rdata->mvert[ed->v2].co); + } + vbo_len_used = vidx; + + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return vbo; +} + +static Gwn_IndexBuf *mesh_create_tri_overlay_weight_faces( + MeshRenderData *rdata) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI)); + + { + const int vert_len = mesh_render_data_verts_len_get(rdata); + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len); + + for (int i = 0; i < tri_len; ++i) { + const MLoopTri *mlt = &rdata->mlooptri[i]; + if (!(rdata->mpoly[mlt->poly].flag & (ME_FACE_SEL | ME_HIDE))) { + for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { + GWN_indexbuf_add_generic_vert(&elb, rdata->mloop[mlt->tri[tri_corner]].v); + } + } + } + return GWN_indexbuf_build(&elb); + } +} + +/** + * Non-edit mode vertices (only used for weight-paint mode). + */ +static Gwn_VertBuf *mesh_create_vert_pos_with_overlay_data( + MeshRenderData *rdata) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT)); + BLI_assert(rdata->edit_bmesh == NULL); + + Gwn_VertBuf *vbo; + { + uint cidx = 0; + + static Gwn_VertFormat format = { 0 }; + static struct { uint data; } attr_id; + if (format.attrib_ct == 0) { + attr_id.data = GWN_vertformat_attr_add(&format, "data", GWN_COMP_I8, 1, GWN_FETCH_INT); + } + + const int vert_len = mesh_render_data_verts_len_get(rdata); + + vbo = GWN_vertbuf_create_with_format(&format); + + const int vbo_len_capacity = vert_len; + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + for (int i = 0; i < vert_len; i++) { + const MVert *mv = &rdata->mvert[i]; + const char data = mv->flag & (SELECT | ME_HIDE); + GWN_vertbuf_attr_set(vbo, attr_id.data, cidx++, &data); + } + vbo_len_used = cidx; + + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + return vbo; +} + +/** \} */ + + +/* ---------------------------------------------------------------------- */ + +/** \name Public API + * \{ */ + +Gwn_Batch *DRW_mesh_batch_cache_get_all_edges(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->all_edges == NULL) { + /* create batch from Mesh */ + const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + cache->all_edges = GWN_batch_create( + GWN_PRIM_LINES, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), + mesh_batch_cache_get_edges_in_order(rdata, cache)); + + mesh_render_data_free(rdata); + } + + return cache->all_edges; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->all_triangles == NULL) { + /* create batch from DM */ + const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + cache->all_triangles = GWN_batch_create( + GWN_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), + mesh_batch_cache_get_triangles_in_order(rdata, cache)); + + mesh_render_data_free(rdata); + } + + return cache->all_triangles; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->triangles_with_normals == NULL) { + const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + cache->triangles_with_normals = GWN_batch_create( + GWN_PRIM_TRIS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL); + + mesh_render_data_free(rdata); + } + + return cache->triangles_with_normals; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(Mesh *me, int defgroup) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->triangles_with_weights == NULL) { + const bool use_hide = (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) != 0; + const int datatype = + MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_DVERT; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + cache->triangles_with_weights = GWN_batch_create_ex( + GWN_PRIM_TRIS, mesh_create_tri_weights(rdata, use_hide, defgroup), NULL, GWN_BATCH_OWNS_VBO); + + Gwn_VertBuf *vbo_tris = use_hide ? + mesh_create_tri_pos_and_normals_visible_only(rdata) : + mesh_batch_cache_get_tri_pos_and_normals(rdata, cache); + + GWN_batch_vertbuf_add_ex(cache->triangles_with_weights, vbo_tris, use_hide); + + mesh_render_data_free(rdata); + } + + return cache->triangles_with_weights; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->triangles_with_vert_colors == NULL) { + const bool use_hide = (me->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) != 0; + const int datatype = + MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPCOL; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + cache->triangles_with_vert_colors = GWN_batch_create_ex( + GWN_PRIM_TRIS, mesh_create_tri_vert_colors(rdata, use_hide), NULL, GWN_BATCH_OWNS_VBO); + + Gwn_VertBuf *vbo_tris = use_hide ? + mesh_create_tri_pos_and_normals_visible_only(rdata) : + mesh_batch_cache_get_tri_pos_and_normals(rdata, cache); + GWN_batch_vertbuf_add_ex(cache->triangles_with_vert_colors, vbo_tris, use_hide); + + mesh_render_data_free(rdata); + } + + return cache->triangles_with_vert_colors; +} + + +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id( + struct Mesh *me, bool use_hide, uint select_id_offset) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->triangles_with_select_id_offset != select_id_offset) { + cache->triangles_with_select_id_offset = select_id_offset; + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id); + } + + if (cache->triangles_with_select_id == NULL) { + const int datatype = + MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + cache->triangles_with_select_id = GWN_batch_create_ex( + GWN_PRIM_TRIS, mesh_create_tri_select_id(rdata, use_hide, select_id_offset), NULL, GWN_BATCH_OWNS_VBO); + + Gwn_VertBuf *vbo_tris = use_hide ? + mesh_create_tri_pos_and_normals_visible_only(rdata) : + mesh_batch_cache_get_tri_pos_and_normals(rdata, cache); + GWN_batch_vertbuf_add_ex(cache->triangles_with_select_id, vbo_tris, use_hide); + + mesh_render_data_free(rdata); + } + + return cache->triangles_with_select_id; +} + +/** + * Same as #DRW_mesh_batch_cache_get_triangles_with_select_id + * without the ID's, use to mask out geometry, eg - dont select face-dots behind other faces. + */ +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + if (cache->triangles_with_select_mask == NULL) { + const int datatype = + MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + Gwn_VertBuf *vbo_tris = use_hide ? + mesh_create_tri_pos_and_normals_visible_only(rdata) : + mesh_batch_cache_get_tri_pos_and_normals(rdata, cache); + + cache->triangles_with_select_mask = GWN_batch_create_ex( + GWN_PRIM_TRIS, vbo_tris, NULL, use_hide ? GWN_BATCH_OWNS_VBO : 0); + + mesh_render_data_free(rdata); + } + + return cache->triangles_with_select_mask; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->points_with_normals == NULL) { + const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + cache->points_with_normals = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_tri_pos_and_normals(rdata, cache), NULL); + + mesh_render_data_free(rdata); + } + + return cache->points_with_normals; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->all_verts == NULL) { + /* create batch from DM */ + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT); + + cache->all_verts = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL); + + mesh_render_data_free(rdata); + } + + return cache->all_verts; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->fancy_edges == NULL) { + /* create batch from DM */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, n1, n2; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + attr_id.n1 = GWN_vertformat_attr_add(&format, "N1", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + attr_id.n2 = GWN_vertformat_attr_add(&format, "N2", GWN_COMP_I10, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + } + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + + MeshRenderData *rdata = mesh_render_data_create( + me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY); + + const int edge_len = mesh_render_data_edges_len_get(rdata); + + const int vbo_len_capacity = edge_len * 2; /* these are PRIM_LINE verts, not mesh verts */ + int vbo_len_used = 0; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + for (int i = 0; i < edge_len; ++i) { + float *vcos1, *vcos2; + float *pnor1 = NULL, *pnor2 = NULL; + bool is_manifold; + + if (mesh_render_data_edge_vcos_manifold_pnors(rdata, i, &vcos1, &vcos2, &pnor1, &pnor2, &is_manifold)) { + + Gwn_PackedNormal n1value = { .x = 0, .y = 0, .z = +511 }; + Gwn_PackedNormal n2value = { .x = 0, .y = 0, .z = -511 }; + + if (is_manifold) { + n1value = GWN_normal_convert_i10_v3(pnor1); + n2value = GWN_normal_convert_i10_v3(pnor2); + } + + const Gwn_PackedNormal *n1 = &n1value; + const Gwn_PackedNormal *n2 = &n2value; + + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * i, vcos1); + GWN_vertbuf_attr_set(vbo, attr_id.n1, 2 * i, n1); + GWN_vertbuf_attr_set(vbo, attr_id.n2, 2 * i, n2); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * i + 1, vcos2); + GWN_vertbuf_attr_set(vbo, attr_id.n1, 2 * i + 1, n1); + GWN_vertbuf_attr_set(vbo, attr_id.n2, 2 * i + 1, n2); + + vbo_len_used += 2; + } + } + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + + cache->fancy_edges = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + + mesh_render_data_free(rdata); + } + + return cache->fancy_edges; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->edge_detection == NULL) { + const int options = MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI; + + MeshRenderData *rdata = mesh_render_data_create(me, options); + + cache->edge_detection = GWN_batch_create_ex( + GWN_PRIM_LINES_ADJ, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), + mesh_batch_cache_get_edges_adjacency(rdata, cache), 0); + + mesh_render_data_free(rdata); + } + + if (r_is_manifold) { + *r_is_manifold = cache->is_manifold; + } + + return cache->edge_detection; +} + +static void mesh_batch_cache_create_overlay_batches(Mesh *me) +{ + BLI_assert(me->edit_btmesh != NULL); + + /* Since MR_DATATYPE_OVERLAY is slow to generate, generate them all at once */ + const int options = + MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | + MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY; + + MeshBatchCache *cache = mesh_batch_cache_get(me); + MeshRenderData *rdata = mesh_render_data_create(me, options); + + if (cache->overlay_triangles == NULL) { + cache->overlay_triangles = GWN_batch_create( + GWN_PRIM_TRIS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL); + GWN_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_nor(rdata, cache)); + GWN_batch_vertbuf_add(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_data(rdata, cache)); + } + + if (cache->overlay_loose_edges == NULL) { + cache->overlay_loose_edges = GWN_batch_create( + GWN_PRIM_LINES, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL); + GWN_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_nor(rdata, cache)); + GWN_batch_vertbuf_add(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_data(rdata, cache)); + } + + if (cache->overlay_loose_verts == NULL) { + cache->overlay_loose_verts = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_edit_lvert_pos(rdata, cache), NULL); + GWN_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_nor(rdata, cache)); + GWN_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_data(rdata, cache)); + } + + if (cache->overlay_triangles_nor == NULL) { + cache->overlay_triangles_nor = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL); + GWN_batch_vertbuf_add(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_nor(rdata, cache)); + } + + if (cache->overlay_loose_edges_nor == NULL) { + cache->overlay_loose_edges_nor = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL); + GWN_batch_vertbuf_add(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_nor(rdata, cache)); + } + + mesh_render_data_free(rdata); +} + +Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_triangles == NULL) { + mesh_batch_cache_create_overlay_batches(me); + } + + return cache->overlay_triangles; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_loose_edges == NULL) { + mesh_batch_cache_create_overlay_batches(me); + } + + return cache->overlay_loose_edges; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_loose_verts == NULL) { + mesh_batch_cache_create_overlay_batches(me); + } + + return cache->overlay_loose_verts; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_triangles_nor == NULL) { + mesh_batch_cache_create_overlay_batches(me); + } + + return cache->overlay_triangles_nor; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_loose_edges_nor == NULL) { + mesh_batch_cache_create_overlay_batches(me); + } + + return cache->overlay_loose_edges_nor; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_facedots == NULL) { + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY); + + cache->overlay_facedots = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL); + + mesh_render_data_free(rdata); + } + + return cache->overlay_facedots; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint select_id_offset) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->facedot_with_select_id_offset != select_id_offset) { + cache->facedot_with_select_id_offset = select_id_offset; + GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id); + } + + if (cache->facedot_with_select_id == NULL) { + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY); + + /* We only want the 'pos', not the normals or flag. + * Use since this is almost certainly already created. */ + cache->facedot_with_select_id = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL); + + GWN_batch_vertbuf_add_ex( + cache->facedot_with_select_id, + mesh_create_facedot_select_id(rdata, select_id_offset), true); + + mesh_render_data_free(rdata); + } + + return cache->facedot_with_select_id; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me, uint select_id_offset) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->edges_with_select_id_offset != select_id_offset) { + cache->edges_with_select_id_offset = select_id_offset; + GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id); + } + + if (cache->edges_with_select_id == NULL) { + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE); + + cache->edges_with_select_id = GWN_batch_create( + GWN_PRIM_LINES, mesh_batch_cache_get_edges_visible(rdata, cache), NULL); + + GWN_batch_vertbuf_add_ex( + cache->edges_with_select_id, + mesh_create_edges_select_id(rdata, select_id_offset), true); + + mesh_render_data_free(rdata); + } + + return cache->edges_with_select_id; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me, uint select_id_offset) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->verts_with_select_id_offset != select_id_offset) { + cache->verts_with_select_id_offset = select_id_offset; + GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id); + } + + if (cache->verts_with_select_id == NULL) { + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT); + + cache->verts_with_select_id = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_verts_visible(rdata, cache), NULL); + + GWN_batch_vertbuf_add_ex( + cache->verts_with_select_id, + mesh_create_verts_select_id(rdata, select_id_offset), true); + + mesh_render_data_free(rdata); + } + + return cache->verts_with_select_id; +} + +Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded( + Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len, + char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->shaded_triangles == NULL) { + /* create batch from DM */ + const int datatype = + MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI | + MR_DATATYPE_POLY | MR_DATATYPE_SHADING; + MeshRenderData *rdata = mesh_render_data_create_ex(me, datatype, gpumat_array, gpumat_array_len); + + const int mat_len = mesh_render_data_mat_len_get(rdata); + + cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__); + + Gwn_IndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache); + + Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache); + Gwn_VertBuf *vbo_shading = mesh_batch_cache_get_tri_shading_data(rdata, cache); + + for (int i = 0; i < mat_len; ++i) { + cache->shaded_triangles[i] = GWN_batch_create( + GWN_PRIM_TRIS, vbo, el[i]); + if (vbo_shading) { + GWN_batch_vertbuf_add(cache->shaded_triangles[i], vbo_shading); + } + } + + mesh_render_data_free(rdata); + } + + if (auto_layer_names) { + *auto_layer_names = cache->auto_layer_names; + *auto_layer_is_srgb = cache->auto_layer_is_srgb; + *auto_layer_count = cache->auto_layer_ct; + } + + return cache->shaded_triangles; +} + +Gwn_Batch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->texpaint_triangles == NULL) { + /* create batch from DM */ + const int datatype = + MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + const int mat_len = mesh_render_data_mat_len_get(rdata); + + cache->texpaint_triangles = MEM_callocN(sizeof(*cache->texpaint_triangles) * mat_len, __func__); + + Gwn_IndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache); + + Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache); + for (int i = 0; i < mat_len; ++i) { + cache->texpaint_triangles[i] = GWN_batch_create( + GWN_PRIM_TRIS, vbo, el[i]); + Gwn_VertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache); + if (vbo_uv) { + GWN_batch_vertbuf_add(cache->texpaint_triangles[i], vbo_uv); + } + } + mesh_render_data_free(rdata); + } + + return cache->texpaint_triangles; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->texpaint_triangles_single == NULL) { + /* create batch from DM */ + const int datatype = + MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + Gwn_VertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache); + + cache->texpaint_triangles_single = GWN_batch_create( + GWN_PRIM_TRIS, vbo, NULL); + Gwn_VertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache); + if (vbo_uv) { + GWN_batch_vertbuf_add(cache->texpaint_triangles_single, vbo_uv); + } + mesh_render_data_free(rdata); + } + return cache->texpaint_triangles_single; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire, bool use_sel) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_paint_edges == NULL) { + /* create batch from Mesh */ + const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + cache->overlay_paint_edges = GWN_batch_create_ex( + GWN_PRIM_LINES, mesh_create_edge_pos_with_sel(rdata, use_wire, use_sel), NULL, GWN_BATCH_OWNS_VBO); + + mesh_render_data_free(rdata); + } + + return cache->overlay_paint_edges; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_weight_faces == NULL) { + /* create batch from Mesh */ + const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + cache->overlay_weight_faces = GWN_batch_create_ex( + GWN_PRIM_TRIS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), + mesh_create_tri_overlay_weight_faces(rdata), GWN_BATCH_OWNS_INDEX); + + mesh_render_data_free(rdata); + } + + return cache->overlay_weight_faces; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_weight_overlay_verts(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_weight_verts == NULL) { + /* create batch from Mesh */ + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT); + + cache->overlay_weight_verts = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), NULL); + + GWN_batch_vertbuf_add_ex( + cache->overlay_weight_verts, + mesh_create_vert_pos_with_overlay_data(rdata), true); + mesh_render_data_free(rdata); + } + + return cache->overlay_weight_verts; +} + +/** + * Needed for when we draw with shaded data. + */ +void DRW_mesh_cache_sculpt_coords_ensure(Mesh *me) +{ + if (me->runtime.batch_cache) { + MeshBatchCache *cache = mesh_batch_cache_get(me); + if (cache && cache->pos_with_normals && cache->is_sculpt_points_tag) { + /* XXX Force update of all the batches that contains the pos_with_normals buffer. + * TODO(fclem): Ideally, Gawain should provide a way to update a buffer without destroying it. */ + mesh_batch_cache_clear_selective(me, cache->pos_with_normals); + GWN_VERTBUF_DISCARD_SAFE(cache->pos_with_normals); + } + cache->is_sculpt_points_tag = false; + } +} + +/** \} */ + +#undef MESH_RENDER_FUNCTION diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c new file mode 100644 index 00000000000..f01e7b929f8 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_metaball.c @@ -0,0 +1,144 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file draw_cache_impl_metaball.c + * \ingroup draw + * + * \brief MetaBall API for render engines + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" + +#include "DNA_meta_types.h" +#include "DNA_object_types.h" + +#include "BKE_curve.h" +#include "BKE_mball.h" + +#include "GPU_batch.h" + +#include "draw_cache_impl.h" /* own include */ + + +static void metaball_batch_cache_clear(MetaBall *mb); + +/* ---------------------------------------------------------------------- */ +/* MetaBall Gwn_Batch Cache */ + +typedef struct MetaBallBatchCache { + Gwn_Batch *batch; + + /* settings to determine if cache is invalid */ + bool is_dirty; +} MetaBallBatchCache; + +/* Gwn_Batch cache management. */ + +static bool metaball_batch_cache_valid(MetaBall *mb) +{ + MetaBallBatchCache *cache = mb->batch_cache; + + if (cache == NULL) { + return false; + } + + return cache->is_dirty == false; +} + +static void metaball_batch_cache_init(MetaBall *mb) +{ + MetaBallBatchCache *cache = mb->batch_cache; + + if (!cache) { + cache = mb->batch_cache = MEM_mallocN(sizeof(*cache), __func__); + } + cache->batch = NULL; + cache->is_dirty = false; +} + +static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb) +{ + if (!metaball_batch_cache_valid(mb)) { + metaball_batch_cache_clear(mb); + metaball_batch_cache_init(mb); + } + return mb->batch_cache; +} + +void DRW_mball_batch_cache_dirty(MetaBall *mb, int mode) +{ + MetaBallBatchCache *cache = mb->batch_cache; + if (cache == NULL) { + return; + } + switch (mode) { + case BKE_MBALL_BATCH_DIRTY_ALL: + cache->is_dirty = true; + break; + default: + BLI_assert(0); + } +} + +static void metaball_batch_cache_clear(MetaBall *mb) +{ + MetaBallBatchCache *cache = mb->batch_cache; + if (!cache) { + return; + } + + GWN_BATCH_DISCARD_SAFE(cache->batch); +} + +void DRW_mball_batch_cache_free(MetaBall *mb) +{ + metaball_batch_cache_clear(mb); + MEM_SAFE_FREE(mb->batch_cache); +} + +/* -------------------------------------------------------------------- */ + +/** \name Public Object/MetaBall API + * \{ */ + +Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob) +{ + if (!BKE_mball_is_basis(ob)) + return NULL; + + MetaBall *mb = ob->data; + MetaBallBatchCache *cache = metaball_batch_cache_get(mb); + + if (cache->batch == NULL) { + ListBase *lb = &ob->curve_cache->disp; + cache->batch = GWN_batch_create_ex( + GWN_PRIM_TRIS, + DRW_displist_vertbuf_calc_pos_with_normals(lb), + DRW_displist_indexbuf_calc_triangles_in_order(lb), + GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); + } + + return cache->batch; +} diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c new file mode 100644 index 00000000000..1348968bad7 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -0,0 +1,1556 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file draw_cache_impl_particles.c + * \ingroup draw + * + * \brief Particle API for render engines + */ + +#include "DRW_render.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math_vector.h" +#include "BLI_string.h" +#include "BLI_ghash.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_particle_types.h" +#include "DNA_customdata_types.h" + +#include "BKE_mesh.h" +#include "BKE_particle.h" +#include "BKE_pointcache.h" + +#include "ED_particle.h" + +#include "GPU_batch.h" + +#include "DEG_depsgraph_query.h" + +#include "draw_cache_impl.h" /* own include */ +#include "draw_hair_private.h" + +static void particle_batch_cache_clear(ParticleSystem *psys); + +/* ---------------------------------------------------------------------- */ +/* Particle Gwn_Batch Cache */ + +typedef struct ParticlePointCache { + Gwn_VertBuf *pos; + Gwn_Batch *points; + int elems_count; + int point_count; +} ParticlePointCache; + +typedef struct ParticleBatchCache { + /* Object mode strands for hair and points for particle, + * strands for paths when in edit mode. + */ + ParticleHairCache hair; /* Used for hair strands */ + ParticlePointCache point; /* Used for particle points. */ + + /* Control points when in edit mode. */ + ParticleHairCache edit_hair; + + Gwn_VertBuf *edit_inner_pos; + Gwn_Batch *edit_inner_points; + int edit_inner_point_count; + + Gwn_VertBuf *edit_tip_pos; + Gwn_Batch *edit_tip_points; + int edit_tip_point_count; + + /* Settings to determine if cache is invalid. */ + bool is_dirty; +} ParticleBatchCache; + +/* Gwn_Batch cache management. */ + +typedef struct HairAttributeID { + uint pos; + uint tan; + uint ind; +} HairAttributeID; + +static bool particle_batch_cache_valid(ParticleSystem *psys) +{ + ParticleBatchCache *cache = psys->batch_cache; + + if (cache == NULL) { + return false; + } + + if (cache->is_dirty == false) { + return true; + } + else { + return false; + } + + return true; +} + +static void particle_batch_cache_init(ParticleSystem *psys) +{ + ParticleBatchCache *cache = psys->batch_cache; + + if (!cache) { + cache = psys->batch_cache = MEM_callocN(sizeof(*cache), __func__); + } + else { + memset(cache, 0, sizeof(*cache)); + } + + cache->is_dirty = false; +} + +static ParticleBatchCache *particle_batch_cache_get(ParticleSystem *psys) +{ + if (!particle_batch_cache_valid(psys)) { + particle_batch_cache_clear(psys); + particle_batch_cache_init(psys); + } + return psys->batch_cache; +} + +void DRW_particle_batch_cache_dirty(ParticleSystem *psys, int mode) +{ + ParticleBatchCache *cache = psys->batch_cache; + if (cache == NULL) { + return; + } + switch (mode) { + case BKE_PARTICLE_BATCH_DIRTY_ALL: + cache->is_dirty = true; + break; + default: + BLI_assert(0); + } +} + +static void particle_batch_cache_clear_point(ParticlePointCache *point_cache) +{ + GWN_BATCH_DISCARD_SAFE(point_cache->points); + GWN_VERTBUF_DISCARD_SAFE(point_cache->pos); +} + +static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache) +{ + /* TODO more granular update tagging. */ + GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf); + DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex); + + GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_buf); + DRW_TEXTURE_FREE_SAFE(hair_cache->strand_tex); + + for (int i = 0; i < MAX_MTFACE; ++i) { + GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]); + DRW_TEXTURE_FREE_SAFE(hair_cache->uv_tex[i]); + } + for (int i = 0; i < MAX_MCOL; ++i) { + GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_col_buf[i]); + DRW_TEXTURE_FREE_SAFE(hair_cache->col_tex[i]); + } + for (int i = 0; i < MAX_HAIR_SUBDIV; ++i) { + GWN_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_buf); + DRW_TEXTURE_FREE_SAFE(hair_cache->final[i].proc_tex); + for (int j = 0; j < MAX_THICKRES - 1; ++j) { + GWN_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]); + } + } + + /* "Normal" legacy hairs */ + GWN_BATCH_DISCARD_SAFE(hair_cache->hairs); + GWN_VERTBUF_DISCARD_SAFE(hair_cache->pos); + GWN_INDEXBUF_DISCARD_SAFE(hair_cache->indices); +} + +static void particle_batch_cache_clear(ParticleSystem *psys) +{ + ParticleBatchCache *cache = psys->batch_cache; + if (!cache) { + return; + } + + particle_batch_cache_clear_point(&cache->point); + particle_batch_cache_clear_hair(&cache->hair); + + particle_batch_cache_clear_hair(&cache->edit_hair); + + GWN_BATCH_DISCARD_SAFE(cache->edit_inner_points); + GWN_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos); + GWN_BATCH_DISCARD_SAFE(cache->edit_tip_points); + GWN_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos); +} + +void DRW_particle_batch_cache_free(ParticleSystem *psys) +{ + particle_batch_cache_clear(psys); + MEM_SAFE_FREE(psys->batch_cache); +} + +static void count_cache_segment_keys( + ParticleCacheKey **pathcache, + const int num_path_cache_keys, + ParticleHairCache *hair_cache) +{ + for (int i = 0; i < num_path_cache_keys; i++) { + ParticleCacheKey *path = pathcache[i]; + if (path->segments > 0) { + hair_cache->strands_count++; + hair_cache->elems_count += path->segments + 2; + hair_cache->point_count += path->segments + 1; + } + } +} + +static void ensure_seg_pt_count( + PTCacheEdit *edit, + ParticleSystem *psys, + ParticleHairCache *hair_cache) +{ + if ((hair_cache->pos != NULL && hair_cache->indices != NULL) || + (hair_cache->proc_point_buf != NULL)) + { + return; + } + + hair_cache->strands_count = 0; + hair_cache->elems_count = 0; + hair_cache->point_count = 0; + + if (edit != NULL && edit->pathcache != NULL) { + count_cache_segment_keys(edit->pathcache, edit->totcached, hair_cache); + } + else { + if (psys->pathcache && + (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) + { + count_cache_segment_keys(psys->pathcache, psys->totpart, hair_cache); + } + if (psys->childcache) { + const int child_count = psys->totchild * psys->part->disp / 100; + count_cache_segment_keys(psys->childcache, child_count, hair_cache); + } + } +} + +static void particle_pack_mcol(MCol *mcol, unsigned short r_scol[3]) +{ + /* Convert to linear ushort and swizzle */ + r_scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]); + r_scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]); + r_scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]); +} + +/* Used by parent particles and simple children. */ +static void particle_calculate_parent_uvs( + ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const int num_uv_layers, + const int parent_index, + /*const*/ MTFace **mtfaces, + float (*r_uv)[2]) +{ + if (psmd == NULL) { + return; + } + const int emit_from = psmd->psys->part->from; + if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { + return; + } + ParticleData *particle = &psys->particles[parent_index]; + int num = particle->num_dmcache; + if (num == DMCACHE_NOTFOUND) { + if (particle->num < psmd->mesh_final->totface) { + num = particle->num; + } + } + if (num != DMCACHE_NOTFOUND) { + MFace *mface = &psmd->mesh_final->mface[num]; + for (int j = 0; j < num_uv_layers; j++) { + psys_interpolate_uvs( + mtfaces[j] + num, + mface->v4, + particle->fuv, + r_uv[j]); + } + } +} + +static void particle_calculate_parent_mcol( + ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const int num_uv_layers, + const int parent_index, + /*const*/ MCol **mcols, + MCol *r_mcol) +{ + if (psmd == NULL) { + return; + } + const int emit_from = psmd->psys->part->from; + if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { + return; + } + ParticleData *particle = &psys->particles[parent_index]; + int num = particle->num_dmcache; + if (num == DMCACHE_NOTFOUND) { + if (particle->num < psmd->mesh_final->totface) { + num = particle->num; + } + } + if (num != DMCACHE_NOTFOUND) { + MFace *mface = &psmd->mesh_final->mface[num]; + for (int j = 0; j < num_uv_layers; j++) { + psys_interpolate_mcol( + mcols[j] + num, + mface->v4, + particle->fuv, + &r_mcol[j]); + } + } +} + +/* Used by interpolated children. */ +static void particle_interpolate_children_uvs( + ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const int num_uv_layers, + const int child_index, + /*const*/ MTFace **mtfaces, + float (*r_uv)[2]) +{ + if (psmd == NULL) { + return; + } + const int emit_from = psmd->psys->part->from; + if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { + return; + } + ChildParticle *particle = &psys->child[child_index]; + int num = particle->num; + if (num != DMCACHE_NOTFOUND) { + MFace *mface = &psmd->mesh_final->mface[num]; + for (int j = 0; j < num_uv_layers; j++) { + psys_interpolate_uvs( + mtfaces[j] + num, + mface->v4, + particle->fuv, + r_uv[j]); + } + } +} + +static void particle_interpolate_children_mcol( + ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const int num_col_layers, + const int child_index, + /*const*/ MCol **mcols, + MCol *r_mcol) +{ + if (psmd == NULL) { + return; + } + const int emit_from = psmd->psys->part->from; + if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { + return; + } + ChildParticle *particle = &psys->child[child_index]; + int num = particle->num; + if (num != DMCACHE_NOTFOUND) { + MFace *mface = &psmd->mesh_final->mface[num]; + for (int j = 0; j < num_col_layers; j++) { + psys_interpolate_mcol( + mcols[j] + num, + mface->v4, + particle->fuv, + &r_mcol[j]); + } + } +} + +static void particle_calculate_uvs( + ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const bool is_simple, + const int num_uv_layers, + const int parent_index, + const int child_index, + /*const*/ MTFace **mtfaces, + float (**r_parent_uvs)[2], + float (**r_uv)[2]) +{ + if (psmd == NULL) { + return; + } + if (is_simple) { + if (r_parent_uvs[parent_index] != NULL) { + *r_uv = r_parent_uvs[parent_index]; + } + else { + *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs"); + } + } + else { + *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs"); + } + if (child_index == -1) { + /* Calculate UVs for parent particles. */ + if (is_simple) { + r_parent_uvs[parent_index] = *r_uv; + } + particle_calculate_parent_uvs( + psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv); + } + else { + /* Calculate UVs for child particles. */ + if (!is_simple) { + particle_interpolate_children_uvs( + psys, psmd, num_uv_layers, child_index, mtfaces, *r_uv); + } + else if (!r_parent_uvs[psys->child[child_index].parent]) { + r_parent_uvs[psys->child[child_index].parent] = *r_uv; + particle_calculate_parent_uvs( + psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv); + } + } +} + +static void particle_calculate_mcol( + ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const bool is_simple, + const int num_col_layers, + const int parent_index, + const int child_index, + /*const*/ MCol **mcols, + MCol **r_parent_mcol, + MCol **r_mcol) +{ + if (psmd == NULL) { + return; + } + if (is_simple) { + if (r_parent_mcol[parent_index] != NULL) { + *r_mcol = r_parent_mcol[parent_index]; + } + else { + *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol"); + } + } + else { + *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol"); + } + if (child_index == -1) { + /* Calculate MCols for parent particles. */ + if (is_simple) { + r_parent_mcol[parent_index] = *r_mcol; + } + particle_calculate_parent_mcol( + psys, psmd, num_col_layers, parent_index, mcols, *r_mcol); + } + else { + /* Calculate MCols for child particles. */ + if (!is_simple) { + particle_interpolate_children_mcol( + psys, psmd, num_col_layers, child_index, mcols, *r_mcol); + } + else if (!r_parent_mcol[psys->child[child_index].parent]) { + r_parent_mcol[psys->child[child_index].parent] = *r_mcol; + particle_calculate_parent_mcol( + psys, psmd, num_col_layers, parent_index, mcols, *r_mcol); + } + } +} + +/* Will return last filled index. */ +typedef enum ParticleSource { + PARTICLE_SOURCE_PARENT, + PARTICLE_SOURCE_CHILDREN, +} ParticleSource; +static int particle_batch_cache_fill_segments( + ParticleSystem *psys, + ParticleSystemModifierData *psmd, + ParticleCacheKey **path_cache, + const ParticleSource particle_source, + const int global_offset, + const int start_index, + const int num_path_keys, + const int num_uv_layers, + const int num_col_layers, + /*const*/ MTFace **mtfaces, + /*const*/ MCol **mcols, + uint *uv_id, + uint *col_id, + float (***r_parent_uvs)[2], + MCol ***r_parent_mcol, + Gwn_IndexBufBuilder *elb, + HairAttributeID *attr_id, + ParticleHairCache *hair_cache) +{ + const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES); + const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN); + if (is_simple && *r_parent_uvs == NULL) { + /* TODO(sergey): For edit mode it should be edit->totcached. */ + *r_parent_uvs = MEM_callocN( + sizeof(*r_parent_uvs) * psys->totpart, + "Parent particle UVs"); + } + if (is_simple && *r_parent_mcol == NULL) { + *r_parent_mcol = MEM_callocN( + sizeof(*r_parent_mcol) * psys->totpart, + "Parent particle MCol"); + } + int curr_point = start_index; + for (int i = 0; i < num_path_keys; i++) { + ParticleCacheKey *path = path_cache[i]; + if (path->segments <= 0) { + continue; + } + float tangent[3]; + float (*uv)[2] = NULL; + MCol *mcol = NULL; + particle_calculate_mcol( + psys, psmd, + is_simple, num_col_layers, + is_child ? psys->child[i].parent : i, + is_child ? i : -1, + mcols, + *r_parent_mcol, &mcol); + particle_calculate_uvs( + psys, psmd, + is_simple, num_uv_layers, + is_child ? psys->child[i].parent : i, + is_child ? i : -1, + mtfaces, + *r_parent_uvs, &uv); + for (int j = 0; j < path->segments; j++) { + if (j == 0) { + sub_v3_v3v3(tangent, path[j + 1].co, path[j].co); + } + else { + sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co); + } + GWN_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[j].co); + GWN_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent); + GWN_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &i); + if (psmd != NULL) { + for (int k = 0; k < num_uv_layers; k++) { + GWN_vertbuf_attr_set( + hair_cache->pos, uv_id[k], curr_point, + (is_simple && is_child) ? + (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]); + } + for (int k = 0; k < num_col_layers; k++) { + /* TODO Put the conversion outside the loop */ + unsigned short scol[4]; + particle_pack_mcol( + (is_simple && is_child) ? + &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k], + scol); + GWN_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol); + } + } + GWN_indexbuf_add_generic_vert(elb, curr_point); + curr_point++; + } + sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co); + + int global_index = i + global_offset; + GWN_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[path->segments].co); + GWN_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent); + GWN_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &global_index); + + if (psmd != NULL) { + for (int k = 0; k < num_uv_layers; k++) { + GWN_vertbuf_attr_set( + hair_cache->pos, uv_id[k], curr_point, + (is_simple && is_child) ? + (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]); + } + for (int k = 0; k < num_col_layers; k++) { + /* TODO Put the conversion outside the loop */ + unsigned short scol[4]; + particle_pack_mcol( + (is_simple && is_child) ? + &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k], + scol); + GWN_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol); + } + if (!is_simple) { + MEM_freeN(uv); + MEM_freeN(mcol); + } + } + /* Finish the segment and add restart primitive. */ + GWN_indexbuf_add_generic_vert(elb, curr_point); + GWN_indexbuf_add_primitive_restart(elb); + curr_point++; + } + return curr_point; +} + +static void particle_batch_cache_fill_segments_proc_pos( + ParticleCacheKey **path_cache, + const int num_path_keys, + Gwn_VertBufRaw *attr_step) +{ + for (int i = 0; i < num_path_keys; i++) { + ParticleCacheKey *path = path_cache[i]; + if (path->segments <= 0) { + continue; + } + float total_len = 0.0f; + float *co_prev = NULL, *seg_data_first; + for (int j = 0; j <= path->segments; j++) { + float *seg_data = (float *)GWN_vertbuf_raw_step(attr_step); + copy_v3_v3(seg_data, path[j].co); + if (co_prev) { + total_len += len_v3v3(co_prev, path[j].co); + } + else { + seg_data_first = seg_data; + } + seg_data[3] = total_len; + co_prev = path[j].co; + } + if (total_len > 0.0f) { + /* Divide by total length to have a [0-1] number. */ + for (int j = 0; j <= path->segments; j++, seg_data_first += 4) { + seg_data_first[3] /= total_len; + } + } + } +} + +static int particle_batch_cache_fill_segments_indices( + ParticleCacheKey **path_cache, + const int start_index, + const int num_path_keys, + const int res, + Gwn_IndexBufBuilder *elb) +{ + int curr_point = start_index; + for (int i = 0; i < num_path_keys; i++) { + ParticleCacheKey *path = path_cache[i]; + if (path->segments <= 0) { + continue; + } + for (int k = 0; k < res; k++) { + GWN_indexbuf_add_generic_vert(elb, curr_point++); + } + GWN_indexbuf_add_primitive_restart(elb); + } + return curr_point; +} + +static int particle_batch_cache_fill_strands_data( + ParticleSystem *psys, + ParticleSystemModifierData *psmd, + ParticleCacheKey **path_cache, + const ParticleSource particle_source, + const int start_index, + const int num_path_keys, + Gwn_VertBufRaw *data_step, + float (***r_parent_uvs)[2], Gwn_VertBufRaw *uv_step, MTFace **mtfaces, int num_uv_layers, + MCol ***r_parent_mcol, Gwn_VertBufRaw *col_step, MCol **mcols, int num_col_layers) +{ + const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES); + const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN); + if (is_simple && *r_parent_uvs == NULL) { + /* TODO(sergey): For edit mode it should be edit->totcached. */ + *r_parent_uvs = MEM_callocN( + sizeof(*r_parent_uvs) * psys->totpart, + "Parent particle UVs"); + } + if (is_simple && *r_parent_mcol == NULL) { + *r_parent_mcol = MEM_callocN( + sizeof(*r_parent_mcol) * psys->totpart, + "Parent particle MCol"); + } + int curr_point = start_index; + for (int i = 0; i < num_path_keys; i++) { + ParticleCacheKey *path = path_cache[i]; + if (path->segments <= 0) { + continue; + } + + uint *seg_data = (uint *)GWN_vertbuf_raw_step(data_step); + *seg_data = (curr_point & 0xFFFFFF) | (path->segments << 24); + curr_point += path->segments + 1; + + if (psmd != NULL) { + float (*uv)[2] = NULL; + MCol *mcol = NULL; + + particle_calculate_uvs( + psys, psmd, + is_simple, num_uv_layers, + is_child ? psys->child[i].parent : i, + is_child ? i : -1, + mtfaces, + *r_parent_uvs, &uv); + + particle_calculate_mcol( + psys, psmd, + is_simple, num_col_layers, + is_child ? psys->child[i].parent : i, + is_child ? i : -1, + mcols, + *r_parent_mcol, &mcol); + + for (int k = 0; k < num_uv_layers; k++) { + float *t_uv = (float *)GWN_vertbuf_raw_step(uv_step + k); + copy_v2_v2(t_uv, uv[k]); + } + for (int k = 0; k < num_col_layers; k++) { + unsigned short *scol = (unsigned short *)GWN_vertbuf_raw_step(col_step + k); + particle_pack_mcol( + (is_simple && is_child) ? + &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k], + scol); + } + if (!is_simple) { + MEM_freeN(uv); + MEM_freeN(mcol); + } + } + } + return curr_point; +} + +static void particle_batch_cache_ensure_procedural_final_points( + ParticleHairCache *cache, + int subdiv) +{ + /* Same format as point_tex. */ + Gwn_VertFormat format = { 0 }; + GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + cache->final[subdiv].proc_buf = GWN_vertbuf_create_with_format(&format); + + /* Create a destination buffer for the tranform feedback. Sized appropriately */ + /* Thoses are points! not line segments. */ + GWN_vertbuf_data_alloc(cache->final[subdiv].proc_buf, cache->final[subdiv].strands_res * cache->strands_count); + + /* Create vbo immediatly to bind to texture buffer. */ + GWN_vertbuf_use(cache->final[subdiv].proc_buf); + + cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_buf); +} + +static void particle_batch_cache_ensure_procedural_strand_data( + PTCacheEdit *edit, + ParticleSystem *psys, + ModifierData *md, + ParticleHairCache *cache) +{ + int active_uv = 0; + int active_col = 0; + + ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; + + if (psmd != NULL) { + if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) { + cache->num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV); + active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV); + } + if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) { + cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL); + active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL); + } + } + + Gwn_VertBufRaw data_step; + Gwn_VertBufRaw uv_step[MAX_MTFACE]; + Gwn_VertBufRaw col_step[MAX_MCOL]; + + MTFace *mtfaces[MAX_MTFACE] = {NULL}; + MCol *mcols[MAX_MCOL] = {NULL}; + float (**parent_uvs)[2] = NULL; + MCol **parent_mcol = NULL; + + Gwn_VertFormat format_data = {0}; + uint data_id = GWN_vertformat_attr_add(&format_data, "data", GWN_COMP_U32, 1, GWN_FETCH_INT); + + Gwn_VertFormat format_uv = {0}; + uint uv_id = GWN_vertformat_attr_add(&format_uv, "uv", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + Gwn_VertFormat format_col = {0}; + uint col_id = GWN_vertformat_attr_add(&format_col, "col", GWN_COMP_U16, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + memset(cache->uv_layer_names, 0, sizeof(cache->uv_layer_names)); + memset(cache->col_layer_names, 0, sizeof(cache->col_layer_names)); + + /* Strand Data */ + cache->proc_strand_buf = GWN_vertbuf_create_with_format(&format_data); + GWN_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_count); + GWN_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step); + + /* UV layers */ + for (int i = 0; i < cache->num_uv_layers; i++) { + cache->proc_uv_buf[i] = GWN_vertbuf_create_with_format(&format_uv); + GWN_vertbuf_data_alloc(cache->proc_uv_buf[i], cache->strands_count); + GWN_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]); + + const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i); + uint hash = BLI_ghashutil_strhash_p(name); + int n = 0; + BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "u%u", hash); + BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash); + + if (i == active_uv) { + BLI_snprintf(cache->uv_layer_names[i][n], MAX_LAYER_NAME_LEN, "u"); + } + } + /* Vertex colors */ + for (int i = 0; i < cache->num_col_layers; i++) { + cache->proc_col_buf[i] = GWN_vertbuf_create_with_format(&format_col); + GWN_vertbuf_data_alloc(cache->proc_col_buf[i], cache->strands_count); + GWN_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]); + + const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i); + uint hash = BLI_ghashutil_strhash_p(name); + int n = 0; + BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "c%u", hash); + + /* We only do vcols auto name that are not overridden by uvs */ + if (CustomData_get_named_layer_index(&psmd->mesh_final->ldata, CD_MLOOPUV, name) == -1) { + BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash); + } + + if (i == active_col) { + BLI_snprintf(cache->col_layer_names[i][n], MAX_LAYER_NAME_LEN, "c"); + } + } + + if (cache->num_uv_layers || cache->num_col_layers) { + BKE_mesh_tessface_ensure(psmd->mesh_final); + if (cache->num_uv_layers) { + for (int j = 0; j < cache->num_uv_layers; j++) { + mtfaces[j] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, j); + } + } + if (cache->num_col_layers) { + for (int j = 0; j < cache->num_col_layers; j++) { + mcols[j] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, j); + } + } + } + + if (edit != NULL && edit->pathcache != NULL) { + particle_batch_cache_fill_strands_data( + psys, psmd, edit->pathcache, PARTICLE_SOURCE_PARENT, + 0, edit->totcached, + &data_step, + &parent_uvs, uv_step, (MTFace **)mtfaces, cache->num_uv_layers, + &parent_mcol, col_step, (MCol **)mcols, cache->num_col_layers); + } + else { + int curr_point = 0; + if ((psys->pathcache != NULL) && + (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) + { + curr_point = particle_batch_cache_fill_strands_data( + psys, psmd, psys->pathcache, PARTICLE_SOURCE_PARENT, + 0, psys->totpart, + &data_step, + &parent_uvs, uv_step, (MTFace **)mtfaces, cache->num_uv_layers, + &parent_mcol, col_step, (MCol **)mcols, cache->num_col_layers); + } + if (psys->childcache) { + const int child_count = psys->totchild * psys->part->disp / 100; + curr_point = particle_batch_cache_fill_strands_data( + psys, psmd, psys->childcache, PARTICLE_SOURCE_CHILDREN, + curr_point, child_count, + &data_step, + &parent_uvs, uv_step, (MTFace **)mtfaces, cache->num_uv_layers, + &parent_mcol, col_step, (MCol **)mcols, cache->num_col_layers); + } + } + /* Cleanup. */ + if (parent_uvs != NULL) { + /* TODO(sergey): For edit mode it should be edit->totcached. */ + for (int i = 0; i < psys->totpart; i++) { + MEM_SAFE_FREE(parent_uvs[i]); + } + MEM_freeN(parent_uvs); + } + if (parent_mcol != NULL) { + for (int i = 0; i < psys->totpart; i++) { + MEM_SAFE_FREE(parent_mcol[i]); + } + MEM_freeN(parent_mcol); + } + + /* Create vbo immediatly to bind to texture buffer. */ + GWN_vertbuf_use(cache->proc_strand_buf); + cache->strand_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_buf); + + for (int i = 0; i < cache->num_uv_layers; i++) { + GWN_vertbuf_use(cache->proc_uv_buf[i]); + cache->uv_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_uv_buf[i]); + } + for (int i = 0; i < cache->num_col_layers; i++) { + GWN_vertbuf_use(cache->proc_col_buf[i]); + cache->col_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_col_buf[i]); + } +} + +static void particle_batch_cache_ensure_procedural_indices( + PTCacheEdit *edit, + ParticleSystem *psys, + ParticleHairCache *cache, + int thickness_res, + int subdiv) +{ + BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */ + + if (cache->final[subdiv].proc_hairs[thickness_res - 1] != NULL) { + return; + } + + int verts_per_hair = cache->final[subdiv].strands_res * thickness_res; + /* +1 for primitive restart */ + int element_count = (verts_per_hair + 1) * cache->strands_count; + Gwn_PrimType prim_type = (thickness_res == 1) ? GWN_PRIM_LINE_STRIP : GWN_PRIM_TRI_STRIP; + + static Gwn_VertFormat format = { 0 }; + GWN_vertformat_clear(&format); + + /* initialize vertex format */ + GWN_vertformat_attr_add(&format, "dummy", GWN_COMP_U8, 1, GWN_FETCH_INT_TO_FLOAT_UNIT); + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 1); + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init_ex(&elb, prim_type, element_count, element_count, true); + + if (edit != NULL && edit->pathcache != NULL) { + particle_batch_cache_fill_segments_indices( + edit->pathcache, 0, edit->totcached, verts_per_hair, &elb); + } + else { + int curr_point = 0; + if ((psys->pathcache != NULL) && + (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) + { + curr_point = particle_batch_cache_fill_segments_indices( + psys->pathcache, 0, psys->totpart, verts_per_hair, &elb); + } + if (psys->childcache) { + const int child_count = psys->totchild * psys->part->disp / 100; + curr_point = particle_batch_cache_fill_segments_indices( + psys->childcache, curr_point, child_count, verts_per_hair, &elb); + } + } + + cache->final[subdiv].proc_hairs[thickness_res - 1] = GWN_batch_create_ex( + prim_type, + vbo, + GWN_indexbuf_build(&elb), + GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); +} + +static void particle_batch_cache_ensure_procedural_pos( + PTCacheEdit *edit, + ParticleSystem *psys, + ParticleHairCache *cache) +{ + if (cache->proc_point_buf != NULL) { + return; + } + + /* initialize vertex format */ + Gwn_VertFormat format = {0}; + uint pos_id = GWN_vertformat_attr_add(&format, "posTime", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + cache->proc_point_buf = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(cache->proc_point_buf, cache->point_count); + + Gwn_VertBufRaw pos_step; + GWN_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step); + + if (edit != NULL && edit->pathcache != NULL) { + particle_batch_cache_fill_segments_proc_pos( + edit->pathcache, + edit->totcached, + &pos_step); + } + else { + if ((psys->pathcache != NULL) && + (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) + { + particle_batch_cache_fill_segments_proc_pos( + psys->pathcache, + psys->totpart, + &pos_step); + } + if (psys->childcache) { + const int child_count = psys->totchild * psys->part->disp / 100; + particle_batch_cache_fill_segments_proc_pos( + psys->childcache, + child_count, + &pos_step); + } + } + + /* Create vbo immediatly to bind to texture buffer. */ + GWN_vertbuf_use(cache->proc_point_buf); + + cache->point_tex = GPU_texture_create_from_vertbuf(cache->proc_point_buf); +} + +static void particle_batch_cache_ensure_pos_and_seg( + PTCacheEdit *edit, + ParticleSystem *psys, + ModifierData *md, + ParticleHairCache *hair_cache) +{ + if (hair_cache->pos != NULL && hair_cache->indices != NULL) { + return; + } + + int curr_point = 0; + ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; + + GWN_VERTBUF_DISCARD_SAFE(hair_cache->pos); + GWN_INDEXBUF_DISCARD_SAFE(hair_cache->indices); + + static Gwn_VertFormat format = { 0 }; + HairAttributeID attr_id; + uint *uv_id = NULL; + uint *col_id = NULL; + int num_uv_layers = 0; + int num_col_layers = 0; + int active_uv = 0; + int active_col = 0; + MTFace **mtfaces = NULL; + MCol **mcols = NULL; + float (**parent_uvs)[2] = NULL; + MCol **parent_mcol = NULL; + + if (psmd != NULL) { + if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) { + num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV); + active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV); + } + if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) { + num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL); + active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL); + } + } + + GWN_vertformat_clear(&format); + + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.tan = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.ind = GWN_vertformat_attr_add(&format, "ind", GWN_COMP_I32, 1, GWN_FETCH_INT); + + if (psmd) { + uv_id = MEM_mallocN(sizeof(*uv_id) * num_uv_layers, "UV attrib format"); + col_id = MEM_mallocN(sizeof(*col_id) * num_col_layers, "Col attrib format"); + + for (int i = 0; i < num_uv_layers; i++) { + const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i); + char uuid[32]; + + BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name)); + uv_id[i] = GWN_vertformat_attr_add(&format, uuid, GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + if (i == active_uv) { + GWN_vertformat_alias_add(&format, "u"); + } + } + + for (int i = 0; i < num_uv_layers; i++) { + const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i); + char uuid[32]; + + BLI_snprintf(uuid, sizeof(uuid), "c%u", BLI_ghashutil_strhash_p(name)); + col_id[i] = GWN_vertformat_attr_add(&format, uuid, GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + if (i == active_col) { + GWN_vertformat_alias_add(&format, "c"); + } + } + } + + hair_cache->pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_count); + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init_ex( + &elb, + GWN_PRIM_LINE_STRIP, + hair_cache->elems_count, hair_cache->point_count, + true); + + if (num_uv_layers || num_col_layers) { + BKE_mesh_tessface_ensure(psmd->mesh_final); + if (num_uv_layers) { + mtfaces = MEM_mallocN(sizeof(*mtfaces) * num_uv_layers, "Faces UV layers"); + for (int i = 0; i < num_uv_layers; i++) { + mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, i); + } + } + if (num_col_layers) { + mcols = MEM_mallocN(sizeof(*mcols) * num_col_layers, "Color layers"); + for (int i = 0; i < num_col_layers; i++) { + mcols[i] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, i); + } + } + } + + if (edit != NULL && edit->pathcache != NULL) { + curr_point = particle_batch_cache_fill_segments( + psys, psmd, edit->pathcache, PARTICLE_SOURCE_PARENT, + 0, 0, edit->totcached, + num_uv_layers, num_col_layers, mtfaces, mcols, uv_id, col_id, &parent_uvs, &parent_mcol, + &elb, &attr_id, hair_cache); + } + else { + if ((psys->pathcache != NULL) && + (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) + { + curr_point = particle_batch_cache_fill_segments( + psys, psmd, psys->pathcache, PARTICLE_SOURCE_PARENT, + 0, 0, psys->totpart, + num_uv_layers, num_col_layers, mtfaces, mcols, uv_id, col_id, &parent_uvs, &parent_mcol, + &elb, &attr_id, hair_cache); + } + if (psys->childcache != NULL) { + const int child_count = psys->totchild * psys->part->disp / 100; + curr_point = particle_batch_cache_fill_segments( + psys, psmd, psys->childcache, PARTICLE_SOURCE_CHILDREN, + psys->totpart, curr_point, child_count, + num_uv_layers, num_col_layers, mtfaces, mcols, uv_id, col_id, &parent_uvs, &parent_mcol, + &elb, &attr_id, hair_cache); + } + } + /* Cleanup. */ + if (parent_uvs != NULL) { + /* TODO(sergey): For edit mode it should be edit->totcached. */ + for (int i = 0; i < psys->totpart; i++) { + MEM_SAFE_FREE(parent_uvs[i]); + } + MEM_freeN(parent_uvs); + } + if (parent_mcol != NULL) { + for (int i = 0; i < psys->totpart; i++) { + MEM_SAFE_FREE(parent_mcol[i]); + } + MEM_freeN(parent_mcol); + } + if (num_uv_layers) { + MEM_freeN(mtfaces); + } + if (num_col_layers) { + MEM_freeN(mcols); + } + if (psmd != NULL) { + MEM_freeN(uv_id); + } + hair_cache->indices = GWN_indexbuf_build(&elb); +} + +static void particle_batch_cache_ensure_pos( + Object *object, + ParticleSystem *psys, + ParticlePointCache *point_cache) +{ + if (point_cache->pos != NULL) { + return; + } + + static Gwn_VertFormat format = { 0 }; + static unsigned pos_id, rot_id, val_id; + int i, curr_point; + ParticleData *pa; + ParticleKey state; + ParticleSimulationData sim = {NULL}; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + sim.depsgraph = draw_ctx->depsgraph; + sim.scene = draw_ctx->scene; + sim.ob = object; + sim.psys = psys; + sim.psmd = psys_get_modifier(object, psys); + + if (psys->part->phystype == PART_PHYS_KEYED) { + if (psys->flag & PSYS_KEYED) { + psys_count_keyed_targets(&sim); + if (psys->totkeyed == 0) + return; + } + } + + GWN_VERTBUF_DISCARD_SAFE(point_cache->pos); + + if (format.attrib_ct == 0) { + /* initialize vertex format */ + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + rot_id = GWN_vertformat_attr_add(&format, "rot", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + val_id = GWN_vertformat_attr_add(&format, "val", GWN_COMP_F32, 1, GWN_FETCH_FLOAT); + } + + point_cache->pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(point_cache->pos, psys->totpart); + + for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) { + state.time = DEG_get_ctime(draw_ctx->depsgraph); + if (!psys_get_particle_state(&sim, i, &state, 0)) { + continue; + } + + float val; + + GWN_vertbuf_attr_set(point_cache->pos, pos_id, curr_point, pa->state.co); + GWN_vertbuf_attr_set(point_cache->pos, rot_id, curr_point, pa->state.rot); + + switch (psys->part->draw_col) { + case PART_DRAW_COL_VEL: + val = len_v3(pa->state.vel) / psys->part->color_vec_max; + break; + case PART_DRAW_COL_ACC: + val = len_v3v3( + pa->state.vel, + pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max); + break; + default: + val = -1.0f; + break; + } + + GWN_vertbuf_attr_set(point_cache->pos, val_id, curr_point, &val); + + curr_point++; + } + + if (curr_point != psys->totpart) { + GWN_vertbuf_data_resize(point_cache->pos, curr_point); + } +} + +static void drw_particle_update_ptcache_edit( + Object *object_eval, + ParticleSystem *psys, + PTCacheEdit *edit) +{ + if (edit->psys == NULL) { + return; + } + /* NOTE: Get flag from particle system coming from drawing object. + * this is where depsgraph will be setting flags to. + */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id); + Object *object_orig = DEG_get_original_object(object_eval); + if (psys->flag & PSYS_HAIR_UPDATED) { + PE_update_object(draw_ctx->depsgraph, scene_orig, object_orig, 0); + psys->flag &= ~PSYS_HAIR_UPDATED; + } + if (edit->pathcache == NULL) { + Depsgraph *depsgraph = draw_ctx->depsgraph; + psys_cache_edit_paths( + depsgraph, + scene_orig, object_orig, + edit, + DEG_get_ctime(depsgraph), + DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + } +} + +static void drw_particle_update_ptcache( + Object *object_eval, + ParticleSystem *psys) +{ + if ((object_eval->mode & OB_MODE_PARTICLE_EDIT) == 0) { + return; + } + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id); + Object *object_orig = DEG_get_original_object(object_eval); + PTCacheEdit *edit = PE_create_current( + draw_ctx->depsgraph, scene_orig, object_orig); + if (edit != NULL) { + drw_particle_update_ptcache_edit(object_eval, psys, edit); + } +} + +Gwn_Batch *DRW_particles_batch_cache_get_hair( + Object *object, + ParticleSystem *psys, + ModifierData *md) +{ + ParticleBatchCache *cache = particle_batch_cache_get(psys); + + if (cache->hair.hairs == NULL) { + drw_particle_update_ptcache(object, psys); + ensure_seg_pt_count(NULL, psys, &cache->hair); + particle_batch_cache_ensure_pos_and_seg(NULL, psys, md, &cache->hair); + cache->hair.hairs = GWN_batch_create( + GWN_PRIM_LINE_STRIP, + cache->hair.pos, + cache->hair.indices); + } + return cache->hair.hairs; +} + +Gwn_Batch *DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psys) +{ + ParticleBatchCache *cache = particle_batch_cache_get(psys); + + if (cache->point.points == NULL) { + particle_batch_cache_ensure_pos(object, psys, &cache->point); + cache->point.points = GWN_batch_create(GWN_PRIM_POINTS, cache->point.pos, NULL); + } + + return cache->point.points; +} + +Gwn_Batch *DRW_particles_batch_cache_get_edit_strands( + Object *object, + ParticleSystem *psys, + PTCacheEdit *edit) +{ + ParticleBatchCache *cache = particle_batch_cache_get(psys); + if (cache->edit_hair.hairs != NULL) { + return cache->edit_hair.hairs; + } + drw_particle_update_ptcache_edit(object, psys, edit); + ensure_seg_pt_count(edit, psys, &cache->edit_hair); + particle_batch_cache_ensure_pos_and_seg(edit, psys, NULL, &cache->edit_hair); + cache->edit_hair.hairs = GWN_batch_create( + GWN_PRIM_LINE_STRIP, + cache->edit_hair.pos, + cache->edit_hair.indices); + return cache->edit_hair.hairs; +} + +static void ensure_edit_inner_points_count( + const PTCacheEdit *edit, + ParticleBatchCache *cache) +{ + if (cache->edit_inner_pos != NULL) { + return; + } + cache->edit_inner_point_count = 0; + for (int point_index = 0; point_index < edit->totpoint; point_index++) { + const PTCacheEditPoint *point = &edit->points[point_index]; + BLI_assert(point->totkey >= 1); + cache->edit_inner_point_count += (point->totkey - 1); + } +} + +static void edit_colors_get( + PTCacheEdit *edit, + float selected_color[4], + float normal_color[4]) +{ + rgb_uchar_to_float(selected_color, edit->sel_col); + rgb_uchar_to_float(normal_color, edit->nosel_col); + selected_color[3] = 1.0f; + normal_color[3] = 1.0f; +} + +static void particle_batch_cache_ensure_edit_inner_pos( + PTCacheEdit *edit, + ParticleBatchCache *cache) +{ + if (cache->edit_inner_pos != NULL) { + return; + } + + static Gwn_VertFormat format = { 0 }; + static unsigned pos_id, color_id; + + GWN_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos); + + if (format.attrib_ct == 0) { + /* initialize vertex format */ + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + color_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + } + + cache->edit_inner_pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_count); + + float selected_color[4], normal_color[4]; + edit_colors_get(edit, selected_color, normal_color); + + int global_key_index = 0; + for (int point_index = 0; point_index < edit->totpoint; point_index++) { + const PTCacheEditPoint *point = &edit->points[point_index]; + for (int key_index = 0; key_index < point->totkey - 1; key_index++) { + PTCacheEditKey *key = &point->keys[key_index]; + GWN_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co); + if (key->flag & PEK_SELECT) { + GWN_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, selected_color); + } + else { + GWN_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, normal_color); + } + global_key_index++; + } + } +} + +Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points( + Object *object, + ParticleSystem *psys, + PTCacheEdit *edit) +{ + ParticleBatchCache *cache = particle_batch_cache_get(psys); + if (cache->edit_inner_points != NULL) { + return cache->edit_inner_points; + } + drw_particle_update_ptcache_edit(object, psys, edit); + ensure_edit_inner_points_count(edit, cache); + particle_batch_cache_ensure_edit_inner_pos(edit, cache); + cache->edit_inner_points = GWN_batch_create( + GWN_PRIM_POINTS, + cache->edit_inner_pos, + NULL); + return cache->edit_inner_points; +} + +static void ensure_edit_tip_points_count( + const PTCacheEdit *edit, + ParticleBatchCache *cache) +{ + if (cache->edit_tip_pos != NULL) { + return; + } + cache->edit_tip_point_count = edit->totpoint; +} + +static void particle_batch_cache_ensure_edit_tip_pos( + PTCacheEdit *edit, + ParticleBatchCache *cache) +{ + if (cache->edit_tip_pos != NULL) { + return; + } + + static Gwn_VertFormat format = { 0 }; + static unsigned pos_id, color_id; + + GWN_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos); + + if (format.attrib_ct == 0) { + /* initialize vertex format */ + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + color_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + } + + cache->edit_tip_pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_count); + + float selected_color[4], normal_color[4]; + edit_colors_get(edit, selected_color, normal_color); + + for (int point_index = 0; point_index < edit->totpoint; point_index++) { + const PTCacheEditPoint *point = &edit->points[point_index]; + PTCacheEditKey *key = &point->keys[point->totkey - 1]; + GWN_vertbuf_attr_set(cache->edit_tip_pos, pos_id, point_index, key->world_co); + if (key->flag & PEK_SELECT) { + GWN_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, selected_color); + } + else { + GWN_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, normal_color); + } + } +} + +Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points( + Object *object, + ParticleSystem *psys, + PTCacheEdit *edit) +{ + ParticleBatchCache *cache = particle_batch_cache_get(psys); + if (cache->edit_tip_points != NULL) { + return cache->edit_tip_points; + } + drw_particle_update_ptcache_edit(object, psys, edit); + ensure_edit_tip_points_count(edit, cache); + particle_batch_cache_ensure_edit_tip_pos(edit, cache); + cache->edit_tip_points = GWN_batch_create( + GWN_PRIM_POINTS, + cache->edit_tip_pos, + NULL); + return cache->edit_tip_points; +} + +/* Ensure all textures and buffers needed for GPU accelerated drawing. */ +bool particles_ensure_procedural_data( + Object *UNUSED(object), + ParticleSystem *psys, + ModifierData *md, + ParticleHairCache **r_hair_cache, + int subdiv, + int thickness_res) +{ + bool need_ft_update = false; + + ParticleSettings *part = psys->part; + ParticleBatchCache *cache = particle_batch_cache_get(psys); + *r_hair_cache = &cache->hair; + + (*r_hair_cache)->final[subdiv].strands_res = 1 << (part->draw_step + subdiv); + + /* Refreshed on combing and simulation. */ + if ((*r_hair_cache)->proc_point_buf == NULL) { + ensure_seg_pt_count(NULL, psys, &cache->hair); + particle_batch_cache_ensure_procedural_pos(NULL, psys, &cache->hair); + need_ft_update = true; + } + + /* Refreshed if active layer or custom data changes. */ + if ((*r_hair_cache)->strand_tex == NULL) { + particle_batch_cache_ensure_procedural_strand_data(NULL, psys, md, &cache->hair); + } + + /* Refreshed only on subdiv count change. */ + if ((*r_hair_cache)->final[subdiv].proc_buf == NULL) { + particle_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv); + need_ft_update = true; + } + if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == NULL) { + particle_batch_cache_ensure_procedural_indices(NULL, psys, &cache->hair, thickness_res, subdiv); + } + + + return need_ft_update; +} diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c new file mode 100644 index 00000000000..11e04306143 --- /dev/null +++ b/source/blender/draw/intern/draw_common.c @@ -0,0 +1,772 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_common.c + * \ingroup draw + */ + +#include "DRW_render.h" + +#include "GPU_shader.h" +#include "GPU_texture.h" + +#include "UI_resources.h" + +#include "BKE_global.h" +#include "BKE_colorband.h" + +#include "draw_common.h" + +#if 0 +#define UI_COLOR_RGB_FROM_U8(r, g, b, v4) \ + ARRAY_SET_ITEMS(v4, (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 1.0) +#endif +#define UI_COLOR_RGBA_FROM_U8(r, g, b, a, v4) \ + ARRAY_SET_ITEMS(v4, (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f) + +/* Colors & Constant */ +GlobalsUboStorage ts; +struct GPUUniformBuffer *globals_ubo = NULL; +struct GPUTexture *globals_ramp = NULL; + +void DRW_globals_update(void) +{ + UI_GetThemeColor4fv(TH_WIRE, ts.colorWire); + UI_GetThemeColor4fv(TH_WIRE_EDIT, ts.colorWireEdit); + UI_GetThemeColor4fv(TH_ACTIVE, ts.colorActive); + UI_GetThemeColor4fv(TH_SELECT, ts.colorSelect); + UI_GetThemeColor4fv(TH_TRANSFORM, ts.colorTransform); + UI_COLOR_RGBA_FROM_U8(0x88, 0xFF, 0xFF, 155, ts.colorLibrarySelect); + UI_COLOR_RGBA_FROM_U8(0x55, 0xCC, 0xCC, 155, ts.colorLibrary); + UI_GetThemeColor4fv(TH_LAMP, ts.colorLamp); + UI_GetThemeColor4fv(TH_SPEAKER, ts.colorSpeaker); + UI_GetThemeColor4fv(TH_CAMERA, ts.colorCamera); + UI_GetThemeColor4fv(TH_EMPTY, ts.colorEmpty); + UI_GetThemeColor4fv(TH_VERTEX, ts.colorVertex); + UI_GetThemeColor4fv(TH_VERTEX_SELECT, ts.colorVertexSelect); + UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, ts.colorEditMeshActive); + UI_GetThemeColor4fv(TH_EDGE_SELECT, ts.colorEdgeSelect); + UI_GetThemeColor4fv(TH_EDGE_SEAM, ts.colorEdgeSeam); + UI_GetThemeColor4fv(TH_EDGE_SHARP, ts.colorEdgeSharp); + UI_GetThemeColor4fv(TH_EDGE_CREASE, ts.colorEdgeCrease); + UI_GetThemeColor4fv(TH_EDGE_BEVEL, ts.colorEdgeBWeight); + UI_GetThemeColor4fv(TH_EDGE_FACESEL, ts.colorEdgeFaceSelect); + UI_GetThemeColor4fv(TH_FACE, ts.colorFace); + UI_GetThemeColor4fv(TH_FACE_SELECT, ts.colorFaceSelect); + UI_GetThemeColor4fv(TH_NORMAL, ts.colorNormal); + UI_GetThemeColor4fv(TH_VNORMAL, ts.colorVNormal); + UI_GetThemeColor4fv(TH_LNORMAL, ts.colorLNormal); + UI_GetThemeColor4fv(TH_FACE_DOT, ts.colorFaceDot); + UI_GetThemeColor4fv(TH_BACK, ts.colorBackground); + + /* Curve */ + UI_GetThemeColor4fv(TH_HANDLE_FREE, ts.colorHandleFree); + UI_GetThemeColor4fv(TH_HANDLE_AUTO, ts.colorHandleAuto); + UI_GetThemeColor4fv(TH_HANDLE_VECT, ts.colorHandleVect); + UI_GetThemeColor4fv(TH_HANDLE_ALIGN, ts.colorHandleAlign); + UI_GetThemeColor4fv(TH_HANDLE_AUTOCLAMP, ts.colorHandleAutoclamp); + UI_GetThemeColor4fv(TH_HANDLE_SEL_FREE, ts.colorHandleSelFree); + UI_GetThemeColor4fv(TH_HANDLE_SEL_AUTO, ts.colorHandleSelAuto); + UI_GetThemeColor4fv(TH_HANDLE_SEL_VECT, ts.colorHandleSelVect); + UI_GetThemeColor4fv(TH_HANDLE_SEL_ALIGN, ts.colorHandleSelAlign); + UI_GetThemeColor4fv(TH_HANDLE_SEL_AUTOCLAMP, ts.colorHandleSelAutoclamp); + UI_GetThemeColor4fv(TH_NURB_ULINE, ts.colorNurbUline); + UI_GetThemeColor4fv(TH_NURB_SEL_ULINE, ts.colorNurbSelUline); + UI_GetThemeColor4fv(TH_ACTIVE_SPLINE, ts.colorActiveSpline); + + /* Grid */ + UI_GetThemeColorShade4fv(TH_GRID, 10, ts.colorGrid); + /* emphasise division lines lighter instead of darker, if background is darker than grid */ + UI_GetThemeColorShade4fv( + TH_GRID, + (ts.colorGrid[0] + ts.colorGrid[1] + ts.colorGrid[2] + 0.12f > + ts.colorBackground[0] + ts.colorBackground[1] + ts.colorBackground[2]) ? + 20 : -10, ts.colorGridEmphasise); + /* Grid Axis */ + UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_X, 0.5f, -10, ts.colorGridAxisX); + UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Y, 0.5f, -10, ts.colorGridAxisY); + UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Z, 0.5f, -10, ts.colorGridAxisZ); + + UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, ts.colorDeselect); + UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, ts.colorOutline); + UI_GetThemeColorShadeAlpha4fv(TH_LAMP, 0, 255, ts.colorLampNoAlpha); + + ts.sizeLampCenter = (U.obcenter_dia + 1.5f) * U.pixelsize; + ts.sizeLampCircle = U.pixelsize * 9.0f; + ts.sizeLampCircleShadow = ts.sizeLampCircle + U.pixelsize * 3.0f; + + /* M_SQRT2 to be at least the same size of the old square */ + ts.sizeVertex = ceilf(UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f); + ts.sizeFaceDot = ceilf(UI_GetThemeValuef(TH_FACEDOT_SIZE) * (float)M_SQRT2); + ts.sizeEdge = 1.0f / 2.0f; /* TODO Theme */ + ts.sizeEdgeFix = 0.5f + 2.0f * (2.0f * (MAX2(ts.sizeVertex, ts.sizeEdge)) * (float)M_SQRT1_2); + + + if (globals_ubo == NULL) { + globals_ubo = DRW_uniformbuffer_create(sizeof(GlobalsUboStorage), &ts); + } + + DRW_uniformbuffer_update(globals_ubo, &ts); + + ColorBand ramp = {0}; + float *colors; + int col_size; + + ramp.tot = 3; + ramp.data[0].a = 1.0f; + ramp.data[0].b = 1.0f; + ramp.data[0].pos = 0.0f; + ramp.data[1].a = 1.0f; + ramp.data[1].g = 1.0f; + ramp.data[1].pos = 0.5f; + ramp.data[2].a = 1.0f; + ramp.data[2].r = 1.0f; + ramp.data[2].pos = 1.0f; + + BKE_colorband_evaluate_table_rgba(&ramp, &colors, &col_size); + + if (globals_ramp) { + GPU_texture_free(globals_ramp); + } + globals_ramp = GPU_texture_create_1D(col_size, GPU_RGBA8, colors, NULL); + + MEM_freeN(colors); +} + +/* ********************************* SHGROUP ************************************* */ + +extern char datatoc_armature_axes_vert_glsl[]; +extern char datatoc_armature_sphere_solid_vert_glsl[]; +extern char datatoc_armature_sphere_solid_frag_glsl[]; +extern char datatoc_armature_sphere_outline_vert_glsl[]; +extern char datatoc_armature_envelope_solid_vert_glsl[]; +extern char datatoc_armature_envelope_solid_frag_glsl[]; +extern char datatoc_armature_envelope_outline_vert_glsl[]; +extern char datatoc_armature_envelope_distance_frag_glsl[]; +extern char datatoc_armature_shape_solid_vert_glsl[]; +extern char datatoc_armature_shape_solid_frag_glsl[]; +extern char datatoc_armature_shape_outline_vert_glsl[]; +extern char datatoc_armature_shape_outline_geom_glsl[]; +extern char datatoc_armature_stick_vert_glsl[]; +extern char datatoc_armature_stick_frag_glsl[]; +extern char datatoc_gpu_shader_flat_color_frag_glsl[]; + +extern char datatoc_object_mball_handles_vert_glsl[]; + +static struct { + struct GPUShader *shape_outline; + struct GPUShader *shape_solid; + struct GPUShader *bone_axes; + struct GPUShader *bone_envelope; + struct GPUShader *bone_envelope_distance; + struct GPUShader *bone_envelope_outline; + struct GPUShader *bone_sphere; + struct GPUShader *bone_sphere_outline; + struct GPUShader *bone_stick; + + struct GPUShader *mball_handles; +} g_shaders = {NULL}; + +static struct { + struct Gwn_VertFormat *instance_screenspace; + struct Gwn_VertFormat *instance_color; + struct Gwn_VertFormat *instance_screen_aligned; + struct Gwn_VertFormat *instance_scaled; + struct Gwn_VertFormat *instance_sized; + struct Gwn_VertFormat *instance_outline; + struct Gwn_VertFormat *instance; + struct Gwn_VertFormat *instance_camera; + struct Gwn_VertFormat *instance_distance_lines; + struct Gwn_VertFormat *instance_spot; + struct Gwn_VertFormat *instance_bone; + struct Gwn_VertFormat *instance_bone_stick; + struct Gwn_VertFormat *instance_bone_outline; + struct Gwn_VertFormat *instance_bone_envelope; + struct Gwn_VertFormat *instance_bone_envelope_distance; + struct Gwn_VertFormat *instance_bone_envelope_outline; + struct Gwn_VertFormat *instance_mball_handles; + struct Gwn_VertFormat *dynlines_color; +} g_formats = {NULL}; + +void DRW_globals_free(void) +{ + struct Gwn_VertFormat **format = &g_formats.instance_screenspace; + for (int i = 0; i < sizeof(g_formats) / sizeof(void *); ++i, ++format) { + MEM_SAFE_FREE(*format); + } + + struct GPUShader **shader = &g_shaders.shape_outline; + for (int i = 0; i < sizeof(g_shaders) / sizeof(void *); ++i, ++shader) { + DRW_SHADER_FREE_SAFE(*shader); + } +} + +DRWShadingGroup *shgroup_dynlines_flat_color(DRWPass *pass) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR); + + DRW_shgroup_instance_format(g_formats.dynlines_color, { + {"pos", DRW_ATTRIB_FLOAT, 3}, + {"color", DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_line_batch_create_with_format(sh, pass, g_formats.dynlines_color); + + return grp; +} + +DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(DRWPass *pass, float color[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + + static float dash_width = 12.0f; + static float dash_factor = 0.5f; + DRWShadingGroup *grp = DRW_shgroup_line_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + DRW_shgroup_uniform_vec2(grp, "viewport_size", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_float(grp, "dash_width", &dash_width, 1); + DRW_shgroup_uniform_float(grp, "dash_factor", &dash_factor, 1); + DRW_shgroup_uniform_int_copy(grp, "num_colors", 0); /* "simple" mode */ + + return grp; +} + +DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4], float *size) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + + DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + DRW_shgroup_uniform_float(grp, "size", size, 1); + DRW_shgroup_state_enable(grp, DRW_STATE_POINT); + + return grp; +} + +DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, float color[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE); + + DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + + return grp; +} + +DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4]) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT); + + DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", color, 1); + DRW_shgroup_state_enable(grp, DRW_STATE_POINT); + + return grp; +} + +DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_Batch *geom, float *size) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR); + + DRW_shgroup_instance_format(g_formats.instance_screenspace, { + {"world_pos", DRW_ATTRIB_FLOAT, 3}, + {"color", DRW_ATTRIB_FLOAT, 3} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screenspace); + DRW_shgroup_uniform_float(grp, "size", size, 1); + DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1); + DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); + DRW_shgroup_state_enable(grp, DRW_STATE_STIPPLE_3); + + return grp; +} + +DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct Gwn_Batch *geom) +{ + static float light[3] = {0.0f, 0.0f, 1.0f}; + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR); + + DRW_shgroup_instance_format(g_formats.instance_color, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"color", DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); + DRW_shgroup_uniform_vec3(grp, "light", light, 1); + + return grp; +} + +DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct Gwn_Batch *geom) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR); + + DRW_shgroup_instance_format(g_formats.instance_color, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"color", DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); + + return grp; +} + +DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, struct Gwn_Batch *geom) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED); + + DRW_shgroup_instance_format(g_formats.instance_screen_aligned, { + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screen_aligned); + DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); + + return grp; +} + +DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Gwn_Batch *geom) +{ + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS); + + DRW_shgroup_instance_format(g_formats.instance_screen_aligned, { + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screen_aligned); + DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); + + return grp; +} + +DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, struct Gwn_Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE); + + DRW_shgroup_instance_format(g_formats.instance_scaled, { + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 3}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_scaled); + + return grp; +} + +DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Gwn_Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE); + + DRW_shgroup_instance_format(g_formats.instance_sized, { + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_sized); + + return grp; +} + +DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct Gwn_Batch *geom, int *baseid) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE); + + DRW_shgroup_instance_format(g_formats.instance_outline, { + {"callId", DRW_ATTRIB_INT, 1}, + {"size", DRW_ATTRIB_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_outline); + DRW_shgroup_uniform_int(grp, "baseId", baseid, 1); + + return grp; +} + +DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Gwn_Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA); + + DRW_shgroup_instance_format(g_formats.instance_camera, { + {"color", DRW_ATTRIB_FLOAT, 3}, + {"corners", DRW_ATTRIB_FLOAT, 8}, + {"depth", DRW_ATTRIB_FLOAT, 1}, + {"tria", DRW_ATTRIB_FLOAT, 4}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_camera); + + return grp; +} + +DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Gwn_Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES); + static float point_size = 4.0f; + + DRW_shgroup_instance_format(g_formats.instance_distance_lines, { + {"color", DRW_ATTRIB_FLOAT, 3}, + {"start", DRW_ATTRIB_FLOAT, 1}, + {"end", DRW_ATTRIB_FLOAT, 1}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_distance_lines); + DRW_shgroup_uniform_float(grp, "size", &point_size, 1); + + return grp; +} + +DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR); + static const int True = true; + static const int False = false; + + DRW_shgroup_instance_format(g_formats.instance_spot, { + {"color", DRW_ATTRIB_FLOAT, 3}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_spot); + DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1); + DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1); + DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1); + + return grp; +} + +DRWShadingGroup *shgroup_instance_bone_axes(DRWPass *pass) +{ + if (g_shaders.bone_axes == NULL) { + g_shaders.bone_axes = DRW_shader_create( + datatoc_armature_axes_vert_glsl, NULL, + datatoc_gpu_shader_flat_color_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_color, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"color", DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_axes, + pass, DRW_cache_bone_arrows_get(), + g_formats.instance_color); + DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2); + + return grp; +} + +DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass) +{ + if (g_shaders.bone_envelope_outline == NULL) { + g_shaders.bone_envelope_outline = DRW_shader_create( + datatoc_armature_envelope_outline_vert_glsl, NULL, + datatoc_gpu_shader_flat_color_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_bone_envelope_outline, { + {"headSphere", DRW_ATTRIB_FLOAT, 4}, + {"tailSphere", DRW_ATTRIB_FLOAT, 4}, + {"outlineColorSize", DRW_ATTRIB_FLOAT, 4}, + {"xAxis", DRW_ATTRIB_FLOAT, 3} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_envelope_outline, + pass, DRW_cache_bone_envelope_outline_get(), + g_formats.instance_bone_envelope_outline); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + + return grp; +} + +DRWShadingGroup *shgroup_instance_bone_envelope_distance(DRWPass *pass) +{ + if (g_shaders.bone_envelope_distance == NULL) { + g_shaders.bone_envelope_distance = DRW_shader_create( + datatoc_armature_envelope_solid_vert_glsl, NULL, + datatoc_armature_envelope_distance_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_bone_envelope_distance, { + {"headSphere", DRW_ATTRIB_FLOAT, 4}, + {"tailSphere", DRW_ATTRIB_FLOAT, 4}, + {"xAxis", DRW_ATTRIB_FLOAT, 3} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_envelope_distance, + pass, DRW_cache_bone_envelope_solid_get(), + g_formats.instance_bone_envelope_distance); + + return grp; +} + +DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass) +{ + if (g_shaders.bone_envelope == NULL) { + g_shaders.bone_envelope = DRW_shader_create( + datatoc_armature_envelope_solid_vert_glsl, NULL, + datatoc_armature_envelope_solid_frag_glsl, "#define SMOOTH_ENVELOPE\n"); + } + + DRW_shgroup_instance_format(g_formats.instance_bone_envelope, { + {"headSphere", DRW_ATTRIB_FLOAT, 4}, + {"tailSphere", DRW_ATTRIB_FLOAT, 4}, + {"boneColor", DRW_ATTRIB_FLOAT, 3}, + {"stateColor", DRW_ATTRIB_FLOAT, 3}, + {"xAxis", DRW_ATTRIB_FLOAT, 3} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_envelope, + pass, DRW_cache_bone_envelope_solid_get(), + g_formats.instance_bone_envelope); + + return grp; +} + +DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass) +{ + if (g_shaders.mball_handles == NULL) { + g_shaders.mball_handles = DRW_shader_create( + datatoc_object_mball_handles_vert_glsl, NULL, + datatoc_gpu_shader_flat_color_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_mball_handles, { + {"ScaleTranslationMatrix", DRW_ATTRIB_FLOAT, 12}, + {"radius", DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.mball_handles, pass, + DRW_cache_screenspace_circle_get(), + g_formats.instance_mball_handles); + DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); + + return grp; +} + +/* Only works with batches with adjacency infos. */ +DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, struct Gwn_Batch *geom) +{ + if (g_shaders.shape_outline == NULL) { + g_shaders.shape_outline = DRW_shader_create( + datatoc_armature_shape_outline_vert_glsl, + datatoc_armature_shape_outline_geom_glsl, + datatoc_gpu_shader_flat_color_frag_glsl, + NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_bone_outline, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"outlineColorSize", DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.shape_outline, + pass, geom, g_formats.instance_bone_outline); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + + return grp; +} + +DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass, struct Gwn_Batch *geom) +{ + if (g_shaders.shape_solid == NULL) { + g_shaders.shape_solid = DRW_shader_create( + datatoc_armature_shape_solid_vert_glsl, NULL, + datatoc_armature_shape_solid_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_bone, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"boneColor", DRW_ATTRIB_FLOAT, 3}, + {"stateColor", DRW_ATTRIB_FLOAT, 3} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.shape_solid, + pass, geom, g_formats.instance_bone); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + + return grp; +} + +DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass) +{ + if (g_shaders.bone_sphere == NULL) { + g_shaders.bone_sphere = DRW_shader_create( + datatoc_armature_sphere_solid_vert_glsl, NULL, + datatoc_armature_sphere_solid_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_bone, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"boneColor", DRW_ATTRIB_FLOAT, 3}, + {"stateColor", DRW_ATTRIB_FLOAT, 3} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_sphere, + pass, DRW_cache_bone_point_get(), g_formats.instance_bone); + + return grp; +} + +DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass) +{ + if (g_shaders.bone_sphere_outline == NULL) { + g_shaders.bone_sphere_outline = DRW_shader_create( + datatoc_armature_sphere_outline_vert_glsl, NULL, + datatoc_gpu_shader_flat_color_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_bone_outline, { + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + {"outlineColorSize", DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_sphere_outline, + pass, DRW_cache_bone_point_wire_outline_get(), + g_formats.instance_bone_outline); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + + return grp; +} + +DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass) +{ + if (g_shaders.bone_stick == NULL) { + g_shaders.bone_stick = DRW_shader_create( + datatoc_armature_stick_vert_glsl, NULL, + datatoc_armature_stick_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_bone_stick, { + {"boneStart", DRW_ATTRIB_FLOAT, 3}, + {"boneEnd", DRW_ATTRIB_FLOAT, 3}, + {"wireColor", DRW_ATTRIB_FLOAT, 4}, /* TODO port theses to uchar color */ + {"boneColor", DRW_ATTRIB_FLOAT, 4}, + {"headColor", DRW_ATTRIB_FLOAT, 4}, + {"tailColor", DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_stick, + pass, DRW_cache_bone_stick_get(), + g_formats.instance_bone_stick); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + + return grp; +} + +/* ******************************************** COLOR UTILS *********************************************** */ + +/* TODO FINISH */ +/** + * Get the wire color theme_id of an object based on it's state + * \a r_color is a way to get a pointer to the static color var associated + */ +int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool is_edit = (draw_ctx->object_mode & OB_MODE_EDIT) != 0; + const bool active = (view_layer->basact && view_layer->basact->object == ob); + /* confusing logic here, there are 2 methods of setting the color + * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id. + * + * note: no theme yet for 'colindex' */ + int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE; + + if (//(scene->obedit == NULL) && + ((G.moving & G_TRANSFORM_OBJ) != 0) && + ((ob->base_flag & BASE_SELECTED) != 0)) + { + theme_id = TH_TRANSFORM; + } + else { + /* Sets the 'theme_id' or fallback to wire */ + if ((ob->base_flag & BASE_SELECTED) != 0) { + theme_id = (active) ? TH_ACTIVE : TH_SELECT; + } + else { + if (ob->type == OB_LAMP) theme_id = TH_LAMP; + else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER; + else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA; + else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY; + else if (ob->type == OB_LIGHTPROBE) theme_id = TH_EMPTY; /* TODO add lightprobe color */ + /* fallback to TH_WIRE */ + } + } + + if (r_color != NULL) { + switch (theme_id) { + case TH_WIRE_EDIT: *r_color = ts.colorWireEdit; break; + case TH_ACTIVE: *r_color = ts.colorActive; break; + case TH_SELECT: *r_color = ts.colorSelect; break; + case TH_TRANSFORM: *r_color = ts.colorTransform; break; + case TH_SPEAKER: *r_color = ts.colorSpeaker; break; + case TH_CAMERA: *r_color = ts.colorCamera; break; + case TH_EMPTY: *r_color = ts.colorEmpty; break; + case TH_LAMP: *r_color = ts.colorLamp; break; + default: *r_color = ts.colorWire; break; + } + } + + return theme_id; +} + +/* XXX This is utter shit, better find something more general */ +float *DRW_color_background_blend_get(int theme_id) +{ + static float colors[11][4]; + float *ret; + + switch (theme_id) { + case TH_WIRE_EDIT: ret = colors[0]; break; + case TH_ACTIVE: ret = colors[1]; break; + case TH_SELECT: ret = colors[2]; break; + case TH_TRANSFORM: ret = colors[5]; break; + case TH_SPEAKER: ret = colors[6]; break; + case TH_CAMERA: ret = colors[7]; break; + case TH_EMPTY: ret = colors[8]; break; + case TH_LAMP: ret = colors[9]; break; + default: ret = colors[10]; break; + } + + UI_GetThemeColorBlendShade4fv(theme_id, TH_BACK, 0.5, 0, ret); + + return ret; +} diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h new file mode 100644 index 00000000000..49a1ae42198 --- /dev/null +++ b/source/blender/draw/intern/draw_common.h @@ -0,0 +1,172 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_common.h + * \ingroup draw + */ + +#ifndef __DRAW_COMMON_H__ +#define __DRAW_COMMON_H__ + +struct DRWPass; +struct DRWShadingGroup; +struct Gwn_Batch; +struct GPUMaterial; +struct Object; +struct ViewLayer; +struct ModifierData; +struct ParticleSystem; +struct PTCacheEdit; + +/* Used as ubo but colors can be directly referenced as well */ +/* Keep in sync with: common_globals_lib.glsl (globalsBlock) */ +typedef struct GlobalsUboStorage { + /* UBOs data needs to be 16 byte aligned (size of vec4) */ + float colorWire[4]; + float colorWireEdit[4]; + float colorActive[4]; + float colorSelect[4]; + float colorTransform[4]; + float colorLibrarySelect[4]; + float colorLibrary[4]; + float colorLamp[4]; + float colorSpeaker[4]; + float colorCamera[4]; + float colorEmpty[4]; + float colorVertex[4]; + float colorVertexSelect[4]; + float colorEditMeshActive[4]; + float colorEdgeSelect[4]; + float colorEdgeSeam[4]; + float colorEdgeSharp[4]; + float colorEdgeCrease[4]; + float colorEdgeBWeight[4]; + float colorEdgeFaceSelect[4]; + float colorFace[4]; + float colorFaceSelect[4]; + float colorNormal[4]; + float colorVNormal[4]; + float colorLNormal[4]; + float colorFaceDot[4]; + + float colorDeselect[4]; + float colorOutline[4]; + float colorLampNoAlpha[4]; + + float colorBackground[4]; + + float colorHandleFree[4]; + float colorHandleAuto[4]; + float colorHandleVect[4]; + float colorHandleAlign[4]; + float colorHandleAutoclamp[4]; + float colorHandleSelFree[4]; + float colorHandleSelAuto[4]; + float colorHandleSelVect[4]; + float colorHandleSelAlign[4]; + float colorHandleSelAutoclamp[4]; + float colorNurbUline[4]; + float colorNurbSelUline[4]; + float colorActiveSpline[4]; + + float colorGrid[4]; + float colorGridEmphasise[4]; + float colorGridAxisX[4]; + float colorGridAxisY[4]; + float colorGridAxisZ[4]; + + /* Pack individual float at the end of the buffer to avoid alignement errors */ + float sizeLampCenter, sizeLampCircle, sizeLampCircleShadow; + float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot; + float gridDistance, gridResolution, gridSubdivisions, gridScale; +} GlobalsUboStorage; +/* Keep in sync with globalsBlock in shaders */ + +void DRW_globals_update(void); +void DRW_globals_free(void); + +struct DRWShadingGroup *shgroup_dynlines_flat_color(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(struct DRWPass *pass, float color[4]); +struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, float color[4], float *size); +struct DRWShadingGroup *shgroup_groundlines_uniform_color(struct DRWPass *pass, float color[4]); +struct DRWShadingGroup *shgroup_groundpoints_uniform_color(struct DRWPass *pass, float color[4]); +struct DRWShadingGroup *shgroup_instance_screenspace(struct DRWPass *pass, struct Gwn_Batch *geom, float *size); +struct DRWShadingGroup *shgroup_instance_solid(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_wire(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_screen_aligned(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_axis_names(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_image_plane(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_scaled(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_outline(struct DRWPass *pass, struct Gwn_Batch *geom, int *baseid); +struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_mball_handles(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_axes(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_envelope_distance(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_envelope_outline(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_shape_outline(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_bone_shape_solid(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_sphere_solid(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_stick(struct DRWPass *pass); + +int DRW_object_wire_theme_get( + struct Object *ob, struct ViewLayer *view_layer, float **r_color); +float *DRW_color_background_blend_get(int theme_id); + +/* draw_armature.c */ +typedef struct DRWArmaturePasses { + struct DRWPass *bone_solid; + struct DRWPass *bone_outline; + struct DRWPass *bone_wire; + struct DRWPass *bone_envelope; + struct DRWPass *bone_axes; + struct DRWPass *relationship_lines; +} DRWArmaturePasses; + +void DRW_shgroup_armature_object(struct Object *ob, struct ViewLayer *view_layer, struct DRWArmaturePasses passes); +void DRW_shgroup_armature_pose(struct Object *ob, struct DRWArmaturePasses passes); +void DRW_shgroup_armature_edit(struct Object *ob, struct DRWArmaturePasses passes); + +/* draw_hair.c */ + +/* This creates a shading group with display hairs. + * The draw call is already added by this function, just add additional uniforms. */ +struct DRWShadingGroup *DRW_shgroup_hair_create( + struct Object *object, struct ParticleSystem *psys, struct ModifierData *md, + struct DRWPass *hair_pass, struct DRWPass *tf_pass, + struct GPUShader *shader); + +struct DRWShadingGroup *DRW_shgroup_material_hair_create( + struct Object *object, struct ParticleSystem *psys, struct ModifierData *md, + struct DRWPass *hair_pass, struct DRWPass *tf_pass, + struct GPUMaterial *material); + +void DRW_hair_free(void); + +/* pose_mode.c */ +bool DRW_pose_mode_armature( + struct Object *ob, struct Object *active_ob); + +#endif /* __DRAW_COMMON_H__ */ diff --git a/source/blender/draw/intern/draw_debug.c b/source/blender/draw/intern/draw_debug.c new file mode 100644 index 00000000000..0e4176f90a6 --- /dev/null +++ b/source/blender/draw/intern/draw_debug.c @@ -0,0 +1,151 @@ +/* + * Copyright 2018, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_debug.c + * \ingroup draw + * + * \brief Simple API to draw debug shapes in the viewport. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_object_types.h" + +#include "BLI_link_utils.h" + +#include "GPU_immediate.h" + +#include "draw_debug.h" +#include "draw_manager.h" + +/* --------- Register --------- */ + +/* Matrix applied to all points before drawing. Could be a stack if needed. */ +static float g_modelmat[4][4]; + +void DRW_debug_modelmat_reset(void) +{ + unit_m4(g_modelmat); +} + +void DRW_debug_modelmat(const float modelmat[4][4]) +{ + copy_m4_m4(g_modelmat, modelmat); +} + +void DRW_debug_line_v3v3(const float v1[3], const float v2[3], const float color[4]) +{ + DRWDebugLine *line = MEM_mallocN(sizeof(DRWDebugLine), "DRWDebugLine"); + mul_v3_m4v3(line->pos[0], g_modelmat, v1); + mul_v3_m4v3(line->pos[1], g_modelmat, v2); + copy_v4_v4(line->color, color); + BLI_LINKS_PREPEND(DST.debug.lines, line); +} + +void DRW_debug_polygon_v3(const float (*v)[3], const int vert_len, const float color[4]) +{ + BLI_assert(vert_len > 1); + + for (int i = 0; i < vert_len; ++i) { + DRW_debug_line_v3v3(v[i], v[(i + 1) % vert_len], color); + } +} + +/* NOTE: g_modelmat is still applied on top. */ +void DRW_debug_m4(const float m[4][4]) +{ + float v0[3] = {0.0f, 0.0f, 0.0f}; + float v1[3] = {1.0f, 0.0f, 0.0f}; + float v2[3] = {0.0f, 1.0f, 0.0f}; + float v3[3] = {0.0f, 0.0f, 1.0f}; + + mul_m4_v3(m, v0); + mul_m4_v3(m, v1); + mul_m4_v3(m, v2); + mul_m4_v3(m, v3); + + DRW_debug_line_v3v3(v0, v1, (float[4]){1.0f, 0.0f, 0.0f, 1.0f}); + DRW_debug_line_v3v3(v0, v2, (float[4]){0.0f, 1.0f, 0.0f, 1.0f}); + DRW_debug_line_v3v3(v0, v3, (float[4]){0.0f, 0.0f, 1.0f, 1.0f}); +} + +void DRW_debug_bbox(const BoundBox *bbox, const float color[4]) +{ + DRW_debug_line_v3v3(bbox->vec[0], bbox->vec[1], color); + DRW_debug_line_v3v3(bbox->vec[1], bbox->vec[2], color); + DRW_debug_line_v3v3(bbox->vec[2], bbox->vec[3], color); + DRW_debug_line_v3v3(bbox->vec[3], bbox->vec[0], color); + + DRW_debug_line_v3v3(bbox->vec[4], bbox->vec[5], color); + DRW_debug_line_v3v3(bbox->vec[5], bbox->vec[6], color); + DRW_debug_line_v3v3(bbox->vec[6], bbox->vec[7], color); + DRW_debug_line_v3v3(bbox->vec[7], bbox->vec[4], color); + + DRW_debug_line_v3v3(bbox->vec[0], bbox->vec[4], color); + DRW_debug_line_v3v3(bbox->vec[1], bbox->vec[5], color); + DRW_debug_line_v3v3(bbox->vec[2], bbox->vec[6], color); + DRW_debug_line_v3v3(bbox->vec[3], bbox->vec[7], color); +} + +/* --------- Render --------- */ + +static void drw_debug_draw_lines(void) +{ + int count = BLI_linklist_count((LinkNode *)DST.debug.lines); + + if (count == 0) { + return; + } + + Gwn_VertFormat *vert_format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + uint col = GWN_vertformat_attr_add(vert_format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBegin(GWN_PRIM_LINES, count * 2); + + while (DST.debug.lines) { + void *next = DST.debug.lines->next; + + immAttrib4fv(col, DST.debug.lines->color); + immVertex3fv(pos, DST.debug.lines->pos[0]); + + immAttrib4fv(col, DST.debug.lines->color); + immVertex3fv(pos, DST.debug.lines->pos[1]); + + MEM_freeN(DST.debug.lines); + DST.debug.lines = next; + } + immEnd(); + + immUnbindProgram(); +} + +void drw_debug_draw(void) +{ + drw_debug_draw_lines(); +} + +void drw_debug_init(void) +{ + DRW_debug_modelmat_reset(); +} diff --git a/source/blender/draw/intern/draw_debug.h b/source/blender/draw/intern/draw_debug.h new file mode 100644 index 00000000000..1dab431fc88 --- /dev/null +++ b/source/blender/draw/intern/draw_debug.h @@ -0,0 +1,39 @@ +/* + * Copyright 2018, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_debug.h + * \ingroup draw + */ + +#ifndef __DRAW_DEBUG_H__ +#define __DRAW_DEBUG_H__ + +struct BoundBox; + +void DRW_debug_modelmat_reset(void); +void DRW_debug_modelmat(const float modelmat[4][4]); + +void DRW_debug_line_v3v3(const float v1[3], const float v2[3], const float color[4]); +void DRW_debug_polygon_v3(const float (*v)[3], const int vert_len, const float color[4]); +void DRW_debug_m4(const float m[4][4]); +void DRW_debug_bbox(const BoundBox *bbox, const float color[4]); + +#endif /* __DRAW_DEBUG_H__ */ diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c new file mode 100644 index 00000000000..8cb9e0886a9 --- /dev/null +++ b/source/blender/draw/intern/draw_hair.c @@ -0,0 +1,167 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file draw_hair.c + * \ingroup draw + * + * \brief Contains procedural GPU hair drawing methods. + */ + +#include "DRW_render.h" + +#include "BLI_utildefines.h" +#include "BLI_string_utils.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_particle_types.h" +#include "DNA_customdata_types.h" + +#include "BKE_mesh.h" +#include "BKE_particle.h" +#include "BKE_pointcache.h" + +#include "ED_particle.h" + +#include "GPU_batch.h" +#include "GPU_shader.h" + +#include "draw_hair_private.h" + +typedef enum ParticleRefineShader { + PART_REFINE_CATMULL_ROM = 0, + PART_REFINE_MAX_SHADER, +} ParticleRefineShader; + +static GPUShader *g_refine_shaders[PART_REFINE_MAX_SHADER] = {NULL}; + +extern char datatoc_common_hair_lib_glsl[]; +extern char datatoc_common_hair_refine_vert_glsl[]; + +static GPUShader *hair_refine_shader_get(ParticleRefineShader sh) +{ + if (g_refine_shaders[sh]) { + return g_refine_shaders[sh]; + } + + char *vert_with_lib = BLI_string_joinN(datatoc_common_hair_lib_glsl, datatoc_common_hair_refine_vert_glsl); + + const char *var_names[1] = {"outData"}; + + g_refine_shaders[sh] = DRW_shader_create_with_transform_feedback(vert_with_lib, NULL, "#define HAIR_PHASE_SUBDIV\n", + GPU_SHADER_TFB_POINTS, var_names, 1); + + MEM_freeN(vert_with_lib); + + return g_refine_shaders[sh]; +} + +static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex( + Object *object, ParticleSystem *psys, ModifierData *md, + DRWPass *hair_pass, DRWPass *tf_pass, + struct GPUMaterial *gpu_mat, GPUShader *gpu_shader) +{ + /* TODO(fclem): Pass the scene as parameter */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + + int subdiv = scene->r.hair_subdiv; + int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2; + + ParticleHairCache *hair_cache; + ParticleSettings *part = psys->part; + bool need_ft_update = particles_ensure_procedural_data(object, psys, md, &hair_cache, subdiv, thickness_res); + + DRWShadingGroup *shgrp; + if (gpu_mat) { + shgrp = DRW_shgroup_material_create(gpu_mat, hair_pass); + } + else if (gpu_shader) { + shgrp = DRW_shgroup_create(gpu_shader, hair_pass); + } + else { + BLI_assert(0); + } + + /* TODO optimize this. Only bind the ones GPUMaterial needs. */ + for (int i = 0; i < hair_cache->num_uv_layers; ++i) { + for (int n = 0; hair_cache->uv_layer_names[i][n][0] != '\0'; ++n) { + DRW_shgroup_uniform_texture(shgrp, hair_cache->uv_layer_names[i][n], hair_cache->uv_tex[i]); + } + } + for (int i = 0; i < hair_cache->num_col_layers; ++i) { + for (int n = 0; hair_cache->col_layer_names[i][n][0] != '\0'; ++n) { + DRW_shgroup_uniform_texture(shgrp, hair_cache->col_layer_names[i][n], hair_cache->col_tex[i]); + } + } + + DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex); + DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); + DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res); + DRW_shgroup_uniform_float(shgrp, "hairRadShape", &part->shape, 1); + DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", part->rad_root * part->rad_scale * 0.5f); + DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", part->rad_tip * part->rad_scale * 0.5f); + DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0); + /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass culling test. */ + DRW_shgroup_call_object_add_no_cull(shgrp, hair_cache->final[subdiv].proc_hairs[thickness_res - 1], object); + + /* Transform Feedback subdiv. */ + if (need_ft_update) { + int final_points_ct = hair_cache->final[subdiv].strands_res * hair_cache->strands_count; + GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); + DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(tf_shader, tf_pass, + hair_cache->final[subdiv].proc_buf); + DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", hair_cache->point_tex); + DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex); + DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); + DRW_shgroup_call_procedural_points_add(tf_shgrp, final_points_ct, NULL); + } + + return shgrp; +} + +DRWShadingGroup *DRW_shgroup_hair_create( + Object *object, ParticleSystem *psys, ModifierData *md, + DRWPass *hair_pass, DRWPass *tf_pass, + GPUShader *shader) +{ + return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, tf_pass, NULL, shader); +} + +DRWShadingGroup *DRW_shgroup_material_hair_create( + Object *object, ParticleSystem *psys, ModifierData *md, + DRWPass *hair_pass, DRWPass *tf_pass, + struct GPUMaterial *material) +{ + return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, tf_pass, material, NULL); +} + +void DRW_hair_free(void) +{ + for (int i = 0; i < PART_REFINE_MAX_SHADER; ++i) { + DRW_SHADER_FREE_SAFE(g_refine_shaders[i]); + } +} diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h new file mode 100644 index 00000000000..2e6c9a0d3c1 --- /dev/null +++ b/source/blender/draw/intern/draw_hair_private.h @@ -0,0 +1,92 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file draw_hair_private.h + * \ingroup draw + */ + +#ifndef __DRAW_HAIR_PRIVATE_H__ +#define __DRAW_HAIR_PRIVATE_H__ + +#define MAX_LAYER_NAME_CT 3 /* u0123456789, u, a0123456789 */ +#define MAX_LAYER_NAME_LEN DECIMAL_DIGITS_BOUND(unsigned int) + 2 +#define MAX_THICKRES 2 /* see eHairType */ +#define MAX_HAIR_SUBDIV 4 /* see hair_subdiv rna */ + +struct Object; +struct ParticleSystem; +struct ModifierData; +struct ParticleHairCache; + +typedef struct ParticleHairFinalCache { + /* Output of the subdivision stage: vertex buff sized to subdiv level. */ + Gwn_VertBuf *proc_buf; + GPUTexture *proc_tex; + + /* Just contains a huge index buffer used to draw the final hair. */ + Gwn_Batch *proc_hairs[MAX_THICKRES]; + + int strands_res; /* points per hair, at least 2 */ +} ParticleHairFinalCache; + +typedef struct ParticleHairCache { + Gwn_VertBuf *pos; + Gwn_IndexBuf *indices; + Gwn_Batch *hairs; + + /* Hair Procedural display: Interpolation is done on the GPU. */ + Gwn_VertBuf *proc_point_buf; /* Input control points */ + GPUTexture *point_tex; + + Gwn_VertBuf *proc_strand_buf; /* Infos of control points strands (segment count and base index) */ + GPUTexture *strand_tex; + + Gwn_VertBuf *proc_uv_buf[MAX_MTFACE]; + GPUTexture *uv_tex[MAX_MTFACE]; + char uv_layer_names[MAX_MTFACE][MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN]; + + Gwn_VertBuf *proc_col_buf[MAX_MCOL]; + GPUTexture *col_tex[MAX_MCOL]; + char col_layer_names[MAX_MCOL][MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN]; + + int num_uv_layers; + int num_col_layers; + + ParticleHairFinalCache final[MAX_HAIR_SUBDIV]; + + int strands_count; + int elems_count; + int point_count; +} ParticleHairCache; + +bool particles_ensure_procedural_data( + struct Object *object, + struct ParticleSystem *psys, + struct ModifierData *md, + struct ParticleHairCache **r_hair_cache, + int subdiv, + int thickness_res); + +#endif /* __DRAW_HAIR_PRIVATE_H__ */ diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c new file mode 100644 index 00000000000..3e4f812af27 --- /dev/null +++ b/source/blender/draw/intern/draw_instance_data.c @@ -0,0 +1,436 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_instance_data.c + * \ingroup draw + */ + +/** + * DRW Instance Data Manager + * This is a special memory manager that keeps memory blocks ready to send as vbo data in one continuous allocation. + * This way we avoid feeding gawain each instance data one by one and unecessary memcpy. + * Since we loose which memory block was used each DRWShadingGroup we need to redistribute them in the same order/size + * to avoid to realloc each frame. + * This is why DRWInstanceDatas are sorted in a list for each different data size. + **/ + +#include "draw_instance_data.h" +#include "DRW_engine.h" +#include "DRW_render.h" /* For DRW_shgroup_get_instance_count() */ + +#include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" +#include "BLI_mempool.h" + +#define BUFFER_CHUNK_SIZE 32 +#define BUFFER_VERTS_CHUNK 32 + +typedef struct DRWBatchingBuffer { + struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */ + Gwn_VertFormat *format; /* Identifier. */ + Gwn_VertBuf *vert; /* Gwn_VertBuf contained in the Gwn_Batch. */ + Gwn_Batch *batch; /* Gwn_Batch containing the Gwn_VertBuf. */ +} DRWBatchingBuffer; + +typedef struct DRWInstancingBuffer { + struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */ + Gwn_VertFormat *format; /* Identifier. */ + Gwn_Batch *instance; /* Identifier. */ + Gwn_VertBuf *vert; /* Gwn_VertBuf contained in the Gwn_Batch. */ + Gwn_Batch *batch; /* Gwn_Batch containing the Gwn_VertBuf. */ +} DRWInstancingBuffer; + +typedef struct DRWInstanceChunk { + size_t cursor; /* Offset to the next instance data. */ + size_t alloc_size; /* Number of DRWBatchingBuffer/Batches alloc'd in ibufs/btchs. */ + union { + DRWBatchingBuffer *bbufs; + DRWInstancingBuffer *ibufs; + }; +} DRWInstanceChunk; + +struct DRWInstanceData { + struct DRWInstanceData *next; + bool used; /* If this data is used or not. */ + size_t data_size; /* Size of one instance data. */ + BLI_mempool *mempool; +}; + +struct DRWInstanceDataList { + struct DRWInstanceDataList *next, *prev; + /* Linked lists for all possible data pool size */ + DRWInstanceData *idata_head[MAX_INSTANCE_DATA_SIZE]; + DRWInstanceData *idata_tail[MAX_INSTANCE_DATA_SIZE]; + + DRWInstanceChunk instancing; + DRWInstanceChunk batching; +}; + +static ListBase g_idatalists = {NULL, NULL}; + +/* -------------------------------------------------------------------- */ + +/** \name Instance Buffer Management + * \{ */ + +/** + * This manager allows to distribute existing batches for instancing + * attributes. This reduce the number of batches creation. + * Querying a batch is done with a vertex format. This format should + * be static so that it's pointer never changes (because we are using + * this pointer as identifier [we don't want to check the full format + * that would be too slow]). + **/ + +static void instance_batch_free(Gwn_Batch *batch, void *UNUSED(user_data)) +{ + /* Free all batches that have the same key before they are reused. */ + /* TODO: Make it thread safe! Batch freeing can happen from another thread. */ + /* XXX we need to iterate over all idatalists unless we make some smart + * data structure to store the locations to update. */ + for (DRWInstanceDataList *idatalist = g_idatalists.first; idatalist; idatalist = idatalist->next) { + DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; + for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { + if (ibuf->instance == batch) { + BLI_assert(ibuf->shgroup == NULL); /* Make sure it has no other users. */ + GWN_VERTBUF_DISCARD_SAFE(ibuf->vert); + GWN_BATCH_DISCARD_SAFE(ibuf->batch); + /* Tag as non alloced. */ + ibuf->format = NULL; + } + } + } +} + +void DRW_batching_buffer_request( + DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_PrimType type, struct DRWShadingGroup *shgroup, + Gwn_Batch **r_batch, Gwn_VertBuf **r_vert) +{ + DRWInstanceChunk *chunk = &idatalist->batching; + DRWBatchingBuffer *bbuf = idatalist->batching.bbufs; + BLI_assert(format); + /* Search for an unused batch. */ + for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) { + if (bbuf->shgroup == NULL) { + if (bbuf->format == format) { + bbuf->shgroup = shgroup; + *r_batch = bbuf->batch; + *r_vert = bbuf->vert; + return; + } + } + } + int new_id = 0; /* Find insertion point. */ + for (; new_id < chunk->alloc_size; ++new_id) { + if (chunk->bbufs[new_id].format == NULL) + break; + } + /* If there is no batch left. Allocate more. */ + if (new_id == chunk->alloc_size) { + new_id = chunk->alloc_size; + chunk->alloc_size += BUFFER_CHUNK_SIZE; + chunk->bbufs = MEM_reallocN(chunk->bbufs, chunk->alloc_size * sizeof(DRWBatchingBuffer)); + memset(chunk->bbufs + new_id, 0, sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE); + } + /* Create the batch. */ + bbuf = chunk->bbufs + new_id; + bbuf->vert = *r_vert = GWN_vertbuf_create_with_format_ex(format, GWN_USAGE_DYNAMIC); + bbuf->batch = *r_batch = GWN_batch_create_ex(type, bbuf->vert, NULL, 0); + bbuf->format = format; + bbuf->shgroup = shgroup; + GWN_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK); +} + +void DRW_instancing_buffer_request( + DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_Batch *instance, struct DRWShadingGroup *shgroup, + Gwn_Batch **r_batch, Gwn_VertBuf **r_vert) +{ + DRWInstanceChunk *chunk = &idatalist->instancing; + DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; + BLI_assert(format); + /* Search for an unused batch. */ + for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { + if (ibuf->shgroup == NULL) { + if (ibuf->format == format) { + if (ibuf->instance == instance) { + ibuf->shgroup = shgroup; + *r_batch = ibuf->batch; + *r_vert = ibuf->vert; + return; + } + } + } + } + int new_id = 0; /* Find insertion point. */ + for (; new_id < chunk->alloc_size; ++new_id) { + if (chunk->ibufs[new_id].format == NULL) + break; + } + /* If there is no batch left. Allocate more. */ + if (new_id == chunk->alloc_size) { + new_id = chunk->alloc_size; + chunk->alloc_size += BUFFER_CHUNK_SIZE; + chunk->ibufs = MEM_reallocN(chunk->ibufs, chunk->alloc_size * sizeof(DRWInstancingBuffer)); + memset(chunk->ibufs + new_id, 0, sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE); + } + /* Create the batch. */ + ibuf = chunk->ibufs + new_id; + ibuf->vert = *r_vert = GWN_vertbuf_create_with_format_ex(format, GWN_USAGE_DYNAMIC); + ibuf->batch = *r_batch = GWN_batch_duplicate(instance); + ibuf->format = format; + ibuf->shgroup = shgroup; + ibuf->instance = instance; + GWN_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK); + GWN_batch_instbuf_set(ibuf->batch, ibuf->vert, false); + /* Make sure to free this ibuf if the instance batch gets free. */ + GWN_batch_callback_free_set(instance, &instance_batch_free, NULL); +} + +void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist) +{ + size_t realloc_size = 1; /* Avoid 0 size realloc. */ + /* Resize down buffers in use and send data to GPU & free unused buffers. */ + DRWInstanceChunk *batching = &idatalist->batching; + DRWBatchingBuffer *bbuf = batching->bbufs; + for (int i = 0; i < batching->alloc_size; i++, bbuf++) { + if (bbuf->shgroup != NULL) { + realloc_size = i + 1; + uint vert_ct = DRW_shgroup_get_instance_count(bbuf->shgroup); + vert_ct += (vert_ct == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */ + if (vert_ct + BUFFER_VERTS_CHUNK <= bbuf->vert->vertex_ct) { + uint size = vert_ct + BUFFER_VERTS_CHUNK - 1; + size = size - size % BUFFER_VERTS_CHUNK; + GWN_vertbuf_data_resize(bbuf->vert, size); + } + GWN_vertbuf_use(bbuf->vert); /* Send data. */ + bbuf->shgroup = NULL; /* Set as non used for the next round. */ + } + else { + GWN_VERTBUF_DISCARD_SAFE(bbuf->vert); + GWN_BATCH_DISCARD_SAFE(bbuf->batch); + bbuf->format = NULL; /* Tag as non alloced. */ + } + } + /* Rounding up to nearest chunk size. */ + realloc_size += BUFFER_CHUNK_SIZE - 1; + realloc_size -= realloc_size % BUFFER_CHUNK_SIZE; + /* Resize down if necessary. */ + if (realloc_size < batching->alloc_size) { + batching->alloc_size = realloc_size; + batching->ibufs = MEM_reallocN(batching->ibufs, realloc_size * sizeof(DRWBatchingBuffer)); + } + + realloc_size = 1; + /* Resize down buffers in use and send data to GPU & free unused buffers. */ + DRWInstanceChunk *instancing = &idatalist->instancing; + DRWInstancingBuffer *ibuf = instancing->ibufs; + for (int i = 0; i < instancing->alloc_size; i++, ibuf++) { + if (ibuf->shgroup != NULL) { + realloc_size = i + 1; + uint vert_ct = DRW_shgroup_get_instance_count(ibuf->shgroup); + vert_ct += (vert_ct == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */ + if (vert_ct + BUFFER_VERTS_CHUNK <= ibuf->vert->vertex_ct) { + uint size = vert_ct + BUFFER_VERTS_CHUNK - 1; + size = size - size % BUFFER_VERTS_CHUNK; + GWN_vertbuf_data_resize(ibuf->vert, size); + } + GWN_vertbuf_use(ibuf->vert); /* Send data. */ + ibuf->shgroup = NULL; /* Set as non used for the next round. */ + } + else { + GWN_VERTBUF_DISCARD_SAFE(ibuf->vert); + GWN_BATCH_DISCARD_SAFE(ibuf->batch); + ibuf->format = NULL; /* Tag as non alloced. */ + } + } + /* Rounding up to nearest chunk size. */ + realloc_size += BUFFER_CHUNK_SIZE - 1; + realloc_size -= realloc_size % BUFFER_CHUNK_SIZE; + /* Resize down if necessary. */ + if (realloc_size < instancing->alloc_size) { + instancing->alloc_size = realloc_size; + instancing->ibufs = MEM_reallocN(instancing->ibufs, realloc_size * sizeof(DRWInstancingBuffer)); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Instance Data (DRWInstanceData) + * \{ */ + +static DRWInstanceData *drw_instance_data_create(DRWInstanceDataList *idatalist, uint attrib_size) +{ + DRWInstanceData *idata = MEM_callocN(sizeof(DRWInstanceData), "DRWInstanceData"); + idata->next = NULL; + idata->used = true; + idata->data_size = attrib_size; + idata->mempool = BLI_mempool_create(sizeof(float) * idata->data_size, 0, 16, 0); + + BLI_assert(attrib_size > 0); + + /* Push to linked list. */ + if (idatalist->idata_head[attrib_size - 1] == NULL) { + idatalist->idata_head[attrib_size - 1] = idata; + } + else { + idatalist->idata_tail[attrib_size - 1]->next = idata; + } + idatalist->idata_tail[attrib_size - 1] = idata; + + return idata; +} + +static void DRW_instance_data_free(DRWInstanceData *idata) +{ + BLI_mempool_destroy(idata->mempool); +} + +/** + * Return a pointer to the next instance data space. + **/ +void *DRW_instance_data_next(DRWInstanceData *idata) +{ + return BLI_mempool_alloc(idata->mempool); +} + +DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint attrib_size) +{ + BLI_assert(attrib_size > 0 && attrib_size <= MAX_INSTANCE_DATA_SIZE); + + DRWInstanceData *idata = idatalist->idata_head[attrib_size - 1]; + + /* Search for an unused data chunk. */ + for (; idata; idata = idata->next) { + if (idata->used == false) { + idata->used = true; + return idata; + } + } + + return drw_instance_data_create(idatalist, attrib_size); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Instance Data List (DRWInstanceDataList) + * \{ */ + +DRWInstanceDataList *DRW_instance_data_list_create(void) +{ + DRWInstanceDataList *idatalist = MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList"); + idatalist->batching.bbufs = MEM_callocN(sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE, "DRWBatchingBuffers"); + idatalist->batching.alloc_size = BUFFER_CHUNK_SIZE; + idatalist->instancing.ibufs = MEM_callocN(sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE, "DRWInstancingBuffers"); + idatalist->instancing.alloc_size = BUFFER_CHUNK_SIZE; + + BLI_addtail(&g_idatalists, idatalist); + + return idatalist; +} + +void DRW_instance_data_list_free(DRWInstanceDataList *idatalist) +{ + DRWInstanceData *idata, *next_idata; + + for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { + for (idata = idatalist->idata_head[i]; idata; idata = next_idata) { + next_idata = idata->next; + DRW_instance_data_free(idata); + MEM_freeN(idata); + } + idatalist->idata_head[i] = NULL; + idatalist->idata_tail[i] = NULL; + } + + DRWBatchingBuffer *bbuf = idatalist->batching.bbufs; + for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) { + GWN_VERTBUF_DISCARD_SAFE(bbuf->vert); + GWN_BATCH_DISCARD_SAFE(bbuf->batch); + } + MEM_freeN(idatalist->batching.bbufs); + + DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; + for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { + GWN_VERTBUF_DISCARD_SAFE(ibuf->vert); + GWN_BATCH_DISCARD_SAFE(ibuf->batch); + } + MEM_freeN(idatalist->instancing.ibufs); + + BLI_remlink(&g_idatalists, idatalist); +} + +void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist) +{ + DRWInstanceData *idata; + + for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { + for (idata = idatalist->idata_head[i]; idata; idata = idata->next) { + idata->used = false; + } + } +} + +void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist) +{ + DRWInstanceData *idata, *next_idata; + + /* Remove unused data blocks and sanitize each list. */ + for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { + idatalist->idata_tail[i] = NULL; + for (idata = idatalist->idata_head[i]; idata; idata = next_idata) { + next_idata = idata->next; + if (idata->used == false) { + if (idatalist->idata_head[i] == idata) { + idatalist->idata_head[i] = next_idata; + } + else { + /* idatalist->idata_tail[i] is garanteed not to be null in this case. */ + idatalist->idata_tail[i]->next = next_idata; + } + DRW_instance_data_free(idata); + MEM_freeN(idata); + } + else { + if (idatalist->idata_tail[i] != NULL) { + idatalist->idata_tail[i]->next = idata; + } + idatalist->idata_tail[i] = idata; + } + } + } +} + +void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist) +{ + DRWInstanceData *idata; + + for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) { + for (idata = idatalist->idata_head[i]; idata; idata = idata->next) { + BLI_mempool_clear_ex(idata->mempool, BLI_mempool_len(idata->mempool)); + } + } +} + +/** \} */ diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h new file mode 100644 index 00000000000..86c4429a091 --- /dev/null +++ b/source/blender/draw/intern/draw_instance_data.h @@ -0,0 +1,59 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_instance_data.h + * \ingroup draw + */ + +#ifndef __DRAW_INSTANCE_DATA_H__ +#define __DRAW_INSTANCE_DATA_H__ + +#include "BLI_compiler_attrs.h" +#include "BLI_sys_types.h" + +#include "GPU_batch.h" + +#define MAX_INSTANCE_DATA_SIZE 48 /* Can be adjusted for more */ + +typedef struct DRWInstanceData DRWInstanceData; +typedef struct DRWInstanceDataList DRWInstanceDataList; + +struct DRWShadingGroup; + +void *DRW_instance_data_next(DRWInstanceData *idata); +DRWInstanceData *DRW_instance_data_request( + DRWInstanceDataList *idatalist, uint attrib_size); + +void DRW_batching_buffer_request( + DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_PrimType type, struct DRWShadingGroup *shgroup, + Gwn_Batch **r_batch, Gwn_VertBuf **r_vert); +void DRW_instancing_buffer_request( + DRWInstanceDataList *idatalist, Gwn_VertFormat *format, Gwn_Batch *instance, struct DRWShadingGroup *shgroup, + Gwn_Batch **r_batch, Gwn_VertBuf **r_vert); + +/* Upload all instance data to the GPU as soon as possible. */ +void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist); + +void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist); +void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist); +void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist); + +#endif /* __DRAW_INSTANCE_DATA_H__ */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c new file mode 100644 index 00000000000..2aa24ade1b2 --- /dev/null +++ b/source/blender/draw/intern/draw_manager.c @@ -0,0 +1,2215 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_manager.c + * \ingroup draw + */ + +#include <stdio.h> + +#include "BLI_listbase.h" +#include "BLI_mempool.h" +#include "BLI_rect.h" +#include "BLI_string.h" +#include "BLI_threads.h" + +#include "BLF_api.h" + +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_pointcache.h" +#include "BKE_workspace.h" + +#include "draw_manager.h" +#include "DNA_camera_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "ED_space_api.h" +#include "ED_screen.h" +#include "ED_particle.h" +#include "ED_view3d.h" + +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_framebuffer.h" +#include "GPU_immediate.h" +#include "GPU_uniformbuffer.h" +#include "GPU_viewport.h" +#include "GPU_matrix.h" + +#include "IMB_colormanagement.h" + +#include "RE_engine.h" +#include "RE_pipeline.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "WM_api.h" +#include "wm_window.h" + +#include "draw_manager_text.h" +#include "draw_manager_profiling.h" + +/* only for callbacks */ +#include "draw_cache_impl.h" + +#include "draw_mode_engines.h" +#include "engines/clay/clay_engine.h" +#include "engines/eevee/eevee_engine.h" +#include "engines/basic/basic_engine.h" +#include "engines/workbench/workbench_engine.h" +#include "engines/external/external_engine.h" + +#include "../../../intern/gawain/gawain/gwn_context.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#ifdef USE_GPU_SELECT +# include "GPU_select.h" +#endif + +/** Render State: No persistent data between draw calls. */ +DRWManager DST = {NULL}; + +ListBase DRW_engines = {NULL, NULL}; + +extern struct GPUUniformBuffer *view_ubo; /* draw_manager_exec.c */ + +static void drw_state_prepare_clean_for_draw(DRWManager *dst) +{ + memset(dst, 0x0, offsetof(DRWManager, ogl_context)); +} + +/* This function is used to reset draw manager to a state + * where we don't re-use data by accident across different + * draw calls. + */ +#ifdef DEBUG +static void drw_state_ensure_not_reused(DRWManager *dst) +{ + memset(dst, 0xff, offsetof(DRWManager, ogl_context)); +} +#endif + +/* -------------------------------------------------------------------- */ + +void DRW_draw_callbacks_pre_scene(void) +{ + RegionView3D *rv3d = DST.draw_ctx.rv3d; + + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); +} + +void DRW_draw_callbacks_post_scene(void) +{ + RegionView3D *rv3d = DST.draw_ctx.rv3d; + + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); +} + +struct DRWTextStore *DRW_text_cache_ensure(void) +{ + BLI_assert(DST.text_store_p); + if (*DST.text_store_p == NULL) { + *DST.text_store_p = DRW_text_cache_create(); + } + return *DST.text_store_p; +} + + +/* -------------------------------------------------------------------- */ + +/** \name Settings + * \{ */ + +bool DRW_object_is_renderable(Object *ob) +{ + BLI_assert(BKE_object_is_visible(ob, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE)); + + if (ob->type == OB_MESH) { + if (ob == DST.draw_ctx.object_edit) { + View3D *v3d = DST.draw_ctx.v3d; + const int mask = (V3D_OVERLAY_EDIT_OCCLUDE_WIRE | V3D_OVERLAY_EDIT_WEIGHT); + + if (v3d && v3d->overlay.edit_flag & mask) { + return false; + } + } + } + + return true; +} + +/** + * Return whether this object is visible depending if + * we are rendering or drawing in the viewport. + */ +bool DRW_check_object_visible_within_active_context(Object *ob) +{ + const eObjectVisibilityCheck mode = DRW_state_is_scene_render() ? + OB_VISIBILITY_CHECK_FOR_RENDER : + OB_VISIBILITY_CHECK_FOR_VIEWPORT; + return BKE_object_is_visible(ob, mode); +} + +bool DRW_object_is_flat_normal(const Object *ob) +{ + if (ob->type == OB_MESH) { + const Mesh *me = ob->data; + if (me->mpoly && me->mpoly[0].flag & ME_SMOOTH) { + return false; + } + } + return true; +} + +/** + * Return true if the object has its own draw mode. + * Caller must check this is active */ +int DRW_object_is_mode_shade(const Object *ob) +{ + BLI_assert(ob == DST.draw_ctx.obact); + UNUSED_VARS_NDEBUG(ob); + if ((DST.draw_ctx.object_mode & OB_MODE_EDIT) == 0) { + if ((DST.draw_ctx.object_mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) > 0) { + if (ELEM(DST.draw_ctx.v3d->drawtype, OB_MATERIAL, OB_RENDER)) { + return false; + } + else if ((DST.draw_ctx.v3d->flag2 & V3D_SHOW_MODE_SHADE_OVERRIDE) == 0) { + return true; + } + else { + return false; + } + } + } + return -1; +} + +int DRW_object_is_paint_mode(const Object *ob) +{ + if (ob == DST.draw_ctx.obact) { + if ((DST.draw_ctx.object_mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) > 0) { + return true; + } + } + return false; +} + +bool DRW_check_psys_visible_within_active_context( + Object *object, + struct ParticleSystem *psys) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene = draw_ctx->scene; + if (object == draw_ctx->object_edit) { + return false; + } + const ParticleSettings *part = psys->part; + const ParticleEditSettings *pset = &scene->toolsettings->particle; + if (object->mode == OB_MODE_PARTICLE_EDIT) { + if (psys_in_edit_mode(draw_ctx->depsgraph, psys)) { + if ((pset->flag & PE_DRAW_PART) == 0) { + return false; + } + if ((part->childtype == 0) && + (psys->flag & PSYS_HAIR_DYNAMICS && + psys->pointcache->flag & PTCACHE_BAKED) == 0) + { + return false; + } + } + } + return true; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Color Management + * \{ */ + +/* Use color management profile to draw texture to framebuffer */ +void DRW_transform_to_display(GPUTexture *tex) +{ + drw_state_set(DRW_STATE_WRITE_COLOR); + + Gwn_VertFormat *vert_format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + uint texco = GWN_vertformat_attr_add(vert_format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + const float dither = 1.0f; + + bool use_ocio = false; + + /* View transform is already applied for offscreen, don't apply again, see: T52046 */ + if (!(DST.options.is_image_render && !DST.options.is_scene_render)) { + Scene *scene = DST.draw_ctx.scene; + use_ocio = IMB_colormanagement_setup_glsl_draw_from_space( + &scene->view_settings, &scene->display_settings, NULL, dither, false); + } + + if (!use_ocio) { + /* View transform is already applied for offscreen, don't apply again, see: T52046 */ + if (DST.options.is_image_render && !DST.options.is_scene_render) { + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR); + immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f); + } + else { + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB); + } + immUniform1i("image", 0); + } + + GPU_texture_bind(tex, 0); /* OCIO texture bind point is 0 */ + + float mat[4][4]; + unit_m4(mat); + immUniformMatrix4fv("ModelViewProjectionMatrix", mat); + + /* Full screen triangle */ + immBegin(GWN_PRIM_TRIS, 3); + immAttrib2f(texco, 0.0f, 0.0f); + immVertex2f(pos, -1.0f, -1.0f); + + immAttrib2f(texco, 2.0f, 0.0f); + immVertex2f(pos, 3.0f, -1.0f); + + immAttrib2f(texco, 0.0f, 2.0f); + immVertex2f(pos, -1.0f, 3.0f); + immEnd(); + + GPU_texture_unbind(tex); + + if (use_ocio) { + IMB_colormanagement_finish_glsl_draw(); + } + else { + immUnbindProgram(); + } +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Multisample Resolve + * \{ */ + +/* Use manual multisample resolve pass. + * Much quicker than blitting back and forth. + * Assume destination fb is bound*/ +void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color) +{ + drw_state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL | + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); + + int samples = GPU_texture_samples(src_depth); + + BLI_assert(samples > 0); + BLI_assert(GPU_texture_samples(src_color) == samples); + + Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + + int builtin; + switch (samples) { + case 2: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2; break; + case 4: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_4; break; + case 8: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_8; break; + case 16: builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16; break; + default: + BLI_assert(0); + builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2; + break; + } + + GWN_batch_program_set_builtin(geom, builtin); + + GPU_texture_bind(src_depth, 0); + GPU_texture_bind(src_color, 1); + GWN_batch_uniform_1i(geom, "depthMulti", 0); + GWN_batch_uniform_1i(geom, "colorMulti", 1); + + float mat[4][4]; + unit_m4(mat); + GWN_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat); + + /* avoid gpuMatrix calls */ + GWN_batch_program_use_begin(geom); + GWN_batch_draw_range_ex(geom, 0, 0, false); + GWN_batch_program_use_end(geom); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Viewport (DRW_viewport) + * \{ */ + +void *drw_viewport_engine_data_ensure(void *engine_type) +{ + void *data = GPU_viewport_engine_data_get(DST.viewport, engine_type); + + if (data == NULL) { + data = GPU_viewport_engine_data_create(DST.viewport, engine_type); + } + return data; +} + +void DRW_engine_viewport_data_size_get( + const void *engine_type_v, + int *r_fbl_len, int *r_txl_len, int *r_psl_len, int *r_stl_len) +{ + const DrawEngineType *engine_type = engine_type_v; + + if (r_fbl_len) { + *r_fbl_len = engine_type->vedata_size->fbl_len; + } + if (r_txl_len) { + *r_txl_len = engine_type->vedata_size->txl_len; + } + if (r_psl_len) { + *r_psl_len = engine_type->vedata_size->psl_len; + } + if (r_stl_len) { + *r_stl_len = engine_type->vedata_size->stl_len; + } +} + +const float *DRW_viewport_size_get(void) +{ + return DST.size; +} + +const float *DRW_viewport_invert_size_get(void) +{ + return DST.inv_size; +} + +const float *DRW_viewport_screenvecs_get(void) +{ + return &DST.screenvecs[0][0]; +} + +const float *DRW_viewport_pixelsize_get(void) +{ + return &DST.pixsize; +} + +static void drw_viewport_cache_resize(void) +{ + /* Release the memiter before clearing the mempools that references them */ + GPU_viewport_cache_release(DST.viewport); + + if (DST.vmempool != NULL) { + BLI_mempool_clear_ex(DST.vmempool->calls, BLI_mempool_len(DST.vmempool->calls)); + BLI_mempool_clear_ex(DST.vmempool->states, BLI_mempool_len(DST.vmempool->states)); + BLI_mempool_clear_ex(DST.vmempool->shgroups, BLI_mempool_len(DST.vmempool->shgroups)); + BLI_mempool_clear_ex(DST.vmempool->uniforms, BLI_mempool_len(DST.vmempool->uniforms)); + BLI_mempool_clear_ex(DST.vmempool->passes, BLI_mempool_len(DST.vmempool->passes)); + } + + DRW_instance_data_list_free_unused(DST.idatalist); + DRW_instance_data_list_resize(DST.idatalist); +} + +/* Not a viewport variable, we could split this out. */ +static void drw_context_state_init(void) +{ + if (DST.draw_ctx.obact) { + DST.draw_ctx.object_mode = DST.draw_ctx.obact->mode; + } + else { + DST.draw_ctx.object_mode = OB_MODE_OBJECT; + } + + /* Edit object. */ + if (DST.draw_ctx.object_mode & OB_MODE_EDIT) { + DST.draw_ctx.object_edit = DST.draw_ctx.obact; + } + else { + DST.draw_ctx.object_edit = NULL; + } + + /* Pose object. */ + if (DST.draw_ctx.object_mode & OB_MODE_POSE) { + DST.draw_ctx.object_pose = DST.draw_ctx.obact; + } + else if (DST.draw_ctx.object_mode & OB_MODE_WEIGHT_PAINT) { + DST.draw_ctx.object_pose = BKE_object_pose_armature_get(DST.draw_ctx.obact); + } + else { + DST.draw_ctx.object_pose = NULL; + } +} + +/* It also stores viewport variable to an immutable place: DST + * This is because a cache uniform only store reference + * to its value. And we don't want to invalidate the cache + * if this value change per viewport */ +static void drw_viewport_var_init(void) +{ + RegionView3D *rv3d = DST.draw_ctx.rv3d; + /* Refresh DST.size */ + if (DST.viewport) { + int size[2]; + GPU_viewport_size_get(DST.viewport, size); + DST.size[0] = size[0]; + DST.size[1] = size[1]; + DST.inv_size[0] = 1.0f / size[0]; + DST.inv_size[1] = 1.0f / size[1]; + + DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(DST.viewport); + DST.default_framebuffer = fbl->default_fb; + + DST.vmempool = GPU_viewport_mempool_get(DST.viewport); + + if (DST.vmempool->calls == NULL) { + DST.vmempool->calls = BLI_mempool_create(sizeof(DRWCall), 0, 512, 0); + } + if (DST.vmempool->states == NULL) { + DST.vmempool->states = BLI_mempool_create(sizeof(DRWCallState), 0, 512, BLI_MEMPOOL_ALLOW_ITER); + } + if (DST.vmempool->shgroups == NULL) { + DST.vmempool->shgroups = BLI_mempool_create(sizeof(DRWShadingGroup), 0, 256, 0); + } + if (DST.vmempool->uniforms == NULL) { + DST.vmempool->uniforms = BLI_mempool_create(sizeof(DRWUniform), 0, 512, 0); + } + if (DST.vmempool->passes == NULL) { + DST.vmempool->passes = BLI_mempool_create(sizeof(DRWPass), 0, 64, 0); + } + + DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport); + DRW_instance_data_list_reset(DST.idatalist); + } + else { + DST.size[0] = 0; + DST.size[1] = 0; + + DST.inv_size[0] = 0; + DST.inv_size[1] = 0; + + DST.default_framebuffer = NULL; + DST.vmempool = NULL; + } + + if (rv3d != NULL) { + /* Refresh DST.screenvecs */ + copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]); + copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]); + normalize_v3(DST.screenvecs[0]); + normalize_v3(DST.screenvecs[1]); + + /* Refresh DST.pixelsize */ + DST.pixsize = rv3d->pixsize; + + copy_m4_m4(DST.original_mat.mat[DRW_MAT_PERS], rv3d->persmat); + copy_m4_m4(DST.original_mat.mat[DRW_MAT_PERSINV], rv3d->persinv); + copy_m4_m4(DST.original_mat.mat[DRW_MAT_VIEW], rv3d->viewmat); + copy_m4_m4(DST.original_mat.mat[DRW_MAT_VIEWINV], rv3d->viewinv); + copy_m4_m4(DST.original_mat.mat[DRW_MAT_WIN], rv3d->winmat); + invert_m4_m4(DST.original_mat.mat[DRW_MAT_WININV], rv3d->winmat); + + memcpy(DST.view_data.matstate.mat, DST.original_mat.mat, sizeof(DST.original_mat.mat)); + + copy_v4_v4(DST.view_data.viewcamtexcofac, rv3d->viewcamtexcofac); + } + else { + copy_v4_fl4(DST.view_data.viewcamtexcofac, 1.0f, 1.0f, 0.0f, 0.0f); + } + + /* Reset facing */ + DST.frontface = GL_CCW; + DST.backface = GL_CW; + glFrontFace(DST.frontface); + + if (DST.draw_ctx.object_edit) { + ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d); + } + + /* Alloc array of texture reference. */ + if (DST.RST.bound_texs == NULL) { + DST.RST.bound_texs = MEM_callocN(sizeof(GPUTexture *) * GPU_max_textures(), "Bound GPUTexture refs"); + } + if (DST.RST.bound_tex_slots == NULL) { + DST.RST.bound_tex_slots = MEM_callocN(sizeof(char) * GPU_max_textures(), "Bound Texture Slots"); + } + if (DST.RST.bound_ubos == NULL) { + DST.RST.bound_ubos = MEM_callocN(sizeof(GPUUniformBuffer *) * GPU_max_ubo_binds(), "Bound GPUUniformBuffer refs"); + } + if (DST.RST.bound_ubo_slots == NULL) { + DST.RST.bound_ubo_slots = MEM_callocN(sizeof(char) * GPU_max_ubo_binds(), "Bound Ubo Slots"); + } + + if (view_ubo == NULL) { + view_ubo = DRW_uniformbuffer_create(sizeof(ViewUboStorage), NULL); + } + + DST.override_mat = 0; + DST.dirty_mat = true; + DST.state_cache_id = 1; + + DST.clipping.updated = false; + + memset(DST.object_instance_data, 0x0, sizeof(DST.object_instance_data)); +} + +void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type) +{ + BLI_assert(type >= 0 && type < DRW_MAT_COUNT); + /* Can't use this in render mode. */ + BLI_assert(((DST.override_mat & (1 << type)) != 0) || DST.draw_ctx.rv3d != NULL); + + copy_m4_m4(mat, DST.view_data.matstate.mat[type]); +} + +void DRW_viewport_matrix_get_all(DRWMatrixState *state) +{ + memcpy(state, DST.view_data.matstate.mat, sizeof(DRWMatrixState)); +} + +void DRW_viewport_matrix_override_set(const float mat[4][4], DRWViewportMatrixType type) +{ + BLI_assert(type < DRW_MAT_COUNT); + copy_m4_m4(DST.view_data.matstate.mat[type], mat); + DST.override_mat |= (1 << type); + DST.dirty_mat = true; + DST.clipping.updated = false; +} + +void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type) +{ + BLI_assert(type < DRW_MAT_COUNT); + copy_m4_m4(DST.view_data.matstate.mat[type], DST.original_mat.mat[type]); + DST.override_mat &= ~(1 << type); + DST.dirty_mat = true; + DST.clipping.updated = false; +} + +void DRW_viewport_matrix_override_set_all(DRWMatrixState *state) +{ + memcpy(DST.view_data.matstate.mat, state, sizeof(DRWMatrixState)); + DST.override_mat = 0xFFFFFF; + DST.dirty_mat = true; + DST.clipping.updated = false; +} + +void DRW_viewport_matrix_override_unset_all(void) +{ + memcpy(DST.view_data.matstate.mat, DST.original_mat.mat, sizeof(DRWMatrixState)); + DST.override_mat = 0; + DST.dirty_mat = true; + DST.clipping.updated = false; +} + +bool DRW_viewport_is_persp_get(void) +{ + RegionView3D *rv3d = DST.draw_ctx.rv3d; + if (rv3d) { + return rv3d->is_persp; + } + else { + return DST.view_data.matstate.mat[DRW_MAT_WIN][3][3] == 0.0f; + } +} + +float DRW_viewport_near_distance_get(void) +{ + float projmat[4][4]; + DRW_viewport_matrix_get(projmat, DRW_MAT_WIN); + + if (DRW_viewport_is_persp_get()) { + return -projmat[3][2] / (projmat[2][2] - 1.0f); + } + else { + return -(projmat[3][2] + 1.0f) / projmat[2][2]; + } +} + +float DRW_viewport_far_distance_get(void) +{ + float projmat[4][4]; + DRW_viewport_matrix_get(projmat, DRW_MAT_WIN); + + if (DRW_viewport_is_persp_get()) { + return -projmat[3][2] / (projmat[2][2] + 1.0f); + } + else { + return -(projmat[3][2] - 1.0f) / projmat[2][2]; + } +} + +DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void) +{ + return GPU_viewport_framebuffer_list_get(DST.viewport); +} + +DefaultTextureList *DRW_viewport_texture_list_get(void) +{ + return GPU_viewport_texture_list_get(DST.viewport); +} + +void DRW_viewport_request_redraw(void) +{ + GPU_viewport_tag_update(DST.viewport); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ +/** \name ViewLayers (DRW_scenelayer) + * \{ */ + +void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type) +{ + for (ViewLayerEngineData *sled = DST.draw_ctx.view_layer->drawdata.first; sled; sled = sled->next) { + if (sled->engine_type == engine_type) { + return sled->storage; + } + } + return NULL; +} + +void **DRW_view_layer_engine_data_ensure_ex( + ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)) +{ + ViewLayerEngineData *sled; + + for (sled = view_layer->drawdata.first; sled; sled = sled->next) { + if (sled->engine_type == engine_type) { + return &sled->storage; + } + } + + sled = MEM_callocN(sizeof(ViewLayerEngineData), "ViewLayerEngineData"); + sled->engine_type = engine_type; + sled->free = callback; + BLI_addtail(&view_layer->drawdata, sled); + + return &sled->storage; +} + +void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*callback)(void *storage)) +{ + return DRW_view_layer_engine_data_ensure_ex(DST.draw_ctx.view_layer, engine_type, callback); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Objects (DRW_object) + * \{ */ + +ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type) +{ + for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) { + if (oed->engine_type == engine_type) { + return oed; + } + } + return NULL; +} + +ObjectEngineData *DRW_object_engine_data_ensure( + Object *ob, + DrawEngineType *engine_type, + size_t size, + ObjectEngineDataInitCb init_cb, + ObjectEngineDataFreeCb free_cb) +{ + BLI_assert(size >= sizeof(ObjectEngineData)); + /* Try to re-use existing data. */ + ObjectEngineData *oed = DRW_object_engine_data_get(ob, engine_type); + if (oed != NULL) { + return oed; + } + /* Allocate new data. */ + if ((ob->base_flag & BASE_FROMDUPLI) != 0) { + /* NOTE: data is not persistent in this case. It is reset each redraw. */ + BLI_assert(free_cb == NULL); /* No callback allowed. */ + /* Round to sizeof(float) for DRW_instance_data_request(). */ + const size_t t = sizeof(float) - 1; + size = (size + t) & ~t; + size_t fsize = size / sizeof(float); + if (DST.object_instance_data[fsize] == NULL) { + DST.object_instance_data[fsize] = DRW_instance_data_request(DST.idatalist, fsize); + } + oed = (ObjectEngineData *)DRW_instance_data_next(DST.object_instance_data[fsize]); + memset(oed, 0, size); + } + else { + oed = MEM_callocN(size, "ObjectEngineData"); + } + oed->engine_type = engine_type; + oed->free = free_cb; + /* Perform user-side initialization, if needed. */ + if (init_cb != NULL) { + init_cb(oed); + } + /* Register in the list. */ + BLI_addtail(&ob->drawdata, oed); + return oed; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Rendering (DRW_engines) + * \{ */ + +static void drw_engines_init(void) +{ + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + PROFILE_START(stime); + + if (engine->engine_init) { + engine->engine_init(data); + } + + PROFILE_END_UPDATE(data->init_time, stime); + } +} + +static void drw_engines_cache_init(void) +{ + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + + if (data->text_draw_cache) { + DRW_text_cache_destroy(data->text_draw_cache); + data->text_draw_cache = NULL; + } + if (DST.text_store_p == NULL) { + DST.text_store_p = &data->text_draw_cache; + } + + if (engine->cache_init) { + engine->cache_init(data); + } + } +} + +static void drw_engines_cache_populate(Object *ob) +{ + DST.ob_state = NULL; + + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + + if (engine->id_update) { + engine->id_update(data, &ob->id); + } + + if (engine->cache_populate) { + engine->cache_populate(data, ob); + } + } +} + +static void drw_engines_cache_finish(void) +{ + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + + if (engine->cache_finish) { + engine->cache_finish(data); + } + } +} + +static void drw_engines_draw_background(void) +{ + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + + if (engine->draw_background) { + PROFILE_START(stime); + + DRW_stats_group_start(engine->idname); + engine->draw_background(data); + DRW_stats_group_end(); + + PROFILE_END_UPDATE(data->background_time, stime); + return; + } + } + + /* No draw_background found, doing default background */ + if (DRW_state_draw_background()) { + DRW_draw_background(); + } +} + +static void drw_engines_draw_scene(void) +{ + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + PROFILE_START(stime); + + if (engine->draw_scene) { + DRW_stats_group_start(engine->idname); + engine->draw_scene(data); + /* Restore for next engine */ + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(DST.default_framebuffer); + } + DRW_stats_group_end(); + } + + PROFILE_END_UPDATE(data->render_time, stime); + } +} + +static void drw_engines_draw_text(void) +{ + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + PROFILE_START(stime); + + if (data->text_draw_cache) { + DRW_text_cache_draw(data->text_draw_cache, DST.draw_ctx.v3d, DST.draw_ctx.ar, false); + } + + PROFILE_END_UPDATE(data->render_time, stime); + } +} + +#define MAX_INFO_LINES 10 + +/** + * Returns the offset required for the drawing of engines info. + */ +int DRW_draw_region_engine_info_offset(void) +{ + int lines = 0; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + + /* Count the number of lines. */ + if (data->info[0] != '\0') { + lines++; + char *c = data->info; + while (*c++ != '\0') { + if (*c == '\n') { + lines++; + } + } + } + } + return MIN2(MAX_INFO_LINES, lines) * UI_UNIT_Y; +} + +/** + * Actual drawing; + */ +void DRW_draw_region_engine_info(void) +{ + const char *info_array_final[MAX_INFO_LINES + 1]; + /* This should be maxium number of engines running at the same time. */ + char info_array[MAX_INFO_LINES][GPU_INFO_SIZE]; + int i = 0; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + ARegion *ar = draw_ctx->ar; + float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; + + UI_GetThemeColor3fv(TH_HIGH_GRAD, fill_color); + mul_v3_fl(fill_color, fill_color[3]); + + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + + if (data->info[0] != '\0') { + char *chr_current = data->info; + char *chr_start = chr_current; + int line_len = 0; + + while (*chr_current++ != '\0') { + line_len++; + if (*chr_current == '\n') { + BLI_strncpy(info_array[i++], chr_start, line_len + 1); + /* Re-start counting. */ + chr_start = chr_current + 1; + line_len = -1; + } + } + + BLI_strncpy(info_array[i++], chr_start, line_len + 1); + + if (i >= MAX_INFO_LINES) { + break; + } + } + } + + for (int j = 0; j < i; j++) { + info_array_final[j] = info_array[j]; + } + info_array_final[i] = NULL; + + if (info_array[0] != NULL) { + ED_region_info_draw_multiline(ar, info_array_final, fill_color, true); + } +} + +#undef MAX_INFO_LINES + +static void use_drw_engine(DrawEngineType *engine) +{ + LinkData *ld = MEM_callocN(sizeof(LinkData), "enabled engine link data"); + ld->data = engine; + BLI_addtail(&DST.enabled_engines, ld); +} + +/** + * Use for external render engines. + */ +static void drw_engines_enable_external(void) +{ + use_drw_engine(DRW_engine_viewport_external_type.draw_engine); +} + +/* TODO revisit this when proper layering is implemented */ +/* Gather all draw engines needed and store them in DST.enabled_engines + * That also define the rendering order of engines */ +static void drw_engines_enable_from_engine(RenderEngineType *engine_type, int drawtype, int shading_flags) +{ + switch (drawtype) { + case OB_WIRE: + break; + + case OB_SOLID: + case OB_TEXTURE: + if (shading_flags & V3D_SHADING_XRAY) { + use_drw_engine(&draw_engine_workbench_transparent); + } + else { + use_drw_engine(&draw_engine_workbench_solid); + } + break; + + case OB_MATERIAL: + case OB_RENDER: + default: + /* TODO layers */ + if (engine_type->draw_engine != NULL) { + use_drw_engine(engine_type->draw_engine); + } + + if ((engine_type->flag & RE_INTERNAL) == 0) { + drw_engines_enable_external(); + } + break; + } +} + +static void drw_engines_enable_from_object_mode(void) +{ + use_drw_engine(&draw_engine_object_type); +} + +static void drw_engines_enable_from_mode(int mode) +{ + switch (mode) { + case CTX_MODE_EDIT_MESH: + use_drw_engine(&draw_engine_edit_mesh_type); + break; + case CTX_MODE_EDIT_CURVE: + use_drw_engine(&draw_engine_edit_curve_type); + break; + case CTX_MODE_EDIT_SURFACE: + use_drw_engine(&draw_engine_edit_surface_type); + break; + case CTX_MODE_EDIT_TEXT: + use_drw_engine(&draw_engine_edit_text_type); + break; + case CTX_MODE_EDIT_ARMATURE: + use_drw_engine(&draw_engine_edit_armature_type); + break; + case CTX_MODE_EDIT_METABALL: + use_drw_engine(&draw_engine_edit_metaball_type); + break; + case CTX_MODE_EDIT_LATTICE: + use_drw_engine(&draw_engine_edit_lattice_type); + break; + case CTX_MODE_POSE: + use_drw_engine(&draw_engine_pose_type); + break; + case CTX_MODE_SCULPT: + use_drw_engine(&draw_engine_sculpt_type); + break; + case CTX_MODE_PAINT_WEIGHT: + use_drw_engine(&draw_engine_pose_type); + use_drw_engine(&draw_engine_paint_weight_type); + break; + case CTX_MODE_PAINT_VERTEX: + use_drw_engine(&draw_engine_paint_vertex_type); + break; + case CTX_MODE_PAINT_TEXTURE: + use_drw_engine(&draw_engine_paint_texture_type); + break; + case CTX_MODE_PARTICLE: + use_drw_engine(&draw_engine_particle_type); + break; + case CTX_MODE_OBJECT: + break; + default: + BLI_assert(!"Draw mode invalid"); + break; + } +} + +static void drw_engines_enable_from_overlays(int overlay_flag) +{ + if (overlay_flag) { + use_drw_engine(&draw_engine_overlay_type); + } +} +/** + * Use for select and depth-drawing. + */ +static void drw_engines_enable_basic(void) +{ + use_drw_engine(DRW_engine_viewport_basic_type.draw_engine); +} + +static void drw_engines_enable(ViewLayer *view_layer, RenderEngineType *engine_type) +{ + Object *obact = OBACT(view_layer); + const int mode = CTX_data_mode_enum_ex(DST.draw_ctx.object_edit, obact, DST.draw_ctx.object_mode); + View3D * v3d = DST.draw_ctx.v3d; + const int drawtype = v3d->drawtype; + + drw_engines_enable_from_engine(engine_type, drawtype, v3d->shading.flag); + + if (DRW_state_draw_support()) { + drw_engines_enable_from_overlays(v3d->overlay.flag); + drw_engines_enable_from_object_mode(); + drw_engines_enable_from_mode(mode); + } +} + +static void drw_engines_disable(void) +{ + BLI_freelistN(&DST.enabled_engines); +} + +static uint DRW_engines_get_hash(void) +{ + uint hash = 0; + /* The cache depends on enabled engines */ + /* FIXME : if collision occurs ... segfault */ + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + hash += BLI_ghashutil_strhash_p(engine->idname); + } + + return hash; +} + +/* -------------------------------------------------------------------- */ + +/** \name View Update + * \{ */ + +void DRW_notify_view_update(const DRWUpdateContext *update_ctx) +{ + RenderEngineType *engine_type = update_ctx->engine_type; + ARegion *ar = update_ctx->ar; + View3D *v3d = update_ctx->v3d; + RegionView3D *rv3d = ar->regiondata; + Depsgraph *depsgraph = update_ctx->depsgraph; + Scene *scene = update_ctx->scene; + ViewLayer *view_layer = update_ctx->view_layer; + + /* Separate update for each stereo view. */ + for (int view = 0; view < 2; view++) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, view); + if (!viewport) { + continue; + } + + /* XXX Really nasty locking. But else this could + * be executed by the material previews thread + * while rendering a viewport. */ + BLI_mutex_lock(&DST.ogl_context_mutex); + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + + DST.viewport = viewport; + DST.draw_ctx = (DRWContextState){ + .ar = ar, .rv3d = rv3d, .v3d = v3d, + .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer), + .engine_type = engine_type, + .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT, + }; + + drw_engines_enable(view_layer, engine_type); + + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *draw_engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine); + + if (draw_engine->view_update) { + draw_engine->view_update(data); + } + } + + DST.viewport = NULL; + + drw_engines_disable(); + + BLI_mutex_unlock(&DST.ogl_context_mutex); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Main Draw Loops (DRW_draw) + * \{ */ + +/* Everything starts here. + * This function takes care of calling all cache and rendering functions + * for each relevant engine / mode engine. */ +void DRW_draw_view(const bContext *C) +{ + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = DEG_get_evaluated_scene(depsgraph); + RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); + GPUViewport *viewport = WM_draw_region_get_bound_viewport(ar); + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C); +} + +/** + * Used for both regular and off-screen drawing. + * Need to reset DST before calling this function + */ +void DRW_draw_render_loop_ex( + struct Depsgraph *depsgraph, + RenderEngineType *engine_type, + ARegion *ar, View3D *v3d, + GPUViewport *viewport, + const bContext *evil_C) +{ + + Scene *scene = DEG_get_evaluated_scene(depsgraph); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + RegionView3D *rv3d = ar->regiondata; + + DST.draw_ctx.evil_C = evil_C; + + DST.viewport = viewport; + v3d->zbuf = true; + + /* Setup viewport */ + GPU_viewport_engines_data_validate(DST.viewport, DRW_engines_get_hash()); + + DST.draw_ctx = (DRWContextState){ + .ar = ar, .rv3d = rv3d, .v3d = v3d, + .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer), + .engine_type = engine_type, + .depsgraph = depsgraph, + + /* reuse if caller sets */ + .evil_C = DST.draw_ctx.evil_C, + }; + drw_context_state_init(); + drw_viewport_var_init(); + + /* Get list of enabled engines */ + drw_engines_enable(view_layer, engine_type); + + /* Update ubos */ + DRW_globals_update(); + + drw_debug_init(); + + /* No framebuffer allowed before drawing. */ + BLI_assert(GPU_framebuffer_current_get() == 0); + + /* Init engines */ + drw_engines_init(); + + /* Cache filling */ + { + PROFILE_START(stime); + drw_engines_cache_init(); + + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob, DRW_iterator_mode_get()) + { + drw_engines_cache_populate(ob); + } + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END; + + drw_engines_cache_finish(); + + DRW_render_instance_buffer_finish(); + +#ifdef USE_PROFILE + double *cache_time = GPU_viewport_cache_time_get(DST.viewport); + PROFILE_END_UPDATE(*cache_time, stime); +#endif + } + + DRW_stats_begin(); + + GPU_framebuffer_bind(DST.default_framebuffer); + + /* Start Drawing */ + DRW_state_reset(); + + drw_engines_draw_background(); + + /* WIP, single image drawn over the camera view (replace) */ + bool do_bg_image = false; + if (rv3d->persp == RV3D_CAMOB) { + Object *cam_ob = v3d->camera; + if (cam_ob && cam_ob->type == OB_CAMERA) { + Camera *cam = cam_ob->data; + if (!BLI_listbase_is_empty(&cam->bg_images)) { + do_bg_image = true; + } + } + } + + if (do_bg_image) { + ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, false, true); + } + + + DRW_draw_callbacks_pre_scene(); + if (DST.draw_ctx.evil_C) { + ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_PRE_VIEW); + } + + drw_engines_draw_scene(); + + DRW_draw_callbacks_post_scene(); + if (DST.draw_ctx.evil_C) { + ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_POST_VIEW); + } + + DRW_state_reset(); + + drw_debug_draw(); + + drw_engines_draw_text(); + + if (DST.draw_ctx.evil_C) { + /* needed so manipulator isn't obscured */ + glDisable(GL_DEPTH_TEST); + DRW_draw_manipulator_3d(); + + DRW_draw_region_info(); + + /* Draw 2D after region info so we can draw on top of the camera passepartout overlay. + * 'DRW_draw_region_info' sets the projection in pixel-space. */ + DRW_draw_manipulator_2d(); + glEnable(GL_DEPTH_TEST); + } + + DRW_stats_reset(); + + if (do_bg_image) { + ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, true, true); + } + + if (G.debug_value > 20) { + glDisable(GL_DEPTH_TEST); + rcti rect; /* local coordinate visible rect inside region, to accomodate overlapping ui */ + ED_region_visible_rect(DST.draw_ctx.ar, &rect); + DRW_stats_draw(&rect); + glEnable(GL_DEPTH_TEST); + } + + if (WM_draw_region_get_bound_viewport(ar)) { + /* Don't unbind the framebuffer yet in this case and let + * GPU_viewport_unbind do it, so that we can still do further + * drawing of action zones on top. */ + } + else { + GPU_framebuffer_restore(); + } + + DRW_state_reset(); + drw_engines_disable(); + + drw_viewport_cache_resize(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif +} + +void DRW_draw_render_loop( + struct Depsgraph *depsgraph, + ARegion *ar, View3D *v3d, + GPUViewport *viewport) +{ + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + + Scene *scene = DEG_get_evaluated_scene(depsgraph); + RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); + + DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, NULL); +} + +/* @viewport CAN be NULL, in this case we create one. */ +void DRW_draw_render_loop_offscreen( + struct Depsgraph *depsgraph, RenderEngineType *engine_type, + ARegion *ar, View3D *v3d, + const bool draw_background, GPUOffScreen *ofs, + GPUViewport *viewport) +{ + /* Create temporary viewport if needed. */ + GPUViewport *render_viewport = viewport; + if (viewport == NULL) { + render_viewport = GPU_viewport_create_from_offscreen(ofs); + } + + GPU_framebuffer_restore(); + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + DST.options.is_image_render = true; + DST.options.draw_background = draw_background; + DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, render_viewport, NULL); + + /* Free temporary viewport. */ + if (viewport == NULL) { + /* don't free data owned by 'ofs' */ + GPU_viewport_clear_from_offscreen(render_viewport); + GPU_viewport_free(render_viewport); + } + + /* we need to re-bind (annoying!) */ + GPU_offscreen_bind(ofs, false); +} + +void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + RenderEngineType *engine_type = engine->type; + DrawEngineType *draw_engine_type = engine_type->draw_engine; + RenderData *r = &scene->r; + Render *render = engine->re; + + if (G.background && DST.ogl_context == NULL) { + WM_init_opengl(); + } + + /* Changing Context */ + DRW_opengl_context_enable(); + /* IMPORTANT: We dont support immediate mode in render mode! + * This shall remain in effect until immediate mode supports + * multiple threads. */ + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + DST.options.is_image_render = true; + DST.options.is_scene_render = true; + DST.options.draw_background = scene->r.alphamode == R_ADDSKY; + + DST.draw_ctx = (DRWContextState){ + .scene = scene, .view_layer = view_layer, + .engine_type = engine_type, + .depsgraph = depsgraph, .object_mode = OB_MODE_OBJECT, + }; + drw_context_state_init(); + + DST.viewport = GPU_viewport_create(); + const int size[2] = {(r->size * r->xsch) / 100, (r->size * r->ysch) / 100}; + GPU_viewport_size_set(DST.viewport, size); + + drw_viewport_var_init(); + + ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type); + + /* set default viewport */ + glViewport(0, 0, size[0], size[1]); + + /* Main rendering. */ + rctf view_rect; + rcti render_rect; + RE_GetViewPlane(render, &view_rect, &render_rect); + if (BLI_rcti_is_empty(&render_rect)) { + BLI_rcti_init(&render_rect, 0, size[0], 0, size[1]); + } + + /* Init render result. */ + RenderResult *render_result = RE_engine_begin_result( + engine, + 0, + 0, + (int)size[0], + (int)size[1], + view_layer->name, + /* RR_ALL_VIEWS */ NULL); + + RenderLayer *render_layer = render_result->layers.first; + for (RenderView *render_view = render_result->views.first; + render_view != NULL; + render_view = render_view->next) + { + RE_SetActiveRenderView(render, render_view->name); + engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect); + DST.buffer_finish_called = false; + } + + RE_engine_end_result(engine, render_result, false, false, false); + + /* Force cache to reset. */ + drw_viewport_cache_resize(); + + /* TODO grease pencil */ + + GPU_viewport_free(DST.viewport); + GPU_framebuffer_restore(); + + /* Changing Context */ + DRW_opengl_context_disable(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif +} + +void DRW_render_object_iter( + void *vedata, RenderEngine *engine, struct Depsgraph *depsgraph, + void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph)) +{ + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob, DRW_iterator_mode_get()) + { + DST.ob_state = NULL; + callback(vedata, ob, engine, depsgraph); + } + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END +} + +static struct DRWSelectBuffer { + struct GPUFrameBuffer *framebuffer; + struct GPUTexture *texture_depth; +} g_select_buffer = {NULL}; + +static void draw_select_framebuffer_setup(const rcti *rect) +{ + if (g_select_buffer.framebuffer == NULL) { + g_select_buffer.framebuffer = GPU_framebuffer_create(); + } + + /* If size mismatch recreate the texture. */ + if ((g_select_buffer.texture_depth != NULL) && + ((GPU_texture_width(g_select_buffer.texture_depth) != BLI_rcti_size_x(rect)) || + (GPU_texture_height(g_select_buffer.texture_depth) != BLI_rcti_size_y(rect)))) + { + GPU_texture_free(g_select_buffer.texture_depth); + g_select_buffer.texture_depth = NULL; + } + + if (g_select_buffer.texture_depth == NULL) { + g_select_buffer.texture_depth = GPU_texture_create_2D( + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), GPU_DEPTH_COMPONENT24, NULL, NULL); + + GPU_framebuffer_texture_attach(g_select_buffer.framebuffer, g_select_buffer.texture_depth, 0, 0); + + if (!GPU_framebuffer_check_valid(g_select_buffer.framebuffer, NULL)) { + printf("Error invalid selection framebuffer\n"); + } + } +} + +/* Must run after all instance datas have been added. */ +void DRW_render_instance_buffer_finish(void) +{ + BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!"); + DST.buffer_finish_called = true; + DRW_instance_buffer_finish(DST.idatalist); +} + +/** + * object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing). + */ +void DRW_draw_select_loop( + struct Depsgraph *depsgraph, + ARegion *ar, View3D *v3d, + bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti *rect, + DRW_SelectPassFn select_pass_fn, void *select_pass_user_data) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + Object *obact = OBACT(view_layer); + Object *obedit = OBEDIT_FROM_OBACT(obact); +#ifndef USE_GPU_SELECT + UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect); +#else + RegionView3D *rv3d = ar->regiondata; + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + + bool use_obedit = false; + int obedit_mode = 0; + if (obedit != NULL) { + if (obedit->type == OB_MBALL) { + use_obedit = true; + obedit_mode = CTX_MODE_EDIT_METABALL; + } + else if (obedit->type == OB_ARMATURE) { + use_obedit = true; + obedit_mode = CTX_MODE_EDIT_ARMATURE; + } + } + if (v3d->overlay.flag &= V3D_OVERLAY_BONE_SELECTION) { + if (!(v3d->flag2 &= V3D_RENDER_OVERRIDE)) { + Object *obpose = OBPOSE_FROM_OBACT(obact); + if (obpose) { + use_obedit = true; + obedit_mode = CTX_MODE_POSE; + } + } + } + + struct GPUViewport *viewport = GPU_viewport_create(); + GPU_viewport_size_set(viewport, (const int[2]){BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)}); + + DST.viewport = viewport; + v3d->zbuf = true; + + DST.options.is_select = true; + + /* Get list of enabled engines */ + if (use_obedit) { + drw_engines_enable_from_mode(obedit_mode); + } + else { + drw_engines_enable_basic(); + drw_engines_enable_from_object_mode(); + } + + /* Setup viewport */ + + /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ + DST.draw_ctx = (DRWContextState){ + .ar = ar, .rv3d = rv3d, .v3d = v3d, + .scene = scene, .view_layer = view_layer, .obact = obact, + .engine_type = engine_type, + .depsgraph = depsgraph, + }; + drw_context_state_init(); + drw_viewport_var_init(); + + /* Update ubos */ + DRW_globals_update(); + + /* Init engines */ + drw_engines_init(); + + { + drw_engines_cache_init(); + + if (use_obedit) { +#if 0 + drw_engines_cache_populate(obact); +#else + FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, obact->mode, ob_iter) { + drw_engines_cache_populate(ob_iter); + } + FOREACH_OBJECT_IN_MODE_END; +#endif + } + else { + DEG_OBJECT_ITER_BEGIN( + depsgraph, ob, DRW_iterator_mode_get(), + DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI) + { + if ((ob->base_flag & BASE_SELECTABLED) != 0) { + DRW_select_load_id(ob->select_color); + drw_engines_cache_populate(ob); + } + } + DEG_OBJECT_ITER_END; + } + + drw_engines_cache_finish(); + + DRW_render_instance_buffer_finish(); + } + + /* Setup framebuffer */ + draw_select_framebuffer_setup(rect); + GPU_framebuffer_bind(g_select_buffer.framebuffer); + GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f); + + /* Start Drawing */ + DRW_state_reset(); + DRW_draw_callbacks_pre_scene(); + + DRW_state_lock( + DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_ALWAYS | + DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_DEPTH_EQUAL | + DRW_STATE_DEPTH_GREATER | + DRW_STATE_DEPTH_ALWAYS); + + /* Only 1-2 passes. */ + while (true) { + if (!select_pass_fn(DRW_SELECT_PASS_PRE, select_pass_user_data)) { + break; + } + + drw_engines_draw_scene(); + + if (!select_pass_fn(DRW_SELECT_PASS_POST, select_pass_user_data)) { + break; + } + } + + DRW_state_lock(0); + + DRW_draw_callbacks_post_scene(); + + DRW_state_reset(); + drw_engines_disable(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif + GPU_framebuffer_restore(); + + /* Cleanup for selection state */ + GPU_viewport_free(viewport); +#endif /* USE_GPU_SELECT */ +} + +static void draw_depth_texture_to_screen(GPUTexture *texture) +{ + const float w = (float)GPU_texture_width(texture); + const float h = (float)GPU_texture_height(texture); + + Gwn_VertFormat *format = immVertexFormat(); + uint texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH_COPY); + + GPU_texture_bind(texture, 0); + + immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ + + immBegin(GWN_PRIM_TRI_STRIP, 4); + + immAttrib2f(texcoord, 0.0f, 0.0f); + immVertex2f(pos, 0.0f, 0.0f); + + immAttrib2f(texcoord, 1.0f, 0.0f); + immVertex2f(pos, w, 0.0f); + + immAttrib2f(texcoord, 0.0f, 1.0f); + immVertex2f(pos, 0.0f, h); + + immAttrib2f(texcoord, 1.0f, 1.0f); + immVertex2f(pos, w, h); + + immEnd(); + + GPU_texture_unbind(texture); + + immUnbindProgram(); +} + +/** + * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing). + */ +void DRW_draw_depth_loop( + Depsgraph *depsgraph, + ARegion *ar, View3D *v3d) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->drawtype); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + RegionView3D *rv3d = ar->regiondata; + + DRW_opengl_context_enable(); + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + + struct GPUViewport *viewport = GPU_viewport_create(); + GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy}); + + /* Setup framebuffer */ + draw_select_framebuffer_setup(&ar->winrct); + GPU_framebuffer_bind(g_select_buffer.framebuffer); + GPU_framebuffer_clear_depth(g_select_buffer.framebuffer, 1.0f); + + bool cache_is_dirty; + DST.viewport = viewport; + v3d->zbuf = true; + + DST.options.is_depth = true; + + /* Get list of enabled engines */ + { + drw_engines_enable_basic(); + drw_engines_enable_from_object_mode(); + } + + /* Setup viewport */ + cache_is_dirty = true; + + /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ + DST.draw_ctx = (DRWContextState){ + .ar = ar, .rv3d = rv3d, .v3d = v3d, + .scene = scene, .view_layer = view_layer, .obact = OBACT(view_layer), + .engine_type = engine_type, + .depsgraph = depsgraph, + }; + drw_context_state_init(); + drw_viewport_var_init(); + + /* Update ubos */ + DRW_globals_update(); + + /* Init engines */ + drw_engines_init(); + + /* TODO : tag to refresh by the dependency graph */ + /* ideally only refresh when objects are added/removed */ + /* or render properties / materials change */ + if (cache_is_dirty) { + drw_engines_cache_init(); + + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob, DRW_iterator_mode_get()) + { + drw_engines_cache_populate(ob); + } + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END; + + drw_engines_cache_finish(); + + DRW_render_instance_buffer_finish(); + } + + /* Start Drawing */ + DRW_state_reset(); + DRW_draw_callbacks_pre_scene(); + drw_engines_draw_scene(); + DRW_draw_callbacks_post_scene(); + + DRW_state_reset(); + drw_engines_disable(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif + + /* TODO: Reading depth for operators should be done here. */ + + GPU_framebuffer_restore(); + + /* Cleanup for selection state */ + GPU_viewport_free(viewport); + + /* Changin context */ + DRW_opengl_context_disable(); + + /* XXX Drawing the resulting buffer to the BACK_BUFFER */ + gpuPushMatrix(); + gpuPushProjectionMatrix(); + wmOrtho2_region_pixelspace(ar); + gpuLoadIdentity(); + + glEnable(GL_DEPTH_TEST); /* Cannot write to depth buffer without testing */ + glDepthFunc(GL_ALWAYS); + draw_depth_texture_to_screen(g_select_buffer.texture_depth); + glDepthFunc(GL_LEQUAL); + + gpuPopMatrix(); + gpuPopProjectionMatrix(); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Draw Manager State (DRW_state) + * \{ */ + +void DRW_state_dfdy_factors_get(float dfdyfac[2]) +{ + GPU_get_dfdy_factors(dfdyfac); +} + +/** + * When false, drawing doesn't output to a pixel buffer + * eg: Occlusion queries, or when we have setup a context to draw in already. + */ +bool DRW_state_is_fbo(void) +{ + return ((DST.default_framebuffer != NULL) || DST.options.is_image_render); +} + +/** + * For when engines need to know if this is drawing for selection or not. + */ +bool DRW_state_is_select(void) +{ + return DST.options.is_select; +} + +bool DRW_state_is_depth(void) +{ + return DST.options.is_depth; +} + +/** + * Whether we are rendering for an image + */ +bool DRW_state_is_image_render(void) +{ + return DST.options.is_image_render; +} + +/** + * Whether we are rendering only the render engine, + * or if we should also render the mode engines. + */ +bool DRW_state_is_scene_render(void) +{ + BLI_assert(DST.options.is_scene_render ? + DST.options.is_image_render : true); + return DST.options.is_scene_render; +} + +/** +* Whether we are rendering simple opengl render +*/ +bool DRW_state_is_opengl_render(void) +{ + return DST.options.is_image_render && !DST.options.is_scene_render; +} + +/** + * Gives you the iterator mode to use for depsgraph. + */ +eDepsObjectIteratorMode DRW_iterator_mode_get(void) +{ + return DRW_state_is_scene_render() ? DEG_ITER_OBJECT_MODE_RENDER : + DEG_ITER_OBJECT_MODE_VIEWPORT; +} + +/** + * Should text draw in this mode? + */ +bool DRW_state_show_text(void) +{ + return (DST.options.is_select) == 0 && + (DST.options.is_depth) == 0 && + (DST.options.is_scene_render) == 0; +} + +/** + * Should draw support elements + * Objects center, selection outline, probe data, ... + */ +bool DRW_state_draw_support(void) +{ + View3D *v3d = DST.draw_ctx.v3d; + return (DRW_state_is_scene_render() == false) && + (v3d != NULL) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0); +} + +/** + * Whether we should render the background + */ +bool DRW_state_draw_background(void) +{ + if (DRW_state_is_image_render() == false) { + return true; + } + return DST.options.draw_background; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Context State (DRW_context_state) + * \{ */ + +const DRWContextState *DRW_context_state_get(void) +{ + return &DST.draw_ctx; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Init/Exit (DRW_engines) + * \{ */ + +bool DRW_engine_render_support(DrawEngineType *draw_engine_type) +{ + return draw_engine_type->render_to_image; +} + +void DRW_engine_register(DrawEngineType *draw_engine_type) +{ + BLI_addtail(&DRW_engines, draw_engine_type); +} + +void DRW_engines_register(void) +{ +#ifdef WITH_CLAY_ENGINE + RE_engines_register(&DRW_engine_viewport_clay_type); +#endif + RE_engines_register(&DRW_engine_viewport_eevee_type); + RE_engines_register(&DRW_engine_viewport_workbench_type); + + DRW_engine_register(&draw_engine_workbench_solid); + DRW_engine_register(&draw_engine_workbench_transparent); + + DRW_engine_register(&draw_engine_object_type); + DRW_engine_register(&draw_engine_edit_armature_type); + DRW_engine_register(&draw_engine_edit_curve_type); + DRW_engine_register(&draw_engine_edit_lattice_type); + DRW_engine_register(&draw_engine_edit_mesh_type); + DRW_engine_register(&draw_engine_edit_metaball_type); + DRW_engine_register(&draw_engine_edit_surface_type); + DRW_engine_register(&draw_engine_edit_text_type); + DRW_engine_register(&draw_engine_overlay_type); + DRW_engine_register(&draw_engine_paint_texture_type); + DRW_engine_register(&draw_engine_paint_vertex_type); + DRW_engine_register(&draw_engine_paint_weight_type); + DRW_engine_register(&draw_engine_particle_type); + DRW_engine_register(&draw_engine_pose_type); + DRW_engine_register(&draw_engine_sculpt_type); + + /* setup callbacks */ + { + /* BKE: mball.c */ + extern void *BKE_mball_batch_cache_dirty_cb; + extern void *BKE_mball_batch_cache_free_cb; + /* BKE: curve.c */ + extern void *BKE_curve_batch_cache_dirty_cb; + extern void *BKE_curve_batch_cache_free_cb; + /* BKE: mesh.c */ + extern void *BKE_mesh_batch_cache_dirty_cb; + extern void *BKE_mesh_batch_cache_free_cb; + /* BKE: lattice.c */ + extern void *BKE_lattice_batch_cache_dirty_cb; + extern void *BKE_lattice_batch_cache_free_cb; + /* BKE: particle.c */ + extern void *BKE_particle_batch_cache_dirty_cb; + extern void *BKE_particle_batch_cache_free_cb; + + BKE_mball_batch_cache_dirty_cb = DRW_mball_batch_cache_dirty; + BKE_mball_batch_cache_free_cb = DRW_mball_batch_cache_free; + + BKE_curve_batch_cache_dirty_cb = DRW_curve_batch_cache_dirty; + BKE_curve_batch_cache_free_cb = DRW_curve_batch_cache_free; + + BKE_mesh_batch_cache_dirty_cb = DRW_mesh_batch_cache_dirty; + BKE_mesh_batch_cache_free_cb = DRW_mesh_batch_cache_free; + + BKE_lattice_batch_cache_dirty_cb = DRW_lattice_batch_cache_dirty; + BKE_lattice_batch_cache_free_cb = DRW_lattice_batch_cache_free; + + BKE_particle_batch_cache_dirty_cb = DRW_particle_batch_cache_dirty; + BKE_particle_batch_cache_free_cb = DRW_particle_batch_cache_free; + } +} + +extern struct Gwn_VertFormat *g_pos_format; /* draw_shgroup.c */ +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GPUTexture *globals_ramp; /* draw_common.c */ +void DRW_engines_free(void) +{ + DRW_opengl_context_enable(); + + DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth); + GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer); + + DRW_hair_free(); + DRW_shape_cache_free(); + DRW_stats_free(); + DRW_globals_free(); + + DrawEngineType *next; + for (DrawEngineType *type = DRW_engines.first; type; type = next) { + next = type->next; + BLI_remlink(&R_engines, type); + + if (type->engine_free) { + type->engine_free(); + } + } + + DRW_UBO_FREE_SAFE(globals_ubo); + DRW_UBO_FREE_SAFE(view_ubo); + DRW_TEXTURE_FREE_SAFE(globals_ramp); + MEM_SAFE_FREE(g_pos_format); + + MEM_SAFE_FREE(DST.RST.bound_texs); + MEM_SAFE_FREE(DST.RST.bound_tex_slots); + MEM_SAFE_FREE(DST.RST.bound_ubos); + MEM_SAFE_FREE(DST.RST.bound_ubo_slots); + + DRW_opengl_context_disable(); + +#ifdef WITH_CLAY_ENGINE + BLI_remlink(&R_engines, &DRW_engine_viewport_clay_type); +#endif +} + +/** \} */ + +/** \name Init/Exit (DRW_opengl_ctx) + * \{ */ + +void DRW_opengl_context_create(void) +{ + BLI_assert(DST.ogl_context == NULL); /* Ensure it's called once */ + + BLI_mutex_init(&DST.ogl_context_mutex); + if (!G.background) { + immDeactivate(); + } + /* This changes the active context. */ + DST.ogl_context = WM_opengl_context_create(); + /* Be sure to create gawain.context too. */ + DST.gwn_context = GWN_context_create(); + if (!G.background) { + immActivate(); + } + /* Set default Blender OpenGL state */ + GPU_state_init(); + /* So we activate the window's one afterwards. */ + wm_window_reset_drawable(); +} + +void DRW_opengl_context_destroy(void) +{ + BLI_assert(BLI_thread_is_main()); + if (DST.ogl_context != NULL) { + WM_opengl_context_activate(DST.ogl_context); + GWN_context_active_set(DST.gwn_context); + GWN_context_discard(DST.gwn_context); + WM_opengl_context_dispose(DST.ogl_context); + BLI_mutex_end(&DST.ogl_context_mutex); + } +} + +void DRW_opengl_context_enable(void) +{ + if (DST.ogl_context != NULL) { + /* IMPORTANT: We dont support immediate mode in render mode! + * This shall remain in effect until immediate mode supports + * multiple threads. */ + BLI_mutex_lock(&DST.ogl_context_mutex); + if (BLI_thread_is_main()) { + if (!G.background) { + immDeactivate(); + } + } + WM_opengl_context_activate(DST.ogl_context); + GWN_context_active_set(DST.gwn_context); + if (BLI_thread_is_main()) { + if (!G.background) { + immActivate(); + } + BLF_batch_reset(); + } + } +} + +void DRW_opengl_context_disable(void) +{ + if (DST.ogl_context != NULL) { +#ifdef __APPLE__ + /* Need to flush before disabling draw context, otherwise it does not + * always finish drawing and viewport can be empty or partially drawn */ + glFlush(); +#endif + + if (BLI_thread_is_main()) { + wm_window_reset_drawable(); + } + else { + WM_opengl_context_release(DST.ogl_context); + GWN_context_active_set(NULL); + } + + BLI_mutex_unlock(&DST.ogl_context_mutex); + } +} + +/** \} */ diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h new file mode 100644 index 00000000000..9faab2cc2b0 --- /dev/null +++ b/source/blender/draw/intern/draw_manager.h @@ -0,0 +1,399 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_manager.h + * \ingroup draw + */ + +/* Private functions / structs of the draw manager */ + +#ifndef __DRAW_MANAGER_H__ +#define __DRAW_MANAGER_H__ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "BLI_linklist.h" +#include "BLI_threads.h" + +#include "GPU_batch.h" +#include "GPU_framebuffer.h" +#include "GPU_shader.h" +#include "GPU_uniformbuffer.h" +#include "GPU_viewport.h" + +#include "draw_instance_data.h" + +/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */ +#define USE_GPU_SELECT + +/* ------------ Profiling --------------- */ + +#define USE_PROFILE + +#ifdef USE_PROFILE +# include "PIL_time.h" + +# define PROFILE_TIMER_FALLOFF 0.04 + +# define PROFILE_START(time_start) \ + double time_start = PIL_check_seconds_timer(); + +# define PROFILE_END_ACCUM(time_accum, time_start) { \ + time_accum += (PIL_check_seconds_timer() - time_start) * 1e3; \ +} ((void)0) + +/* exp average */ +# define PROFILE_END_UPDATE(time_update, time_start) { \ + double _time_delta = (PIL_check_seconds_timer() - time_start) * 1e3; \ + time_update = (time_update * (1.0 - PROFILE_TIMER_FALLOFF)) + \ + (_time_delta * PROFILE_TIMER_FALLOFF); \ +} ((void)0) + +#else /* USE_PROFILE */ + +# define PROFILE_START(time_start) ((void)0) +# define PROFILE_END_ACCUM(time_accum, time_start) ((void)0) +# define PROFILE_END_UPDATE(time_update, time_start) ((void)0) + +#endif /* USE_PROFILE */ + +/* ------------ Data Structure --------------- */ +/** + * Data structure containing all drawcalls organized by passes and materials. + * DRWPass > DRWShadingGroup > DRWCall > DRWCallState + * > DRWUniform + **/ + +/* Used by DRWCallState.flag */ +enum { + DRW_CALL_CULLED = (1 << 0), + DRW_CALL_NEGSCALE = (1 << 1), + DRW_CALL_BYPASS_CULLING = (1 << 2), +}; + +/* Used by DRWCallState.matflag */ +enum { + DRW_CALL_MODELINVERSE = (1 << 0), + DRW_CALL_MODELVIEW = (1 << 1), + DRW_CALL_MODELVIEWINVERSE = (1 << 2), + DRW_CALL_MODELVIEWPROJECTION = (1 << 3), + DRW_CALL_NORMALVIEW = (1 << 4), + DRW_CALL_NORMALWORLD = (1 << 5), + DRW_CALL_ORCOTEXFAC = (1 << 6), + DRW_CALL_EYEVEC = (1 << 7), +}; + +typedef struct DRWCallState { + DRWCallVisibilityFn *visibility_cb; + void *user_data; + + unsigned char flag; + unsigned char cache_id; /* Compared with DST.state_cache_id to see if matrices are still valid. */ + uint16_t matflag; /* Which matrices to compute. */ + /* Culling: Using Bounding Sphere for now for faster culling. + * Not ideal for planes. */ + BoundSphere bsphere; + /* Matrices */ + float model[4][4]; + float modelinverse[4][4]; + float modelview[4][4]; + float modelviewinverse[4][4]; + float modelviewprojection[4][4]; + float normalview[3][3]; + float normalworld[3][3]; /* Not view dependant */ + float orcotexfac[2][3]; /* Not view dependant */ + float eyevec[3]; +} DRWCallState; + +typedef enum { + DRW_CALL_SINGLE, /* A single batch */ + DRW_CALL_INSTANCES, /* Draw instances without any instancing attribs. */ + DRW_CALL_GENERATE, /* Uses a callback to draw with any number of batches. */ + DRW_CALL_PROCEDURAL, /* Generate a drawcall without any Gwn_Batch. */ +} DRWCallType; + +typedef struct DRWCall { + struct DRWCall *next; + DRWCallState *state; + + union { + struct { /* type == DRW_CALL_SINGLE */ + Gwn_Batch *geometry; + } single; + struct { /* type == DRW_CALL_INSTANCES */ + Gwn_Batch *geometry; + /* Count can be adjusted between redraw. If needed, we can add fixed count. */ + uint *count; + } instances; + struct { /* type == DRW_CALL_GENERATE */ + DRWCallGenerateFn *geometry_fn; + void *user_data; + } generate; + struct { /* type == DRW_CALL_PROCEDURAL */ + unsigned int prim_count; + Gwn_PrimType prim_type; + } procedural; + }; + + DRWCallType type; +#ifdef USE_GPU_SELECT + int select_id; +#endif +} DRWCall; + +/* Used by DRWUniform.type */ +typedef enum { + DRW_UNIFORM_BOOL, + DRW_UNIFORM_BOOL_COPY, + DRW_UNIFORM_SHORT_TO_INT, + DRW_UNIFORM_SHORT_TO_FLOAT, + DRW_UNIFORM_INT, + DRW_UNIFORM_INT_COPY, + DRW_UNIFORM_FLOAT, + DRW_UNIFORM_FLOAT_COPY, + DRW_UNIFORM_TEXTURE, + DRW_UNIFORM_TEXTURE_PERSIST, + DRW_UNIFORM_TEXTURE_REF, + DRW_UNIFORM_BLOCK, + DRW_UNIFORM_BLOCK_PERSIST +} DRWUniformType; + +struct DRWUniform { + DRWUniform *next; /* single-linked list */ + union { + /* For reference or array/vector types. */ + const void *pvalue; + /* Single values. */ + float fvalue; + int ivalue; + }; + int location; + char type; /* DRWUniformType */ + char length; /* cannot be more than 16 */ + char arraysize; /* cannot be more than 16 too */ +}; + +typedef enum { + DRW_SHG_NORMAL, + DRW_SHG_POINT_BATCH, + DRW_SHG_LINE_BATCH, + DRW_SHG_TRIANGLE_BATCH, + DRW_SHG_INSTANCE, + DRW_SHG_INSTANCE_EXTERNAL, + DRW_SHG_FEEDBACK_TRANSFORM, +} DRWShadingGroupType; + +struct DRWShadingGroup { + DRWShadingGroup *next; + + GPUShader *shader; /* Shader to bind */ + DRWUniform *uniforms; /* Uniforms pointers */ + + /* Watch this! Can be nasty for debugging. */ + union { + struct { /* DRW_SHG_NORMAL */ + DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */ + } calls; + struct { /* DRW_SHG_FEEDBACK_TRANSFORM */ + DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */ + struct Gwn_VertBuf *tfeedback_target; /* Transform Feedback target. */ + }; + struct { /* DRW_SHG_***_BATCH */ + struct Gwn_Batch *batch_geom; /* Result of call batching */ + struct Gwn_VertBuf *batch_vbo; + uint primitive_count; + }; + struct { /* DRW_SHG_INSTANCE[_EXTERNAL] */ + struct Gwn_Batch *instance_geom; + struct Gwn_VertBuf *instance_vbo; + uint instance_count; + float instance_orcofac[2][3]; /* TODO find a better place. */ + }; + }; + + DRWState state_extra; /* State changes for this batch only (or'd with the pass's state) */ + DRWState state_extra_disable; /* State changes for this batch only (and'd with the pass's state) */ + uint stencil_mask; /* Stencil mask to use for stencil test / write operations */ + DRWShadingGroupType type; + + /* Builtin matrices locations */ + int model; + int modelinverse; + int modelview; + int modelviewinverse; + int modelviewprojection; + int normalview; + int normalworld; + int orcotexfac; + int eye; + int callid; + uint16_t matflag; /* Matrices needed, same as DRWCall.flag */ + +#ifndef NDEBUG + char attribs_count; +#endif + +#ifdef USE_GPU_SELECT + Gwn_VertBuf *inst_selectid; + DRWPass *pass_parent; /* backlink to pass we're in */ + int override_selectid; /* Override for single object instances. */ +#endif +}; + +#define MAX_PASS_NAME 32 + +struct DRWPass { + /* Linked list */ + struct { + DRWShadingGroup *first; + DRWShadingGroup *last; + } shgroups; + + DRWState state; + char name[MAX_PASS_NAME]; +}; + +typedef struct ViewUboStorage { + DRWMatrixState matstate; + float viewcamtexcofac[4]; + float clipplanes[2][4]; +} ViewUboStorage; + +/* ------------- DRAW DEBUG ------------ */ + +typedef struct DRWDebugLine { + struct DRWDebugLine *next; /* linked list */ + float pos[2][3]; + float color[4]; +} DRWDebugLine; + +/* ------------- DRAW MANAGER ------------ */ + +#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */ +#define STENCIL_UNDEFINED 256 +typedef struct DRWManager { + /* TODO clean up this struct a bit */ + /* Cache generation */ + ViewportMemoryPool *vmempool; + DRWInstanceDataList *idatalist; + DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE]; + /* State of the object being evaluated if already allocated. */ + DRWCallState *ob_state; + unsigned char state_cache_id; /* Could be larger but 254 view changes is already a lot! */ + + /* Rendering state */ + GPUShader *shader; + + /* Managed by `DRW_state_set`, `DRW_state_reset` */ + DRWState state; + DRWState state_lock; + uint stencil_mask; + + /* Per viewport */ + GPUViewport *viewport; + struct GPUFrameBuffer *default_framebuffer; + float size[2]; + float inv_size[2]; + float screenvecs[2][3]; + float pixsize; + + GLenum backface, frontface; + + struct { + uint is_select : 1; + uint is_depth : 1; + uint is_image_render : 1; + uint is_scene_render : 1; + uint draw_background : 1; + } options; + + /* Current rendering context */ + DRWContextState draw_ctx; + + /* Convenience pointer to text_store owned by the viewport */ + struct DRWTextStore **text_store_p; + + ListBase enabled_engines; /* RenderEngineType */ + + bool buffer_finish_called; /* Avoid bad usage of DRW_render_instance_buffer_finish */ + + /* View dependant uniforms. */ + DRWMatrixState original_mat; /* Original rv3d matrices. */ + int override_mat; /* Bitflag of which matrices are overriden. */ + int num_clip_planes; /* Number of active clipplanes. */ + bool dirty_mat; + + /* keep in sync with viewBlock */ + ViewUboStorage view_data; + + struct { + float frustum_planes[6][4]; + BoundBox frustum_corners; + BoundSphere frustum_bsphere; + bool updated; + } clipping; + +#ifdef USE_GPU_SELECT + uint select_id; +#endif + + /* ---------- Nothing after this point is cleared after use ----------- */ + + /* ogl_context serves as the offset for clearing only + * the top portion of the struct so DO NOT MOVE IT! */ + void *ogl_context; /* Unique ghost context used by the draw manager. */ + Gwn_Context *gwn_context; + ThreadMutex ogl_context_mutex; /* Mutex to lock the drw manager and avoid concurent context usage. */ + + /** GPU Resource State: Memory storage between drawing. */ + struct { + GPUTexture **bound_texs; + char *bound_tex_slots; + int bind_tex_inc; + GPUUniformBuffer **bound_ubos; + char *bound_ubo_slots; + int bind_ubo_inc; + } RST; + + struct { + /* TODO(fclem) optimize: use chunks. */ + DRWDebugLine *lines; + } debug; +} DRWManager; + +extern DRWManager DST; /* TODO : get rid of this and allow multithreaded rendering */ + +/* --------------- FUNCTIONS ------------- */ + +void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags); +void drw_texture_get_format( + GPUTextureFormat format, bool is_framebuffer, + GPUTextureFormat *r_data_type, int *r_channels, bool *r_is_depth); + +void *drw_viewport_engine_data_ensure(void *engine_type); + +void drw_state_set(DRWState state); + +void drw_debug_draw(void); +void drw_debug_init(void); + +#endif /* __DRAW_MANAGER_H__ */ diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c new file mode 100644 index 00000000000..054db5968cc --- /dev/null +++ b/source/blender/draw/intern/draw_manager_data.c @@ -0,0 +1,1079 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_manager_data.c + * \ingroup draw + */ + +#include "draw_manager.h" + +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_pbvh.h" + +#include "DNA_curve_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meta_types.h" + +#include "BLI_link_utils.h" +#include "BLI_mempool.h" + +#include "intern/gpu_codegen.h" + +struct Gwn_VertFormat *g_pos_format = NULL; + +extern struct GPUUniformBuffer *view_ubo; /* draw_manager_exec.c */ + +/* -------------------------------------------------------------------- */ + +/** \name Uniform Buffer Object (DRW_uniformbuffer) + * \{ */ + +GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data) +{ + return GPU_uniformbuffer_create(size, data, NULL); +} + +void DRW_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data) +{ + GPU_uniformbuffer_update(ubo, data); +} + +void DRW_uniformbuffer_free(GPUUniformBuffer *ubo) +{ + GPU_uniformbuffer_free(ubo); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Uniforms (DRW_shgroup_uniform) + * \{ */ + +static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, int loc, + DRWUniformType type, const void *value, int length, int arraysize) +{ + DRWUniform *uni = BLI_mempool_alloc(DST.vmempool->uniforms); + uni->location = loc; + uni->type = type; + uni->length = length; + uni->arraysize = arraysize; + + switch (type) { + case DRW_UNIFORM_INT_COPY: + uni->ivalue = *((int *)value); + break; + case DRW_UNIFORM_BOOL_COPY: + uni->ivalue = (int)*((bool *)value); + break; + case DRW_UNIFORM_FLOAT_COPY: + uni->fvalue = *((float *)value); + break; + default: + uni->pvalue = value; + break; + } + + BLI_LINKS_PREPEND(shgroup->uniforms, uni); +} + +static void drw_shgroup_builtin_uniform( + DRWShadingGroup *shgroup, int builtin, const void *value, int length, int arraysize) +{ + int loc = GPU_shader_get_builtin_uniform(shgroup->shader, builtin); + + if (loc != -1) { + drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_FLOAT, value, length, arraysize); + } +} + +static void drw_shgroup_uniform(DRWShadingGroup *shgroup, const char *name, + DRWUniformType type, const void *value, int length, int arraysize) +{ + int location; + if (ELEM(type, DRW_UNIFORM_BLOCK, DRW_UNIFORM_BLOCK_PERSIST)) { + location = GPU_shader_get_uniform_block(shgroup->shader, name); + } + else { + location = GPU_shader_get_uniform(shgroup->shader, name); + } + + if (location == -1) { + if (G.debug & G_DEBUG) + fprintf(stderr, "Uniform '%s' not found!\n", name); + /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */ + // BLI_assert(0); + return; + } + + BLI_assert(arraysize > 0 && arraysize <= 16); + BLI_assert(length >= 0 && length <= 16); + + drw_shgroup_uniform_create_ex(shgroup, location, type, value, length, arraysize); +} + +void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex) +{ + BLI_assert(tex != NULL); + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1); +} + +/* Same as DRW_shgroup_uniform_texture but is garanteed to be bound if shader does not change between shgrp. */ +void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex) +{ + BLI_assert(tex != NULL); + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_PERSIST, tex, 0, 1); +} + +void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo) +{ + BLI_assert(ubo != NULL); + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 1); +} + +/* Same as DRW_shgroup_uniform_block but is garanteed to be bound if shader does not change between shgrp. */ +void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo) +{ + BLI_assert(ubo != NULL); + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK_PERSIST, ubo, 0, 1); +} + +void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_REF, tex, 0, 1); +} + +void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BOOL, value, 1, arraysize); +} + +void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 1, arraysize); +} + +void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 2, arraysize); +} + +void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 3, arraysize); +} + +void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize); +} + +void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_INT, value, 1, arraysize); +} + +void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_FLOAT, value, 1, arraysize); +} + +void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize); +} + +void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 2, arraysize); +} + +void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 3, arraysize); +} + +void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float (*value)[3]) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, (float *)value, 9, 1); +} + +void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float (*value)[4]) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, (float *)value, 16, 1); +} + +/* Stores the int instead of a pointer. */ +void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, &value, 1, 1); +} + +void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BOOL_COPY, &value, 1, 1); +} + +void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, &value, 1, 1); +} + + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Draw Call (DRW_calls) + * \{ */ + +static void drw_call_calc_orco(Object *ob, float (*r_orcofacs)[3]) +{ + ID *ob_data = (ob) ? ob->data : NULL; + float *texcoloc = NULL; + float *texcosize = NULL; + if (ob_data != NULL) { + switch (GS(ob_data->name)) { + case ID_ME: + BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize); + break; + case ID_CU: + { + Curve *cu = (Curve *)ob_data; + if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) { + BKE_curve_texspace_calc(cu); + } + texcoloc = cu->loc; + texcosize = cu->size; + break; + } + case ID_MB: + { + MetaBall *mb = (MetaBall *)ob_data; + texcoloc = mb->loc; + texcosize = mb->size; + break; + } + default: + break; + } + } + + if ((texcoloc != NULL) && (texcosize != NULL)) { + mul_v3_v3fl(r_orcofacs[1], texcosize, 2.0f); + invert_v3(r_orcofacs[1]); + sub_v3_v3v3(r_orcofacs[0], texcoloc, texcosize); + negate_v3(r_orcofacs[0]); + mul_v3_v3(r_orcofacs[0], r_orcofacs[1]); /* result in a nice MADD in the shader */ + } + else { + copy_v3_fl(r_orcofacs[0], 0.0f); + copy_v3_fl(r_orcofacs[1], 1.0f); + } +} + +static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob) +{ + DRWCallState *state = BLI_mempool_alloc(DST.vmempool->states); + state->flag = 0; + state->cache_id = 0; + state->visibility_cb = NULL; + state->matflag = shgroup->matflag; + + /* Matrices */ + if (obmat != NULL) { + copy_m4_m4(state->model, obmat); + + if (is_negative_m4(state->model)) { + state->flag |= DRW_CALL_NEGSCALE; + } + } + else { + unit_m4(state->model); + } + + if (ob != NULL) { + float corner[3]; + BoundBox *bbox = BKE_object_boundbox_get(ob); + /* Get BoundSphere center and radius from the BoundBox. */ + mid_v3_v3v3(state->bsphere.center, bbox->vec[0], bbox->vec[6]); + mul_v3_m4v3(corner, obmat, bbox->vec[0]); + mul_m4_v3(obmat, state->bsphere.center); + state->bsphere.radius = len_v3v3(state->bsphere.center, corner); + } + else { + /* Bypass test. */ + state->bsphere.radius = -1.0f; + } + + /* Orco factors: We compute this at creation to not have to save the *ob_data */ + if ((state->matflag & DRW_CALL_ORCOTEXFAC) != 0) { + drw_call_calc_orco(ob, state->orcotexfac); + state->matflag &= ~DRW_CALL_ORCOTEXFAC; + } + + return state; +} + +static DRWCallState *drw_call_state_object(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob) +{ + if (DST.ob_state == NULL) { + DST.ob_state = drw_call_state_create(shgroup, obmat, ob); + } + else { + /* If the DRWCallState is reused, add necessary matrices. */ + DST.ob_state->matflag |= shgroup->matflag; + } + + return DST.ob_state; +} + +void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4]) +{ + BLI_assert(geom != NULL); + BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)); + + DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + call->state = drw_call_state_create(shgroup, obmat, NULL); + call->type = DRW_CALL_SINGLE; + call->single.geometry = geom; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; +#endif + + BLI_LINKS_APPEND(&shgroup->calls, call); +} + +static void drw_shgroup_call_procedural_add_ex( + DRWShadingGroup *shgroup, Gwn_PrimType prim_type, uint prim_count, float (*obmat)[4]) +{ + BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)); + + DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + call->state = drw_call_state_create(shgroup, obmat, NULL); + call->type = DRW_CALL_PROCEDURAL; + call->procedural.prim_type = prim_type; + call->procedural.prim_count = prim_count; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; +#endif + + BLI_LINKS_APPEND(&shgroup->calls, call); +} + +void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup, uint point_count, float (*obmat)[4]) +{ + drw_shgroup_call_procedural_add_ex(shgroup, GWN_PRIM_POINTS, point_count, obmat); +} + +void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup, uint line_count, float (*obmat)[4]) +{ + drw_shgroup_call_procedural_add_ex(shgroup, GWN_PRIM_LINES, line_count, obmat); +} + +void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, uint tria_count, float (*obmat)[4]) +{ + drw_shgroup_call_procedural_add_ex(shgroup, GWN_PRIM_TRIS, tria_count, obmat); +} + + +/* These calls can be culled and are optimized for redraw */ +void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, bool bypass_culling) +{ + BLI_assert(geom != NULL); + BLI_assert(shgroup->type == DRW_SHG_NORMAL); + + DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + call->state = drw_call_state_object(shgroup, ob->obmat, ob); + call->type = DRW_CALL_SINGLE; + call->single.geometry = geom; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; +#endif + + SET_FLAG_FROM_TEST(call->state->flag, bypass_culling, DRW_CALL_BYPASS_CULLING); + + BLI_LINKS_APPEND(&shgroup->calls, call); +} + +void DRW_shgroup_call_object_add_with_callback( + DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, + DRWCallVisibilityFn *callback, void *user_data) +{ + BLI_assert(geom != NULL); + BLI_assert(shgroup->type == DRW_SHG_NORMAL); + + DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + call->state = drw_call_state_object(shgroup, ob->obmat, ob); + call->state->visibility_cb = callback; + call->state->user_data = user_data; + call->type = DRW_CALL_SINGLE; + call->single.geometry = geom; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; +#endif + + BLI_LINKS_APPEND(&shgroup->calls, call); +} + +void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4], uint *count) +{ + BLI_assert(geom != NULL); + BLI_assert(shgroup->type == DRW_SHG_NORMAL); + + DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + call->state = drw_call_state_create(shgroup, obmat, NULL); + call->type = DRW_CALL_INSTANCES; + call->instances.geometry = geom; + call->instances.count = count; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; +#endif + + BLI_LINKS_APPEND(&shgroup->calls, call); +} + +/* These calls can be culled and are optimized for redraw */ +void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, uint *count) +{ + BLI_assert(geom != NULL); + BLI_assert(shgroup->type == DRW_SHG_NORMAL); + + DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + call->state = drw_call_state_object(shgroup, ob->obmat, ob); + call->type = DRW_CALL_INSTANCES; + call->instances.geometry = geom; + call->instances.count = count; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; +#endif + + BLI_LINKS_APPEND(&shgroup->calls, call); +} + +void DRW_shgroup_call_generate_add( + DRWShadingGroup *shgroup, + DRWCallGenerateFn *geometry_fn, void *user_data, + float (*obmat)[4]) +{ + BLI_assert(geometry_fn != NULL); + BLI_assert(shgroup->type == DRW_SHG_NORMAL); + + DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + call->state = drw_call_state_create(shgroup, obmat, NULL); + call->type = DRW_CALL_GENERATE; + call->generate.geometry_fn = geometry_fn; + call->generate.user_data = user_data; +#ifdef USE_GPU_SELECT + call->select_id = DST.select_id; +#endif + + BLI_LINKS_APPEND(&shgroup->calls, call); +} + +static void sculpt_draw_cb( + DRWShadingGroup *shgroup, + void (*draw_fn)(DRWShadingGroup *shgroup, Gwn_Batch *geom), + void *user_data) +{ + Object *ob = user_data; + PBVH *pbvh = ob->sculpt->pbvh; + + if (pbvh) { + BKE_pbvh_draw_cb( + pbvh, NULL, NULL, false, + (void (*)(void *, Gwn_Batch *))draw_fn, shgroup); + } +} + +void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4]) +{ + DRW_shgroup_call_generate_add(shgroup, sculpt_draw_cb, ob, obmat); +} + +void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *attr[], uint attr_len) +{ +#ifdef USE_GPU_SELECT + if (G.f & G_PICKSEL) { + if (shgroup->instance_count == shgroup->inst_selectid->vertex_ct) { + GWN_vertbuf_data_resize(shgroup->inst_selectid, shgroup->instance_count + 32); + } + GWN_vertbuf_attr_set(shgroup->inst_selectid, 0, shgroup->instance_count, &DST.select_id); + } +#endif + + BLI_assert(attr_len == shgroup->attribs_count); + UNUSED_VARS_NDEBUG(attr_len); + + for (int i = 0; i < attr_len; ++i) { + if (shgroup->instance_count == shgroup->instance_vbo->vertex_ct) { + GWN_vertbuf_data_resize(shgroup->instance_vbo, shgroup->instance_count + 32); + } + GWN_vertbuf_attr_set(shgroup->instance_vbo, i, shgroup->instance_count, attr[i]); + } + + shgroup->instance_count += 1; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Shading Groups (DRW_shgroup) + * \{ */ + +static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) +{ + shgroup->instance_geom = NULL; + shgroup->instance_vbo = NULL; + shgroup->instance_count = 0; + shgroup->uniforms = NULL; +#ifdef USE_GPU_SELECT + shgroup->inst_selectid = NULL; + shgroup->override_selectid = -1; +#endif +#ifndef NDEBUG + shgroup->attribs_count = 0; +#endif + + int view_ubo_location = GPU_shader_get_uniform_block(shader, "viewBlock"); + + if (view_ubo_location != -1) { + drw_shgroup_uniform_create_ex(shgroup, view_ubo_location, DRW_UNIFORM_BLOCK_PERSIST, view_ubo, 0, 1); + } + else { + /* Only here to support builtin shaders. This should not be used by engines. */ + drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEW, DST.view_data.matstate.mat[DRW_MAT_VIEW], 16, 1); + drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEW_INV, DST.view_data.matstate.mat[DRW_MAT_VIEWINV], 16, 1); + drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEWPROJECTION, DST.view_data.matstate.mat[DRW_MAT_PERS], 16, 1); + drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_VIEWPROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_PERSINV], 16, 1); + drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_PROJECTION, DST.view_data.matstate.mat[DRW_MAT_WIN], 16, 1); + drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_PROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_WININV], 16, 1); + drw_shgroup_builtin_uniform(shgroup, GWN_UNIFORM_CAMERATEXCO, DST.view_data.viewcamtexcofac, 3, 2); + } + + shgroup->model = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL); + shgroup->modelinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODEL_INV); + shgroup->modelview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW); + shgroup->modelviewinverse = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MODELVIEW_INV); + shgroup->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_MVP); + shgroup->normalview = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_NORMAL); + shgroup->normalworld = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_WORLDNORMAL); + shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_ORCO); + shgroup->eye = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_EYE); + shgroup->callid = GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_CALLID); + + shgroup->matflag = 0; + if (shgroup->modelinverse > -1) + shgroup->matflag |= DRW_CALL_MODELINVERSE; + if (shgroup->modelview > -1) + shgroup->matflag |= DRW_CALL_MODELVIEW; + if (shgroup->modelviewinverse > -1) + shgroup->matflag |= DRW_CALL_MODELVIEWINVERSE; + if (shgroup->modelviewprojection > -1) + shgroup->matflag |= DRW_CALL_MODELVIEWPROJECTION; + if (shgroup->normalview > -1) + shgroup->matflag |= DRW_CALL_NORMALVIEW; + if (shgroup->normalworld > -1) + shgroup->matflag |= DRW_CALL_NORMALWORLD; + if (shgroup->orcotexfac > -1) + shgroup->matflag |= DRW_CALL_ORCOTEXFAC; + if (shgroup->eye > -1) + shgroup->matflag |= DRW_CALL_EYEVEC; +} + +static void drw_shgroup_instance_init( + DRWShadingGroup *shgroup, GPUShader *shader, Gwn_Batch *batch, Gwn_VertFormat *format) +{ + BLI_assert(shgroup->type == DRW_SHG_INSTANCE); + BLI_assert(batch != NULL); + BLI_assert(format != NULL); + + drw_shgroup_init(shgroup, shader); + + shgroup->instance_geom = batch; +#ifndef NDEBUG + shgroup->attribs_count = format->attrib_ct; +#endif + + DRW_instancing_buffer_request(DST.idatalist, format, batch, shgroup, + &shgroup->instance_geom, &shgroup->instance_vbo); + +#ifdef USE_GPU_SELECT + if (G.f & G_PICKSEL) { + /* Not actually used for rendering but alloced in one chunk. + * Plus we don't have to care about ownership. */ + static Gwn_VertFormat inst_select_format = {0}; + if (inst_select_format.attrib_ct == 0) { + GWN_vertformat_attr_add(&inst_select_format, "selectId", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + Gwn_Batch *batch_dummy; /* Not used */ + DRW_batching_buffer_request(DST.idatalist, &inst_select_format, + GWN_PRIM_POINTS, shgroup, + &batch_dummy, &shgroup->inst_selectid); + } +#endif +} + +static void drw_shgroup_batching_init( + DRWShadingGroup *shgroup, GPUShader *shader, Gwn_VertFormat *format) +{ + drw_shgroup_init(shgroup, shader); + +#ifndef NDEBUG + shgroup->attribs_count = (format != NULL) ? format->attrib_ct : 0; +#endif + BLI_assert(format != NULL); + + Gwn_PrimType type; + switch (shgroup->type) { + case DRW_SHG_POINT_BATCH: type = GWN_PRIM_POINTS; break; + case DRW_SHG_LINE_BATCH: type = GWN_PRIM_LINES; break; + case DRW_SHG_TRIANGLE_BATCH: type = GWN_PRIM_TRIS; break; + default: type = GWN_PRIM_NONE; BLI_assert(0); break; + } + + DRW_batching_buffer_request(DST.idatalist, format, type, shgroup, + &shgroup->batch_geom, &shgroup->batch_vbo); + +#ifdef USE_GPU_SELECT + if (G.f & G_PICKSEL) { + /* Not actually used for rendering but alloced in one chunk. */ + static Gwn_VertFormat inst_select_format = {0}; + if (inst_select_format.attrib_ct == 0) { + GWN_vertformat_attr_add(&inst_select_format, "selectId", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + Gwn_Batch *batch; /* Not used */ + DRW_batching_buffer_request(DST.idatalist, &inst_select_format, + GWN_PRIM_POINTS, shgroup, + &batch, &shgroup->inst_selectid); + } +#endif +} + +static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass) +{ + DRWShadingGroup *shgroup = BLI_mempool_alloc(DST.vmempool->shgroups); + + BLI_LINKS_APPEND(&pass->shgroups, shgroup); + + shgroup->type = DRW_SHG_NORMAL; + shgroup->shader = shader; + shgroup->state_extra = 0; + shgroup->state_extra_disable = ~0x0; + shgroup->stencil_mask = 0; + shgroup->calls.first = NULL; + shgroup->calls.last = NULL; +#if 0 /* All the same in the union! */ + shgroup->batch_geom = NULL; + shgroup->batch_vbo = NULL; + + shgroup->instance_geom = NULL; + shgroup->instance_vbo = NULL; +#endif + +#ifdef USE_GPU_SELECT + shgroup->pass_parent = pass; +#endif + + return shgroup; +} + +static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass *pass) +{ + if (!gpupass) { + /* Shader compilation error */ + return NULL; + } + + DRWShadingGroup *grp = drw_shgroup_create_ex(GPU_pass_shader(gpupass), pass); + return grp; +} + +static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, struct GPUMaterial *material) +{ + /* TODO : Ideally we should not convert. But since the whole codegen + * is relying on GPUPass we keep it as is for now. */ + + ListBase *inputs = GPU_material_get_inputs(material); + + /* Converting dynamic GPUInput to DRWUniform */ + for (GPUInput *input = inputs->first; input; input = input->next) { + /* Textures */ + if (input->ima) { + double time = 0.0; /* TODO make time variable */ + GPUTexture *tex = GPU_texture_from_blender( + input->ima, input->iuser, input->textarget, input->image_isdata, time, 1); + + if (input->bindtex) { + DRW_shgroup_uniform_texture(grp, input->shadername, tex); + } + } + /* Color Ramps */ + else if (input->tex) { + DRW_shgroup_uniform_texture(grp, input->shadername, input->tex); + } + /* Floats */ + else { + switch (input->type) { + case GPU_FLOAT: + case GPU_VEC2: + case GPU_VEC3: + case GPU_VEC4: + /* Should already be in the material ubo. */ + break; + case GPU_MAT3: + DRW_shgroup_uniform_mat3(grp, input->shadername, (float (*)[3])input->dynamicvec); + break; + case GPU_MAT4: + DRW_shgroup_uniform_mat4(grp, input->shadername, (float (*)[4])input->dynamicvec); + break; + default: + break; + } + } + } + + GPUUniformBuffer *ubo = GPU_material_get_uniform_buffer(material); + if (ubo != NULL) { + DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo); + } + + return grp; +} + +Gwn_VertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttribFormat attribs[], int arraysize) +{ + Gwn_VertFormat *format = MEM_callocN(sizeof(Gwn_VertFormat), "Gwn_VertFormat"); + + for (int i = 0; i < arraysize; ++i) { + GWN_vertformat_attr_add(format, attribs[i].name, + (attribs[i].type == DRW_ATTRIB_INT) ? GWN_COMP_I32 : GWN_COMP_F32, + attribs[i].components, + (attribs[i].type == DRW_ATTRIB_INT) ? GWN_FETCH_INT : GWN_FETCH_FLOAT); + } + return format; +} + +DRWShadingGroup *DRW_shgroup_material_create( + struct GPUMaterial *material, DRWPass *pass) +{ + GPUPass *gpupass = GPU_material_get_pass(material); + DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass); + + if (shgroup) { + drw_shgroup_init(shgroup, GPU_pass_shader(gpupass)); + drw_shgroup_material_inputs(shgroup, material); + } + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_material_instance_create( + struct GPUMaterial *material, DRWPass *pass, Gwn_Batch *geom, Object *ob, Gwn_VertFormat *format) +{ + GPUPass *gpupass = GPU_material_get_pass(material); + DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass); + + if (shgroup) { + shgroup->type = DRW_SHG_INSTANCE; + shgroup->instance_geom = geom; + drw_call_calc_orco(ob, shgroup->instance_orcofac); + drw_shgroup_instance_init(shgroup, GPU_pass_shader(gpupass), geom, format); + drw_shgroup_material_inputs(shgroup, material); + } + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create( + struct GPUMaterial *material, DRWPass *pass, int tri_count) +{ +#ifdef USE_GPU_SELECT + BLI_assert((G.f & G_PICKSEL) == 0); +#endif + GPUPass *gpupass = GPU_material_get_pass(material); + DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass); + + if (shgroup) { + /* Calling drw_shgroup_init will cause it to call GWN_draw_primitive(). */ + drw_shgroup_init(shgroup, GPU_pass_shader(gpupass)); + shgroup->type = DRW_SHG_TRIANGLE_BATCH; + shgroup->instance_count = tri_count * 3; + drw_shgroup_material_inputs(shgroup, material); + } + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass) +{ + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); + drw_shgroup_init(shgroup, shader); + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_instance_create( + struct GPUShader *shader, DRWPass *pass, Gwn_Batch *geom, Gwn_VertFormat *format) +{ + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); + shgroup->type = DRW_SHG_INSTANCE; + shgroup->instance_geom = geom; + drw_call_calc_orco(NULL, shgroup->instance_orcofac); + drw_shgroup_instance_init(shgroup, shader, geom, format); + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass) +{ + DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTRIB_FLOAT, 3}}); + + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); + shgroup->type = DRW_SHG_POINT_BATCH; + + drw_shgroup_batching_init(shgroup, shader, g_pos_format); + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_line_batch_create_with_format( + struct GPUShader *shader, DRWPass *pass, Gwn_VertFormat *format) +{ + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); + shgroup->type = DRW_SHG_LINE_BATCH; + + drw_shgroup_batching_init(shgroup, shader, format); + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass) +{ + DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTRIB_FLOAT, 3}}); + + return DRW_shgroup_line_batch_create_with_format(shader, pass, g_pos_format); +} + +/* Very special batch. Use this if you position + * your vertices with the vertex shader + * and dont need any VBO attrib */ +DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int tri_count) +{ +#ifdef USE_GPU_SELECT + BLI_assert((G.f & G_PICKSEL) == 0); +#endif + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); + + /* Calling drw_shgroup_init will cause it to call GWN_draw_primitive(). */ + drw_shgroup_init(shgroup, shader); + + shgroup->type = DRW_SHG_TRIANGLE_BATCH; + shgroup->instance_count = tri_count * 3; + + return shgroup; +} + +DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, Gwn_VertBuf *tf_target) +{ + BLI_assert(tf_target != NULL); + DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); + shgroup->type = DRW_SHG_FEEDBACK_TRANSFORM; + + drw_shgroup_init(shgroup, shader); + + shgroup->tfeedback_target = tf_target; + + return shgroup; +} + +/* Specify an external batch instead of adding each attrib one by one. */ +void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batch) +{ + BLI_assert(shgroup->type == DRW_SHG_INSTANCE); + BLI_assert(shgroup->instance_count == 0); + /* You cannot use external instancing batch without a dummy format. */ + BLI_assert(shgroup->attribs_count != 0); + + shgroup->type = DRW_SHG_INSTANCE_EXTERNAL; + drw_call_calc_orco(NULL, shgroup->instance_orcofac); + /* PERF : This destroys the vaos cache so better check if it's necessary. */ + /* Note: This WILL break if batch->verts[0] is destroyed and reallocated + * at the same adress. Bindings/VAOs would remain obsolete. */ + //if (shgroup->instancing_geom->inst != batch->verts[0]) + GWN_batch_instbuf_set(shgroup->instance_geom, batch->verts[0], false); + +#ifdef USE_GPU_SELECT + shgroup->override_selectid = DST.select_id; +#endif +} + +uint DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup) +{ + return shgroup->instance_count; +} + +/** + * State is added to #Pass.state while drawing. + * Use to temporarily enable draw options. + */ +void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state) +{ + shgroup->state_extra |= state; +} + +void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state) +{ + shgroup->state_extra_disable &= ~state; +} + +void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask) +{ + BLI_assert(mask <= 255); + shgroup->stencil_mask = mask; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Passes (DRW_pass) + * \{ */ + +DRWPass *DRW_pass_create(const char *name, DRWState state) +{ + DRWPass *pass = BLI_mempool_alloc(DST.vmempool->passes); + pass->state = state; + if (G.debug_value > 20) { + BLI_strncpy(pass->name, name, MAX_PASS_NAME); + } + + pass->shgroups.first = NULL; + pass->shgroups.last = NULL; + + return pass; +} + +void DRW_pass_state_set(DRWPass *pass, DRWState state) +{ + pass->state = state; +} + +void DRW_pass_state_add(DRWPass *pass, DRWState state) +{ + pass->state |= state; +} + +void DRW_pass_state_remove(DRWPass *pass, DRWState state) +{ + pass->state &= ~state; +} + +void DRW_pass_free(DRWPass *pass) +{ + pass->shgroups.first = NULL; + pass->shgroups.last = NULL; +} + +void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData) +{ + for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) { + callback(userData, shgroup); + } +} + +typedef struct ZSortData { + float *axis; + float *origin; +} ZSortData; + +static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b) +{ + const ZSortData *zsortdata = (ZSortData *)thunk; + const DRWShadingGroup *shgrp_a = (const DRWShadingGroup *)a; + const DRWShadingGroup *shgrp_b = (const DRWShadingGroup *)b; + + const DRWCall *call_a = (DRWCall *)shgrp_a->calls.first; + const DRWCall *call_b = (DRWCall *)shgrp_b->calls.first; + + if (call_a == NULL) return -1; + if (call_b == NULL) return -1; + + float tmp[3]; + sub_v3_v3v3(tmp, zsortdata->origin, call_a->state->model[3]); + const float a_sq = dot_v3v3(zsortdata->axis, tmp); + sub_v3_v3v3(tmp, zsortdata->origin, call_b->state->model[3]); + const float b_sq = dot_v3v3(zsortdata->axis, tmp); + + if (a_sq < b_sq) return 1; + else if (a_sq > b_sq) return -1; + else { + /* If there is a depth prepass put it before */ + if ((shgrp_a->state_extra & DRW_STATE_WRITE_DEPTH) != 0) { + return -1; + } + else if ((shgrp_b->state_extra & DRW_STATE_WRITE_DEPTH) != 0) { + return 1; + } + else return 0; + } +} + +/* ------------------ Shading group sorting --------------------- */ + +#define SORT_IMPL_LINKTYPE DRWShadingGroup + +#define SORT_IMPL_USE_THUNK +#define SORT_IMPL_FUNC shgroup_sort_fn_r +#include "../../blenlib/intern/list_sort_impl.h" +#undef SORT_IMPL_FUNC +#undef SORT_IMPL_USE_THUNK + +#undef SORT_IMPL_LINKTYPE + +/** + * Sort Shading groups by decreasing Z of their first draw call. + * This is usefull for order dependant effect such as transparency. + **/ +void DRW_pass_sort_shgroup_z(DRWPass *pass) +{ + float (*viewinv)[4]; + viewinv = DST.view_data.matstate.mat[DRW_MAT_VIEWINV]; + + ZSortData zsortdata = {viewinv[2], viewinv[3]}; + + if (pass->shgroups.first && pass->shgroups.first->next) { + pass->shgroups.first = shgroup_sort_fn_r(pass->shgroups.first, pass_shgroup_dist_sort, &zsortdata); + + /* Find the next last */ + DRWShadingGroup *last = pass->shgroups.first; + while ((last = last->next)) { + /* Do nothing */ + } + pass->shgroups.last = last; + } +} + +/** \} */ diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c new file mode 100644 index 00000000000..94250920c57 --- /dev/null +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -0,0 +1,1263 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_manager_exec.c + * \ingroup draw + */ + +#include "draw_manager.h" + +#include "BLI_mempool.h" + +#include "BIF_glutil.h" + +#include "BKE_global.h" +#include "BKE_object.h" + +#include "GPU_draw.h" +#include "GPU_extensions.h" + +#ifdef USE_GPU_SELECT +# include "ED_view3d.h" +# include "ED_armature.h" +# include "GPU_select.h" +#endif + +#ifdef USE_GPU_SELECT +void DRW_select_load_id(uint id) +{ + BLI_assert(G.f & G_PICKSEL); + DST.select_id = id; +} +#endif + +struct GPUUniformBuffer *view_ubo; + +/* -------------------------------------------------------------------- */ + +/** \name Draw State (DRW_state) + * \{ */ + +void drw_state_set(DRWState state) +{ + if (DST.state == state) { + return; + } + +#define CHANGED_TO(f) \ + ((DST.state_lock & (f)) ? 0 : \ + (((DST.state & (f)) ? \ + ((state & (f)) ? 0 : -1) : \ + ((state & (f)) ? 1 : 0)))) + +#define CHANGED_ANY(f) \ + (((DST.state & (f)) != (state & (f))) && \ + ((DST.state_lock & (f)) == 0)) + +#define CHANGED_ANY_STORE_VAR(f, enabled) \ + (((DST.state & (f)) != (enabled = (state & (f)))) && \ + (((DST.state_lock & (f)) == 0))) + + /* Depth Write */ + { + int test; + if ((test = CHANGED_TO(DRW_STATE_WRITE_DEPTH))) { + if (test == 1) { + glDepthMask(GL_TRUE); + } + else { + glDepthMask(GL_FALSE); + } + } + } + + /* Color Write */ + { + int test; + if ((test = CHANGED_TO(DRW_STATE_WRITE_COLOR))) { + if (test == 1) { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + else { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + } + } + } + + /* Raster Discard */ + { + if (CHANGED_ANY(DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | + DRW_STATE_WRITE_STENCIL | + DRW_STATE_WRITE_STENCIL_SHADOW_PASS | + DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)) + { + if ((state & (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | + DRW_STATE_WRITE_STENCIL | DRW_STATE_WRITE_STENCIL_SHADOW_PASS | + DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)) != 0) + { + glDisable(GL_RASTERIZER_DISCARD); + } + else { + glEnable(GL_RASTERIZER_DISCARD); + } + } + } + + /* Cull */ + { + DRWState test; + if (CHANGED_ANY_STORE_VAR( + DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT, + test)) + { + if (test) { + glEnable(GL_CULL_FACE); + + if ((state & DRW_STATE_CULL_BACK) != 0) { + glCullFace(GL_BACK); + } + else if ((state & DRW_STATE_CULL_FRONT) != 0) { + glCullFace(GL_FRONT); + } + else { + BLI_assert(0); + } + } + else { + glDisable(GL_CULL_FACE); + } + } + } + + /* Depth Test */ + { + DRWState test; + if (CHANGED_ANY_STORE_VAR( + DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | + DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_DEPTH_ALWAYS, + test)) + { + if (test) { + glEnable(GL_DEPTH_TEST); + + if (state & DRW_STATE_DEPTH_LESS) { + glDepthFunc(GL_LESS); + } + else if (state & DRW_STATE_DEPTH_LESS_EQUAL) { + glDepthFunc(GL_LEQUAL); + } + else if (state & DRW_STATE_DEPTH_EQUAL) { + glDepthFunc(GL_EQUAL); + } + else if (state & DRW_STATE_DEPTH_GREATER) { + glDepthFunc(GL_GREATER); + } + else if (state & DRW_STATE_DEPTH_GREATER_EQUAL) { + glDepthFunc(GL_GEQUAL); + } + else if (state & DRW_STATE_DEPTH_ALWAYS) { + glDepthFunc(GL_ALWAYS); + } + else { + BLI_assert(0); + } + } + else { + glDisable(GL_DEPTH_TEST); + } + } + } + + /* Wire Width */ + { + if (CHANGED_ANY(DRW_STATE_WIRE | DRW_STATE_WIRE_SMOOTH)) { + if ((state & DRW_STATE_WIRE_SMOOTH) != 0) { + glLineWidth(2.0f); + glEnable(GL_LINE_SMOOTH); + } + else if ((state & DRW_STATE_WIRE) != 0) { + glLineWidth(1.0f); + } + else { + glDisable(GL_LINE_SMOOTH); + } + } + } + + /* Points Size */ + { + int test; + if ((test = CHANGED_TO(DRW_STATE_POINT))) { + if (test == 1) { + GPU_enable_program_point_size(); + glPointSize(5.0f); + } + else { + GPU_disable_program_point_size(); + } + } + } + + /* Blending (all buffer) */ + { + int test; + if (CHANGED_ANY_STORE_VAR( + DRW_STATE_BLEND | DRW_STATE_BLEND_PREMUL | DRW_STATE_ADDITIVE | + DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION | DRW_STATE_ADDITIVE_FULL | + DRW_STATE_TRANSPARENT_REVEALAGE, + test)) + { + if (test) { + glEnable(GL_BLEND); + + if ((state & DRW_STATE_BLEND) != 0) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, /* RGB */ + GL_ONE, GL_ONE_MINUS_SRC_ALPHA); /* Alpha */ + } + else if ((state & DRW_STATE_BLEND_PREMUL) != 0) { + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + else if ((state & DRW_STATE_MULTIPLY) != 0) { + glBlendFunc(GL_DST_COLOR, GL_ZERO); + } + else if ((state & DRW_STATE_TRANSMISSION) != 0) { + glBlendFunc(GL_ONE, GL_SRC_ALPHA); + } + else if ((state & DRW_STATE_TRANSPARENT_REVEALAGE) != 0) { + glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + } + else if ((state & DRW_STATE_ADDITIVE) != 0) { + /* Do not let alpha accumulate but premult the source RGB by it. */ + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, /* RGB */ + GL_ZERO, GL_ONE); /* Alpha */ + } + else if ((state & DRW_STATE_ADDITIVE_FULL) != 0) { + /* Let alpha accumulate. */ + glBlendFunc(GL_ONE, GL_ONE); + } + else { + BLI_assert(0); + } + } + else { + glDisable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); /* Don't multiply incoming color by alpha. */ + } + } + } + + /* Clip Planes */ + { + int test; + if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) { + if (test == 1) { + for (int i = 0; i < DST.num_clip_planes; ++i) { + glEnable(GL_CLIP_DISTANCE0 + i); + } + } + else { + for (int i = 0; i < MAX_CLIP_PLANES; ++i) { + glDisable(GL_CLIP_DISTANCE0 + i); + } + } + } + } + + /* Line Stipple */ + { + int test; + if (CHANGED_ANY_STORE_VAR( + DRW_STATE_STIPPLE_2 | DRW_STATE_STIPPLE_3 | DRW_STATE_STIPPLE_4, + test)) + { + if (test) { + if ((state & DRW_STATE_STIPPLE_2) != 0) { + setlinestyle(2); + } + else if ((state & DRW_STATE_STIPPLE_3) != 0) { + setlinestyle(3); + } + else if ((state & DRW_STATE_STIPPLE_4) != 0) { + setlinestyle(4); + } + else { + BLI_assert(0); + } + } + else { + setlinestyle(0); + } + } + } + + /* Stencil */ + { + DRWState test; + if (CHANGED_ANY_STORE_VAR( + DRW_STATE_WRITE_STENCIL | + DRW_STATE_WRITE_STENCIL_SHADOW_PASS | + DRW_STATE_WRITE_STENCIL_SHADOW_FAIL | + DRW_STATE_STENCIL_EQUAL | + DRW_STATE_STENCIL_NEQUAL, + test)) + { + if (test) { + glEnable(GL_STENCIL_TEST); + /* Stencil Write */ + if ((state & DRW_STATE_WRITE_STENCIL) != 0) { + glStencilMask(0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } + else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_PASS) != 0) { + glStencilMask(0xFF); + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP); + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP); + } + else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_FAIL) != 0) { + glStencilMask(0xFF); + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP); + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP); + } + /* Stencil Test */ + else if ((state & (DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)) != 0) { + glStencilMask(0x00); /* disable write */ + DST.stencil_mask = STENCIL_UNDEFINED; + } + else { + BLI_assert(0); + } + } + else { + /* disable write & test */ + DST.stencil_mask = 0; + glStencilMask(0x00); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glDisable(GL_STENCIL_TEST); + } + } + } + +#undef CHANGED_TO +#undef CHANGED_ANY +#undef CHANGED_ANY_STORE_VAR + + DST.state = state; +} + +static void drw_stencil_set(uint mask) +{ + if (DST.stencil_mask != mask) { + DST.stencil_mask = mask; + /* Stencil Write */ + if ((DST.state & DRW_STATE_WRITE_STENCIL) != 0) { + glStencilFunc(GL_ALWAYS, mask, 0xFF); + } + /* Stencil Test */ + else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) { + glStencilFunc(GL_EQUAL, mask, 0xFF); + } + else if ((DST.state & DRW_STATE_STENCIL_NEQUAL) != 0) { + glStencilFunc(GL_NOTEQUAL, mask, 0xFF); + } + } +} + +/* Reset state to not interfer with other UI drawcall */ +void DRW_state_reset_ex(DRWState state) +{ + DST.state = ~state; + drw_state_set(state); +} + +/** + * Use with care, intended so selection code can override passes depth settings, + * which is important for selection to work properly. + * + * Should be set in main draw loop, cleared afterwards + */ +void DRW_state_lock(DRWState state) +{ + DST.state_lock = state; +} + +void DRW_state_reset(void) +{ + DRW_state_reset_ex(DRW_STATE_DEFAULT); + + /* Reset blending function */ + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); +} + +/* NOTE : Make sure to reset after use! */ +void DRW_state_invert_facing(void) +{ + SWAP(GLenum, DST.backface, DST.frontface); + glFrontFace(DST.frontface); +} + +/** + * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES, + * and if the shaders have support for it (see usage of gl_ClipDistance). + * Be sure to call DRW_state_clip_planes_reset() after you finish drawing. + **/ +void DRW_state_clip_planes_count_set(uint plane_ct) +{ + BLI_assert(plane_ct <= MAX_CLIP_PLANES); + DST.num_clip_planes = plane_ct; +} + +void DRW_state_clip_planes_reset(void) +{ + DST.num_clip_planes = 0; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Clipping (DRW_clipping) + * \{ */ + +/* Extract the 8 corners from a Projection Matrix. + * Although less accurate, this solution can be simplified as follows: + * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f}); + * for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv, bbox.vec[i]);} + */ +static void draw_frustum_boundbox_calc(const float(*projmat)[4], BoundBox *r_bbox) +{ + float near, far, left, right, bottom, top; + bool is_persp = projmat[3][3] == 0.0f; + + if (is_persp) { + near = projmat[3][2] / (projmat[2][2] - 1.0f); + far = projmat[3][2] / (projmat[2][2] + 1.0f); + left = near * (projmat[2][0] - 1.0f) / projmat[0][0]; + right = near * (projmat[2][0] + 1.0f) / projmat[0][0]; + bottom = near * (projmat[2][1] - 1.0f) / projmat[1][1]; + top = near * (projmat[2][1] + 1.0f) / projmat[1][1]; + } + else { + near = ( projmat[3][2] + 1.0f) / projmat[2][2]; + far = ( projmat[3][2] - 1.0f) / projmat[2][2]; + left = (-projmat[3][0] - 1.0f) / projmat[0][0]; + right = (-projmat[3][0] + 1.0f) / projmat[0][0]; + bottom = (-projmat[3][1] - 1.0f) / projmat[1][1]; + top = (-projmat[3][1] + 1.0f) / projmat[1][1]; + } + + r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near; + r_bbox->vec[0][0] = r_bbox->vec[3][0] = left; + r_bbox->vec[4][0] = r_bbox->vec[7][0] = right; + r_bbox->vec[0][1] = r_bbox->vec[4][1] = bottom; + r_bbox->vec[7][1] = r_bbox->vec[3][1] = top; + + /* Get the coordinates of the far plane. */ + if (is_persp) { + float sca_far = far / near; + left *= sca_far; + bottom *= sca_far; + right *= sca_far; + top *= sca_far; + } + + r_bbox->vec[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far; + r_bbox->vec[1][0] = r_bbox->vec[2][0] = left; + r_bbox->vec[6][0] = r_bbox->vec[5][0] = right; + r_bbox->vec[1][1] = r_bbox->vec[5][1] = bottom; + r_bbox->vec[2][1] = r_bbox->vec[6][1] = top; +} + +static void draw_clipping_setup_from_view(void) +{ + if (DST.clipping.updated) + return; + + float (*viewinv)[4] = DST.view_data.matstate.mat[DRW_MAT_VIEWINV]; + float (*projmat)[4] = DST.view_data.matstate.mat[DRW_MAT_WIN]; + float (*projinv)[4] = DST.view_data.matstate.mat[DRW_MAT_WININV]; + BoundSphere *bsphere = &DST.clipping.frustum_bsphere; + + /* Extract Clipping Planes */ + BoundBox bbox; +#if 0 /* It has accuracy problems. */ + BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f}); + for (int i = 0; i < 8; i++) { + mul_project_m4_v3(projinv, bbox.vec[i]); + } +#else + draw_frustum_boundbox_calc(projmat, &bbox); +#endif + /* Transform into world space. */ + for (int i = 0; i < 8; i++) { + mul_m4_v3(viewinv, bbox.vec[i]); + } + + memcpy(&DST.clipping.frustum_corners, &bbox, sizeof(BoundBox)); + + /* Compute clip planes using the world space frustum corners. */ + for (int p = 0; p < 6; p++) { + int q, r; + switch (p) { + case 0: q = 1; r = 2; break; + case 1: q = 0; r = 5; break; + case 2: q = 1; r = 5; break; + case 3: q = 2; r = 6; break; + case 4: q = 0; r = 3; break; + default: q = 4; r = 7; break; + } + if (DST.frontface == GL_CW) { + SWAP(int, q, r); + } + + normal_tri_v3(DST.clipping.frustum_planes[p], bbox.vec[p], bbox.vec[q], bbox.vec[r]); + DST.clipping.frustum_planes[p][3] = -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[p]); + } + + /* Extract Bounding Sphere */ + if (projmat[3][3] != 0.0f) { + /* Orthographic */ + /* The most extreme points on the near and far plane. (normalized device coords). */ + float *nearpoint = bbox.vec[0]; + float *farpoint = bbox.vec[6]; + + /* just use median point */ + mid_v3_v3v3(bsphere->center, farpoint, nearpoint); + bsphere->radius = len_v3v3(bsphere->center, farpoint); + } + else if (projmat[2][0] == 0.0f && projmat[2][1] == 0.0f) { + /* Perspective with symmetrical frustum. */ + + /* We obtain the center and radius of the circumscribed circle of the + * isosceles trapezoid composed by the diagonals of the near and far clipping plane */ + + /* center of each clipping plane */ + float mid_min[3], mid_max[3]; + mid_v3_v3v3(mid_min, bbox.vec[3], bbox.vec[4]); + mid_v3_v3v3(mid_max, bbox.vec[2], bbox.vec[5]); + + /* square length of the diagonals of each clipping plane */ + float a_sq = len_squared_v3v3(bbox.vec[3], bbox.vec[4]); + float b_sq = len_squared_v3v3(bbox.vec[2], bbox.vec[5]); + + /* distance squared between clipping planes */ + float h_sq = len_squared_v3v3(mid_min, mid_max); + + float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq); + + /* The goal is to get the smallest sphere, + * not the sphere that passes through each corner */ + CLAMP(fac, 0.0f, 1.0f); + + interp_v3_v3v3(bsphere->center, mid_min, mid_max, fac); + + /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */ + bsphere->radius = len_v3v3(bsphere->center, bbox.vec[1]); + } + else { + /* Perspective with asymmetrical frustum. */ + + /* We put the sphere center on the line that goes from origin + * to the center of the far clipping plane. */ + + /* Detect which of the corner of the far clipping plane is the farthest to the origin */ + float nfar[4]; /* most extreme far point in NDC space */ + float farxy[2]; /* farpoint projection onto the near plane */ + float farpoint[3] = {0.0f}; /* most extreme far point in camera coordinate */ + float nearpoint[3]; /* most extreme near point in camera coordinate */ + float farcenter[3] = {0.0f}; /* center of far cliping plane in camera coordinate */ + float F = -1.0f, N; /* square distance of far and near point to origin */ + float f, n; /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */ + float e, s; /* far and near clipping distance (<0) */ + float c; /* slope of center line = distance of far clipping center to z axis / far clipping distance */ + float z; /* projection of sphere center on z axis (<0) */ + + /* Find farthest corner and center of far clip plane. */ + float corner[3] = {1.0f, 1.0f, 1.0f}; /* in clip space */ + for (int i = 0; i < 4; i++) { + float point[3]; + mul_v3_project_m4_v3(point, projinv, corner); + float len = len_squared_v3(point); + if (len > F) { + copy_v3_v3(nfar, corner); + copy_v3_v3(farpoint, point); + F = len; + } + add_v3_v3(farcenter, point); + /* rotate by 90 degree to walk through the 4 points of the far clip plane */ + float tmp = corner[0]; + corner[0] = -corner[1]; + corner[1] = tmp; + } + + /* the far center is the average of the far clipping points */ + mul_v3_fl(farcenter, 0.25f); + /* the extreme near point is the opposite point on the near clipping plane */ + copy_v3_fl3(nfar, -nfar[0], -nfar[1], -1.0f); + mul_v3_project_m4_v3(nearpoint, projinv, nfar); + /* this is a frustum projection */ + N = len_squared_v3(nearpoint); + e = farpoint[2]; + s = nearpoint[2]; + /* distance to view Z axis */ + f = len_v2(farpoint); + /* get corresponding point on the near plane */ + mul_v2_v2fl(farxy, farpoint, s / e); + /* this formula preserve the sign of n */ + sub_v2_v2(nearpoint, farxy); + n = f * s / e - len_v2(nearpoint); + c = len_v2(farcenter) / e; + /* the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case */ + z = (F - N) / (2.0f * (e - s + c * (f - n))); + + bsphere->center[0] = farcenter[0] * z / e; + bsphere->center[1] = farcenter[1] * z / e; + bsphere->center[2] = z; + bsphere->radius = len_v3v3(bsphere->center, farpoint); + + /* Transform to world space. */ + mul_m4_v3(viewinv, bsphere->center); + } + + DST.clipping.updated = true; +} + +/* Return True if the given BoundSphere intersect the current view frustum */ +bool DRW_culling_sphere_test(BoundSphere *bsphere) +{ + draw_clipping_setup_from_view(); + + /* Bypass test if radius is negative. */ + if (bsphere->radius < 0.0f) + return true; + + /* Do a rough test first: Sphere VS Sphere intersect. */ + BoundSphere *frustum_bsphere = &DST.clipping.frustum_bsphere; + float center_dist = len_squared_v3v3(bsphere->center, frustum_bsphere->center); + if (center_dist > SQUARE(bsphere->radius + frustum_bsphere->radius)) + return false; + + /* Test against the 6 frustum planes. */ + for (int p = 0; p < 6; p++) { + float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bsphere->center); + if (dist < -bsphere->radius) { + return false; + } + } + + return true; +} + +/* Return True if the given BoundBox intersect the current view frustum. + * bbox must be in world space. */ +bool DRW_culling_box_test(BoundBox *bbox) +{ + draw_clipping_setup_from_view(); + + /* 6 view frustum planes */ + for (int p = 0; p < 6; p++) { + /* 8 box vertices. */ + for (int v = 0; v < 8 ; v++) { + float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bbox->vec[v]); + if (dist > 0.0f) { + /* At least one point in front of this plane. + * Go to next plane. */ + break; + } + else if (v == 7) { + /* 8 points behind this plane. */ + return false; + } + } + } + + return true; +} + +/* Return True if the current view frustum is inside or intersect the given plane */ +bool DRW_culling_plane_test(float plane[4]) +{ + draw_clipping_setup_from_view(); + + /* Test against the 8 frustum corners. */ + for (int c = 0; c < 8; c++) { + float dist = plane_point_side_v3(plane, DST.clipping.frustum_corners.vec[c]); + if (dist < 0.0f) { + return true; + } + } + + return false; +} + +void DRW_culling_frustum_corners_get(BoundBox *corners) +{ + draw_clipping_setup_from_view(); + memcpy(corners, &DST.clipping.frustum_corners, sizeof(BoundBox)); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Draw (DRW_draw) + * \{ */ + +static void draw_visibility_eval(DRWCallState *st) +{ + bool culled = st->flag & DRW_CALL_CULLED; + + if (st->cache_id != DST.state_cache_id) { + /* Update culling result for this view. */ + culled = !DRW_culling_sphere_test(&st->bsphere); + } + + if (st->visibility_cb) { + culled = !st->visibility_cb(!culled, st->user_data); + } + + SET_FLAG_FROM_TEST(st->flag, culled, DRW_CALL_CULLED); +} + +static void draw_matrices_model_prepare(DRWCallState *st) +{ + if (st->cache_id == DST.state_cache_id) { + /* Values are already updated for this view. */ + return; + } + else { + st->cache_id = DST.state_cache_id; + } + + /* No need to go further the call will not be used. */ + if ((st->flag & DRW_CALL_CULLED) != 0 && + (st->flag & DRW_CALL_BYPASS_CULLING) == 0) + { + return; + } + /* Order matters */ + if (st->matflag & (DRW_CALL_MODELVIEW | DRW_CALL_MODELVIEWINVERSE | + DRW_CALL_NORMALVIEW | DRW_CALL_EYEVEC)) + { + mul_m4_m4m4(st->modelview, DST.view_data.matstate.mat[DRW_MAT_VIEW], st->model); + } + if (st->matflag & DRW_CALL_MODELVIEWINVERSE) { + invert_m4_m4(st->modelviewinverse, st->modelview); + } + if (st->matflag & DRW_CALL_MODELVIEWPROJECTION) { + mul_m4_m4m4(st->modelviewprojection, DST.view_data.matstate.mat[DRW_MAT_PERS], st->model); + } + if (st->matflag & (DRW_CALL_NORMALVIEW | DRW_CALL_EYEVEC)) { + copy_m3_m4(st->normalview, st->modelview); + invert_m3(st->normalview); + transpose_m3(st->normalview); + } + if (st->matflag & DRW_CALL_EYEVEC) { + /* Used by orthographic wires */ + float tmp[3][3]; + copy_v3_fl3(st->eyevec, 0.0f, 0.0f, 1.0f); + invert_m3_m3(tmp, st->normalview); + /* set eye vector, transformed to object coords */ + mul_m3_v3(tmp, st->eyevec); + } + /* Non view dependant */ + if (st->matflag & DRW_CALL_MODELINVERSE) { + invert_m4_m4(st->modelinverse, st->model); + st->matflag &= ~DRW_CALL_MODELINVERSE; + } + if (st->matflag & DRW_CALL_NORMALWORLD) { + copy_m3_m4(st->normalworld, st->model); + invert_m3(st->normalworld); + transpose_m3(st->normalworld); + st->matflag &= ~DRW_CALL_NORMALWORLD; + } +} + +static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCallState *state) +{ + /* step 1 : bind object dependent matrices */ + if (state != NULL) { + GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelview, 16, 1, (float *)state->modelview); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewinverse, 16, 1, (float *)state->modelviewinverse); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)state->modelviewprojection); + GPU_shader_uniform_vector(shgroup->shader, shgroup->normalview, 9, 1, (float *)state->normalview); + GPU_shader_uniform_vector(shgroup->shader, shgroup->normalworld, 9, 1, (float *)state->normalworld); + GPU_shader_uniform_vector(shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac); + GPU_shader_uniform_vector(shgroup->shader, shgroup->eye, 3, 1, (float *)state->eyevec); + } + else { + BLI_assert((shgroup->normalview == -1) && (shgroup->normalworld == -1) && (shgroup->eye == -1)); + /* For instancing and batching. */ + float unitmat[4][4]; + unit_m4(unitmat); + GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)unitmat); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)unitmat); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelview, 16, 1, (float *)DST.view_data.matstate.mat[DRW_MAT_VIEW]); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewinverse, 16, 1, (float *)DST.view_data.matstate.mat[DRW_MAT_VIEWINV]); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)DST.view_data.matstate.mat[DRW_MAT_PERS]); + GPU_shader_uniform_vector(shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)shgroup->instance_orcofac); + } +} + +static void draw_geometry_execute_ex( + DRWShadingGroup *shgroup, Gwn_Batch *geom, uint start, uint count, bool draw_instance) +{ + /* Special case: empty drawcall, placement is done via shader, don't bind anything. */ + /* TODO use DRW_CALL_PROCEDURAL instead */ + if (geom == NULL) { + BLI_assert(shgroup->type == DRW_SHG_TRIANGLE_BATCH); /* Add other type if needed. */ + /* Shader is already bound. */ + GWN_draw_primitive(GWN_PRIM_TRIS, count); + return; + } + + /* step 2 : bind vertex array & draw */ + GWN_batch_program_set_no_use( + geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); + /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */ + geom->program_in_use = true; + + GWN_batch_draw_range_ex(geom, start, count, draw_instance); + + geom->program_in_use = false; /* XXX hacking gawain */ +} + +static void draw_geometry_execute(DRWShadingGroup *shgroup, Gwn_Batch *geom) +{ + draw_geometry_execute_ex(shgroup, geom, 0, 0, false); +} + +enum { + BIND_NONE = 0, + BIND_TEMP = 1, /* Release slot after this shading group. */ + BIND_PERSIST = 2, /* Release slot only after the next shader change. */ +}; + +static void bind_texture(GPUTexture *tex, char bind_type) +{ + int index; + char *slot_flags = DST.RST.bound_tex_slots; + int bind_num = GPU_texture_bound_number(tex); + if (bind_num == -1) { + for (int i = 0; i < GPU_max_textures(); ++i) { + index = DST.RST.bind_tex_inc = (DST.RST.bind_tex_inc + 1) % GPU_max_textures(); + if (slot_flags[index] == BIND_NONE) { + if (DST.RST.bound_texs[index] != NULL) { + GPU_texture_unbind(DST.RST.bound_texs[index]); + } + GPU_texture_bind(tex, index); + DST.RST.bound_texs[index] = tex; + slot_flags[index] = bind_type; + // printf("Binds Texture %d %p\n", DST.RST.bind_tex_inc, tex); + return; + } + } + printf("Not enough texture slots! Reduce number of textures used by your shader.\n"); + } + slot_flags[bind_num] = bind_type; +} + +static void bind_ubo(GPUUniformBuffer *ubo, char bind_type) +{ + int index; + char *slot_flags = DST.RST.bound_ubo_slots; + int bind_num = GPU_uniformbuffer_bindpoint(ubo); + if (bind_num == -1) { + for (int i = 0; i < GPU_max_ubo_binds(); ++i) { + index = DST.RST.bind_ubo_inc = (DST.RST.bind_ubo_inc + 1) % GPU_max_ubo_binds(); + if (slot_flags[index] == BIND_NONE) { + if (DST.RST.bound_ubos[index] != NULL) { + GPU_uniformbuffer_unbind(DST.RST.bound_ubos[index]); + } + GPU_uniformbuffer_bind(ubo, index); + DST.RST.bound_ubos[index] = ubo; + slot_flags[index] = bind_type; + return; + } + } + /* printf so user can report bad behaviour */ + printf("Not enough ubo slots! This should not happen!\n"); + /* This is not depending on user input. + * It is our responsability to make sure there is enough slots. */ + BLI_assert(0); + } + slot_flags[bind_num] = bind_type; +} + +static void release_texture_slots(bool with_persist) +{ + if (with_persist) { + memset(DST.RST.bound_tex_slots, 0x0, sizeof(*DST.RST.bound_tex_slots) * GPU_max_textures()); + } + else { + for (int i = 0; i < GPU_max_textures(); ++i) { + if (DST.RST.bound_tex_slots[i] != BIND_PERSIST) + DST.RST.bound_tex_slots[i] = BIND_NONE; + } + } + + /* Reset so that slots are consistenly assigned for different shader + * draw calls, to avoid shader specialization/patching by the driver. */ + DST.RST.bind_tex_inc = 0; +} + +static void release_ubo_slots(bool with_persist) +{ + if (with_persist) { + memset(DST.RST.bound_ubo_slots, 0x0, sizeof(*DST.RST.bound_ubo_slots) * GPU_max_ubo_binds()); + } + else { + for (int i = 0; i < GPU_max_ubo_binds(); ++i) { + if (DST.RST.bound_ubo_slots[i] != BIND_PERSIST) + DST.RST.bound_ubo_slots[i] = BIND_NONE; + } + } + + /* Reset so that slots are consistenly assigned for different shader + * draw calls, to avoid shader specialization/patching by the driver. */ + DST.RST.bind_ubo_inc = 0; +} + +static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) +{ + BLI_assert(shgroup->shader); + + GPUTexture *tex; + GPUUniformBuffer *ubo; + int val; + float fval; + const bool shader_changed = (DST.shader != shgroup->shader); + bool use_tfeedback = false; + + if (shader_changed) { + if (DST.shader) GPU_shader_unbind(); + GPU_shader_bind(shgroup->shader); + DST.shader = shgroup->shader; + } + + if ((pass_state & DRW_STATE_TRANS_FEEDBACK) != 0 && + (shgroup->type == DRW_SHG_FEEDBACK_TRANSFORM)) + { + use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader, + shgroup->tfeedback_target->vbo_id); + } + + release_ubo_slots(shader_changed); + release_texture_slots(shader_changed); + + drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra); + drw_stencil_set(shgroup->stencil_mask); + + /* Binding Uniform */ + for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) { + switch (uni->type) { + case DRW_UNIFORM_SHORT_TO_INT: + val = (int)*((short *)uni->pvalue); + GPU_shader_uniform_vector_int( + shgroup->shader, uni->location, uni->length, uni->arraysize, &val); + break; + case DRW_UNIFORM_SHORT_TO_FLOAT: + fval = (float)*((short *)uni->pvalue); + GPU_shader_uniform_vector( + shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)&fval); + break; + case DRW_UNIFORM_BOOL_COPY: + case DRW_UNIFORM_INT_COPY: + GPU_shader_uniform_vector_int( + shgroup->shader, uni->location, uni->length, uni->arraysize, &uni->ivalue); + break; + case DRW_UNIFORM_BOOL: + case DRW_UNIFORM_INT: + GPU_shader_uniform_vector_int( + shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)uni->pvalue); + break; + case DRW_UNIFORM_FLOAT_COPY: + GPU_shader_uniform_vector( + shgroup->shader, uni->location, uni->length, uni->arraysize, &uni->fvalue); + break; + case DRW_UNIFORM_FLOAT: + GPU_shader_uniform_vector( + shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->pvalue); + break; + case DRW_UNIFORM_TEXTURE: + tex = (GPUTexture *)uni->pvalue; + BLI_assert(tex); + bind_texture(tex, BIND_TEMP); + GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + break; + case DRW_UNIFORM_TEXTURE_PERSIST: + tex = (GPUTexture *)uni->pvalue; + BLI_assert(tex); + bind_texture(tex, BIND_PERSIST); + GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + break; + case DRW_UNIFORM_TEXTURE_REF: + tex = *((GPUTexture **)uni->pvalue); + BLI_assert(tex); + bind_texture(tex, BIND_TEMP); + GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + break; + case DRW_UNIFORM_BLOCK: + ubo = (GPUUniformBuffer *)uni->pvalue; + bind_ubo(ubo, BIND_TEMP); + GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + break; + case DRW_UNIFORM_BLOCK_PERSIST: + ubo = (GPUUniformBuffer *)uni->pvalue; + bind_ubo(ubo, BIND_PERSIST); + GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + break; + } + } + +#ifdef USE_GPU_SELECT +# define GPU_SELECT_LOAD_IF_PICKSEL(_select_id) \ + if (G.f & G_PICKSEL) { \ + GPU_select_load_id(_select_id); \ + } ((void)0) + +# define GPU_SELECT_LOAD_IF_PICKSEL_CALL(_call) \ + if ((G.f & G_PICKSEL) && (_call)) { \ + GPU_select_load_id((_call)->select_id); \ + } ((void)0) + +# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \ + _start = 0; \ + _count = _shgroup->instance_count; \ + int *select_id = NULL; \ + if (G.f & G_PICKSEL) { \ + if (_shgroup->override_selectid == -1) { \ + /* Hack : get vbo data without actually drawing. */ \ + Gwn_VertBufRaw raw; \ + GWN_vertbuf_attr_get_raw_data(_shgroup->inst_selectid, 0, &raw); \ + select_id = GWN_vertbuf_raw_step(&raw); \ + switch (_shgroup->type) { \ + case DRW_SHG_TRIANGLE_BATCH: _count = 3; break; \ + case DRW_SHG_LINE_BATCH: _count = 2; break; \ + default: _count = 1; break; \ + } \ + } \ + else { \ + GPU_select_load_id(_shgroup->override_selectid); \ + } \ + } \ + while (_start < _shgroup->instance_count) { \ + if (select_id) { \ + GPU_select_load_id(select_id[_start]); \ + } + +# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(_start, _count) \ + _start += _count; \ + } + +#else +# define GPU_SELECT_LOAD_IF_PICKSEL(select_id) +# define GPU_SELECT_LOAD_IF_PICKSEL_CALL(call) +# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) +# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \ + _start = 0; \ + _count = _shgroup->instance_count; + +#endif + + /* Rendering Calls */ + if (!ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)) { + /* Replacing multiple calls with only one */ + if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL)) { + if (shgroup->type == DRW_SHG_INSTANCE_EXTERNAL) { + if (shgroup->instance_geom != NULL) { + GPU_SELECT_LOAD_IF_PICKSEL(shgroup->override_selectid); + draw_geometry_prepare(shgroup, NULL); + draw_geometry_execute_ex(shgroup, shgroup->instance_geom, 0, 0, true); + } + } + else { + if (shgroup->instance_count > 0) { + uint count, start; + draw_geometry_prepare(shgroup, NULL); + GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count) + { + draw_geometry_execute_ex(shgroup, shgroup->instance_geom, start, count, true); + } + GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) + } + } + } + else { /* DRW_SHG_***_BATCH */ + /* Some dynamic batch can have no geom (no call to aggregate) */ + if (shgroup->instance_count > 0) { + uint count, start; + draw_geometry_prepare(shgroup, NULL); + GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count) + { + draw_geometry_execute_ex(shgroup, shgroup->batch_geom, start, count, false); + } + GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) + } + } + } + else { + bool prev_neg_scale = false; + int callid = 0; + for (DRWCall *call = shgroup->calls.first; call; call = call->next) { + + /* OPTI/IDEA(clem): Do this preparation in another thread. */ + draw_visibility_eval(call->state); + draw_matrices_model_prepare(call->state); + + if ((call->state->flag & DRW_CALL_CULLED) != 0 && + (call->state->flag & DRW_CALL_BYPASS_CULLING) == 0) + { + continue; + } + + /* XXX small exception/optimisation for outline rendering. */ + if (shgroup->callid != -1) { + GPU_shader_uniform_vector_int(shgroup->shader, shgroup->callid, 1, 1, &callid); + callid += 1; + } + + /* Negative scale objects */ + bool neg_scale = call->state->flag & DRW_CALL_NEGSCALE; + if (neg_scale != prev_neg_scale) { + glFrontFace((neg_scale) ? DST.backface : DST.frontface); + prev_neg_scale = neg_scale; + } + + GPU_SELECT_LOAD_IF_PICKSEL_CALL(call); + draw_geometry_prepare(shgroup, call->state); + + switch (call->type) { + case DRW_CALL_SINGLE: + draw_geometry_execute(shgroup, call->single.geometry); + break; + case DRW_CALL_INSTANCES: + draw_geometry_execute_ex(shgroup, call->instances.geometry, 0, *call->instances.count, true); + break; + case DRW_CALL_GENERATE: + call->generate.geometry_fn(shgroup, draw_geometry_execute, call->generate.user_data); + break; + case DRW_CALL_PROCEDURAL: + GWN_draw_primitive(call->procedural.prim_type, call->procedural.prim_count); + break; + default: + BLI_assert(0); + } + } + /* Reset state */ + glFrontFace(DST.frontface); + } + + if (use_tfeedback) { + GPU_shader_transform_feedback_disable(shgroup->shader); + } + + /* TODO: remove, (currently causes alpha issue with sculpt, need to investigate) */ + DRW_state_reset(); +} + +static void drw_update_view(void) +{ + if (DST.dirty_mat) { + DST.state_cache_id++; + DST.dirty_mat = false; + + DRW_uniformbuffer_update(view_ubo, &DST.view_data); + + /* Catch integer wrap around. */ + if (UNLIKELY(DST.state_cache_id == 0)) { + DST.state_cache_id = 1; + /* We must reset all CallStates to ensure that not + * a single one stayed with cache_id equal to 1. */ + BLI_mempool_iter iter; + DRWCallState *state; + BLI_mempool_iternew(DST.vmempool->states, &iter); + while ((state = BLI_mempool_iterstep(&iter))) { + state->cache_id = 0; + } + } + + /* TODO dispatch threads to compute matrices/culling */ + } + + draw_clipping_setup_from_view(); +} + +static void drw_draw_pass_ex(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group) +{ + if (start_group == NULL) + return; + + DST.shader = NULL; + + BLI_assert(DST.buffer_finish_called && "DRW_render_instance_buffer_finish had not been called before drawing"); + + drw_update_view(); + + drw_state_set(pass->state); + + DRW_stats_query_start(pass->name); + + for (DRWShadingGroup *shgroup = start_group; shgroup; shgroup = shgroup->next) { + draw_shgroup(shgroup, pass->state); + /* break if upper limit */ + if (shgroup == end_group) { + break; + } + } + + /* Clear Bound textures */ + for (int i = 0; i < GPU_max_textures(); i++) { + if (DST.RST.bound_texs[i] != NULL) { + GPU_texture_unbind(DST.RST.bound_texs[i]); + DST.RST.bound_texs[i] = NULL; + } + } + + /* Clear Bound Ubos */ + for (int i = 0; i < GPU_max_ubo_binds(); i++) { + if (DST.RST.bound_ubos[i] != NULL) { + GPU_uniformbuffer_unbind(DST.RST.bound_ubos[i]); + DST.RST.bound_ubos[i] = NULL; + } + } + + if (DST.shader) { + GPU_shader_unbind(); + DST.shader = NULL; + } + + DRW_stats_query_end(); +} + +void DRW_draw_pass(DRWPass *pass) +{ + drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last); +} + +/* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */ +void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group) +{ + drw_draw_pass_ex(pass, start_group, end_group); +} + +/** \} */ diff --git a/source/blender/draw/intern/draw_manager_profiling.c b/source/blender/draw/intern/draw_manager_profiling.c new file mode 100644 index 00000000000..e4c0877b907 --- /dev/null +++ b/source/blender/draw/intern/draw_manager_profiling.c @@ -0,0 +1,363 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_manager_profiling.c + * \ingroup draw + */ + +#include "BLI_rect.h" +#include "BLI_string.h" + +#include "BKE_global.h" + +#include "BLF_api.h" + +#include "MEM_guardedalloc.h" + +#include "draw_manager.h" + +#include "GPU_glew.h" +#include "GPU_texture.h" + +#include "UI_resources.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "draw_manager_profiling.h" + +#define MAX_TIMER_NAME 32 +#define MAX_NESTED_TIMER 8 +#define CHUNK_SIZE 8 +#define GPU_TIMER_FALLOFF 0.1 + +typedef struct DRWTimer { + GLuint query[2]; + GLuint64 time_average; + char name[MAX_TIMER_NAME]; + int lvl; /* Hierarchy level for nested timer. */ + bool is_query; /* Does this timer actually perform queries or is it just a group. */ +} DRWTimer; + +static struct DRWTimerPool { + DRWTimer *timers; + int chunk_count; /* Number of chunk allocated. */ + int timer_count; /* chunk_count * CHUNK_SIZE */ + int timer_increment; /* Keep track of where we are in the stack. */ + int end_increment; /* Keep track of bad usage. */ + bool is_recording; /* Are we in the render loop? */ + bool is_querying; /* Keep track of bad usage. */ +} DTP = {NULL}; + +void DRW_stats_free(void) +{ + if (DTP.timers != NULL) { + for (int i = 0; i < DTP.timer_count; ++i) { + DRWTimer *timer = &DTP.timers[i]; + glDeleteQueries(2, timer->query); + } + MEM_freeN(DTP.timers); + DTP.timers = NULL; + } +} + +void DRW_stats_begin(void) +{ + if (G.debug_value > 20) { + DTP.is_recording = true; + } + + if (DTP.is_recording && DTP.timers == NULL) { + DTP.chunk_count = 1; + DTP.timer_count = DTP.chunk_count * CHUNK_SIZE; + DTP.timers = MEM_callocN(sizeof(DRWTimer) * DTP.timer_count, "DRWTimer stack"); + } + else if (!DTP.is_recording && DTP.timers != NULL) { + DRW_stats_free(); + } + + DTP.is_querying = false; + DTP.timer_increment = 0; + DTP.end_increment = 0; +} + +static DRWTimer *drw_stats_timer_get(void) +{ + if (UNLIKELY(DTP.timer_increment >= DTP.timer_count)) { + /* Resize the stack. */ + DTP.chunk_count++; + DTP.timer_count = DTP.chunk_count * CHUNK_SIZE; + DTP.timers = MEM_recallocN(DTP.timers, sizeof(DRWTimer) * DTP.timer_count); + } + + return &DTP.timers[DTP.timer_increment++]; +} + +static void drw_stats_timer_start_ex(const char *name, const bool is_query) +{ + if (DTP.is_recording) { + DRWTimer *timer = drw_stats_timer_get(); + BLI_strncpy(timer->name, name, MAX_TIMER_NAME); + timer->lvl = DTP.timer_increment - DTP.end_increment - 1; + timer->is_query = is_query; + + /* Queries cannot be nested or interleaved. */ + BLI_assert(!DTP.is_querying); + if (timer->is_query) { + if (timer->query[0] == 0) { + glGenQueries(1, timer->query); + } + + /* Issue query for the next frame */ + glBeginQuery(GL_TIME_ELAPSED, timer->query[0]); + DTP.is_querying = true; + } + } +} + +/* Use this to group the queries. It does NOT keep track + * of the time, it only sum what the queries inside it. */ +void DRW_stats_group_start(const char *name) +{ + drw_stats_timer_start_ex(name, false); +} + +void DRW_stats_group_end(void) +{ + if (DTP.is_recording) { + BLI_assert(!DTP.is_querying); + DTP.end_increment++; + } +} + +/* NOTE: Only call this when no sub timer will be called. */ +void DRW_stats_query_start(const char *name) +{ + drw_stats_timer_start_ex(name, true); +} + +void DRW_stats_query_end(void) +{ + if (DTP.is_recording) { + DTP.end_increment++; + BLI_assert(DTP.is_querying); + glEndQuery(GL_TIME_ELAPSED); + DTP.is_querying = false; + } +} + +void DRW_stats_reset(void) +{ + BLI_assert((DTP.timer_increment - DTP.end_increment) <= 0 && "You forgot a DRW_stats_group/query_end somewhere!"); + BLI_assert((DTP.timer_increment - DTP.end_increment) >= 0 && "You forgot a DRW_stats_group/query_start somewhere!"); + + if (DTP.is_recording) { + GLuint64 lvl_time[MAX_NESTED_TIMER] = {0}; + + /* Swap queries for the next frame and sum up each lvl time. */ + for (int i = DTP.timer_increment - 1; i >= 0; --i) { + DRWTimer *timer = &DTP.timers[i]; + SWAP(GLuint, timer->query[0], timer->query[1]); + + BLI_assert(timer->lvl < MAX_NESTED_TIMER); + + if (timer->is_query) { + GLuint64 time; + if (timer->query[0] != 0) { + glGetQueryObjectui64v(timer->query[0], GL_QUERY_RESULT, &time); + } + else { + time = 1000000000; /* 1ms default */ + } + + timer->time_average = timer->time_average * (1.0 - GPU_TIMER_FALLOFF) + time * GPU_TIMER_FALLOFF; + timer->time_average = MIN2(timer->time_average, 1000000000); + } + else { + timer->time_average = lvl_time[timer->lvl + 1]; + lvl_time[timer->lvl + 1] = 0; + } + + lvl_time[timer->lvl] += timer->time_average; + } + + DTP.is_recording = false; + } +} + +static void draw_stat_5row(rcti *rect, int u, int v, const char *txt, const int size) +{ + BLF_draw_default_ascii(rect->xmin + (1 + u * 5) * U.widget_unit, + rect->ymax - (3 + v) * U.widget_unit, 0.0f, + txt, size); +} + +static void draw_stat(rcti *rect, int u, int v, const char *txt, const int size) +{ + BLF_draw_default_ascii(rect->xmin + (1 + u) * U.widget_unit, + rect->ymax - (3 + v) * U.widget_unit, 0.0f, + txt, size); +} + +void DRW_stats_draw(rcti *rect) +{ + char stat_string[64]; + int lvl_index[MAX_NESTED_TIMER]; + int v = 0, u = 0; + + double init_tot_time = 0.0, background_tot_time = 0.0, render_tot_time = 0.0, tot_time = 0.0; + + int fontid = BLF_default(); + UI_FontThemeColor(fontid, TH_TEXT_HI); + BLF_enable(fontid, BLF_SHADOW); + BLF_shadow(fontid, 5, (const float[4]){0.0f, 0.0f, 0.0f, 0.75f}); + BLF_shadow_offset(fontid, 0, -1); + + BLF_batch_draw_begin(); + + /* ------------------------------------------ */ + /* ---------------- CPU stats --------------- */ + /* ------------------------------------------ */ + /* Label row */ + char col_label[32]; + sprintf(col_label, "Engine"); + draw_stat_5row(rect, u++, v, col_label, sizeof(col_label)); + sprintf(col_label, "Init"); + draw_stat_5row(rect, u++, v, col_label, sizeof(col_label)); + sprintf(col_label, "Background"); + draw_stat_5row(rect, u++, v, col_label, sizeof(col_label)); + sprintf(col_label, "Render"); + draw_stat_5row(rect, u++, v, col_label, sizeof(col_label)); + sprintf(col_label, "Total (w/o cache)"); + draw_stat_5row(rect, u++, v, col_label, sizeof(col_label)); + v++; + + /* Engines rows */ + char time_to_txt[16]; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + u = 0; + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + + draw_stat_5row(rect, u++, v, engine->idname, sizeof(engine->idname)); + + init_tot_time += data->init_time; + sprintf(time_to_txt, "%.2fms", data->init_time); + draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt)); + + background_tot_time += data->background_time; + sprintf(time_to_txt, "%.2fms", data->background_time); + draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt)); + + render_tot_time += data->render_time; + sprintf(time_to_txt, "%.2fms", data->render_time); + draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt)); + + tot_time += data->init_time + data->background_time + data->render_time; + sprintf(time_to_txt, "%.2fms", data->init_time + data->background_time + data->render_time); + draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt)); + v++; + } + + /* Totals row */ + u = 0; + sprintf(col_label, "Sub Total"); + draw_stat_5row(rect, u++, v, col_label, sizeof(col_label)); + sprintf(time_to_txt, "%.2fms", init_tot_time); + draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt)); + sprintf(time_to_txt, "%.2fms", background_tot_time); + draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt)); + sprintf(time_to_txt, "%.2fms", render_tot_time); + draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt)); + sprintf(time_to_txt, "%.2fms", tot_time); + draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt)); + v += 2; + + u = 0; + double *cache_time = GPU_viewport_cache_time_get(DST.viewport); + sprintf(col_label, "Cache Time"); + draw_stat_5row(rect, u++, v, col_label, sizeof(col_label)); + sprintf(time_to_txt, "%.2fms", *cache_time); + draw_stat_5row(rect, u++, v, time_to_txt, sizeof(time_to_txt)); + v += 2; + + /* ------------------------------------------ */ + /* ---------------- GPU stats --------------- */ + /* ------------------------------------------ */ + + /* Memory Stats */ + uint tex_mem = GPU_texture_memory_usage_get(); + uint vbo_mem = GWN_vertbuf_get_memory_usage(); + + sprintf(stat_string, "GPU Memory"); + draw_stat(rect, 0, v, stat_string, sizeof(stat_string)); + sprintf(stat_string, "%.2fMB", (double)(tex_mem + vbo_mem) / 1000000.0); + draw_stat_5row(rect, 1, v++, stat_string, sizeof(stat_string)); + sprintf(stat_string, "Textures"); + draw_stat(rect, 1, v, stat_string, sizeof(stat_string)); + sprintf(stat_string, "%.2fMB", (double)tex_mem / 1000000.0); + draw_stat_5row(rect, 1, v++, stat_string, sizeof(stat_string)); + sprintf(stat_string, "Meshes"); + draw_stat(rect, 1, v, stat_string, sizeof(stat_string)); + sprintf(stat_string, "%.2fMB", (double)vbo_mem / 1000000.0); + draw_stat_5row(rect, 1, v++, stat_string, sizeof(stat_string)); + v += 1; + + /* GPU Timings */ + BLI_snprintf(stat_string, sizeof(stat_string), "GPU Render Timings"); + draw_stat(rect, 0, v++, stat_string, sizeof(stat_string)); + + for (int i = 0; i < DTP.timer_increment; ++i) { + double time_ms, time_percent; + DRWTimer *timer = &DTP.timers[i]; + DRWTimer *timer_parent = (timer->lvl > 0) ? &DTP.timers[lvl_index[timer->lvl - 1]] : NULL; + + /* Only display a number of lvl at a time */ + if ((G.debug_value - 21) < timer->lvl) continue; + + BLI_assert(timer->lvl < MAX_NESTED_TIMER); + lvl_index[timer->lvl] = i; + + time_ms = timer->time_average / 1000000.0; + + if (timer_parent != NULL) { + time_percent = ((double)timer->time_average / (double)timer_parent->time_average) * 100.0; + } + else { + time_percent = 100.0; + } + + /* avoid very long number */ + time_ms = MIN2(time_ms, 999.0); + time_percent = MIN2(time_percent, 100.0); + + BLI_snprintf(stat_string, sizeof(stat_string), "%s", timer->name); + draw_stat(rect, 0 + timer->lvl, v, stat_string, sizeof(stat_string)); + BLI_snprintf(stat_string, sizeof(stat_string), "%.2fms", time_ms); + draw_stat(rect, 12 + timer->lvl, v, stat_string, sizeof(stat_string)); + BLI_snprintf(stat_string, sizeof(stat_string), "%.0f", time_percent); + draw_stat(rect, 16 + timer->lvl, v, stat_string, sizeof(stat_string)); + v++; + } + + BLF_batch_draw_end(); + BLF_disable(fontid, BLF_SHADOW); +} diff --git a/source/blender/draw/intern/draw_manager_profiling.h b/source/blender/draw/intern/draw_manager_profiling.h new file mode 100644 index 00000000000..233cd3878d2 --- /dev/null +++ b/source/blender/draw/intern/draw_manager_profiling.h @@ -0,0 +1,43 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_manager_profiling.h + * \ingroup draw + */ + +#ifndef __DRAW_MANAGER_PROFILING_H__ +#define __DRAW_MANAGER_PROFILING_H__ + +struct rcti; + +void DRW_stats_free(void); +void DRW_stats_begin(void); +void DRW_stats_reset(void); + +void DRW_stats_group_start(const char *name); +void DRW_stats_group_end(void); + +void DRW_stats_query_start(const char *name); +void DRW_stats_query_end(void); + +void DRW_stats_draw(rcti *rect); + +#endif /* __DRAW_MANAGER_PROFILING_H__ */ diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c new file mode 100644 index 00000000000..56a7c5db08e --- /dev/null +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -0,0 +1,394 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_manager_shader.c + * \ingroup draw + */ + +#include "draw_manager.h" + +#include "DNA_world_types.h" +#include "DNA_material_types.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_string_utils.h" +#include "BLI_threads.h" +#include "BLI_task.h" + +#include "BKE_global.h" +#include "BKE_main.h" + +#include "GPU_shader.h" +#include "GPU_material.h" + +#include "WM_api.h" +#include "WM_types.h" + +extern char datatoc_gpu_shader_2D_vert_glsl[]; +extern char datatoc_gpu_shader_3D_vert_glsl[]; +extern char datatoc_common_fullscreen_vert_glsl[]; + +#define USE_DEFERRED_COMPILATION 1 + +/* -------------------------------------------------------------------- */ + +/** \name Deferred Compilation (DRW_deferred) + * + * Since compiling shader can take a long time, we do it in a non blocking + * manner in another thread. + * + * \{ */ + +typedef struct DRWDeferredShader { + struct DRWDeferredShader *prev, *next; + + GPUMaterial *mat; + char *vert, *geom, *frag, *defs; +} DRWDeferredShader; + +typedef struct DRWShaderCompiler { + ListBase queue; /* DRWDeferredShader */ + SpinLock list_lock; + + DRWDeferredShader *mat_compiling; + ThreadMutex compilation_lock; + + void *ogl_context; + + int shaders_done; /* To compute progress. */ +} DRWShaderCompiler; + +static void drw_deferred_shader_free(DRWDeferredShader *dsh) +{ + /* Make sure it is not queued before freeing. */ + MEM_SAFE_FREE(dsh->vert); + MEM_SAFE_FREE(dsh->geom); + MEM_SAFE_FREE(dsh->frag); + MEM_SAFE_FREE(dsh->defs); + + MEM_freeN(dsh); +} + +static void drw_deferred_shader_queue_free(ListBase *queue) +{ + DRWDeferredShader *dsh; + while ((dsh = BLI_pophead(queue))) { + drw_deferred_shader_free(dsh); + } +} + +static void drw_deferred_shader_compilation_exec(void *custom_data, short *stop, short *do_update, float *progress) +{ + DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data; + void *ogl_context = comp->ogl_context; + + WM_opengl_context_activate(ogl_context); + + while (true) { + BLI_spin_lock(&comp->list_lock); + + if (*stop != 0) { + /* We don't want user to be able to cancel the compilation + * but wm can kill the task if we are closing blender. */ + BLI_spin_unlock(&comp->list_lock); + break; + } + + /* Pop tail because it will be less likely to lock the main thread + * if all GPUMaterials are to be freed (see DRW_deferred_shader_remove()). */ + comp->mat_compiling = BLI_poptail(&comp->queue); + if (comp->mat_compiling == NULL) { + /* No more Shader to compile. */ + BLI_spin_unlock(&comp->list_lock); + break; + } + + comp->shaders_done++; + int total = BLI_listbase_count(&comp->queue) + comp->shaders_done; + + BLI_mutex_lock(&comp->compilation_lock); + BLI_spin_unlock(&comp->list_lock); + + /* Do the compilation. */ + GPU_material_generate_pass( + comp->mat_compiling->mat, + comp->mat_compiling->vert, + comp->mat_compiling->geom, + comp->mat_compiling->frag, + comp->mat_compiling->defs); + + *progress = (float)comp->shaders_done / (float)total; + *do_update = true; + + glFlush(); + BLI_mutex_unlock(&comp->compilation_lock); + + drw_deferred_shader_free(comp->mat_compiling); + } + + WM_opengl_context_release(ogl_context); +} + +static void drw_deferred_shader_compilation_free(void *custom_data) +{ + DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data; + + drw_deferred_shader_queue_free(&comp->queue); + + BLI_spin_end(&comp->list_lock); + BLI_mutex_end(&comp->compilation_lock); + + if (comp->ogl_context) { + /* Only destroy if the job owns the context. */ + WM_opengl_context_dispose(comp->ogl_context); + } + + MEM_freeN(comp); +} + +static void drw_deferred_shader_add( + GPUMaterial *mat, const char *vert, const char *geom, const char *frag_lib, const char *defines) +{ + /* Do not deferre the compilation if we are rendering for image. */ + if (DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION) { + /* Double checking that this GPUMaterial is not going to be + * compiled by another thread. */ + DRW_deferred_shader_remove(mat); + GPU_material_generate_pass(mat, vert, geom, frag_lib, defines); + return; + } + + DRWDeferredShader *dsh = MEM_callocN(sizeof(DRWDeferredShader), "Deferred Shader"); + + dsh->mat = mat; + if (vert) dsh->vert = BLI_strdup(vert); + if (geom) dsh->geom = BLI_strdup(geom); + if (frag_lib) dsh->frag = BLI_strdup(frag_lib); + if (defines) dsh->defs = BLI_strdup(defines); + + BLI_assert(DST.draw_ctx.evil_C); + wmWindowManager *wm = CTX_wm_manager(DST.draw_ctx.evil_C); + wmWindow *win = CTX_wm_window(DST.draw_ctx.evil_C); + Scene *scene = DST.draw_ctx.scene; + + /* Get the running job or a new one if none is running. Can only have one job per type & owner. */ + wmJob *wm_job = WM_jobs_get(wm, win, scene, "Shaders Compilation", + WM_JOB_PROGRESS | WM_JOB_SUSPEND, WM_JOB_TYPE_SHADER_COMPILATION); + + DRWShaderCompiler *old_comp = (DRWShaderCompiler *)WM_jobs_customdata_get(wm_job); + + DRWShaderCompiler *comp = MEM_callocN(sizeof(DRWShaderCompiler), "DRWShaderCompiler"); + BLI_spin_init(&comp->list_lock); + BLI_mutex_init(&comp->compilation_lock); + + if (old_comp) { + BLI_spin_lock(&old_comp->list_lock); + BLI_movelisttolist(&comp->queue, &old_comp->queue); + BLI_spin_unlock(&old_comp->list_lock); + /* Do not recreate context, just pass ownership. */ + comp->ogl_context = old_comp->ogl_context; + old_comp->ogl_context = NULL; + } + + BLI_addtail(&comp->queue, dsh); + + /* Create only one context. */ + if (comp->ogl_context == NULL) { + comp->ogl_context = WM_opengl_context_create(); + WM_opengl_context_activate(DST.ogl_context); + } + + WM_jobs_customdata_set(wm_job, comp, drw_deferred_shader_compilation_free); + WM_jobs_timer(wm_job, 0.1, NC_MATERIAL | ND_SHADING_DRAW, 0); + WM_jobs_callbacks(wm_job, drw_deferred_shader_compilation_exec, NULL, NULL, NULL); + WM_jobs_start(wm, wm_job); +} + +void DRW_deferred_shader_remove(GPUMaterial *mat) +{ + Scene *scene = GPU_material_scene(mat); + + for (wmWindowManager *wm = G.main->wm.first; wm; wm = wm->id.next) { + if (WM_jobs_test(wm, scene, WM_JOB_TYPE_SHADER_COMPILATION) == false) { + /* No job running, do not create a new one by calling WM_jobs_get. */ + continue; + } + for (wmWindow *win = wm->windows.first; win; win = win->next) { + wmJob *wm_job = WM_jobs_get(wm, win, scene, "Shaders Compilation", + WM_JOB_PROGRESS | WM_JOB_SUSPEND, WM_JOB_TYPE_SHADER_COMPILATION); + + DRWShaderCompiler *comp = (DRWShaderCompiler *)WM_jobs_customdata_get(wm_job); + if (comp != NULL) { + BLI_spin_lock(&comp->list_lock); + DRWDeferredShader *dsh; + dsh = (DRWDeferredShader *)BLI_findptr(&comp->queue, mat, offsetof(DRWDeferredShader, mat)); + if (dsh) { + BLI_remlink(&comp->queue, dsh); + } + + /* Wait for compilation to finish */ + if (comp->mat_compiling != NULL) { + if (comp->mat_compiling->mat == mat) { + BLI_mutex_lock(&comp->compilation_lock); + BLI_mutex_unlock(&comp->compilation_lock); + } + } + BLI_spin_unlock(&comp->list_lock); + + if (dsh) { + drw_deferred_shader_free(dsh); + } + } + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines) +{ + return GPU_shader_create(vert, frag, geom, NULL, defines); +} + +GPUShader *DRW_shader_create_with_lib( + const char *vert, const char *geom, const char *frag, const char *lib, const char *defines) +{ + GPUShader *sh; + char *vert_with_lib = NULL; + char *frag_with_lib = NULL; + char *geom_with_lib = NULL; + + vert_with_lib = BLI_string_joinN(lib, vert); + frag_with_lib = BLI_string_joinN(lib, frag); + if (geom) { + geom_with_lib = BLI_string_joinN(lib, geom); + } + + sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines); + + MEM_freeN(vert_with_lib); + MEM_freeN(frag_with_lib); + if (geom) { + MEM_freeN(geom_with_lib); + } + + return sh; +} + +GPUShader *DRW_shader_create_with_transform_feedback( + const char *vert, const char *geom, const char *defines, + const GPUShaderTFBType prim_type, const char **varying_names, const int varying_count) +{ + return GPU_shader_create_ex(vert, NULL, geom, NULL, defines, GPU_SHADER_FLAGS_NONE, + prim_type, varying_names, varying_count); +} + +GPUShader *DRW_shader_create_2D(const char *frag, const char *defines) +{ + return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines); +} + +GPUShader *DRW_shader_create_3D(const char *frag, const char *defines) +{ + return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines); +} + +GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines) +{ + return GPU_shader_create(datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines); +} + +GPUShader *DRW_shader_create_3D_depth_only(void) +{ + return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY); +} + +GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, int options) +{ + GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options); + if (DRW_state_is_image_render()) { + if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) { + /* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX + * with the shader code and we will resume the compilation from there. */ + return NULL; + } + } + return mat; +} + +GPUMaterial *DRW_shader_find_from_material(Material *ma, const void *engine_type, int options) +{ + GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options); + if (DRW_state_is_image_render()) { + if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) { + /* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX + * with the shader code and we will resume the compilation from there. */ + return NULL; + } + } + return mat; +} + +GPUMaterial *DRW_shader_create_from_world( + struct Scene *scene, World *wo, const void *engine_type, int options, + const char *vert, const char *geom, const char *frag_lib, const char *defines) +{ + GPUMaterial *mat = NULL; + if (DRW_state_is_image_render()) { + mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options); + } + + if (mat == NULL) { + mat = GPU_material_from_nodetree( + scene, wo->nodetree, &wo->gpumaterial, engine_type, options); + } + + drw_deferred_shader_add(mat, vert, geom, frag_lib, defines); + + return mat; +} + +GPUMaterial *DRW_shader_create_from_material( + struct Scene *scene, Material *ma, const void *engine_type, int options, + const char *vert, const char *geom, const char *frag_lib, const char *defines) +{ + GPUMaterial *mat = NULL; + if (DRW_state_is_image_render()) { + mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options); + } + + if (mat == NULL) { + mat = GPU_material_from_nodetree( + scene, ma->nodetree, &ma->gpumaterial, engine_type, options); + } + + drw_deferred_shader_add(mat, vert, geom, frag_lib, defines); + + return mat; +} + +void DRW_shader_free(GPUShader *shader) +{ + GPU_shader_free(shader); +} diff --git a/source/blender/draw/intern/draw_manager_text.c b/source/blender/draw/intern/draw_manager_text.c new file mode 100644 index 00000000000..56255af98ce --- /dev/null +++ b/source/blender/draw/intern/draw_manager_text.c @@ -0,0 +1,199 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/** \file blender/draw/intern/draw_manager_text.c + * \ingroup draw + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_math.h" + +#include "BIF_gl.h" + +#include "GPU_matrix.h" + +#include "ED_screen.h" +#include "ED_view3d.h" + +#include "UI_resources.h" +#include "UI_interface.h" + +#include "WM_api.h" +#include "BLF_api.h" + +#include "draw_manager_text.h" + +typedef struct ViewCachedString { + struct ViewCachedString *next, *prev; + float vec[3]; + union { + unsigned char ub[4]; + int pack; + } col; + short sco[2]; + short xoffs; + short flag; + int str_len; + + /* str is allocated past the end */ + char str[0]; +} ViewCachedString; + +typedef struct DRWTextStore { + ListBase list; +} DRWTextStore; + +DRWTextStore *DRW_text_cache_create(void) +{ + DRWTextStore *dt = MEM_callocN(sizeof(*dt), __func__); + return dt; +} + +void DRW_text_cache_destroy(struct DRWTextStore *dt) +{ + BLI_freelistN(&dt->list); + MEM_freeN(dt); +} + +void DRW_text_cache_add( + DRWTextStore *dt, + const float co[3], + const char *str, const int str_len, + short xoffs, short flag, + const unsigned char col[4]) +{ + int alloc_len; + ViewCachedString *vos; + + if (flag & DRW_TEXT_CACHE_STRING_PTR) { + BLI_assert(str_len == strlen(str)); + alloc_len = sizeof(void *); + } + else { + alloc_len = str_len + 1; + } + + vos = MEM_mallocN(sizeof(ViewCachedString) + alloc_len, __func__); + + BLI_addtail(&dt->list, vos); + + copy_v3_v3(vos->vec, co); + copy_v4_v4_uchar(vos->col.ub, col); + vos->xoffs = xoffs; + vos->flag = flag; + vos->str_len = str_len; + + /* allocate past the end */ + if (flag & DRW_TEXT_CACHE_STRING_PTR) { + memcpy(vos->str, &str, alloc_len); + } + else { + memcpy(vos->str, str, alloc_len); + } +} + +void DRW_text_cache_draw( + DRWTextStore *dt, + View3D *v3d, ARegion *ar, bool depth_write) +{ + RegionView3D *rv3d = ar->regiondata; + ViewCachedString *vos; + int tot = 0; + + /* project first and test */ + for (vos = dt->list.first; vos; vos = vos->next) { + if (ED_view3d_project_short_ex( + ar, + (vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob, + (vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0, + vos->vec, vos->sco, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) + { + tot++; + } + else { + vos->sco[0] = IS_CLIPPED; + } + } + + if (tot) { + int col_pack_prev = 0; + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_disable(); + } + + float original_proj[4][4]; + gpuGetProjectionMatrix(original_proj); + wmOrtho2_region_pixelspace(ar); + + gpuPushMatrix(); + gpuLoadIdentity(); + + if (depth_write) { + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + } + else { + glDepthMask(GL_FALSE); + } + + const int font_id = BLF_default(); + + const uiStyle *style = UI_style_get(); + + BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi); + + for (vos = dt->list.first; vos; vos = vos->next) { + if (vos->sco[0] != IS_CLIPPED) { + if (col_pack_prev != vos->col.pack) { + BLF_color4ubv(font_id, vos->col.ub); + col_pack_prev = vos->col.pack; + } + + BLF_position( + font_id, + (float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1]), (depth_write) ? 0.0f : 2.0f); + + ((vos->flag & DRW_TEXT_CACHE_ASCII) ? + BLF_draw_ascii : + BLF_draw + )(font_id, + (vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str, + vos->str_len); + } + } + + if (depth_write) { + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); + } + else { + glDepthMask(GL_TRUE); + } + + gpuPopMatrix(); + gpuLoadProjectionMatrix(original_proj); + + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_enable(); + } + } +} diff --git a/source/blender/draw/intern/draw_manager_text.h b/source/blender/draw/intern/draw_manager_text.h new file mode 100644 index 00000000000..a58e167be0d --- /dev/null +++ b/source/blender/draw/intern/draw_manager_text.h @@ -0,0 +1,54 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/** \file blender/draw/intern/draw_manager_text.h + * \ingroup draw + */ + +#ifndef __DRAW_MANAGER_TEXT_H__ +#define __DRAW_MANAGER_TEXT_H__ + +struct DRWTextStore; + +struct DRWTextStore *DRW_text_cache_create(void); +void DRW_text_cache_destroy(struct DRWTextStore *dt); + +void DRW_text_cache_add( + struct DRWTextStore *dt, + const float co[3], + const char *str, const int str_len, + short xoffs, short flag, + const unsigned char col[4]); + +void DRW_text_cache_draw( + struct DRWTextStore *dt, + struct View3D *v3d, struct ARegion *ar, bool depth_write); + +enum { + DRW_TEXT_CACHE_ASCII = (1 << 0), + DRW_TEXT_CACHE_GLOBALSPACE = (1 << 1), + DRW_TEXT_CACHE_LOCALCLIP = (1 << 2), + /* reference the string by pointer */ + DRW_TEXT_CACHE_STRING_PTR = (1 << 3), +}; + +/* draw_manager.c */ +struct DRWTextStore *DRW_text_cache_ensure(void); + +#endif /* __DRAW_MANAGER_TEXT_H__ */ diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c new file mode 100644 index 00000000000..607b5e19745 --- /dev/null +++ b/source/blender/draw/intern/draw_manager_texture.c @@ -0,0 +1,151 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_manager_texture.c + * \ingroup draw + */ + +#include "draw_manager.h" + +#ifndef NDEBUG +/* Maybe gpu_texture.c is a better place for this. */ +static bool drw_texture_format_supports_framebuffer(GPUTextureFormat format) +{ + /* Some formats do not work with framebuffers. */ + switch (format) { + /* Only add formats that are COMPATIBLE with FB. + * Generally they are multiple of 16bit. */ + case GPU_R16F: + case GPU_R16I: + case GPU_R16UI: + case GPU_R32F: + case GPU_R32UI: + case GPU_RG8: + case GPU_RG16: + case GPU_RG16F: + case GPU_RG16I: + case GPU_RG32F: + case GPU_R11F_G11F_B10F: + case GPU_RGBA8: + case GPU_RGBA16F: + case GPU_RGBA32F: + case GPU_DEPTH_COMPONENT16: + case GPU_DEPTH_COMPONENT24: + case GPU_DEPTH24_STENCIL8: + case GPU_DEPTH_COMPONENT32F: + return true; + default: + return false; + } +} +#endif + +void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags) +{ + GPU_texture_bind(tex, 0); + if (flags & DRW_TEX_MIPMAP) { + GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER); + GPU_texture_generate_mipmap(tex); + } + else { + GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER); + } + GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP); + GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE); + GPU_texture_unbind(tex); +} + +GPUTexture *DRW_texture_create_1D(int w, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels) +{ + GPUTexture *tex = GPU_texture_create_1D(w, format, fpixels, NULL); + drw_texture_set_parameters(tex, flags); + + return tex; +} + +GPUTexture *DRW_texture_create_2D(int w, int h, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels) +{ + GPUTexture *tex = GPU_texture_create_2D(w, h, format, fpixels, NULL); + drw_texture_set_parameters(tex, flags); + + return tex; +} + +GPUTexture *DRW_texture_create_2D_array( + int w, int h, int d, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels) +{ + GPUTexture *tex = GPU_texture_create_2D_array(w, h, d, format, fpixels, NULL); + drw_texture_set_parameters(tex, flags); + + return tex; +} + +GPUTexture *DRW_texture_create_3D( + int w, int h, int d, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels) +{ + GPUTexture *tex = GPU_texture_create_3D(w, h, d, format, fpixels, NULL); + drw_texture_set_parameters(tex, flags); + + return tex; +} + +GPUTexture *DRW_texture_create_cube(int w, GPUTextureFormat format, DRWTextureFlag flags, const float *fpixels) +{ + GPUTexture *tex = GPU_texture_create_cube(w, format, fpixels, NULL); + drw_texture_set_parameters(tex, flags); + + return tex; +} + +GPUTexture *DRW_texture_pool_query_2D(int w, int h, GPUTextureFormat format, DrawEngineType *engine_type) +{ + BLI_assert(drw_texture_format_supports_framebuffer(format)); + GPUTexture *tex = GPU_viewport_texture_pool_query(DST.viewport, engine_type, w, h, format); + + return tex; +} + +void DRW_texture_ensure_fullscreen_2D(GPUTexture **tex, GPUTextureFormat format, DRWTextureFlag flags) +{ + if (*(tex) == NULL) { + const float *size = DRW_viewport_size_get(); + *(tex) = DRW_texture_create_2D((int)size[0], (int)size[1], format, flags, NULL); + } +} + +void DRW_texture_ensure_2D(GPUTexture **tex, int w, int h, GPUTextureFormat format, DRWTextureFlag flags) +{ + if (*(tex) == NULL) { + *(tex) = DRW_texture_create_2D(w, h, format, flags, NULL); + } +} + +void DRW_texture_generate_mipmaps(GPUTexture *tex) +{ + GPU_texture_bind(tex, 0); + GPU_texture_generate_mipmap(tex); + GPU_texture_unbind(tex); +} + +void DRW_texture_free(GPUTexture *tex) +{ + GPU_texture_free(tex); +} diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c new file mode 100644 index 00000000000..726d77a9925 --- /dev/null +++ b/source/blender/draw/intern/draw_view.c @@ -0,0 +1,757 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_view.c + * \ingroup draw + * + * Contains dynamic drawing using immediate mode + */ + +#include "DNA_brush_types.h" +#include "DNA_screen_types.h" +#include "DNA_userdef_types.h" +#include "DNA_view3d_types.h" + +#include "ED_screen.h" +#include "ED_transform.h" +#include "ED_view3d.h" + +#include "GPU_draw.h" +#include "GPU_shader.h" +#include "GPU_immediate.h" +#include "GPU_matrix.h" + +#include "UI_resources.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "BKE_global.h" +#include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_unit.h" + +#include "DRW_render.h" + +#include "view3d_intern.h" + +#include "draw_view.h" + +/* ******************** region info ***************** */ + +void DRW_draw_region_info(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + ARegion *ar = draw_ctx->ar; + int offset; + + DRW_draw_cursor(); + + offset = DRW_draw_region_engine_info_offset(); + + view3d_draw_region_info(draw_ctx->evil_C, ar, offset); + + if (offset > 0) { + DRW_draw_region_engine_info(); + } +} + +/* ************************* Grid ************************** */ + +static void gridline_range(double x0, double dx, double max, int *r_first, int *r_count) +{ + /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y + * x0 is gridline 0, the axis in screen space + * Area covers [0 .. max) pixels */ + + int first = (int)ceil(-x0 / dx); + int last = (int)floor((max - x0) / dx); + + if (first <= last) { + *r_first = first; + *r_count = last - first + 1; + } + else { + *r_first = 0; + *r_count = 0; + } +} + +static int gridline_count(ARegion *ar, double x0, double y0, double dx) +{ + /* x0 & y0 establish the "phase" of the grid within this 2D region + * dx is the frequency, shared by x & y directions + * pass in dx of smallest (highest precision) grid we want to draw */ + + int first, x_ct, y_ct; + + gridline_range(x0, dx, ar->winx, &first, &x_ct); + gridline_range(y0, dx, ar->winy, &first, &y_ct); + + int total_ct = x_ct + y_ct; + + return total_ct; +} + +static bool drawgrid_draw( + ARegion *ar, double x0, double y0, double dx, int skip_mod, + unsigned pos, unsigned col, GLubyte col_value[3]) +{ + /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw + * always skip exact x0 & y0 axes; they will be drawn later in color + * + * set grid color once, just before the first line is drawn + * it's harmless to set same color for every line, or every vertex + * but if no lines are drawn, color must not be set! */ + + const float x_max = (float)ar->winx; + const float y_max = (float)ar->winy; + + int first, ct; + int x_ct = 0, y_ct = 0; /* count of lines actually drawn */ + int lines_skipped_for_next_unit = 0; + + /* draw vertical lines */ + gridline_range(x0, dx, x_max, &first, &ct); + + for (int i = first; i < first + ct; ++i) { + if (i == 0) + continue; + else if (skip_mod && (i % skip_mod) == 0) { + ++lines_skipped_for_next_unit; + continue; + } + + if (x_ct == 0) + immAttrib3ub(col, col_value[0], col_value[1], col_value[2]); + + float x = (float)(x0 + i * dx); + immVertex2f(pos, x, 0.0f); + immVertex2f(pos, x, y_max); + ++x_ct; + } + + /* draw horizontal lines */ + gridline_range(y0, dx, y_max, &first, &ct); + + for (int i = first; i < first + ct; ++i) { + if (i == 0) + continue; + else if (skip_mod && (i % skip_mod) == 0) { + ++lines_skipped_for_next_unit; + continue; + } + + if (x_ct + y_ct == 0) + immAttrib3ub(col, col_value[0], col_value[1], col_value[2]); + + float y = (float)(y0 + i * dx); + immVertex2f(pos, 0.0f, y); + immVertex2f(pos, x_max, y); + ++y_ct; + } + + return lines_skipped_for_next_unit > 0; +} + +#define GRID_MIN_PX_D 6.0 +#define GRID_MIN_PX_F 6.0f + +static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit) +{ + RegionView3D *rv3d = ar->regiondata; + + double fx = rv3d->persmat[3][0]; + double fy = rv3d->persmat[3][1]; + double fw = rv3d->persmat[3][3]; + + const double wx = 0.5 * ar->winx; /* use double precision to avoid rounding errors */ + const double wy = 0.5 * ar->winy; + + double x = wx * fx / fw; + double y = wy * fy / fw; + + double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 }; + mul_m4_v4d(rv3d->persmat, vec4); + fx = vec4[0]; + fy = vec4[1]; + fw = vec4[3]; + + double dx = fabs(x - wx * fx / fw); + if (dx == 0) dx = fabs(y - wy * fy / fw); + + x += wx; + y += wy; + + /* now x, y, and dx have their final values + * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space + * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */ + + glLineWidth(1.0f); + +#if 0 /* TODO: write to UI/widget depth buffer, not scene depth */ + glDepthMask(GL_FALSE); /* disable write in zbuffer */ +#endif + + Gwn_VertFormat *format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + + unsigned char col[3], col2[3]; + UI_GetThemeColor3ubv(TH_GRID, col); + + if (unit->system) { + const void *usys; + int len; + + bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len); + + bool first = true; + + if (usys) { + int i = len; + while (i--) { + double scalar = bUnit_GetScaler(usys, i); + + double dx_scalar = dx * scalar / (double)unit->scale_length; + if (dx_scalar < (GRID_MIN_PX_D * 2.0)) { + /* very very small grid items are less useful when dealing with units */ + continue; + } + + if (first) { + first = false; + + /* Store the smallest drawn grid size units name so users know how big each grid cell is */ + *grid_unit = bUnit_GetNameDisplay(usys, i); + rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length); + + int gridline_ct = gridline_count(ar, x, y, dx_scalar); + if (gridline_ct == 0) + goto drawgrid_cleanup; /* nothing to draw */ + + immBegin(GWN_PRIM_LINES, gridline_ct * 2); + } + + float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar); + /* tweak to have the fade a bit nicer */ + blend_fac = (blend_fac * blend_fac) * 2.0f; + CLAMP(blend_fac, 0.3f, 1.0f); + + UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2); + + const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar); + if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2)) + break; + } + } + } + else { + const double sublines = v3d->gridsubdiv; + const float sublines_fl = v3d->gridsubdiv; + + int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */ + + if (dx < GRID_MIN_PX_D) { + rv3d->gridview *= sublines_fl; + dx *= sublines; + if (dx < GRID_MIN_PX_D) { + rv3d->gridview *= sublines_fl; + dx *= sublines; + if (dx < GRID_MIN_PX_D) { + rv3d->gridview *= sublines_fl; + dx *= sublines; + grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1; + } + } + } + else { + if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ + rv3d->gridview /= sublines_fl; + dx /= sublines; + if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */ + rv3d->gridview /= sublines_fl; + dx /= sublines; + if (dx > (GRID_MIN_PX_D * 10.0)) { + grids_to_draw = 1; + } + } + } + } + + int gridline_ct = gridline_count(ar, x, y, dx); + if (gridline_ct == 0) + goto drawgrid_cleanup; /* nothing to draw */ + + immBegin(GWN_PRIM_LINES, gridline_ct * 2); + + if (grids_to_draw == 2) { + UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2); + if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2)) { + drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col); + } + } + else if (grids_to_draw == 1) { + drawgrid_draw(ar, x, y, dx, 0, pos, color, col); + } + } + + /* draw visible axes */ + /* horizontal line */ + if (0 <= y && y < ar->winy) { + UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X'); + immAttrib3ub(color, col2[0], col2[1], col2[2]); + immVertex2f(pos, 0.0f, y); + immVertex2f(pos, (float)ar->winx, y); + } + + /* vertical line */ + if (0 <= x && x < ar->winx) { + UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z'); + immAttrib3ub(color, col2[0], col2[1], col2[2]); + immVertex2f(pos, x, 0.0f); + immVertex2f(pos, x, (float)ar->winy); + } + + immEnd(); + +drawgrid_cleanup: + immUnbindProgram(); + +#if 0 /* depth write is left enabled above */ + glDepthMask(GL_TRUE); /* enable write in zbuffer */ +#endif +} + +#undef DEBUG_GRID +#undef GRID_MIN_PX_D +#undef GRID_MIN_PX_F + +static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) +{ + /* draw only if there is something to draw */ + if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) { + /* draw how many lines? + * trunc(v3d->gridlines / 2) * 4 + * + 2 for xy axes (possibly with special colors) + * + 1 for z axis (the only line not in xy plane) + * even v3d->gridlines are honored, odd rounded down */ + const int gridlines = v3d->gridlines / 2; + const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); + const float grid = gridlines * grid_scale; + + const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1; + + bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0; + bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0; + bool show_axis_z = (v3d->gridflag & V3D_SHOW_Z) != 0; + + unsigned char col_grid[3], col_axis[3]; + + glLineWidth(1.0f); + + UI_GetThemeColor3ubv(TH_GRID, col_grid); + + if (show_floor) { + const unsigned vertex_ct = 2 * (gridlines * 4 + 2); + const int sublines = v3d->gridsubdiv; + + unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3]; + + Gwn_VertFormat *format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBegin(GWN_PRIM_LINES, vertex_ct); + + /* draw normal grid lines */ + UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10); + + for (int a = 1; a <= gridlines; a++) { + /* skip emphasised divider lines */ + if (a % sublines != 0) { + const float line = a * grid_scale; + + immAttrib3ubv(color, col_grid_light); + + immVertex2f(pos, -grid, -line); + immVertex2f(pos, +grid, -line); + immVertex2f(pos, -grid, +line); + immVertex2f(pos, +grid, +line); + + immVertex2f(pos, -line, -grid); + immVertex2f(pos, -line, +grid); + immVertex2f(pos, +line, -grid); + immVertex2f(pos, +line, +grid); + } + } + + /* draw emphasised grid lines */ + UI_GetThemeColor3ubv(TH_BACK, col_bg); + /* emphasise division lines lighter instead of darker, if background is darker than grid */ + UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise, + (col_grid[0] + col_grid[1] + col_grid[2] + 30 > + col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10); + + if (sublines <= gridlines) { + immAttrib3ubv(color, col_grid_emphasise); + + for (int a = sublines; a <= gridlines; a += sublines) { + const float line = a * grid_scale; + + immVertex2f(pos, -grid, -line); + immVertex2f(pos, +grid, -line); + immVertex2f(pos, -grid, +line); + immVertex2f(pos, +grid, +line); + + immVertex2f(pos, -line, -grid); + immVertex2f(pos, -line, +grid); + immVertex2f(pos, +line, -grid); + immVertex2f(pos, +line, +grid); + } + } + + /* draw X axis */ + if (show_axis_x) { + show_axis_x = false; /* drawing now, won't need to draw later */ + UI_make_axis_color(col_grid, col_axis, 'X'); + immAttrib3ubv(color, col_axis); + } + else + immAttrib3ubv(color, col_grid_emphasise); + + immVertex2f(pos, -grid, 0.0f); + immVertex2f(pos, +grid, 0.0f); + + /* draw Y axis */ + if (show_axis_y) { + show_axis_y = false; /* drawing now, won't need to draw later */ + UI_make_axis_color(col_grid, col_axis, 'Y'); + immAttrib3ubv(color, col_axis); + } + else + immAttrib3ubv(color, col_grid_emphasise); + + immVertex2f(pos, 0.0f, -grid); + immVertex2f(pos, 0.0f, +grid); + + immEnd(); + immUnbindProgram(); + + /* done with XY plane */ + } + + if (show_axis_x || show_axis_y || show_axis_z) { + /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */ + + Gwn_VertFormat *format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + uint color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + immBegin(GWN_PRIM_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2); + + if (show_axis_x) { + UI_make_axis_color(col_grid, col_axis, 'X'); + immAttrib3ubv(color, col_axis); + immVertex3f(pos, -grid, 0.0f, 0.0f); + immVertex3f(pos, +grid, 0.0f, 0.0f); + } + + if (show_axis_y) { + UI_make_axis_color(col_grid, col_axis, 'Y'); + immAttrib3ubv(color, col_axis); + immVertex3f(pos, 0.0f, -grid, 0.0f); + immVertex3f(pos, 0.0f, +grid, 0.0f); + } + + if (show_axis_z) { + UI_make_axis_color(col_grid, col_axis, 'Z'); + immAttrib3ubv(color, col_axis); + immVertex3f(pos, 0.0f, 0.0f, -grid); + immVertex3f(pos, 0.0f, 0.0f, +grid); + } + + immEnd(); + immUnbindProgram(); + } + } +} + +void DRW_draw_grid(void) +{ + /* TODO viewport + * Missing is the flags to check whether to draw it + * for now now we are using the flags in v3d itself. + * + * Also for now always assume depth is there, so we + * draw on top of it. + */ + /** + * Calculate pixel-size factor once, is used for lamps and object centers. + * Used by #ED_view3d_pixel_size and typically not accessed directly. + * + * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value, + * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value, + * but in perspective mode its offset by the near-clip. + * + * 'RegionView3D.pixsize' is used for viewport drawing, not rendering. + */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + View3D *v3d = draw_ctx->v3d; + ARegion *ar = draw_ctx->ar; + RegionView3D *rv3d = draw_ctx->rv3d; + + const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); + const char *grid_unit = NULL; + + /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override + * objects if done last + * needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views. + */ + rv3d->gridview = ED_view3d_grid_scale(scene, v3d, &grid_unit); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + if (!draw_floor) { + /* Do not get in front of overlays */ + glDepthMask(GL_FALSE); + + ED_region_pixelspace(ar); + *(&grid_unit) = NULL; /* drawgrid need this to detect/affect smallest valid unit... */ + drawgrid(&scene->unit, ar, v3d, &grid_unit); + + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); + } + else { + glDepthMask(GL_TRUE); + drawfloor(scene, v3d, &grid_unit); + } +} + +/* ************************* Background ************************** */ + +void DRW_draw_background(void) +{ + /* Just to make sure */ + glDepthMask(GL_TRUE); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glStencilMask(0xFF); + + if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { + float m[4][4]; + unit_m4(m); + + /* Gradient background Color */ + glDisable(GL_DEPTH_TEST); + + Gwn_VertFormat *format = immVertexFormat(); + unsigned pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + unsigned color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + unsigned char col_hi[3], col_lo[3]; + + gpuPushMatrix(); + gpuLoadIdentity(); + gpuLoadProjectionMatrix(m); + + immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR_DITHER); + + UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo); + UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi); + + immBegin(GWN_PRIM_TRI_FAN, 4); + immAttrib3ubv(color, col_lo); + immVertex2f(pos, -1.0f, -1.0f); + immVertex2f(pos, 1.0f, -1.0f); + + immAttrib3ubv(color, col_hi); + immVertex2f(pos, 1.0f, 1.0f); + immVertex2f(pos, -1.0f, 1.0f); + immEnd(); + + immUnbindProgram(); + + gpuPopMatrix(); + + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + glEnable(GL_DEPTH_TEST); + } + else { + /* Solid background Color */ + UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } +} + +/* **************************** 3D Cursor ******************************** */ + +static bool is_cursor_visible(const DRWContextState *draw_ctx, Scene *scene, ViewLayer *view_layer) +{ + Object *ob = OBACT(view_layer); + View3D *v3d = draw_ctx->v3d; + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) > 0 || (v3d->overlay.flag & V3D_OVERLAY_HIDE_CURSOR)) { + return false; + } + + /* don't draw cursor in paint modes, but with a few exceptions */ + if (ob && draw_ctx->object_mode & OB_MODE_ALL_PAINT) { + /* exception: object is in weight paint and has deforming armature in pose mode */ + if (draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) { + if (BKE_object_pose_armature_get(ob) != NULL) { + return true; + } + } + /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */ + else if (draw_ctx->object_mode & OB_MODE_TEXTURE_PAINT) { + const Paint *p = BKE_paint_get_active(scene, view_layer); + + if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) { + if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) { + return true; + } + } + } + + /* no exception met? then don't draw cursor! */ + return false; + } + + return true; +} + +void DRW_draw_cursor(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + ARegion *ar = draw_ctx->ar; + Scene *scene = draw_ctx->scene; + ViewLayer *view_layer = draw_ctx->view_layer; + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + + if (is_cursor_visible(draw_ctx, scene, view_layer)) { + int co[2]; + const View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d); + if (ED_view3d_project_int_global( + ar, cursor->location, co, V3D_PROJ_TEST_NOP | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) + { + RegionView3D *rv3d = ar->regiondata; + + /* Draw nice Anti Aliased cursor. */ + glLineWidth(1.0f); + glEnable(GL_BLEND); + glEnable(GL_LINE_SMOOTH); + + float eps = 1e-5f; + rv3d->viewquat[0] = -rv3d->viewquat[0]; + const bool is_aligned = compare_v4v4(cursor->rotation, rv3d->viewquat, eps); + rv3d->viewquat[0] = -rv3d->viewquat[0]; + + /* Draw lines */ + if (is_aligned == false) { + uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor3(TH_VIEW_OVERLAY); + immBegin(GWN_PRIM_LINES, 12); + + const float scale = ED_view3d_pixel_size_no_ui_scale(rv3d, cursor->location) * U.widget_unit; + +#define CURSOR_VERT(axis_vec, axis, fac) \ + immVertex3f( \ + pos, \ + cursor->location[0] + axis_vec[0] * (fac), \ + cursor->location[1] + axis_vec[1] * (fac), \ + cursor->location[2] + axis_vec[2] * (fac)) + +#define CURSOR_EDGE(axis_vec, axis, sign) { \ + CURSOR_VERT(axis_vec, axis, sign 1.0f); \ + CURSOR_VERT(axis_vec, axis, sign 0.25f); \ + } + + for (int axis = 0; axis < 3; axis++) { + float axis_vec[3] = {0}; + axis_vec[axis] = scale; + mul_qt_v3(cursor->rotation, axis_vec); + CURSOR_EDGE(axis_vec, axis, +); + CURSOR_EDGE(axis_vec, axis, -); + } + +#undef CURSOR_VERT +#undef CURSOR_EDGE + + immEnd(); + immUnbindProgram(); + } + + ED_region_pixelspace(ar); + gpuTranslate2f(co[0] + 0.5f, co[1] + 0.5f); + gpuScale2f(U.widget_unit, U.widget_unit); + + Gwn_Batch *cursor_batch = DRW_cache_cursor_get(is_aligned); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR); + GWN_batch_program_set(cursor_batch, GPU_shader_get_program(shader), GPU_shader_get_interface(shader)); + + GWN_batch_draw(cursor_batch); + } + } +} + +/* **************************** 3D Manipulator ******************************** */ + +void DRW_draw_manipulator_3d(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + v3d->zbuf = false; + ARegion *ar = draw_ctx->ar; + + /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */ + /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should + * later become _IN_SCENE (and draw _3D separate) */ + WM_manipulatormap_draw( + ar->manipulator_map, draw_ctx->evil_C, + WM_MANIPULATORMAP_DRAWSTEP_3D); + +} + +void DRW_draw_manipulator_2d(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + v3d->zbuf = false; + ARegion *ar = draw_ctx->ar; + + WM_manipulatormap_draw( + ar->manipulator_map, draw_ctx->evil_C, + WM_MANIPULATORMAP_DRAWSTEP_2D); + + glDepthMask(GL_TRUE); +} diff --git a/source/blender/draw/intern/draw_view.h b/source/blender/draw/intern/draw_view.h new file mode 100644 index 00000000000..203420483a7 --- /dev/null +++ b/source/blender/draw/intern/draw_view.h @@ -0,0 +1,36 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_view.h + * \ingroup draw + */ + +#ifndef __DRAW_VIEW_H__ +#define __DRAW_VIEW_H__ + +void DRW_draw_grid(void); +void DRW_draw_region_info(void); +void DRW_draw_background(void); +void DRW_draw_cursor(void); +void DRW_draw_manipulator_3d(void); +void DRW_draw_manipulator_2d(void); + +#endif /* __DRAW_VIEW_H__ */ diff --git a/source/blender/draw/modes/draw_mode_engines.h b/source/blender/draw/modes/draw_mode_engines.h new file mode 100644 index 00000000000..9522e3cddc6 --- /dev/null +++ b/source/blender/draw/modes/draw_mode_engines.h @@ -0,0 +1,45 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/draw_mode_engines.h + * \ingroup draw + */ + +#ifndef __DRAW_MODE_ENGINES_H__ +#define __DRAW_MODE_ENGINES_H__ + +extern DrawEngineType draw_engine_object_type; +extern DrawEngineType draw_engine_edit_armature_type; +extern DrawEngineType draw_engine_edit_curve_type; +extern DrawEngineType draw_engine_edit_lattice_type; +extern DrawEngineType draw_engine_edit_mesh_type; +extern DrawEngineType draw_engine_edit_metaball_type; +extern DrawEngineType draw_engine_edit_surface_type; +extern DrawEngineType draw_engine_edit_text_type; +extern DrawEngineType draw_engine_paint_texture_type; +extern DrawEngineType draw_engine_paint_vertex_type; +extern DrawEngineType draw_engine_paint_weight_type; +extern DrawEngineType draw_engine_particle_type; +extern DrawEngineType draw_engine_pose_type; +extern DrawEngineType draw_engine_sculpt_type; +extern DrawEngineType draw_engine_overlay_type; + +#endif /* __DRAW_MODE_ENGINES_H__ */ diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c new file mode 100644 index 00000000000..285e703afbf --- /dev/null +++ b/source/blender/draw/modes/edit_armature_mode.c @@ -0,0 +1,183 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/edit_armature_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_armature_types.h" +#include "DNA_view3d_types.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +extern GlobalsUboStorage ts; + +/* *********** LISTS *********** */ +typedef struct EDIT_ARMATURE_PassList { + struct DRWPass *bone_solid; + struct DRWPass *bone_wire; + struct DRWPass *bone_outline; + struct DRWPass *bone_envelope; + struct DRWPass *bone_axes; + struct DRWPass *relationship; +} EDIT_ARMATURE_PassList; + +typedef struct EDIT_ARMATURE_StorageList { + struct EDIT_ARMATURE_PrivateData *g_data; +} EDIT_ARMATURE_StorageList; + +typedef struct EDIT_ARMATURE_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + EDIT_ARMATURE_PassList *psl; + EDIT_ARMATURE_StorageList *stl; +} EDIT_ARMATURE_Data; + +/* *********** STATIC *********** */ + +typedef struct EDIT_ARMATURE_PrivateData { + char pad; /* UNUSED */ +} EDIT_ARMATURE_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +static void EDIT_ARMATURE_cache_init(void *vedata) +{ + EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl; + EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Solid bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; + psl->bone_solid = DRW_pass_create("Bone Solid Pass", state); + } + + { + /* Bones Outline */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + psl->bone_outline = DRW_pass_create("Bone Outline Pass", state); + } + + { + /* Wire bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND; + psl->bone_wire = DRW_pass_create("Bone Wire Pass", state); + } + + { + /* distance outline around envelope bones */ + DRWState state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_FRONT; + psl->bone_envelope = DRW_pass_create("Bone Envelope Outline Pass", state); + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WIRE_SMOOTH | DRW_STATE_BLEND; + psl->bone_axes = DRW_pass_create("Bone Axes Pass", state); + } + + { + /* Non Meshes Pass (Camera, empties, lamps ...) */ + DRWState state = + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE; + psl->relationship = DRW_pass_create("Bone Relationship Pass", state); + } +} + +static void EDIT_ARMATURE_cache_populate(void *vedata, Object *ob) +{ + bArmature *arm = ob->data; + EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl; + + if (ob->type == OB_ARMATURE) { + if (arm->edbo) { + DRWArmaturePasses passes = { + .bone_solid = psl->bone_solid, + .bone_outline = psl->bone_outline, + .bone_wire = psl->bone_wire, + .bone_envelope = psl->bone_envelope, + .bone_axes = psl->bone_axes, + .relationship_lines = psl->relationship, + }; + DRW_shgroup_armature_edit(ob, passes); + } + } +} + +static void EDIT_ARMATURE_draw_scene(void *vedata) +{ + EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0; + + DRW_draw_pass(psl->bone_envelope); + + if (transparent_bones) { + DRW_pass_state_add(psl->bone_solid, DRW_STATE_BLEND); + DRW_pass_state_remove(psl->bone_solid, DRW_STATE_WRITE_DEPTH); + DRW_draw_pass(psl->bone_solid); + } + + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl) + + if (!transparent_bones) { + DRW_draw_pass(psl->bone_solid); + } + + DRW_draw_pass(psl->bone_outline); + DRW_draw_pass(psl->bone_wire); + DRW_draw_pass(psl->relationship); + + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl) + + /* Draw axes with linesmooth and outside of multisample buffer. */ + DRW_draw_pass(psl->bone_axes); +} + +static const DrawEngineDataSize EDIT_ARMATURE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_ARMATURE_Data); + +DrawEngineType draw_engine_edit_armature_type = { + NULL, NULL, + N_("EditArmatureMode"), + &EDIT_ARMATURE_data_size, + NULL, + NULL, + &EDIT_ARMATURE_cache_init, + &EDIT_ARMATURE_cache_populate, + NULL, + NULL, + &EDIT_ARMATURE_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c new file mode 100644 index 00000000000..50ce29b7b1a --- /dev/null +++ b/source/blender/draw/modes/edit_curve_mode.c @@ -0,0 +1,337 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/edit_curve_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_curve_types.h" +#include "DNA_view3d_types.h" + +#include "BKE_object.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" +#include "GPU_batch.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +/* If needed, contains all global/Theme colors + * Add needed theme colors / values to DRW_globals_update() and update UBO + * Not needed for constant color. */ +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ + +extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_edit_curve_overlay_loosevert_vert_glsl[]; +extern char datatoc_edit_curve_overlay_frag_glsl[]; +extern char datatoc_edit_curve_overlay_handle_geom_glsl[]; + +extern char datatoc_gpu_shader_3D_vert_glsl[]; +extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; +extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[]; +extern char datatoc_gpu_shader_flat_color_frag_glsl[]; + +/* *********** LISTS *********** */ +/* All lists are per viewport specific datas. + * They are all free when viewport changes engines + * or is free itself. Use EDIT_CURVE_engine_init() to + * initialize most of them and EDIT_CURVE_cache_init() + * for EDIT_CURVE_PassList */ + +typedef struct EDIT_CURVE_PassList { + /* Declare all passes here and init them in + * EDIT_CURVE_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *wire_pass; + struct DRWPass *overlay_edge_pass; + struct DRWPass *overlay_vert_pass; +} EDIT_CURVE_PassList; + +typedef struct EDIT_CURVE_FramebufferList { + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; +} EDIT_CURVE_FramebufferList; + +typedef struct EDIT_CURVE_TextureList { + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; +} EDIT_CURVE_TextureList; + +typedef struct EDIT_CURVE_StorageList { + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct EDIT_CURVE_PrivateData *g_data; +} EDIT_CURVE_StorageList; + +typedef struct EDIT_CURVE_Data { + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + EDIT_CURVE_FramebufferList *fbl; + EDIT_CURVE_TextureList *txl; + EDIT_CURVE_PassList *psl; + EDIT_CURVE_StorageList *stl; +} EDIT_CURVE_Data; + +/* *********** STATIC *********** */ + +static struct { + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in EDIT_CURVE_engine_init(); + * free in EDIT_CURVE_engine_free(); */ + + GPUShader *wire_sh; + + GPUShader *overlay_edge_sh; /* handles and nurbs control cage */ + GPUShader *overlay_vert_sh; + +} e_data = {NULL}; /* Engine data */ + +typedef struct EDIT_CURVE_PrivateData { + /* This keeps the references of the shading groups for + * easy access in EDIT_CURVE_cache_populate() */ + + /* resulting curve as 'wire' for curves (and optionally normals) */ + DRWShadingGroup *wire_shgrp; + + DRWShadingGroup *overlay_edge_shgrp; + DRWShadingGroup *overlay_vert_shgrp; +} EDIT_CURVE_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +/* Init Textures, Framebuffers, Storage and Shaders. + * It is called for every frames. + * (Optional) */ +static void EDIT_CURVE_engine_init(void *vedata) +{ + EDIT_CURVE_TextureList *txl = ((EDIT_CURVE_Data *)vedata)->txl; + EDIT_CURVE_FramebufferList *fbl = ((EDIT_CURVE_Data *)vedata)->fbl; + EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl; + + UNUSED_VARS(txl, fbl, stl); + + /* Init Framebuffers like this: order is attachment order (for color texs) */ + /* + * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, + * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; + */ + + /* DRW_framebuffer_init takes care of checking if + * the framebuffer is valid and has the right size*/ + /* + * float *viewport_size = DRW_viewport_size_get(); + * DRW_framebuffer_init(&fbl->occlude_wire_fb, + * (int)viewport_size[0], (int)viewport_size[1], + * tex, 2); + */ + + if (!e_data.wire_sh) { + e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } + + if (!e_data.overlay_edge_sh) { + e_data.overlay_edge_sh = DRW_shader_create_with_lib( + datatoc_edit_curve_overlay_loosevert_vert_glsl, + datatoc_edit_curve_overlay_handle_geom_glsl, + datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + } + + if (!e_data.overlay_vert_sh) { + e_data.overlay_vert_sh = DRW_shader_create_with_lib( + datatoc_edit_curve_overlay_loosevert_vert_glsl, NULL, + datatoc_edit_curve_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + } +} + +/* Here init all passes and shading groups + * Assume that all Passes are NULL */ +static void EDIT_CURVE_cache_init(void *vedata) +{ + EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl; + EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + DRWShadingGroup *grp; + + /* Center-Line (wire) */ + psl->wire_pass = DRW_pass_create( + "Curve Wire", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + + grp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass); + DRW_shgroup_uniform_vec4(grp, "color", ts.colorWireEdit, 1); + stl->g_data->wire_shgrp = grp; + + + psl->overlay_edge_pass = DRW_pass_create( + "Curve Handle Overlay", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_WIRE); + + grp = DRW_shgroup_create(e_data.overlay_edge_sh, psl->overlay_edge_pass); + DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + stl->g_data->overlay_edge_shgrp = grp; + + + psl->overlay_vert_pass = DRW_pass_create( + "Curve Vert Overlay", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_POINT); + + grp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_vert_pass); + DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + stl->g_data->overlay_vert_shgrp = grp; + } + +} + +/* Add geometry to shadingGroups. Execute for each objects */ +static void EDIT_CURVE_cache_populate(void *vedata, Object *ob) +{ + EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl; + EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + UNUSED_VARS(psl, stl); + + if (ob->type == OB_CURVE) { +#if 0 + if (ob == draw_ctx->object_edit) +#else + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) +#endif + { + Curve *cu = ob->data; + /* Get geometry cache */ + struct Gwn_Batch *geom; + + geom = DRW_cache_curve_edge_wire_get(ob); + DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); + + if ((cu->flag & CU_3D) && (cu->drawflag & CU_HIDE_NORMALS) == 0) { + geom = DRW_cache_curve_edge_normal_get(ob, v3d->overlay.normals_length); + DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); + } + + /* Add geom to a shading group */ + geom = DRW_cache_curve_edge_overlay_get(ob); + if (geom) { + DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat); + } + + geom = DRW_cache_curve_vert_overlay_get(ob); + DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat); + } + } +} + +/* Optional: Post-cache_populate callback */ +static void EDIT_CURVE_cache_finish(void *vedata) +{ + EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl; + EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl; + + /* Do something here! dependant on the objects gathered */ + UNUSED_VARS(psl, stl); +} + +/* Draw time ! Control rendering pipeline from here */ +static void EDIT_CURVE_draw_scene(void *vedata) +{ + EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl; + EDIT_CURVE_FramebufferList *fbl = ((EDIT_CURVE_Data *)vedata)->fbl; + + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + UNUSED_VARS(fbl); + + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl) + + /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ + /* + * DRW_framebuffer_texture_detach(dtxl->depth); + * DRW_framebuffer_bind(fbl->custom_fb); + * DRW_draw_pass(psl->pass); + * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); + * DRW_framebuffer_bind(dfbl->default_fb); + */ + + /* ... or just render passes on default framebuffer. */ + DRW_draw_pass(psl->wire_pass); + DRW_draw_pass(psl->overlay_edge_pass); + DRW_draw_pass(psl->overlay_vert_pass); + + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl) + + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ +} + +/* Cleanup when destroying the engine. + * This is not per viewport ! only when quitting blender. + * Mostly used for freeing shaders */ +static void EDIT_CURVE_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.overlay_edge_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh); +} + +static const DrawEngineDataSize EDIT_CURVE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_CURVE_Data); + +DrawEngineType draw_engine_edit_curve_type = { + NULL, NULL, + N_("EditCurveMode"), + &EDIT_CURVE_data_size, + &EDIT_CURVE_engine_init, + &EDIT_CURVE_engine_free, + &EDIT_CURVE_cache_init, + &EDIT_CURVE_cache_populate, + &EDIT_CURVE_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_CURVE_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c new file mode 100644 index 00000000000..870dd14d677 --- /dev/null +++ b/source/blender/draw/modes/edit_lattice_mode.c @@ -0,0 +1,277 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/edit_lattice_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "BKE_object.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +/* If needed, contains all global/Theme colors + * Add needed theme colors / values to DRW_globals_update() and update UBO + * Not needed for constant color. */ +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ + +extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_edit_lattice_overlay_loosevert_vert_glsl[]; +extern char datatoc_edit_lattice_overlay_frag_glsl[]; + +extern char datatoc_gpu_shader_3D_vert_glsl[]; +extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; +extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[]; + +/* *********** LISTS *********** */ +/* All lists are per viewport specific datas. + * They are all free when viewport changes engines + * or is free itself. Use EDIT_LATTICE_engine_init() to + * initialize most of them and EDIT_LATTICE_cache_init() + * for EDIT_LATTICE_PassList */ + +typedef struct EDIT_LATTICE_PassList { + /* Declare all passes here and init them in + * EDIT_LATTICE_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *wire_pass; + struct DRWPass *vert_pass; +} EDIT_LATTICE_PassList; + +typedef struct EDIT_LATTICE_FramebufferList { + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; +} EDIT_LATTICE_FramebufferList; + +typedef struct EDIT_LATTICE_TextureList { + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; +} EDIT_LATTICE_TextureList; + +typedef struct EDIT_LATTICE_StorageList { + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct EDIT_LATTICE_PrivateData *g_data; +} EDIT_LATTICE_StorageList; + +typedef struct EDIT_LATTICE_Data { + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + EDIT_LATTICE_FramebufferList *fbl; + EDIT_LATTICE_TextureList *txl; + EDIT_LATTICE_PassList *psl; + EDIT_LATTICE_StorageList *stl; +} EDIT_LATTICE_Data; + +/* *********** STATIC *********** */ + +static struct { + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in EDIT_LATTICE_engine_init(); + * free in EDIT_LATTICE_engine_free(); */ + GPUShader *wire_sh; + + GPUShader *overlay_vert_sh; + +} e_data = {NULL}; /* Engine data */ + +typedef struct EDIT_LATTICE_PrivateData { + /* This keeps the references of the shading groups for + * easy access in EDIT_LATTICE_cache_populate() */ + DRWShadingGroup *wire_shgrp; + DRWShadingGroup *vert_shgrp; +} EDIT_LATTICE_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +/* Init Textures, Framebuffers, Storage and Shaders. + * It is called for every frames. + * (Optional) */ +static void EDIT_LATTICE_engine_init(void *vedata) +{ + EDIT_LATTICE_TextureList *txl = ((EDIT_LATTICE_Data *)vedata)->txl; + EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl; + EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; + + UNUSED_VARS(txl, fbl, stl); + + /* Init Framebuffers like this: order is attachment order (for color texs) */ + /* + * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, + * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; + */ + + /* DRW_framebuffer_init takes care of checking if + * the framebuffer is valid and has the right size*/ + /* + * float *viewport_size = DRW_viewport_size_get(); + * DRW_framebuffer_init(&fbl->occlude_wire_fb, + * (int)viewport_size[0], (int)viewport_size[1], + * tex, 2); + */ + + if (!e_data.wire_sh) { + e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR); + } + + if (!e_data.overlay_vert_sh) { + e_data.overlay_vert_sh = DRW_shader_create_with_lib( + datatoc_edit_lattice_overlay_loosevert_vert_glsl, NULL, + datatoc_edit_lattice_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + } +} + +/* Here init all passes and shading groups + * Assume that all Passes are NULL */ +static void EDIT_LATTICE_cache_init(void *vedata) +{ + EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; + EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + psl->wire_pass = DRW_pass_create( + "Lattice Wire", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass); + + psl->vert_pass = DRW_pass_create( + "Lattice Verts", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_POINT); + stl->g_data->vert_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->vert_pass); + + DRW_shgroup_uniform_block(stl->g_data->vert_shgrp, "globalsBlock", globals_ubo); + } +} + +/* Add geometry to shadingGroups. Execute for each objects */ +static void EDIT_LATTICE_cache_populate(void *vedata, Object *ob) +{ + EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; + EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + UNUSED_VARS(psl); + + if (ob->type == OB_LATTICE) { + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { + /* Get geometry cache */ + struct Gwn_Batch *geom; + + geom = DRW_cache_lattice_wire_get(ob, true); + DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); + + geom = DRW_cache_lattice_vert_overlay_get(ob); + DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat); + } + } +} + +/* Optional: Post-cache_populate callback */ +static void EDIT_LATTICE_cache_finish(void *vedata) +{ + EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; + EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl; + + /* Do something here! dependant on the objects gathered */ + UNUSED_VARS(psl, stl); +} + +/* Draw time ! Control rendering pipeline from here */ +static void EDIT_LATTICE_draw_scene(void *vedata) +{ + EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl; + EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl; + + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + UNUSED_VARS(fbl); + + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl) + + /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ + /* + * DRW_framebuffer_texture_detach(dtxl->depth); + * DRW_framebuffer_bind(fbl->custom_fb); + * DRW_draw_pass(psl->pass); + * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); + * DRW_framebuffer_bind(dfbl->default_fb); + */ + + /* ... or just render passes on default framebuffer. */ + DRW_draw_pass(psl->wire_pass); + DRW_draw_pass(psl->vert_pass); + + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl) + + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ +} + +/* Cleanup when destroying the engine. + * This is not per viewport ! only when quitting blender. + * Mostly used for freeing shaders */ +static void EDIT_LATTICE_engine_free(void) +{ + // Currently built-in, dont free + DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh); +} + +static const DrawEngineDataSize EDIT_LATTICE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_LATTICE_Data); + +DrawEngineType draw_engine_edit_lattice_type = { + NULL, NULL, + N_("EditLatticeMode"), + &EDIT_LATTICE_data_size, + &EDIT_LATTICE_engine_init, + &EDIT_LATTICE_engine_free, + &EDIT_LATTICE_cache_init, + &EDIT_LATTICE_cache_populate, + &EDIT_LATTICE_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_LATTICE_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c new file mode 100644 index 00000000000..58ebef040da --- /dev/null +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -0,0 +1,588 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/edit_mesh_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "GPU_shader.h" + +#include "DNA_mesh_types.h" +#include "DNA_view3d_types.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +#include "edit_mesh_mode_intern.h" /* own include */ + +#include "BKE_object.h" + +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ + +extern char datatoc_edit_mesh_overlay_frag_glsl[]; +extern char datatoc_edit_mesh_overlay_vert_glsl[]; +extern char datatoc_edit_mesh_overlay_geom_tri_glsl[]; +extern char datatoc_edit_mesh_overlay_geom_edge_glsl[]; +extern char datatoc_edit_mesh_overlay_loosevert_vert_glsl[]; +extern char datatoc_edit_mesh_overlay_facedot_frag_glsl[]; +extern char datatoc_edit_mesh_overlay_facedot_vert_glsl[]; +extern char datatoc_edit_mesh_overlay_mix_vert_glsl[]; +extern char datatoc_edit_mesh_overlay_mix_frag_glsl[]; +extern char datatoc_edit_mesh_overlay_facefill_vert_glsl[]; +extern char datatoc_edit_mesh_overlay_facefill_frag_glsl[]; +extern char datatoc_edit_normals_vert_glsl[]; +extern char datatoc_edit_normals_geom_glsl[]; +extern char datatoc_common_globals_lib_glsl[]; + +extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; + +/* *********** LISTS *********** */ +typedef struct EDIT_MESH_PassList { + struct DRWPass *vcolor_faces; + struct DRWPass *depth_hidden_wire; + struct DRWPass *edit_face_overlay; + struct DRWPass *edit_face_occluded; + struct DRWPass *mix_occlude; + struct DRWPass *facefill_occlude; + struct DRWPass *normals; +} EDIT_MESH_PassList; + +typedef struct EDIT_MESH_FramebufferList { + struct GPUFrameBuffer *occlude_wire_fb; +} EDIT_MESH_FramebufferList; + +typedef struct EDIT_MESH_StorageList { + struct EDIT_MESH_PrivateData *g_data; +} EDIT_MESH_StorageList; + +typedef struct EDIT_MESH_Data { + void *engine_type; + EDIT_MESH_FramebufferList *fbl; + DRWViewportEmptyList *txl; + EDIT_MESH_PassList *psl; + EDIT_MESH_StorageList *stl; +} EDIT_MESH_Data; + +/* *********** STATIC *********** */ + +static struct { + /* weight/vert-color */ + GPUShader *vcolor_face_shader; + GPUShader *overlay_tri_sh; + GPUShader *overlay_tri_fast_sh; + GPUShader *overlay_tri_vcol_sh; + GPUShader *overlay_tri_vcol_fast_sh; + GPUShader *overlay_edge_sh; + GPUShader *overlay_edge_vcol_sh; + GPUShader *overlay_vert_sh; + GPUShader *overlay_facedot_sh; + GPUShader *overlay_mix_sh; + GPUShader *overlay_facefill_sh; + GPUShader *normals_face_sh; + GPUShader *normals_loop_sh; + GPUShader *normals_sh; + GPUShader *depth_sh; + /* temp buffer texture */ + struct GPUTexture *occlude_wire_depth_tx; + struct GPUTexture *occlude_wire_color_tx; +} e_data = {NULL}; /* Engine data */ + +typedef struct EDIT_MESH_PrivateData { + /* weight/vert-color */ + DRWShadingGroup *fvcolor_shgrp; + DRWShadingGroup *depth_shgrp_hidden_wire; + + DRWShadingGroup *fnormals_shgrp; + DRWShadingGroup *vnormals_shgrp; + DRWShadingGroup *lnormals_shgrp; + + DRWShadingGroup *face_overlay_shgrp; + DRWShadingGroup *ledges_overlay_shgrp; + DRWShadingGroup *lverts_overlay_shgrp; + DRWShadingGroup *facedot_overlay_shgrp; + + DRWShadingGroup *face_occluded_shgrp; + DRWShadingGroup *ledges_occluded_shgrp; + DRWShadingGroup *lverts_occluded_shgrp; + DRWShadingGroup *facedot_occluded_shgrp; + DRWShadingGroup *facefill_occluded_shgrp; + +} EDIT_MESH_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +static void EDIT_MESH_engine_init(void *vedata) +{ + EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl; + + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + e_data.occlude_wire_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_DEPTH_COMPONENT24, + &draw_engine_edit_mesh_type); + e_data.occlude_wire_color_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, + &draw_engine_edit_mesh_type); + + GPU_framebuffer_ensure_config(&fbl->occlude_wire_fb, { + GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_depth_tx), + GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_color_tx) + }); + + if (!e_data.vcolor_face_shader) { + e_data.vcolor_face_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA); + } + + if (!e_data.overlay_tri_sh) { + e_data.overlay_tri_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_vert_glsl, + datatoc_edit_mesh_overlay_geom_tri_glsl, + datatoc_edit_mesh_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define EDGE_FIX\n" + "#define ANTI_ALIASING\n" + "#define VERTEX_FACING"); + } + if (!e_data.overlay_tri_fast_sh) { + e_data.overlay_tri_fast_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_vert_glsl, + datatoc_edit_mesh_overlay_geom_tri_glsl, + datatoc_edit_mesh_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define ANTI_ALIASING\n" + "#define VERTEX_FACING\n"); + } + if (!e_data.overlay_tri_vcol_sh) { + e_data.overlay_tri_vcol_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_vert_glsl, + datatoc_edit_mesh_overlay_geom_tri_glsl, + datatoc_edit_mesh_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define EDGE_FIX\n" + "#define VERTEX_SELECTION\n" + "#define ANTI_ALIASING\n" + "#define VERTEX_FACING\n"); + } + if (!e_data.overlay_tri_vcol_fast_sh) { + e_data.overlay_tri_vcol_fast_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_vert_glsl, + datatoc_edit_mesh_overlay_geom_tri_glsl, + datatoc_edit_mesh_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define VERTEX_SELECTION\n" + "#define ANTI_ALIASING\n" + "#define VERTEX_FACING\n"); + } + if (!e_data.overlay_edge_sh) { + e_data.overlay_edge_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_vert_glsl, + datatoc_edit_mesh_overlay_geom_edge_glsl, + datatoc_edit_mesh_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define ANTI_ALIASING\n" + "#define VERTEX_FACING\n"); + } + if (!e_data.overlay_edge_vcol_sh) { + e_data.overlay_edge_vcol_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_vert_glsl, + datatoc_edit_mesh_overlay_geom_edge_glsl, + datatoc_edit_mesh_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define VERTEX_SELECTION\n" + "#define VERTEX_FACING\n"); + } + if (!e_data.overlay_vert_sh) { + e_data.overlay_vert_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_loosevert_vert_glsl, NULL, + datatoc_edit_mesh_overlay_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define VERTEX_SELECTION\n"); + } + if (!e_data.overlay_facedot_sh) { + e_data.overlay_facedot_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_facedot_vert_glsl, NULL, + datatoc_edit_mesh_overlay_facedot_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define VERTEX_FACING\n"); + } + if (!e_data.overlay_mix_sh) { + e_data.overlay_mix_sh = DRW_shader_create_fullscreen(datatoc_edit_mesh_overlay_mix_frag_glsl, NULL); + } + if (!e_data.overlay_facefill_sh) { + e_data.overlay_facefill_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_facefill_vert_glsl, NULL, + datatoc_edit_mesh_overlay_facefill_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + } + if (!e_data.normals_face_sh) { + e_data.normals_face_sh = DRW_shader_create( + datatoc_edit_normals_vert_glsl, + datatoc_edit_normals_geom_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl, + "#define FACE_NORMALS\n"); + } + if (!e_data.normals_loop_sh) { + e_data.normals_loop_sh = DRW_shader_create( + datatoc_edit_normals_vert_glsl, + datatoc_edit_normals_geom_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl, + "#define LOOP_NORMALS\n"); + } + if (!e_data.normals_sh) { + e_data.normals_sh = DRW_shader_create( + datatoc_edit_normals_vert_glsl, + datatoc_edit_normals_geom_glsl, + datatoc_gpu_shader_uniform_color_frag_glsl, NULL); + } + if (!e_data.depth_sh) { + e_data.depth_sh = DRW_shader_create_3D_depth_only(); + } +} + +static DRWPass *edit_mesh_create_overlay_pass( + float *faceAlpha, DRWState statemod, + DRWShadingGroup **r_face_shgrp, DRWShadingGroup **r_ledges_shgrp, + DRWShadingGroup **r_lverts_shgrp, DRWShadingGroup **r_facedot_shgrp) +{ + GPUShader *tri_sh, *ledge_sh; + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + Scene *scene = draw_ctx->scene; + ToolSettings *tsettings = scene->toolsettings; + + if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) { + ledge_sh = e_data.overlay_edge_vcol_sh; + + if ((rv3d->rflag & RV3D_NAVIGATING) != 0) + tri_sh = e_data.overlay_tri_vcol_fast_sh; + else + tri_sh = e_data.overlay_tri_vcol_sh; + } + else { + ledge_sh = e_data.overlay_edge_sh; + + if ((rv3d->rflag & RV3D_NAVIGATING) != 0) + tri_sh = e_data.overlay_tri_fast_sh; + else + tri_sh = e_data.overlay_tri_sh; + } + + DRWPass *pass = DRW_pass_create( + "Edit Mesh Face Overlay Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_POINT | statemod); + + *r_face_shgrp = DRW_shgroup_create(tri_sh, pass); + DRW_shgroup_uniform_block(*r_face_shgrp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_vec2(*r_face_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_float(*r_face_shgrp, "faceAlphaMod", faceAlpha, 1); + + *r_ledges_shgrp = DRW_shgroup_create(ledge_sh, pass); + DRW_shgroup_uniform_block(*r_ledges_shgrp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_vec2(*r_ledges_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + + if ((tsettings->selectmode & (SCE_SELECT_VERTEX)) != 0) { + *r_lverts_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, pass); + DRW_shgroup_uniform_block(*r_lverts_shgrp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_vec2(*r_lverts_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + } + + if ((tsettings->selectmode & (SCE_SELECT_FACE)) != 0) { + *r_facedot_shgrp = DRW_shgroup_create(e_data.overlay_facedot_sh, pass); + DRW_shgroup_uniform_block(*r_facedot_shgrp, "globalsBlock", globals_ubo); + } + + return pass; +} + +static float backwire_opacity; +static float face_mod; +static float size_normal; + +static void EDIT_MESH_cache_init(void *vedata) +{ + EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl; + EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + + bool do_zbufclip = ((v3d->flag & V3D_ZBUF_SELECT) == 0); + + static float zero = 0.0f; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + psl->vcolor_faces = DRW_pass_create( + "Vert Color Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); + + stl->g_data->fvcolor_shgrp = DRW_shgroup_create(e_data.vcolor_face_shader, psl->vcolor_faces); + + static float light[3] = {-0.3f, 0.5f, 1.0f}; + static float alpha = 1.0f; + static float world_light = 1.0f; /* XXX, see: paint_vertex_mode.c */ + DRW_shgroup_uniform_vec3(stl->g_data->fvcolor_shgrp, "light", light, 1); + DRW_shgroup_uniform_float(stl->g_data->fvcolor_shgrp, "alpha", &alpha, 1); + DRW_shgroup_uniform_float(stl->g_data->fvcolor_shgrp, "global", &world_light, 1); + } + + { + /* Complementary Depth Pass */ + psl->depth_hidden_wire = DRW_pass_create( + "Depth Pass Hidden Wire", + DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK); + stl->g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(e_data.depth_sh, psl->depth_hidden_wire); + } + + { + /* Normals */ + psl->normals = DRW_pass_create( + "Edit Mesh Normals Pass", + DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL); + + stl->g_data->fnormals_shgrp = DRW_shgroup_create(e_data.normals_face_sh, psl->normals); + DRW_shgroup_uniform_float(stl->g_data->fnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(stl->g_data->fnormals_shgrp, "color", ts.colorNormal, 1); + + stl->g_data->vnormals_shgrp = DRW_shgroup_create(e_data.normals_sh, psl->normals); + DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", ts.colorVNormal, 1); + + stl->g_data->lnormals_shgrp = DRW_shgroup_create(e_data.normals_loop_sh, psl->normals); + DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", ts.colorLNormal, 1); + } + + if (!do_zbufclip) { + psl->edit_face_overlay = edit_mesh_create_overlay_pass( + &face_mod, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND, + &stl->g_data->face_overlay_shgrp, &stl->g_data->ledges_overlay_shgrp, + &stl->g_data->lverts_overlay_shgrp, &stl->g_data->facedot_overlay_shgrp); + } + else { + /* We render all wires with depth and opaque to a new fbo and blend the result based on depth values */ + psl->edit_face_occluded = edit_mesh_create_overlay_pass( + &zero, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH, + &stl->g_data->face_occluded_shgrp, &stl->g_data->ledges_occluded_shgrp, + &stl->g_data->lverts_occluded_shgrp, &stl->g_data->facedot_occluded_shgrp); + + /* however we loose the front faces value (because we need the depth of occluded wires and + * faces are alpha blended ) so we recover them in a new pass. */ + psl->facefill_occlude = DRW_pass_create( + "Front Face Color", + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + stl->g_data->facefill_occluded_shgrp = DRW_shgroup_create(e_data.overlay_facefill_sh, psl->facefill_occlude); + DRW_shgroup_uniform_block(stl->g_data->facefill_occluded_shgrp, "globalsBlock", globals_ubo); + + /* we need a full screen pass to combine the result */ + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + + psl->mix_occlude = DRW_pass_create( + "Mix Occluded Wires", + DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); + DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.overlay_mix_sh, psl->mix_occlude); + DRW_shgroup_call_add(mix_shgrp, quad, NULL); + DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1); + DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireColor", &e_data.occlude_wire_color_tx); + DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireDepth", &e_data.occlude_wire_depth_tx); + DRW_shgroup_uniform_texture_ref(mix_shgrp, "sceneDepth", &dtxl->depth); + } +} + +static void edit_mesh_add_ob_to_pass( + Scene *scene, Object *ob, DRWShadingGroup *face_shgrp, DRWShadingGroup *ledges_shgrp, + DRWShadingGroup *lverts_shgrp, DRWShadingGroup *facedot_shgrp, DRWShadingGroup *facefill_shgrp) +{ + struct Gwn_Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter; + ToolSettings *tsettings = scene->toolsettings; + + DRW_cache_mesh_wire_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts); + DRW_shgroup_call_add(face_shgrp, geo_ovl_tris, ob->obmat); + DRW_shgroup_call_add(ledges_shgrp, geo_ovl_ledges, ob->obmat); + + if (facefill_shgrp) { + DRW_shgroup_call_add(facefill_shgrp, geo_ovl_tris, ob->obmat); + } + + if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) { + DRW_shgroup_call_add(lverts_shgrp, geo_ovl_lverts, ob->obmat); + } + + if ((tsettings->selectmode & SCE_SELECT_FACE) != 0) { + geo_ovl_fcenter = DRW_cache_face_centers_get(ob); + DRW_shgroup_call_add(facedot_shgrp, geo_ovl_fcenter, ob->obmat); + } +} + +static void EDIT_MESH_cache_populate(void *vedata, Object *ob) +{ + EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + Scene *scene = draw_ctx->scene; + struct Gwn_Batch *geom; + + if (ob->type == OB_MESH) { + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { + const Mesh *me = ob->data; + bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0; + bool do_show_weight = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT) != 0; + + /* Updating uniform */ + backwire_opacity = v3d->overlay.backwire_opacity; + + bool fnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_NORMALS) != 0; + bool vnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0; + bool lnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0; + /* Updating uniform */ + size_normal = v3d->overlay.normals_length; + + face_mod = (do_occlude_wire) ? 0.0f : 1.0f; + + if (do_show_weight) { + geom = DRW_cache_mesh_surface_weights_get(ob); + DRW_shgroup_call_add(stl->g_data->fvcolor_shgrp, geom, ob->obmat); + } + + if (do_occlude_wire) { + geom = DRW_cache_mesh_surface_get(ob); + DRW_shgroup_call_add(stl->g_data->depth_shgrp_hidden_wire, geom, ob->obmat); + } + + if (fnormals_do) { + geom = DRW_cache_face_centers_get(ob); + DRW_shgroup_call_add(stl->g_data->fnormals_shgrp, geom, ob->obmat); + } + + if (vnormals_do || lnormals_do) { + struct Gwn_Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts; + DRW_cache_mesh_normals_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts); + + if (vnormals_do) { + DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_tris, ob->obmat); + DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_ledges, ob->obmat); + DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_lverts, ob->obmat); + } + + if (lnormals_do) { + DRW_shgroup_call_add(stl->g_data->lnormals_shgrp, geo_ovl_tris, ob->obmat); + } + } + + if ((v3d->flag & V3D_ZBUF_SELECT) == 0) { + edit_mesh_add_ob_to_pass( + scene, ob, stl->g_data->face_occluded_shgrp, stl->g_data->ledges_occluded_shgrp, + stl->g_data->lverts_occluded_shgrp, stl->g_data->facedot_occluded_shgrp, + stl->g_data->facefill_occluded_shgrp); + } + else { + edit_mesh_add_ob_to_pass( + scene, ob, stl->g_data->face_overlay_shgrp, stl->g_data->ledges_overlay_shgrp, + stl->g_data->lverts_overlay_shgrp, stl->g_data->facedot_overlay_shgrp, NULL); + } + + /* 3D text overlay */ + if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | + ME_DRAWEXTRA_FACEAREA | + ME_DRAWEXTRA_FACEANG | + ME_DRAWEXTRA_EDGEANG | + ME_DRAWEXTRA_INDICES)) + { + DRW_edit_mesh_mode_text_measure_stats( + draw_ctx->ar, v3d, ob, &scene->unit); + } + } + } +} + +static void EDIT_MESH_draw_scene(void *vedata) +{ + EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl; + EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + DRW_draw_pass(psl->vcolor_faces); + + DRW_draw_pass(psl->depth_hidden_wire); + + if (psl->edit_face_occluded) { + float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + /* render facefill */ + DRW_draw_pass(psl->facefill_occlude); + + /* Render wires on a separate framebuffer */ + GPU_framebuffer_bind(fbl->occlude_wire_fb); + GPU_framebuffer_clear_color_depth(fbl->occlude_wire_fb, clearcol, 1.0f); + DRW_draw_pass(psl->normals); + DRW_draw_pass(psl->edit_face_occluded); + + /* Combine with scene buffer */ + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_draw_pass(psl->mix_occlude); + } + else { + DRW_draw_pass(psl->normals); + DRW_draw_pass(psl->edit_face_overlay); + } +} + +static void EDIT_MESH_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.overlay_tri_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_tri_fast_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_tri_vcol_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_tri_vcol_fast_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_edge_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_edge_vcol_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_facedot_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_mix_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_facefill_sh); + DRW_SHADER_FREE_SAFE(e_data.normals_loop_sh); + DRW_SHADER_FREE_SAFE(e_data.normals_face_sh); + DRW_SHADER_FREE_SAFE(e_data.normals_sh); +} + +static const DrawEngineDataSize EDIT_MESH_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_MESH_Data); + +DrawEngineType draw_engine_edit_mesh_type = { + NULL, NULL, + N_("EditMeshMode"), + &EDIT_MESH_data_size, + &EDIT_MESH_engine_init, + &EDIT_MESH_engine_free, + &EDIT_MESH_cache_init, + &EDIT_MESH_cache_populate, + NULL, + NULL, + &EDIT_MESH_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/edit_mesh_mode_intern.h b/source/blender/draw/modes/edit_mesh_mode_intern.h new file mode 100644 index 00000000000..99298bd41f4 --- /dev/null +++ b/source/blender/draw/modes/edit_mesh_mode_intern.h @@ -0,0 +1,38 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/draw/modes/edit_mesh_mode_intern.h + * \ingroup draw + */ + +#ifndef __EDIT_MESH_MODE_INTERN_H__ +#define __EDIT_MESH_MODE_INTERN_H__ + +struct ARegion; +struct Object; +struct UnitSettings; +struct View3D; + +/* edit_mesh_mode_text.c */ +void DRW_edit_mesh_mode_text_measure_stats( + struct ARegion *ar, struct View3D *v3d, + struct Object *ob, const UnitSettings *unit); + +#endif /* __EDIT_MESH_MODE_INTERN_H__ */ diff --git a/source/blender/draw/modes/edit_mesh_mode_text.c b/source/blender/draw/modes/edit_mesh_mode_text.c new file mode 100644 index 00000000000..def96e79eba --- /dev/null +++ b/source/blender/draw/modes/edit_mesh_mode_text.c @@ -0,0 +1,352 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/edit_mesh_mode_text.c + * \ingroup draw + */ + +#include "BLI_math.h" +#include "BLI_string.h" + +#include "BKE_editmesh.h" +#include "BKE_global.h" +#include "BKE_unit.h" + +#include "ED_view3d.h" + +#include "GPU_shader.h" +#include "GPU_viewport.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" + +#include "UI_resources.h" + +#include "draw_manager_text.h" + +#include "edit_mesh_mode_intern.h" /* own include */ + +/* Copied from drawobject.c */ +void DRW_edit_mesh_mode_text_measure_stats( + ARegion *ar, View3D *v3d, + Object *ob, const UnitSettings *unit) +{ + /* Do not use ascii when using non-default unit system, some unit chars are utf8 (micro, square, etc.). + * See bug #36090. + */ + struct DRWTextStore *dt = DRW_text_cache_ensure(); + const short txt_flag = DRW_TEXT_CACHE_LOCALCLIP | (unit->system ? 0 : DRW_TEXT_CACHE_ASCII); + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + float v1[3], v2[3], v3[3], vmid[3], fvec[3]; + char numstr[32]; /* Stores the measurement display text here */ + size_t numstr_len; + const char *conv_float; /* Use a float conversion matching the grid size */ + unsigned char col[4] = {0, 0, 0, 255}; /* color of the text to draw */ + float area; /* area of the face */ + float grid = unit->system ? unit->scale_length : v3d->grid; + const bool do_split = (unit->flag & USER_UNIT_OPT_SPLIT) != 0; + const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0; + const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0; + /* when 2 edge-info options are enabled, space apart */ + const bool do_edge_textpair = (me->drawflag & ME_DRAWEXTRA_EDGELEN) && (me->drawflag & ME_DRAWEXTRA_EDGEANG); + const float edge_texpair_sep = 0.4f; + float clip_planes[4][4]; + /* allow for displaying shape keys and deform mods */ + BMIter iter; + + /* make the precision of the display value proportionate to the gridsize */ + + if (grid <= 0.01f) conv_float = "%.6g"; + else if (grid <= 0.1f) conv_float = "%.5g"; + else if (grid <= 1.0f) conv_float = "%.4g"; + else if (grid <= 10.0f) conv_float = "%.3g"; + else conv_float = "%.2g"; + + if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_EDGEANG | ME_DRAWEXTRA_INDICES)) { + BoundBox bb; + const rcti rect = {0, ar->winx, 0, ar->winy}; + + ED_view3d_clipping_calc(&bb, clip_planes, ar, em->ob, &rect); + } + + if (me->drawflag & ME_DRAWEXTRA_EDGELEN) { + BMEdge *eed; + + UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col); + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + /* draw selected edges, or edges next to selected verts while dragging */ + if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || + (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || + BM_elem_flag_test(eed->v2, BM_ELEM_SELECT)))) + { + float v1_clip[3], v2_clip[3]; + + copy_v3_v3(v1, eed->v1->co); + copy_v3_v3(v2, eed->v2->co); + + if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { + + if (do_edge_textpair) { + interp_v3_v3v3(vmid, v1, v2, edge_texpair_sep); + } + else { + mid_v3_v3v3(vmid, v1_clip, v2_clip); + } + + if (do_global) { + mul_mat3_m4_v3(ob->obmat, v1); + mul_mat3_m4_v3(ob->obmat, v2); + } + + if (unit->system) { + numstr_len = bUnit_AsString( + numstr, sizeof(numstr), len_v3v3(v1, v2) * unit->scale_length, 3, + unit->system, B_UNIT_LENGTH, do_split, false); + } + else { + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); + } + + DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, txt_flag, col); + } + } + } + } + + if (me->drawflag & ME_DRAWEXTRA_EDGEANG) { + const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS); + BMEdge *eed; + + UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGEANG, col); + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + BMLoop *l_a, *l_b; + if (BM_edge_loop_pair(eed, &l_a, &l_b)) { + /* draw selected edges, or edges next to selected verts while dragging */ + if (BM_elem_flag_test(eed, BM_ELEM_SELECT) || + (do_moving && + (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || + BM_elem_flag_test(eed->v2, BM_ELEM_SELECT) || + /* special case, this is useful to show when verts connected to + * this edge via a face are being transformed */ + BM_elem_flag_test(l_a->next->next->v, BM_ELEM_SELECT) || + BM_elem_flag_test(l_a->prev->v, BM_ELEM_SELECT) || + BM_elem_flag_test(l_b->next->next->v, BM_ELEM_SELECT) || + BM_elem_flag_test(l_b->prev->v, BM_ELEM_SELECT) + ))) + { + float v1_clip[3], v2_clip[3]; + + copy_v3_v3(v1, eed->v1->co); + copy_v3_v3(v2, eed->v2->co); + + if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { + float no_a[3], no_b[3]; + float angle; + + if (do_edge_textpair) { + interp_v3_v3v3(vmid, v2_clip, v1_clip, edge_texpair_sep); + } + else { + mid_v3_v3v3(vmid, v1_clip, v2_clip); + } + + copy_v3_v3(no_a, l_a->f->no); + copy_v3_v3(no_b, l_b->f->no); + + if (do_global) { + mul_mat3_m4_v3(ob->imat, no_a); + mul_mat3_m4_v3(ob->imat, no_b); + normalize_v3(no_a); + normalize_v3(no_b); + } + + angle = angle_normalized_v3v3(no_a, no_b); + + numstr_len = BLI_snprintf_rlen( + numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + + DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, txt_flag, col); + } + } + } + } + } + + if (me->drawflag & ME_DRAWEXTRA_FACEAREA) { + /* would be nice to use BM_face_calc_area, but that is for 2d faces + * so instead add up tessellation triangle areas */ + + UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col); + + int i, n, numtri; + BMFace *f = NULL; + BM_ITER_MESH_INDEX(f, &iter, em->bm, BM_FACES_OF_MESH, i) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + n = 0; + numtri = f->len - 2; + area = 0; + zero_v3(vmid); + BMLoop *(*l)[3] = &em->looptris[poly_to_tri_count(i, BM_elem_index_get(f->l_first))]; + for (int j = 0; j < numtri; j++) { + copy_v3_v3(v1, l[j][0]->v->co); + copy_v3_v3(v2, l[j][1]->v->co); + copy_v3_v3(v3, l[j][2]->v->co); + + add_v3_v3(vmid, v1); + add_v3_v3(vmid, v2); + add_v3_v3(vmid, v3); + n += 3; + + if (do_global) { + mul_mat3_m4_v3(ob->obmat, v1); + mul_mat3_m4_v3(ob->obmat, v2); + mul_mat3_m4_v3(ob->obmat, v3); + } + + area += area_tri_v3(v1, v2, v3); + } + + mul_v3_fl(vmid, 1.0f / (float)n); + + if (unit->system) { + numstr_len = bUnit_AsString( + numstr, sizeof(numstr), + (double)(area * unit->scale_length * unit->scale_length), + 3, unit->system, B_UNIT_AREA, do_split, false); + } + else { + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area); + } + + DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, txt_flag, col); + } + } + } + + if (me->drawflag & ME_DRAWEXTRA_FACEANG) { + BMFace *efa; + const bool is_rad = (unit->system_rotation == USER_UNIT_ROT_RADIANS); + + UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + const bool is_face_sel = BM_elem_flag_test_bool(efa, BM_ELEM_SELECT); + + if (is_face_sel || do_moving) { + BMIter liter; + BMLoop *loop; + bool is_first = true; + + BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) { + if (is_face_sel || + (do_moving && + (BM_elem_flag_test(loop->v, BM_ELEM_SELECT) || + BM_elem_flag_test(loop->prev->v, BM_ELEM_SELECT) || + BM_elem_flag_test(loop->next->v, BM_ELEM_SELECT)))) + { + float v2_local[3]; + + /* lazy init center calc */ + if (is_first) { + BM_face_calc_center_bounds(efa, vmid); + is_first = false; + } + copy_v3_v3(v1, loop->prev->v->co); + copy_v3_v3(v2, loop->v->co); + copy_v3_v3(v3, loop->next->v->co); + + copy_v3_v3(v2_local, v2); + + if (do_global) { + mul_mat3_m4_v3(ob->obmat, v1); + mul_mat3_m4_v3(ob->obmat, v2); + mul_mat3_m4_v3(ob->obmat, v3); + } + + float angle = angle_v3v3v3(v1, v2, v3); + + numstr_len = BLI_snprintf_rlen( + numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + interp_v3_v3v3(fvec, vmid, v2_local, 0.8f); + DRW_text_cache_add(dt, fvec, numstr, numstr_len, 0, txt_flag, col); + } + } + } + } + } + + /* This option is for mesh ops and addons debugging; only available in UI if Blender starts with --debug */ + if (me->drawflag & ME_DRAWEXTRA_INDICES) { + int i; + + /* For now, reuse an appropriate theme color */ + UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); + + if (em->selectmode & SCE_SELECT_VERTEX) { + BMVert *v; + + BM_ITER_MESH_INDEX(v, &iter, em->bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); + DRW_text_cache_add(dt, v->co, numstr, numstr_len, 0, txt_flag, col); + } + } + } + + if (em->selectmode & SCE_SELECT_EDGE) { + BMEdge *e; + + BM_ITER_MESH_INDEX(e, &iter, em->bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + float v1_clip[3], v2_clip[3]; + + copy_v3_v3(v1, e->v1->co); + copy_v3_v3(v2, e->v2->co); + + if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4, v1_clip, v2_clip)) { + mid_v3_v3v3(vmid, v1_clip, v2_clip); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); + DRW_text_cache_add(dt, vmid, numstr, numstr_len, 0, txt_flag, col); + } + } + } + } + + if (em->selectmode & SCE_SELECT_FACE) { + BMFace *f; + + BM_ITER_MESH_INDEX(f, &iter, em->bm, BM_FACES_OF_MESH, i) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BM_face_calc_center_mean(f, v1); + + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); + DRW_text_cache_add(dt, v1, numstr, numstr_len, 0, txt_flag, col); + } + } + } + } +} diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c new file mode 100644 index 00000000000..20539295fd2 --- /dev/null +++ b/source/blender/draw/modes/edit_metaball_mode.c @@ -0,0 +1,235 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/edit_metaball_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_meta_types.h" + +#include "BKE_object.h" +#include "BKE_mball.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" +#include "GPU_select.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +/* If needed, contains all global/Theme colors + * Add needed theme colors / values to DRW_globals_update() and update UBO + * Not needed for constant color. */ +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ + +/* *********** LISTS *********** */ +/* All lists are per viewport specific datas. + * They are all free when viewport changes engines + * or is free itself. Use EDIT_METABALL_engine_init() to + * initialize most of them and EDIT_METABALL_cache_init() + * for EDIT_METABALL_PassList */ + +typedef struct EDIT_METABALL_PassList { + /* Declare all passes here and init them in + * EDIT_METABALL_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *pass; +} EDIT_METABALL_PassList; + +typedef struct EDIT_METABALL_FramebufferList { + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; +} EDIT_METABALL_FramebufferList; + +typedef struct EDIT_METABALL_TextureList { + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; +} EDIT_METABALL_TextureList; + +typedef struct EDIT_METABALL_StorageList { + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + // struct CustomStruct *block; + struct EDIT_METABALL_PrivateData *g_data; +} EDIT_METABALL_StorageList; + +typedef struct EDIT_METABALL_Data { + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + EDIT_METABALL_FramebufferList *fbl; + EDIT_METABALL_TextureList *txl; + EDIT_METABALL_PassList *psl; + EDIT_METABALL_StorageList *stl; +} EDIT_METABALL_Data; + +/* *********** STATIC *********** */ + +typedef struct EDIT_METABALL_PrivateData { + /* This keeps the references of the shading groups for + * easy access in EDIT_METABALL_cache_populate() */ + DRWShadingGroup *group; +} EDIT_METABALL_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +/* Here init all passes and shading groups + * Assume that all Passes are NULL */ +static void EDIT_METABALL_cache_init(void *vedata) +{ + EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; + EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Create a pass */ + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE); + psl->pass = DRW_pass_create("My Pass", state); + + /* Create a shadingGroup using a function in draw_common.c or custom one */ + stl->g_data->group = shgroup_instance_mball_handles(psl->pass); + } +} + +/* Add geometry to shadingGroups. Execute for each objects */ +static void EDIT_METABALL_cache_populate(void *vedata, Object *ob) +{ + //EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; + EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl; + + if (ob->type == OB_MBALL) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + DRWShadingGroup *group = stl->g_data->group; + + if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { + MetaBall *mb = ob->data; + + const float *color; + const float col_radius[3] = {0.63, 0.19, 0.19}; /* 0x3030A0 */ + const float col_radius_select[3] = {0.94, 0.63, 0.63}; /* 0xA0A0F0 */ + const float col_stiffness[3] = {0.19, 0.63, 0.19}; /* 0x30A030 */ + const float col_stiffness_select[3] = {0.63, 0.94, 0.63}; /* 0xA0F0A0 */ + + const bool is_select = DRW_state_is_select(); + + int selection_id = 0; + + float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */ + { + float scamat[3][3]; + copy_m3_m4(scamat, ob->obmat); + /* Get the normalized inverse matrix to extract only + * the scale of Scamat */ + float iscamat[3][3]; + invert_m3_m3(iscamat, scamat); + normalize_m3(iscamat); + mul_m3_m3_post(scamat, iscamat); + + copy_v3_v3(draw_scale_xform[0], scamat[0]); + copy_v3_v3(draw_scale_xform[1], scamat[1]); + copy_v3_v3(draw_scale_xform[2], scamat[2]); + } + + for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) { + float world_pos[3]; + mul_v3_m4v3(world_pos, ob->obmat, &ml->x); + draw_scale_xform[0][3] = world_pos[0]; + draw_scale_xform[1][3] = world_pos[1]; + draw_scale_xform[2][3] = world_pos[2]; + + float draw_stiffness_radius = ml->rad * atanf(ml->s) / (float)M_PI_2; + + if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) color = col_radius_select; + else color = col_radius; + + if (is_select) { + ml->selcol1 = ++selection_id; + DRW_select_load_id(selection_id); + } + + DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &ml->rad, color); + + if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) color = col_stiffness_select; + else color = col_stiffness; + + if (is_select) { + ml->selcol2 = ++selection_id; + DRW_select_load_id(selection_id); + } + + DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &draw_stiffness_radius, color); + } + } + } +} + +/* Draw time ! Control rendering pipeline from here */ +static void EDIT_METABALL_draw_scene(void *vedata) +{ + EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; + /* render passes on default framebuffer. */ + DRW_draw_pass(psl->pass); + + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ +} + +/* Cleanup when destroying the engine. + * This is not per viewport ! only when quitting blender. + * Mostly used for freeing shaders */ +static void EDIT_METABALL_engine_free(void) +{ + // DRW_SHADER_FREE_SAFE(custom_shader); +} + +static const DrawEngineDataSize EDIT_METABALL_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_METABALL_Data); + +DrawEngineType draw_engine_edit_metaball_type = { + NULL, NULL, + N_("EditMetaballMode"), + &EDIT_METABALL_data_size, + NULL, + &EDIT_METABALL_engine_free, + &EDIT_METABALL_cache_init, + &EDIT_METABALL_cache_populate, + NULL, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_METABALL_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/edit_surface_mode.c b/source/blender/draw/modes/edit_surface_mode.c new file mode 100644 index 00000000000..7074ba3d024 --- /dev/null +++ b/source/blender/draw/modes/edit_surface_mode.c @@ -0,0 +1,251 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/edit_surface_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +/* If needed, contains all global/Theme colors + * Add needed theme colors / values to DRW_globals_update() and update UBO + * Not needed for constant color. */ +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ + +/* *********** LISTS *********** */ +/* All lists are per viewport specific datas. + * They are all free when viewport changes engines + * or is free itself. Use EDIT_SURFACE_engine_init() to + * initialize most of them and EDIT_SURFACE_cache_init() + * for EDIT_SURFACE_PassList */ + +typedef struct EDIT_SURFACE_PassList { + /* Declare all passes here and init them in + * EDIT_SURFACE_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *pass; +} EDIT_SURFACE_PassList; + +typedef struct EDIT_SURFACE_FramebufferList { + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; +} EDIT_SURFACE_FramebufferList; + +typedef struct EDIT_SURFACE_TextureList { + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; +} EDIT_SURFACE_TextureList; + +typedef struct EDIT_SURFACE_StorageList { + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct EDIT_SURFACE_PrivateData *g_data; +} EDIT_SURFACE_StorageList; + +typedef struct EDIT_SURFACE_Data { + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + EDIT_SURFACE_FramebufferList *fbl; + EDIT_SURFACE_TextureList *txl; + EDIT_SURFACE_PassList *psl; + EDIT_SURFACE_StorageList *stl; +} EDIT_SURFACE_Data; + +/* *********** STATIC *********** */ + +static struct { + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in EDIT_SURFACE_engine_init(); + * free in EDIT_SURFACE_engine_free(); */ + struct GPUShader *custom_shader; +} e_data = {NULL}; /* Engine data */ + +typedef struct EDIT_SURFACE_PrivateData { + /* This keeps the references of the shading groups for + * easy access in EDIT_SURFACE_cache_populate() */ + DRWShadingGroup *group; +} EDIT_SURFACE_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +/* Init Textures, Framebuffers, Storage and Shaders. + * It is called for every frames. + * (Optional) */ +static void EDIT_SURFACE_engine_init(void *vedata) +{ + EDIT_SURFACE_TextureList *txl = ((EDIT_SURFACE_Data *)vedata)->txl; + EDIT_SURFACE_FramebufferList *fbl = ((EDIT_SURFACE_Data *)vedata)->fbl; + EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl; + + UNUSED_VARS(txl, fbl, stl); + + /* Init Framebuffers like this: order is attachment order (for color texs) */ + /* + * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, + * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; + */ + + /* DRW_framebuffer_init takes care of checking if + * the framebuffer is valid and has the right size*/ + /* + * float *viewport_size = DRW_viewport_size_get(); + * DRW_framebuffer_init(&fbl->occlude_wire_fb, + * (int)viewport_size[0], (int)viewport_size[1], + * tex, 2); + */ + + if (!e_data.custom_shader) { + e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } +} + +/* Here init all passes and shading groups + * Assume that all Passes are NULL */ +static void EDIT_SURFACE_cache_init(void *vedata) +{ + EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl; + EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Create a pass */ + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE); + psl->pass = DRW_pass_create("My Pass", state); + + /* Create a shadingGroup using a function in draw_common.c or custom one */ + /* + * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire); + * -- or -- + * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass); + */ + stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass); + + /* Uniforms need a pointer to it's value so be sure it's accessible at + * any given time (i.e. use static vars) */ + static float color[4] = {0.0f, 0.0f, 1.0f, 1.0}; + DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1); + } + +} + +/* Add geometry to shadingGroups. Execute for each objects */ +static void EDIT_SURFACE_cache_populate(void *vedata, Object *ob) +{ + EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl; + EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl; + + UNUSED_VARS(psl, stl); + + if (ob->type == OB_MESH) { + /* Get geometry cache */ + struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob); + + /* Add geom to a shading group */ + DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat); + } +} + +/* Optional: Post-cache_populate callback */ +static void EDIT_SURFACE_cache_finish(void *vedata) +{ + EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl; + EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl; + + /* Do something here! dependant on the objects gathered */ + UNUSED_VARS(psl, stl); +} + +/* Draw time ! Control rendering pipeline from here */ +static void EDIT_SURFACE_draw_scene(void *vedata) +{ + EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl; + EDIT_SURFACE_FramebufferList *fbl = ((EDIT_SURFACE_Data *)vedata)->fbl; + + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + UNUSED_VARS(fbl, dfbl, dtxl); + + /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ + /* + * DRW_framebuffer_texture_detach(dtxl->depth); + * DRW_framebuffer_bind(fbl->custom_fb); + * DRW_draw_pass(psl->pass); + * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); + * DRW_framebuffer_bind(dfbl->default_fb); + */ + + /* ... or just render passes on default framebuffer. */ + DRW_draw_pass(psl->pass); + + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ +} + +/* Cleanup when destroying the engine. + * This is not per viewport ! only when quitting blender. + * Mostly used for freeing shaders */ +static void EDIT_SURFACE_engine_free(void) +{ + // DRW_SHADER_FREE_SAFE(custom_shader); +} + +static const DrawEngineDataSize EDIT_SURFACE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_SURFACE_Data); + +DrawEngineType draw_engine_edit_surface_type = { + NULL, NULL, + N_("EditSurfaceMode"), + &EDIT_SURFACE_data_size, + &EDIT_SURFACE_engine_init, + &EDIT_SURFACE_engine_free, + &EDIT_SURFACE_cache_init, + &EDIT_SURFACE_cache_populate, + &EDIT_SURFACE_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_SURFACE_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c new file mode 100644 index 00000000000..5750dc8a0b9 --- /dev/null +++ b/source/blender/draw/modes/edit_text_mode.c @@ -0,0 +1,290 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/edit_text_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_curve_types.h" + +#include "BIF_glutil.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" +#include "GPU_batch.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +/* If needed, contains all global/Theme colors + * Add needed theme colors / values to DRW_globals_update() and update UBO + * Not needed for constant color. */ +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ + +/* *********** LISTS *********** */ +/* All lists are per viewport specific datas. + * They are all free when viewport changes engines + * or is free itself. Use EDIT_TEXT_engine_init() to + * initialize most of them and EDIT_TEXT_cache_init() + * for EDIT_TEXT_PassList */ + +typedef struct EDIT_TEXT_PassList { + /* Declare all passes here and init them in + * EDIT_TEXT_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *wire_pass; + struct DRWPass *overlay_select_pass; + struct DRWPass *overlay_cursor_pass; +} EDIT_TEXT_PassList; + +typedef struct EDIT_TEXT_FramebufferList { + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; +} EDIT_TEXT_FramebufferList; + +typedef struct EDIT_TEXT_TextureList { + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; +} EDIT_TEXT_TextureList; + +typedef struct EDIT_TEXT_StorageList { + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct EDIT_TEXT_PrivateData *g_data; +} EDIT_TEXT_StorageList; + +typedef struct EDIT_TEXT_Data { + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + EDIT_TEXT_FramebufferList *fbl; + EDIT_TEXT_TextureList *txl; + EDIT_TEXT_PassList *psl; + EDIT_TEXT_StorageList *stl; +} EDIT_TEXT_Data; + +/* *********** STATIC *********** */ + +static struct { + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in EDIT_TEXT_engine_init(); + * free in EDIT_TEXT_engine_free(); */ + GPUShader *wire_sh; + GPUShader *overlay_select_sh; + GPUShader *overlay_cursor_sh; +} e_data = {NULL}; /* Engine data */ + +typedef struct EDIT_TEXT_PrivateData { + /* resulting curve as 'wire' for fast editmode drawing */ + DRWShadingGroup *wire_shgrp; + DRWShadingGroup *overlay_select_shgrp; + DRWShadingGroup *overlay_cursor_shgrp; +} EDIT_TEXT_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +/* Init Textures, Framebuffers, Storage and Shaders. + * It is called for every frames. + * (Optional) */ +static void EDIT_TEXT_engine_init(void *vedata) +{ + EDIT_TEXT_TextureList *txl = ((EDIT_TEXT_Data *)vedata)->txl; + EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + + UNUSED_VARS(txl, fbl, stl); + + /* Init Framebuffers like this: order is attachment order (for color texs) */ + /* + * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, + * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; + */ + + /* DRW_framebuffer_init takes care of checking if + * the framebuffer is valid and has the right size*/ + /* + * float *viewport_size = DRW_viewport_size_get(); + * DRW_framebuffer_init(&fbl->occlude_wire_fb, + * (int)viewport_size[0], (int)viewport_size[1], + * tex, 2); + */ + + if (!e_data.wire_sh) { + e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } + + if (!e_data.overlay_select_sh) { + e_data.overlay_select_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } + + if (!e_data.overlay_cursor_sh) { + e_data.overlay_cursor_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } +} + +/* Here init all passes and shading groups + * Assume that all Passes are NULL */ +static void EDIT_TEXT_cache_init(void *vedata) +{ + EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Text outline (fast drawing!) */ + psl->wire_pass = DRW_pass_create( + "Font Wire", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass); + + psl->overlay_select_pass = DRW_pass_create( + "Font Select", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH); + stl->g_data->overlay_select_shgrp = DRW_shgroup_create(e_data.overlay_select_sh, psl->overlay_select_pass); + + psl->overlay_cursor_pass = DRW_pass_create( + "Font Cursor", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH); + stl->g_data->overlay_cursor_shgrp = DRW_shgroup_create(e_data.overlay_cursor_sh, psl->overlay_cursor_pass); + } +} + +/* Add geometry to shadingGroups. Execute for each objects */ +static void EDIT_TEXT_cache_populate(void *vedata, Object *ob) +{ + EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + UNUSED_VARS(psl, stl); + + if (ob->type == OB_FONT) { + if (ob == draw_ctx->object_edit) { + const Curve *cu = ob->data; + /* Get geometry cache */ + struct Gwn_Batch *geom; + + if (cu->flag & CU_FAST) { + geom = DRW_cache_text_edge_wire_get(ob); + if (geom) { + DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); + } + } + else { + /* object mode draws */ + } + + geom = DRW_cache_text_select_overlay_get(ob); + if (geom) { + DRW_shgroup_call_add(stl->g_data->overlay_select_shgrp, geom, ob->obmat); + } + + geom = DRW_cache_text_cursor_overlay_get(ob); + if (geom) { + DRW_shgroup_call_add(stl->g_data->overlay_cursor_shgrp, geom, ob->obmat); + } + } + } +} + +/* Optional: Post-cache_populate callback */ +static void EDIT_TEXT_cache_finish(void *vedata) +{ + EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; + EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; + + /* Do something here! dependant on the objects gathered */ + UNUSED_VARS(psl, stl); +} + +/* Draw time ! Control rendering pipeline from here */ +static void EDIT_TEXT_draw_scene(void *vedata) +{ + EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl; + EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl; + + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + UNUSED_VARS(fbl, dfbl, dtxl); + + /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ + /* + * DRW_framebuffer_texture_detach(dtxl->depth); + * DRW_framebuffer_bind(fbl->custom_fb); + * DRW_draw_pass(psl->pass); + * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); + * DRW_framebuffer_bind(dfbl->default_fb); + */ + + DRW_draw_pass(psl->wire_pass); + + set_inverted_drawing(1); + DRW_draw_pass(psl->overlay_select_pass); + DRW_draw_pass(psl->overlay_cursor_pass); + set_inverted_drawing(0); + + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ +} + +/* Cleanup when destroying the engine. + * This is not per viewport ! only when quitting blender. + * Mostly used for freeing shaders */ +static void EDIT_TEXT_engine_free(void) +{ + // DRW_SHADER_FREE_SAFE(custom_shader); +} + +static const DrawEngineDataSize EDIT_TEXT_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_TEXT_Data); + +DrawEngineType draw_engine_edit_text_type = { + NULL, NULL, + N_("EditTextMode"), + &EDIT_TEXT_data_size, + &EDIT_TEXT_engine_init, + &EDIT_TEXT_engine_free, + &EDIT_TEXT_cache_init, + &EDIT_TEXT_cache_populate, + &EDIT_TEXT_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_TEXT_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c new file mode 100644 index 00000000000..c6a90527f39 --- /dev/null +++ b/source/blender/draw/modes/object_mode.c @@ -0,0 +1,2348 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/object_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_userdef_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_curve_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meta_types.h" +#include "DNA_object_force_types.h" +#include "DNA_lightprobe_types.h" +#include "DNA_particle_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BIF_gl.h" + +#include "BLI_string_utils.h" + +#include "BKE_anim.h" +#include "BKE_camera.h" +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_mball.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_image.h" +#include "BKE_texture.h" + +#include "ED_view3d.h" + +#include "GPU_shader.h" +#include "GPU_texture.h" + +#include "MEM_guardedalloc.h" + +#include "UI_resources.h" + +#include "draw_mode_engines.h" +#include "draw_manager_text.h" +#include "draw_common.h" + +#include "DEG_depsgraph_query.h" + +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GPUTexture *globals_ramp; /* draw_common.c */ +extern GlobalsUboStorage ts; + +extern char datatoc_object_outline_prepass_frag_glsl[]; +extern char datatoc_object_outline_resolve_frag_glsl[]; +extern char datatoc_object_outline_detect_frag_glsl[]; +extern char datatoc_object_outline_expand_frag_glsl[]; +extern char datatoc_object_grid_frag_glsl[]; +extern char datatoc_object_grid_vert_glsl[]; +extern char datatoc_object_empty_image_frag_glsl[]; +extern char datatoc_object_empty_image_vert_glsl[]; +extern char datatoc_object_lightprobe_grid_vert_glsl[]; +extern char datatoc_object_particle_prim_vert_glsl[]; +extern char datatoc_object_particle_dot_vert_glsl[]; +extern char datatoc_object_particle_dot_frag_glsl[]; +extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_fxaa_lib_glsl[]; +extern char datatoc_gpu_shader_flat_color_frag_glsl[]; +extern char datatoc_gpu_shader_flat_id_frag_glsl[]; +extern char datatoc_common_fullscreen_vert_glsl[]; +extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; + +/* *********** LISTS *********** */ +typedef struct OBJECT_PassList { + struct DRWPass *non_meshes; + struct DRWPass *ob_center; + struct DRWPass *outlines; + struct DRWPass *outlines_search; + struct DRWPass *outlines_expand; + struct DRWPass *outlines_bleed; + struct DRWPass *outlines_resolve; + struct DRWPass *grid; + struct DRWPass *bone_solid; + struct DRWPass *bone_outline; + struct DRWPass *bone_wire; + struct DRWPass *bone_envelope; + struct DRWPass *bone_axes; + struct DRWPass *particle; + struct DRWPass *lightprobes; + /* use for empty/background images */ + struct DRWPass *reference_image; +} OBJECT_PassList; + +typedef struct OBJECT_FramebufferList { + struct GPUFrameBuffer *outlines_fb; + struct GPUFrameBuffer *blur_fb; + struct GPUFrameBuffer *expand_fb; +} OBJECT_FramebufferList; + +typedef struct OBJECT_StorageList { + struct OBJECT_PrivateData *g_data; +} OBJECT_StorageList; + +typedef struct OBJECT_Data { + void *engine_type; + OBJECT_FramebufferList *fbl; + DRWViewportEmptyList *txl; + OBJECT_PassList *psl; + OBJECT_StorageList *stl; +} OBJECT_Data; + +/* *********** STATIC *********** */ + +typedef struct OBJECT_PrivateData { + /* Empties */ + DRWShadingGroup *plain_axes; + DRWShadingGroup *cube; + DRWShadingGroup *circle; + DRWShadingGroup *sphere; + DRWShadingGroup *cone; + DRWShadingGroup *single_arrow; + DRWShadingGroup *single_arrow_line; + DRWShadingGroup *arrows; + DRWShadingGroup *axis_names; + /* GPUTexture -> EmptyImageShadingGroupData */ + GHash *image_plane_map; + + /* Force Field */ + DRWShadingGroup *field_wind; + DRWShadingGroup *field_force; + DRWShadingGroup *field_vortex; + DRWShadingGroup *field_curve_sta; + DRWShadingGroup *field_curve_end; + DRWShadingGroup *field_tube_limit; + DRWShadingGroup *field_cone_limit; + + /* Speaker */ + DRWShadingGroup *speaker; + + /* Probe */ + DRWShadingGroup *probe_cube; + DRWShadingGroup *probe_planar; + DRWShadingGroup *probe_grid; + + /* MetaBalls */ + DRWShadingGroup *mball_handle; + + /* Lamps */ + DRWShadingGroup *lamp_center; + DRWShadingGroup *lamp_groundpoint; + DRWShadingGroup *lamp_groundline; + DRWShadingGroup *lamp_circle; + DRWShadingGroup *lamp_circle_shadow; + DRWShadingGroup *lamp_sunrays; + DRWShadingGroup *lamp_distance; + DRWShadingGroup *lamp_buflimit; + DRWShadingGroup *lamp_buflimit_points; + DRWShadingGroup *lamp_area_square; + DRWShadingGroup *lamp_area_disk; + DRWShadingGroup *lamp_hemi; + DRWShadingGroup *lamp_spot_cone; + DRWShadingGroup *lamp_spot_blend; + DRWShadingGroup *lamp_spot_pyramid; + DRWShadingGroup *lamp_spot_blend_rect; + + /* Helpers */ + DRWShadingGroup *relationship_lines; + + /* Objects Centers */ + DRWShadingGroup *center_active; + DRWShadingGroup *center_selected; + DRWShadingGroup *center_deselected; + DRWShadingGroup *center_selected_lib; + DRWShadingGroup *center_deselected_lib; + + /* Camera */ + DRWShadingGroup *camera; + DRWShadingGroup *camera_frame; + DRWShadingGroup *camera_tria; + DRWShadingGroup *camera_focus; + DRWShadingGroup *camera_clip; + DRWShadingGroup *camera_clip_points; + DRWShadingGroup *camera_mist; + DRWShadingGroup *camera_mist_points; + + /* Outlines */ + DRWShadingGroup *outlines_active; + DRWShadingGroup *outlines_select; + DRWShadingGroup *outlines_transform; + + /* Lightprobes */ + DRWShadingGroup *lightprobes_cube_select; + DRWShadingGroup *lightprobes_cube_active; + DRWShadingGroup *lightprobes_cube_transform; + + DRWShadingGroup *lightprobes_planar_select; + DRWShadingGroup *lightprobes_planar_active; + DRWShadingGroup *lightprobes_planar_transform; + + /* Wire */ + DRWShadingGroup *wire; + DRWShadingGroup *wire_active; + DRWShadingGroup *wire_select; + DRWShadingGroup *wire_transform; + + /* Points */ + DRWShadingGroup *points; + DRWShadingGroup *points_active; + DRWShadingGroup *points_select; + DRWShadingGroup *points_transform; + + /* Texture Space */ + DRWShadingGroup *texspace; + + /* Outlines id offset */ + int id_ofs_active; + int id_ofs_select; + int id_ofs_transform; + int id_ofs_prb_active; + int id_ofs_prb_select; + int id_ofs_prb_transform; +} OBJECT_PrivateData; /* Transient data */ + +static struct { + /* Instance Data format */ + struct Gwn_VertFormat *particle_format; + struct Gwn_VertFormat *empty_image_format; + struct Gwn_VertFormat *empty_image_wire_format; + + /* fullscreen shaders */ + GPUShader *outline_prepass_sh; + GPUShader *outline_resolve_sh; + GPUShader *outline_resolve_aa_sh; + GPUShader *outline_detect_sh; + GPUShader *outline_fade_sh; + + /* regular shaders */ + GPUShader *object_empty_image_sh; + GPUShader *object_empty_image_wire_sh; + GPUShader *grid_sh; + GPUShader *part_dot_sh; + GPUShader *part_prim_sh; + GPUShader *part_axis_sh; + GPUShader *lightprobe_grid_sh; + float camera_pos[3]; + float screenvecs[3][4]; + float grid_settings[5]; + int grid_flag; + float grid_normal[3]; + float grid_axes[3]; + int zpos_flag; + int zneg_flag; + float zplane_normal[3]; + float zplane_axes[3]; + float inv_viewport_size[2]; + bool draw_grid; + /* Temp buffer textures */ + struct GPUTexture *outlines_depth_tx; + struct GPUTexture *outlines_id_tx; + struct GPUTexture *outlines_color_tx; + struct GPUTexture *outlines_blur_tx; +} e_data = {NULL}; /* Engine data */ + + +enum { + SHOW_AXIS_X = (1 << 0), + SHOW_AXIS_Y = (1 << 1), + SHOW_AXIS_Z = (1 << 2), + SHOW_GRID = (1 << 3), + PLANE_XY = (1 << 4), + PLANE_XZ = (1 << 5), + PLANE_YZ = (1 << 6), + CLIP_ZPOS = (1 << 7), + CLIP_ZNEG = (1 << 8), + GRID_BACK = (1 << 9), +}; + +/* *********** FUNCTIONS *********** */ + +static void OBJECT_engine_init(void *vedata) +{ + OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl; + + const float *viewport_size = DRW_viewport_size_get(); + const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; + + if (DRW_state_is_fbo()) { + e_data.outlines_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_DEPTH_COMPONENT24, + &draw_engine_object_type); + /* XXX TODO GPU_R16UI can overflow, it would cause no harm + * (only bad colored or missing outlines) but we should + * use 32bits only if the scene have that many objects */ + e_data.outlines_id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R16UI, + &draw_engine_object_type); + + GPU_framebuffer_ensure_config(&fbl->outlines_fb, { + GPU_ATTACHMENT_TEXTURE(e_data.outlines_depth_tx), + GPU_ATTACHMENT_TEXTURE(e_data.outlines_id_tx) + }); + + e_data.outlines_color_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, + &draw_engine_object_type); + + GPU_framebuffer_ensure_config(&fbl->expand_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.outlines_color_tx) + }); + + e_data.outlines_blur_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, + &draw_engine_object_type); + + GPU_framebuffer_ensure_config(&fbl->blur_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.outlines_blur_tx) + }); + } + + /* Shaders */ + if (!e_data.outline_resolve_sh) { + /* Outline */ + e_data.outline_prepass_sh = DRW_shader_create_3D(datatoc_object_outline_prepass_frag_glsl, NULL); + + e_data.outline_resolve_sh = DRW_shader_create_fullscreen(datatoc_object_outline_resolve_frag_glsl, NULL); + + e_data.outline_resolve_aa_sh = DRW_shader_create_with_lib( + datatoc_common_fullscreen_vert_glsl, NULL, + datatoc_object_outline_resolve_frag_glsl, + datatoc_common_fxaa_lib_glsl, + "#define FXAA_ALPHA\n" + "#define USE_FXAA\n"); + + e_data.outline_detect_sh = DRW_shader_create_with_lib( + datatoc_common_fullscreen_vert_glsl, NULL, + datatoc_object_outline_detect_frag_glsl, + datatoc_common_globals_lib_glsl, + "#extension GL_ARB_texture_gather : enable\n"); + + e_data.outline_fade_sh = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, NULL); + + /* Empty images */ + e_data.object_empty_image_sh = DRW_shader_create_with_lib( + datatoc_object_empty_image_vert_glsl, NULL, + datatoc_object_empty_image_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + + e_data.object_empty_image_wire_sh = DRW_shader_create_with_lib( + datatoc_object_empty_image_vert_glsl, NULL, + datatoc_object_empty_image_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define USE_WIRE\n"); + + /* Grid */ + e_data.grid_sh = DRW_shader_create_with_lib( + datatoc_object_grid_vert_glsl, NULL, + datatoc_object_grid_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + + /* Particles */ + e_data.part_prim_sh = DRW_shader_create( + datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, NULL); + + e_data.part_axis_sh = DRW_shader_create( + datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, + "#define USE_AXIS\n"); + + e_data.part_dot_sh = DRW_shader_create( + datatoc_object_particle_dot_vert_glsl, NULL, datatoc_object_particle_dot_frag_glsl, NULL); + + /* Lightprobes */ + e_data.lightprobe_grid_sh = DRW_shader_create( + datatoc_object_lightprobe_grid_vert_glsl, NULL, datatoc_gpu_shader_flat_id_frag_glsl, NULL); + } + + { + /* Grid precompute */ + float invviewmat[4][4], invwinmat[4][4]; + float viewmat[4][4], winmat[4][4]; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + Scene *scene = draw_ctx->scene; + RegionView3D *rv3d = draw_ctx->rv3d; + float grid_scale = ED_view3d_grid_scale(scene, v3d, NULL); + float grid_res; + + const bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0; + const bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0; + const bool show_axis_z = (v3d->gridflag & V3D_SHOW_Z) != 0; + const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) != 0; + e_data.draw_grid = show_axis_x || show_axis_y || show_axis_z || show_floor; + + DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_get(invwinmat, DRW_MAT_WININV); + DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); + + /* Setup camera pos */ + copy_v3_v3(e_data.camera_pos, invviewmat[3]); + + /* if perps */ + if (winmat[3][3] == 0.0f) { + float fov; + float viewvecs[2][4] = { + {1.0f, -1.0f, -1.0f, 1.0f}, + {-1.0f, 1.0f, -1.0f, 1.0f} + }; + + /* convert the view vectors to view space */ + for (int i = 0; i < 2; i++) { + mul_m4_v4(invwinmat, viewvecs[i]); + mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */ + } + + fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f; + grid_res = fabsf(tanf(fov)) / grid_scale; + + e_data.grid_flag = (1 << 4); /* XY plane */ + if (show_axis_x) + e_data.grid_flag |= SHOW_AXIS_X; + if (show_axis_y) + e_data.grid_flag |= SHOW_AXIS_Y; + if (show_floor) + e_data.grid_flag |= SHOW_GRID; + + } + else { + float viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); + grid_res = viewdist / grid_scale; + + if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) { + e_data.grid_flag = PLANE_YZ; + e_data.grid_flag |= SHOW_AXIS_Y; + e_data.grid_flag |= SHOW_AXIS_Z; + e_data.grid_flag |= SHOW_GRID; + e_data.grid_flag |= GRID_BACK; + } + else if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { + e_data.grid_flag = PLANE_XY; + e_data.grid_flag |= SHOW_AXIS_X; + e_data.grid_flag |= SHOW_AXIS_Y; + e_data.grid_flag |= SHOW_GRID; + e_data.grid_flag |= GRID_BACK; + } + else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { + e_data.grid_flag = PLANE_XZ; + e_data.grid_flag |= SHOW_AXIS_X; + e_data.grid_flag |= SHOW_AXIS_Z; + e_data.grid_flag |= SHOW_GRID; + e_data.grid_flag |= GRID_BACK; + } + else { /* RV3D_VIEW_USER */ + e_data.grid_flag = PLANE_XY; + if (show_axis_x) + e_data.grid_flag |= SHOW_AXIS_X; + if (show_axis_y) + e_data.grid_flag |= SHOW_AXIS_Y; + if (show_floor) + e_data.grid_flag |= SHOW_GRID; + } + } + + e_data.grid_normal[0] = (float)((e_data.grid_flag & PLANE_YZ) != 0); + e_data.grid_normal[1] = (float)((e_data.grid_flag & PLANE_XZ) != 0); + e_data.grid_normal[2] = (float)((e_data.grid_flag & PLANE_XY) != 0); + + e_data.grid_axes[0] = (float)((e_data.grid_flag & (PLANE_XZ | PLANE_XY)) != 0); + e_data.grid_axes[1] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XY)) != 0); + e_data.grid_axes[2] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XZ)) != 0); + + /* Vectors to recover pixel world position. Fix grid precision issue. */ + /* Using pixel at z = 0.0f in ndc space : gives average precision between + * near and far plane. Note that it might not be the best choice. */ + copy_v4_fl4(e_data.screenvecs[0], 1.0f, -1.0f, 0.0f, 1.0f); + copy_v4_fl4(e_data.screenvecs[1], -1.0f, 1.0f, 0.0f, 1.0f); + copy_v4_fl4(e_data.screenvecs[2], -1.0f, -1.0f, 0.0f, 1.0f); + + for (int i = 0; i < 3; i++) { + /* Doing 2 steps to recover world position of the corners of the frustum. + * Using the inverse perspective matrix is giving very low precision output. */ + mul_m4_v4(invwinmat, e_data.screenvecs[i]); + e_data.screenvecs[i][0] /= e_data.screenvecs[i][3]; /* perspective divide */ + e_data.screenvecs[i][1] /= e_data.screenvecs[i][3]; /* perspective divide */ + e_data.screenvecs[i][2] /= e_data.screenvecs[i][3]; /* perspective divide */ + e_data.screenvecs[i][3] = 1.0f; + /* main instability come from this one */ + /* TODO : to make things even more stable, don't use + * invviewmat and derive vectors from camera properties */ + mul_m4_v4(invviewmat, e_data.screenvecs[i]); + } + + sub_v3_v3(e_data.screenvecs[0], e_data.screenvecs[2]); + sub_v3_v3(e_data.screenvecs[1], e_data.screenvecs[2]); + + /* Z axis if needed */ + if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) { + e_data.zpos_flag = SHOW_AXIS_Z; + + float zvec[4] = {0.0f, 0.0f, -1.0f, 0.0f}; + mul_m4_v4(invviewmat, zvec); + + /* z axis : chose the most facing plane */ + if (fabsf(zvec[0]) < fabsf(zvec[1])) { + e_data.zpos_flag |= PLANE_XZ; + } + else { + e_data.zpos_flag |= PLANE_YZ; + } + + e_data.zneg_flag = e_data.zpos_flag; + + /* Persp : If camera is below floor plane, we switch clipping + * Ortho : If eye vector is looking up, we switch clipping */ + if (((winmat[3][3] == 0.0f) && (e_data.camera_pos[2] > 0.0f)) || + ((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f))) + { + e_data.zpos_flag |= CLIP_ZPOS; + e_data.zneg_flag |= CLIP_ZNEG; + } + else { + e_data.zpos_flag |= CLIP_ZNEG; + e_data.zneg_flag |= CLIP_ZPOS; + } + + e_data.zplane_normal[0] = (float)((e_data.zpos_flag & PLANE_YZ) != 0); + e_data.zplane_normal[1] = (float)((e_data.zpos_flag & PLANE_XZ) != 0); + e_data.zplane_normal[2] = (float)((e_data.zpos_flag & PLANE_XY) != 0); + + e_data.zplane_axes[0] = (float)((e_data.zpos_flag & (PLANE_XZ | PLANE_XY)) != 0); + e_data.zplane_axes[1] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XY)) != 0); + e_data.zplane_axes[2] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XZ)) != 0); + + } + else { + e_data.zneg_flag = e_data.zpos_flag = CLIP_ZNEG | CLIP_ZPOS; + } + + float dist; + if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera); + dist = ((Camera *)camera_object)->clipend; + } + else { + dist = v3d->far; + } + + e_data.grid_settings[0] = dist / 2.0f; /* gridDistance */ + e_data.grid_settings[1] = grid_res; /* gridResolution */ + e_data.grid_settings[2] = grid_scale; /* gridScale */ + e_data.grid_settings[3] = v3d->gridsubdiv; /* gridSubdiv */ + e_data.grid_settings[4] = (v3d->gridsubdiv > 1) ? 1.0f / logf(v3d->gridsubdiv) : 0.0f; /* 1/log(gridSubdiv) */ + } + + copy_v2_v2(e_data.inv_viewport_size, DRW_viewport_size_get()); + invert_v2(e_data.inv_viewport_size); +} + +static void OBJECT_engine_free(void) +{ + MEM_SAFE_FREE(e_data.particle_format); + MEM_SAFE_FREE(e_data.empty_image_format); + MEM_SAFE_FREE(e_data.empty_image_wire_format); + DRW_SHADER_FREE_SAFE(e_data.outline_prepass_sh); + DRW_SHADER_FREE_SAFE(e_data.outline_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data.outline_resolve_aa_sh); + DRW_SHADER_FREE_SAFE(e_data.outline_detect_sh); + DRW_SHADER_FREE_SAFE(e_data.outline_fade_sh); + DRW_SHADER_FREE_SAFE(e_data.object_empty_image_sh); + DRW_SHADER_FREE_SAFE(e_data.object_empty_image_wire_sh); + DRW_SHADER_FREE_SAFE(e_data.grid_sh); + DRW_SHADER_FREE_SAFE(e_data.part_prim_sh); + DRW_SHADER_FREE_SAFE(e_data.part_axis_sh); + DRW_SHADER_FREE_SAFE(e_data.part_dot_sh); + DRW_SHADER_FREE_SAFE(e_data.lightprobe_grid_sh); +} + +static DRWShadingGroup *shgroup_outline(DRWPass *pass, const int *ofs, GPUShader *sh) +{ + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_int(grp, "baseId", ofs, 1); + + return grp; +} + +/* currently same as 'shgroup_outline', new function to avoid confustion */ +static DRWShadingGroup *shgroup_wire(DRWPass *pass, const float col[4], GPUShader *sh) +{ + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", col, 1); + + return grp; +} + +/* currently same as 'shgroup_outline', new function to avoid confustion */ +static DRWShadingGroup *shgroup_points(DRWPass *pass, const float col[4], GPUShader *sh) +{ + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_vec4(grp, "color", col, 1); + + return grp; +} + +static int *shgroup_theme_id_to_probe_outline_counter( + OBJECT_StorageList *stl, int theme_id) +{ + switch (theme_id) { + case TH_ACTIVE: + return &stl->g_data->id_ofs_prb_active; + case TH_SELECT: + return &stl->g_data->id_ofs_prb_select; + case TH_TRANSFORM: + default: + return &stl->g_data->id_ofs_prb_transform; + } +} + +static int *shgroup_theme_id_to_outline_counter( + OBJECT_StorageList *stl, int theme_id) +{ + switch (theme_id) { + case TH_ACTIVE: + return &stl->g_data->id_ofs_active; + case TH_SELECT: + return &stl->g_data->id_ofs_select; + case TH_TRANSFORM: + default: + return &stl->g_data->id_ofs_transform; + } +} + +static DRWShadingGroup *shgroup_theme_id_to_probe_planar_outline_shgrp( + OBJECT_StorageList *stl, int theme_id) +{ + /* does not increment counter */ + switch (theme_id) { + case TH_ACTIVE: + return stl->g_data->lightprobes_planar_active; + case TH_SELECT: + return stl->g_data->lightprobes_planar_select; + case TH_TRANSFORM: + default: + return stl->g_data->lightprobes_planar_transform; + } +} + +static DRWShadingGroup *shgroup_theme_id_to_probe_cube_outline_shgrp( + OBJECT_StorageList *stl, int theme_id) +{ + /* does not increment counter */ + switch (theme_id) { + case TH_ACTIVE: + return stl->g_data->lightprobes_cube_active; + case TH_SELECT: + return stl->g_data->lightprobes_cube_select; + case TH_TRANSFORM: + default: + return stl->g_data->lightprobes_cube_transform; + } +} + +static DRWShadingGroup *shgroup_theme_id_to_outline_or( + OBJECT_StorageList *stl, int theme_id, DRWShadingGroup *fallback) +{ + int *counter = shgroup_theme_id_to_outline_counter(stl, theme_id); + *counter += 1; + + switch (theme_id) { + case TH_ACTIVE: + return stl->g_data->outlines_active; + case TH_SELECT: + return stl->g_data->outlines_select; + case TH_TRANSFORM: + return stl->g_data->outlines_transform; + default: + return fallback; + } +} + +static DRWShadingGroup *shgroup_theme_id_to_wire_or( + OBJECT_StorageList *stl, int theme_id, DRWShadingGroup *fallback) +{ + switch (theme_id) { + case TH_ACTIVE: + return stl->g_data->wire_active; + case TH_SELECT: + return stl->g_data->wire_select; + case TH_TRANSFORM: + return stl->g_data->wire_transform; + default: + return fallback; + } +} + +static DRWShadingGroup *shgroup_theme_id_to_point_or( + OBJECT_StorageList *stl, int theme_id, DRWShadingGroup *fallback) +{ + switch (theme_id) { + case TH_ACTIVE: + return stl->g_data->points_active; + case TH_SELECT: + return stl->g_data->points_select; + case TH_TRANSFORM: + return stl->g_data->points_transform; + default: + return fallback; + } +} + +static void image_calc_aspect(Image *ima, ImageUser *iuser, float r_image_aspect[2]) +{ + float ima_x, ima_y; + if (ima) { + int w, h; + BKE_image_get_size(ima, iuser, &w, &h); + ima_x = w; + ima_y = h; + } + else { + /* if no image, make it a 1x1 empty square, honor scale & offset */ + ima_x = ima_y = 1.0f; + } + /* Get the image aspect even if the buffer is invalid */ + float sca_x = 1.0f, sca_y = 1.0f; + if (ima) { + if (ima->aspx > ima->aspy) { + sca_y = ima->aspy / ima->aspx; + } + else if (ima->aspx < ima->aspy) { + sca_x = ima->aspx / ima->aspy; + } + } + + const float scale_x_inv = ima_x * sca_x; + const float scale_y_inv = ima_y * sca_y; + if (scale_x_inv > scale_y_inv) { + r_image_aspect[0] = 1.0f; + r_image_aspect[1] = scale_y_inv / scale_x_inv; + } + else { + r_image_aspect[0] = scale_x_inv / scale_y_inv; + r_image_aspect[1] = 1.0f; + } +} + +/* per-image shading groups for image-type empty objects */ +struct EmptyImageShadingGroupData { + DRWShadingGroup *shgrp_image; + DRWShadingGroup *shgrp_wire; + float image_aspect[2]; +}; + +static void DRW_shgroup_empty_image( + OBJECT_StorageList *stl, OBJECT_PassList *psl, Object *ob, const float color[3]) +{ + /* TODO: 'StereoViews', see draw_empty_image. */ + + if (stl->g_data->image_plane_map == NULL) { + stl->g_data->image_plane_map = BLI_ghash_ptr_new(__func__); + } + + struct EmptyImageShadingGroupData *empty_image_data; + + GPUTexture *tex = ob->data ? + GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false, false, false) : NULL; + void **val_p; + + /* Create on demand, 'tex' may be NULL. */ + if (BLI_ghash_ensure_p(stl->g_data->image_plane_map, tex, &val_p)) { + empty_image_data = *val_p; + } + else { + empty_image_data = MEM_mallocN(sizeof(*empty_image_data), __func__); + + image_calc_aspect(ob->data, ob->iuser, empty_image_data->image_aspect); + + if (tex) { + DRW_shgroup_instance_format(e_data.empty_image_format, { + {"objectColor", DRW_ATTRIB_FLOAT, 4}, + {"size", DRW_ATTRIB_FLOAT, 1}, + {"offset", DRW_ATTRIB_FLOAT, 2}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, + }); + + struct Gwn_Batch *geom = DRW_cache_image_plane_get(); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + e_data.object_empty_image_sh, psl->non_meshes, geom, e_data.empty_image_format); + DRW_shgroup_uniform_texture(grp, "image", tex); + DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1); + + empty_image_data->shgrp_image = grp; + } + else { + empty_image_data->shgrp_image = NULL; + } + + { + DRW_shgroup_instance_format(e_data.empty_image_wire_format, { + {"objectColor", DRW_ATTRIB_FLOAT, 4}, + {"size", DRW_ATTRIB_FLOAT, 1}, + {"offset", DRW_ATTRIB_FLOAT, 2}, + {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} + }); + + struct Gwn_Batch *geom = DRW_cache_image_plane_wire_get(); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + e_data.object_empty_image_wire_sh, psl->non_meshes, geom, e_data.empty_image_wire_format); + DRW_shgroup_uniform_vec2(grp, "aspect", empty_image_data->image_aspect, 1); + + empty_image_data->shgrp_wire = grp; + } + + *val_p = empty_image_data; + } + + if (empty_image_data->shgrp_image != NULL) { + DRW_shgroup_call_dynamic_add( + empty_image_data->shgrp_image, + ob->col, + &ob->empty_drawsize, + ob->ima_ofs, + ob->obmat); + } + + DRW_shgroup_call_dynamic_add( + empty_image_data->shgrp_wire, + color, + &ob->empty_drawsize, + ob->ima_ofs, + ob->obmat); +} + +static void OBJECT_cache_init(void *vedata) +{ + OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; + OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + OBJECT_PrivateData *g_data; + /* TODO : use dpi setting for enabling the second pass */ + const bool do_outline_expand = false; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + g_data = stl->g_data; + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE; + psl->outlines = DRW_pass_create("Outlines Depth Pass", state); + + GPUShader *sh = e_data.outline_prepass_sh; + + /* Select */ + g_data->outlines_select = shgroup_outline(psl->outlines, &g_data->id_ofs_select, sh); + + /* Transform */ + g_data->outlines_transform = shgroup_outline(psl->outlines, &g_data->id_ofs_transform, sh); + + /* Active */ + g_data->outlines_active = shgroup_outline(psl->outlines, &g_data->id_ofs_active, sh); + + g_data->id_ofs_select = 0; + g_data->id_ofs_active = 0; + g_data->id_ofs_transform = 0; + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + DRWPass *pass = psl->lightprobes = DRW_pass_create("Object Probe Pass", state); + struct Gwn_Batch *sphere = DRW_cache_sphere_get(); + struct Gwn_Batch *quad = DRW_cache_quad_get(); + + /* Cubemap */ + g_data->lightprobes_cube_select = shgroup_instance_outline(pass, sphere, &g_data->id_ofs_prb_select); + g_data->lightprobes_cube_active = shgroup_instance_outline(pass, sphere, &g_data->id_ofs_prb_active); + g_data->lightprobes_cube_transform = shgroup_instance_outline(pass, sphere, &g_data->id_ofs_prb_transform); + + /* Planar */ + g_data->lightprobes_planar_select = shgroup_instance_outline(pass, quad, &g_data->id_ofs_prb_select); + g_data->lightprobes_planar_active = shgroup_instance_outline(pass, quad, &g_data->id_ofs_prb_active); + g_data->lightprobes_planar_transform = shgroup_instance_outline(pass, quad, &g_data->id_ofs_prb_transform); + + g_data->id_ofs_prb_select = 0; + g_data->id_ofs_prb_active = 0; + g_data->id_ofs_prb_transform = 0; + } + + { + DRWState state = DRW_STATE_WRITE_COLOR; + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + static float alphaOcclu = 0.35f; + /* Reminder : bool uniforms need to be 4 bytes. */ + static const int bTrue = true; + static const int bFalse = false; + + psl->outlines_search = DRW_pass_create("Outlines Detect Pass", state); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_detect_sh, psl->outlines_search); + DRW_shgroup_uniform_texture_ref(grp, "outlineId", &e_data.outlines_id_tx); + DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &e_data.outlines_depth_tx); + DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth); + DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_float(grp, "alphaOcclu", &alphaOcclu, 1); + DRW_shgroup_uniform_int(grp, "idOffsets", &stl->g_data->id_ofs_active, 3); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state); + + grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_expand); + DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_blur_tx); + DRW_shgroup_uniform_bool(grp, "doExpand", (do_outline_expand) ? &bTrue : &bFalse, 1); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->outlines_bleed = DRW_pass_create("Outlines Bleed Pass", state); + + if (do_outline_expand) { + grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_bleed); + DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_color_tx); + DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1); + DRW_shgroup_call_add(grp, quad, NULL); + } + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND; + psl->outlines_resolve = DRW_pass_create("Outlines Resolve Pass", state); + + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + GPUTexture **outline_tx = (do_outline_expand) ? &e_data.outlines_blur_tx : &e_data.outlines_color_tx; + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_resolve_aa_sh, psl->outlines_resolve); + DRW_shgroup_uniform_texture_ref(grp, "outlineBluredColor", outline_tx); + DRW_shgroup_uniform_vec2(grp, "rcpDimensions", e_data.inv_viewport_size, 1); + DRW_shgroup_call_add(grp, quad, NULL); + } + + { + /* Grid pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND; + psl->grid = DRW_pass_create("Infinite Grid Pass", state); + + struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); + static float mat[4][4]; + unit_m4(mat); + + /* Create 3 quads to render ordered transparency Z axis */ + DRWShadingGroup *grp = DRW_shgroup_create(e_data.grid_sh, psl->grid); + DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1); + DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.zplane_normal, 1); + DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); + DRW_shgroup_uniform_vec3(grp, "cameraPos", e_data.camera_pos, 1); + DRW_shgroup_uniform_vec4(grp, "screenvecs[0]", e_data.screenvecs[0], 3); + DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1); + DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1); + DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_call_add(grp, quad, mat); + + grp = DRW_shgroup_create(e_data.grid_sh, psl->grid); + DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.grid_flag, 1); + DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.grid_normal, 1); + DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1); + DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_call_add(grp, quad, mat); + + grp = DRW_shgroup_create(e_data.grid_sh, psl->grid); + DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zpos_flag, 1); + DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.zplane_normal, 1); + DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); + DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_call_add(grp, quad, mat); + } + + { + /* Solid bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + psl->bone_solid = DRW_pass_create("Bone Solid Pass", state); + psl->bone_outline = DRW_pass_create("Bone Outline Pass", state); + } + + { + /* Wire bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND; + psl->bone_wire = DRW_pass_create("Bone Wire Pass", state); + } + + { + /* distance outline around envelope bones */ + DRWState state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_FRONT; + psl->bone_envelope = DRW_pass_create("Bone Envelope Outline Pass", state); + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE; + psl->bone_axes = DRW_pass_create("Bone Axes Pass", state); + } + + { + /* Non Meshes Pass (Camera, empties, lamps ...) */ + struct Gwn_Batch *geom; + + DRWState state = + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_POINT; + state |= DRW_STATE_WIRE; + psl->non_meshes = DRW_pass_create("Non Meshes Pass", state); + + /* Empties */ + geom = DRW_cache_plain_axes_get(); + stl->g_data->plain_axes = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_cube_get(); + stl->g_data->cube = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_circle_get(); + stl->g_data->circle = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_empty_sphere_get(); + stl->g_data->sphere = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_empty_cone_get(); + stl->g_data->cone = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_arrow_get(); + stl->g_data->single_arrow = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_get(); + stl->g_data->single_arrow_line = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_arrows_get(); + stl->g_data->arrows = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_axis_names_get(); + stl->g_data->axis_names = shgroup_instance_axis_names(psl->non_meshes, geom); + + /* initialize on first use */ + stl->g_data->image_plane_map = NULL; + + /* Force Field */ + geom = DRW_cache_field_wind_get(); + stl->g_data->field_wind = shgroup_instance_scaled(psl->non_meshes, geom); + + geom = DRW_cache_field_force_get(); + stl->g_data->field_force = shgroup_instance_screen_aligned(psl->non_meshes, geom); + + geom = DRW_cache_field_vortex_get(); + stl->g_data->field_vortex = shgroup_instance_scaled(psl->non_meshes, geom); + + geom = DRW_cache_screenspace_circle_get(); + stl->g_data->field_curve_sta = shgroup_instance_screen_aligned(psl->non_meshes, geom); + + /* Speaker */ + geom = DRW_cache_speaker_get(); + stl->g_data->speaker = shgroup_instance(psl->non_meshes, geom); + + /* Probe */ + static float probeSize = 14.0f; + geom = DRW_cache_lightprobe_cube_get(); + stl->g_data->probe_cube = shgroup_instance_screenspace(psl->non_meshes, geom, &probeSize); + + geom = DRW_cache_lightprobe_grid_get(); + stl->g_data->probe_grid = shgroup_instance_screenspace(psl->non_meshes, geom, &probeSize); + + static float probePlanarSize = 20.0f; + geom = DRW_cache_lightprobe_planar_get(); + stl->g_data->probe_planar = shgroup_instance_screenspace(psl->non_meshes, geom, &probePlanarSize); + + /* Camera */ + geom = DRW_cache_camera_get(); + stl->g_data->camera = shgroup_camera_instance(psl->non_meshes, geom); + + geom = DRW_cache_camera_frame_get(); + stl->g_data->camera_frame = shgroup_camera_instance(psl->non_meshes, geom); + + geom = DRW_cache_camera_tria_get(); + stl->g_data->camera_tria = shgroup_camera_instance(psl->non_meshes, geom); + + geom = DRW_cache_plain_axes_get(); + stl->g_data->camera_focus = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_get(); + stl->g_data->camera_clip = shgroup_distance_lines_instance(psl->non_meshes, geom); + stl->g_data->camera_mist = shgroup_distance_lines_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_endpoints_get(); + stl->g_data->camera_clip_points = shgroup_distance_lines_instance(psl->non_meshes, geom); + stl->g_data->camera_mist_points = shgroup_distance_lines_instance(psl->non_meshes, geom); + + /* Texture Space */ + geom = DRW_cache_cube_get(); + stl->g_data->texspace = shgroup_instance(psl->non_meshes, geom); + } + + { + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + + /* Unselected */ + stl->g_data->wire = shgroup_wire(psl->non_meshes, ts.colorWire, sh); + + /* Select */ + stl->g_data->wire_select = shgroup_wire(psl->non_meshes, ts.colorSelect, sh); + + /* Transform */ + stl->g_data->wire_transform = shgroup_wire(psl->non_meshes, ts.colorTransform, sh); + + /* Active */ + stl->g_data->wire_active = shgroup_wire(psl->non_meshes, ts.colorActive, sh); + } + + + { + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + + /* Unselected */ + stl->g_data->points = shgroup_points(psl->non_meshes, ts.colorWire, sh); + + /* Select */ + stl->g_data->points_select = shgroup_points(psl->non_meshes, ts.colorSelect, sh); + + /* Transform */ + stl->g_data->points_transform = shgroup_points(psl->non_meshes, ts.colorTransform, sh); + + /* Active */ + stl->g_data->points_active = shgroup_points(psl->non_meshes, ts.colorActive, sh); + } + + { + /* Metaballs Handles */ + stl->g_data->mball_handle = shgroup_instance_mball_handles(psl->non_meshes); + } + + { + /* Lamps */ + /* TODO + * for now we create multiple times the same VBO with only lamp center coordinates + * but ideally we would only create it once */ + struct Gwn_Batch *geom; + + /* start with buflimit because we don't want stipples */ + geom = DRW_cache_single_line_get(); + stl->g_data->lamp_buflimit = shgroup_distance_lines_instance(psl->non_meshes, geom); + + stl->g_data->lamp_center = shgroup_dynpoints_uniform_color(psl->non_meshes, ts.colorLampNoAlpha, &ts.sizeLampCenter); + + geom = DRW_cache_lamp_get(); + stl->g_data->lamp_circle = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle); + geom = DRW_cache_lamp_shadows_get(); + stl->g_data->lamp_circle_shadow = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircleShadow); + + geom = DRW_cache_lamp_sunrays_get(); + stl->g_data->lamp_sunrays = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle); + + stl->g_data->lamp_groundline = shgroup_groundlines_uniform_color(psl->non_meshes, ts.colorLamp); + stl->g_data->lamp_groundpoint = shgroup_groundpoints_uniform_color(psl->non_meshes, ts.colorLamp); + + geom = DRW_cache_lamp_area_square_get(); + stl->g_data->lamp_area_square = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_lamp_area_disk_get(); + stl->g_data->lamp_area_disk = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_lamp_hemi_get(); + stl->g_data->lamp_hemi = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_get(); + stl->g_data->lamp_distance = shgroup_distance_lines_instance(psl->non_meshes, geom); + + geom = DRW_cache_single_line_endpoints_get(); + stl->g_data->lamp_buflimit_points = shgroup_distance_lines_instance(psl->non_meshes, geom); + + geom = DRW_cache_lamp_spot_get(); + stl->g_data->lamp_spot_cone = shgroup_spot_instance(psl->non_meshes, geom); + + geom = DRW_cache_circle_get(); + stl->g_data->lamp_spot_blend = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_lamp_spot_square_get(); + stl->g_data->lamp_spot_pyramid = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_square_get(); + stl->g_data->lamp_spot_blend_rect = shgroup_instance(psl->non_meshes, geom); + } + + { + /* -------- STIPPLES ------- */ + struct Gwn_Batch *geom; + + /* Relationship Lines */ + stl->g_data->relationship_lines = shgroup_dynlines_dashed_uniform_color(psl->non_meshes, ts.colorWire); + + /* Force Field Curve Guide End (here because of stipple) */ + /* TODO port to shader stipple */ + geom = DRW_cache_screenspace_circle_get(); + stl->g_data->field_curve_end = shgroup_instance_screen_aligned(psl->non_meshes, geom); + + /* Force Field Limits */ + /* TODO port to shader stipple */ + geom = DRW_cache_field_tube_limit_get(); + stl->g_data->field_tube_limit = shgroup_instance_scaled(psl->non_meshes, geom); + + /* TODO port to shader stipple */ + geom = DRW_cache_field_cone_limit_get(); + stl->g_data->field_cone_limit = shgroup_instance_scaled(psl->non_meshes, geom); + } + + { + /* Object Center pass grouped by State */ + DRWShadingGroup *grp; + static float outlineWidth, size; + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT; + psl->ob_center = DRW_pass_create("Obj Center Pass", state); + + outlineWidth = 1.0f * U.pixelsize; + size = U.obcenter_dia * U.pixelsize + outlineWidth; + + GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + + /* Active */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_float(grp, "size", &size, 1); + DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1); + DRW_shgroup_uniform_vec4(grp, "color", ts.colorActive, 1); + DRW_shgroup_uniform_vec4(grp, "outlineColor", ts.colorOutline, 1); + stl->g_data->center_active = grp; + + /* Select */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", ts.colorSelect, 1); + stl->g_data->center_selected = grp; + + /* Deselect */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", ts.colorDeselect, 1); + stl->g_data->center_deselected = grp; + + /* Select (library) */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", ts.colorLibrarySelect, 1); + stl->g_data->center_selected_lib = grp; + + /* Deselect (library) */ + grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + DRW_shgroup_uniform_vec4(grp, "color", ts.colorLibrary, 1); + stl->g_data->center_deselected_lib = grp; + } + + { + /* Particle Pass */ + psl->particle = DRW_pass_create( + "Particle Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_POINT | DRW_STATE_BLEND); + } + + { + /* Empty/Background Image Pass */ + psl->reference_image = DRW_pass_create( + "Refrence Image Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + } +} + +static void DRW_shgroup_mball_handles(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer) +{ + MetaBall *mb = ob->data; + + float *color; + DRW_object_wire_theme_get(ob, view_layer, &color); + + float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */ + { + float scamat[3][3]; + copy_m3_m4(scamat, ob->obmat); + /* Get the normalized inverse matrix to extract only + * the scale of Scamat */ + float iscamat[3][3]; + invert_m3_m3(iscamat, scamat); + normalize_m3(iscamat); + mul_m3_m3_post(scamat, iscamat); + + copy_v3_v3(draw_scale_xform[0], scamat[0]); + copy_v3_v3(draw_scale_xform[1], scamat[1]); + copy_v3_v3(draw_scale_xform[2], scamat[2]); + } + + for (MetaElem *ml = mb->elems.first; ml != NULL; ml = ml->next) { + /* draw radius */ + float world_pos[3]; + mul_v3_m4v3(world_pos, ob->obmat, &ml->x); + draw_scale_xform[0][3] = world_pos[0]; + draw_scale_xform[1][3] = world_pos[1]; + draw_scale_xform[2][3] = world_pos[2]; + + DRW_shgroup_call_dynamic_add(stl->g_data->mball_handle, draw_scale_xform, &ml->rad, color); + } +} + +static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer) +{ + Lamp *la = ob->data; + float *color; + int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color); + static float zero = 0.0f; + + typedef struct LampEngineData { + ObjectEngineData engine_data; + float shape_mat[4][4]; + float spot_blend_mat[4][4]; + } LampEngineData; + + LampEngineData *lamp_engine_data = + (LampEngineData *)DRW_object_engine_data_ensure( + ob, + &draw_engine_object_type, + sizeof(LampEngineData), + NULL, + NULL); + + float (*shapemat)[4] = lamp_engine_data->shape_mat; + float (*spotblendmat)[4] = lamp_engine_data->spot_blend_mat; + + /* Don't draw the center if it's selected or active */ + if (theme_id == TH_LAMP) + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_center, ob->obmat[3]); + + /* First circle */ + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_circle, ob->obmat[3], color); + + /* draw dashed outer circle for shadow */ + if (la->type != LA_HEMI) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_circle_shadow, ob->obmat[3], color); + } + + /* Distance */ + if (ELEM(la->type, LA_HEMI, LA_SUN, LA_AREA)) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_distance, color, &zero, &la->dist, ob->obmat); + } + + copy_m4_m4(shapemat, ob->obmat); + + if (la->type == LA_SUN) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_sunrays, ob->obmat[3], color); + } + else if (la->type == LA_SPOT) { + float size[3], sizemat[4][4]; + static float one = 1.0f; + float blend = 1.0f - pow2f(la->spotblend); + + size[0] = size[1] = sinf(la->spotsize * 0.5f) * la->dist; + size[2] = cosf(la->spotsize * 0.5f) * la->dist; + + size_to_mat4(sizemat, size); + mul_m4_m4m4(shapemat, ob->obmat, sizemat); + + size[0] = size[1] = blend; size[2] = 1.0f; + size_to_mat4(sizemat, size); + translate_m4(sizemat, 0.0f, 0.0f, -1.0f); + rotate_m4(sizemat, 'X', (float)(M_PI / 2)); + mul_m4_m4m4(spotblendmat, shapemat, sizemat); + + if (la->mode & LA_SQUARE) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_spot_pyramid, color, &one, shapemat); + + /* hide line if it is zero size or overlaps with outer border, + * previously it adjusted to always to show it but that seems + * confusing because it doesn't show the actual blend size */ + if (blend != 0.0f && blend != 1.0f) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_spot_blend_rect, color, &one, spotblendmat); + } + } + else { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_spot_cone, color, shapemat); + + /* hide line if it is zero size or overlaps with outer border, + * previously it adjusted to always to show it but that seems + * confusing because it doesn't show the actual blend size */ + if (blend != 0.0f && blend != 1.0f) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_spot_blend, color, &one, spotblendmat); + } + } + + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_buflimit, color, &la->clipsta, &la->clipend, ob->obmat); + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat); + } + else if (la->type == LA_HEMI) { + static float hemisize = 2.0f; + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_hemi, color, &hemisize, shapemat); + } + else if (la->type == LA_AREA) { + float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4]; + + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { + size[1] = la->area_sizey / la->area_size; + size_to_mat4(sizemat, size); + mul_m4_m4m4(shapemat, shapemat, sizemat); + } + + if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_area_disk, color, &la->area_size, shapemat); + } + else { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_area_square, color, &la->area_size, shapemat); + } + } + + /* Line and point going to the ground */ + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_groundline, ob->obmat[3]); + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_groundpoint, ob->obmat[3]); +} + +static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + Scene *scene = draw_ctx->scene; + RegionView3D *rv3d = draw_ctx->rv3d; + + Camera *cam = ob->data; + const Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera); + const bool is_active = (ob == camera_object); + const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB)); + float *color; + DRW_object_wire_theme_get(ob, view_layer, &color); + + float vec[4][3], asp[2], shift[2], scale[3], drawsize; + + scale[0] = 1.0f / len_v3(ob->obmat[0]); + scale[1] = 1.0f / len_v3(ob->obmat[1]); + scale[2] = 1.0f / len_v3(ob->obmat[2]); + + BKE_camera_view_frame_ex(scene, cam, cam->drawsize, false, scale, + asp, shift, &drawsize, vec); + + /* Frame coords */ + copy_v2_v2(cam->drwcorners[0], vec[0]); + copy_v2_v2(cam->drwcorners[1], vec[1]); + copy_v2_v2(cam->drwcorners[2], vec[2]); + copy_v2_v2(cam->drwcorners[3], vec[3]); + + /* depth */ + cam->drwdepth = vec[0][2]; + + /* tria */ + cam->drwtria[0][0] = shift[0] + ((0.7f * drawsize) * scale[0]); + cam->drwtria[0][1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]); + cam->drwtria[1][0] = shift[0]; + cam->drwtria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); + + if (look_through) { + /* Only draw the frame. */ + DRW_shgroup_call_dynamic_add( + stl->g_data->camera_frame, color, cam->drwcorners, + &cam->drwdepth, cam->drwtria, ob->obmat); + } + else { + DRW_shgroup_call_dynamic_add( + stl->g_data->camera, color, cam->drwcorners, + &cam->drwdepth, cam->drwtria, ob->obmat); + + /* Active cam */ + if (is_active) { + DRW_shgroup_call_dynamic_add( + stl->g_data->camera_tria, color, + cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat); + } + } + + /* draw the rest in normalize object space */ + copy_m4_m4(cam->drwnormalmat, ob->obmat); + normalize_m4(cam->drwnormalmat); + + if (cam->flag & CAM_SHOWLIMITS) { + static float col[3] = {0.5f, 0.5f, 0.25f}, col_hi[3] = {1.0f, 1.0f, 0.5f}; + float sizemat[4][4], size[3] = {1.0f, 1.0f, 0.0f}; + float focusdist = BKE_camera_object_dof_distance(ob); + + copy_m4_m4(cam->drwfocusmat, cam->drwnormalmat); + translate_m4(cam->drwfocusmat, 0.0f, 0.0f, -focusdist); + size_to_mat4(sizemat, size); + mul_m4_m4m4(cam->drwfocusmat, cam->drwfocusmat, sizemat); + + DRW_shgroup_call_dynamic_add( + stl->g_data->camera_focus, (is_active ? col_hi : col), + &cam->drawsize, cam->drwfocusmat); + + DRW_shgroup_call_dynamic_add( + stl->g_data->camera_clip, color, + &cam->clipsta, &cam->clipend, cam->drwnormalmat); + DRW_shgroup_call_dynamic_add( + stl->g_data->camera_clip_points, (is_active ? col_hi : col), + &cam->clipsta, &cam->clipend, cam->drwnormalmat); + } + + if (cam->flag & CAM_SHOWMIST) { + World *world = scene->world; + + if (world) { + static float col[3] = {0.5f, 0.5f, 0.5f}, col_hi[3] = {1.0f, 1.0f, 1.0f}; + world->mistend = world->miststa + world->mistdist; + DRW_shgroup_call_dynamic_add( + stl->g_data->camera_mist, color, + &world->miststa, &world->mistend, cam->drwnormalmat); + DRW_shgroup_call_dynamic_add( + stl->g_data->camera_mist_points, (is_active ? col_hi : col), + &world->miststa, &world->mistend, cam->drwnormalmat); + } + } +} + +static void DRW_shgroup_empty(OBJECT_StorageList *stl, OBJECT_PassList *psl, Object *ob, ViewLayer *view_layer) +{ + float *color; + DRW_object_wire_theme_get(ob, view_layer, &color); + + switch (ob->empty_drawtype) { + case OB_PLAINAXES: + DRW_shgroup_call_dynamic_add(stl->g_data->plain_axes, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_SINGLE_ARROW: + DRW_shgroup_call_dynamic_add(stl->g_data->single_arrow, color, &ob->empty_drawsize, ob->obmat); + DRW_shgroup_call_dynamic_add(stl->g_data->single_arrow_line, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_CUBE: + DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_CIRCLE: + DRW_shgroup_call_dynamic_add(stl->g_data->circle, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_EMPTY_SPHERE: + DRW_shgroup_call_dynamic_add(stl->g_data->sphere, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_EMPTY_CONE: + DRW_shgroup_call_dynamic_add(stl->g_data->cone, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_ARROWS: + DRW_shgroup_call_dynamic_add(stl->g_data->arrows, color, &ob->empty_drawsize, ob->obmat); + DRW_shgroup_call_dynamic_add(stl->g_data->axis_names, color, &ob->empty_drawsize, ob->obmat); + break; + case OB_EMPTY_IMAGE: + DRW_shgroup_empty_image(stl, psl, ob, color); + break; + } +} + +static void DRW_shgroup_forcefield(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer) +{ + int theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + float *color = DRW_color_background_blend_get(theme_id); + PartDeflect *pd = ob->pd; + Curve *cu = (ob->type == OB_CURVE) ? ob->data : NULL; + + /* TODO Move this to depsgraph */ + float tmp[3]; + copy_v3_fl(pd->drawvec1, ob->empty_drawsize); + + switch (pd->forcefield) { + case PFIELD_WIND: + pd->drawvec1[2] = pd->f_strength; + break; + case PFIELD_VORTEX: + if (pd->f_strength < 0.0f) { + pd->drawvec1[1] = -pd->drawvec1[1]; + } + break; + case PFIELD_GUIDE: + if (cu && (cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) { + where_on_path(ob, 0.0f, pd->drawvec1, tmp, NULL, NULL, NULL); + where_on_path(ob, 1.0f, pd->drawvec2, tmp, NULL, NULL, NULL); + } + break; + } + + if (pd->falloff == PFIELD_FALL_TUBE) { + pd->drawvec_falloff_max[0] = pd->drawvec_falloff_max[1] = (pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f; + pd->drawvec_falloff_max[2] = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f; + + pd->drawvec_falloff_min[0] = pd->drawvec_falloff_min[1] = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f; + pd->drawvec_falloff_min[2] = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; + } + else if (pd->falloff == PFIELD_FALL_CONE) { + float radius, distance; + + radius = DEG2RADF((pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f); + distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f; + pd->drawvec_falloff_max[0] = pd->drawvec_falloff_max[1] = distance * sinf(radius); + pd->drawvec_falloff_max[2] = distance * cosf(radius); + + radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f); + distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; + + pd->drawvec_falloff_min[0] = pd->drawvec_falloff_min[1] = distance * sinf(radius); + pd->drawvec_falloff_min[2] = distance * cosf(radius); + } + /* End of things that should go to depthgraph */ + + switch (pd->forcefield) { + case PFIELD_WIND: + DRW_shgroup_call_dynamic_add(stl->g_data->field_wind, color, &pd->drawvec1, ob->obmat); + break; + case PFIELD_FORCE: + DRW_shgroup_call_dynamic_add(stl->g_data->field_force, color, &pd->drawvec1, ob->obmat); + break; + case PFIELD_VORTEX: + DRW_shgroup_call_dynamic_add(stl->g_data->field_vortex, color, &pd->drawvec1, ob->obmat); + break; + case PFIELD_GUIDE: + if (cu && (cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) { + DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_sta, color, &pd->f_strength, ob->obmat); + DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_end, color, &pd->f_strength, ob->obmat); + } + break; + } + + if (pd->falloff == PFIELD_FALL_SPHERE) { + /* as last, guide curve alters it */ + if ((pd->flag & PFIELD_USEMAX) != 0) { + DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_end, color, &pd->maxdist, ob->obmat); + } + + if ((pd->flag & PFIELD_USEMIN) != 0) { + DRW_shgroup_call_dynamic_add(stl->g_data->field_curve_end, color, &pd->mindist, ob->obmat); + } + } + else if (pd->falloff == PFIELD_FALL_TUBE) { + if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { + DRW_shgroup_call_dynamic_add(stl->g_data->field_tube_limit, color, &pd->drawvec_falloff_max, ob->obmat); + } + + if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { + DRW_shgroup_call_dynamic_add(stl->g_data->field_tube_limit, color, &pd->drawvec_falloff_min, ob->obmat); + } + } + else if (pd->falloff == PFIELD_FALL_CONE) { + if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { + DRW_shgroup_call_dynamic_add(stl->g_data->field_cone_limit, color, &pd->drawvec_falloff_max, ob->obmat); + } + + if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { + DRW_shgroup_call_dynamic_add(stl->g_data->field_cone_limit, color, &pd->drawvec_falloff_min, ob->obmat); + } + } +} + +static void DRW_shgroup_speaker(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer) +{ + float *color; + static float one = 1.0f; + DRW_object_wire_theme_get(ob, view_layer, &color); + + DRW_shgroup_call_dynamic_add(stl->g_data->speaker, color, &one, ob->obmat); +} + +typedef struct OBJECT_LightProbeEngineData { + ObjectEngineData engine_data; + + float prb_mats[6][4][4]; + float probe_cube_mat[4][4]; + float draw_size; + float increment_x[3]; + float increment_y[3]; + float increment_z[3]; + float corner[3]; + uint cell_count; +} OBJECT_LightProbeEngineData; + +static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl, Object *ob, ViewLayer *view_layer) +{ + float *color; + static float one = 1.0f; + LightProbe *prb = (LightProbe *)ob->data; + bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0); + int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color); + + OBJECT_LightProbeEngineData *prb_data = + (OBJECT_LightProbeEngineData *)DRW_object_engine_data_ensure( + ob, + &draw_engine_object_type, + sizeof(OBJECT_LightProbeEngineData), + NULL, + NULL); + + if ((DRW_state_is_select() || do_outlines) && ((prb->flag & LIGHTPROBE_FLAG_SHOW_DATA) != 0)) { + int *call_id = shgroup_theme_id_to_probe_outline_counter(stl, theme_id); + + if (prb->type == LIGHTPROBE_TYPE_GRID) { + /* Update transforms */ + float cell_dim[3], half_cell_dim[3]; + cell_dim[0] = 2.0f / (float)(prb->grid_resolution_x); + cell_dim[1] = 2.0f / (float)(prb->grid_resolution_y); + cell_dim[2] = 2.0f / (float)(prb->grid_resolution_z); + + mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f); + + /* First cell. */ + copy_v3_fl(prb_data->corner, -1.0f); + add_v3_v3(prb_data->corner, half_cell_dim); + mul_m4_v3(ob->obmat, prb_data->corner); + + /* Opposite neighbor cell. */ + copy_v3_fl3(prb_data->increment_x, cell_dim[0], 0.0f, 0.0f); + add_v3_v3(prb_data->increment_x, half_cell_dim); + add_v3_fl(prb_data->increment_x, -1.0f); + mul_m4_v3(ob->obmat, prb_data->increment_x); + sub_v3_v3(prb_data->increment_x, prb_data->corner); + + copy_v3_fl3(prb_data->increment_y, 0.0f, cell_dim[1], 0.0f); + add_v3_v3(prb_data->increment_y, half_cell_dim); + add_v3_fl(prb_data->increment_y, -1.0f); + mul_m4_v3(ob->obmat, prb_data->increment_y); + sub_v3_v3(prb_data->increment_y, prb_data->corner); + + copy_v3_fl3(prb_data->increment_z, 0.0f, 0.0f, cell_dim[2]); + add_v3_v3(prb_data->increment_z, half_cell_dim); + add_v3_fl(prb_data->increment_z, -1.0f); + mul_m4_v3(ob->obmat, prb_data->increment_z); + sub_v3_v3(prb_data->increment_z, prb_data->corner); + + prb_data->cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z; + DRWShadingGroup *grp = DRW_shgroup_create(e_data.lightprobe_grid_sh, psl->lightprobes); + DRW_shgroup_uniform_int_copy(grp, "call_id", *call_id); + DRW_shgroup_uniform_int(grp, "baseId", call_id, 1); /* that's correct */ + DRW_shgroup_uniform_vec3(grp, "corner", prb_data->corner, 1); + DRW_shgroup_uniform_vec3(grp, "increment_x", prb_data->increment_x, 1); + DRW_shgroup_uniform_vec3(grp, "increment_y", prb_data->increment_y, 1); + DRW_shgroup_uniform_vec3(grp, "increment_z", prb_data->increment_z, 1); + DRW_shgroup_uniform_ivec3(grp, "grid_resolution", &prb->grid_resolution_x, 1); + DRW_shgroup_uniform_float(grp, "sphere_size", &prb->data_draw_size, 1); + DRW_shgroup_call_instances_add(grp, DRW_cache_sphere_get(), NULL, &prb_data->cell_count); + } + else if (prb->type == LIGHTPROBE_TYPE_CUBE) { + prb_data->draw_size = prb->data_draw_size * 0.1f; + unit_m4(prb_data->probe_cube_mat); + copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]); + + DRWShadingGroup *grp = shgroup_theme_id_to_probe_cube_outline_shgrp(stl, theme_id); + DRW_shgroup_call_dynamic_add(grp, call_id, &prb_data->draw_size, prb_data->probe_cube_mat); + } + else { + prb_data->draw_size = 1.0f; + + DRWShadingGroup *grp = shgroup_theme_id_to_probe_planar_outline_shgrp(stl, theme_id); + DRW_shgroup_call_dynamic_add(grp, call_id, &prb_data->draw_size, ob->obmat); + } + + *call_id += 1; + } + + switch (prb->type) { + case LIGHTPROBE_TYPE_PLANAR: + DRW_shgroup_call_dynamic_add(stl->g_data->probe_planar, ob->obmat[3], color); + break; + case LIGHTPROBE_TYPE_GRID: + DRW_shgroup_call_dynamic_add(stl->g_data->probe_grid, ob->obmat[3], color); + break; + case LIGHTPROBE_TYPE_CUBE: + default: + DRW_shgroup_call_dynamic_add(stl->g_data->probe_cube, ob->obmat[3], color); + break; + } + + + + if (prb->type == LIGHTPROBE_TYPE_PLANAR) { + float (*mat)[4]; + mat = (float (*)[4])(prb_data->prb_mats[0]); + copy_m4_m4(mat, ob->obmat); + normalize_m4(mat); + + DRW_shgroup_call_dynamic_add(stl->g_data->single_arrow, color, &ob->empty_drawsize, mat); + DRW_shgroup_call_dynamic_add(stl->g_data->single_arrow_line, color, &ob->empty_drawsize, mat); + + mat = (float (*)[4])(prb_data->prb_mats[1]); + copy_m4_m4(mat, ob->obmat); + zero_v3(mat[2]); + + DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &one, mat); + } + + if ((prb->flag & LIGHTPROBE_FLAG_SHOW_INFLUENCE) != 0) { + + prb->distfalloff = (1.0f - prb->falloff) * prb->distinf; + prb->distgridinf = prb->distinf; + + if (prb->type == LIGHTPROBE_TYPE_GRID) { + prb->distfalloff += 1.0f; + prb->distgridinf += 1.0f; + } + + if (prb->type == LIGHTPROBE_TYPE_GRID || + prb->attenuation_type == LIGHTPROBE_SHAPE_BOX) + { + DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &prb->distgridinf, ob->obmat); + DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &prb->distfalloff, ob->obmat); + } + else if (prb->type == LIGHTPROBE_TYPE_PLANAR) { + float (*rangemat)[4]; + rangemat = (float (*)[4])(prb_data->prb_mats[2]); + copy_m4_m4(rangemat, ob->obmat); + normalize_v3(rangemat[2]); + mul_v3_fl(rangemat[2], prb->distinf); + + DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &one, rangemat); + + rangemat = (float (*)[4])(prb_data->prb_mats[3]); + copy_m4_m4(rangemat, ob->obmat); + normalize_v3(rangemat[2]); + mul_v3_fl(rangemat[2], prb->distfalloff); + + DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, &one, rangemat); + } + else { + DRW_shgroup_call_dynamic_add(stl->g_data->sphere, color, &prb->distgridinf, ob->obmat); + DRW_shgroup_call_dynamic_add(stl->g_data->sphere, color, &prb->distfalloff, ob->obmat); + } + } + + if ((prb->flag & LIGHTPROBE_FLAG_SHOW_PARALLAX) != 0) { + if (prb->type != LIGHTPROBE_TYPE_PLANAR) { + float (*obmat)[4], *dist; + + if ((prb->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) != 0) { + dist = &prb->distpar; + /* TODO object parallax */ + obmat = ob->obmat; + } + else { + dist = &prb->distinf; + obmat = ob->obmat; + } + + if (prb->parallax_type == LIGHTPROBE_SHAPE_BOX) { + DRW_shgroup_call_dynamic_add(stl->g_data->cube, color, dist, obmat); + } + else { + DRW_shgroup_call_dynamic_add(stl->g_data->sphere, color, dist, obmat); + } + } + } + + if ((prb->flag & LIGHTPROBE_FLAG_SHOW_CLIP_DIST) != 0) { + if (prb->type != LIGHTPROBE_TYPE_PLANAR) { + static const float cubefacemat[6][4][4] = { + {{0.0, 0.0, -1.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, + {{0.0, 0.0, 1.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, + {{1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, -1.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, + {{1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, + {{1.0, 0.0, 0.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {0.0, 0.0, -1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, + {{-1.0, 0.0, 0.0, 0.0}, {0.0, -1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}}, + }; + + for (int i = 0; i < 6; ++i) { + float (*clipmat)[4]; + clipmat = (float (*)[4])(prb_data->prb_mats[i]); + + normalize_m4_m4(clipmat, ob->obmat); + mul_m4_m4m4(clipmat, clipmat, cubefacemat[i]); + + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_buflimit, color, &prb->clipsta, &prb->clipend, clipmat); + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_buflimit_points, color, &prb->clipsta, &prb->clipend, clipmat); + } + } + } + + /* Line and point going to the ground */ + if (prb->type == LIGHTPROBE_TYPE_CUBE) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_groundline, ob->obmat[3]); + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_groundpoint, ob->obmat[3]); + } +} + +static void DRW_shgroup_relationship_lines(OBJECT_StorageList *stl, Object *ob) +{ + if (ob->parent && DRW_check_object_visible_within_active_context(ob->parent)) { + DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->parent->obmat[3]); + DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->obmat[3]); + } +} + +static void DRW_shgroup_object_center(OBJECT_StorageList *stl, Object *ob, ViewLayer *view_layer, View3D *v3d) +{ + const bool is_library = ob->id.us > 1 || ID_IS_LINKED(ob); + DRWShadingGroup *shgroup; + + if (ob == OBACT(view_layer)) { + shgroup = stl->g_data->center_active; + } + else if (ob->base_flag & BASE_SELECTED) { + if (is_library) { + shgroup = stl->g_data->center_selected_lib; + } + else { + shgroup = stl->g_data->center_selected; + } + } + else if (v3d->flag & V3D_DRAW_CENTERS) { + if (is_library) { + shgroup = stl->g_data->center_deselected_lib; + } + else { + shgroup = stl->g_data->center_deselected; + } + } + else { + return; + } + + DRW_shgroup_call_dynamic_add(shgroup, ob->obmat[3]); +} + +static void DRW_shgroup_texture_space(OBJECT_StorageList *stl, Object *ob, int theme_id) +{ + if (ob->data == NULL) { + return; + } + + ID *ob_data = ob->data; + float *texcoloc = NULL; + float *texcosize = NULL; + if (ob->data != NULL) { + switch (GS(ob_data->name)) { + case ID_ME: + BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize); + break; + case ID_CU: + { + Curve *cu = (Curve *)ob_data; + if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) { + BKE_curve_texspace_calc(cu); + } + texcoloc = cu->loc; + texcosize = cu->size; + break; + } + case ID_MB: + { + MetaBall *mb = (MetaBall *)ob_data; + texcoloc = mb->loc; + texcosize = mb->size; + break; + } + default: + BLI_assert(0); + } + } + + float tmp[4][4] = {{0.0f}}, one = 1.0f; + tmp[0][0] = texcosize[0]; + tmp[1][1] = texcosize[1]; + tmp[2][2] = texcosize[2]; + tmp[3][0] = texcoloc[0]; + tmp[3][1] = texcoloc[1]; + tmp[3][2] = texcoloc[2]; + tmp[3][3] = 1.0f; + + mul_m4_m4m4(tmp, ob->obmat, tmp); + + float color[4]; + UI_GetThemeColor4fv(theme_id, color); + + DRW_shgroup_call_dynamic_add(stl->g_data->texspace, color, &one, tmp); +} + +static void OBJECT_cache_populate_particles(Object *ob, + OBJECT_PassList *psl) +{ + for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { + if (!psys_check_enabled(ob, psys, false)) { + continue; + } + if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + return; + } + + ParticleSettings *part = psys->part; + int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + + if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) { + draw_as = PART_DRAW_DOT; + } + + static float mat[4][4]; + unit_m4(mat); + + if (draw_as != PART_DRAW_PATH) { + struct Gwn_Batch *geom = DRW_cache_particles_get_dots(ob, psys); + DRWShadingGroup *shgrp = NULL; + static int screen_space[2] = {0, 1}; + static float def_prim_col[3] = {0.5f, 0.5f, 0.5f}; + static float def_sec_col[3] = {1.0f, 1.0f, 1.0f}; + + /* Dummy particle format for instancing to work. */ + DRW_shgroup_instance_format(e_data.particle_format, {{"dummy", DRW_ATTRIB_FLOAT, 1}}); + + Material *ma = give_current_material(ob, part->omat); + + switch (draw_as) { + case PART_DRAW_DOT: + shgrp = DRW_shgroup_create(e_data.part_dot_sh, psl->particle); + DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); + DRW_shgroup_uniform_vec3(shgrp, "outlineColor", ma ? &ma->specr : def_sec_col, 1); + DRW_shgroup_uniform_float(shgrp, "pixel_size", DRW_viewport_pixelsize_get(), 1); + DRW_shgroup_uniform_float(shgrp, "size", &part->draw_size, 1); + DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp); + DRW_shgroup_call_add(shgrp, geom, mat); + break; + case PART_DRAW_CROSS: + shgrp = DRW_shgroup_instance_create( + e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CROSS), + e_data.particle_format); + DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp); + DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); + DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); + break; + case PART_DRAW_CIRC: + shgrp = DRW_shgroup_instance_create( + e_data.part_prim_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_CIRC), + e_data.particle_format); + DRW_shgroup_uniform_texture(shgrp, "ramp", globals_ramp); + DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); + DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[1], 1); + break; + case PART_DRAW_AXIS: + shgrp = DRW_shgroup_instance_create( + e_data.part_axis_sh, psl->particle, DRW_cache_particles_get_prim(PART_DRAW_AXIS), + e_data.particle_format); + DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); + break; + default: + break; + } + + if (shgrp) { + if (draw_as != PART_DRAW_DOT) { + DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1); + DRW_shgroup_instance_batch(shgrp, geom); + } + } + } + } +} + +static void OBJECT_cache_populate(void *vedata, Object *ob) +{ + OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; + OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + View3D *v3d = draw_ctx->v3d; + int theme_id = TH_UNDEFINED; + + /* Handle particles first in case the emitter itself shouldn't be rendered. */ + if (ob->type == OB_MESH) { + OBJECT_cache_populate_particles(ob, psl); + } + + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + + bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0); + + if (do_outlines) { + if ((ob != draw_ctx->object_edit) && !((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) { + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_or(stl, theme_id, NULL); + if (shgroup != NULL) { + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + } + } + } + + switch (ob->type) { + case OB_MESH: + { + if (ob != draw_ctx->object_edit) { + Mesh *me = ob->data; + if (me->totpoly == 0) { + if (me->totedge == 0) { + struct Gwn_Batch *geom = DRW_cache_mesh_verts_get(ob); + if (geom) { + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + + DRWShadingGroup *shgroup = shgroup_theme_id_to_point_or(stl, theme_id, stl->g_data->points); + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + } + else { + struct Gwn_Batch *geom = DRW_cache_mesh_edges_get(ob); + if (geom) { + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + + DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire); + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + } + } + } + break; + } + case OB_SURF: + break; + case OB_LATTICE: + { + if (ob != draw_ctx->object_edit) { + struct Gwn_Batch *geom = DRW_cache_lattice_wire_get(ob, false); + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + + DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire); + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + break; + } + + case OB_CURVE: + { + if (ob != draw_ctx->object_edit) { + struct Gwn_Batch *geom = DRW_cache_curve_edge_wire_get(ob); + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + DRWShadingGroup *shgroup = shgroup_theme_id_to_wire_or(stl, theme_id, stl->g_data->wire); + DRW_shgroup_call_object_add(shgroup, geom, ob); + } + break; + } + case OB_MBALL: + { + if (ob != draw_ctx->object_edit) { + DRW_shgroup_mball_handles(stl, ob, view_layer); + } + break; + } + case OB_LAMP: + DRW_shgroup_lamp(stl, ob, view_layer); + break; + case OB_CAMERA: + DRW_shgroup_camera(stl, ob, view_layer); + break; + case OB_EMPTY: + DRW_shgroup_empty(stl, psl, ob, view_layer); + break; + case OB_SPEAKER: + DRW_shgroup_speaker(stl, ob, view_layer); + break; + case OB_LIGHTPROBE: + DRW_shgroup_lightprobe(stl, psl, ob, view_layer); + break; + case OB_ARMATURE: + { + bArmature *arm = ob->data; + if (arm->edbo == NULL) { + if (DRW_state_is_select() || !DRW_pose_mode_armature(ob, draw_ctx->obact)) { + DRWArmaturePasses passes = { + .bone_solid = psl->bone_solid, + .bone_outline = psl->bone_outline, + .bone_wire = psl->bone_wire, + .bone_envelope = psl->bone_envelope, + .bone_axes = psl->bone_axes, + .relationship_lines = NULL, /* Don't draw relationship lines */ + }; + DRW_shgroup_armature_object(ob, view_layer, passes); + } + } + break; + } + default: + break; + } + + if (ob->pd && ob->pd->forcefield) { + DRW_shgroup_forcefield(stl, ob, view_layer); + } + + /* don't show object extras in set's */ + if ((ob->base_flag & (BASE_FROM_SET | BASE_FROMDUPLI)) == 0) { + + DRW_shgroup_object_center(stl, ob, view_layer, v3d); + + DRW_shgroup_relationship_lines(stl, ob); + + if ((ob->dtx != 0) && theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + + if ((ob->dtx & OB_DRAWNAME) && DRW_state_show_text()) { + struct DRWTextStore *dt = DRW_text_cache_ensure(); + + unsigned char color[4]; + UI_GetThemeColor4ubv(theme_id, color); + + DRW_text_cache_add( + dt, ob->obmat[3], + ob->id.name + 2, strlen(ob->id.name + 2), + 10, DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR, color); + } + + if ((ob->dtx & OB_TEXSPACE) && ELEM(ob->type, OB_MESH, OB_CURVE, OB_MBALL)) { + DRW_shgroup_texture_space(stl, ob, theme_id); + } + } +} + +static void OBJECT_draw_scene(void *vedata) +{ + + OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; + OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl; + OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl; + OBJECT_PrivateData *g_data = stl->g_data; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + int id_ct_select = g_data->id_ofs_select; + int id_ct_active = g_data->id_ofs_active; + int id_ct_transform = g_data->id_ofs_transform; + + int id_ct_prb_select = g_data->id_ofs_prb_select; + int id_ct_prb_active = g_data->id_ofs_prb_active; + int id_ct_prb_transform = g_data->id_ofs_prb_transform; + + int outline_calls = id_ct_select + id_ct_active + id_ct_transform; + outline_calls += id_ct_prb_select + id_ct_prb_active + id_ct_prb_transform; + + float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + +// DRW_draw_pass(psl->bone_envelope); /* Never drawn in Object mode currently. */ + + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl) + + /* This needs to be drawn after the oultine */ + DRW_draw_pass(psl->bone_solid); + DRW_draw_pass(psl->bone_wire); + DRW_draw_pass(psl->bone_outline); + DRW_draw_pass(psl->non_meshes); + DRW_draw_pass(psl->particle); + DRW_draw_pass(psl->reference_image); + DRW_draw_pass(psl->bone_axes); + + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl) + + if (DRW_state_is_fbo() && outline_calls > 0) { + DRW_stats_group_start("Outlines"); + + g_data->id_ofs_active = 1; + g_data->id_ofs_select = g_data->id_ofs_active + id_ct_active + id_ct_prb_active + 1; + g_data->id_ofs_transform = g_data->id_ofs_select + id_ct_select + id_ct_prb_select + 1; + + g_data->id_ofs_prb_active = g_data->id_ofs_active + id_ct_active; + g_data->id_ofs_prb_select = g_data->id_ofs_select + id_ct_select; + g_data->id_ofs_prb_transform = g_data->id_ofs_transform + id_ct_transform; + + /* Render filled polygon on a separate framebuffer */ + GPU_framebuffer_bind(fbl->outlines_fb); + GPU_framebuffer_clear_color_depth(fbl->outlines_fb, clearcol, 1.0f); + DRW_draw_pass(psl->outlines); + DRW_draw_pass(psl->lightprobes); + + /* Search outline pixels */ + GPU_framebuffer_bind(fbl->blur_fb); + DRW_draw_pass(psl->outlines_search); + + /* Expand outline to form a 3px wide line */ + GPU_framebuffer_bind(fbl->expand_fb); + DRW_draw_pass(psl->outlines_expand); + + /* Bleed color so the AA can do it's stuff */ + GPU_framebuffer_bind(fbl->blur_fb); + DRW_draw_pass(psl->outlines_bleed); + + /* restore main framebuffer */ + GPU_framebuffer_bind(dfbl->default_fb); + DRW_stats_group_end(); + } + else if (DRW_state_is_select()) { + /* Render probes spheres/planes so we can select them. */ + DRW_draw_pass(psl->lightprobes); + } + + DRW_draw_pass(psl->ob_center); + + if (DRW_state_is_fbo()) { + if (e_data.draw_grid) { + GPU_framebuffer_bind(dfbl->color_only_fb); + DRW_draw_pass(psl->grid); + } + + /* Combine with scene buffer last */ + if (outline_calls > 0) { + DRW_draw_pass(psl->outlines_resolve); + } + } + + /* This has to be freed only after drawing empties! */ + if (stl->g_data->image_plane_map) { + BLI_ghash_free(stl->g_data->image_plane_map, NULL, MEM_freeN); + stl->g_data->image_plane_map = NULL; + } +} + +static const DrawEngineDataSize OBJECT_data_size = DRW_VIEWPORT_DATA_SIZE(OBJECT_Data); + +DrawEngineType draw_engine_object_type = { + NULL, NULL, + N_("ObjectMode"), + &OBJECT_data_size, + &OBJECT_engine_init, + &OBJECT_engine_free, + &OBJECT_cache_init, + &OBJECT_cache_populate, + NULL, + NULL, + &OBJECT_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c new file mode 100644 index 00000000000..c4b64e03c48 --- /dev/null +++ b/source/blender/draw/modes/overlay_mode.c @@ -0,0 +1,165 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file overlay_mode.c + * \ingroup draw_engine + */ + +#include "DNA_view3d_types.h" + +#include "GPU_shader.h" +#include "DRW_render.h" + +#include "draw_mode_engines.h" + +/* Structures */ +typedef struct OVERLAY_StorageList { + struct OVERLAY_PrivateData *g_data; +} OVERLAY_StorageList; + +typedef struct OVERLAY_PassList { + struct DRWPass *face_orientation_pass; +} OVERLAY_PassList; + +typedef struct OVERLAY_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + OVERLAY_PassList *psl; + OVERLAY_StorageList *stl; +} OVERLAY_Data; + +typedef struct OVERLAY_PrivateData { + DRWShadingGroup *face_orientation_shgrp; + View3DOverlay overlay; +} OVERLAY_PrivateData; /* Transient data */ + +/* *********** STATIC *********** */ +static struct { + /* Face orientation shader */ + struct GPUShader *face_orientation_sh; +} e_data = {NULL}; + +/* Shaders */ +extern char datatoc_overlay_face_orientation_frag_glsl[]; +extern char datatoc_overlay_face_orientation_vert_glsl[]; + + +/* Functions */ +static void overlay_engine_init(void *vedata) +{ + OVERLAY_Data * data = (OVERLAY_Data *)vedata; + OVERLAY_StorageList *stl = data->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + if (!e_data.face_orientation_sh) { + /* Face orientation */ + e_data.face_orientation_sh = DRW_shader_create( + datatoc_overlay_face_orientation_vert_glsl, NULL, datatoc_overlay_face_orientation_frag_glsl, "\n"); + } +} + +static void overlay_cache_init(void *vedata) +{ + OVERLAY_Data * data = (OVERLAY_Data *)vedata; + OVERLAY_PassList *psl = data->psl; + OVERLAY_StorageList *stl = data->stl; + + const DRWContextState *DCS = DRW_context_state_get(); + + View3D *v3d = DCS->v3d; + if (v3d) { + stl->g_data->overlay = v3d->overlay; + } + else { + memset(&stl->g_data->overlay, 0, sizeof(stl->g_data->overlay)); + } + + /* Face Orientation Pass */ + if (stl->g_data->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; + psl->face_orientation_pass = DRW_pass_create("Face Orientation", state); + stl->g_data->face_orientation_shgrp = DRW_shgroup_create( + e_data.face_orientation_sh, psl->face_orientation_pass); + } +} + +static void overlay_cache_populate(void *vedata, Object *ob) +{ + OVERLAY_Data * data = (OVERLAY_Data *)vedata; + OVERLAY_StorageList *stl = data->stl; + OVERLAY_PrivateData *pd = stl->g_data; + + if (!DRW_object_is_renderable(ob)) + return; + + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + /* Face Orientation */ + if (stl->g_data->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) { + DRW_shgroup_call_add(pd->face_orientation_shgrp, geom, ob->obmat); + } + } +} + +static void overlay_cache_finish(void *UNUSED(vedata)) +{ +} + +static void overlay_draw_scene(void *vedata) +{ + OVERLAY_Data * data = (OVERLAY_Data *)vedata; + OVERLAY_PassList *psl = data->psl; + OVERLAY_StorageList *stl = data->stl; + OVERLAY_PrivateData *pd = stl->g_data; + + if (pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) { + DRW_draw_pass(psl->face_orientation_pass); + } +} + +static void overlay_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.face_orientation_sh); +} + +static const DrawEngineDataSize overlay_data_size = DRW_VIEWPORT_DATA_SIZE(OVERLAY_Data); + +DrawEngineType draw_engine_overlay_type = { + NULL, NULL, + N_("OverlayEngine"), + &overlay_data_size, + &overlay_engine_init, + &overlay_engine_free, + &overlay_cache_init, + &overlay_cache_populate, + &overlay_cache_finish, + NULL, + &overlay_draw_scene, + NULL, + NULL, + NULL, +}; + diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c new file mode 100644 index 00000000000..1d7f686a51c --- /dev/null +++ b/source/blender/draw/modes/paint_texture_mode.c @@ -0,0 +1,397 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/paint_texture_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "BIF_gl.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" +#include "GPU_texture.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +#include "DNA_mesh_types.h" + +extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_paint_texture_vert_glsl[]; +extern char datatoc_paint_texture_frag_glsl[]; +extern char datatoc_paint_wire_vert_glsl[]; +extern char datatoc_paint_wire_frag_glsl[]; + +/* If needed, contains all global/Theme colors + * Add needed theme colors / values to DRW_globals_update() and update UBO + * Not needed for constant color. */ +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ + +/* *********** LISTS *********** */ +/* All lists are per viewport specific datas. + * They are all free when viewport changes engines + * or is free itself. Use PAINT_TEXTURE_engine_init() to + * initialize most of them and PAINT_TEXTURE_cache_init() + * for PAINT_TEXTURE_PassList */ + +typedef struct PAINT_TEXTURE_PassList { + /* Declare all passes here and init them in + * PAINT_TEXTURE_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *image_faces; + + struct DRWPass *wire_overlay; + struct DRWPass *face_overlay; +} PAINT_TEXTURE_PassList; + +typedef struct PAINT_TEXTURE_FramebufferList { + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; +} PAINT_TEXTURE_FramebufferList; + +typedef struct PAINT_TEXTURE_TextureList { + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; +} PAINT_TEXTURE_TextureList; + +typedef struct PAINT_TEXTURE_StorageList { + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct PAINT_TEXTURE_PrivateData *g_data; +} PAINT_TEXTURE_StorageList; + +typedef struct PAINT_TEXTURE_Data { + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + PAINT_TEXTURE_FramebufferList *fbl; + PAINT_TEXTURE_TextureList *txl; + PAINT_TEXTURE_PassList *psl; + PAINT_TEXTURE_StorageList *stl; +} PAINT_TEXTURE_Data; + +/* *********** STATIC *********** */ + +static struct { + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in PAINT_TEXTURE_engine_init(); + * free in PAINT_TEXTURE_engine_free(); */ + struct GPUShader *fallback_sh; + struct GPUShader *image_sh; + + struct GPUShader *wire_overlay_shader; + struct GPUShader *face_overlay_shader; +} e_data = {NULL}; /* Engine data */ + +typedef struct PAINT_TEXTURE_PrivateData { + /* This keeps the references of the shading groups for + * easy access in PAINT_TEXTURE_cache_populate() */ + DRWShadingGroup *shgroup_fallback; + DRWShadingGroup **shgroup_image_array; + + /* face-mask */ + DRWShadingGroup *lwire_shgrp; + DRWShadingGroup *face_shgrp; +} PAINT_TEXTURE_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +/* Init Textures, Framebuffers, Storage and Shaders. + * It is called for every frames. + * (Optional) */ +static void PAINT_TEXTURE_engine_init(void *vedata) +{ + PAINT_TEXTURE_TextureList *txl = ((PAINT_TEXTURE_Data *)vedata)->txl; + PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl; + PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; + + UNUSED_VARS(txl, fbl, stl); + + /* Init Framebuffers like this: order is attachment order (for color texs) */ + /* + * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, + * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; + */ + + /* DRW_framebuffer_init takes care of checking if + * the framebuffer is valid and has the right size*/ + /* + * float *viewport_size = DRW_viewport_size_get(); + * DRW_framebuffer_init(&fbl->occlude_wire_fb, + * (int)viewport_size[0], (int)viewport_size[1], + * tex, 2); + */ + + if (!e_data.fallback_sh) { + e_data.fallback_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } + if (!e_data.image_sh) { + e_data.image_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + + e_data.image_sh = DRW_shader_create_with_lib( + datatoc_paint_texture_vert_glsl, NULL, + datatoc_paint_texture_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + + } + + if (!e_data.wire_overlay_shader) { + e_data.wire_overlay_shader = DRW_shader_create_with_lib( + datatoc_paint_wire_vert_glsl, NULL, + datatoc_paint_wire_frag_glsl, + datatoc_common_globals_lib_glsl, + "#define VERTEX_MODE\n"); + } + + if (!e_data.face_overlay_shader) { + e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } +} + +/* Here init all passes and shading groups + * Assume that all Passes are NULL */ +static void PAINT_TEXTURE_cache_init(void *vedata) +{ + PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; + PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + stl->g_data->shgroup_image_array = NULL; + } + + { + /* Create a pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_MULTIPLY | DRW_STATE_WIRE; + psl->image_faces = DRW_pass_create("Image Color Pass", state); + + stl->g_data->shgroup_fallback = DRW_shgroup_create(e_data.fallback_sh, psl->image_faces); + + /* Uniforms need a pointer to it's value so be sure it's accessible at + * any given time (i.e. use static vars) */ + static float color[4] = {1.0f, 0.0f, 1.0f, 1.0}; + DRW_shgroup_uniform_vec4(stl->g_data->shgroup_fallback, "color", color, 1); + + MEM_SAFE_FREE(stl->g_data->shgroup_image_array); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + Object *ob = draw_ctx->obact; + if (ob && ob->type == OB_MESH) { + Scene *scene = draw_ctx->scene; + const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL); + const Mesh *me = ob->data; + + stl->g_data->shgroup_image_array = MEM_mallocN( + sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? me->totcol : 1), __func__); + + if (use_material_slots) { + for (int i = 0; i < me->totcol; i++) { + Material *ma = give_current_material(ob, i + 1); + Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; + GPUTexture *tex = ima ? + GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false) : NULL; + + if (tex) { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces); + DRW_shgroup_uniform_texture(grp, "image", tex); + stl->g_data->shgroup_image_array[i] = grp; + } + else { + stl->g_data->shgroup_image_array[i] = NULL; + } + } + } + else { + Image *ima = scene->toolsettings->imapaint.canvas; + GPUTexture *tex = ima ? + GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, false, false) : NULL; + + if (tex) { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces); + DRW_shgroup_uniform_texture(grp, "image", tex); + stl->g_data->shgroup_image_array[0] = grp; + } + else { + stl->g_data->shgroup_image_array[0] = NULL; + } + } + } + } + + /* Face Mask */ + { + psl->wire_overlay = DRW_pass_create( + "Wire Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); + + stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay); + } + + { + psl->face_overlay = DRW_pass_create( + "Face Mask Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + + stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay); + + static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f}; + DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1); + } +} + +/* Add geometry to shadingGroups. Execute for each objects */ +static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob) +{ + PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; + PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + UNUSED_VARS(psl, stl); + + if ((ob->type == OB_MESH) && (draw_ctx->obact == ob)) { + /* Get geometry cache */ + const Mesh *me = ob->data; + Scene *scene = draw_ctx->scene; + const bool use_surface = DRW_object_is_mode_shade(ob) == true; + const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL); + bool ok = false; + + if (use_surface) { + if (me->mloopuv != NULL) { + if (use_material_slots) { + struct Gwn_Batch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL; + if ((me->totcol == 0) || (geom_array == NULL)) { + struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob); + DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat); + ok = true; + } + else { + for (int i = 0; i < me->totcol; i++) { + if (stl->g_data->shgroup_image_array[i]) { + DRW_shgroup_call_add(stl->g_data->shgroup_image_array[i], geom_array[i], ob->obmat); + } + else { + DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat); + } + ok = true; + } + } + } + else { + struct Gwn_Batch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob); + if (geom && stl->g_data->shgroup_image_array[0]) { + DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat); + ok = true; + } + } + } + + if (!ok) { + struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob); + DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat); + } + } + + /* Face Mask */ + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; + if (use_face_sel) { + struct Gwn_Batch *geom; + /* Note: ideally selected faces wouldn't show interior wire. */ + const bool use_wire = true; + geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel); + DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat); + + geom = DRW_cache_mesh_faces_weight_overlay_get(ob); + DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat); + } + } +} + +/* Optional: Post-cache_populate callback */ +static void PAINT_TEXTURE_cache_finish(void *vedata) +{ + PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; + PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; + + /* Do something here! dependant on the objects gathered */ + UNUSED_VARS(psl); + + MEM_SAFE_FREE(stl->g_data->shgroup_image_array); +} + +/* Draw time ! Control rendering pipeline from here */ +static void PAINT_TEXTURE_draw_scene(void *vedata) +{ + PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; + PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl; + + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + UNUSED_VARS(fbl, dfbl, dtxl); + + DRW_draw_pass(psl->image_faces); + + DRW_draw_pass(psl->face_overlay); + DRW_draw_pass(psl->wire_overlay); +} + +/* Cleanup when destroying the engine. + * This is not per viewport ! only when quitting blender. + * Mostly used for freeing shaders */ +static void PAINT_TEXTURE_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.image_sh); + DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader); +} + +static const DrawEngineDataSize PAINT_TEXTURE_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_TEXTURE_Data); + +DrawEngineType draw_engine_paint_texture_type = { + NULL, NULL, + N_("PaintTextureMode"), + &PAINT_TEXTURE_data_size, + &PAINT_TEXTURE_engine_init, + &PAINT_TEXTURE_engine_free, + &PAINT_TEXTURE_cache_init, + &PAINT_TEXTURE_cache_populate, + &PAINT_TEXTURE_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &PAINT_TEXTURE_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c new file mode 100644 index 00000000000..d335e0a4d70 --- /dev/null +++ b/source/blender/draw/modes/paint_vertex_mode.c @@ -0,0 +1,199 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/paint_vertex_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +#include "DNA_mesh_types.h" +#include "DNA_view3d_types.h" + +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ + +extern char datatoc_paint_vertex_vert_glsl[]; +extern char datatoc_paint_vertex_frag_glsl[]; +extern char datatoc_paint_wire_vert_glsl[]; +extern char datatoc_paint_wire_frag_glsl[]; +extern char datatoc_common_globals_lib_glsl[]; + +/* *********** LISTS *********** */ + +typedef struct PAINT_VERTEX_PassList { + struct DRWPass *vcolor_faces; + struct DRWPass *wire_overlay; + struct DRWPass *face_overlay; +} PAINT_VERTEX_PassList; + +typedef struct PAINT_VERTEX_StorageList { + struct PAINT_VERTEX_PrivateData *g_data; +} PAINT_VERTEX_StorageList; + +typedef struct PAINT_VERTEX_Data { + void *engine_type; /* Required */ + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + PAINT_VERTEX_PassList *psl; + PAINT_VERTEX_StorageList *stl; +} PAINT_VERTEX_Data; + +/* *********** STATIC *********** */ + +static struct { + struct GPUShader *vcolor_face_shader; + struct GPUShader *wire_overlay_shader; + struct GPUShader *face_overlay_shader; +} e_data = {NULL}; /* Engine data */ + +typedef struct PAINT_VERTEX_PrivateData { + DRWShadingGroup *fvcolor_shgrp; + DRWShadingGroup *lwire_shgrp; + DRWShadingGroup *face_shgrp; +} PAINT_VERTEX_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +static void PAINT_VERTEX_engine_init(void *UNUSED(vedata)) +{ + if (!e_data.vcolor_face_shader) { + e_data.vcolor_face_shader = DRW_shader_create( + datatoc_paint_vertex_vert_glsl, NULL, + datatoc_paint_vertex_frag_glsl, NULL); + + e_data.wire_overlay_shader = DRW_shader_create_with_lib( + datatoc_paint_wire_vert_glsl, NULL, + datatoc_paint_wire_frag_glsl, + datatoc_common_globals_lib_glsl, "#define VERTEX_MODE\n"); + + e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } +} + +static void PAINT_VERTEX_cache_init(void *vedata) +{ + PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl; + PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Create a pass */ + psl->vcolor_faces = DRW_pass_create( + "Vert Color Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_MULTIPLY); + + stl->g_data->fvcolor_shgrp = DRW_shgroup_create(e_data.vcolor_face_shader, psl->vcolor_faces); + } + + { + psl->wire_overlay = DRW_pass_create( + "Wire Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); + + stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay); + } + + { + psl->face_overlay = DRW_pass_create( + "Face Mask Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + + stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay); + + static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f}; + DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1); + } +} + +static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob) +{ + PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + + if ((ob->type == OB_MESH) && (ob == draw_ctx->obact)) { + const Mesh *me = ob->data; + const bool use_wire = (v3d->overlay.paint_flag & V3D_OVERLAY_PAINT_WIRE) != 0; + const bool use_surface = DRW_object_is_mode_shade(ob) == true; + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; + struct Gwn_Batch *geom; + + if (use_surface) { + geom = DRW_cache_mesh_surface_vert_colors_get(ob); + DRW_shgroup_call_add(stl->g_data->fvcolor_shgrp, geom, ob->obmat); + } + + if (use_face_sel || use_wire) { + geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel); + DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat); + } + + if (use_face_sel) { + geom = DRW_cache_mesh_faces_weight_overlay_get(ob); + DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat); + } + } +} + +static void PAINT_VERTEX_draw_scene(void *vedata) +{ + PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl; + + DRW_draw_pass(psl->vcolor_faces); + DRW_draw_pass(psl->face_overlay); + DRW_draw_pass(psl->wire_overlay); +} + +static void PAINT_VERTEX_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.vcolor_face_shader); + DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader); +} + +static const DrawEngineDataSize PAINT_VERTEX_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_VERTEX_Data); + +DrawEngineType draw_engine_paint_vertex_type = { + NULL, NULL, + N_("PaintVertexMode"), + &PAINT_VERTEX_data_size, + &PAINT_VERTEX_engine_init, + &PAINT_VERTEX_engine_free, + &PAINT_VERTEX_cache_init, + &PAINT_VERTEX_cache_populate, + NULL, + NULL, + &PAINT_VERTEX_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/paint_weight_mode.c b/source/blender/draw/modes/paint_weight_mode.c new file mode 100644 index 00000000000..13ef42d8622 --- /dev/null +++ b/source/blender/draw/modes/paint_weight_mode.c @@ -0,0 +1,243 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/paint_weight_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +#include "DNA_mesh_types.h" +#include "DNA_view3d_types.h" + +#include "BKE_mesh.h" + +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ +extern struct GlobalsUboStorage ts; /* draw_common.c */ + +extern char datatoc_paint_wire_vert_glsl[]; +extern char datatoc_paint_wire_frag_glsl[]; +extern char datatoc_paint_vert_frag_glsl[]; +extern char datatoc_common_globals_lib_glsl[]; + +/* *********** LISTS *********** */ + +typedef struct PAINT_WEIGHT_PassList { + struct DRWPass *weight_faces; + struct DRWPass *wire_overlay; + struct DRWPass *face_overlay; + struct DRWPass *vert_overlay; +} PAINT_WEIGHT_PassList; + +typedef struct PAINT_WEIGHT_StorageList { + struct PAINT_WEIGHT_PrivateData *g_data; +} PAINT_WEIGHT_StorageList; + +typedef struct PAINT_WEIGHT_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + PAINT_WEIGHT_PassList *psl; + PAINT_WEIGHT_StorageList *stl; +} PAINT_WEIGHT_Data; + +/* *********** STATIC *********** */ + +static struct { + struct GPUShader *weight_face_shader; + struct GPUShader *wire_overlay_shader; + struct GPUShader *face_overlay_shader; + struct GPUShader *vert_overlay_shader; + int actdef; +} e_data = {NULL}; /* Engine data */ + +typedef struct PAINT_WEIGHT_PrivateData { + DRWShadingGroup *fweights_shgrp; + DRWShadingGroup *lwire_shgrp; + DRWShadingGroup *face_shgrp; + DRWShadingGroup *vert_shgrp; +} PAINT_WEIGHT_PrivateData; + +/* *********** FUNCTIONS *********** */ + +static void PAINT_WEIGHT_engine_init(void *UNUSED(vedata)) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (e_data.actdef != draw_ctx->obact->actdef) { + e_data.actdef = draw_ctx->obact->actdef; + + BKE_mesh_batch_cache_dirty(draw_ctx->obact->data, BKE_MESH_BATCH_DIRTY_ALL); + } + + if (!e_data.weight_face_shader) { + e_data.weight_face_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA); + } + + if (!e_data.wire_overlay_shader) { + e_data.wire_overlay_shader = DRW_shader_create_with_lib( + datatoc_paint_wire_vert_glsl, NULL, + datatoc_paint_wire_frag_glsl, + datatoc_common_globals_lib_glsl, "#define WEIGHT_MODE\n"); + } + + if (!e_data.face_overlay_shader) { + e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } + + if (!e_data.vert_overlay_shader) { + e_data.vert_overlay_shader = DRW_shader_create_with_lib( + datatoc_paint_wire_vert_glsl, NULL, + datatoc_paint_vert_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + } +} + +static void PAINT_WEIGHT_cache_init(void *vedata) +{ + PAINT_WEIGHT_PassList *psl = ((PAINT_WEIGHT_Data *)vedata)->psl; + PAINT_WEIGHT_StorageList *stl = ((PAINT_WEIGHT_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Create a pass */ + psl->weight_faces = DRW_pass_create( + "Weight Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_MULTIPLY); + + stl->g_data->fweights_shgrp = DRW_shgroup_create(e_data.weight_face_shader, psl->weight_faces); + + static float light[3] = {-0.3f, 0.5f, 1.0f}; + static float alpha = 1.0f; + static float world_light = 1.0f; + DRW_shgroup_uniform_vec3(stl->g_data->fweights_shgrp, "light", light, 1); + DRW_shgroup_uniform_float(stl->g_data->fweights_shgrp, "alpha", &alpha, 1); + DRW_shgroup_uniform_float(stl->g_data->fweights_shgrp, "global", &world_light, 1); + } + + { + psl->wire_overlay = DRW_pass_create( + "Wire Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); + + stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay); + } + + { + psl->face_overlay = DRW_pass_create( + "Face Mask Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + + stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay); + + static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f}; + DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1); + } + + { + psl->vert_overlay = DRW_pass_create( + "Vert Mask Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); + + stl->g_data->vert_shgrp = DRW_shgroup_create(e_data.vert_overlay_shader, psl->vert_overlay); + } +} + +static void PAINT_WEIGHT_cache_populate(void *vedata, Object *ob) +{ + PAINT_WEIGHT_StorageList *stl = ((PAINT_WEIGHT_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + + if ((ob->type == OB_MESH) && (ob == draw_ctx->obact)) { + const Mesh *me = ob->data; + const bool use_wire = (v3d->overlay.paint_flag & V3D_OVERLAY_PAINT_WIRE) != 0; + const bool use_surface = DRW_object_is_mode_shade(ob) == true; + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + struct Gwn_Batch *geom; + + if (use_surface) { + geom = DRW_cache_mesh_surface_weights_get(ob); + DRW_shgroup_call_add(stl->g_data->fweights_shgrp, geom, ob->obmat); + } + + if (use_face_sel || use_wire) { + geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel); + DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat); + } + + if (use_face_sel) { + geom = DRW_cache_mesh_faces_weight_overlay_get(ob); + DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat); + } + + if (use_vert_sel) { + geom = DRW_cache_mesh_verts_weight_overlay_get(ob); + DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat); + } + } +} + +static void PAINT_WEIGHT_draw_scene(void *vedata) +{ + PAINT_WEIGHT_PassList *psl = ((PAINT_WEIGHT_Data *)vedata)->psl; + + DRW_draw_pass(psl->weight_faces); + DRW_draw_pass(psl->face_overlay); + DRW_draw_pass(psl->wire_overlay); + DRW_draw_pass(psl->vert_overlay); +} + +static void PAINT_WEIGHT_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader); + DRW_SHADER_FREE_SAFE(e_data.vert_overlay_shader); +} + +static const DrawEngineDataSize PAINT_WEIGHT_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_WEIGHT_Data); + +DrawEngineType draw_engine_paint_weight_type = { + NULL, NULL, + N_("PaintWeightMode"), + &PAINT_WEIGHT_data_size, + &PAINT_WEIGHT_engine_init, + &PAINT_WEIGHT_engine_free, + &PAINT_WEIGHT_cache_init, + &PAINT_WEIGHT_cache_populate, + NULL, + NULL, + &PAINT_WEIGHT_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c new file mode 100644 index 00000000000..dacd4b72834 --- /dev/null +++ b/source/blender/draw/modes/particle_mode.c @@ -0,0 +1,240 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/particle_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_particle_types.h" + +#include "BKE_particle.h" +#include "BKE_pointcache.h" + +#include "GPU_shader.h" +#include "GPU_batch.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +#include "ED_particle.h" + +#include "DEG_depsgraph_query.h" + +#include "draw_cache_impl.h" + +extern char datatoc_particle_strand_vert_glsl[]; +extern char datatoc_particle_strand_frag_glsl[]; + +/* *********** LISTS *********** */ + +typedef struct PARTICLE_PassList { + struct DRWPass *psys_edit_pass; +} PARTICLE_PassList; + +typedef struct PARTICLE_FramebufferList { + struct GPUFrameBuffer *fb; +} PARTICLE_FramebufferList; + +typedef struct PARTICLE_TextureList { + struct GPUTexture *texture; +} PARTICLE_TextureList; + +typedef struct PARTICLE_StorageList { + struct CustomStruct *block; + struct PARTICLE_PrivateData *g_data; +} PARTICLE_StorageList; + +typedef struct PARTICLE_Data { + void *engine_type; /* Required */ + PARTICLE_FramebufferList *fbl; + PARTICLE_TextureList *txl; + PARTICLE_PassList *psl; + PARTICLE_StorageList *stl; +} PARTICLE_Data; + +/* *********** STATIC *********** */ + +static struct { + struct GPUShader *strands_shader; + struct GPUShader *points_shader; +} e_data = {NULL}; /* Engine data */ + +typedef struct PARTICLE_PrivateData { + DRWShadingGroup *strands_group; + DRWShadingGroup *inner_points_group; + DRWShadingGroup *tip_points_group; +} PARTICLE_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +static void particle_engine_init(void *UNUSED(vedata)) +{ + if (!e_data.strands_shader) { + e_data.strands_shader = DRW_shader_create( + datatoc_particle_strand_vert_glsl, + NULL, + datatoc_particle_strand_frag_glsl, + ""); + } + if (!e_data.points_shader) { + e_data.points_shader = GPU_shader_get_builtin_shader( + GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + } +} + +static void particle_cache_init(void *vedata) +{ + PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl; + PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + /* Create a pass */ + psl->psys_edit_pass = DRW_pass_create("PSys Edit Pass", + (DRW_STATE_WRITE_COLOR | + DRW_STATE_WRITE_DEPTH | + DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_WIRE | + DRW_STATE_POINT)); + + stl->g_data->strands_group = DRW_shgroup_create( + e_data.strands_shader, psl->psys_edit_pass); + stl->g_data->inner_points_group = DRW_shgroup_create( + e_data.points_shader, psl->psys_edit_pass); + stl->g_data->tip_points_group = DRW_shgroup_create( + e_data.points_shader, psl->psys_edit_pass); + + static float size = 5.0f; + static float outline_width = 1.0f; + DRW_shgroup_uniform_float(stl->g_data->inner_points_group, "size", &size, 1); + DRW_shgroup_uniform_float(stl->g_data->inner_points_group, "outlineWidth", &outline_width, 1); + DRW_shgroup_uniform_float(stl->g_data->tip_points_group, "size", &size, 1); + DRW_shgroup_uniform_float(stl->g_data->tip_points_group, "outlineWidth", &outline_width, 1); +} + +static void particle_edit_cache_populate(void *vedata, + Object *object, + ParticleSystem *psys, + PTCacheEdit *edit) +{ + PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + ParticleEditSettings *pset = PE_settings(draw_ctx->scene); + { + struct Gwn_Batch *strands = + DRW_cache_particles_get_edit_strands(object, psys, edit); + DRW_shgroup_call_add(stl->g_data->strands_group, strands, NULL); + } + if (pset->selectmode == SCE_SELECT_POINT) { + struct Gwn_Batch *points = + DRW_cache_particles_get_edit_inner_points(object, psys, edit); + DRW_shgroup_call_add(stl->g_data->inner_points_group, points, NULL); + } + if (ELEM(pset->selectmode, SCE_SELECT_POINT, SCE_SELECT_END)) { + struct Gwn_Batch *points = + DRW_cache_particles_get_edit_tip_points(object, psys, edit); + DRW_shgroup_call_add(stl->g_data->tip_points_group, points, NULL); + } +} + +static void particle_cache_populate(void *vedata, Object *object) +{ + if (object->mode != OB_MODE_PARTICLE_EDIT) { + return; + } + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id); + /* Usually the edit structure is created by Particle Edit Mode Toggle + * operator, but sometimes it's invoked after tagging hair as outdated + * (for example, when toggling edit mode). That makes it impossible to + * create edit structure for until after next dependency graph evaluation. + * + * Ideally, the edit structure will be created here already via some + * dependency graph callback or so, but currently trying to make it nicer + * only causes bad level calls and breaks design from the past. + */ + Object *object_orig = DEG_get_original_object(object); + PTCacheEdit *edit = PE_create_current( + draw_ctx->depsgraph, scene_orig, object_orig); + /* NOTE: We need to pass evaluated particle system, which we need + * to find first. + */ + ParticleSystem *psys = object->particlesystem.first; + ParticleSystem *psys_orig = object_orig->particlesystem.first; + while (psys_orig != NULL) { + if (PE_get_current_from_psys(psys_orig) == edit) { + break; + } + psys = psys->next; + psys_orig = psys_orig->next; + } + if (psys == NULL) { + printf("Error getting evaluated particle system for edit.\n"); + return; + } + particle_edit_cache_populate(vedata, object, psys, edit); +} + +/* Optional: Post-cache_populate callback */ +static void particle_cache_finish(void *UNUSED(vedata)) +{ +} + +/* Draw time ! Control rendering pipeline from here */ +static void particle_draw_scene(void *vedata) +{ + + PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl; + + DRW_draw_pass(psl->psys_edit_pass); +} + +static void particle_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.strands_shader); +} + +static const DrawEngineDataSize particle_data_size = + DRW_VIEWPORT_DATA_SIZE(PARTICLE_Data); + +DrawEngineType draw_engine_particle_type = { + NULL, NULL, + N_("Particle Mode"), + &particle_data_size, + &particle_engine_init, + &particle_engine_free, + &particle_cache_init, + &particle_cache_populate, + &particle_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &particle_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c new file mode 100644 index 00000000000..586fb590ebf --- /dev/null +++ b/source/blender/draw/modes/pose_mode.c @@ -0,0 +1,306 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/pose_mode.c + * \ingroup draw + */ +#include "BKE_modifier.h" + +#include "DNA_modifier_types.h" +#include "DNA_view3d_types.h" + +#include "DRW_engine.h" +#include "DRW_render.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +extern GlobalsUboStorage ts; + +/* *********** LISTS *********** */ +/* All lists are per viewport specific datas. + * They are all free when viewport changes engines + * or is free itself. Use POSE_engine_init() to + * initialize most of them and POSE_cache_init() + * for POSE_PassList */ + +typedef struct POSE_PassList { + struct DRWPass *bone_solid; + struct DRWPass *bone_outline; + struct DRWPass *bone_wire; + struct DRWPass *bone_envelope; + struct DRWPass *bone_axes; + struct DRWPass *relationship; + struct DRWPass *bone_selection; +} POSE_PassList; + +typedef struct POSE_StorageList { + struct POSE_PrivateData *g_data; +} POSE_StorageList; + +typedef struct POSE_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + POSE_PassList *psl; + POSE_StorageList *stl; +} POSE_Data; + +/* *********** STATIC *********** */ + +typedef struct POSE_PrivateData { + DRWShadingGroup *bone_selection_shgrp; +} POSE_PrivateData; /* Transient data */ + +static struct { + struct GPUShader *bone_selection_sh; +} e_data = {NULL}; + +static float blend_color[4] = {0.0, 0.0, 0.0, 0.5}; + +/* *********** FUNCTIONS *********** */ +static bool POSE_is_bone_selection_overlay_active(void) +{ + const DRWContextState *dcs = DRW_context_state_get(); + const View3D *v3d = dcs->v3d; + return v3d && (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECTION); +} + +static void POSE_engine_init(void *UNUSED(vedata)) +{ + if (!e_data.bone_selection_sh) { + e_data.bone_selection_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + } +} + +static void POSE_engine_free(void) +{ +} + +/* Here init all passes and shading groups + * Assume that all Passes are NULL */ +static void POSE_cache_init(void *vedata) +{ + POSE_PassList *psl = ((POSE_Data *)vedata)->psl; + POSE_StorageList *stl = ((POSE_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Solid bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; + psl->bone_solid = DRW_pass_create("Bone Solid Pass", state); + } + + { + /* Bones Outline */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + psl->bone_outline = DRW_pass_create("Bone Outline Pass", state); + } + + { + /* Wire bones */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND; + psl->bone_wire = DRW_pass_create("Bone Wire Pass", state); + } + + { + /* distance outline around envelope bones */ + DRWState state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_FRONT; + psl->bone_envelope = DRW_pass_create("Bone Envelope Outline Pass", state); + } + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WIRE_SMOOTH | DRW_STATE_BLEND; + psl->bone_axes = DRW_pass_create("Bone Axes Pass", state); + } + + { + /* Non Meshes Pass (Camera, empties, lamps ...) */ + DRWState state = + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE; + psl->relationship = DRW_pass_create("Bone Relationship Pass", state); + } + + { + if (POSE_is_bone_selection_overlay_active()) { + DRWShadingGroup *grp; + psl->bone_selection = DRW_pass_create( + "Bone Selection", + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND); + grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection); + DRW_shgroup_uniform_vec4(grp, "color", blend_color, 1); + stl->g_data->bone_selection_shgrp = grp; + } + } +} + +static bool POSE_is_driven_by_active_armature(Object *ob) +{ + Object *ob_arm = modifiers_isDeformedByArmature(ob); + if (ob_arm) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + bool is_active = DRW_pose_mode_armature(ob_arm, draw_ctx->obact); + if (!is_active && ob_arm->proxy_from) { + is_active = DRW_pose_mode_armature(ob_arm->proxy_from, draw_ctx->obact); + } + return is_active; + } + else { + Object *ob_mesh_deform = modifiers_isDeformedByMeshDeform(ob); + if (ob_mesh_deform) { + return POSE_is_driven_by_active_armature(ob_mesh_deform); + } + } + return false; +} + +/* Add geometry to shading groups. Execute for each objects */ +static void POSE_cache_populate(void *vedata, Object *ob) +{ + POSE_PassList *psl = ((POSE_Data *)vedata)->psl; + POSE_StorageList *stl = ((POSE_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + /* In the future this will allow us to implement face manipulators, + * and similar functionalities. For now we handle only pose bones. */ + + if (ob->type == OB_ARMATURE) { + if (DRW_pose_mode_armature(ob, draw_ctx->obact)) { + DRWArmaturePasses passes = { + .bone_solid = psl->bone_solid, + .bone_outline = psl->bone_outline, + .bone_wire = psl->bone_wire, + .bone_envelope = psl->bone_envelope, + .bone_axes = psl->bone_axes, + .relationship_lines = psl->relationship, + }; + DRW_shgroup_armature_pose(ob, passes); + } + } + else if (ob->type == OB_MESH && + !DRW_state_is_select() && + POSE_is_bone_selection_overlay_active() && + POSE_is_driven_by_active_armature(ob)) + { + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); + if (geom) { + DRW_shgroup_call_object_add(stl->g_data->bone_selection_shgrp, geom, ob); + } + } +} + +/** + * Return true if armature should be handled by the pose mode engine. + */ +bool DRW_pose_mode_armature(Object *ob, Object *active_ob) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + + /* Pose armature is handled by pose mode engine. */ + if (((ob == active_ob) || (ob->mode & OB_MODE_POSE)) && + ((draw_ctx->object_mode & OB_MODE_POSE) != 0)) + { + return true; + } + + /* Armature parent is also handled by pose mode engine. */ + if ((active_ob != NULL) && ((draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) != 0)) { + if (ob == draw_ctx->object_pose) { + return true; + } + } + + return false; +} + +/* Draw time ! Control rendering pipeline from here */ +static void POSE_draw_scene(void *vedata) +{ + POSE_PassList *psl = ((POSE_Data *)vedata)->psl; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0; + const bool bone_selection_overlay = POSE_is_bone_selection_overlay_active(); + + if (DRW_state_is_select()) { + DRW_draw_pass(psl->bone_solid); + DRW_draw_pass(psl->bone_wire); + return; + } + + if (bone_selection_overlay) { + GPU_framebuffer_bind(dfbl->default_fb); + DRW_draw_pass(psl->bone_selection); + GPU_framebuffer_bind(dfbl->depth_only_fb); + GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0); + GPU_framebuffer_bind(dfbl->default_fb); + } + + DRW_draw_pass(psl->bone_envelope); + + if (transparent_bones) { + DRW_pass_state_add(psl->bone_solid, DRW_STATE_BLEND); + DRW_pass_state_remove(psl->bone_solid, DRW_STATE_WRITE_DEPTH); + DRW_draw_pass(psl->bone_solid); + } + + MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl) + + if (!transparent_bones) { + DRW_draw_pass(psl->bone_solid); + } + + DRW_draw_pass(psl->bone_outline); + DRW_draw_pass(psl->bone_wire); + DRW_draw_pass(psl->relationship); + + MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl) + + /* Draw axes with linesmooth and outside of multisample buffer. */ + DRW_draw_pass(psl->bone_axes); +} + +static const DrawEngineDataSize POSE_data_size = DRW_VIEWPORT_DATA_SIZE(POSE_Data); + +DrawEngineType draw_engine_pose_type = { + NULL, NULL, + N_("PoseMode"), + &POSE_data_size, + &POSE_engine_init, + &POSE_engine_free, + &POSE_cache_init, + &POSE_cache_populate, + NULL, + NULL, + &POSE_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c new file mode 100644 index 00000000000..56b5898a6cf --- /dev/null +++ b/source/blender/draw/modes/sculpt_mode.c @@ -0,0 +1,281 @@ +/* + * Copyright 2016, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/sculpt_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_pbvh.h" +#include "BKE_paint.h" + +#include "DEG_depsgraph.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" +#include "GPU_matrix.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +/* *********** LISTS *********** */ +/* All lists are per viewport specific datas. + * They are all free when viewport changes engines + * or is free itself. Use SCULPT_engine_init() to + * initialize most of them and SCULPT_cache_init() + * for SCULPT_PassList */ + +typedef struct SCULPT_PassList { + /* Declare all passes here and init them in + * SCULPT_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *pass; +} SCULPT_PassList; + +typedef struct SCULPT_FramebufferList { + /* Contains all framebuffer objects needed by this engine. + * Only contains (GPUFrameBuffer *) */ + struct GPUFrameBuffer *fb; +} SCULPT_FramebufferList; + +typedef struct SCULPT_TextureList { + /* Contains all framebuffer textures / utility textures + * needed by this engine. Only viewport specific textures + * (not per object). Only contains (GPUTexture *) */ + struct GPUTexture *texture; +} SCULPT_TextureList; + +typedef struct SCULPT_StorageList { + /* Contains any other memory block that the engine needs. + * Only directly MEM_(m/c)allocN'ed blocks because they are + * free with MEM_freeN() when viewport is freed. + * (not per object) */ + struct CustomStruct *block; + struct SCULPT_PrivateData *g_data; +} SCULPT_StorageList; + +typedef struct SCULPT_Data { + /* Struct returned by DRW_viewport_engine_data_ensure. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + SCULPT_FramebufferList *fbl; + SCULPT_TextureList *txl; + SCULPT_PassList *psl; + SCULPT_StorageList *stl; +} SCULPT_Data; + +/* *********** STATIC *********** */ + +static struct { + /* Custom shaders : + * Add sources to source/blender/draw/modes/shaders + * init in SCULPT_engine_init(); + * free in SCULPT_engine_free(); */ + struct GPUShader *shader_flat; + struct GPUShader *shader_smooth; +} e_data = {NULL}; /* Engine data */ + +typedef struct SCULPT_PrivateData { + /* This keeps the references of the shading groups for + * easy access in SCULPT_cache_populate() */ + DRWShadingGroup *group_flat; + DRWShadingGroup *group_smooth; +} SCULPT_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +/* Init Textures, Framebuffers, Storage and Shaders. + * It is called for every frames. + * (Optional) */ +static void SCULPT_engine_init(void *vedata) +{ + SCULPT_TextureList *txl = ((SCULPT_Data *)vedata)->txl; + SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl; + SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; + + UNUSED_VARS(txl, fbl, stl); + + /* Init Framebuffers like this: order is attachment order (for color texs) */ + /* + * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0}, + * {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}}; + */ + + /* DRW_framebuffer_init takes care of checking if + * the framebuffer is valid and has the right size*/ + /* + * float *viewport_size = DRW_viewport_size_get(); + * DRW_framebuffer_init(&fbl->occlude_wire_fb, + * (int)viewport_size[0], (int)viewport_size[1], + * tex, 2); + */ + + if (!e_data.shader_flat) { + e_data.shader_flat = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR); + } + if (!e_data.shader_smooth) { + e_data.shader_smooth = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SMOOTH_COLOR); + } +} + +/* Here init all passes and shading groups + * Assume that all Passes are NULL */ +static void SCULPT_cache_init(void *vedata) +{ + SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; + SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Create a pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY; + psl->pass = DRW_pass_create("Sculpt Pass", state); + + /* Create a shadingGroup using a function in draw_common.c or custom one */ + /* + * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire); + * -- or -- + * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass); + */ + stl->g_data->group_flat = DRW_shgroup_create(e_data.shader_flat, psl->pass); + stl->g_data->group_smooth = DRW_shgroup_create(e_data.shader_smooth, psl->pass); + } +} + +static bool object_is_flat(const Object *ob) +{ + Mesh *me = ob->data; + if (me->mpoly && me->mpoly[0].flag & ME_SMOOTH) { + return false; + } + else { + return true; + } +} + +/* Add geometry to shadingGroups. Execute for each objects */ +static void SCULPT_cache_populate(void *vedata, Object *ob) +{ + SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; + SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; + + UNUSED_VARS(psl, stl); + + if (ob->type == OB_MESH) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (ob->sculpt && (ob == draw_ctx->obact)) { + /* XXX, needed for dyntopo-undo (which clears). + * probably depsgraph should handlle? in 2.7x getting derived-mesh does this (mesh_build_data) */ + if (ob->sculpt->pbvh == NULL) { + /* create PBVH immediately (would be created on the fly too, + * but this avoids waiting on first stroke) */ + Scene *scene = draw_ctx->scene; + + BKE_sculpt_update_mesh_elements(draw_ctx->depsgraph, scene, scene->toolsettings->sculpt, ob, false, false); + } + + PBVH *pbvh = ob->sculpt->pbvh; + if (pbvh && pbvh_has_mask(pbvh)) { + /* Get geometry cache */ + DRWShadingGroup *shgroup = object_is_flat(ob) ? stl->g_data->group_flat : stl->g_data->group_smooth; + + /* Add geom to a shading group */ + DRW_shgroup_call_sculpt_add(shgroup, ob, ob->obmat); + } + } + } +} + +/* Optional: Post-cache_populate callback */ +static void SCULPT_cache_finish(void *vedata) +{ + SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; + SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl; + + /* Do something here! dependant on the objects gathered */ + UNUSED_VARS(psl, stl); +} + +/* Draw time ! Control rendering pipeline from here */ +static void SCULPT_draw_scene(void *vedata) +{ + SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl; + SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl; + + /* Default framebuffer and texture */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + UNUSED_VARS(fbl, dfbl, dtxl); + + /* Show / hide entire passes, swap framebuffers ... whatever you fancy */ + /* + * DRW_framebuffer_texture_detach(dtxl->depth); + * DRW_framebuffer_bind(fbl->custom_fb); + * DRW_draw_pass(psl->pass); + * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); + * DRW_framebuffer_bind(dfbl->default_fb); + */ + + /* ... or just render passes on default framebuffer. */ + DRW_draw_pass(psl->pass); + + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ +} + +/* Cleanup when destroying the engine. + * This is not per viewport ! only when quitting blender. + * Mostly used for freeing shaders */ +static void SCULPT_engine_free(void) +{ + // DRW_SHADER_FREE_SAFE(custom_shader); +} + +static const DrawEngineDataSize SCULPT_data_size = DRW_VIEWPORT_DATA_SIZE(SCULPT_Data); + +DrawEngineType draw_engine_sculpt_type = { + NULL, NULL, + N_("SculptMode"), + &SCULPT_data_size, + &SCULPT_engine_init, + &SCULPT_engine_free, + &SCULPT_cache_init, + &SCULPT_cache_populate, + &SCULPT_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &SCULPT_draw_scene, + NULL, + NULL, +}; diff --git a/source/blender/draw/modes/shaders/armature_axes_vert.glsl b/source/blender/draw/modes/shaders/armature_axes_vert.glsl new file mode 100644 index 00000000000..e46dab458e0 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_axes_vert.glsl @@ -0,0 +1,30 @@ + +uniform mat4 ViewProjectionMatrix; +uniform vec3 screenVecs[3]; + +/* ---- Instanciated Attribs ---- */ +in float axis; /* position on the axis. [0.0-1.0] is X axis, [1.0-2.0] is Y, etc... */ +in vec2 screenPos; +in vec3 colorAxis; + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; +in vec4 color; + +flat out vec4 finalColor; + +void main() +{ + vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz; + vec3 y_axis = InstanceModelMatrix[1].xyz; + vec3 bone_loc = InstanceModelMatrix[3].xyz; + vec3 wpos = bone_loc + y_axis + chosen_axis * fract(axis); + vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y; + /* Scale uniformly by axis length */ + spos *= length(chosen_axis); + + gl_Position = ViewProjectionMatrix * vec4(wpos + spos, 1.0); + + finalColor.rgb = mix(colorAxis, color.rgb, color.a); + finalColor.a = 1.0; +} diff --git a/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl b/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl new file mode 100644 index 00000000000..cecc5447c7c --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_envelope_distance_frag.glsl @@ -0,0 +1,15 @@ + +flat in vec3 finalStateColor; /* UNUSED */ +flat in vec3 finalBoneColor; /* UNUSED */ +in vec3 normalView; + +out vec4 fragColor; + +uniform vec4 color = vec4(1.0, 1.0, 1.0, 0.2); + +void main() +{ + float n = normalize(normalView).z; + n = 1.0 - clamp(-n, 0.0, 1.0); + fragColor = color * n; +} diff --git a/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl new file mode 100644 index 00000000000..a836d7fa9e1 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl @@ -0,0 +1,156 @@ + +uniform mat4 ViewMatrix; +uniform mat4 ViewMatrixInverse; +uniform mat4 ViewProjectionMatrix; +uniform mat4 ProjectionMatrix; + +uniform vec2 viewportSize; +uniform float lineThickness = 2.0; + +/* ---- Instanciated Attribs ---- */ +in vec2 pos0; +in vec2 pos1; +in vec2 pos2; + +/* ---- Per instance Attribs ---- */ +/* Assumed to be in world coordinate already. */ +in vec4 headSphere; +in vec4 tailSphere; +in vec4 outlineColorSize; +in vec3 xAxis; + +flat out vec4 finalColor; + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +vec2 compute_dir(vec2 v0, vec2 v1, vec2 v2) +{ + vec2 dir = normalize(v2 - v0); + dir = vec2(dir.y, -dir.x); + return dir; +} + +mat3 compute_mat(vec4 sphere, vec3 bone_vec, out float z_ofs) +{ + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + vec3 cam_ray = (is_persp) ? sphere.xyz - ViewMatrixInverse[3].xyz + : -ViewMatrixInverse[2].xyz; + + /* Sphere center distance from the camera (persp) in world space. */ + float cam_dist = length(cam_ray); + + /* Compute view aligned orthonormal space. */ + vec3 z_axis = cam_ray / cam_dist; + vec3 x_axis = normalize(cross(bone_vec, z_axis)); + vec3 y_axis = cross(z_axis, x_axis); + z_ofs = 0.0; + + if (is_persp) { + /* For perspective, the projected sphere radius + * can be bigger than the center disc. Compute the + * max angular size and compensate by sliding the disc + * towards the camera and scale it accordingly. */ + const float half_pi = 3.1415926 * 0.5; + float rad = sphere.w; + /* Let be : + * V the view vector origin. + * O the sphere origin. + * T the point on the target circle. + * We compute the angle between (OV) and (OT). */ + float a = half_pi - asin(rad / cam_dist); + float cos_b = cos(a); + float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0)); + + x_axis *= sin_b; + y_axis *= sin_b; + z_ofs = -rad * cos_b; + } + + return mat3(x_axis, y_axis, z_axis); +} + +struct Bone { vec3 vec; float sinb; }; + +bool bone_blend_starts(vec3 p, Bone b) +{ + /* we just want to know when the head sphere starts interpolating. */ + return dot(p, b.vec) > -b.sinb; +} + +vec3 get_outline_point( + vec2 pos, vec4 sph_near, vec4 sph_far, + mat3 mat_near, mat3 mat_far, float z_ofs_near, float z_ofs_far, Bone b) +{ + /* Compute outline position on the nearest sphere and check + * if it penetrates the capsule body. If it does, put this + * vertex on the farthest sphere. */ + vec3 wpos = mat_near * vec3(pos * sph_near.w, z_ofs_near); + if (bone_blend_starts(wpos, b)) { + wpos = sph_far.xyz + mat_far * vec3(pos * sph_far.w, z_ofs_far); + } + else { + wpos += sph_near.xyz; + } + return wpos; +} + +void main() +{ + float dst_head = distance(headSphere.xyz, ViewMatrixInverse[3].xyz); + float dst_tail = distance(tailSphere.xyz, ViewMatrixInverse[3].xyz); + // float dst_head = -dot(headSphere.xyz, ViewMatrix[2].xyz); + // float dst_tail = -dot(tailSphere.xyz, ViewMatrix[2].xyz); + + vec4 sph_near, sph_far; + if ((dst_head > dst_tail) && (ProjectionMatrix[3][3] == 0.0)) { + sph_near = tailSphere; + sph_far = headSphere; + } + else { + sph_near = headSphere; + sph_far = tailSphere; + } + + vec3 bone_vec = (sph_far.xyz - sph_near.xyz) + 1e-8; + + Bone b; + float bone_lenrcp = 1.0 / max(1e-8, sqrt(dot(bone_vec, bone_vec))); + b.sinb = (sph_far.w - sph_near.w) * bone_lenrcp * sph_near.w; + b.vec = bone_vec * bone_lenrcp; + + float z_ofs_near, z_ofs_far; + mat3 mat_near = compute_mat(sph_near, bone_vec, z_ofs_near); + mat3 mat_far = compute_mat(sph_far, bone_vec, z_ofs_far); + + vec3 wpos0 = get_outline_point(pos0, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); + vec3 wpos1 = get_outline_point(pos1, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); + vec3 wpos2 = get_outline_point(pos2, sph_near, sph_far, mat_near, mat_far, z_ofs_near, z_ofs_far, b); + + vec4 V = ViewMatrix * vec4(wpos1, 1.0); + float pres_fac = (ProjectionMatrix[3][3] == 0.0) ? abs(V.z) : 1.0; + + vec4 p0 = ViewProjectionMatrix * vec4(wpos0, 1.0); + vec4 p1 = ProjectionMatrix * V; + vec4 p2 = ViewProjectionMatrix * vec4(wpos2, 1.0); + + /* compute position from 3 vertex because the change in direction + * can happen very quicky and lead to very thin edges. */ + vec2 ss0 = proj(p0); + vec2 ss1 = proj(p1); + vec2 ss2 = proj(p2); + vec2 edge_dir = compute_dir(ss0, ss1, ss2); + + bool outer = ((gl_VertexID & 1) == 1); + vec2 t = outlineColorSize.w * (lineThickness / viewportSize); + t *= pres_fac; + t = (outer) ? t : vec2(0.0); + + gl_Position = p1; + gl_Position.xy += t * edge_dir; + + finalColor = vec4(outlineColorSize.rgb, 1.0); +} diff --git a/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl new file mode 100644 index 00000000000..b20656ff326 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_envelope_solid_frag.glsl @@ -0,0 +1,16 @@ + +flat in vec3 finalStateColor; +flat in vec3 finalBoneColor; +in vec3 normalView; + +out vec4 fragColor; + +void main() +{ + /* Smooth lighting factor. */ + const float s = 0.2; /* [0.0-0.5] range */ + float n = normalize(normalView).z; + float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0); + fragColor.rgb = mix(finalStateColor, finalBoneColor, fac); + fragColor.a = 0.6; /* Hardcoded transparency factor. */ +} diff --git a/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl new file mode 100644 index 00000000000..83ae720e70a --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl @@ -0,0 +1,55 @@ + +uniform mat4 ViewMatrix; +uniform mat4 ViewMatrixInverse; +uniform mat4 ViewProjectionMatrix; + +/* ---- Instanciated Attribs ---- */ +in vec3 pos; + +/* ---- Per instance Attribs ---- */ +/* Assumed to be in world coordinate already. */ +in vec4 headSphere; +in vec4 tailSphere; +in vec3 xAxis; +in vec3 stateColor; +in vec3 boneColor; + +flat out vec3 finalStateColor; +flat out vec3 finalBoneColor; +out vec3 normalView; + +void main() +{ + vec3 bone_vec = tailSphere.xyz - headSphere.xyz; + float bone_len = max(1e-8, sqrt(dot(bone_vec, bone_vec))); + float bone_lenrcp = 1.0 / bone_len; +#ifdef SMOOTH_ENVELOPE + float sinb = (tailSphere.w - headSphere.w) * bone_lenrcp; +#else + const float sinb = 0.0; +#endif + + vec3 y_axis = bone_vec * bone_lenrcp; + vec3 z_axis = normalize(cross(xAxis, -y_axis)); + vec3 x_axis = cross(y_axis, z_axis); /* cannot trust xAxis to be orthogonal. */ + + vec3 sp, nor; + nor = sp = pos.xyz; + + /* In bone space */ + bool is_head = (pos.z < -sinb); + sp *= (is_head) ? headSphere.w : tailSphere.w; + sp.z += (is_head) ? 0.0 : bone_len; + + /* Convert to world space */ + mat3 bone_mat = mat3(x_axis, y_axis, z_axis); + sp = bone_mat * sp.xzy + headSphere.xyz; + nor = bone_mat * nor.xzy; + + normalView = mat3(ViewMatrix) * nor; + + gl_Position = ViewProjectionMatrix * vec4(sp, 1.0); + + finalStateColor = stateColor; + finalBoneColor = boneColor; +} diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl new file mode 100644 index 00000000000..11924b19cf8 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl @@ -0,0 +1,87 @@ + +layout(lines_adjacency) in; +layout(triangle_strip, max_vertices = 6) out; + +in vec4 pPos[]; +in vec3 vPos[]; +in vec2 ssPos[]; +in vec2 ssNor[]; +in vec4 vColSize[]; + +flat out vec4 finalColor; +uniform mat4 ProjectionMatrix; +uniform vec2 viewportSize; +uniform float lineThickness = 2.0; + +vec2 compute_dir(vec2 v0, vec2 v1) +{ + vec2 dir = normalize(v1 - v0); + dir = vec2(-dir.y, dir.x); + return dir; +} + +void emit_edge(vec2 edge_dir, vec2 hidden_dir, vec2 thick, bool is_persp) +{ + float fac = dot(-hidden_dir, edge_dir); + + vec2 t = thick * (is_persp ? abs(vPos[1].z) : 1.0); + gl_Position = pPos[1]; + EmitVertex(); + gl_Position.xy += t * edge_dir * sign(fac); + EmitVertex(); + + t = thick * (is_persp ? abs(vPos[2].z) : 1.0); + gl_Position = pPos[2]; + EmitVertex(); + gl_Position.xy += t * edge_dir * sign(fac); + EmitVertex(); +} + +void emit_corner(const int e, vec2 thick, bool is_persp) +{ + vec2 corner_dir = ssNor[e]; + vec2 t = thick * (is_persp ? abs(vPos[e].z) : 1.0); + + gl_Position = pPos[e] + vec4(t * corner_dir, 0.0, 0.0); + EmitVertex(); +} + +void main(void) +{ + finalColor = vec4(vColSize[0].rgb, 1.0); + + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + + vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0); + vec3 v10 = vPos[0] - vPos[1]; + vec3 v12 = vPos[2] - vPos[1]; + vec3 v13 = vPos[3] - vPos[1]; + + vec3 n0 = cross(v12, v10); + vec3 n3 = cross(v13, v12); + + float fac0 = dot(view_vec, n0); + float fac3 = dot(view_vec, n3); + + /* If both adjacent verts are facing the camera the same way, + * then it isn't an outline edge. */ + if (sign(fac0) == sign(fac3)) + return; + + /* Don't outline if concave edge. */ + if (dot(n0, v13) > 0.0) + return; + + vec2 thick = vColSize[0].w * (lineThickness / viewportSize); + vec2 edge_dir = compute_dir(ssPos[1], ssPos[2]); + + /* Take the farthest point to compute edge direction + * (avoid problems with point behind near plane). */ + vec2 hidden_point = (vPos[0].z < vPos[3].z) ? ssPos[0] : ssPos[3]; + vec2 hidden_dir = normalize(hidden_point - ssPos[1]); + + emit_corner(1, thick, is_persp); + emit_edge(edge_dir, hidden_dir, thick, is_persp); + emit_corner(2, thick, is_persp); + EndPrimitive(); +} diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl new file mode 100644 index 00000000000..3e7a185bb62 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl @@ -0,0 +1,48 @@ + +uniform mat3 NormalMatrix; + +uniform mat4 ViewMatrix; +uniform mat4 ProjectionMatrix; +uniform vec2 viewportSize; + +/* ---- Instanciated Attribs ---- */ +in vec3 pos; +in vec3 nor; +in vec3 snor; + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; +in vec4 outlineColorSize; + +out vec4 pPos; +out vec3 vPos; +out vec2 ssPos; +out vec2 ssNor; +out vec4 vColSize; + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +void main() +{ + /* This is slow and run per vertex, but it's still faster than + * doing it per instance on CPU and sending it on via instance attrib */ + mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); + + vec4 viewpos = ViewMatrix * (InstanceModelMatrix * vec4(pos, 1.0)); + + vPos = viewpos.xyz; + pPos = ProjectionMatrix * viewpos; + + /* TODO FIX: there is still a problem with this vector + * when the bone is scaled or in persp mode. But it's + * barelly visible at the outline corners. */ + ssNor = normalize((NormalMatrix * snor).xy); + + ssPos = proj(pPos); + + vColSize = outlineColorSize; +} diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl new file mode 100644 index 00000000000..89f4d97f29b --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl @@ -0,0 +1,9 @@ + +in vec4 finalColor; + +out vec4 fragColor; + +void main() +{ + fragColor = vec4(finalColor.rgb, 0.6); /* Hardcoded transparency factor. */ +} diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl new file mode 100644 index 00000000000..505868c9dcf --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl @@ -0,0 +1,37 @@ + +uniform mat3 NormalMatrix; +uniform mat4 ViewMatrixInverse; +uniform mat4 ViewProjectionMatrix; + +uniform mat4 ViewMatrix; +uniform mat4 ProjectionMatrix; +uniform vec2 viewportSize; + +/* ---- Instanciated Attribs ---- */ +in vec3 pos; +in vec3 nor; + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; +in vec3 boneColor; +in vec3 stateColor; + +out vec4 finalColor; + +void main() +{ + mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); + vec3 normal = normalize(NormalMatrix * nor); + + /* Do lighting at an angle to avoid flat shading on front facing bone. */ + const vec3 light = vec3(0.1, 0.1, 0.8); + float n = dot(normal, light); + + /* Smooth lighting factor. */ + const float s = 0.2; /* [0.0-0.5] range */ + float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0); + finalColor.rgb = mix(stateColor, boneColor, fac); + finalColor.a = 1.0; + + gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(pos, 1.0)); +} diff --git a/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl new file mode 100644 index 00000000000..a169facd45a --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl @@ -0,0 +1,102 @@ + +uniform mat4 ViewMatrix; +uniform mat4 ProjectionMatrix; +uniform vec2 viewportSize; +uniform float lineThickness = 2.0; + +/* ---- Instanciated Attribs ---- */ +in vec2 pos0; +in vec2 pos1; + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; +in vec4 outlineColorSize; + +flat out vec4 finalColor; + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +vec2 compute_dir(vec2 v0, vec2 v1, vec2 c) +{ + vec2 dir = normalize(v1 - v0); + dir = vec2(dir.y, -dir.x); + /* The model matrix can be scaled negativly. + * Use projected sphere center to determine + * the outline direction. */ + vec2 cv = c - v0; + dir = (dot(dir, cv) > 0.0) ? -dir : dir; + return dir; +} + +void main() +{ + mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix; + mat4 sphereMatrix = inverse(model_view_matrix); + + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + + /* This is the local space camera ray (not normalize). + * In perspective mode it's also the viewspace position + * of the sphere center. */ + vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0); + cam_ray = mat3(sphereMatrix) * cam_ray; + + /* Sphere center distance from the camera (persp) in local space. */ + float cam_dist = length(cam_ray); + + /* Compute view aligned orthonormal space. */ + vec3 z_axis = cam_ray / cam_dist; + vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis)); + vec3 y_axis = cross(z_axis, x_axis); + float z_ofs = 0.0; + + if (is_persp) { + /* For perspective, the projected sphere radius + * can be bigger than the center disc. Compute the + * max angular size and compensate by sliding the disc + * towards the camera and scale it accordingly. */ + const float half_pi = 3.1415926 * 0.5; + const float rad = 0.05; + /* Let be (in local space): + * V the view vector origin. + * O the sphere origin. + * T the point on the target circle. + * We compute the angle between (OV) and (OT). */ + float a = half_pi - asin(rad / cam_dist); + float cos_b = cos(a); + float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0)); + + x_axis *= sin_b; + y_axis *= sin_b; + z_ofs = -rad * cos_b; + } + + /* Camera oriented position (but still in local space) */ + vec3 cam_pos0 = x_axis * pos0.x + y_axis * pos0.y + z_axis * z_ofs; + vec3 cam_pos1 = x_axis * pos1.x + y_axis * pos1.y + z_axis * z_ofs; + + vec4 V = model_view_matrix * vec4(cam_pos0, 1.0); + vec4 p0 = ProjectionMatrix * V; + vec4 p1 = ProjectionMatrix * (model_view_matrix * vec4(cam_pos1, 1.0)); + vec4 c = ProjectionMatrix * vec4(model_view_matrix[3].xyz, 1.0); + + vec2 ssc = proj(c); + vec2 ss0 = proj(p0); + vec2 ss1 = proj(p1); + vec2 edge_dir = compute_dir(ss0, ss1, ssc); + + bool outer = ((gl_VertexID & 1) == 1); + + vec2 t = outlineColorSize.w * (lineThickness / viewportSize); + t *= (is_persp) ? abs(V.z) : 1.0; + t = (outer) ? t : vec2(0.0); + + gl_Position = p0; + gl_Position.xy += t * edge_dir; + + finalColor = vec4(outlineColorSize.rgb, 1.0); +} diff --git a/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl new file mode 100644 index 00000000000..3c80f629d79 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_sphere_solid_frag.glsl @@ -0,0 +1,81 @@ + +#extension GL_ARB_conservative_depth : enable + +uniform mat4 ViewMatrixInverse; +uniform mat4 ProjectionMatrix; + +flat in vec3 finalStateColor; +flat in vec3 finalBoneColor; +flat in mat4 sphereMatrix; +in vec3 viewPosition; + +#ifdef GL_ARB_conservative_depth +/* Saves a lot of overdraw! */ +layout(depth_greater) out float gl_FragDepth; +#endif + +out vec4 fragColor; + +#define cameraPos ViewMatrixInverse[3].xyz + +float get_depth_from_view_z(float z) +{ + if (ProjectionMatrix[3][3] == 0.0) { + z = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2]; + } + else { + z = z * ProjectionMatrix[2][2] / (1.0 - ProjectionMatrix[3][2]); + } + return z * 0.5 + 0.5; +} + +void main() +{ + const float sphere_radius = 0.05; + + bool is_perp = (ProjectionMatrix[3][3] == 0.0); + vec3 ray_ori_view = (is_perp) ? vec3(0.0) : viewPosition.xyz; + vec3 ray_dir_view = (is_perp) ? viewPosition : vec3(0.0, 0.0, -1.0); + + /* Single matrix mul without branch. */ + vec4 mul_vec = (is_perp) ? vec4(ray_dir_view, 0.0) : vec4(ray_ori_view, 1.0); + vec3 mul_res = (sphereMatrix * mul_vec).xyz; + + /* Reminder : + * sphereMatrix[3] is the view space origin in sphere space (sph_ori -> view_ori). + * sphereMatrix[2] is the view space Z axis in sphere space. */ + + /* convert to sphere local space */ + vec3 ray_ori = (is_perp) ? sphereMatrix[3].xyz : mul_res; + vec3 ray_dir = (is_perp) ? mul_res : -sphereMatrix[2].xyz; + float ray_len = length(ray_dir); + ray_dir /= ray_len; + + /* Line to sphere intersect */ + const float sphere_radius_sqr = sphere_radius * sphere_radius; + float b = dot(ray_ori, ray_dir); + float c = dot(ray_ori, ray_ori) - sphere_radius_sqr; + float h = b * b - c; + float t = -sqrt(max(0.0, h)) - b; + + /* Compute dot product for lighting */ + vec3 p = ray_dir * t + ray_ori; /* Point on sphere */ + vec3 n = normalize(p); /* Normal is just the point in sphere space, normalized. */ + vec3 l = normalize(sphereMatrix[2].xyz); /* Just the view Z axis in the sphere space. */ + + + /* Smooth lighting factor. */ + const float s = 0.2; /* [0.0-0.5] range */ + float fac = clamp((dot(n, l) * (1.0 - s)) + s, 0.0, 1.0); + fragColor.rgb = mix(finalStateColor, finalBoneColor, fac); + + /* 2x2 dither pattern to smooth the lighting. */ + float dither = (0.5 + dot(vec2(ivec2(gl_FragCoord.xy) & ivec2(1)), vec2(1.0, 2.0))) * 0.25; + dither *= (1.0 / 255.0); /* Assume 8bit per color buffer. */ + + /* Hardcoded transparency factor. Less than shape to be less distractive. */ + fragColor = vec4(fragColor.rgb + dither, 0.4); + + t /= ray_len; + gl_FragDepth = get_depth_from_view_z(ray_dir_view.z * t + ray_ori_view.z); +} diff --git a/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl new file mode 100644 index 00000000000..1e06047054e --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_sphere_solid_vert.glsl @@ -0,0 +1,82 @@ + +uniform mat4 ViewMatrix; +uniform mat4 ProjectionMatrix; + +/* ---- Instanciated Attribs ---- */ +in vec2 pos; + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; +in vec3 stateColor; +in vec3 boneColor; + +flat out vec3 finalStateColor; +flat out vec3 finalBoneColor; +flat out mat4 sphereMatrix; +out vec3 viewPosition; + +/* Sphere radius */ +const float rad = 0.05; + +void main() +{ + mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix; + sphereMatrix = inverse(model_view_matrix); + + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + + /* This is the local space camera ray (not normalize). + * In perspective mode it's also the viewspace position + * of the sphere center. */ + vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0); + cam_ray = mat3(sphereMatrix) * cam_ray; + + /* Sphere center distance from the camera (persp) in local space. */ + float cam_dist = length(cam_ray); + + /* Compute view aligned orthonormal space. */ + vec3 z_axis = cam_ray / cam_dist; + vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis)); + vec3 y_axis = cross(z_axis, x_axis); + + float z_ofs = -rad - 1e-8; /* offset to the front of the sphere */ + if (is_persp) { + /* For perspective, the projected sphere radius + * can be bigger than the center disc. Compute the + * max angular size and compensate by sliding the disc + * towards the camera and scale it accordingly. */ + const float half_pi = 3.1415926 * 0.5; + /* Let be (in local space): + * V the view vector origin. + * O the sphere origin. + * T the point on the target circle. + * We compute the angle between (OV) and (OT). */ + float a = half_pi - asin(rad / cam_dist); + float cos_b = cos(a); + float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0)); +#if 1 + /* Instead of choosing the biggest circle in screenspace, + * we choose the nearest with the same angular size. This + * permit us to leverage GL_ARB_conservative_depth in the + * fragment shader. */ + float minor = cam_dist - rad; + float major = cam_dist - cos_b * rad; + float fac = minor / major; + sin_b *= fac; +#else + z_ofs = -rad * cos_b; +#endif + x_axis *= sin_b; + y_axis *= sin_b; + } + + /* Camera oriented position (but still in local space) */ + vec3 cam_pos = x_axis * pos.x + y_axis * pos.y + z_axis * z_ofs; + + vec4 V = model_view_matrix * vec4(cam_pos, 1.0); + gl_Position = ProjectionMatrix * V; + viewPosition = V.xyz; + + finalStateColor = stateColor; + finalBoneColor = boneColor; +} diff --git a/source/blender/draw/modes/shaders/armature_stick_frag.glsl b/source/blender/draw/modes/shaders/armature_stick_frag.glsl new file mode 100644 index 00000000000..d03cf4c0366 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_stick_frag.glsl @@ -0,0 +1,13 @@ + +noperspective in float colorFac; +flat in vec4 finalWireColor; +flat in vec4 finalInnerColor; + +out vec4 fragColor; + +void main() +{ + float fac = smoothstep(1.0, 0.2, colorFac); + fragColor.rgb = mix(finalInnerColor.rgb, finalWireColor.rgb, fac); + fragColor.a = 1.0; +} diff --git a/source/blender/draw/modes/shaders/armature_stick_vert.glsl b/source/blender/draw/modes/shaders/armature_stick_vert.glsl new file mode 100644 index 00000000000..eb14239bc6f --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_stick_vert.glsl @@ -0,0 +1,88 @@ + +uniform mat4 ProjectionMatrix; +uniform mat4 ViewProjectionMatrix; +uniform mat4 ViewMatrix; +uniform vec2 viewportSize; + +/* ---- Instanciated Attribs ---- */ +in vec2 pos; /* bone aligned screen space */ +in uint flag; + +#define COL_WIRE (1u << 0u) +#define COL_HEAD (1u << 1u) +#define COL_TAIL (1u << 2u) +#define COL_BONE (1u << 3u) + +#define POS_HEAD (1u << 4u) +#define POS_TAIL (1u << 5u) /* UNUSED */ +#define POS_BONE (1u << 6u) + +/* ---- Per instance Attribs ---- */ +in vec3 boneStart; +in vec3 boneEnd; +in vec4 wireColor; /* alpha encode if we do wire. If 0.0 we dont. */ +in vec4 boneColor; /* alpha encode if we do bone. If 0.0 we dont. */ +in vec4 headColor; /* alpha encode if we do head. If 0.0 we dont. */ +in vec4 tailColor; /* alpha encode if we do tail. If 0.0 we dont. */ + +#define do_wire (wireColor.a > 0.0) +#define is_head ((flag & POS_HEAD) != 0u) +#define is_bone ((flag & POS_BONE) != 0u) + +noperspective out float colorFac; +flat out vec4 finalWireColor; +flat out vec4 finalInnerColor; + +uniform float stickSize = 5.0; /* might be dependant on DPI setting in the future. */ + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +void main() +{ + finalInnerColor = ((flag & COL_HEAD) != 0u) ? headColor : tailColor; + finalInnerColor = ((flag & COL_BONE) != 0u) ? boneColor : finalInnerColor; + finalWireColor = (do_wire) ? wireColor : finalInnerColor; + /* Make the color */ + colorFac = ((flag & COL_WIRE) == 0u) ? ((flag & COL_BONE) != 0u) ? 1.0 : 2.0 : 0.0; + + vec4 v0 = ViewMatrix * vec4(boneStart, 1.0); + vec4 v1 = ViewMatrix * vec4(boneEnd, 1.0); + + /* Clip the bone to the camera origin plane (not the clip plane) + * to avoid glitches if one end is behind the camera origin (in persp). */ + const float clip_dist = -1e-7; /* hardcoded, -1e-8 is giving gliches. */ + vec3 bvec = v1.xyz - v0.xyz; + vec3 clip_pt = v0.xyz + bvec * ((v0.z - clip_dist) / -bvec.z); + if (v0.z > clip_dist) { + v0.xyz = clip_pt; + } + else if (v1.z > clip_dist) { + v1.xyz = clip_pt; + } + + vec4 p0 = ProjectionMatrix * v0; + vec4 p1 = ProjectionMatrix * v1; + + float h = (is_head) ? p0.w : p1.w; + + vec2 x_screen_vec = normalize(proj(p1) - proj(p0) + 1e-8); + vec2 y_screen_vec = vec2(x_screen_vec.y, -x_screen_vec.x); + + /* 2D screen aligned pos at the point */ + vec2 vpos = pos.x * x_screen_vec + pos.y * y_screen_vec; + vpos *= (ProjectionMatrix[3][3] == 0.0) ? h : 1.0; + vpos *= (do_wire) ? 1.0 : 0.5; + + if (finalInnerColor.a > 0.0) { + gl_Position = (is_head) ? p0 : p1; + gl_Position.xy += stickSize * (vpos / viewportSize); + gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */ + } + else { + gl_Position = vec4(0.0); + } +} diff --git a/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl new file mode 100644 index 00000000000..fc5cc1cdcc3 --- /dev/null +++ b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl @@ -0,0 +1,10 @@ + +in vec2 pos; +in vec2 uvs; +out vec4 uvcoordsvar; + +void main() +{ + uvcoordsvar = vec4(uvs, 0.0, 0.0); + gl_Position = vec4(pos, 0.0, 1.0); +} diff --git a/source/blender/draw/modes/shaders/common_fxaa_lib.glsl b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl new file mode 100644 index 00000000000..8158437b943 --- /dev/null +++ b/source/blender/draw/modes/shaders/common_fxaa_lib.glsl @@ -0,0 +1,678 @@ +//---------------------------------------------------------------------------------- +// File: es3-kepler\FXAA/FXAA3_11.h +// SDK Version: v3.00 +// Email: gameworks@nvidia.com +// Site: http://developer.nvidia.com/ +// +// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA CORPORATION nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//---------------------------------------------------------------------------------- + +/* BLENDER MODIFICATIONS: + * + * - (#B1#) Compute luma on the fly using BT. 709 luma function + * - (#B2#) main function instead of #include, due to lack of + * ARB_shading_language_include in 3.3 + * - (#B3#) version and extension directives + * - removed "FXAA Console" algorithm support and shader parameters + * - removed HLSL support shims + * - (#B4#) change luma sampling to compute, not use A channel + * (this also removes GATHER4_ALPHA support) + * - removed all the console shaders (only remaining algorithm is "FXAA PC + * Quality") + * + * Note that this file doesn't follow the coding style guidelines. + */ + +/*============================================================================ + FXAA QUALITY - TUNING KNOBS +------------------------------------------------------------------------------ +NOTE the other tuning knobs are now in the shader function inputs! +============================================================================*/ +#ifndef FXAA_QUALITY__PRESET + // + // Choose the quality preset. + // This needs to be compiled into the shader as it effects code. + // Best option to include multiple presets is to + // in each shader define the preset, then include this file. + // + // OPTIONS + // ----------------------------------------------------------------------- + // 10 to 15 - default medium dither (10=fastest, 15=highest quality) + // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) + // 39 - no dither, very expensive + // + // NOTES + // ----------------------------------------------------------------------- + // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) + // 13 = about same speed as FXAA 3.9 and better than 12 + // 23 = closest to FXAA 3.9 visually and performance wise + // _ = the lowest digit is directly related to performance + // _ = the highest digit is directly related to style + // + #define FXAA_QUALITY__PRESET 12 +#endif + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 3.0 + #define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 3.0 + #define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 4.0 + #define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 4.0 + #define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 4.0 + #define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) + #define FXAA_QUALITY__PS 3 + #define FXAA_QUALITY__P0 1.5 + #define FXAA_QUALITY__P1 2.0 + #define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) + #define FXAA_QUALITY__PS 4 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) + #define FXAA_QUALITY__PS 5 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) + #define FXAA_QUALITY__PS 6 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) + #define FXAA_QUALITY__PS 7 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 3.0 + #define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) + #define FXAA_QUALITY__PS 8 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 4.0 + #define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) + #define FXAA_QUALITY__PS 9 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 4.0 + #define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) + #define FXAA_QUALITY__PS 10 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 4.0 + #define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) + #define FXAA_QUALITY__PS 11 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 4.0 + #define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.5 + #define FXAA_QUALITY__P2 2.0 + #define FXAA_QUALITY__P3 2.0 + #define FXAA_QUALITY__P4 2.0 + #define FXAA_QUALITY__P5 2.0 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) + #define FXAA_QUALITY__PS 12 + #define FXAA_QUALITY__P0 1.0 + #define FXAA_QUALITY__P1 1.0 + #define FXAA_QUALITY__P2 1.0 + #define FXAA_QUALITY__P3 1.0 + #define FXAA_QUALITY__P4 1.0 + #define FXAA_QUALITY__P5 1.5 + #define FXAA_QUALITY__P6 2.0 + #define FXAA_QUALITY__P7 2.0 + #define FXAA_QUALITY__P8 2.0 + #define FXAA_QUALITY__P9 2.0 + #define FXAA_QUALITY__P10 4.0 + #define FXAA_QUALITY__P11 8.0 +#endif + +#define FxaaSat(x) clamp(x, 0.0, 1.0) + +#ifdef FXAA_ALPHA + +#define FxaaTexTop(t, p) textureLod(t, p, 0.0).aaaa +#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o).aaaa +#define FxaaLuma(rgba) rgba.a + +#else + +#define FxaaTexTop(t, p) textureLod(t, p, 0.0) +#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + +/* (#B1#) */ +float FxaaLuma(vec4 rgba) { + // note: sqrt because the sampled colors are in a linear colorspace! + // this approximates a perceptual conversion, which is good enough for the + // algorithm + return sqrt(dot(rgba.rgb, vec3(0.2126, 0.7152, 0.0722))); +} + +#endif + +/*============================================================================ + + FXAA3 QUALITY - PC + +============================================================================*/ +/*--------------------------------------------------------------------------*/ +vec4 FxaaPixelShader( + // + // Use noperspective interpolation here (turn off perspective interpolation). + // {xy} = center of pixel + vec2 pos, + // + // Input color texture. + // {rgb_} = color in linear or perceptual color space + sampler2D tex, + // + // Only used on FXAA Quality. + // This must be from a constant/uniform. + // {x_} = 1.0/screenWidthInPixels + // {_y} = 1.0/screenHeightInPixels + vec2 fxaaQualityRcpFrame, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__SUBPIX define. + // It is here now to allow easier tuning. + // Choose the amount of sub-pixel aliasing removal. + // This can effect sharpness. + // 1.00 - upper limit (softer) + // 0.75 - default amount of filtering + // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) + // 0.25 - almost off + // 0.00 - completely off + float fxaaQualitySubpix, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. + // It is here now to allow easier tuning. + // The minimum amount of local contrast required to apply algorithm. + // 0.333 - too little (faster) + // 0.250 - low quality + // 0.166 - default + // 0.125 - high quality + // 0.063 - overkill (slower) + float fxaaQualityEdgeThreshold, + // + // Only used on FXAA Quality. + // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. + // It is here now to allow easier tuning. + // Trims the algorithm from processing darks. + // 0.0833 - upper limit (default, the start of visible unfiltered edges) + // 0.0625 - high quality (faster) + // 0.0312 - visible limit (slower) + float fxaaQualityEdgeThresholdMin +) { +/*--------------------------------------------------------------------------*/ + vec2 posM; + posM.x = pos.x; + posM.y = pos.y; + vec4 rgbyM = FxaaTexTop(tex, posM); + float lumaM = FxaaLuma(rgbyM); // (#B4#) + float lumaS = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0, 1), fxaaQualityRcpFrame.xy)); + float lumaE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 0), fxaaQualityRcpFrame.xy)); + float lumaN = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 0,-1), fxaaQualityRcpFrame.xy)); + float lumaW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 0), fxaaQualityRcpFrame.xy)); +/*--------------------------------------------------------------------------*/ + float maxSM = max(lumaS, lumaM); + float minSM = min(lumaS, lumaM); + float maxESM = max(lumaE, maxSM); + float minESM = min(lumaE, minSM); + float maxWN = max(lumaN, lumaW); + float minWN = min(lumaN, lumaW); + float rangeMax = max(maxWN, maxESM); + float rangeMin = min(minWN, minESM); + float rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; + float range = rangeMax - rangeMin; + float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); + bool earlyExit = range < rangeMaxClamped; +/*--------------------------------------------------------------------------*/ + if(earlyExit) { + return rgbyM; + } +/*--------------------------------------------------------------------------*/ + float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1,-1), fxaaQualityRcpFrame.xy)); + float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1, 1), fxaaQualityRcpFrame.xy)); + float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, ivec2( 1,-1), fxaaQualityRcpFrame.xy)); + float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, ivec2(-1, 1), fxaaQualityRcpFrame.xy)); +/*--------------------------------------------------------------------------*/ + float lumaNS = lumaN + lumaS; + float lumaWE = lumaW + lumaE; + float subpixRcpRange = 1.0/range; + float subpixNSWE = lumaNS + lumaWE; + float edgeHorz1 = (-2.0 * lumaM) + lumaNS; + float edgeVert1 = (-2.0 * lumaM) + lumaWE; +/*--------------------------------------------------------------------------*/ + float lumaNESE = lumaNE + lumaSE; + float lumaNWNE = lumaNW + lumaNE; + float edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + float edgeVert2 = (-2.0 * lumaN) + lumaNWNE; +/*--------------------------------------------------------------------------*/ + float lumaNWSW = lumaNW + lumaSW; + float lumaSWSE = lumaSW + lumaSE; + float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + float edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + float edgeHorz = abs(edgeHorz3) + edgeHorz4; + float edgeVert = abs(edgeVert3) + edgeVert4; +/*--------------------------------------------------------------------------*/ + float subpixNWSWNESE = lumaNWSW + lumaNESE; + float lengthSign = fxaaQualityRcpFrame.x; + bool horzSpan = edgeHorz >= edgeVert; + float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + float subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + float gradientN = lumaN - lumaM; + float gradientS = lumaS - lumaM; + float lumaNN = lumaN + lumaM; + float lumaSS = lumaS + lumaM; + bool pairN = abs(gradientN) >= abs(gradientS); + float gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + float subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + vec2 posB; + posB.x = posM.x; + posB.y = posM.y; + vec2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + vec2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + vec2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + float subpixD = ((-2.0)*subpixC) + 3.0; + float lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + float subpixE = subpixC * subpixC; + float lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + float gradientScaled = gradient * 1.0/4.0; + float lumaMM = lumaM - lumaNN * 0.5; + float subpixF = subpixD * subpixE; + bool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + bool doneN = abs(lumaEndN) >= gradientScaled; + bool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + bool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + float dstN = posM.x - posN.x; + float dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + float spanLength = (dstP + dstN); + bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + float spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + bool directionN = dstN < dstP; + float dst = min(dstN, dstP); + bool goodSpan = directionN ? goodSpanN : goodSpanP; + float subpixG = subpixF * subpixF; + float pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + float subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + float pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + float pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + return vec4(FxaaTexTop(tex, posM).xyz, lumaM); +} +/*==========================================================================*/ + diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl new file mode 100644 index 00000000000..4a0104e2cf2 --- /dev/null +++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl @@ -0,0 +1,69 @@ + +/* keep in sync with GlobalsUboStorage */ +layout(std140) uniform globalsBlock { + vec4 colorWire; + vec4 colorWireEdit; + vec4 colorActive; + vec4 colorSelect; + vec4 colorTransform; + vec4 colorLibrarySelect; + vec4 colorLibrary; + vec4 colorLamp; + vec4 colorSpeaker; + vec4 colorCamera; + vec4 colorEmpty; + vec4 colorVertex; + vec4 colorVertexSelect; + vec4 colorEditMeshActive; + vec4 colorEdgeSelect; + vec4 colorEdgeSeam; + vec4 colorEdgeSharp; + vec4 colorEdgeCrease; + vec4 colorEdgeBWeight; + vec4 colorEdgeFaceSelect; + vec4 colorFace; + vec4 colorFaceSelect; + vec4 colorNormal; + vec4 colorVNormal; + vec4 colorLNormal; + vec4 colorFaceDot; + + vec4 colorDeselect; + vec4 colorOutline; + vec4 colorLampNoAlpha; + + vec4 colorBackground; + + vec4 colorHandleFree; + vec4 colorHandleAuto; + vec4 colorHandleVect; + vec4 colorHandleAlign; + vec4 colorHandleAutoclamp; + vec4 colorHandleSelFree; + vec4 colorHandleSelAuto; + vec4 colorHandleSelVect; + vec4 colorHandleSelAlign; + vec4 colorHandleSelAutoclamp; + vec4 colorNurbUline; + vec4 colorNurbSelUline; + vec4 colorActiveSpline; + + vec4 colorGrid; + vec4 colorGridEmphasise; + vec4 colorGridAxisX; + vec4 colorGridAxisY; + vec4 colorGridAxisZ; + + float sizeLampCenter; + float sizeLampCircle; + float sizeLampCircleShadow; + float sizeVertex; + float sizeEdge; + float sizeEdgeFix; + float sizeFaceDot; + + float gridDistance; + float gridResolution; + float gridSubdivisions; + float gridScale; +}; diff --git a/source/blender/draw/modes/shaders/common_hair_lib.glsl b/source/blender/draw/modes/shaders/common_hair_lib.glsl new file mode 100644 index 00000000000..3fe44b4e142 --- /dev/null +++ b/source/blender/draw/modes/shaders/common_hair_lib.glsl @@ -0,0 +1,190 @@ +/** + * Library to create hairs dynamically from control points. + * This is less bandwidth intensive than fetching the vertex attributes + * but does more ALU work per vertex. This also reduce the number + * of data the CPU has to precompute and transfert for each update. + **/ + +/** + * hairStrandsRes: Number of points per hair strand. + * 2 - no subdivision + * 3+ - 1 or more interpolated points per hair. + **/ +uniform int hairStrandsRes = 8; + +/** + * hairThicknessRes : Subdiv around the hair. + * 1 - Wire Hair: Only one pixel thick, independant of view distance. + * 2 - Polystrip Hair: Correct width, flat if camera is parallel. + * 3+ - Cylinder Hair: Massive calculation but potentially perfect. Still need proper support. + **/ +uniform int hairThicknessRes = 1; + +/* Hair thickness shape. */ +uniform float hairRadRoot = 0.01; +uniform float hairRadTip = 0.0; +uniform float hairRadShape = 0.5; +uniform bool hairCloseTip = true; + +/* -- Per control points -- */ +uniform samplerBuffer hairPointBuffer; /* RGBA32F */ +#define point_position xyz +#define point_time w /* Position along the hair length */ + +/* -- Per strands data -- */ +uniform usamplerBuffer hairStrandBuffer; /* R32UI */ + +/* Not used, use one buffer per uv layer */ +//uniform samplerBuffer hairUVBuffer; /* RG32F */ +//uniform samplerBuffer hairColBuffer; /* RGBA16 linear color */ + +void unpack_strand_data(uint data, out int strand_offset, out int strand_segments) +{ +#if 0 /* Pack point count */ + // strand_offset = (data & 0x1FFFFFFFu); + // strand_segments = 1u << (data >> 29u); /* We only need 3 bits to store subdivision level. */ +#else + strand_offset = int(data & 0x00FFFFFFu); + strand_segments = int(data >> 24u); +#endif +} + +/* -- Subdivision stage -- */ +/** + * We use a transform feedback to preprocess the strands and add more subdivision to it. + * For the moment theses are simple smooth interpolation but one could hope to see the full + * children particle modifiers being evaluated at this stage. + * + * If no more subdivision is needed, we can skip this step. + **/ + +#ifdef HAIR_PHASE_SUBDIV +int hair_get_base_id(float local_time, int strand_segments, out float interp_time) +{ + float time_per_strand_seg = 1.0 / float(strand_segments); + + float ratio = local_time / time_per_strand_seg; + interp_time = fract(ratio); + + return int(ratio); +} + +void hair_get_interp_attribs(out vec4 data0, out vec4 data1, out vec4 data2, out vec4 data3, out float interp_time) +{ + float local_time = float(gl_VertexID % hairStrandsRes) / float(hairStrandsRes - 1); + + int hair_id = gl_VertexID / hairStrandsRes; + uint strand_data = texelFetch(hairStrandBuffer, hair_id).x; + + int strand_offset, strand_segments; + unpack_strand_data(strand_data, strand_offset, strand_segments); + + int id = hair_get_base_id(local_time, strand_segments, interp_time); + + int ofs_id = id + strand_offset; + + data0 = texelFetch(hairPointBuffer, ofs_id - 1); + data1 = texelFetch(hairPointBuffer, ofs_id); + data2 = texelFetch(hairPointBuffer, ofs_id + 1); + data3 = texelFetch(hairPointBuffer, ofs_id + 2); + + if (id <= 0) { + /* root points. Need to reconstruct previous data. */ + data0 = data1 * 2.0 - data2; + } + if (id + 1 >= strand_segments) { + /* tip points. Need to reconstruct next data. */ + data3 = data2 * 2.0 - data1; + } +} +#endif + +/* -- Drawing stage -- */ +/** + * For final drawing, the vertex index and the number of vertex per segment + **/ + +#ifndef HAIR_PHASE_SUBDIV +int hair_get_strand_id(void) +{ + return gl_VertexID / (hairStrandsRes * hairThicknessRes); +} + +int hair_get_base_id(void) +{ + return gl_VertexID / hairThicknessRes; +} + +/* Copied from cycles. */ +float hair_shaperadius(float shape, float root, float tip, float time) +{ + float radius = 1.0 - time; + + if (shape < 0.0) { + radius = pow(radius, 1.0 + shape); + } + else { + radius = pow(radius, 1.0 / (1.0 - shape)); + } + + if (hairCloseTip && (time > 0.99)) { + return 0.0; + } + + return (radius * (root - tip)) + tip; +} + +void hair_get_pos_tan_nor_time( + bool is_persp, vec3 camera_pos, vec3 camera_z, + out vec3 wpos, out vec3 wtan, out vec3 wnor, out float time, out float thickness, out float thick_time) +{ + int id = hair_get_base_id(); + vec4 data = texelFetch(hairPointBuffer, id); + wpos = data.point_position; + time = data.point_time; + if (time == 0.0) { + /* Hair root */ + wtan = texelFetch(hairPointBuffer, id + 1).point_position - wpos; + } + else { + wtan = wpos - texelFetch(hairPointBuffer, id - 1).point_position; + } + + vec3 camera_vec = (is_persp) ? wpos - camera_pos : -camera_z; + wnor = normalize(cross(camera_vec, wtan)); + + thickness = hair_shaperadius(hairRadShape, hairRadRoot, hairRadTip, time); + + if (hairThicknessRes > 1) { + thick_time = float(gl_VertexID % hairThicknessRes) / float(hairThicknessRes - 1); + thick_time = thickness * (thick_time * 2.0 - 1.0); + + wpos += wnor * thick_time; + } +} + +vec2 hair_get_customdata_vec2(const samplerBuffer cd_buf) +{ + int id = hair_get_strand_id(); + return texelFetch(cd_buf, id).rg; +} + +vec3 hair_get_customdata_vec3(const samplerBuffer cd_buf) +{ + int id = hair_get_strand_id(); + return texelFetch(cd_buf, id).rgb; +} + +vec4 hair_get_customdata_vec4(const samplerBuffer cd_buf) +{ + int id = hair_get_strand_id(); + return texelFetch(cd_buf, id).rgba; +} + +vec3 hair_get_strand_pos(void) +{ + int id = hair_get_strand_id() * hairStrandsRes; + return texelFetch(hairPointBuffer, id).point_position; +} + +#endif diff --git a/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl b/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl new file mode 100644 index 00000000000..96a3103f666 --- /dev/null +++ b/source/blender/draw/modes/shaders/common_hair_refine_vert.glsl @@ -0,0 +1,15 @@ + +/* To be compiled with common_hair_lib.glsl */ + +out vec4 outData; + +void main(void) +{ + float interp_time; + vec4 data0, data1, data2, data3; + hair_get_interp_attribs(data0, data1, data2, data3, interp_time); + + /* TODO some interpolation. */ + + outData = mix(data1, data2, interp_time); +} diff --git a/source/blender/draw/modes/shaders/common_view_lib.glsl b/source/blender/draw/modes/shaders/common_view_lib.glsl new file mode 100644 index 00000000000..d261d263a6f --- /dev/null +++ b/source/blender/draw/modes/shaders/common_view_lib.glsl @@ -0,0 +1,14 @@ +/* keep in sync with DRWManager.view_data */ +layout(std140) uniform viewBlock { + /* Same order as DRWViewportMatrixType */ + mat4 ViewProjectionMatrix; + mat4 ViewProjectionMatrixInverse; + mat4 ViewMatrix; + mat4 ViewMatrixInverse; + mat4 ProjectionMatrix; + mat4 ProjectionMatrixInverse; + + vec4 CameraTexCoFactors; + + vec4 clipPlanes[2]; +}; diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl new file mode 100644 index 00000000000..e78462b6915 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_frag.glsl @@ -0,0 +1,22 @@ + +flat in int vertFlag; + +#define VERTEX_SELECTED (1 << 0) +#define VERTEX_ACTIVE (1 << 1) + +out vec4 FragColor; + +void main() +{ + /* TODO: vertex size */ + + if ((vertFlag & VERTEX_SELECTED) != 0) { + FragColor = colorVertexSelect; + } + else if ((vertFlag & VERTEX_ACTIVE) != 0) { + FragColor = colorEditMeshActive; + } + else { + FragColor = colorVertex; + } +} diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl new file mode 100644 index 00000000000..9da8d9b50d7 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl @@ -0,0 +1,79 @@ + +#define ACTIVE_NURB 1 << 7 /* Keep the same value of `ACTIVE_NURB` in `draw_cache_imp_curve.c` */ + +layout(lines) in; +layout(line_strip, max_vertices = 6) out; + +uniform vec2 viewportSize; + +flat in int vertFlag[]; + +flat out vec4 finalColor; + +void main() +{ + /* TODO: vertex size */ + + vec4 v1 = gl_in[0].gl_Position; + vec4 v2 = gl_in[1].gl_Position; + + int is_active_nurb = vertFlag[1] & ACTIVE_NURB; + int color_id = vertFlag[1] ^ is_active_nurb; + + if (is_active_nurb != 0) { + /* draw the outline. */ + vec2 v1_2 = (v2.xy/v2.w - v1.xy/v1.w); + vec2 offset; + + if (abs(v1_2.x * viewportSize.x) < abs(v1_2.y * viewportSize.y)) { + offset = vec2(2.0 / viewportSize.x, 0.0); + } + else { + offset = vec2(0.0, 2.0 / viewportSize.y); + } + + finalColor = colorActiveSpline; + + gl_Position = v1; + gl_Position.xy += offset * v1.w; + EmitVertex(); + + gl_Position = v2; + gl_Position.xy += offset * v2.w; + EmitVertex(); + + EndPrimitive(); + + gl_Position = v1; + gl_Position.xy -= offset * v1.w; + EmitVertex(); + + gl_Position = v2; + gl_Position.xy -= offset * v2.w; + EmitVertex(); + + EndPrimitive(); + } + + if (color_id == 0) finalColor = colorHandleFree; + else if (color_id == 1) finalColor = colorHandleAuto; + else if (color_id == 2) finalColor = colorHandleVect; + else if (color_id == 3) finalColor = colorHandleAlign; + else if (color_id == 4) finalColor = colorHandleAutoclamp; + else if (color_id == 5) finalColor = colorHandleSelFree; + else if (color_id == 6) finalColor = colorHandleSelAuto; + else if (color_id == 7) finalColor = colorHandleSelVect; + else if (color_id == 8) finalColor = colorHandleSelAlign; + else if (color_id == 9) finalColor = colorHandleSelAutoclamp; + else if (color_id == 10) finalColor = colorNurbUline; + else if (color_id == 11) finalColor = colorNurbSelUline; + else finalColor = colorVertexSelect; + + gl_Position = v1; + EmitVertex(); + + gl_Position = v2; + EmitVertex(); + + EndPrimitive(); +} diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl new file mode 100644 index 00000000000..9150ef8cd63 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl @@ -0,0 +1,39 @@ + +/* Draw Curve Vertices */ + +uniform mat4 ModelViewProjectionMatrix; +uniform vec2 viewportSize; + +in vec3 pos; +in int data; + +/* these are the same for all vertices + * and does not need interpolation */ +flat out int vertFlag; +flat out int clipCase; + +/* See fragment shader */ +noperspective out vec4 eData1; +flat out vec4 eData2; + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +void main() +{ + clipCase = 0; + + vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + + /* only vertex position 0 is used */ + eData1 = eData2 = vec4(1e10); + eData2.zw = proj(pPos); + + vertFlag = data; + + gl_Position = pPos; + gl_PointSize = sizeVertex; +} diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl new file mode 100644 index 00000000000..e78462b6915 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_frag.glsl @@ -0,0 +1,22 @@ + +flat in int vertFlag; + +#define VERTEX_SELECTED (1 << 0) +#define VERTEX_ACTIVE (1 << 1) + +out vec4 FragColor; + +void main() +{ + /* TODO: vertex size */ + + if ((vertFlag & VERTEX_SELECTED) != 0) { + FragColor = colorVertexSelect; + } + else if ((vertFlag & VERTEX_ACTIVE) != 0) { + FragColor = colorEditMeshActive; + } + else { + FragColor = colorVertex; + } +} diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl new file mode 100644 index 00000000000..0cbc66a2b1f --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl @@ -0,0 +1,39 @@ + +/* Draw Lattice Vertices */ + +uniform mat4 ModelViewProjectionMatrix; +uniform vec2 viewportSize; + +in vec3 pos; +in int data; + +/* these are the same for all vertices + * and does not need interpolation */ +flat out int vertFlag; +flat out int clipCase; + +/* See fragment shader */ +noperspective out vec4 eData1; +flat out vec4 eData2; + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +void main() +{ + clipCase = 0; + + vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + + /* only vertex position 0 is used */ + eData1 = eData2 = vec4(1e10); + eData2.zw = proj(pPos); + + vertFlag = data; + + gl_PointSize = sizeVertex; + gl_Position = pPos; +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl new file mode 100644 index 00000000000..07b36079884 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_frag.glsl @@ -0,0 +1,19 @@ + +flat in int isSelected; +#ifdef VERTEX_FACING +flat in float facing; +#endif + +out vec4 FragColor; + +void main() +{ + if (isSelected != 0) + FragColor = colorFaceDot; + else + FragColor = colorWireEdit; + +#ifdef VERTEX_FACING + FragColor.a *= 1.0 - abs(facing) * 0.4; +#endif +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl new file mode 100644 index 00000000000..fa3934c4b77 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facedot_vert.glsl @@ -0,0 +1,31 @@ + +uniform mat4 ModelViewProjectionMatrix; + +in vec3 pos; +in vec4 norAndFlag; + +flat out int isSelected; + +#ifdef VERTEX_FACING +uniform mat4 ProjectionMatrix; +uniform mat4 ModelViewMatrix; +uniform mat3 NormalMatrix; + +flat out float facing; +#endif + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + /* Bias Facedot Z position in clipspace. */ + gl_Position.z -= 0.0002; + gl_PointSize = sizeFaceDot; + isSelected = int(norAndFlag.w); +#ifdef VERTEX_FACING + vec3 view_normal = normalize(NormalMatrix * norAndFlag.xyz); + vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) + ? normalize((ModelViewMatrix * vec4(pos, 1.0)).xyz) + : vec3(0.0, 0.0, 1.0); + facing = dot(view_vec, view_normal); +#endif +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl new file mode 100644 index 00000000000..23b794d9b8b --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl @@ -0,0 +1,29 @@ + +/* Solid Wirefram implementation + * Mike Erwin, Clément Foucault */ + +/* This shader follows the principles of + * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ + +flat in vec4 faceColor; +flat in int faceActive; + +out vec4 FragColor; + +const vec4 stipple_matrix[4] = vec4[4]( + vec4(1.0, 0.0, 0.0, 0.0), + vec4(0.0, 0.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 0.0) +); + +void main() +{ + FragColor = faceColor; + + if (faceActive == 1) { + int x = int(gl_FragCoord.x) & 0x3; /* mod 4 */ + int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */ + FragColor *= stipple_matrix[x][y]; + } +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl new file mode 100644 index 00000000000..3b9aa77306f --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl @@ -0,0 +1,29 @@ + +uniform mat4 ModelViewProjectionMatrix; + +in vec3 pos; +in ivec4 data; + +flat out vec4 faceColor; +flat out int faceActive; + +#define FACE_ACTIVE (1 << 2) +#define FACE_SELECTED (1 << 3) + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + + if ((data.x & FACE_ACTIVE) != 0) { + faceColor = colorEditMeshActive; + faceActive = 1; + } + else if ((data.x & FACE_SELECTED) != 0) { + faceColor = colorFaceSelect; + faceActive = 0; + } + else { + faceColor = colorFace; + faceActive = 0; + } +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl new file mode 100644 index 00000000000..cf1051b70b3 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl @@ -0,0 +1,212 @@ + +/* Solid Wirefram implementation + * Mike Erwin, Clément Foucault */ + +/* This shader follows the principles of + * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ + +/* This is not perfect. Only a subset of intel gpus are affected. + * This fix have some performance impact. + * TODO Refine the range to only affect GPUs. */ + +uniform float faceAlphaMod; + +flat in vec3 edgesCrease; +flat in vec3 edgesBweight; +flat in vec4 faceColor; +flat in ivec3 flag; +flat in int clipCase; +#ifdef VERTEX_SELECTION +in vec3 vertexColor; +#endif +#ifdef VERTEX_FACING +in float facing; +#endif + +/* We use a vec4[2] interface to pass edge data + * (without fragmenting memory accesses) + * + * There are 2 cases : + * + * - Simple case : geometry shader return edge distances + * in the first 2 components of the first vec4. + * This needs noperspective interpolation. + * The rest is filled with vertex screen positions. + * eData2[0] actually contain v2 + * eData2[1] actually contain v1 + * eData2[2] actually contain v0 + * + * - Hard case : two 2d edge corner are described by each + * vec4 as origin and direction. This is constant over + * the triangle and use to detect the correct case. */ + +noperspective in vec2 eData1; +flat in vec2 eData2[3]; + +out vec4 FragColor; + +#define EDGE_EXISTS (1 << 0) +#define EDGE_ACTIVE (1 << 1) +#define EDGE_SELECTED (1 << 2) +#define EDGE_SEAM (1 << 3) +#define EDGE_SHARP (1 << 4) +/* Vertex flag is shifted and combined with the edge flag */ +#define VERTEX_ACTIVE (1 << (0 + 8)) +#define VERTEX_SELECTED (1 << (1 + 8)) +#define FACE_ACTIVE (1 << (2 + 8)) + +/* Style Parameters in pixel */ + +/* Array to retrieve vert/edge indices */ +const ivec3 clipEdgeIdx[6] = ivec3[6]( + ivec3(1, 0, 2), + ivec3(2, 0, 1), + ivec3(2, 1, 0), + ivec3(2, 1, 0), + ivec3(2, 0, 1), + ivec3(1, 0, 2) +); + +const ivec3 clipPointIdx[6] = ivec3[6]( + ivec3(0, 1, 2), + ivec3(0, 2, 1), + ivec3(0, 2, 1), + ivec3(1, 2, 0), + ivec3(1, 2, 0), + ivec3(2, 1, 0) +); + +const vec4 stipple_matrix[4] = vec4[4]( + vec4(1.0, 0.0, 0.0, 0.0), + vec4(0.0, 0.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 0.0) +); + +void colorDist(vec4 color, float dist) +{ + FragColor = (dist < 0) ? color : FragColor; +} + +float distToEdge(vec2 o, vec2 dir) +{ + vec2 af = gl_FragCoord.xy - o; + float daf = dot(dir, af); + return sqrt(abs(dot(af, af) - daf * daf)); +} + +#ifdef ANTI_ALIASING +void colorDistEdge(vec4 color, float dist) +{ + FragColor = mix(color, FragColor, clamp(dist, 0.0, 1.0)); +} +#else +#define colorDistEdge colorDist +#endif + +void main() +{ + vec3 e, p; + + /* Step 1 : Computing Distances */ + + if (clipCase == 0) { + e.xy = eData1; + + /* computing missing distance */ + vec2 dir = normalize(eData2[2] - eData2[1]); + e.z = distToEdge(eData2[2], dir); + + p.x = distance(eData2[2], gl_FragCoord.xy); + p.y = distance(eData2[1], gl_FragCoord.xy); + p.z = distance(eData2[0], gl_FragCoord.xy); + } + else { + ivec3 eidxs = clipEdgeIdx[clipCase - 1]; + ivec3 pidxs = clipPointIdx[clipCase - 1]; + + e[eidxs.x] = distToEdge(eData1, eData2[0]); + e[eidxs.y] = distToEdge(eData2[1], eData2[2]); + + /* Three edges visible cases */ + if (clipCase == 1 || clipCase == 2 || clipCase == 4) { + e[eidxs.z] = distToEdge(eData1, normalize(eData2[1] - eData1)); + p[pidxs.y] = distance(eData2[1], gl_FragCoord.xy); + } + else { + e[eidxs.z] = 1e10; /* off screen */ + p[pidxs.y] = 1e10; /* off screen */ + } + + p[pidxs.x] = distance(eData1, gl_FragCoord.xy); + p[pidxs.z] = 1e10; /* off screen */ + } + + /* Step 2 : coloring (order dependant) */ + + /* First */ + FragColor = faceColor; + + if ((flag[0] & FACE_ACTIVE) != 0) { + int x = int(gl_FragCoord.x) & 0x3; /* mod 4 */ + int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */ + FragColor *= stipple_matrix[x][y]; + } + else { + FragColor.a *= faceAlphaMod; + } + + /* Edges */ + for (int v = 0; v < 3; ++v) { + if ((flag[v] & EDGE_EXISTS) != 0) { + /* Outer large edge */ + float largeEdge = e[v] - sizeEdge * 3.0; + + vec4 large_edge_color = vec4(0.0); + large_edge_color = ((flag[v] & EDGE_SHARP) != 0) ? colorEdgeSharp : large_edge_color; + large_edge_color = (edgesCrease[v] > 0.0) ? vec4(colorEdgeCrease.rgb, edgesCrease[v]) : large_edge_color; + large_edge_color = (edgesBweight[v] > 0.0) ? vec4(colorEdgeBWeight.rgb, edgesBweight[v]) : large_edge_color; + large_edge_color = ((flag[v] & EDGE_SEAM) != 0) ? colorEdgeSeam : large_edge_color; + + if (large_edge_color.a != 0.0) { + colorDistEdge(large_edge_color, largeEdge); + } + + /* Inner thin edge */ + float innerEdge = e[v] - sizeEdge; +#ifdef ANTI_ALIASING + innerEdge += 0.125; +#endif + +#ifdef VERTEX_SELECTION + colorDistEdge(vec4(vertexColor, 1.0), innerEdge); +#else + vec4 inner_edge_color = colorWireEdit; + inner_edge_color = ((flag[v] & EDGE_SELECTED) != 0) ? colorEdgeSelect : inner_edge_color; + inner_edge_color = ((flag[v] & EDGE_ACTIVE) != 0) ? vec4(colorEditMeshActive.xyz, 1.0) : inner_edge_color; + + colorDistEdge(inner_edge_color, innerEdge); +#endif + } + } + + /* Points */ +#ifdef VERTEX_SELECTION + for (int v = 0; v < 3; ++v) { + float size = p[v] - sizeVertex; + + vec4 point_color = colorVertex; + point_color = ((flag[v] & VERTEX_SELECTED) != 0) ? colorVertexSelect : point_color; + point_color = ((flag[v] & VERTEX_ACTIVE) != 0) ? vec4(colorEditMeshActive.xyz, 1.0) : point_color; + + colorDist(point_color, size); + } +#endif + +#ifdef VERTEX_FACING + FragColor.a *= 1.0 - abs(facing) * 0.4; +#endif + + /* don't write depth if not opaque */ + if (FragColor.a == 0.0) discard; +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl new file mode 100644 index 00000000000..77bc8a25695 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl @@ -0,0 +1,154 @@ + +/* Solid Wirefram implementation + * Mike Erwin, Clément Foucault */ + +/* This shader follows the principles of + * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ + +layout(lines) in; +layout(triangle_strip, max_vertices=6) out; + +uniform mat4 ProjectionMatrix; +uniform vec2 viewportSize; + +in vec4 vPos[]; +in vec4 pPos[]; +in ivec4 vData[]; +#ifdef VERTEX_FACING +in float vFacing[]; +#endif + +/* these are the same for all vertices + * and does not need interpolation */ +flat out vec3 edgesCrease; +flat out vec3 edgesBweight; +flat out vec4 faceColor; +flat out ivec3 flag; +flat out int clipCase; +#ifdef VERTEX_SELECTION +out vec3 vertexColor; +#endif +#ifdef VERTEX_FACING +out float facing; +#endif + +/* See fragment shader */ +noperspective out vec2 eData1; +flat out vec2 eData2[3]; + +#define VERTEX_ACTIVE (1 << 0) +#define VERTEX_SELECTED (1 << 1) + +#define FACE_ACTIVE (1 << 2) +#define FACE_SELECTED (1 << 3) + +/* Table 1. Triangle Projection Cases */ +const ivec4 clipPointsIdx[6] = ivec4[6]( + ivec4(0, 1, 2, 2), + ivec4(0, 2, 1, 1), + ivec4(0, 0, 1, 2), + ivec4(1, 2, 0, 0), + ivec4(1, 1, 0, 2), + ivec4(2, 2, 0, 1) +); + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +float dist(vec2 pos[3], vec2 vpos, int v) +{ + /* endpoints of opposite edge */ + vec2 e1 = pos[(v + 1) % 3]; + vec2 e2 = pos[(v + 2) % 3]; + /* Edge normalized vector */ + vec2 dir = normalize(e2 - e1); + /* perpendicular to dir */ + vec2 orthogonal = vec2(-dir.y, dir.x); + + return abs(dot(vpos - e1, orthogonal)); +} + +vec3 getVertexColor(int v) +{ + if ((vData[v].x & (VERTEX_ACTIVE | VERTEX_SELECTED)) != 0) + return colorEdgeSelect.rgb; + else + return colorWireEdit.rgb; +} + +void doVertex(int v, vec4 pos) +{ +#ifdef VERTEX_SELECTION + vertexColor = getVertexColor(v); +#endif + +#ifdef VERTEX_FACING + facing = vFacing[v]; +#endif + + gl_Position = pos; + + EmitVertex(); +} + +void main() +{ + clipCase = 0; + + /* Face */ + faceColor = vec4(0.0); + + /* Proj Vertex */ + vec2 pos[2] = vec2[2](proj(pPos[0]), proj(pPos[1])); + + /* little optimization use a vec4 to vectorize + * following operations */ + vec4 dirs1, dirs2; + + /* Edge normalized vector */ + dirs1.xy = normalize(pos[1] - pos[0]); + + /* perpendicular to dir */ + dirs1.zw = vec2(-dirs1.y, dirs1.x); + + /* Make it view independent */ + dirs1 *= sizeEdgeFix / viewportSize.xyxy; + + dirs2 = dirs1; + + /* Perspective */ + if (ProjectionMatrix[3][3] == 0.0) { + /* vPos[i].z is negative and we don't want + * our fixvec to be flipped */ + dirs1 *= -vPos[0].z; + dirs2 *= -vPos[1].z; + } + + /* Edge / Vert data */ + eData1 = vec2(1e10); + eData2[0] = vec2(1e10); + eData2[2] = pos[0]; + eData2[1] = pos[1]; + flag[0] = (vData[0].x << 8); + flag[1] = (vData[1].x << 8); + flag[2] = 0; + + doVertex(0, pPos[0] + vec4(-dirs1.xy, 0.0, 0.0)); + doVertex(0, pPos[0] + vec4( dirs1.zw, 0.0, 0.0)); + doVertex(0, pPos[0] + vec4(-dirs1.zw, 0.0, 0.0)); + + flag[2] = vData[0].y | (vData[0].x << 8); + edgesCrease[2] = vData[0].z / 255.0; + edgesBweight[2] = vData[0].w / 255.0; + + doVertex(1, pPos[1] + vec4( dirs2.zw, 0.0, 0.0)); + doVertex(1, pPos[1] + vec4(-dirs2.zw, 0.0, 0.0)); + + flag[2] = 0; + doVertex(1, pPos[1] + vec4( dirs2.xy, 0.0, 0.0)); + + EndPrimitive(); +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl new file mode 100644 index 00000000000..d9c902697b6 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl @@ -0,0 +1,307 @@ + +/* Solid Wirefram implementation + * Mike Erwin, Clément Foucault */ + +/* This shader follows the principles of + * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ + +layout(triangles) in; + +/* This is not perfect. Only a subset of intel gpus are affected. + * This fix have some performance impact. + * TODO Refine the range to only affect GPUs. */ + +#ifdef EDGE_FIX +/* To fix the edge artifacts, we render + * an outline strip around the screenspace + * triangle. Order is important. + * TODO diagram + */ + +#ifdef VERTEX_SELECTION +layout(triangle_strip, max_vertices=23) out; +#else +layout(triangle_strip, max_vertices=17) out; +#endif +#else +layout(triangle_strip, max_vertices=3) out; +#endif + +uniform mat4 ProjectionMatrix; +uniform vec2 viewportSize; + +in vec4 vPos[]; +in vec4 pPos[]; +in ivec4 vData[]; +#ifdef VERTEX_FACING +in float vFacing[]; +#endif + +/* these are the same for all vertices + * and does not need interpolation */ +flat out vec3 edgesCrease; +flat out vec3 edgesBweight; +flat out vec4 faceColor; +flat out ivec3 flag; +flat out int clipCase; +#ifdef VERTEX_SELECTION +out vec3 vertexColor; +#endif +#ifdef VERTEX_FACING +out float facing; +#endif + +/* See fragment shader */ +noperspective out vec2 eData1; +flat out vec2 eData2[3]; + +#define VERTEX_ACTIVE (1 << 0) +#define VERTEX_SELECTED (1 << 1) + +#define FACE_ACTIVE (1 << 2) +#define FACE_SELECTED (1 << 3) + +/* Table 1. Triangle Projection Cases */ +const ivec4 clipPointsIdx[6] = ivec4[6]( + ivec4(0, 1, 2, 2), + ivec4(0, 2, 1, 1), + ivec4(0, 0, 1, 2), + ivec4(1, 2, 0, 0), + ivec4(1, 1, 0, 2), + ivec4(2, 2, 0, 1) +); + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +float dist(vec2 pos[3], vec2 vpos, int v) +{ + /* endpoints of opposite edge */ + vec2 e1 = pos[(v + 1) % 3]; + vec2 e2 = pos[(v + 2) % 3]; + /* Edge normalized vector */ + vec2 dir = normalize(e2 - e1); + /* perpendicular to dir */ + vec2 orthogonal = vec2(-dir.y, dir.x); + + return abs(dot(vpos - e1, orthogonal)); +} + +vec3 getVertexColor(int v) +{ + if ((vData[v].x & (VERTEX_ACTIVE | VERTEX_SELECTED)) != 0) + return colorEdgeSelect.rgb; + else + return colorWireEdit.rgb; +} + +vec4 getClipData(vec2 pos[3], ivec2 vidx) +{ + vec2 A = pos[vidx.x]; + vec2 Adir = normalize(A - pos[vidx.y]); + + return vec4(A, Adir); +} + +void doVertex(int v) +{ +#ifdef VERTEX_SELECTION + vertexColor = getVertexColor(v); +#endif + +#ifdef VERTEX_FACING + facing = vFacing[v]; +#endif + + gl_Position = pPos[v]; + + EmitVertex(); +} + +void doLoopStrip(int v, vec3 offset) +{ + doVertex(v); + + gl_Position.xyz += offset; + + EmitVertex(); +} + +#ifdef ANTI_ALIASING +#define Z_OFFSET 0.008 +#else +#define Z_OFFSET 0.0 +#endif + +void main() +{ + /* First we detect which case we are in */ + clipCase = 0; + + /* if perspective */ + if (ProjectionMatrix[3][3] == 0.0) { + /* See Table 1. Triangle Projection Cases */ + clipCase += int(pPos[0].z / pPos[0].w < -1 || vPos[0].z > 0.0) * 4; + clipCase += int(pPos[1].z / pPos[1].w < -1 || vPos[1].z > 0.0) * 2; + clipCase += int(pPos[2].z / pPos[2].w < -1 || vPos[2].z > 0.0) * 1; + } + + /* If triangle is behind nearplane, early out */ + if (clipCase == 7) + return; + + /* Edge */ + ivec3 eflag; vec3 ecrease, ebweight; + for (int v = 0; v < 3; ++v) { + flag[v] = eflag[v] = vData[v].y | (vData[v].x << 8); + edgesCrease[v] = ecrease[v] = vData[v].z / 255.0; + edgesBweight[v] = ebweight[v] = vData[v].w / 255.0; + } + + /* Face */ + if ((vData[0].x & FACE_ACTIVE) != 0) + faceColor = colorEditMeshActive; + else if ((vData[0].x & FACE_SELECTED) != 0) + faceColor = colorFaceSelect; + else + faceColor = colorFace; + + /* Vertex */ + vec2 pos[3] = vec2[3](proj(pPos[0]), proj(pPos[1]), proj(pPos[2])); + + /* Simple case : compute edge distances in geometry shader */ + if (clipCase == 0) { + + /* Packing screen positions and 2 distances */ + eData2[0] = pos[2]; + eData2[1] = pos[1]; + eData2[2] = pos[0]; + + /* Only pass the first 2 distances */ + for (int v = 0; v < 2; ++v) { + eData1[v] = dist(pos, pos[v], v); + doVertex(v); + eData1[v] = 0.0; + } + + /* and the last vertex */ + doVertex(2); + +#ifdef EDGE_FIX + vec2 fixvec[6]; + vec2 fixvecaf[6]; + vec2 cornervec[3]; + + /* This fix the case when 2 vertices are perfectly aligned + * and corner vectors have nowhere to go. + * ie: length(cornervec[i]) == 0 */ + const float epsilon = 1e-2; /* in pixel so not that much */ + const vec2 bias[3] = vec2[3]( + vec2( epsilon, epsilon), + vec2(-epsilon, epsilon), + vec2( 0.0, -epsilon) + ); + + for (int i = 0; i < 3; ++i) { + int i1 = (i + 1) % 3; + int i2 = (i + 2) % 3; + + vec2 v1 = pos[i] + bias[i]; + vec2 v2 = pos[i1] + bias[i1]; + vec2 v3 = pos[i2] + bias[i2]; + + /* Edge normalized vector */ + vec2 dir = normalize(v2 - v1); + vec2 dir2 = normalize(v3 - v1); + + cornervec[i] = -normalize(dir + dir2); + + /* perpendicular to dir */ + vec2 perp = vec2(-dir.y, dir.x); + + /* Backface case */ + if (dot(perp, dir2) > 0) { + perp = -perp; + } + + /* Make it view independent */ + perp *= sizeEdgeFix / viewportSize; + cornervec[i] *= sizeEdgeFix / viewportSize; + fixvec[i] = fixvecaf[i] = perp; + + /* Perspective */ + if (ProjectionMatrix[3][3] == 0.0) { + /* vPos[i].z is negative and we don't want + * our fixvec to be flipped */ + fixvec[i] *= -vPos[i].z; + fixvecaf[i] *= -vPos[i1].z; + cornervec[i] *= -vPos[i].z; + } + } + + /* to not let face color bleed */ + faceColor.a = 0.0; + + /* we don't want other edges : make them far */ + eData1 = vec2(1e10); + eData2[0] = vec2(1e10); + + /* Start with the same last vertex to create a + * degenerate triangle in order to "create" + * a new triangle strip */ + for (int i = 2; i < 5; ++i) { + int vbe = (i - 1) % 3; + int vaf = (i + 1) % 3; + int v = i % 3; + + /* Position of the "hidden" third vertex */ + eData2[0] = pos[vbe]; + doLoopStrip(v, vec3(fixvec[v], Z_OFFSET)); + + /* Now one triangle only shade one edge + * so we use the edge distance calculated + * in the fragment shader, the third edge; + * we do this because we need flat interp to + * draw a continuous triangle strip */ + eData2[1] = pos[vaf]; + eData2[2] = pos[v]; + flag[0] = (vData[v].x << 8); + flag[1] = (vData[vaf].x << 8); + flag[2] = eflag[vbe]; + edgesCrease[2] = ecrease[vbe]; + edgesBweight[2] = ebweight[vbe]; + + doLoopStrip(vaf, vec3(fixvecaf[v], Z_OFFSET)); + + /* corner vertices should not draw edges but draw point only */ + flag[2] = (vData[vbe].x << 8); +#ifdef VERTEX_SELECTION + doLoopStrip(vaf, vec3(cornervec[vaf], Z_OFFSET)); +#endif + } + + /* finish the loop strip */ + doLoopStrip(2, vec3(fixvec[2], Z_OFFSET)); +#endif + } + /* Harder case : compute visible edges vectors */ + else { + ivec4 vindices = clipPointsIdx[clipCase - 1]; + + vec4 tmp; + tmp = getClipData(pos, vindices.xz); + eData1 = tmp.xy; + eData2[0] = tmp.zw; + tmp = getClipData(pos, vindices.yw); + eData2[1] = tmp.xy; + eData2[2] = tmp.zw; + + for (int v = 0; v < 3; ++v) + doVertex(v); + } + + EndPrimitive(); +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl new file mode 100644 index 00000000000..53e5b09cb70 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl @@ -0,0 +1,61 @@ + +/* Solid Wirefram implementation + * Mike Erwin, Clément Foucault */ + +/* This shader follows the principles of + * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ + +uniform mat4 ModelViewProjectionMatrix; +uniform vec2 viewportSize; + +in vec3 pos; +in ivec4 data; + +/* these are the same for all vertices + * and does not need interpolation */ +flat out vec3 edgesCrease; +flat out vec3 edgesBweight; +flat out vec4 faceColor; +flat out ivec3 flag; +flat out int clipCase; +#ifdef VERTEX_SELECTION +out vec3 vertexColor; +#endif + +/* See fragment shader */ +noperspective out vec2 eData1; +flat out vec2 eData2[3]; + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +void main() +{ + clipCase = 0; + edgesCrease = vec3(0.0); + edgesBweight = vec3(0.0); + + vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + + /* there is no face */ + faceColor = vec4(0.0); + +#ifdef VERTEX_SELECTION + vertexColor = vec3(0.0); +#endif + + /* only vertex position 0 is used */ + eData1 = vec2(1e10); + eData2[0] = vec2(1e10); + eData2[1] = vec2(1e10); + eData2[2] = proj(pPos); + + flag[0] = (data.x << 8); + flag[1] = flag[2] = 0; + + gl_PointSize = sizeEdgeFix; + gl_Position = pPos; +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl new file mode 100644 index 00000000000..8f94a105332 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_mix_frag.glsl @@ -0,0 +1,22 @@ + +out vec4 FragColor; + +uniform sampler2D wireColor; +uniform sampler2D wireDepth; +uniform sampler2D sceneDepth; +uniform float alpha; + +void main() +{ + ivec2 uv = ivec2(gl_FragCoord.xy); + float wire_depth = texelFetch(wireDepth, uv, 0).r; + float scene_depth = texelFetch(sceneDepth, uv, 0).r; + vec4 wire_color = texelFetch(wireColor, uv, 0).rgba; + + FragColor = wire_color; + + /* Modulate alpha if occluded */ + if (wire_depth > scene_depth) { + FragColor.a *= alpha; + } +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl new file mode 100644 index 00000000000..8ebfa4376f0 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl @@ -0,0 +1,38 @@ + +/* Solid Wirefram implementation + * Mike Erwin, Clément Foucault */ + +/* This shader follows the principles of + * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ + +uniform mat4 ModelViewMatrix; +uniform mat4 ModelViewProjectionMatrix; + +in vec3 pos; +in ivec4 data; + +out vec4 vPos; +out vec4 pPos; +out ivec4 vData; + +#ifdef VERTEX_FACING +uniform mat4 ProjectionMatrix; +uniform mat3 NormalMatrix; + +in vec3 vnor; +out float vFacing; +#endif + +void main() +{ + vPos = ModelViewMatrix * vec4(pos, 1.0); + pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + vData = data; +#ifdef VERTEX_FACING + vec3 view_normal = normalize(NormalMatrix * vnor); + vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) + ? normalize(vPos.xyz) + : vec3(0.0, 0.0, 1.0); + vFacing = dot(view_vec, view_normal); +#endif +} diff --git a/source/blender/draw/modes/shaders/edit_normals_geom.glsl b/source/blender/draw/modes/shaders/edit_normals_geom.glsl new file mode 100644 index 00000000000..d17823f2f5a --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_normals_geom.glsl @@ -0,0 +1,15 @@ + +layout(points) in; +layout(line_strip, max_vertices=2) out; + +flat in vec4 v1[1]; +flat in vec4 v2[1]; + +void main() +{ + gl_Position = v1[0]; + EmitVertex(); + gl_Position = v2[0]; + EmitVertex(); + EndPrimitive(); +} diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl new file mode 100644 index 00000000000..3ce7e618511 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl @@ -0,0 +1,30 @@ + +uniform mat4 ModelViewProjectionMatrix; +uniform mat3 NormalMatrix; +uniform mat4 ProjectionMatrix; +uniform float normalSize; + +in vec3 pos; + +#ifdef LOOP_NORMALS +in vec3 lnor; +#define nor lnor + +#elif defined(FACE_NORMALS) +in vec4 norAndFlag; +#define nor norAndFlag.xyz +#else + +in vec3 vnor; +#define nor vnor +#endif + +flat out vec4 v1; +flat out vec4 v2; + +void main() +{ + v1 = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 n = normalize(NormalMatrix * nor); /* viewspace */ + v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0); +} diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl new file mode 100644 index 00000000000..eab107354d1 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl @@ -0,0 +1,21 @@ + +flat in vec4 finalColor; + +#ifndef USE_WIRE +in vec2 texCoord_interp; +#endif + +out vec4 fragColor; + +#ifndef USE_WIRE +uniform sampler2D image; +#endif + +void main() +{ +#ifdef USE_WIRE + fragColor = finalColor; +#else + fragColor = finalColor * texture(image, texCoord_interp); +#endif +} diff --git a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl new file mode 100644 index 00000000000..c629fdcb7ef --- /dev/null +++ b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl @@ -0,0 +1,38 @@ + +uniform mat4 ViewProjectionMatrix; +uniform vec2 aspect; + +/* ---- Instanciated Attribs ---- */ +in vec2 texCoord; +in vec2 pos; +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; + +#ifdef USE_WIRE +in vec3 color; +#else +in vec4 objectColor; +#endif + +in float size; +in vec2 offset; + +flat out vec4 finalColor; + +#ifndef USE_WIRE +out vec2 texCoord_interp; +#endif + +void main() +{ + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4( + (pos[0] + offset[0]) * (size * aspect[0]), + (pos[1] + offset[1]) * (size * aspect[1]), + 0.0, 1.0); +#ifdef USE_WIRE + finalColor = vec4(color, 1.0); +#else + texCoord_interp = texCoord; + finalColor = objectColor; +#endif +} diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl new file mode 100644 index 00000000000..2b04bb0d855 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -0,0 +1,227 @@ + +/* Infinite grid + * Clément Foucault */ + +out vec4 FragColor; + +uniform mat4 ProjectionMatrix; +uniform vec3 cameraPos; +uniform vec3 planeNormal; +uniform vec3 planeAxes; +uniform vec3 eye; +uniform vec4 gridSettings; +uniform vec2 viewportSize; +uniform vec4 screenvecs[3]; +uniform float gridOneOverLogSubdiv; +uniform sampler2D depthBuffer; + +#define gridDistance gridSettings.x +#define gridResolution gridSettings.y +#define gridScale gridSettings.z +#define gridSubdiv gridSettings.w + +uniform int gridFlag; + +#define AXIS_X (1 << 0) +#define AXIS_Y (1 << 1) +#define AXIS_Z (1 << 2) +#define GRID (1 << 3) +#define PLANE_XY (1 << 4) +#define PLANE_XZ (1 << 5) +#define PLANE_YZ (1 << 6) +#define GRID_BACK (1 << 9) /* grid is behind objects */ + +#define GRID_LINE_SMOOTH 1.15 + +float get_grid(vec2 co, vec2 fwidthCos, float grid_size) +{ + float half_size = grid_size / 2.0; + /* triangular wave pattern, amplitude is [0, half_size] */ + vec2 grid_domain = abs(mod(co + half_size, grid_size) - half_size); + /* modulate by the absolute rate of change of the coordinates + * (make lines have the same width under perspective) */ + grid_domain /= fwidthCos; + + /* collapse waves and normalize */ + grid_domain.x = min(grid_domain.x, grid_domain.y) / half_size; + + return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x * 0.5); +} + +vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size) +{ + vec3 axes_domain = abs(co); + /* modulate by the absolute rate of change of the coordinates + * (make line have the same width under perspective) */ + axes_domain /= fwidthCos; + + return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH, axes_domain - line_size); +} + +vec3 get_floor_pos(vec2 uv, out vec3 wPos) +{ + vec3 camera_vec, camera_pos, corner_pos; + vec3 floored_pos = planeAxes * floor(screenvecs[2].xyz); + corner_pos = screenvecs[2].xyz - floored_pos; + + vec3 pixel_pos = corner_pos + uv.x * screenvecs[0].xyz + uv.y * screenvecs[1].xyz; + + /* if perspective */ + if (ProjectionMatrix[3][3] == 0.0) { + camera_pos = cameraPos - floored_pos; + camera_vec = normalize(pixel_pos - camera_pos); + } + else { + camera_pos = pixel_pos; + camera_vec = normalize(eye); + } + + float plane_normal_dot_camera_vec = dot(planeNormal, camera_vec); + float p = -dot(planeNormal, camera_pos); + if (plane_normal_dot_camera_vec != 0) { + p /= plane_normal_dot_camera_vec; + } + vec3 plane = camera_pos + camera_vec * p; + + /* fix residual imprecision */ + plane *= planeAxes; + + /* Recover non-offseted world position */ + wPos = plane + floored_pos; + + return plane; +} + +void main() +{ + vec2 sPos = gl_FragCoord.xy / viewportSize; /* Screen [0,1] position */ + + /* To reduce artifacts, use a local version of the positions + * to compute derivatives since they are not position dependant. + * This gets rid of the blocky artifacts. Unfortunately we still + * need the world position for the grid to scale properly from the origin. */ + vec3 gPos, wPos; /* Grid pos., World pos. */ + gPos = get_floor_pos(sPos, wPos); + + vec3 fwidthPos = fwidth(gPos); + + float dist, fade; + /* if persp */ + if (ProjectionMatrix[3][3] == 0.0) { + vec3 viewvec = cameraPos - wPos; + dist = length(viewvec); + viewvec /= dist; + + float angle; + if ((gridFlag & PLANE_XZ) > 0) + angle = viewvec.y; + else if ((gridFlag & PLANE_YZ) > 0) + angle = viewvec.x; + else + angle = viewvec.z; + + angle = 1.0 - abs(angle); + angle *= angle; + fade = 1.0 - angle * angle; + fade *= 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance); + } + else { + dist = abs(gl_FragCoord.z * 2.0 - 1.0); + fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5); + dist = 1.0; /* avoid branch after */ + + if ((gridFlag & PLANE_XY) > 0) { + float angle = 1.0 - abs(eye.z); + dist = 1.0 + angle * 2.0; + angle *= angle; + fade *= 1.0 - angle * angle; + } + } + + if ((gridFlag & GRID) > 0) { + float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv; + + float blend = fract(-max(grid_res, 0.0)); + float lvl = floor(grid_res); + + /* from biggest to smallest */ + float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0)); + float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0)); + float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0)); + + vec2 grid_pos, grid_fwidth; + if ((gridFlag & PLANE_XZ) > 0) { + grid_pos = wPos.xz; + grid_fwidth = fwidthPos.xz; + } + else if ((gridFlag & PLANE_YZ) > 0) { + grid_pos = wPos.yz; + grid_fwidth = fwidthPos.yz; + } + else { + grid_pos = wPos.xy; + grid_fwidth = fwidthPos.xy; + } + + float gridA = get_grid(grid_pos, grid_fwidth, scaleA); + float gridB = get_grid(grid_pos, grid_fwidth, scaleB); + float gridC = get_grid(grid_pos, grid_fwidth, scaleC); + + FragColor = vec4(colorGrid.rgb, gridA * blend); + FragColor = mix(FragColor, vec4(mix(colorGrid.rgb, colorGridEmphasise.rgb, blend), 1.0), gridB); + FragColor = mix(FragColor, vec4(colorGridEmphasise.rgb, 1.0), gridC); + } + else { + FragColor = vec4(colorGrid.rgb, 0.0); + } + + if ((gridFlag & (AXIS_X | AXIS_Y | AXIS_Z)) > 0) { + /* Setup axes 'domains' */ + vec3 axes_dist, axes_fwidth; + + if ((gridFlag & AXIS_X) > 0) { + axes_dist.x = dot(wPos.yz, planeAxes.yz); + axes_fwidth.x = dot(fwidthPos.yz, planeAxes.yz); + } + if ((gridFlag & AXIS_Y) > 0) { + axes_dist.y = dot(wPos.xz, planeAxes.xz); + axes_fwidth.y = dot(fwidthPos.xz, planeAxes.xz); + } + if ((gridFlag & AXIS_Z) > 0) { + axes_dist.z = dot(wPos.xy, planeAxes.xy); + axes_fwidth.z = dot(fwidthPos.xy, planeAxes.xy); + } + + /* Computing all axes at once using vec3 */ + vec3 axes = get_axes(axes_dist, axes_fwidth, 0.1); + + if ((gridFlag & AXIS_X) > 0) { + FragColor = mix(FragColor, colorGridAxisX, axes.x); + } + if ((gridFlag & AXIS_Y) > 0) { + FragColor = mix(FragColor, colorGridAxisY, axes.y); + } + if ((gridFlag & AXIS_Z) > 0) { + FragColor = mix(FragColor, colorGridAxisZ, axes.z); + } + } + + float scene_depth = texture(depthBuffer, sPos).r; + if ((gridFlag & GRID_BACK) > 0) { + fade *= (scene_depth == 1.0) ? 1.0 : 0.0; + } + else { + /* Manual, non hard, depth test: + * Progressively fade the grid below occluders + * (avoids poping visuals due to depth buffer precision) */ + /* Add a small bias so the grid will always + * be on top of a mesh with the same depth. */ + float grid_depth = gl_FragCoord.z - 1e-8; + /* Harder settings tend to flicker more, + * but have less "see through" appearance. */ + const float test_hardness = 1e4; + fade *= 1.0 - clamp((grid_depth - scene_depth) * test_hardness, 0.0, 1.0); + } + + FragColor.a *= fade; +} diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl new file mode 100644 index 00000000000..3f99d8b5d0a --- /dev/null +++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl @@ -0,0 +1,63 @@ + +/* Infinite grid + * Clément Foucault */ + +uniform mat4 ViewProjectionMatrix; +uniform mat4 ProjectionMatrix; +uniform vec3 cameraPos; +uniform vec4 gridSettings; + +#define gridDistance gridSettings.x +#define gridResolution gridSettings.y +#define gridScale gridSettings.z +#define gridSubdiv gridSettings.w + +uniform int gridFlag; + +#define PLANE_XY (1 << 4) +#define PLANE_XZ (1 << 5) +#define PLANE_YZ (1 << 6) +#define CLIP_Z_POS (1 << 7) +#define CLIP_Z_NEG (1 << 8) + +in vec3 pos; + +void main() +{ + vec3 vert_pos, proj_camera_pos; + + /* Project camera pos to the needed plane */ + if ((gridFlag & PLANE_XY) > 0) { + vert_pos = vec3(pos.x, pos.y, 0.0); + proj_camera_pos = vec3(cameraPos.x, cameraPos.y, 0.0); + } + else if ((gridFlag & PLANE_XZ) > 0) { + vert_pos = vec3(pos.x, 0.0, pos.y); + proj_camera_pos = vec3(cameraPos.x, 0.0, cameraPos.z); + } + else { + vert_pos = vec3(0.0, pos.x, pos.y); + proj_camera_pos = vec3(0.0, cameraPos.y, cameraPos.z); + } + + /* if persp */ + if (ProjectionMatrix[3][3] == 0.0) { + vert_pos *= gridDistance * 2.0; + } + else { + float viewdist = 1.0 / min(abs(ProjectionMatrix[0][0]), abs(ProjectionMatrix[1][1])); + vert_pos *= viewdist * gridDistance * 2.0; + } + + vec3 realPos = proj_camera_pos + vert_pos; + + /* Used for additional Z axis */ + if ((gridFlag & CLIP_Z_POS) > 0) { + realPos.z = max(realPos.z, 0.0); + } + if ((gridFlag & CLIP_Z_NEG) > 0) { + realPos.z = min(-realPos.z, 0.0); + } + + gl_Position = ViewProjectionMatrix * vec4(realPos, 1.0); +} diff --git a/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl new file mode 100644 index 00000000000..d9616076dbf --- /dev/null +++ b/source/blender/draw/modes/shaders/object_lightprobe_grid_vert.glsl @@ -0,0 +1,35 @@ + +in vec3 pos; +in vec3 nor; + +uniform mat4 ViewProjectionMatrix; + +uniform float sphere_size; +uniform ivec3 grid_resolution; +uniform vec3 corner; +uniform vec3 increment_x; +uniform vec3 increment_y; +uniform vec3 increment_z; + +uniform int call_id; /* we don't want the builtin callId which would be 0. */ +uniform int baseId; + +flat out uint finalId; + +void main() +{ + vec3 ls_cell_location; + /* Keep in sync with update_irradiance_probe */ + ls_cell_location.z = float(gl_InstanceID % grid_resolution.z); + ls_cell_location.y = float((gl_InstanceID / grid_resolution.z) % grid_resolution.y); + ls_cell_location.x = float(gl_InstanceID / (grid_resolution.z * grid_resolution.y)); + + vec3 ws_cell_location = corner + + (increment_x * ls_cell_location.x + + increment_y * ls_cell_location.y + + increment_z * ls_cell_location.z); + + gl_Position = ViewProjectionMatrix * vec4(pos * 0.02 * sphere_size + ws_cell_location, 1.0); + + finalId = uint(baseId + call_id); +} diff --git a/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl new file mode 100644 index 00000000000..baa3ecb804c --- /dev/null +++ b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl @@ -0,0 +1,34 @@ + +/* This shader takes a 2D shape, puts it in 3D Object space such that is stays aligned with view, + * and scales the shape according to per-instance attributes + * Note that if the stiffness is zero, it assumes the scale is directly multiplied by the radius */ + + +uniform mat4 ViewProjectionMatrix; +uniform vec3 screen_vecs[2]; + +/* ---- Instanciated Attribs ---- */ +in vec2 pos; + +/* ---- Per instance Attribs ---- */ +in mat3x4 ScaleTranslationMatrix; +in float radius; +in vec3 color; + +flat out vec4 finalColor; + +void main() +{ + mat3 Scamat = mat3(ScaleTranslationMatrix); + vec4 world_pos = vec4( + ScaleTranslationMatrix[0][3], + ScaleTranslationMatrix[1][3], + ScaleTranslationMatrix[2][3], + 1.0); + + vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; + world_pos.xyz += Scamat * (screen_pos * radius); + + gl_Position = ViewProjectionMatrix * world_pos; + finalColor = vec4(color, 1.0); +} diff --git a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl new file mode 100644 index 00000000000..45bbdb18340 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl @@ -0,0 +1,82 @@ + +in vec4 uvcoordsvar; + +out vec4 FragColor; + +uniform usampler2D outlineId; +uniform sampler2D outlineDepth; +uniform sampler2D sceneDepth; + +uniform int idOffsets[3]; + +uniform float alphaOcclu; +uniform vec2 viewportSize; + +vec4 convert_id_to_color(int id) +{ + if (id == 0) { + return vec4(0.0); + } + if (id < idOffsets[1]) { + return colorActive; + } + else if (id < idOffsets[2]) { + return colorSelect; + } + else { + return colorTransform; + } +} + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + +#ifdef GL_ARB_texture_gather + vec2 texel_size = 1.0 / vec2(textureSize(outlineId, 0).xy); + vec2 uv = ceil(gl_FragCoord.xy) * texel_size; + + /* Samples order is CW starting from top left. */ + uvec4 tmp1 = textureGather(outlineId, uv - texel_size); + uvec4 tmp2 = textureGather(outlineId, uv); + + uint ref_id = tmp1.y; + uvec4 id = uvec4(tmp1.xz, tmp2.xz); +#else + uvec4 id; + uint ref_id = texelFetch(outlineId, texel, 0).r; + id.x = texelFetchOffset(outlineId, texel, 0, ivec2(-1, 0)).r; + id.y = texelFetchOffset(outlineId, texel, 0, ivec2( 0, -1)).r; + id.z = texelFetchOffset(outlineId, texel, 0, ivec2( 0, 1)).r; + id.w = texelFetchOffset(outlineId, texel, 0, ivec2( 1, 0)).r; +#endif + + bool outline = any(notEqual(id, uvec4(ref_id))); + + ivec2 depth_texel = texel; + /* If texel is an outline but has no valid id ... + * replace id and depth texel by a valid one. + * This keeps the outline thickness consistent everywhere. */ + if (ref_id == 0u && outline) { + depth_texel = (id.x != 0u) ? texel + ivec2(-1, 0) : depth_texel; + depth_texel = (id.y != 0u) ? texel + ivec2( 0, -1) : depth_texel; + depth_texel = (id.z != 0u) ? texel + ivec2( 0, 1) : depth_texel; + depth_texel = (id.w != 0u) ? texel + ivec2( 1, 0) : depth_texel; + + ref_id = (id.x != 0u) ? id.x : ref_id; + ref_id = (id.y != 0u) ? id.y : ref_id; + ref_id = (id.z != 0u) ? id.z : ref_id; + ref_id = (id.w != 0u) ? id.w : ref_id; + } + + float ref_depth = texelFetch(outlineDepth, depth_texel, 0).r; + float scene_depth = texelFetch(sceneDepth, depth_texel, 0).r; + + /* Avoid bad cases of zfighting for occlusion only. */ + const float epsilon = 3.0 / 8388608.0; + bool occluded = (ref_depth > scene_depth + epsilon); + + FragColor = convert_id_to_color(int(ref_id)); + FragColor.a *= (occluded) ? alphaOcclu : 1.0; + FragColor.a = (outline) ? FragColor.a : 0.0; +} diff --git a/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl new file mode 100644 index 00000000000..7e288cde236 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl @@ -0,0 +1,37 @@ + +in vec4 uvcoordsvar; + +out vec4 FragColor; + +uniform sampler2D outlineColor; + +uniform float alpha; +uniform bool doExpand; + +void main() +{ + ivec2 uv = ivec2(gl_FragCoord.xy); + FragColor = texelFetch(outlineColor, uv, 0).rgba; + + vec4 color[4]; + color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2( 1, 0)).rgba; + color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, 1)).rgba; + color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-1, 0)).rgba; + color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2( 0, -1)).rgba; + + vec4 values = vec4(color[0].a, color[1].a, color[2].a, color[3].a); + + vec4 tests = step(vec4(1e-6), values); /* (color.a != 0.0) */ + bvec4 btests = equal(tests, vec4(1.0)); + + if (FragColor.a != 0.0) { + return; + } + + FragColor = (btests.x) ? color[0] : FragColor; + FragColor = (btests.y) ? color[1] : FragColor; + FragColor = (btests.z) ? color[2] : FragColor; + FragColor = (btests.w) ? color[3] : FragColor; + + FragColor.a *= (!doExpand) ? 0.0 : 1.0; +} diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl new file mode 100644 index 00000000000..776adb787ad --- /dev/null +++ b/source/blender/draw/modes/shaders/object_outline_prepass_frag.glsl @@ -0,0 +1,10 @@ +uniform int callId; +uniform int baseId; + +/* using uint because 16bit uint can contain more ids than int. */ +out uint outId; + +void main() +{ + outId = uint(baseId + callId); +} diff --git a/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl new file mode 100644 index 00000000000..964ebe72e81 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl @@ -0,0 +1,27 @@ + +in vec4 uvcoordsvar; + +out vec4 FragColor; + +uniform sampler2D outlineBluredColor; +uniform vec2 rcpDimensions; + +void main() +{ +#ifdef USE_FXAA + float aa_alpha = FxaaPixelShader( + uvcoordsvar.st, + outlineBluredColor, + rcpDimensions, + 1.0, + 0.166, + 0.0833 + ).r; +#endif + + FragColor = texture(outlineBluredColor, uvcoordsvar.st).rgba; + +#ifdef USE_FXAA + FragColor.a = aa_alpha; +#endif +} diff --git a/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl b/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl new file mode 100644 index 00000000000..e8bf7884701 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_particle_dot_frag.glsl @@ -0,0 +1,52 @@ + +uniform vec3 color; +uniform vec3 outlineColor; +uniform sampler1D ramp; + +in vec4 radii; +flat in float finalVal; + +out vec4 fragColor; + +void main() { + float dist = length(gl_PointCoord - vec2(0.5)); + +// transparent outside of point +// --- 0 --- +// smooth transition +// --- 1 --- +// pure outline color +// --- 2 --- +// smooth transition +// --- 3 --- +// pure point color +// ... +// dist = 0 at center of point + + float midStroke = 0.5 * (radii[1] + radii[2]); + + if (dist > midStroke) { + if (finalVal < 0.0) { + fragColor.rgb = outlineColor; + } + else { + fragColor.rgb = texture(ramp, finalVal).rgb; + } + + fragColor.a = mix(1.0, 0.0, smoothstep(radii[1], radii[0], dist)); + } + else { + if (finalVal < 0.0) { + fragColor.rgb = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist)); + } + else { + fragColor.rgb = texture(ramp, finalVal).rgb; + } + + fragColor.a = 1.0; + } + + if (fragColor.a == 0.0) { + discard; + } +} diff --git a/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl new file mode 100644 index 00000000000..6dfc212a776 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl @@ -0,0 +1,35 @@ + +uniform mat4 ModelViewMatrix; +uniform mat4 ProjectionMatrix; +uniform float pixel_size; +uniform float size; + +in vec3 pos; +in float val; + +out vec4 radii; +flat out float finalVal; + +void main() { + gl_Position = ModelViewMatrix * vec4(pos, 1.0); + + float psize = (ProjectionMatrix[3][3] == 0.0) ? (size / (-gl_Position.z * pixel_size)) : (size / pixel_size); + + gl_PointSize = psize; + + // calculate concentric radii in pixels + float radius = 0.5 * psize; + + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; + radii[2] = radius - 1.0; + radii[3] = radius - 2.0; + + // convert to PointCoord units + radii /= psize; + + gl_Position = ProjectionMatrix * gl_Position; + + finalVal = val; +} diff --git a/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl new file mode 100644 index 00000000000..54ae319307a --- /dev/null +++ b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl @@ -0,0 +1,56 @@ + +uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ViewProjectionMatrix; +uniform mat4 ModelViewMatrix; +uniform mat4 ProjectionMatrix; +uniform int screen_space; +uniform float draw_size; +uniform vec3 color; +uniform sampler1D ramp; + +in vec3 pos; +in vec4 rot; +in float val; +in vec3 inst_pos; +in int axis; + +flat out vec4 finalColor; + +vec3 rotate(vec3 vec, vec4 quat) +{ + /* The quaternion representation here stores the w component in the first index */ + return vec + 2.0 * cross(quat.yzw, cross(quat.yzw, vec) + quat.x * vec); +} + +void main() +{ + if (screen_space == 1) { + gl_Position = ModelViewMatrix * vec4(pos, 1.0) + vec4(inst_pos * draw_size, 0.0); + gl_Position = ProjectionMatrix * gl_Position; + } + else { + float size = draw_size; + + if (axis > -1) { + size *= 2; + } + + gl_Position = ModelViewProjectionMatrix * vec4(pos + rotate(inst_pos * size, rot), 1.0); + } + +#ifdef USE_AXIS + if (axis == 0) + finalColor = vec4(1.0, 0.0, 0.0, 1.0); + else if (axis == 1) + finalColor = vec4(0.0, 1.0, 0.0, 1.0); + else + finalColor = vec4(0.0, 0.0, 1.0, 1.0); +#else + if (val < 0.0) { + finalColor = vec4(color, 1.0); + } + else { + finalColor = vec4(texture(ramp, val).rgb, 1.0); + } +#endif +} diff --git a/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl b/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl new file mode 100644 index 00000000000..5b0ad7863d1 --- /dev/null +++ b/source/blender/draw/modes/shaders/overlay_face_orientation_frag.glsl @@ -0,0 +1,10 @@ +uniform vec3 color_towards = vec3(0.0, 0.0, 1.0); +uniform vec3 color_outwards = vec3(1.0, 0.0, 0.0); + +out vec4 fragColor; + + +void main() +{ + fragColor = vec4(gl_FrontFacing ? color_towards: color_outwards, 0.7); +} diff --git a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl new file mode 100644 index 00000000000..d8a72f28eee --- /dev/null +++ b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl @@ -0,0 +1,7 @@ +uniform mat4 ModelViewProjectionMatrix; +in vec3 pos; + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); +} diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl new file mode 100644 index 00000000000..18c58a54dca --- /dev/null +++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl @@ -0,0 +1,11 @@ + +in vec2 uv_interp; +out vec4 fragColor; + +uniform sampler2D image; + + +void main() +{ + fragColor = texture(image, uv_interp); +} diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl new file mode 100644 index 00000000000..4ce12e048fa --- /dev/null +++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl @@ -0,0 +1,15 @@ + +uniform mat4 ModelViewProjectionMatrix; + +in vec2 uv; +in vec3 pos; + +out vec2 uv_interp; + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + + uv_interp = uv; + +} diff --git a/source/blender/draw/modes/shaders/paint_vert_frag.glsl b/source/blender/draw/modes/shaders/paint_vert_frag.glsl new file mode 100644 index 00000000000..c22e1c04b96 --- /dev/null +++ b/source/blender/draw/modes/shaders/paint_vert_frag.glsl @@ -0,0 +1,26 @@ + +flat in int finalFlag; +out vec4 fragColor; + +#define VERTEX_SELECTED (1 << 0) +#define VERTEX_HIDE (1 << 4) + +void main() +{ + if (bool(finalFlag & VERTEX_HIDE)) { + discard; + } + + vec2 centered = gl_PointCoord - vec2(0.5); + float dist_squared = dot(centered, centered); + const float rad_squared = 0.25; + const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0); + const vec4 colUnsel = vec4(0.5, 0.5, 0.5, 1.0); + + // round point with jaggy edges + if (dist_squared > rad_squared) { + discard; + } + + fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colUnsel; +} diff --git a/source/blender/draw/modes/shaders/paint_vertex_frag.glsl b/source/blender/draw/modes/shaders/paint_vertex_frag.glsl new file mode 100644 index 00000000000..5a00fec9c43 --- /dev/null +++ b/source/blender/draw/modes/shaders/paint_vertex_frag.glsl @@ -0,0 +1,17 @@ + +in vec3 finalColor; + +out vec4 fragColor; + +vec3 linear_to_srgb_attrib(vec3 c) { + c = max(c, vec3(0.0)); + vec3 c1 = c * 12.92; + vec3 c2 = 1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055; + return mix(c1, c2, step(vec3(0.0031308), c)); +} + +void main() +{ + fragColor.rgb = linear_to_srgb_attrib(finalColor); + fragColor.a = 1.0; +} diff --git a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl new file mode 100644 index 00000000000..178f77c6b9c --- /dev/null +++ b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl @@ -0,0 +1,21 @@ + +uniform mat4 ModelViewProjectionMatrix; + +in vec3 pos; +in vec3 color; + +out vec3 finalColor; + +vec3 srgb_to_linear_attrib(vec3 c) { + c = max(c, vec3(0.0)); + vec3 c1 = c * (1.0 / 12.92); + vec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4)); + return mix(c1, c2, step(vec3(0.04045), c)); +} + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + + finalColor = srgb_to_linear_attrib(color); +} diff --git a/source/blender/draw/modes/shaders/paint_wire_frag.glsl b/source/blender/draw/modes/shaders/paint_wire_frag.glsl new file mode 100644 index 00000000000..e4214a4c6d1 --- /dev/null +++ b/source/blender/draw/modes/shaders/paint_wire_frag.glsl @@ -0,0 +1,24 @@ + +flat in int finalFlag; +out vec4 fragColor; + +#define VERTEX_SELECTED (1 << 0) +#define VERTEX_HIDE (1 << 4) + +void main() +{ + if (bool(finalFlag & VERTEX_HIDE)) { + discard; + } + +#ifdef VERTEX_MODE + vec4 colSel = colorEdgeSelect; + colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0); +#else + const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0); +#endif + + const vec4 colUnsel = vec4(0.5, 0.5, 0.5, 1.0); + + fragColor = bool(finalFlag & VERTEX_SELECTED) ? colSel : colUnsel; +} diff --git a/source/blender/draw/modes/shaders/paint_wire_vert.glsl b/source/blender/draw/modes/shaders/paint_wire_vert.glsl new file mode 100644 index 00000000000..6a800e56d94 --- /dev/null +++ b/source/blender/draw/modes/shaders/paint_wire_vert.glsl @@ -0,0 +1,17 @@ + +uniform mat4 ModelViewProjectionMatrix; + +in vec3 pos; +in int data; + +flat out int finalFlag; + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + + /* Temp hack for william to start using blender 2.8 for icons. Will be removed by T54910 */ + gl_Position.z -= 0.0001; + + finalFlag = data; +} diff --git a/source/blender/draw/modes/shaders/particle_strand_frag.glsl b/source/blender/draw/modes/shaders/particle_strand_frag.glsl new file mode 100644 index 00000000000..7053ca43ae7 --- /dev/null +++ b/source/blender/draw/modes/shaders/particle_strand_frag.glsl @@ -0,0 +1,12 @@ +uniform mat4 ProjectionMatrix; + +in vec3 tangent; +in vec3 viewPosition; +flat in float colRand; +out vec4 fragColor; + +void main() +{ + fragColor.rgb = tangent; + fragColor.a = 1.0; +} diff --git a/source/blender/draw/modes/shaders/particle_strand_vert.glsl b/source/blender/draw/modes/shaders/particle_strand_vert.glsl new file mode 100644 index 00000000000..d4c35d14182 --- /dev/null +++ b/source/blender/draw/modes/shaders/particle_strand_vert.glsl @@ -0,0 +1,34 @@ + +uniform mat4 ModelViewProjectionMatrix; +uniform mat3 NormalMatrix; +uniform mat4 ModelViewMatrix; + +in vec3 pos; +in vec3 nor; +in int ind; +out vec3 tangent; +out vec3 viewPosition; +flat out float colRand; + +float rand(int s) +{ + int seed = s * 1023423; + + seed = (seed ^ 61) ^ (seed >> 16); + seed *= 9; + seed = seed ^ (seed >> 4); + seed *= 0x27d4eb2d; + seed = seed ^ (seed >> 15); + + float value = float(seed); + value *= 1.0 / 42596.0; + return fract(value); +} + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + tangent = normalize(NormalMatrix * nor); + viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz; + colRand = rand(ind); +} |