diff options
112 files changed, 11718 insertions, 1690 deletions
diff --git a/.gitignore b/.gitignore index 977fd9c2627..8347d2d2944 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ __pycache__/ *~ *.swp *.swo +*.sublime-project +*.sublime-workspace *# # QtCreator diff --git a/release/datafiles/gmon.out b/release/datafiles/gmon.out Binary files differnew file mode 100644 index 00000000000..9f19378ce5d --- /dev/null +++ b/release/datafiles/gmon.out diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py index 30cd39d2e2f..c5d985e7b12 100644 --- a/release/scripts/startup/bl_ui/properties_data_lamp.py +++ b/release/scripts/startup/bl_ui/properties_data_lamp.py @@ -388,6 +388,52 @@ class DATA_PT_falloff_curve(DataButtonsPanel, Panel): self.layout.template_curve_mapping(lamp, "falloff_curve", use_negative_slope=True) +class DATA_PT_viewport(DataButtonsPanel, Panel): + bl_label = "Viewport Settings" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'CYCLES'} + + @classmethod + def poll(cls, context): + lamp = context.lamp + engine = context.scene.render.engine + + return lamp and (engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + + lamp = context.lamp + + split = layout.split() + col = split.column() + col.prop(lamp, "use_specular") + col.prop(lamp, "use_diffuse") + + + if lamp.type in {'SPOT','SUN','AREA'}: + + col = split.column() + col.prop(lamp, "use_shadow", text="Use Shadow") + + layout.label(text="Shadow Settings:") + + col = layout.column(align=True) + col.active = lamp.use_shadow + col.prop(lamp, "ge_shadow_buffer_type", text="", toggle=True) + col.prop(lamp, "shadow_buffer_size", text="Size") + col.prop(lamp, "shadow_buffer_bias", text="Bias") + col.prop(lamp, "shadow_buffer_bleed_bias", text="Bleed Bias") + + row = layout.row(align=True) + row.active = lamp.use_shadow + row.prop(lamp, "shadow_buffer_clip_start", text="Clip Start") + row.prop(lamp, "shadow_buffer_clip_end", text="Clip End") + + if lamp.type == 'SUN': + row = layout.row() + row.prop(lamp, "shadow_frustum_size", text="Frustum Size") + class DATA_PT_custom_props_lamp(DataButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 3ff7a248c60..55b24065060 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -323,6 +323,69 @@ class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel): layout.prop(ob, "use_extra_recalc_data") +class OBJECT_PT_probe_settings(ObjectButtonsPanel, Panel): + bl_label = "Viewport Probe" + bl_context = "object" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'CYCLES'} + + @classmethod + def poll(cls, context): + return (context.object) + + def draw(self, context): + layout = self.layout + + ob = context.object + + layout.prop(ob, "probe_type", expand=True) + + if ob.probe_type == 'OBJECT': + layout.prop(ob, "probe_object") + + elif ob.probe_type in {'CUBE', 'PLANE'}: + split = layout.split() + + layout.operator("object.probe_update", text="Update Probe", icon="FILE_REFRESH").type = 'ACTIVE_PROBE' + + col = split.column() + col.prop(ob, "probe_refresh_auto", text="Auto Refresh") + col.prop(ob, "probe_compute_sh") + col = split.column() + col.prop(ob, "probe_refresh_double", text="Double Refresh") + col.prop(ob, "probe_use_layers") + + split = layout.split() + + col = split.column(align=True) + col.label(text="Quality:") + col.prop(ob, "probe_size", text="Reflection") + col.prop(ob, "probe_sh_quality", text="Diffuse") + + col = split.column(align=True) + col.label(text="Clipping:") + + if ob.probe_type == 'PLANE': + col.prop(ob, "probe_clip_bias", text="Bias") + else : + col.prop(ob, "probe_clip_start", text="Start") + + col.prop(ob, "probe_clip_end", text="End") + + if ob.probe_type == 'PLANE': + row = layout.row() + row.prop(ob, "probe_reflection_plane", text="Reflection Plane") + layout.prop(ob, "probe_object", text="Default Cube Probe") + + elif ob.probe_type == 'CUBE': + row = layout.row() + row.prop(ob, "probe_parallax_type", text="Parallax") + + row = layout.row() + row.active = (ob.probe_parallax_type in {"ELLIPSOID", "BOX"}) + row.prop(ob, "probe_parallax_volume", text="Parallax Volume") + + from bl_ui.properties_animviz import ( MotionPathButtonsPanel, OnionSkinButtonsPanel, diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py index e07349a99ee..9bf23dacca6 100644 --- a/release/scripts/startup/bl_ui/properties_world.py +++ b/release/scripts/startup/bl_ui/properties_world.py @@ -243,6 +243,30 @@ class WORLD_PT_mist(WorldButtonsPanel, Panel): layout.prop(world.mist_settings, "falloff") +class WORLD_PT_probe_settings(WorldButtonsPanel, Panel): + bl_label = "Viewport Probe" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'CYCLES'} + + def draw(self, context): + layout = self.layout + + world = context.world + split = layout.split() + + col = split.column() + col.prop(world, "probe_refresh_auto") + col = split.column() + col.prop(world, "probe_compute_sh") + + layout.operator("world.probe_update", text="Update Probe", icon="FILE_REFRESH") + + layout.label(text="Quality:") + row = layout.row(align=True) + row.prop(world, "probe_size", text="Reflection") + row.prop(world, "probe_sh_quality", text="Diffuse") + + class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} _context_path = "world" diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 1748d1d3738..a8ab0934abd 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -3213,6 +3213,11 @@ class VIEW3D_PT_view3d_display(Panel): col.prop(view, "show_only_render") col.prop(view, "show_world") + if scene.render.use_shading_nodes: + col = layout.column() + col.active = view.show_world + col.prop(view, "show_world_sh") + col = layout.column() display_all = not view.show_only_render col.active = display_all @@ -3321,6 +3326,38 @@ class VIEW3D_PT_view3d_shading(Panel): if scene.render.use_shading_nodes or gs.material_mode != 'GLSL': col.prop(view, "show_textured_shadeless") + if scene.render.use_shading_nodes and view.viewport_shade == 'MATERIAL': + pbr_settings = view.pbr_settings + + col.prop(pbr_settings, "use_realistic_mat", text="Material Preview") + if pbr_settings.use_realistic_mat: + brdf_settings = pbr_settings.brdf; + subcol = col.column(align=True) + subcol.prop(brdf_settings, "samples") + subcol.prop(brdf_settings, "lodbias") + + col.prop(pbr_settings, "use_ssao", text="Material Ambient Occlusion") + if pbr_settings.use_ssao: + ssao_settings = pbr_settings.ssao; + subcol = col.column(align=True) + subcol.prop(ssao_settings, "factor") + subcol.prop(scene.world.light_settings, "distance") + subcol.prop(ssao_settings, "samples") + subcol.prop(ssao_settings, "steps") + + col.prop(pbr_settings, "use_ssr", text="Material Reflections") + if pbr_settings.use_ssr: + ssr_settings = pbr_settings.ssr; + subcol = col.column(align=True) + subcol.prop(ssr_settings, "attenuation") + subcol.prop(ssr_settings, "steps") + subcol.prop(ssr_settings, "thickness") + + if pbr_settings.use_ssao or pbr_settings.use_ssr: + col.prop(pbr_settings, "use_backface", text="Backface Buffer") + + col.prop(pbr_settings, "use_layer_override") + col.prop(view, "show_backface_culling") if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}: @@ -3329,7 +3366,9 @@ class VIEW3D_PT_view3d_shading(Panel): fx_settings = view.fx_settings + if view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'}: + col.prop(fx_settings, "use_colormanagement", text="Color Management") sub = col.column() sub.active = view.region_3d.view_perspective == 'CAMERA' sub.prop(fx_settings, "use_dof") diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index cb864334208..5e4f5f160eb 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -492,6 +492,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u } } + CALLBACK_INVOKE(object->probe, IDWALK_NOP); + CALLBACK_INVOKE(object->parallaxcorrect, IDWALK_NOP); + CALLBACK_INVOKE(object->reflectionplane, IDWALK_NOP); + modifiers_foreachIDLink(object, library_foreach_modifiersForeachIDLink, &data); BKE_constraints_id_loop(&object->constraints, library_foreach_constraintObjectLooper, &data); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index cdd7560e3c4..b03eaa5bf85 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -129,6 +129,7 @@ #include "CCGSubSurf.h" #include "GPU_material.h" +#include "GPU_probe.h" /* Vertex parent modifies original BMesh which is not safe for threading. * Ideally such a modification should be handled as a separate DAG update @@ -214,7 +215,6 @@ void BKE_object_free_modifiers(Object *ob) /* same for softbody */ BKE_object_free_softbody(ob); - /* modifiers may have stored data in the DM cache */ BKE_object_free_derived_caches(ob); } @@ -438,6 +438,8 @@ void BKE_object_free(Object *ob) } GPU_lamp_free(ob); + GPU_probe_free(&ob->gpuprobe); + BKE_sculptsession_free(ob); BLI_freelistN(&ob->pc_ids); @@ -643,6 +645,14 @@ void BKE_object_init(Object *ob) ob->col_mask = 0xffff; ob->preview = NULL; + /* Viewport Probe defaults */ + ob->probesize = 256; + ob->probeshres = 32; + ob->probeflags = (OB_PROBE_AUTO_UPDATE | OB_PROBE_COMPUTE_SH); + ob->probeclipsta = 0.1f; + ob->probeclipend = 1000.0f; + ob->probeclipbias = 0.01f; + /* NT fluid sim defaults */ ob->fluidsimSettings = NULL; @@ -1160,6 +1170,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches) obn->derivedFinal = NULL; BLI_listbase_clear(&obn->gpulamp); + BLI_listbase_clear(&obn->gpuprobe); BLI_listbase_clear(&obn->pc_ids); obn->mpath = NULL; diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index caa9a1e357f..0e2e9ac75c2 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -53,6 +53,7 @@ #include "BKE_world.h" #include "GPU_material.h" +#include "GPU_probe.h" /** Free (or release) any data used by this world (does not free the world itself). */ void BKE_world_free(World *wrld) @@ -73,6 +74,8 @@ void BKE_world_free(World *wrld) } GPU_material_free(&wrld->gpumaterial); + + GPU_probe_free(&wrld->gpuprobe); BKE_icon_id_delete((struct ID *)wrld); BKE_previewimg_free(&wrld->preview); @@ -106,6 +109,11 @@ void BKE_world_init(World *wrld) wrld->preview = NULL; wrld->miststa = 5.0f; wrld->mistdist = 25.0f; + + /* Viewport Probe defaults */ + wrld->probesize = 512; + wrld->probeshres = 64; + wrld->probeflags = (WO_PROBE_AUTO_UPDATE | WO_PROBE_COMPUTE_SH); } World *add_world(Main *bmain, const char *name) @@ -141,6 +149,7 @@ World *BKE_world_copy(Main *bmain, World *wrld) BKE_previewimg_id_copy(&wrldn->id, &wrld->id); BLI_listbase_clear(&wrldn->gpumaterial); + BLI_listbase_clear(&wrldn->gpuprobe); BKE_id_copy_ensure_local(bmain, &wrld->id, &wrldn->id); @@ -167,6 +176,7 @@ World *localize_world(World *wrld) wrldn->preview = NULL; BLI_listbase_clear(&wrldn->gpumaterial); + BLI_listbase_clear(&wrldn->gpuprobe); return wrldn; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 60f276b1744..12982241c19 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3593,6 +3593,7 @@ static void direct_link_world(FileData *fd, World *wrld) wrld->preview = direct_link_preview_image(fd, wrld->preview); BLI_listbase_clear(&wrld->gpumaterial); + BLI_listbase_clear(&wrld->gpuprobe); } @@ -4955,6 +4956,13 @@ static void lib_link_object(FileData *fd, Main *main) level->source = ob; } } + + { + ob->probe = newlibadr(fd, ob->id.lib, ob->probe); + ob->parallaxcorrect = newlibadr(fd, ob->id.lib, ob->parallaxcorrect); + ob->reflectionplane = newlibadr(fd, ob->id.lib, ob->reflectionplane); + BLI_listbase_clear(&ob->gpuprobe); + } } } @@ -5537,6 +5545,8 @@ static void direct_link_object(FileData *fd, Object *ob) link_list(fd, &ob->lodlevels); ob->currentlod = ob->lodlevels.first; + BLI_listbase_clear(&ob->gpuprobe); + ob->preview = direct_link_preview_image(fd, ob->preview); } @@ -7045,6 +7055,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc) BLI_listbase_clear(&v3d->afterdraw_xraytransp); v3d->properties_storage = NULL; v3d->defmaterial = NULL; + v3d->pbr = NULL; /* render can be quite heavy, set to solid on load */ if (v3d->drawtype == OB_RENDER) @@ -7055,7 +7066,14 @@ static bool direct_link_screen(FileData *fd, bScreen *sc) v3d->fx_settings.dof = newdataadr(fd, v3d->fx_settings.dof); if (v3d->fx_settings.ssao) v3d->fx_settings.ssao = newdataadr(fd, v3d->fx_settings.ssao); - + + if (v3d->pbr_settings.ssr) + v3d->pbr_settings.ssr = newdataadr(fd, v3d->pbr_settings.ssr); + if (v3d->pbr_settings.ssao) + v3d->pbr_settings.ssao = newdataadr(fd, v3d->pbr_settings.ssao); + if (v3d->pbr_settings.brdf) + v3d->pbr_settings.brdf = newdataadr(fd, v3d->pbr_settings.brdf); + blo_do_versions_view3d_split_250(v3d, &sl->regionbase); } else if (sl->spacetype == SPACE_IPO) { @@ -9426,6 +9444,10 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) expand_doit(fd, mainvar, level->source); } } + + expand_doit(fd, mainvar, ob->probe); + expand_doit(fd, mainvar, ob->parallaxcorrect); + expand_doit(fd, mainvar, ob->reflectionplane); } static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index dfaa59c4e3f..eaa7d487862 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1084,6 +1084,29 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } + /* XXX I don't know against which version I should test */ + if (!MAIN_VERSION_ATLEAST(main, 277, 0)) { + { + World *wo; + for (wo = main->world.first; wo; wo = wo->id.next) { + wo->probesize = 512; + wo->probeflags = (WO_PROBE_AUTO_UPDATE | WO_PROBE_COMPUTE_SH); + wo->probeshres = 64; + } + } + + { + Object *ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + ob->probesize = 256; + ob->probeflags = (OB_PROBE_AUTO_UPDATE | OB_PROBE_COMPUTE_SH); + ob->probeclipsta = 0.1f; + ob->probeclipend = 1000.0f; + ob->probeshres = 32; + } + } + } + if (!MAIN_VERSION_ATLEAST(main, 277, 1)) { for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { ParticleEditSettings *pset = &scene->toolsettings->particle; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index dbc67d30b35..8e797e38de3 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -3065,6 +3065,17 @@ static void write_screens(WriteData *wd, ListBase *scrbase) if (v3d->fx_settings.dof) { writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof); } + + if (v3d->pbr_settings.brdf) { + writestruct(wd, DATA, GPUBRDFSettings, 1, v3d->pbr_settings.brdf); + } + if (v3d->pbr_settings.ssr) + { + writestruct(wd, DATA, GPUSSRSettings, 1, v3d->pbr_settings.ssr); + } + if (v3d->pbr_settings.ssao) { + writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->pbr_settings.ssao); + } } else if (sl->spacetype == SPACE_IPO) { SpaceIpo *sipo = (SpaceIpo *)sl; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 48c1e2d1996..422836b5be2 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -328,10 +328,10 @@ void *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d); void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, void *rv3dmat_pt); bool ED_view3d_context_activate(struct bContext *C); -void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d); +void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d, struct ARegion *ar); void ED_view3d_draw_offscreen( struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4], - float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname, + float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, bool do_meshes, const char *viewname, struct GPUFX *fx, struct GPUFXSettings *fx_settings, struct GPUOffScreen *ofs); diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index b3d02d45e13..98b9b1a11f2 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -50,6 +50,7 @@ set(SRC object_hook.c object_lattice.c object_lod.c + object_probe.c object_modifier.c object_ops.c object_random.c diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 9f91feee4c6..0cb91fd0269 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -112,6 +112,7 @@ #include "UI_resources.h" #include "GPU_material.h" +#include "GPU_probe.h" #include "object_intern.h" @@ -1104,6 +1105,9 @@ static void object_delete_check_glsl_update(Object *ob) if (ob->gpulamp.first) GPU_lamp_free(ob); } + + if (ob->gpuprobe.first) + GPU_probe_free(&ob->gpuprobe); } /* remove base from a specific scene */ diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 9710e4f843d..a599835917c 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -272,6 +272,10 @@ void OBJECT_OT_bake(wmOperatorType *ot); void OBJECT_OT_lod_add(struct wmOperatorType *ot); void OBJECT_OT_lod_remove(struct wmOperatorType *ot); +/* object_probe.c */ +void OBJECT_OT_probe_update(struct wmOperatorType *ot); +void OBJECT_OT_probe_set_active_as_probe(struct wmOperatorType *ot); + /* object_random.c */ void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 7e7e1ef182c..7c7e80edbf7 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -251,6 +251,9 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_lod_add); WM_operatortype_append(OBJECT_OT_lod_remove); + WM_operatortype_append(OBJECT_OT_probe_update); + WM_operatortype_append(OBJECT_OT_probe_set_active_as_probe); + WM_operatortype_append(TRANSFORM_OT_vertex_random); WM_operatortype_append(OBJECT_OT_data_transfer); diff --git a/source/blender/editors/object/object_probe.c b/source/blender/editors/object/object_probe.c new file mode 100644 index 00000000000..17c0296ac90 --- /dev/null +++ b/source/blender/editors/object/object_probe.c @@ -0,0 +1,162 @@ +/* + * ***** 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) Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/object/object_probe.c + * \ingroup edobj + */ + +#include "DNA_object_types.h" + +#include "BKE_context.h" + +#include "BLI_listbase.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "GPU_probe.h" + +#include "ED_screen.h" +#include "ED_object.h" + +#include "object_intern.h" + +enum { + UPDATE_PROBE_ACTIVE = 1, + UPDATE_PROBE_SELECTED = 2, + UPDATE_PROBE_ALL = 3, +}; + +static int object_probe_update_exec(bContext *C, wmOperator *op) +{ + const int mode = RNA_enum_get(op->ptr, "type"); + + if (mode == UPDATE_PROBE_ACTIVE) { + Object *ob = ED_object_context(C); + if (ob->gpuprobe.first) { + LinkData *link; + for (link = ob->gpuprobe.first; link; link = link->next) { + GPUProbe *ref = (GPUProbe *)link->data; + GPU_probe_set_update(ref, true); + } + } + } + else if (mode == UPDATE_PROBE_SELECTED) { + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) { + if (ob->gpuprobe.first) { + LinkData *link; + for (link = ob->gpuprobe.first; link; link = link->next) { + GPUProbe *ref = (GPUProbe *)link->data; + GPU_probe_set_update(ref, true); + } + } + } + CTX_DATA_END; + } + else if (mode == UPDATE_PROBE_ALL) { + CTX_DATA_BEGIN(C, Object *, ob, editable_objects) { + if (ob->gpuprobe.first) { + LinkData *link; + for (link = ob->gpuprobe.first; link; link = link->next) { + GPUProbe *ref = (GPUProbe *)link->data; + GPU_probe_set_update(ref, true); + } + } + } + CTX_DATA_END; + } + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_probe_update(wmOperatorType *ot) +{ + static EnumPropertyItem type_items[] = { + {UPDATE_PROBE_ACTIVE, "ACTIVE_PROBE", 0, "Active Probes", ""}, + {UPDATE_PROBE_SELECTED, "SELECT_PROBE", 0, "Selected Probes", ""}, + {UPDATE_PROBE_ALL, "ALL_PROBE", 0, "All Probes", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Update Probe"; + ot->description = "Update the environment captured by Probe objects"; + ot->idname = "OBJECT_OT_probe_update"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = object_probe_update_exec; + ot->poll = ED_operator_object_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", type_items, 1, "Type", ""); +} + +/* ************ Active as Probe ************** */ + +static int object_active_as_probe_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obt = ED_object_context(C); + + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) { + if (ob != obt) { + if (obt->probetype == OB_PROBE_CUBEMAP || obt->probetype == OB_PROBE_PLANAR) { + if (!ob->probetype) + ob->probetype = OB_PROBE_OBJECT; + ob->probe = obt; + } + } + } + CTX_DATA_END; + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_probe_set_active_as_probe(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Set Active as Probe"; + ot->description = "Make selected objects use the active Probe"; + ot->idname = "OBJECT_OT_probe_set_active_as_probe"; + + /* api callbacks */ + ot->exec = object_active_as_probe_exec; + ot->poll = ED_operator_object_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +}
\ No newline at end of file diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index fb07b03c286..2be5930d9e4 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -50,6 +50,8 @@ void MATERIAL_OT_new(struct wmOperatorType *ot); void TEXTURE_OT_new(struct wmOperatorType *ot); void WORLD_OT_new(struct wmOperatorType *ot); +void WORLD_OT_probe_update(struct wmOperatorType *ot); + void MATERIAL_OT_copy(struct wmOperatorType *ot); void MATERIAL_OT_paste(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index ee2772ce31a..423763fa46b 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -660,7 +660,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) * running notifiers again will overwrite */ oglrender->scene->customdata_mask |= oglrender->scene->customdata_mask_modal; - if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO)) { + if (oglrender->v3d->fx_settings.fx_flag) { oglrender->fx = GPU_fx_compositor_create(); } } diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c index c09e8576dc2..6799220c3cd 100644 --- a/source/blender/editors/render/render_ops.c +++ b/source/blender/editors/render/render_ops.c @@ -56,6 +56,8 @@ void ED_operatortypes_render(void) WM_operatortype_append(MATERIAL_OT_copy); WM_operatortype_append(MATERIAL_OT_paste); + WM_operatortype_append(WORLD_OT_probe_update); + WM_operatortype_append(SCENE_OT_render_layer_add); WM_operatortype_append(SCENE_OT_render_layer_remove); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 5a0c250c777..49cb8a8730a 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -85,6 +85,9 @@ #include "ED_render.h" #include "ED_screen.h" +#include "GPU_material.h" +#include "GPU_probe.h" + #include "RNA_define.h" #include "UI_interface.h" @@ -600,7 +603,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) RNA_property_update(C, &ptr, prop); } - WM_event_add_notifier(C, NC_WORLD | NA_ADDED, wo); + WM_event_add_notifier(C, NC_WORLD | NA_ADDED | ND_WORLD_DRAW, wo); return OPERATOR_FINISHED; } @@ -619,6 +622,48 @@ void WORLD_OT_new(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } +/********************** world probe operator *********************/ + +static int world_probe_update_poll(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + World *wo = scene->world; + return (wo != NULL); +} + +static int world_probe_update_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + World *wo = scene->world; + + if (wo && wo->gpuprobe.first) { + LinkData *link; + for (link = wo->gpuprobe.first; link; link = link->next) { + GPUProbe *ref = (GPUProbe *)link->data; + GPU_probe_set_update(ref, true); + } + } + + WM_event_add_notifier(C, NC_WORLD | ND_WORLD_DRAW, wo); + + return OPERATOR_FINISHED; +} + +void WORLD_OT_probe_update(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Update World Probe"; + ot->description = "Update the environment probe"; + ot->idname = "WORLD_OT_probe_update"; + + /* api callbacks */ + ot->exec = world_probe_update_exec; + ot->poll = world_probe_update_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + /********************** render layer operators *********************/ static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index f11a8177bf8..326b3b6d770 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -56,6 +56,7 @@ #include "GPU_material.h" #include "GPU_buffers.h" +#include "GPU_probe.h" #include "RE_engine.h" #include "RE_pipeline.h" @@ -307,6 +308,16 @@ static void material_changed(Main *bmain, Material *ma) if (parent->gpumaterial.first) GPU_material_free(&parent->gpumaterial); + + for (ob = bmain->object.first; ob; ob = ob->id.next) { + if (ob->gpuprobe.first) { + LinkData *link; + for (link = ob->gpuprobe.first; link; link = link->next) { + GPUProbe *probe = (GPUProbe *)link->data; + GPU_probe_auto_update(probe); + } + } + } } /* find if we have a scene with textured display */ @@ -356,6 +367,16 @@ static void lamp_changed(Main *bmain, Lamp *la) if (defmaterial.gpumaterial.first) GPU_material_free(&defmaterial.gpumaterial); + + for (ob = bmain->object.first; ob; ob = ob->id.next) { + if (ob->gpuprobe.first) { + LinkData *link; + for (link = ob->gpuprobe.first; link; link = link->next) { + GPUProbe *probe = (GPUProbe *)link->data; + GPU_probe_auto_update(probe); + } + } + } } static int material_uses_texture(Material *ma, Tex *tex) @@ -394,6 +415,16 @@ static void texture_changed(Main *bmain, Tex *tex) if (ma->gpumaterial.first) GPU_material_free(&ma->gpumaterial); + + for (ob = bmain->object.first; ob; ob = ob->id.next) { + if (ob->gpuprobe.first) { + LinkData *link; + for (link = ob->gpuprobe.first; link; link = link->next) { + GPUProbe *probe = (GPUProbe *)link->data; + GPU_probe_auto_update(probe); + } + } + } } /* find lamps */ @@ -424,7 +455,25 @@ static void texture_changed(Main *bmain, Tex *tex) BKE_icon_changed(BKE_icon_id_ensure(&wo->id)); if (wo->gpumaterial.first) - GPU_material_free(&wo->gpumaterial); + GPU_material_free(&wo->gpumaterial); + + if (wo->gpuprobe.first) { + LinkData *link; + for (link = wo->gpuprobe.first; link; link = link->next) { + GPUProbe *probe = (GPUProbe *)link->data; + GPU_probe_auto_update(probe); + } + } + + for (ob = bmain->object.first; ob; ob = ob->id.next) { + if (ob->gpuprobe.first) { + LinkData *link; + for (link = ob->gpuprobe.first; link; link = link->next) { + GPUProbe *probe = (GPUProbe *)link->data; + GPU_probe_auto_update(probe); + } + } + } } /* find compositing nodes */ @@ -481,6 +530,25 @@ static void world_changed(Main *bmain, World *wo) if (wo->gpumaterial.first) GPU_material_free(&wo->gpumaterial); + + if (wo->gpuprobe.first){ + LinkData *link; + for (link = wo->gpuprobe.first; link; link = link->next) { + GPUProbe *probe = (GPUProbe *)link->data; + GPU_probe_auto_update(probe); + } + } + + for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { + if (ob->gpuprobe.first) { + LinkData *link; + for (link = ob->gpuprobe.first; link; link = link->next) { + GPUProbe *probe = (GPUProbe *)link->data; + GPU_probe_auto_update(probe); + } + } + } + } static void image_changed(Main *bmain, Image *ima) @@ -521,7 +589,7 @@ static void scene_changed(Main *bmain, Scene *scene) for (wo = bmain->world.first; wo; wo = wo->id.next) if (wo->gpumaterial.first) GPU_material_free(&wo->gpumaterial); - + if (defmaterial.gpumaterial.first) GPU_material_free(&defmaterial.gpumaterial); } diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index bf344e1f721..0924c9a9288 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -1416,9 +1416,9 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) BKE_paint_init(scene, ePaintTextureProjective, PAINT_CURSOR_TEXTURE_PAINT); - if (U.glreslimit != 0) - GPU_free_images(); - GPU_paint_set_mipmap(0); + //if (U.glreslimit != 0) + // GPU_free_images(); + //GPU_paint_set_mipmap(0); toggle_paint_cursor(C, 1); } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index ecbfd5c7c85..d273f898f63 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -322,7 +322,7 @@ static bool set_draw_settings_cached( if (textured) { if (texpaint) { c_badtex = false; - if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, 0, 1, 0, false)) { + if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, 0, 1, 0, false, false)) { glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); @@ -474,7 +474,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O /* load the stencil texture here */ if (Gtexdraw.stencil != NULL) { glActiveTexture(GL_TEXTURE2); - if (GPU_verify_image(Gtexdraw.stencil, NULL, GL_TEXTURE_2D, false, false, false, false)) { + if (GPU_verify_image(Gtexdraw.stencil, NULL, GL_TEXTURE_2D, false, false, false, false, false)) { float col[4] = {imapaint->stencil_col[0], imapaint->stencil_col[1], imapaint->stencil_col[2], 1.0f}; glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); @@ -1092,7 +1092,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs) if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) { /* get openl texture */ int mipmap = 1; - int bindcode = (ima) ? GPU_verify_image(ima, iuser, GL_TEXTURE_2D, 0, 0, mipmap, false) : 0; + int bindcode = (ima) ? GPU_verify_image(ima, iuser, GL_TEXTURE_2D, 0, 0, mipmap, false, false) : 0; if (bindcode) { NodeTexBase *texbase = node->storage; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 4af84589eb8..ac898fe7438 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1170,7 +1170,7 @@ static void draw_transp_sun_volume(Lamp *la) } #endif -static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, +static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) { Object *ob = base->object; @@ -1312,9 +1312,17 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, } - if (la->type == LA_LOCAL) { - if (la->mode & LA_SPHERE) { - drawcircball(GL_LINE_LOOP, vec, la->dist, imat); + + if (BKE_scene_use_new_shading_nodes(scene)) { + if (la->type == LA_LOCAL || la->type == LA_SPOT) { + drawcircball(GL_LINE_LOOP, vec, la->area_size, imat); + } + } + else { + if (la->type == LA_LOCAL) { + if (la->mode & LA_SPHERE) { + drawcircball(GL_LINE_LOOP, vec, la->dist, imat); + } } } @@ -3707,7 +3715,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, } else if (check_object_draw_texture(scene, v3d, dt)) { if (draw_glsl_material(scene, ob, v3d, dt)) { - glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + glFrontFace(((ob->transflag & OB_NEG_SCALE) != (v3d->flag3 & V3D_FLIP_NORMALS)) ? GL_CW : GL_CCW); finalDM->drawMappedFacesGLSL(finalDM, GPU_object_material_bind, draw_em_fancy__setGLSLFaceOpts, em); @@ -3720,7 +3728,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, } } else { - glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + glFrontFace(((ob->transflag & OB_NEG_SCALE) != (v3d->flag3 & V3D_FLIP_NORMALS)) ? GL_CW : GL_CCW); finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, GPU_object_material_bind, NULL, me->edit_btmesh, DM_DRAW_SKIP_HIDDEN | DM_DRAW_NEED_NORMALS); glFrontFace(GL_CCW); @@ -3996,7 +4004,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */ - glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + glFrontFace(((ob->transflag & OB_NEG_SCALE) != (v3d->flag3 & V3D_FLIP_NORMALS)) ? GL_CW : GL_CCW); if (dt == OB_BOUNDBOX) { if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0) @@ -4028,7 +4036,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { Paint *p; - glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + glFrontFace(((ob->transflag & OB_NEG_SCALE) != (v3d->flag3 & V3D_FLIP_NORMALS)) ? GL_CW : GL_CCW); if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene))) { GPUVertexAttribs gattribs; @@ -4120,7 +4128,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D draw_mesh_object_outline(v3d, ob, dm); } - glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + glFrontFace(((ob->transflag & OB_NEG_SCALE) != (v3d->flag3 & V3D_FLIP_NORMALS)) ? GL_CW : GL_CCW); if (ob->sculpt && (p = BKE_paint_get_active(scene))) { float planes[4][4]; @@ -4579,7 +4587,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, DM_update_materials(dm, ob); - glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + glFrontFace(((ob->transflag & OB_NEG_SCALE) != (v3d->flag3 & V3D_FLIP_NORMALS)) ? GL_CW : GL_CCW); if (dt > OB_WIRE && dm->getNumPolys(dm)) { bool glsl = draw_glsl_material(scene, ob, v3d, dt); @@ -4749,10 +4757,10 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba GLenum mode; if (ob->type == OB_MBALL) { - mode = (ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW; + mode = ((ob->transflag & OB_NEG_SCALE) != (v3d->flag3 & V3D_FLIP_NORMALS)) ? GL_CW : GL_CCW; } else { - mode = (ob->transflag & OB_NEG_SCALE) ? GL_CCW : GL_CW; + mode = ((ob->transflag & OB_NEG_SCALE) != (v3d->flag3 & V3D_FLIP_NORMALS)) ? GL_CCW : GL_CW; } glFrontFace(mode); @@ -7717,7 +7725,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short break; case OB_LAMP: if (!render_override) { - drawlamp(v3d, rv3d, base, dt, dflag, ob_wire_col, is_obact); + drawlamp(scene, v3d, rv3d, base, dt, dflag, ob_wire_col, is_obact); } break; case OB_CAMERA: @@ -8463,7 +8471,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); } - glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + glFrontFace(((ob->transflag & OB_NEG_SCALE) != (v3d->flag3 & V3D_FLIP_NORMALS)) ? GL_CW : GL_CCW); if (dm) { dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 075b1faf502..8139a407a43 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -35,6 +35,7 @@ #include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_world_types.h" #include "MEM_guardedalloc.h" @@ -57,6 +58,8 @@ #include "GPU_compositing.h" #include "GPU_framebuffer.h" #include "GPU_material.h" +#include "GPU_probe.h" +#include "GPU_pbr.h" #include "BIF_gl.h" @@ -428,10 +431,20 @@ static void view3d_free(SpaceLink *sl) MEM_freeN(vd->defmaterial); } + if (vd->pbr) + GPU_pbr_free(vd->pbr); + if (vd->fx_settings.ssao) MEM_freeN(vd->fx_settings.ssao); if (vd->fx_settings.dof) MEM_freeN(vd->fx_settings.dof); + + if (vd->pbr_settings.brdf) + MEM_freeN(vd->pbr_settings.brdf); + if (vd->pbr_settings.ssr) + MEM_freeN(vd->pbr_settings.ssr); + if (vd->pbr_settings.ssao) + MEM_freeN(vd->pbr_settings.ssao); } @@ -461,6 +474,7 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) /* copy or clear inside new stuff */ v3dn->defmaterial = NULL; + v3dn->pbr = NULL; BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase); for (bgpic = v3dn->bgpicbase.first; bgpic; bgpic = bgpic->next) { @@ -478,6 +492,13 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) if (v3dn->fx_settings.ssao) v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao); + if (v3dn->pbr_settings.brdf) + v3dn->pbr_settings.brdf = MEM_dupallocN(v3do->pbr_settings.brdf); + if (v3dn->pbr_settings.ssr) + v3dn->pbr_settings.ssr = MEM_dupallocN(v3do->pbr_settings.ssr); + if (v3dn->pbr_settings.ssao) + v3dn->pbr_settings.ssao = MEM_dupallocN(v3do->pbr_settings.ssao); + return (SpaceLink *)v3dn; } @@ -799,6 +820,52 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene } } +static void view3d_tag_probes_update(ARegion *ar, wmNotifier *wmn, Scene *scene) +{ + wmWindow *win = wmn->wm->winactive; + + Base *base; + + if (!win) return; + + base = scene->base.first; + while (base) { + Object *ob = base->object; + + if (ob->gpuprobe.first) { + LinkData *link; + for (link = ob->gpuprobe.first; link; link = link->next) { + GPUProbe *probe = (GPUProbe *)link->data; + GPU_probe_auto_update(probe); + } + } + + base = base->next; + } +} + +static void view3d_tag_world_probe_update(ARegion *ar, wmNotifier *wmn, Scene *scene) +{ + wmWindow *win = wmn->wm->winactive; + + if (!win) return; + + if (scene->world) { + World *wo = scene->world; + + if (wo->gpuprobe.first) { + LinkData *link; + for (link = wo->gpuprobe.first; link; link = link->next) { + GPUProbe *probe = (GPUProbe *)link->data; + GPU_probe_auto_update(probe); + } + } + } + + /* usualy other probes depends on the world lighting so update them */ + view3d_tag_probes_update(ar, wmn, scene); +} + static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *wmn) { Scene *scene = sc->scene; @@ -842,6 +909,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w ED_region_tag_redraw(ar); break; case ND_WORLD: + view3d_tag_world_probe_update(ar, wmn, scene); /* handled by space_view3d_listener() for v3d access */ break; case ND_DRAW_RENDER_VIEWPORT: @@ -870,6 +938,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_KEYS: case ND_PARTICLE: case ND_LOD: + view3d_tag_probes_update(ar, wmn, scene); ED_region_tag_redraw(ar); break; } @@ -938,12 +1007,14 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w !DEG_depsgraph_use_legacy()) #endif { + view3d_tag_probes_update(ar, wmn, scene); ED_region_tag_redraw(ar); } break; } case ND_SHADING_DRAW: case ND_SHADING_LINKS: + view3d_tag_probes_update(ar, wmn, scene); ED_region_tag_redraw(ar); break; } @@ -951,6 +1022,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case NC_WORLD: switch (wmn->data) { case ND_WORLD_DRAW: + view3d_tag_world_probe_update(ar, wmn, scene); /* handled by space_view3d_listener() for v3d access */ break; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index a01f5dbc640..6a58b41a34f 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -100,6 +100,8 @@ #include "GPU_material.h" #include "GPU_compositing.h" #include "GPU_extensions.h" +#include "GPU_probe.h" +#include "GPU_pbr.h" #include "view3d_intern.h" /* own include */ @@ -2502,11 +2504,17 @@ static void gpu_render_lamp_update(Scene *scene, View3D *v3d, View3DShadow *shadow; unsigned int layers; - lamp = GPU_lamp_from_blender(scene, ob, par); + lamp = GPU_lamp_from_blender(scene, ob, par, BKE_scene_use_new_shading_nodes(scene)); if (lamp) { - GPU_lamp_update(lamp, lay, (ob->restrictflag & OB_RESTRICT_RENDER), obmat); + bool hide = (ob->restrictflag & OB_RESTRICT_VIEW); + GPU_lamp_update(lamp, lay, hide, obmat); GPU_lamp_update_colors(lamp, la->r, la->g, la->b, la->energy); + + if (la->area_shape == LA_AREA_SQUARE) + GPU_lamp_update_size(lamp, la->area_size, la->area_size); + else + GPU_lamp_update_size(lamp, la->area_size, la->area_sizey); layers = lay & v3d->lay; if (srl) @@ -2586,7 +2594,7 @@ static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d) /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */ ED_view3d_draw_offscreen( scene, v3d, &ar, winsize, winsize, viewmat, winmat, - false, false, true, + false, false, true, true, NULL, NULL, NULL, NULL); GPU_lamp_shadow_buffer_unbind(shadow->lamp); @@ -2607,6 +2615,373 @@ static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d) } } +/* ***************** Probes rendering *************** */ + +typedef struct View3DProbe { + struct View3DProbe *next, *prev; + GPUProbe *probe; +} View3DProbe; + +static void gpu_update_probes(Scene *scene, View3D *v3d, ARegion *basear) +{ + ListBase probelist; + ListBase afterlist; + int i = 0; + bool do_sky = false; + View3DProbe *vprobe; + GPUProbe *probe; + Scene *sce_iter; + Object *ob; + Base *base; + RegionView3D *baserv3d = basear->regiondata; + + /* gathering probes */ + BLI_listbase_clear(&probelist); + BLI_listbase_clear(&afterlist); + + /* Order matters : watch BLI_addhead and BLI_addtail + * rendering the world first + * then the cubemaps + * finally the planar reflections. */ + + /* Objects Probe (don't do dupliobjects) */ + for (SETLOOPER(scene, sce_iter, base)) { + ob = base->object; + + if (ob->probetype == OB_PROBE_CUBEMAP || ob->probetype == OB_PROBE_PLANAR) { + probe = GPU_probe_object(scene, ob); + + /* XXX free probes if size or type changes */ + if (probe && ((GPU_probe_get_size(probe) != ob->probesize) || + (GPU_probe_get_type(probe) != ob->probetype))) { + if (ob->gpuprobe.first) + GPU_probe_free(&ob->gpuprobe); + probe = GPU_probe_object(scene, ob); + } + + if (probe) { + if (ob->probetype == OB_PROBE_CUBEMAP) { + GPU_probe_update_layers(probe, ob->lay); + + if (ob->parallaxcorrect) + GPU_probe_update_parallax(probe, ob->parallaxcorrect->obmat, ob->obmat); + else + GPU_probe_update_parallax(probe, ob->obmat, ob->obmat); + + if (GPU_probe_get_update(probe)) { + GPU_probe_update_clip(probe, ob->probeclipsta, ob->probeclipend); + GPU_probe_update_sh_res(probe, ob->probeshres); + + vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe"); + vprobe->probe = probe; + BLI_addhead(&probelist, vprobe); + + if (ob->probeflags & OB_PROBE_DOUBLE_UPDATE) { + vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe"); + vprobe->probe = probe; + BLI_addhead(&afterlist, vprobe); + } + } + } + else if (ob->probetype == OB_PROBE_PLANAR) { + + GPU_probe_update_layers(probe, ob->lay); + GPU_probe_update_clip(probe, ob->probeclipbias, ob->probeclipend); + + if (ob->probe) { + if (ob->probe->parallaxcorrect) + GPU_probe_update_parallax(probe, ob->probe->parallaxcorrect->obmat, ob->probe->obmat); + else + GPU_probe_update_parallax(probe, ob->probe->obmat, ob->probe->obmat); + } + + if (ob->reflectionplane) + GPU_probe_update_ref_plane(probe, ob->reflectionplane->obmat); + else + GPU_probe_update_ref_plane(probe, ob->obmat); + + vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe"); + vprobe->probe = probe; + BLI_addtail(&probelist, vprobe); + + if (ob->probeflags & OB_PROBE_DOUBLE_UPDATE) { + vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe"); + vprobe->probe = probe; + BLI_addtail(&afterlist, vprobe); + } + } + } + } + else { + if (ob->gpuprobe.first) + GPU_probe_free(&ob->gpuprobe); + } + } + + /* World Probe */ + if (scene->world) { + do_sky = true; + probe = GPU_probe_world(scene, scene->world); + + /* XXX free probes if size change */ + if (probe && (GPU_probe_get_size(probe) != scene->world->probesize)) { + if (scene->world->gpuprobe.first) + GPU_probe_free(&scene->world->gpuprobe); + probe = GPU_probe_world(scene, scene->world); + } + + if (probe && GPU_probe_get_update(probe)) { + GPU_probe_update_sh_res(probe, scene->world->probeshres); + + vprobe = MEM_callocN(sizeof(View3DProbe), "View3DProbe"); + vprobe->probe = probe; + BLI_addhead(&probelist, vprobe); + } + } + + BLI_movelisttolist(&probelist, &afterlist); + + /* Updating probes */ + for (vprobe = probelist.first, i = 0; vprobe; vprobe = vprobe->next, i++) { + + float viewmat[4][4], winmat[4][4]; + int drawtype, lay, winsize, flag2 = v3d->flag2, flag3 = v3d->flag3, restrictflag; + int pbr_flag = v3d->pbr_settings.pbr_flag; + ARegion ar = {NULL}; + RegionView3D rv3d = {{{0}}}; + Object *ob = GPU_probe_get_object(vprobe->probe); + bool is_cubemap = (GPU_probe_get_type(vprobe->probe) == OB_PROBE_CUBEMAP); + + drawtype = v3d->drawtype; + lay = v3d->lay; + + v3d->drawtype = OB_MATERIAL; + v3d->lay = GPU_probe_get_layers(vprobe->probe); + v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP); + v3d->flag2 |= V3D_RENDER_OVERRIDE; + v3d->flag3 |= V3D_SHOW_WORLD; + v3d->flag3 &= ~V3D_SHOW_WORLD_DIFFUSE; + v3d->flag3 |= V3D_PROBE_CAPTURE; + v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSR; + v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSAO; + + if (ob) { + restrictflag = ob->restrictflag; + ob->restrictflag |= OB_RESTRICT_VIEW; + v3d->probe_source = ob; + } + else { + v3d->probe_source = NULL; + } + + GPU_probe_buffer_bind(vprobe->probe); + + /* cubemap */ + if (is_cubemap) { + for (int face = 0; face < 6; face++) { + GPU_probe_switch_fb_cubeface(vprobe->probe, face, viewmat, &winsize, winmat); + + ar.regiondata = &rv3d; + ar.regiontype = RGN_TYPE_WINDOW; + rv3d.persp = RV3D_CAMOB; + copy_m4_m4(rv3d.winmat, winmat); + copy_m4_m4(rv3d.viewmat, viewmat); + invert_m4_m4(rv3d.viewinv, rv3d.viewmat); + mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); + invert_m4_m4(rv3d.persinv, rv3d.viewinv); + + ED_view3d_draw_offscreen( + scene, v3d, &ar, winsize, winsize, viewmat, winmat, + false, do_sky, true, (bool)ob, + NULL, NULL, NULL, NULL); + } + } + /* planar */ + else { + ar.regiondata = &rv3d; + ar.regiontype = RGN_TYPE_WINDOW; + rv3d.persp = RV3D_CAMOB; + + /* Getting normal camera */ + view3d_winmatrix_set(basear, v3d, NULL); + view3d_viewmatrix_set(scene, v3d, baserv3d); /* note: calls BKE_object_where_is_calc for camera... */ + + /* Flip it along the plane */ + GPU_probe_attach_planar_fb(vprobe->probe, baserv3d->viewmat, baserv3d->winmat, viewmat, &winsize, false); + + copy_m4_m4(rv3d.viewmat, viewmat); + invert_m4_m4(rv3d.viewinv, rv3d.viewmat); + mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat); + invert_m4_m4(rv3d.persinv, rv3d.viewinv); + + v3d->flag3 |= V3D_FLIP_NORMALS; + + ED_view3d_draw_offscreen( + scene, v3d, &ar, winsize, winsize, viewmat, baserv3d->winmat, + false, do_sky, true, true, + NULL, NULL, NULL, NULL); + + /* Non-fliped Camera for refraction */ + GPU_probe_attach_planar_fb(vprobe->probe, baserv3d->viewmat, baserv3d->winmat, viewmat, &winsize, true); + + copy_m4_m4(rv3d.viewmat, viewmat); + invert_m4_m4(rv3d.viewinv, rv3d.viewmat); + mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat); + invert_m4_m4(rv3d.persinv, rv3d.viewinv); + + v3d->flag3 &= ~V3D_FLIP_NORMALS; + + ED_view3d_draw_offscreen( + scene, v3d, &ar, winsize, winsize, viewmat, baserv3d->winmat, + false, do_sky, true, true, + NULL, NULL, NULL, NULL); + + } + + GPU_probe_buffer_unbind(vprobe->probe); + + v3d->drawtype = drawtype; + v3d->lay = lay; + v3d->flag2 = flag2; + v3d->flag3 = flag3; + v3d->probe_source = NULL; + v3d->pbr_settings.pbr_flag = pbr_flag; + + if (ob) + ob->restrictflag = restrictflag; + + GPU_probe_rebuild_mipmaps(vprobe->probe); + + GPU_probe_sh_compute(vprobe->probe); + + GPU_probe_set_update(vprobe->probe, false); + } + + BLI_freelistN(&probelist); +} + +/* ***************** Scene buffer update *************** */ + +static void gpu_update_scene_buffer(Scene *scene, View3D *v3d, ARegion *basear) +{ + int drawtype = v3d->drawtype, winsize[2], flag2 = v3d->flag2, flag3 = v3d->flag3; + float clipsta, clipend; + ARegion ar = {NULL}; + RegionView3D *baserv3d = basear->regiondata; + RegionView3D rv3d = {{{0}}}; + GPUScreenBuffer *scene_buffer; + int res[2] = {basear->winx, basear->winy}; + int pbr_flag = v3d->pbr_settings.pbr_flag; + + scene_buffer = GPU_pbr_scene_buffer(v3d->pbr, res[0], res[1]); + + v3d->drawtype = OB_MATERIAL; + v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP); + v3d->flag2 |= V3D_RENDER_OVERRIDE; + v3d->flag3 |= V3D_SHOW_WORLD; + v3d->flag3 &= ~V3D_SHOW_WORLD_DIFFUSE; + v3d->flag3 |= V3D_PROBE_CAPTURE; + v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSR; + v3d->pbr_settings.pbr_flag &= ~GPU_PBR_FLAG_SSAO; + + ar.regiondata = &rv3d; + ar.regiontype = RGN_TYPE_WINDOW; + rv3d.persp = RV3D_CAMOB; + + /* Getting camera coords */ + ED_view3d_viewplane_get(v3d, baserv3d, basear->winx, basear->winy, NULL, &clipsta, &clipend, NULL); + view3d_winmatrix_set(basear, v3d, NULL); + view3d_viewmatrix_set(scene, v3d, baserv3d); /* note: calls BKE_object_where_is_calc for camera... */ + + GPU_scenebuf_bind(scene_buffer, baserv3d->winmat, winsize, clipsta, clipend); + + copy_m4_m4(rv3d.viewmat, baserv3d->viewmat); + invert_m4_m4(rv3d.viewinv, rv3d.viewmat); + mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat); + invert_m4_m4(rv3d.persinv, rv3d.viewinv); + + ED_view3d_draw_offscreen( + scene, v3d, &ar, winsize[0], winsize[1], baserv3d->viewmat, baserv3d->winmat, + false, (bool)scene->world, true, true, + NULL, NULL, NULL, NULL); + + v3d->drawtype = drawtype; + v3d->flag2 = flag2; + v3d->flag3 = flag3; + v3d->pbr_settings.pbr_flag = pbr_flag; + + GPU_scenebuf_unbind(scene_buffer); + GPU_scenebuf_filter_texture(scene_buffer); +} + +static void gpu_update_backface_buffer(Scene *scene, View3D *v3d, ARegion *basear) +{ + int drawtype = v3d->drawtype, winsize[2], flag2 = v3d->flag2, flag3 = v3d->flag3; + float clipsta, clipend; + ARegion ar = {NULL}; + RegionView3D *baserv3d = basear->regiondata; + RegionView3D rv3d = {{{0}}}; + GPUScreenBuffer *backface_buffer; + int res[2] = {basear->winx, basear->winy}; + + backface_buffer = GPU_pbr_backface_buffer(v3d->pbr, res[0], res[1]); + + v3d->drawtype = OB_SOLID; + v3d->flag2 &= ~(V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP); + v3d->flag2 |= V3D_BACKFACE_CULLING | V3D_RENDER_OVERRIDE | V3D_RENDER_SHADOW; + v3d->flag3 |= V3D_FLIP_NORMALS; + + ar.regiondata = &rv3d; + ar.regiontype = RGN_TYPE_WINDOW; + rv3d.persp = RV3D_CAMOB; + + /* Getting camera coords */ + ED_view3d_viewplane_get(v3d, baserv3d, basear->winx, basear->winy, NULL, &clipsta, &clipend, NULL); + view3d_winmatrix_set(basear, v3d, NULL); + view3d_viewmatrix_set(scene, v3d, baserv3d); /* note: calls BKE_object_where_is_calc for camera... */ + + GPU_scenebuf_bind(backface_buffer, baserv3d->winmat, winsize, clipsta, clipend); + + copy_m4_m4(rv3d.viewmat, baserv3d->viewmat); + invert_m4_m4(rv3d.viewinv, rv3d.viewmat); + mul_m4_m4m4(rv3d.persmat, baserv3d->winmat, rv3d.viewmat); + invert_m4_m4(rv3d.persinv, rv3d.viewinv); + + ED_view3d_draw_offscreen( + scene, v3d, &ar, winsize[0], winsize[1], baserv3d->viewmat, baserv3d->winmat, + false, (bool)scene->world, true, true, + NULL, NULL, NULL, NULL); + + v3d->drawtype = drawtype; + v3d->flag2 = flag2; + v3d->flag3 = flag3; + + GPU_scenebuf_unbind(backface_buffer); + GPU_scenebuf_filter_texture(backface_buffer); +} + + +static void gpu_pbr_update(Scene *scene, View3D *v3d, ARegion *ar) +{ + GPUPBR *pbr = v3d->pbr; + + gpu_update_probes(scene, v3d, ar); + + if (v3d->pbr_settings.pbr_flag & (GPU_PBR_FLAG_SSR | GPU_PBR_FLAG_SSAO)) + gpu_update_scene_buffer(scene, v3d, ar); + else if (pbr->scene) { + GPU_scenebuf_free(pbr->scene); + pbr->scene = NULL; + } + + if ((v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_BACKFACE) && (v3d->pbr_settings.pbr_flag & (GPU_PBR_FLAG_SSR | GPU_PBR_FLAG_SSAO))) + gpu_update_backface_buffer(scene, v3d, ar); + else if (pbr->backface) { + GPU_scenebuf_free(pbr->backface); + pbr->backface = NULL; + } +} + /* *********************** customdata **************** */ CustomDataMask ED_view3d_datamask(const Scene *scene, const View3D *v3d) @@ -2692,7 +3067,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f; rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f; } - + /* calculate pixelsize factor once, is used for lamps and obcenters */ { /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' @@ -2971,11 +3346,22 @@ void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, void *rv3dmat_pt) rv3d->pixsize = rv3dmat->pixsize; } -void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) +void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d, ARegion *ar) { /* shadow buffers, before we setup matrices */ - if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) + if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)){ gpu_update_lamps_shadows_world(scene, v3d); + + /* Cycles Material Mode only */ + if (BKE_scene_use_new_shading_nodes(scene) && (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_ENABLE)) { + GPU_pbr_settings_validate(&v3d->pbr_settings); + + if (!v3d->pbr) + v3d->pbr = GPU_pbr_create(); + + gpu_pbr_update(scene, v3d, ar); + } + } } /* @@ -2983,25 +3369,39 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) */ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) { + GPUFXSettings *fx_settings = &v3d->fx_settings; + bool use_color_correction = (fx_settings->fx_flag2 && (fx_settings->fx_flag2 & GPU_FX_FLAG_COLORMANAGEMENT)) ? false : true; + if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) { bool glsl = GPU_glsl_support(); + if (glsl) { RegionView3D *rv3d = ar->regiondata; - GPUMaterial *gpumat = GPU_material_world(scene, scene->world); + GPUMaterial *gpumat; + GPUProbe *gpuprobe; + bool material_not_bound; - /* calculate full shader for background */ - GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0)); - - bool material_not_bound = !GPU_material_bound(gpumat); + if (v3d->flag3 & V3D_SHOW_WORLD_DIFFUSE) { + gpuprobe = GPU_probe_world(scene, scene->world); + GPU_probe_sh_shader_bind(gpuprobe); + } + else { + gpumat = GPU_material_world(scene, scene->world); - if (material_not_bound) { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + /* calculate full shader for background */ + GPU_material_bind(gpumat, 1, 1, 1.0, true, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0)); + + material_not_bound = !GPU_material_bound(gpumat); + + if (material_not_bound) { + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + } } // Draw world glEnable(GL_DEPTH_TEST); @@ -3012,15 +3412,20 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) glVertex3f(-1.0, 1.0, 1.0); glVertex3f(1.0, 1.0, 1.0); glEnd(); - // - if (material_not_bound) { - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + + if (v3d->flag3 & V3D_SHOW_WORLD_DIFFUSE) { + GPU_probe_sh_shader_unbind(); } + else { + if (material_not_bound) { + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } - GPU_material_unbind(gpumat); + GPU_material_unbind(gpumat); + } glDepthFunc(GL_LEQUAL); glDisable(GL_DEPTH_TEST); @@ -3038,10 +3443,17 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) static GLushort indices[VIEWGRAD_RES_X - 1][VIEWGRAD_RES_X - 1][4]; static bool buf_calculated = false; - IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings, - &scene->display_settings); - IMB_colormanagement_pixel_to_display_space_v3(col_zen, &scene->world->zenr, &scene->view_settings, - &scene->display_settings); + if (use_color_correction) { + IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings, + &scene->display_settings); + IMB_colormanagement_pixel_to_display_space_v3(col_zen, &scene->world->zenr, &scene->view_settings, + &scene->display_settings); + } + else { + copy_v3_v3(col_hor, &scene->world->horr); + copy_v3_v3(col_zen, &scene->world->zenr); + } + glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -3140,8 +3552,13 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) } else { /* solid sky */ float col_hor[3]; - IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings, + if (use_color_correction) { + IMB_colormanagement_pixel_to_display_space_v3(col_hor, &scene->world->horr, &scene->view_settings, &scene->display_settings); + } + else { + copy_v3_v3(col_hor, &scene->world->horr); + } glClearColor(col_hor[0], col_hor[1], col_hor[2], 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -3188,7 +3605,7 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) void ED_view3d_draw_offscreen( Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[4][4], float winmat[4][4], - bool do_bgpic, bool do_sky, bool is_persp, const char *viewname, + bool do_bgpic, bool do_sky, bool is_persp, bool do_meshes, const char *viewname, GPUFX *fx, GPUFXSettings *fx_settings, GPUOffScreen *ofs) { @@ -3231,15 +3648,21 @@ void ED_view3d_draw_offscreen( view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat); /* framebuffer fx needed, we need to draw offscreen first */ - if (v3d->fx_settings.fx_flag && fx) { + if ((v3d->fx_settings.fx_flag || v3d->fx_settings.fx_flag2) && fx) { GPUSSAOSettings *ssao = NULL; + char fx_flag2 = v3d->fx_settings.fx_flag2; + + /* Don't do color management fx for offscreen */ + v3d->fx_settings.fx_flag2 &= ~GPU_FX_FLAG_COLORMANAGEMENT; if (v3d->drawtype < OB_SOLID) { ssao = v3d->fx_settings.ssao; v3d->fx_settings.ssao = NULL; } - do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings); + do_compositing = GPU_fx_compositor_initialize_passes(fx, &ar->winrct, NULL, fx_settings, scene); + + v3d->fx_settings.fx_flag2 = fx_flag2; if (ssao) v3d->fx_settings.ssao = ssao; @@ -3255,7 +3678,8 @@ void ED_view3d_draw_offscreen( } /* main drawing call */ - view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL); + if (do_meshes) + view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL); /* post process */ if (do_compositing) { @@ -3327,7 +3751,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( } } - ED_view3d_draw_offscreen_init(scene, v3d); + ED_view3d_draw_offscreen_init(scene, v3d, ar); GPU_offscreen_bind(ofs, true); @@ -3370,7 +3794,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( /* Single-pass render, common case */ ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, winmat, - draw_background, draw_sky, !is_ortho, viewname, + draw_background, draw_sky, !is_ortho, true, viewname, fx, &fx_settings, ofs); if (ibuf->rect_float) { @@ -3396,7 +3820,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( /* first sample buffer, also initializes 'rv3d->persmat' */ ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, winmat, - draw_background, draw_sky, !is_ortho, viewname, + draw_background, draw_sky, !is_ortho, true, viewname, fx, &fx_settings, ofs); GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp); @@ -3415,7 +3839,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( ED_view3d_draw_offscreen( scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, - draw_background, draw_sky, !is_ortho, viewname, + draw_background, draw_sky, !is_ortho, true, viewname, fx, &fx_settings, ofs); GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp); @@ -3842,14 +4266,25 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie wmWindow *win = CTX_wm_window(C); RegionView3D *rv3d = ar->regiondata; unsigned int lay_used = v3d->lay_used; - + + /* post processing */ bool do_compositing = false; /* shadow buffers, before we setup matrices */ - if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) + if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) { gpu_update_lamps_shadows_world(scene, v3d); + if (BKE_scene_use_new_shading_nodes(scene) && (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_ENABLE)) { + GPU_pbr_settings_validate(&v3d->pbr_settings); + + if (!v3d->pbr) + v3d->pbr = GPU_pbr_create(); + + gpu_pbr_update(scene, v3d, ar); + } + } + /* reset default OpenGL lights if needed (i.e. after preferences have been altered) */ if (rv3d->rflag & RV3D_GPULIGHT_UPDATE) { rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE; @@ -3873,7 +4308,7 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie #endif /* framebuffer fx needed, we need to draw offscreen first */ - if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) { + if ((v3d->fx_settings.fx_flag || v3d->fx_settings.fx_flag2) && v3d->drawtype >= OB_SOLID) { GPUFXSettings fx_settings; BKE_screen_gpu_fx_validate(&v3d->fx_settings); fx_settings = v3d->fx_settings; @@ -3886,7 +4321,7 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie fx_settings.dof = NULL; } - do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings); + do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings, scene); } /* clear the background */ diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 8885209ce01..d00efc3979c 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -55,7 +55,9 @@ set(SRC intern/gpu_extensions.c intern/gpu_framebuffer.c intern/gpu_init_exit.c + intern/gpu_pbr.c intern/gpu_material.c + intern/gpu_probe.c intern/gpu_select.c intern/gpu_shader.c intern/gpu_texture.c @@ -69,6 +71,18 @@ set(SRC shaders/gpu_shader_fx_dof_hq_geo.glsl shaders/gpu_shader_fx_vert.glsl shaders/gpu_shader_material.glsl + shaders/gpu_shader_material_bsdf_anisotropic.glsl + shaders/gpu_shader_material_bsdf_velvet.glsl + shaders/gpu_shader_material_bsdf_diffuse.glsl + shaders/gpu_shader_material_bsdf_glass.glsl + shaders/gpu_shader_material_bsdf_translucent.glsl + shaders/gpu_shader_material_bsdf_transparent.glsl + shaders/gpu_shader_material_bsdf_glossy.glsl + shaders/gpu_shader_material_bsdf_refraction.glsl + shaders/gpu_shader_material_bsdf_toon.glsl + shaders/gpu_shader_material_bsdf_ambient_occlusion.glsl + shaders/gpu_shader_material_new_shading.glsl + shaders/gpu_shader_material_utils.glsl shaders/gpu_shader_sep_gaussian_blur_frag.glsl shaders/gpu_shader_sep_gaussian_blur_vert.glsl shaders/gpu_shader_basic_frag.glsl @@ -78,9 +92,16 @@ set(SRC shaders/gpu_shader_vsm_store_frag.glsl shaders/gpu_shader_vsm_store_vert.glsl shaders/gpu_shader_fx_depth_resolve.glsl + shaders/gpu_shader_fx_colormanage_frag.glsl shaders/gpu_shader_fire_frag.glsl shaders/gpu_shader_smoke_frag.glsl shaders/gpu_shader_smoke_vert.glsl + shaders/gpu_shader_probe_sh_compute_frag.glsl + shaders/gpu_shader_probe_sh_compute_vert.glsl + shaders/gpu_shader_display_sh_frag.glsl + shaders/gpu_shader_display_sh_vert.glsl + shaders/gpu_shader_downsample_maxz_frag.glsl + shaders/gpu_shader_downsample_maxz_vert.glsl GPU_basic_shader.h GPU_buffers.h @@ -91,7 +112,10 @@ set(SRC GPU_framebuffer.h GPU_glew.h GPU_init_exit.h + GPU_pbr.h + GPU_ltc.h GPU_material.h + GPU_probe.h GPU_select.h GPU_shader.h GPU_texture.h @@ -104,6 +128,18 @@ data_to_c_simple(shaders/gpu_shader_fire_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_smoke_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_smoke_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_material.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_anisotropic.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_velvet.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_diffuse.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_glass.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_translucent.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_transparent.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_glossy.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_refraction.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_toon.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_bsdf_ambient_occlusion.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_new_shading.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_utils.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_basic_frag.glsl SRC) @@ -121,7 +157,14 @@ data_to_c_simple(shaders/gpu_shader_fx_dof_hq_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_dof_hq_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_dof_hq_geo.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_depth_resolve.glsl SRC) +data_to_c_simple(shaders/gpu_shader_fx_colormanage_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC) +data_to_c_simple(shaders/gpu_shader_probe_sh_compute_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_probe_sh_compute_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_display_sh_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_display_sh_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_downsample_maxz_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_downsample_maxz_vert.glsl SRC) if(WITH_GAMEENGINE) add_definitions(-DWITH_GAMEENGINE) diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h index d506d91a9aa..d1621f7713c 100644 --- a/source/blender/gpu/GPU_compositing.h +++ b/source/blender/gpu/GPU_compositing.h @@ -40,6 +40,7 @@ extern "C" { typedef struct GPUFX GPUFX; struct GPUDOFSettings; struct GPUSSAOSettings; +struct GPUCCSettings; struct GPUOffScreen; struct GPUFXSettings; struct rcti; @@ -66,10 +67,12 @@ typedef enum GPUFXShaderEffect { GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE = 9, GPU_SHADER_FX_DEPTH_RESOLVE = 10, + + GPU_SHADER_FX_COLORMANAGE = 11, } GPUFXShaderEffect; /* keep in synch with enum above! */ -#define MAX_FX_SHADERS 11 +#define MAX_FX_SHADERS 12 /* generate a new FX compositor */ GPUFX *GPU_fx_compositor_create(void); @@ -80,7 +83,7 @@ void GPU_fx_compositor_destroy(GPUFX *fx); /* initialize a framebuffer with size taken from the viewport */ bool GPU_fx_compositor_initialize_passes( GPUFX *fx, const struct rcti *rect, const struct rcti *scissor_rect, - const struct GPUFXSettings *fx_settings); + const struct GPUFXSettings *fx_settings, struct Scene *scene); /* do compositing on the fx passes that have been initialized */ bool GPU_fx_do_composite_pass( diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 90b65af87c8..d5dbd55279d 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -32,6 +32,8 @@ #ifndef __GPU_DRAW_H__ #define __GPU_DRAW_H__ +#include "GPU_glew.h" + #ifdef __cplusplus extern "C" { #endif @@ -113,6 +115,7 @@ void GPU_render_text( /* Mipmap settings * - these will free textures on changes */ +void GPU_generate_mipmap(GLenum target); void GPU_set_mipmap(bool mipmap); bool GPU_get_mipmap(void); void GPU_set_linear_mipmap(bool linear); @@ -135,10 +138,10 @@ void GPU_update_images_framechange(void); int GPU_update_image_time(struct Image *ima, double time); int GPU_verify_image( struct Image *ima, struct ImageUser *iuser, - int textarget, int tftile, bool compare, bool mipmap, bool is_data); + int textarget, int tftile, bool compare, bool mipmap, bool is_data, bool is_envmap); void GPU_create_gl_tex( unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth, - int textarget, bool mipmap, bool use_hight_bit_depth, struct Image *ima); + int textarget, bool mipmap, bool use_hight_bit_depth, struct Image *ima, bool is_envmap); void GPU_create_gl_tex_compressed( unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, int textarget, struct Image *ima, struct ImBuf *ibuf); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index 2719b8fa6a8..f7ffecf9511 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -51,6 +51,7 @@ void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex); GPUFrameBuffer *GPU_framebuffer_create(void); int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, char err_out[256]); +int GPU_framebuffer_cubeface_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int cubeface, char err_out[256]); void GPU_framebuffer_texture_detach(struct GPUTexture *tex); void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot); void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex); @@ -66,6 +67,8 @@ void GPU_framebuffer_blur( GPUFrameBuffer *fb, struct GPUTexture *tex, GPUFrameBuffer *blurfb, struct GPUTexture *blurtex); +void GPU_framebuffer_hiz_construction(GPUFrameBuffer *fb, struct GPUTexture *tex, const bool max); + /* GPU OffScreen * - wrapper around framebuffer and texture for simple offscreen drawing * - changes size if graphics card can't support it */ diff --git a/source/blender/gpu/GPU_ltc.h b/source/blender/gpu/GPU_ltc.h new file mode 100644 index 00000000000..c99c8d8aea6 --- /dev/null +++ b/source/blender/gpu/GPU_ltc.h @@ -0,0 +1,48 @@ +/* + * ***** 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 GPU_ltc.h + * \ingroup gpu + */ + +#ifndef __GPU_LTC_H__ +#define __GPU_LTC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* XXX should be used only in gpu_texture.c */ +/* It's here only to not bloat the gpu_texture.c file */ +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}; + +#ifdef __cplusplus +} +#endif + +#endif /* __GPU_LUTS_H__ */ diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 0d92d22a173..cc3039b558a 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -55,6 +55,9 @@ struct GPUNodeStack; struct GPUMaterial; struct GPUTexture; struct GPULamp; +struct GPUProbe; +struct GPUPBR; +struct GPUPBRSettings; struct PreviewImage; struct World; @@ -98,6 +101,7 @@ typedef enum GPUBuiltin { GPU_PARTICLE_ANG_VELOCITY = (1 << 12), GPU_LOC_TO_VIEW_MATRIX = (1 << 13), GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14), + GPU_PBR = (1 << 15), } GPUBuiltin; typedef enum GPUOpenGLBuiltin { @@ -106,8 +110,10 @@ typedef enum GPUOpenGLBuiltin { } GPUOpenGLBuiltin; typedef enum GPUMatType { - GPU_MATERIAL_TYPE_MESH = 1, - GPU_MATERIAL_TYPE_WORLD = 2, + GPU_MATERIAL_TYPE_MESH = 1, + GPU_MATERIAL_TYPE_MESH_REAL_SH = 2, + GPU_MATERIAL_TYPE_WORLD = 3, + GPU_MATERIAL_TYPE_LAMP = 5, } GPUMatType; @@ -169,6 +175,10 @@ typedef enum GPUDynamicType { GPU_DYNAMIC_LAMP_COEFFCONST = 13 | GPU_DYNAMIC_GROUP_LAMP, GPU_DYNAMIC_LAMP_COEFFLIN = 14 | GPU_DYNAMIC_GROUP_LAMP, GPU_DYNAMIC_LAMP_COEFFQUAD = 15 | GPU_DYNAMIC_GROUP_LAMP, + GPU_DYNAMIC_LAMP_DYNMAT = 16 | GPU_DYNAMIC_GROUP_LAMP, + GPU_DYNAMIC_LAMP_AREASCALE = 17 | GPU_DYNAMIC_GROUP_LAMP, + GPU_DYNAMIC_LAMP_SIZEX = 18 | GPU_DYNAMIC_GROUP_LAMP, + GPU_DYNAMIC_LAMP_SIZEY = 19 | GPU_DYNAMIC_GROUP_LAMP, GPU_DYNAMIC_SAMPLER_2DBUFFER = 1 | GPU_DYNAMIC_GROUP_SAMPLER, GPU_DYNAMIC_SAMPLER_2DIMAGE = 2 | GPU_DYNAMIC_GROUP_SAMPLER, @@ -199,7 +209,7 @@ typedef enum GPUDynamicType { GPUNodeLink *GPU_attribute(CustomDataType type, const char *name); GPUNodeLink *GPU_uniform(float *num); GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data); -GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data); +GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data, bool is_envmap); GPUNodeLink *GPU_cube_map(struct Image *ima, struct ImageUser *iuser, bool is_data); GPUNodeLink *GPU_image_preview(struct PreviewImage *prv); GPUNodeLink *GPU_texture(int size, float *pixels); @@ -211,14 +221,24 @@ void GPU_node_link_set_type(GPUNodeLink *link, GPUType type); bool GPU_link(GPUMaterial *mat, const char *name, ...); bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...); +void GPU_material_set_lamp_normal_link(GPUMaterial *material, GPUNodeLink *link); +GPUNodeLink *GPU_material_get_lamp_normal_link(GPUMaterial *material); +void GPU_material_set_lamp_position_link(GPUMaterial *material, GPUNodeLink *link); +GPUNodeLink *GPU_material_get_lamp_position_link(GPUMaterial *material); +void GPU_material_set_lamp_incoming_link(GPUMaterial *material, GPUNodeLink *link); +GPUNodeLink *GPU_material_get_lamp_incoming_link(GPUMaterial *material); void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); +void GPU_material_empty_output_link(GPUMaterial *material); +GPUNodeLink *GPU_material_get_output_link(GPUMaterial *material); void GPU_material_enable_alpha(GPUMaterial *material); +GPUNodeLink *GPU_get_world_horicol(void); GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]); /* High level functions to create and use GPU materials */ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo); -GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv); +GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv, + bool use_realistic_preview, bool use_planar_probe, bool use_alpha_as_depth, bool use_backface_depth, bool use_ssr, bool use_ssao, int parallax_correc); GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv); void GPU_material_free(struct ListBase *gpumaterial); @@ -231,10 +251,12 @@ void GPU_material_bind( void GPU_material_bind_uniforms( GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4], float autobumpscale, GPUParticleInfo *pi); +void GPU_material_bind_uniforms_pbr(GPUMaterial *material, struct GPUProbe *probe, struct GPUPBR *pbr, struct GPUPBRSettings *pbr_settings); void GPU_material_unbind(GPUMaterial *material); bool GPU_material_bound(GPUMaterial *material); struct Scene *GPU_material_scene(GPUMaterial *material); -GPUMatType GPU_Material_get_type(GPUMaterial *material); +GPUMatType GPU_material_get_type(GPUMaterial *material); +void GPU_material_set_type(GPUMaterial *material, GPUMatType type); void GPU_material_vertex_attributes(GPUMaterial *material, struct GPUVertexAttribs *attrib); @@ -243,6 +265,55 @@ bool GPU_material_do_color_management(GPUMaterial *mat); bool GPU_material_use_new_shading_nodes(GPUMaterial *mat); bool GPU_material_use_world_space_shading(GPUMaterial *mat); +/* BRDF Shading */ + +typedef enum GPUBrdfType { + GPU_BRDF_DIFFUSE = 0, + + GPU_BRDF_GLOSSY_SHARP = 1, + GPU_BRDF_GLOSSY_GGX = 2, + GPU_BRDF_GLOSSY_BECKMANN = 3, + GPU_BRDF_GLOSSY_ASHIKHMIN_SHIRLEY = 4, + + GPU_BRDF_ANISO_SHARP = 5, + GPU_BRDF_ANISO_GGX = 6, + GPU_BRDF_ANISO_BECKMANN = 7, + GPU_BRDF_ANISO_ASHIKHMIN_SHIRLEY = 8, + + GPU_BRDF_REFRACT_SHARP = 9, + GPU_BRDF_REFRACT_GGX = 10, + GPU_BRDF_REFRACT_BECKMANN = 11, + + GPU_BRDF_GLASS_SHARP = 12, + GPU_BRDF_GLASS_GGX = 13, + GPU_BRDF_GLASS_BECKMANN = 14, + + GPU_BRDF_VELVET = 15, + GPU_BRDF_TRANSLUCENT = 16, + GPU_BRDF_TRANSPARENT = 17, + + GPU_BRDF_TOON_DIFFUSE = 18, + GPU_BRDF_TOON_GLOSSY = 19, + + GPU_BRDF_AMBIENT_OCCLUSION = 20, +} GPUBrdfType; + +typedef struct GPUBrdfInput { + GPUMaterial *mat; + GPUBrdfType type; + + GPUNodeLink *normal, *color, *roughness, *ior; + GPUNodeLink *sigma, *toon_size, *toon_smooth, *anisotropy; + GPUNodeLink *aniso_rotation, *aniso_tangent; + + GPUNodeLink *output; +} GPUBrdfInput; + +void GPU_brdf_input_initialize(GPUBrdfInput *brdf); +void GPU_shade_BRDF(GPUBrdfInput *brdf); +void GPU_material_set_brdf_link(GPUMaterial *material, GPUBrdfInput *brdf); +GPUBrdfInput *GPU_material_get_brdf_link(GPUMaterial *material); + /* Exported shading */ typedef struct GPUShadeInput { @@ -311,7 +382,7 @@ void GPU_free_shader_export(GPUShaderExport *shader); /* Lamps */ -GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par); +GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par, bool use_realistic_preview); void GPU_lamp_free(struct Object *ob); bool GPU_lamp_has_shadow_buffer(GPULamp *lamp); @@ -323,6 +394,7 @@ int GPU_lamp_shadow_bind_code(GPULamp *lamp); float *GPU_lamp_dynpersmat(GPULamp *lamp); void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]); +void GPU_lamp_update_size(GPULamp *lamp, float sizex, float sizey); void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy); void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2, float coeff_const, float coeff_lin, float coeff_quad); @@ -333,6 +405,7 @@ GPUNodeLink *GPU_lamp_get_data( GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy); /* World */ + void GPU_mist_update_enable(short enable); void GPU_mist_update_values(int type, float start, float dist, float inten, float color[3]); void GPU_horizon_update_color(float color[3]); diff --git a/source/blender/gpu/GPU_pbr.h b/source/blender/gpu/GPU_pbr.h new file mode 100644 index 00000000000..1efca5ca68b --- /dev/null +++ b/source/blender/gpu/GPU_pbr.h @@ -0,0 +1,85 @@ +/* + * ***** 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 GPU_pbr.h + * \ingroup gpu + */ + +#ifndef __GPU_LUTS_H__ +#define __GPU_LUTS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct GPUTexture; +struct GPUFrameBuffer; + +typedef struct GPUScreenBuffer { + int type; + int w, h; + float clipsta, clipend; + float pixelprojmat[4][4]; + struct GPUTexture *tex; + struct GPUTexture *depth; + struct GPUFrameBuffer *fb; + struct GPUFrameBuffer *downsamplingfb; +} GPUScreenBuffer; + +typedef struct GPUPBR { + struct GPUTexture *hammersley; + struct GPUTexture *jitter; + struct GPUTexture *ltc_mat_ggx; + struct GPUTexture *ltc_mag_ggx; + + GPUScreenBuffer *scene; + GPUScreenBuffer *backface; +} GPUPBR; + +typedef enum GPUScreenBufferType { + GPU_COLOR_BUFFER = 0, + GPU_BACKFACE_BUFFER = 1, +} GPUScreenBufferType; + +GPUPBR *GPU_pbr_create(void); +void GPU_pbr_update(GPUPBR *pbr, GPUPBRSettings *pbr_settings, struct Scene *scene, struct View3D *v3d, struct ARegion *ar); +void GPU_pbr_free(GPUPBR *pbr); + +void GPU_scenebuf_free(GPUScreenBuffer *buf); +GPUScreenBuffer *GPU_pbr_scene_buffer(GPUPBR *pbr, int width, int height); +GPUScreenBuffer *GPU_pbr_backface_buffer(GPUPBR *pbr, int width, int height); +void GPU_scenebuf_bind(GPUScreenBuffer* buf, float winmat[4][4], int winsize[2], float clipsta, float clipend); +void GPU_scenebuf_unbind(GPUScreenBuffer* buf); +void GPU_scenebuf_filter_texture(GPUScreenBuffer* buf); + +void GPU_pbr_settings_validate(struct GPUPBRSettings *pbr_settings); + +#ifdef __cplusplus +} +#endif + +#endif /* __GPU_LUTS_H__ */ diff --git a/source/blender/gpu/GPU_probe.h b/source/blender/gpu/GPU_probe.h new file mode 100644 index 00000000000..2f35677fec3 --- /dev/null +++ b/source/blender/gpu/GPU_probe.h @@ -0,0 +1,118 @@ +/* + * ***** 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 GPU_probe.h + * \ingroup gpu + */ + +#ifndef __GPU_PROBE_H__ +#define __GPU_PROBE_H__ + +#include "BLI_sys_types.h" /* for bool */ +#include "DNA_listBase.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Object; +struct World; +struct Scene; + +typedef struct GPUProbe { + struct Scene *scene; + struct World *wo; + struct Object *ob; + + int type; + int size, shres; + unsigned int lay; + + bool update; + + float clipsta; + float clipend; + + float obmat[4][4]; + float imat[4][4]; + float winmat[4][4]; + float viewmat[4][4]; + float persmat[4][4]; + + float co[3], planevec[3]; + float correctionmat[4][4]; + float reflectionmat[4][4]; + float reflectmat[4][4]; + + struct GPUTexture *tex; + struct GPUTexture *texreflect; + struct GPUTexture *texrefract; + struct GPUTexture *depthtex; + struct GPUFrameBuffer *fb; + + struct GPUTexture *shtex; + struct GPUFrameBuffer *fbsh; + + float *shcoefs; +} GPUProbe; + +/* Keep this enum in sync with DNA_object_types.h */ +typedef enum GPUProbeType { + GPU_PROBE_CUBE = 2, + GPU_PROBE_PLANAR = 3, +} GPUProbeType; + +GPUProbe *GPU_probe_world(struct Scene *scene, struct World *wo); +GPUProbe *GPU_probe_object(struct Scene *scene, struct Object *ob); +void GPU_probe_free(ListBase *gpuprobe); + +void GPU_probe_buffer_bind(GPUProbe *probe); +void GPU_probe_switch_fb_cubeface(GPUProbe *probe, int cubeface, float viewmat[4][4], int *winsize, float winmat[4][4]); +void GPU_probe_attach_planar_fb(GPUProbe *probe, float camviewmat[4][4], float camwinmat[4][4], float viewmat[4][4], int *winsize, bool refraction); +void GPU_probe_buffer_unbind(GPUProbe *probe); +void GPU_probe_rebuild_mipmaps(GPUProbe *probe); +void GPU_probe_sh_compute(GPUProbe *probe); +void GPU_probe_sh_shader_bind(GPUProbe *probe); +void GPU_probe_sh_shader_unbind(void); +void GPU_probe_auto_update(GPUProbe *probe); +void GPU_probe_set_update(GPUProbe *probe, bool val); +bool GPU_probe_get_update(GPUProbe *probe); +struct Object *GPU_probe_get_object(GPUProbe *probe); +int GPU_probe_get_size(GPUProbe *probe); +int GPU_probe_get_type(GPUProbe *probe); +void GPU_probe_update_clip(GPUProbe *probe, float clipsta, float clipend); +void GPU_probe_update_layers(GPUProbe *probe, unsigned int lay); +unsigned int GPU_probe_get_layers(GPUProbe *probe); +void GPU_probe_update_sh_res(GPUProbe *probe, int res); +void GPU_probe_update_parallax(GPUProbe *probe, float correctionmat[4][4], float obmat[4][4]); +void GPU_probe_update_ref_plane(GPUProbe *probe, float obmat[4][4]); + +#ifdef __cplusplus +} +#endif + +#endif /*__GPU_PROBE_H__*/ diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 762329ee077..b40a2dbd1ed 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -47,6 +47,13 @@ enum { GPU_SHADER_FLAGS_NONE = 0, GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV = (1 << 0), GPU_SHADER_FLAGS_NEW_SHADING = (1 << 1), + GPU_SHADER_FLAGS_PROBE_BOX_CORREC = (1 << 2), + GPU_SHADER_FLAGS_PROBE_ELIPS_CORREC = (1 << 3), + GPU_SHADER_FLAGS_PROBE_PLANAR = (1 << 4), + GPU_SHADER_FLAGS_ALPHA_DEPTH = (1 << 5), + GPU_SHADER_FLAGS_BACKFACE_DEPTH = (1 << 6), + GPU_SHADER_FLAGS_SSR = (1 << 7), + GPU_SHADER_FLAGS_SSAO = (1 << 8), }; GPUShader *GPU_shader_create( @@ -89,8 +96,15 @@ typedef enum GPUBuiltinShader { GPU_SHADER_SEP_GAUSSIAN_BLUR = 1, GPU_SHADER_SMOKE = 2, GPU_SHADER_SMOKE_FIRE = 3, + GPU_SHADER_MINZ_DOWNSAMPLE = 4, + GPU_SHADER_MAXZ_DOWNSAMPLE = 5, + GPU_SHADER_DISPLAY_SH = 6, + + GPU_SHADER_COMPUTE_SH = 7, /* This reserves the MAX_SH_SAMPLES following values */ } GPUBuiltinShader; +#define MAX_SH_SAMPLES 10 + GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader); GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp); diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 756fe79151b..571bd8938a4 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -65,15 +65,27 @@ GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]) GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]); GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels); GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); +GPUTexture *GPU_texture_create_depth_buffer(int w, int h, char err_out[256]); GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]); -GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]); -GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, bool filtering, int channels, char err_out[256]); +GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, int channels, char err_out[256]); +GPUTexture *GPU_texture_create_cube_probe(int size, char err_out[256]); +GPUTexture *GPU_texture_create_planar_probe(int size, char err_out[256]); +GPUTexture *GPU_texture_create_sh_filter_target(char err_out[256]); GPUTexture *GPU_texture_create_2D_multisample( int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]); GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]); GPUTexture *GPU_texture_from_blender( - struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time, int mipmap); + struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, short do_clip, double time, int mipmap); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); + +GPUTexture *GPU_create_ltc_mat_ggx_lut_texture(void); +GPUTexture *GPU_create_ltc_mag_ggx_lut_texture(void); +GPUTexture *GPU_create_hammersley_sample_texture(int samples); +GPUTexture *GPU_create_jitter_texture(void); +GPUTexture *GPU_create_random_texture(void); +GPUTexture *GPU_create_spiral_sample_texture(int numsamples); + void GPU_invalid_tex_init(void); void GPU_invalid_tex_bind(int mode); void GPU_invalid_tex_free(void); @@ -92,6 +104,7 @@ struct GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex); int GPU_texture_framebuffer_attachment(GPUTexture *tex); void GPU_texture_framebuffer_set(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment); + int GPU_texture_target(const GPUTexture *tex); int GPU_texture_width(const GPUTexture *tex); int GPU_texture_height(const GPUTexture *tex); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 211394e7932..aeb656b238b 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -56,6 +56,18 @@ #include <stdarg.h> extern char datatoc_gpu_shader_material_glsl[]; +extern char datatoc_gpu_shader_material_new_shading_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_anisotropic_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_velvet_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_diffuse_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_glossy_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_refraction_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_glass_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_translucent_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_transparent_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_toon_glsl[]; +extern char datatoc_gpu_shader_material_bsdf_ambient_occlusion_glsl[]; +extern char datatoc_gpu_shader_material_utils_glsl[]; extern char datatoc_gpu_shader_vertex_glsl[]; extern char datatoc_gpu_shader_vertex_world_glsl[]; extern char datatoc_gpu_shader_geometry_glsl[]; @@ -410,6 +422,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin) return "unfparticlevel"; else if (builtin == GPU_PARTICLE_ANG_VELOCITY) return "unfparticleangvel"; + else if (builtin == GPU_PBR) + return "unfpbr"; /* Placeholder : does not actualy contains data */ else return ""; } @@ -430,13 +444,15 @@ static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void } } -static void codegen_set_unique_ids(ListBase *nodes) +static void codegen_set_unique_ids(ListBase *nodes, bool reserve_texid) { GHash *bindhash, *definehash; GPUNode *node; GPUInput *input; GPUOutput *output; - int id = 1, texid = 0; + /* XXX tex slot (texid) 0-10 are pbr textures */ + /* TODO : these should reserved on demand not in bulk */ + int id = 1, texid = (reserve_texid) ? 10 : 0; bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh"); definehash = BLI_ghash_ptr_new("codegen_set_unique_ids2 gh"); @@ -503,7 +519,7 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) GPUNode *node; GPUInput *input; const char *name; - int builtins = 0; + int builtins = 0, pbrbuiltins = 0; /* print uniforms */ for (node = nodes->first; node; node = node->next) { @@ -523,7 +539,11 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) builtins |= input->builtin; name = GPU_builtin_name(input->builtin); - if (gpu_str_prefix(name, "unf")) { + if (input->builtin == GPU_VIEW_POSITION) { + /* XXX always here */ + continue; + } + else if (gpu_str_prefix(name, "unf")) { BLI_dynstr_appendf(ds, "uniform %s %s;\n", GPU_DATATYPE_STR[input->type], name); } @@ -653,12 +673,19 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final BLI_dynstr_append(ds, ");\n"); } + BLI_dynstr_appendf(ds, "\n#ifndef ALPHA_AS_DEPTH\n"); BLI_dynstr_append(ds, "\n\tgl_FragColor = "); codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id); BLI_dynstr_append(ds, ";\n"); + BLI_dynstr_appendf(ds, "\n#else\n"); + /* Encode Depth in Alpha if we are capturing for planar reflection / ssr */ + BLI_dynstr_append(ds, "\n\tgl_FragColor = vec4("); + codegen_convert_datatype(ds, finaloutput->type, GPU_VEC3, "tmp", finaloutput->id); + BLI_dynstr_append(ds, ", varposition.z);\n"); + BLI_dynstr_appendf(ds, "\n#endif\n"); } -static char *code_generate_fragment(ListBase *nodes, GPUOutput *output) +static char *code_generate_fragment(ListBase *nodes, const GPUMatType type, GPUOutput *output) { DynStr *ds = BLI_dynstr_new(); char *code; @@ -669,12 +696,11 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output) GPUInput *input; #endif - #if 0 BLI_dynstr_append(ds, FUNCTION_PROTOTYPES); #endif - codegen_set_unique_ids(nodes); + codegen_set_unique_ids(nodes, (type == GPU_MATERIAL_TYPE_MESH_REAL_SH)); builtins = codegen_print_uniforms_functions(ds, nodes); #if 0 @@ -682,6 +708,10 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output) BLI_dynstr_appendf(ds, "/* %s */\n", name); #endif + /* XXX */ + BLI_dynstr_appendf(ds, "%s vec3 varposition;\n", + GLEW_VERSION_3_0 ? "in" : "varying"); + BLI_dynstr_append(ds, "void main()\n{\n"); if (builtins & GPU_VIEW_NORMAL) @@ -738,7 +768,7 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type) GPUInput *input; char *code; char *vertcode = NULL; - + for (node = nodes->first; node; node = node->next) { for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { @@ -768,6 +798,7 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type) switch (type) { case GPU_MATERIAL_TYPE_MESH: + case GPU_MATERIAL_TYPE_MESH_REAL_SH: vertcode = datatoc_gpu_shader_vertex_glsl; break; case GPU_MATERIAL_TYPE_WORLD: @@ -910,8 +941,21 @@ void GPU_code_generate_glsl_lib(void) ds = BLI_dynstr_new(); + /* Orders matters : some functions must be initialized for the later files + * This is in order to avoid unecessary early declarations */ BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl); - + BLI_dynstr_append(ds, datatoc_gpu_shader_material_utils_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_glossy_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_diffuse_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_anisotropic_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_velvet_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_transparent_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_refraction_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_glass_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_translucent_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_toon_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_ambient_occlusion_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_new_shading_glsl); glsl_material_library = BLI_dynstr_get_cstring(ds); @@ -1026,7 +1070,7 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap) /* create the textures */ for (input = inputs->first; input; input = input->next) { if (input->ima) - input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->textarget, input->image_isdata, time, mipmap); + input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->textarget, input->image_isdata, input->image_isenvmap, time, mipmap); else if (input->prv) input->tex = GPU_texture_from_preview(input->prv, mipmap); } @@ -1212,6 +1256,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType input->ima = link->ptr1; input->iuser = link->ptr2; input->image_isdata = link->image_isdata; + input->image_isenvmap = link->image_isenvmap; input->textarget = GL_TEXTURE_2D; input->textype = GPU_TEX2D; } @@ -1366,7 +1411,7 @@ static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *a } } -static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin) +static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin, int *pbrbuiltin) { GPUNode *node; GPUInput *input; @@ -1414,7 +1459,7 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *d return link; } -GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data) +GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data, bool is_envmap) { GPUNodeLink *link = GPU_node_link_create(); @@ -1422,6 +1467,7 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data) link->ptr1 = ima; link->ptr2 = iuser; link->image_isdata = is_data; + link->image_isenvmap = is_envmap; return link; } @@ -1647,10 +1693,17 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink) GPUPass *GPU_generate_pass( ListBase *nodes, GPUNodeLink *outlink, - GPUVertexAttribs *attribs, int *builtins, + GPUVertexAttribs *attribs, int *builtins, int *pbrbuiltins, const GPUMatType type, const char *UNUSED(name), const bool use_opensubdiv, - const bool use_new_shading) + const bool use_new_shading, + const bool use_planar_probe, + const bool use_box_correction, + const bool use_ellipsoid_correction, + const bool use_alpha_as_depth, + const bool use_backface_depth, + const bool use_ssr, + const bool use_ssao) { GPUShader *shader; GPUPass *pass; @@ -1667,10 +1720,10 @@ GPUPass *GPU_generate_pass( gpu_nodes_prune(nodes, outlink); gpu_nodes_get_vertex_attributes(nodes, attribs); - gpu_nodes_get_builtin_flag(nodes, builtins); + gpu_nodes_get_builtin_flag(nodes, builtins, pbrbuiltins); /* generate code and compile with opengl */ - fragmentcode = code_generate_fragment(nodes, outlink->output); + fragmentcode = code_generate_fragment(nodes, type, outlink->output); vertexcode = code_generate_vertex(nodes, type); geometrycode = code_generate_geometry(nodes, use_opensubdiv); @@ -1681,6 +1734,28 @@ GPUPass *GPU_generate_pass( if (use_new_shading) { flags |= GPU_SHADER_FLAGS_NEW_SHADING; } + if (use_box_correction) { + flags |= GPU_SHADER_FLAGS_PROBE_BOX_CORREC; + } + if (use_ellipsoid_correction) { + flags |= GPU_SHADER_FLAGS_PROBE_ELIPS_CORREC; + } + if (use_planar_probe) { + flags |= GPU_SHADER_FLAGS_PROBE_PLANAR; + } + if (use_alpha_as_depth) { + flags |= GPU_SHADER_FLAGS_ALPHA_DEPTH; + } + if (use_backface_depth) { + flags |= GPU_SHADER_FLAGS_BACKFACE_DEPTH; + } + if (use_ssr) { + flags |= GPU_SHADER_FLAGS_SSR; + } + if (use_ssao) { + flags |= GPU_SHADER_FLAGS_SSAO; + } + shader = GPU_shader_create_ex(vertexcode, fragmentcode, geometrycode, @@ -1699,6 +1774,7 @@ GPUPass *GPU_generate_pass( MEM_freeN(vertexcode); memset(attribs, 0, sizeof(*attribs)); memset(builtins, 0, sizeof(*builtins)); + memset(pbrbuiltins, 0, sizeof(*pbrbuiltins)); gpu_nodes_free(nodes); return NULL; } diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 7af17f9122d..999de1b6218 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -87,6 +87,7 @@ struct GPUNodeLink { GPUNodeLinkImage image; bool image_isdata; + bool image_isenvmap; bool texture; int texturesize; @@ -138,6 +139,7 @@ typedef struct GPUInput { struct ImageUser *iuser; /* image user */ struct PreviewImage *prv; /* preview images & icons */ bool image_isdata; /* image does not contain color data */ + bool image_isenvmap; /* image is envmap and should be clamped */ float *dynamicvec; /* vector data in case it is dynamic */ GPUDynamicType dynamictype; /* origin of the dynamic uniform */ void *dynamicdata; /* data source of the dynamic uniform */ @@ -171,10 +173,17 @@ struct GPUPass { typedef struct GPUPass GPUPass; GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink, - struct GPUVertexAttribs *attribs, int *builtin, + struct GPUVertexAttribs *attribs, int *builtins, int *pbrbuiltins, const GPUMatType type, const char *name, const bool use_opensubdiv, - const bool use_new_shading); + const bool use_new_shading, + const bool use_planar_probe, + const bool use_box_correction, + const bool use_ellipsoid_correction, + const bool use_alpha_as_depth, + const bool use_backface_depth, + const bool use_ssr, + const bool use_ssao); struct GPUShader *GPU_pass_shader(GPUPass *pass); diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 964c2b5051e..d1c54ea9865 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -35,12 +35,15 @@ #include "BLI_rect.h" #include "BLI_math.h" -#include "BLI_rand.h" +#include "BKE_colortools.h" +#include "BKE_scene.h" #include "DNA_vec_types.h" #include "DNA_scene_types.h" #include "DNA_gpu_types.h" +#include "IMB_colormanagement.h" + #include "GPU_compositing.h" #include "GPU_extensions.h" #include "GPU_framebuffer.h" @@ -181,6 +184,8 @@ struct GPUFX { int ssao_sample_count_cache; GPUTexture *ssao_spiral_samples_tex; + /* 3D Lut for color correction */ + GPUTexture *colorc_3dLut; GPUFXSettings settings; @@ -196,59 +201,64 @@ struct GPUFX { unsigned int vbuffer; }; -#if 0 -/* concentric mapping, see "A Low Distortion Map Between Disk and Square" and - * http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */ -static GPUTexture * create_concentric_sample_texture(int side) +static GPUTexture *create_3DLUT_from_display_settings(GPUFX *fx, Scene *scene) { + const int LUT3D_EDGE_SIZE = 16; + int num_3d_entries = 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE; + int offset; + int x,y,z; GPUTexture *tex; - float midpoint = 0.5f * (side - 1); - float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex"); - int i, j; - - for (i = 0; i < side; i++) { - for (j = 0; j < side; j++) { - int index = (i * side + j) * 2; - float a = 1.0f - i / midpoint; - float b = 1.0f - j / midpoint; - float phi, r; - if (a * a > b * b) { - r = a; - phi = (M_PI_4) * (b / a); - } - else { - r = b; - phi = M_PI_2 - (M_PI_4) * (a / b); + ColorManagedViewSettings *view_settings = &scene->view_settings; + ColorManagedDisplaySettings *display_settings = &scene->display_settings; + float tmp_pix[3]; + char *display_name = "sRGB"; + + float *lut3d = MEM_callocN(sizeof(float) * num_3d_entries, "Post-Process GPU 3D LUT"); + ColorManagedViewSettings *view_settings_mod = MEM_callocN(sizeof(ColorManagedViewSettings), "LUT Modified View Settings"); + ColorManagedDisplaySettings *display_settings_mod = MEM_callocN(sizeof(ColorManagedDisplaySettings), "LUT Modified Display Settings"); + + BKE_color_managed_view_settings_copy(view_settings_mod, view_settings); + BKE_color_managed_display_settings_copy(display_settings_mod, display_settings); + + /* Setting this to not affect the LUT + * Exposure control and gamma is done in the shader itself for better resolution + * Except if we use curve mapping */ + if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0) { + view_settings_mod->exposure = 0.0; + view_settings_mod->gamma = 1.0; + } + + /* XXX slow, low res ... need to find another way */ + for (z = 0; z < LUT3D_EDGE_SIZE; z++) + { + for (y = 0; y < LUT3D_EDGE_SIZE; y++) + { + for (x = 0; x < LUT3D_EDGE_SIZE; x++) + { + offset = (x + y * LUT3D_EDGE_SIZE + z * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE) * 3; + + /* Apply Linear color through Color Management to get the LUT+ColorCurve+DisplaySpace */ + lut3d[offset+0] = (float)x / ((float)LUT3D_EDGE_SIZE - 1.0f); //R + lut3d[offset+1] = (float)y / ((float)LUT3D_EDGE_SIZE - 1.0f); //G + lut3d[offset+2] = (float)z / ((float)LUT3D_EDGE_SIZE - 1.0f); //B + + IMB_colormanagement_pixel_to_display_space_v3(tmp_pix, &lut3d[offset], view_settings_mod, display_settings_mod); + + lut3d[offset+0] = tmp_pix[0]; + lut3d[offset+1] = tmp_pix[1]; + lut3d[offset+2] = tmp_pix[2]; + } - texels[index] = r * cos(phi); - texels[index + 1] = r * sin(phi); } } - tex = GPU_texture_create_1D_procedural(side * side, texels, NULL); - MEM_freeN(texels); - return tex; -} -#endif + tex = GPU_texture_create_3D(LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, 3, lut3d); -static GPUTexture *create_spiral_sample_texture(int numsaples) -{ - GPUTexture *tex; - float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex"); - const float numsaples_inv = 1.0f / numsaples; - int i; - /* arbitrary number to ensure we don't get conciding samples every circle */ - const float spirals = 7.357; - - for (i = 0; i < numsaples; i++) { - float r = (i + 0.5f) * numsaples_inv; - float phi = r * spirals * (float)(2.0 * M_PI); - texels[i][0] = r * cosf(phi); - texels[i][1] = r * sinf(phi); - } + MEM_freeN(lut3d); + BKE_color_managed_view_settings_free(view_settings_mod); + MEM_freeN(view_settings_mod); + MEM_freeN(display_settings_mod); - tex = GPU_texture_create_1D_procedural(numsaples, (float *)texels, NULL); - MEM_freeN(texels); return tex; } @@ -346,6 +356,11 @@ static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo) GPU_framebuffer_free(fx->gbuffer); fx->gbuffer = NULL; } + + if (fx->colorc_3dLut) { + GPU_texture_free(fx->colorc_3dLut); + fx->colorc_3dLut = NULL; + } } /* destroy a text compositor */ @@ -356,29 +371,15 @@ void GPU_fx_compositor_destroy(GPUFX *fx) MEM_freeN(fx); } -static GPUTexture * create_jitter_texture(void) -{ - float jitter[64 * 64][2]; - int i; - - for (i = 0; i < 64 * 64; i++) { - jitter[i][0] = 2.0f * BLI_frand() - 1.0f; - jitter[i][1] = 2.0f * BLI_frand() - 1.0f; - normalize_v2(jitter[i]); - } - - return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], true, NULL); -} - - bool GPU_fx_compositor_initialize_passes( GPUFX *fx, const rcti *rect, const rcti *scissor_rect, - const GPUFXSettings *fx_settings) + const GPUFXSettings *fx_settings, struct Scene *scene) { int w = BLI_rcti_size_x(rect), h = BLI_rcti_size_y(rect); char err_out[256]; int num_passes = 0; - char fx_flag; + char fx_flag, fx_flag2; + bool no_fx; fx->effects = 0; @@ -391,6 +392,7 @@ bool GPU_fx_compositor_initialize_passes( } fx_flag = fx_settings->fx_flag; + fx_flag2 = fx_settings->fx_flag2; /* disable effects if no options passed for them */ if (!fx_settings->dof) { @@ -400,7 +402,10 @@ bool GPU_fx_compositor_initialize_passes( fx_flag &= ~GPU_FX_FLAG_SSAO; } - if (!fx_flag) { + /* we must test every supported effect in case a non supported fx from the future arrives */ + no_fx = !(fx_flag || (fx_flag2 & GPU_FX_FLAG_COLORMANAGEMENT)); + + if (no_fx) { cleanup_fx_gl_data(fx, true); return false; } @@ -420,6 +425,9 @@ bool GPU_fx_compositor_initialize_passes( if (fx_flag & GPU_FX_FLAG_SSAO) num_passes++; + if (fx_flag2 & GPU_FX_FLAG_COLORMANAGEMENT) + num_passes++; + if (!fx->gbuffer) { fx->gbuffer = GPU_framebuffer_create(); @@ -430,7 +438,7 @@ bool GPU_fx_compositor_initialize_passes( /* try creating the jitter texture */ if (!fx->jitter_buffer) - fx->jitter_buffer = create_jitter_texture(); + fx->jitter_buffer = GPU_create_jitter_texture(); /* check if color buffers need recreation */ if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) { @@ -460,7 +468,7 @@ bool GPU_fx_compositor_initialize_passes( GPU_texture_free(fx->ssao_spiral_samples_tex); } - fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples); + fx->ssao_spiral_samples_tex = GPU_create_spiral_sample_texture(fx_settings->ssao->samples); } } else { @@ -470,6 +478,25 @@ bool GPU_fx_compositor_initialize_passes( } } + if (fx_flag2 & GPU_FX_FLAG_COLORMANAGEMENT) { + ColorManagedViewSettings *view_settings = &scene->view_settings;; + ColorManagedDisplaySettings *display_settings = &scene->display_settings;; + if (!fx->colorc_3dLut || view_settings->lut_is_outdated || display_settings->lut_is_outdated) { + if (fx->colorc_3dLut) { + GPU_texture_free(fx->colorc_3dLut); + } + fx->colorc_3dLut = create_3DLUT_from_display_settings(fx, scene); + view_settings->lut_is_outdated = 0; + display_settings->lut_is_outdated = 0; + } + } + else { + if (fx->colorc_3dLut) { + GPU_texture_free(fx->colorc_3dLut); + fx->colorc_3dLut = NULL; + } + } + /* create textures for dof effect */ if (fx_flag & GPU_FX_FLAG_DOF) { bool dof_high_quality = (fx_settings->dof->high_quality != 0) && @@ -502,7 +529,7 @@ bool GPU_fx_compositor_initialize_passes( return false; } if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural( - fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out))) + fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, false, 2, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); @@ -610,7 +637,7 @@ bool GPU_fx_compositor_initialize_passes( fx->restore_stencil = false; } - fx->effects = fx_flag; + fx->effects = fx_flag | fx_flag2; if (fx_settings) fx->settings = *fx_settings; @@ -1061,6 +1088,7 @@ bool GPU_fx_do_composite_pass( } } + SWAP(GPUTexture *, target, src); numslots = 0; } } @@ -1287,6 +1315,62 @@ bool GPU_fx_do_composite_pass( } } + if (fx->effects & GPU_FX_FLAG_COLORMANAGEMENT) { + GPUShader *colormanage_shader; + colormanage_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_COLORMANAGE, is_persp); + if (colormanage_shader) { + int color_uniform, exposure_uniform, gamma_uniform, lut3d_uniform, displayspace_uniform, offscreen_uniform; + ColorManagedViewSettings *view_settings = &scene->view_settings; + ColorManagedDisplaySettings *display_settings = &scene->display_settings; + float one = 1.0f, zero = 0.0f; + float displayspace = (BKE_scene_check_color_management_enabled(scene)) ? 1.0f : 0.0f; + bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0; + + color_uniform = GPU_shader_get_uniform(colormanage_shader, "colorbuffer"); + lut3d_uniform = GPU_shader_get_uniform(colormanage_shader, "lut3d_texture"); + exposure_uniform = GPU_shader_get_uniform(colormanage_shader, "exposure"); + gamma_uniform = GPU_shader_get_uniform(colormanage_shader, "gamma"); + displayspace_uniform = GPU_shader_get_uniform(colormanage_shader, "displayspace_is_srgb"); + offscreen_uniform = GPU_shader_get_uniform(colormanage_shader, "is_offscreen"); + + GPU_shader_bind(colormanage_shader); + + GPU_shader_uniform_vector(colormanage_shader, exposure_uniform, 1, 1, (use_curve_mapping) ? &zero : &view_settings->exposure); + GPU_shader_uniform_vector(colormanage_shader, gamma_uniform, 1, 1, (use_curve_mapping) ? &one : &view_settings->gamma); + GPU_shader_uniform_vector(colormanage_shader, displayspace_uniform, 1, 1, &displayspace); + GPU_shader_uniform_vector(colormanage_shader, offscreen_uniform, 1, 1, (ofs) ? &one : &zero); + + GPU_texture_bind(src, numslots++); + GPU_shader_uniform_texture(colormanage_shader, color_uniform, src); + + GPU_texture_bind(fx->colorc_3dLut, numslots++); + GPU_shader_uniform_texture(colormanage_shader, lut3d_uniform, fx->colorc_3dLut); + + /* draw */ + gpu_fx_bind_render_target(&passes_left, fx, ofs, target); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + /* disable bindings */ + GPU_texture_unbind(src); + + /* may not be attached, in that case this just returns */ + if (target) { + GPU_framebuffer_texture_detach(target); + if (ofs) { + GPU_offscreen_bind(ofs, false); + } + else { + GPU_framebuffer_restore(); + } + } + + /* swap here, after src/target have been unbound */ + SWAP(GPUTexture *, target, src); + numslots = 0; + } + } + glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -1311,6 +1395,7 @@ void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao) fx_ssao->distance_max = 0.2f; fx_ssao->attenuation = 1.0f; fx_ssao->samples = 20; + fx_ssao->steps = 2; } void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect effect) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7936811ab4d..5d4aef59e1d 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -82,6 +82,8 @@ #include "GPU_material.h" #include "GPU_shader.h" #include "GPU_texture.h" +#include "GPU_probe.h" +#include "GPU_pbr.h" #include "PIL_time.h" @@ -285,11 +287,15 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap) } } -static void gpu_generate_mipmap(GLenum target) +void GPU_generate_mipmap(GLenum target) { const bool is_ati = GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY); int target_enabled = 0; + if (GLEW_ARB_seamless_cube_map) { + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + } + /* work around bug in ATI driver, need to have GL_TEXTURE_2D enabled * http://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation */ if (is_ati) { @@ -534,7 +540,8 @@ static void gpu_verify_high_bit_srgb_buffer_slice(float *srgb_frect, ibuf->x, ibuf->x); IMB_buffer_float_unpremultiply(current_srgb_frect, ibuf->x, height); /* Clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images. */ - IMB_buffer_float_clamp(current_srgb_frect, ibuf->x, height); + if (!GTS.gpu_mipmap && ibuf->miptot == 1) + IMB_buffer_float_clamp(current_srgb_frect, ibuf->x, height); } static void verify_thread_do(void *data_v, @@ -566,7 +573,7 @@ static void gpu_verify_high_bit_srgb_buffer(float *srgb_frect, int GPU_verify_image( Image *ima, ImageUser *iuser, - int textarget, int tftile, bool compare, bool mipmap, bool is_data) + int textarget, int tftile, bool compare, bool mipmap, bool is_data, bool is_envmap) { unsigned int *bind = NULL; int tpx = 0, tpy = 0; @@ -757,7 +764,7 @@ int GPU_verify_image( GPU_create_gl_tex_compressed(bind, rect, rectw, recth, textarget, mipmap, ima, ibuf); else #endif - GPU_create_gl_tex(bind, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); + GPU_create_gl_tex(bind, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima, is_envmap); /* mark as non-color data texture */ if (*bind) { @@ -850,7 +857,7 @@ static void gpu_del_cube_map(void **cube_map) /* Image *ima can be NULL */ void GPU_create_gl_tex( unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth, - int textarget, bool mipmap, bool use_high_bit_depth, Image *ima) + int textarget, bool mipmap, bool use_high_bit_depth, Image *ima, bool is_envmap) { ImBuf *ibuf = NULL; @@ -858,7 +865,7 @@ void GPU_create_gl_tex( int tpy = recth; /* scale if not a power of two. this is not strictly necessary for newer - * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures + * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures * Then don't bother scaling for hardware that supports NPOT textures! */ if (textarget == GL_TEXTURE_2D && ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) || @@ -899,7 +906,7 @@ void GPU_create_gl_tex( if (GPU_get_mipmap() && mipmap) { if (GTS.gpu_mipmap) { - gpu_generate_mipmap(GL_TEXTURE_2D); + GPU_generate_mipmap(GL_TEXTURE_2D); } else { int i; @@ -950,7 +957,7 @@ void GPU_create_gl_tex( if (GPU_get_mipmap() && mipmap) { if (GTS.gpu_mipmap) { - gpu_generate_mipmap(GL_TEXTURE_CUBE_MAP); + GPU_generate_mipmap(GL_TEXTURE_CUBE_MAP); } else { if (!ibuf) { @@ -999,6 +1006,11 @@ void GPU_create_gl_tex( } } + if (is_envmap) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + if (GLEW_EXT_texture_filter_anisotropic) glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); @@ -1079,14 +1091,14 @@ void GPU_create_gl_tex_compressed( #ifndef WITH_DDS (void)ibuf; /* Fall back to uncompressed if DDS isn't enabled */ - GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); + GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima, false); #else glGenTextures(1, (GLuint *)bind); glBindTexture(textarget, *bind); if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf) == 0) { glDeleteTextures(1, (GLuint *)bind); - GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); + GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima, false); } #endif } @@ -1118,7 +1130,7 @@ int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend) gpu_verify_alpha_blend(alphablend); gpu_verify_reflection(ima); - if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, mtexpoly->tile, 1, mipmap, false)) { + if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, mtexpoly->tile, 1, mipmap, false, false)) { GTS.curtile = GTS.tile; GTS.curima = GTS.ima; GTS.curtilemode = GTS.tilemode; @@ -1260,7 +1272,7 @@ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, } if (GPU_get_mipmap()) { - gpu_generate_mipmap(GL_TEXTURE_2D); + GPU_generate_mipmap(GL_TEXTURE_2D); } else { ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; @@ -1310,7 +1322,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i /* we have already accounted for the case where GTS.gpu_mipmap is false * so we will be using GPU mipmap generation here */ if (GPU_get_mipmap()) { - gpu_generate_mipmap(GL_TEXTURE_2D); + GPU_generate_mipmap(GL_TEXTURE_2D); } else { ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; @@ -1344,7 +1356,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i /* see comment above as to why we are using gpu mipmap generation here */ if (GPU_get_mipmap()) { - gpu_generate_mipmap(GL_TEXTURE_2D); + GPU_generate_mipmap(GL_TEXTURE_2D); } else { ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; @@ -1600,7 +1612,7 @@ typedef struct GPUMaterialFixed { float spec[3]; int hard; float alpha; -} GPUMaterialFixed; +} GPUMaterialFixed; static struct GPUMaterialState { GPUMaterialFixed (*matbuf); @@ -1617,6 +1629,8 @@ static struct GPUMaterialState { Object *gob; DupliObject *dob; Scene *gscene; + GPUProbe *gprobe; + GPUPBR *gpbr; int glay; bool gscenelock; float (*gviewmat)[4]; @@ -1634,6 +1648,14 @@ static struct GPUMaterialState { int lastmatnr, lastretval; GPUBlendMode lastalphablend; bool is_opensubdiv; + bool is_planar_probe; + bool is_realistic_mat; + bool is_alpha_as_depth; + bool use_backface_depth; + bool use_ssr; + bool use_ssao; + int parallax_correc; + GPUPBRSettings *gpbrsettings; } GMS = {NULL}; /* fixed function material, alpha handed by caller */ @@ -1712,7 +1734,7 @@ void GPU_begin_object_materials( View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, bool glsl, bool *do_alpha_after) { - Material *ma; + Material *ma = NULL; GPUMaterial *gpumat; GPUBlendMode alphablend; DupliObject *dob; @@ -1778,6 +1800,16 @@ void GPU_begin_object_materials( GMS.gviewmat = rv3d->viewmat; GMS.gviewinv = rv3d->viewinv; GMS.gviewcamtexcofac = rv3d->viewcamtexcofac; + GMS.is_realistic_mat = (new_shading_nodes && (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_ENABLE)); + GMS.is_alpha_as_depth = (v3d->flag3 & V3D_PROBE_CAPTURE); + GMS.gprobe = NULL; + GMS.gpbr = NULL; + GMS.gpbrsettings = NULL; + GMS.use_ssr = false; + GMS.use_ssao = false; + GMS.use_backface_depth = false; + GMS.is_planar_probe = false; + GMS.parallax_correc = 0; /* alpha pass setup. there's various cases to handle here: * - object transparency on: only solid materials draw in the first pass, @@ -1811,22 +1843,88 @@ void GPU_begin_object_materials( GMS.alphablend[0] = GPU_BLEND_SOLID; } else { - + if (glsl && new_shading_nodes && GMS.is_realistic_mat && !(v3d->flag2 & V3D_RENDER_SHADOW)) { + GMS.use_ssr = (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_SSR); + GMS.use_ssao = (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_SSAO); + GMS.use_backface_depth = (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_BACKFACE); + GMS.gpbrsettings = &v3d->pbr_settings; + GMS.gpbr = v3d->pbr; + + /* Layer override */ + if (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_LAYER_OVERRIDE) { + SceneRenderLayer *srl = BLI_findlink(&GMS.gscene->r.layers, GMS.gscene->r.actlay); + if (srl->mat_override) ma = srl->mat_override; + } + + if (v3d->flag3 & V3D_PROBE_CAPTURE) { + Object *pro = (ob->probetype == OB_PROBE_OBJECT && ob->probe) + ? ob->probe /* probe attached */ + : ob; /* object itself */ + + GMS.use_ssr = false; + GMS.use_ssao = false; + GMS.use_backface_depth = false; + + /* check if we are not rendering this particular probe to avoid feedback loop */ + if (pro != v3d->probe_source) { + if (pro->probetype == OB_PROBE_CUBEMAP) { + GMS.gprobe = GPU_probe_object(scene, pro); + GMS.parallax_correc = pro->probeparallax; + } + else if (pro->probetype == OB_PROBE_PLANAR) { + /* fallback to attached probe or world probe */ + if (pro->probe && pro->probe->probetype == OB_PROBE_CUBEMAP + && pro->probe != v3d->probe_source) { + GMS.gprobe = GPU_probe_object(scene, pro->probe); + GMS.parallax_correc = pro->probe->probeparallax; + } + } + } + } + else { + Object *pro = (ob->probetype == OB_PROBE_OBJECT && ob->probe) + ? ob->probe /* probe attached */ + : ob; /* object itself */ + + if (pro->probetype == OB_PROBE_CUBEMAP) { + GMS.gprobe = GPU_probe_object(scene, pro); + GMS.parallax_correc = pro->probeparallax; + } + else if (pro->probetype == OB_PROBE_PLANAR) { + GMS.is_planar_probe = true; + GMS.gprobe = GPU_probe_object(scene, pro); + /* Pass the parallax info of the fallback cubemap*/ + if (pro->probe && pro->probe->probetype == OB_PROBE_CUBEMAP) { + GMS.parallax_correc = pro->probe->probeparallax; + } + } + } + + /* Default : use the world probe if it exists */ + if (!GMS.gprobe && scene->world) { + GMS.gprobe = GPU_probe_world(scene, scene->world); + } + } + /* no materials assigned? */ if (ob->totcol == 0) { - gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes, true); + if (ma == NULL) ma = &defmaterial; + gpu_material_to_fixed(&GMS.matbuf[0], ma, 0, ob, new_shading_nodes, true); /* do material 1 too, for displists! */ memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); if (glsl) { - GMS.gmatbuf[0] = &defmaterial; - GPU_material_from_blender(GMS.gscene, &defmaterial, GMS.is_opensubdiv); + GMS.gmatbuf[0] = ma; + GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv, + GMS.is_realistic_mat, GMS.is_planar_probe, + GMS.is_alpha_as_depth, GMS.use_backface_depth, GMS.use_ssr, GMS.use_ssao, + GMS.parallax_correc); } GMS.alphablend[0] = GPU_BLEND_SOLID; } - + /* setup materials */ for (a = 1; a <= ob->totcol; a++) { /* find a suitable material */ @@ -1834,8 +1932,16 @@ void GPU_begin_object_materials( if (!glsl && !new_shading_nodes) ma = gpu_active_node_material(ma); if (ma == NULL) ma = &defmaterial; + if (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_LAYER_OVERRIDE) { + SceneRenderLayer *srl = BLI_findlink(&GMS.gscene->r.layers, GMS.gscene->r.actlay); + if (srl->mat_override) ma = srl->mat_override; + } + /* create glsl material if requested */ - gpumat = glsl ? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv) : NULL; + gpumat = glsl ? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv, + GMS.is_realistic_mat, GMS.is_planar_probe, + GMS.is_alpha_as_depth, GMS.use_backface_depth, GMS.use_ssr, GMS.use_ssao, + GMS.parallax_correc) : NULL; if (gpumat) { /* do glsl only if creating it succeed, else fallback */ @@ -1934,7 +2040,10 @@ int GPU_object_material_bind(int nr, void *attribs) /* unbind glsl material */ if (GMS.gboundmat) { if (GMS.is_alpha_pass) glDepthMask(0); - GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv)); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv, + GMS.is_realistic_mat, GMS.is_planar_probe, + GMS.is_alpha_as_depth, GMS.use_backface_depth, GMS.use_ssr, GMS.use_ssao, + GMS.parallax_correc)); GMS.gboundmat = NULL; } @@ -1957,22 +2066,27 @@ int GPU_object_material_bind(int nr, void *attribs) if (gattribs && GMS.gmatbuf[nr]) { /* bind glsl material and get attributes */ Material *mat = GMS.gmatbuf[nr]; - GPUParticleInfo partile_info; + GPUParticleInfo particle_info; float auto_bump_scale; - GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv); + GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv, GMS.is_realistic_mat, + GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.use_backface_depth, GMS.use_ssr, + GMS.use_ssao, GMS.parallax_correc); GPU_material_vertex_attributes(gpumat, gattribs); if (GMS.dob) - GPU_get_particle_info(&partile_info); + GPU_get_particle_info(&particle_info); GPU_material_bind( gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock); auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info); + GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &particle_info); + + GPU_material_bind_uniforms_pbr(gpumat, GMS.gprobe, GMS.gpbr, GMS.gpbrsettings); + GMS.gboundmat = mat; /* for glsl use alpha blend mode, unless it's set to solid and @@ -2060,7 +2174,9 @@ void GPU_object_material_unbind(void) glDisable(GL_CULL_FACE); if (GMS.is_alpha_pass) glDepthMask(0); - GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv)); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv, GMS.is_realistic_mat, + GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.use_backface_depth, GMS.use_ssr, GMS.use_ssao, + GMS.parallax_correc)); GMS.gboundmat = NULL; } else @@ -2355,7 +2471,14 @@ void GPU_draw_update_fvar_offset(DerivedMesh *dm) gpu_material = GPU_material_from_blender(GMS.gscene, material, - GMS.is_opensubdiv); + GMS.is_opensubdiv, + GMS.is_realistic_mat, + GMS.is_planar_probe, + GMS.is_alpha_as_depth, + GMS.use_backface_depth, + GMS.use_ssr, + GMS.use_ssao, + GMS.parallax_correc); GPU_material_update_fvar_offset(gpu_material, dm); } diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index d41573b681b..10cd0452278 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -336,7 +336,6 @@ bool GPU_mem_stats_supported(void) return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM); } - void GPU_mem_stats_get(int *totalmem, int *freemem) { if (GLEW_NVX_gpu_memory_info) { diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index c0400cdb04c..d0a4d8a0ac0 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -29,6 +29,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_math_base.h" #include "BKE_global.h" @@ -126,7 +127,7 @@ GPUFrameBuffer *GPU_framebuffer_create(void) return fb; } -int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]) +static int gpu_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int cubeface, char err_out[256]) { GLenum attachment; GLenum error; @@ -157,8 +158,12 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot /* Clean glError buffer. */ while (glGetError() != GL_NO_ERROR) {} - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, - GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0); + if (GPU_texture_target(tex) == GL_TEXTURE_CUBE_MAP) + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, + GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeface, GPU_texture_opengl_bindcode(tex), 0); + else + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, + GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0); error = glGetError(); @@ -178,6 +183,16 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot return 1; } +int GPU_framebuffer_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int cubeface, char err_out[256]) +{ + return gpu_framebuffer_texture_attach(fb, tex, slot, cubeface, err_out); +} + +int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]) +{ + return gpu_framebuffer_texture_attach(fb, tex, slot, 0, err_out); +} + void GPU_framebuffer_texture_detach(GPUTexture *tex) { GLenum attachment; @@ -341,6 +356,7 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]) void GPU_framebuffer_free(GPUFrameBuffer *fb) { int i; + if (fb->depthtex) GPU_framebuffer_texture_detach(fb->depthtex); @@ -443,6 +459,72 @@ void GPU_framebuffer_blur( GPU_shader_unbind(); } +void GPU_framebuffer_hiz_construction(GPUFrameBuffer* fb, GPUTexture *tex, const bool max) +{ + int current_dim[2] = {GPU_texture_width(tex), GPU_texture_height(tex)}; + int levels, bindcode; + int lowermip_uniform, lowermipsize_uniform; + GPUShader *shader = GPU_shader_get_builtin_shader((max) ? GPU_SHADER_MAXZ_DOWNSAMPLE : GPU_SHADER_MINZ_DOWNSAMPLE); + + if (!shader) + return; + + GPU_shader_bind(shader); + lowermip_uniform = GPU_shader_get_uniform(shader, "lowermip"); + lowermipsize_uniform = GPU_shader_get_uniform(shader, "lowermipsize"); + + GPU_framebuffer_texture_attach(fb, tex, 0, NULL); + GPU_texture_bind_as_framebuffer(tex); + + bindcode = GPU_texture_opengl_bindcode(tex); + + levels = 1 + (int)floorf(log2f(fmaxf(current_dim[0], current_dim[1]))); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + + /* Avoid warning from GPU_texture_bind */ + glBindTexture(GL_TEXTURE_2D, bindcode); + GPU_shader_uniform_texture(shader, lowermip_uniform, tex); + + for (int i=1; i < levels; i++) { + /* Send previous mip size to the shader */ + GPU_shader_uniform_vector_int(shader, lowermipsize_uniform, 2, 1, current_dim); + + /* calculate next viewport size */ + current_dim[0] /= 2; + current_dim[1] /= 2; + + /* ensure that the viewport size is always at least 1x1 */ + CLAMP_MIN(current_dim[0], 1); + CLAMP_MIN(current_dim[1], 1); + glViewport(0, 0, current_dim[0], current_dim[1]); + + /* bind next level for rendering but first restrict fetches only to previous level */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, i-1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i-1); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, bindcode, i); + + /* Drawing quad */ + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2d(1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0); + glTexCoord2d(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0); + glTexCoord2d(1.0, 0.0); glVertex3f( 1.0, -1.0, 1.0); + glTexCoord2d(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0); + glEnd(); + } + + GPU_framebuffer_texture_detach(tex); + GPU_framebuffer_texture_unbind(fb, tex); + + /* reset mipmap level range for the depth image */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels - 1); + + GPU_shader_unbind(); + GPU_texture_unbind(tex); +} + /* GPUOffScreen */ struct GPUOffScreen { diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index ed9718f1a17..afae3b12bf1 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -45,10 +45,12 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_dynstr.h" #include "BKE_anim.h" #include "BKE_colortools.h" #include "BKE_global.h" +#include "BKE_object.h" #include "BKE_image.h" #include "BKE_main.h" #include "BKE_node.h" @@ -63,6 +65,9 @@ #include "GPU_material.h" #include "GPU_shader.h" #include "GPU_texture.h" +#include "GPU_draw.h" +#include "GPU_pbr.h" +#include "GPU_probe.h" #include "gpu_codegen.h" @@ -77,6 +82,7 @@ typedef enum DynMatProperty { DYN_LAMP_VEC = 2, DYN_LAMP_IMAT = 4, DYN_LAMP_PERSMAT = 8, + DYN_LAMP_MAT = 16, } DynMatProperty; static struct GPUWorld { @@ -106,7 +112,7 @@ struct GPUMaterial { /* for binding the material */ GPUPass *pass; GPUVertexAttribs attribs; - int builtins; + int builtins, pbrbuiltins; int alpha, obcolalpha; int dynproperty; @@ -122,10 +128,54 @@ struct GPUMaterial { int partvel; int partangvel; + /* Probe binding */ + int brdfsamplesloc, lutsamplesloc, jitterloc; + int ltcmatloc, ltcmagloc; + int probeloc, reflectloc, refractloc; + int lodfactorloc; + int correcmatloc, planarreflloc, planarobjloc; + int probecoloc, planarvecloc; + int shloc[9]; + GPUTexture *bindedcubeprobe; + GPUTexture *bindedreflprobe; + GPUTexture *bindedrefrprobe; + GPUTexture *bindedhammersley; + GPUTexture *bindedjitter; + GPUTexture *bindedltcmat; + GPUTexture *bindedltcmag; + + /* Screen space effects (SSR, SSAO...) */ + int scenebufloc; + int depthbufloc; + int backfacebufloc; + int ssaoparamsloc; + int clipinfoloc; + int ssrparamsloc; + int pixelprojmatloc; + GPUTexture *bindedscenebuffer; + GPUTexture *bindeddepthbuffer; + GPUTexture *bindedbackfacebuffer; + ListBase lamps; bool bound; + /* for passing parameters to the world nodetree */ + GPUNodeLink *lampNorLink; + GPUNodeLink *lampPosLink; + GPUNodeLink *lampInLink; + GPUBrdfInput *brdf; + + int parallax_correc; + bool is_planar_probe; + bool is_alpha_as_depth; + bool use_backface_depth; + bool use_ssr; + bool use_ssao; bool is_opensubdiv; + + /* Keep certain links during the material creation + * to do these calculations only once for the whole material */ + GPUNodeLink *ln_ssao; }; struct GPULamp { @@ -144,9 +194,11 @@ struct GPULamp { float obmat[4][4]; float imat[4][4]; float dynimat[4][4]; + float dynmat[4][4]; float spotsi, spotbl, k; float spotvec[2]; + float areavec[2]; float dyndist, dynatt1, dynatt2; float dist, att1, att2; float coeff_const, coeff_lin, coeff_quad; @@ -155,8 +207,11 @@ struct GPULamp { float bias, d, clipend; int size; + float area_size, area_size_y; + int falloff_type; struct CurveMapping *curfalloff; + bool use_realistic_lighting; float winmat[4][4]; float viewmat[4][4]; @@ -169,6 +224,14 @@ struct GPULamp { GPUTexture *depthtex; GPUTexture *blurtex; + /* Keep certain links during the material creation + * to do these calculations only once for the whole material */ + GPUNodeLink *nl_lv; + GPUNodeLink *nl_dist; + GPUNodeLink *nl_visifac; + GPUNodeLink *nl_shadfac; + GPUNodeLink *nl_lcol; + ListBase materials; }; @@ -181,11 +244,14 @@ static void texture_rgb_blend( static GPUMaterial *GPU_material_construct_begin(Material *ma) { - GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); + GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); + + material->ma = ma; - material->ma = ma; + /* Optimisation variables */ + material->ln_ssao = NULL; - return material; + return material; } static void gpu_material_set_attrib_id(GPUMaterial *material) @@ -229,11 +295,19 @@ static int GPU_material_construct_end(GPUMaterial *material, const char *passnam { if (material->outlink) { GPUNodeLink *outlink = material->outlink; + material->pass = GPU_generate_pass(&material->nodes, outlink, - &material->attribs, &material->builtins, material->type, + &material->attribs, &material->builtins, &material->pbrbuiltins, material->type, passname, material->is_opensubdiv, - GPU_material_use_new_shading_nodes(material)); + GPU_material_use_new_shading_nodes(material), + material->is_planar_probe, + material->parallax_correc & OB_PROBE_PARRALAX_BOX, + material->parallax_correc & OB_PROBE_PARRALAX_ELLIPSOID, + material->is_alpha_as_depth, + material->use_backface_depth, + material->use_ssr, + material->use_ssao); if (!material->pass) return 0; @@ -268,6 +342,39 @@ static int GPU_material_construct_end(GPUMaterial *material, const char *passnam material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY)); if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY)); + + if (material->builtins & GPU_PBR) { + material->brdfsamplesloc = GPU_shader_get_uniform(shader, "unfbsdfsamples"); + material->ltcmatloc = GPU_shader_get_uniform(shader, "unfltcmat"); + material->ltcmagloc = GPU_shader_get_uniform(shader, "unfltcmag"); + material->jitterloc = GPU_shader_get_uniform(shader, "unfjitter"); + material->lutsamplesloc = GPU_shader_get_uniform(shader, "unflutsamples"); + material->probeloc = GPU_shader_get_uniform(shader, "unfprobe"); + material->reflectloc = GPU_shader_get_uniform(shader, "unfreflect"); + material->refractloc = GPU_shader_get_uniform(shader, "unfrefract"); + material->lodfactorloc = GPU_shader_get_uniform(shader, "unflodfactor"); + material->shloc[0] = GPU_shader_get_uniform(shader, "unfsh0"); + material->shloc[1] = GPU_shader_get_uniform(shader, "unfsh1"); + material->shloc[2] = GPU_shader_get_uniform(shader, "unfsh2"); + material->shloc[3] = GPU_shader_get_uniform(shader, "unfsh3"); + material->shloc[4] = GPU_shader_get_uniform(shader, "unfsh4"); + material->shloc[5] = GPU_shader_get_uniform(shader, "unfsh5"); + material->shloc[6] = GPU_shader_get_uniform(shader, "unfsh6"); + material->shloc[7] = GPU_shader_get_uniform(shader, "unfsh7"); + material->shloc[8] = GPU_shader_get_uniform(shader, "unfsh8"); + material->correcmatloc = GPU_shader_get_uniform(shader, "unfprobecorrectionmat"); + material->planarreflloc = GPU_shader_get_uniform(shader, "unfplanarreflectmat"); + material->probecoloc = GPU_shader_get_uniform(shader, "unfprobepos"); + material->planarvecloc = GPU_shader_get_uniform(shader, "unfplanarvec"); + material->scenebufloc = GPU_shader_get_uniform(shader, "unfscenebuf"); + material->depthbufloc = GPU_shader_get_uniform(shader, "unfdepthbuf"); + material->backfacebufloc = GPU_shader_get_uniform(shader, "unfbackfacebuf"); + material->ssrparamsloc = GPU_shader_get_uniform(shader, "unfssrparam"); + material->pixelprojmatloc = GPU_shader_get_uniform(shader, "unfpixelprojmat"); + material->ssaoparamsloc = GPU_shader_get_uniform(shader, "unfssaoparam"); + material->clipinfoloc = GPU_shader_get_uniform(shader, "unfclip"); + } + return 1; } else { @@ -330,7 +437,7 @@ void GPU_material_bind( viewlay &= srl->lay; /* handle layer lamps */ - if (material->type == GPU_MATERIAL_TYPE_MESH) { + if (material->type == GPU_MATERIAL_TYPE_MESH || material->type == GPU_MATERIAL_TYPE_MESH_REAL_SH) { for (LinkData *nlink = material->lamps.first; nlink; nlink = nlink->next) { GPULamp *lamp = nlink->data; @@ -360,6 +467,10 @@ void GPU_material_bind( if (material->dynproperty & DYN_LAMP_IMAT) { mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv); } + + if (material->dynproperty & DYN_LAMP_MAT) { + mul_m4_m4m4(lamp->dynmat, viewmat, lamp->obmat); + } if (material->dynproperty & DYN_LAMP_PERSMAT) { /* The lamp matrices are already updated if we're using shadow buffers */ @@ -395,6 +506,17 @@ void GPU_material_bind( GPU_pass_update_uniforms(material->pass); material->bound = 1; + /* XXX */ + material->bindedcubeprobe = NULL; + material->bindedreflprobe = NULL; + material->bindedrefrprobe = NULL; + material->bindedhammersley = NULL; + material->bindedscenebuffer = NULL; + material->bindeddepthbuffer = NULL; + material->bindedbackfacebuffer = NULL; + material->bindedjitter = NULL; + material->bindedltcmat = NULL; + material->bindedltcmag = NULL; } } @@ -449,13 +571,185 @@ void GPU_material_bind_uniforms( if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) { GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity); } + } +} + +void GPU_material_bind_uniforms_pbr(GPUMaterial *material, GPUProbe *probe, GPUPBR *pbr, GPUPBRSettings *pbr_settings) +{ + if (material->pass && material->builtins & GPU_PBR) { + GPUShader *shader = GPU_pass_shader(material->pass); + + if (pbr) { + material->bindedhammersley = pbr->hammersley; + GPU_texture_bind(material->bindedhammersley, 0); + GPU_shader_uniform_texture(shader, material->lutsamplesloc, material->bindedhammersley); + + material->bindedjitter = pbr->jitter; + GPU_texture_bind(material->bindedjitter, 1); + GPU_shader_uniform_texture(shader, material->jitterloc, material->bindedjitter); + + material->bindedltcmat = pbr->ltc_mat_ggx; + GPU_texture_bind(material->bindedltcmat, 2); + GPU_shader_uniform_texture(shader, material->ltcmatloc, material->bindedltcmat); + + material->bindedltcmag = pbr->ltc_mag_ggx; + GPU_texture_bind(material->bindedltcmag, 3); + GPU_shader_uniform_texture(shader, material->ltcmagloc, material->bindedltcmag); + } + if (probe) { + /* Spherical Harmonics */ + for (int i = 0; i < 9; ++i) { + GPU_shader_uniform_vector(shader, material->shloc[i], 3, 1, &probe->shcoefs[i*3]); + } + + /* BSDF Samples */ + float samples[2]; + samples[0] = pbr_settings->brdf->samples; + samples[1] = 1.0f / samples[0]; + GPU_shader_uniform_vector(shader, material->brdfsamplesloc, 2, 1, samples); + + /* Lod factor for importance sampling */ + float lodfactor = 0.5f * log( ( (float)(probe->size * probe->size) * samples[1] ) ) / log(2); + lodfactor -= pbr_settings->brdf->lodbias; + GPU_shader_uniform_vector(shader, material->lodfactorloc, 1, 1, &lodfactor); + + /* Probe Cube */ + if (probe->type == GPU_PROBE_PLANAR) { + GPUProbe *fallbackprobe = NULL; + /* XXX : this should be moved elsewhere */ + if (probe->ob->probe && probe->ob->probe->probetype == OB_PROBE_CUBEMAP) + fallbackprobe = GPU_probe_object(material->scene, probe->ob->probe); + else if (material->scene->world) + fallbackprobe = GPU_probe_world(material->scene, material->scene->world); + + if (fallbackprobe) + material->bindedcubeprobe = fallbackprobe->tex; + } + else { + /* XXX : save the probe for unbinding */ + material->bindedcubeprobe = probe->tex; + } + if (material->bindedcubeprobe) { + GPU_texture_bind(material->bindedcubeprobe, 4); + GPU_shader_uniform_texture(shader, material->probeloc, material->bindedcubeprobe); + } + + /* Probe Planar */ + if (probe->type == GPU_PROBE_PLANAR) { + /* XXX : save the reflection for unbinding */ + material->bindedreflprobe = probe->texreflect; + material->bindedrefrprobe = probe->texrefract; + GPU_texture_bind(material->bindedreflprobe, 5); + GPU_shader_uniform_texture(shader, material->reflectloc, material->bindedreflprobe); + GPU_texture_bind(material->bindedrefrprobe, 6); + GPU_shader_uniform_texture(shader, material->refractloc, material->bindedrefrprobe); + } + + /* Planar reflection matrix */ + GPU_shader_uniform_vector(shader, material->planarreflloc, 16, 1, (float *)probe->reflectionmat); + + /* Parallax Correction Matrix */ + GPU_shader_uniform_vector(shader, material->correcmatloc, 16, 1, (float *)probe->correctionmat); + + /* Probe Position */ + GPU_shader_uniform_vector(shader, material->probecoloc, 3, 1, probe->co); + + /* Planar vector */ + GPU_shader_uniform_vector(shader, material->planarvecloc, 3, 1, probe->planevec); + } + else { + /* avoid objects with the same material and no probe attached to have the same SH binded */ + float black[3] = {0.0f, 0.0f, 0.0f}; + for (int i = 0; i < 9; ++i) { + GPU_shader_uniform_vector(shader, material->shloc[i], 3, 1, black); + } + } + + if (pbr_settings->pbr_flag & (GPU_PBR_FLAG_SSR | GPU_PBR_FLAG_SSAO)) { + /* Scene Buffer */ + material->bindedscenebuffer = pbr->scene->tex; + GPU_texture_bind(material->bindedscenebuffer, 7); + GPU_shader_uniform_texture(shader, material->scenebufloc, material->bindedscenebuffer); + + /* Depth Buffer */ + material->bindeddepthbuffer = pbr->scene->depth; + GPU_texture_bind(material->bindeddepthbuffer, 8); + GPU_shader_uniform_texture(shader, material->depthbufloc, material->bindeddepthbuffer); + + /* Pixel proj matrix */ + GPU_shader_uniform_vector(shader, material->pixelprojmatloc, 16, 1, (float *)pbr->scene->pixelprojmat); + + float clipinfo[4]; + clipinfo[0] = pbr->scene->clipsta; + clipinfo[1] = pbr->scene->clipend; + clipinfo[2] = (float)pbr->scene->w; + clipinfo[3] = (float)pbr->scene->h; + GPU_shader_uniform_vector(shader, material->clipinfoloc, 4, 1, clipinfo); + + if (pbr_settings->pbr_flag & GPU_PBR_FLAG_BACKFACE) { + /* Backface Buffer */ + material->bindedbackfacebuffer = pbr->backface->tex; + GPU_texture_bind(material->bindedbackfacebuffer, 9); + GPU_shader_uniform_texture(shader, material->backfacebufloc, material->bindedbackfacebuffer); + } + } + + if (pbr_settings->pbr_flag & GPU_PBR_FLAG_SSR) { + /* SSR Parameters */ + /* x : steps : Maximum number of iteration when raymarching + * y : offset : Step between samples. + * z : attenuation : fallof exponent + * w : thickness : pixel thickness */ + float ssrparams[3]; + ssrparams[0] = (float)pbr_settings->ssr->steps; + ssrparams[1] = pbr_settings->ssr->attenuation; + ssrparams[2] = pbr_settings->ssr->thickness; + GPU_shader_uniform_vector(shader, material->ssrparamsloc, 3, 1, ssrparams); + } + + if (pbr_settings->pbr_flag & GPU_PBR_FLAG_SSAO) { + World *wo = material->scene->world; + /* SSAO Parameters */ + /* x : sample : Number of samples + * y : steps : Steps for the raymarching + * z : distance : Max distance + * w : factor : Blend intensity */ + float ssaoparams[4]; + ssaoparams[0] = pbr_settings->ssao->samples; + ssaoparams[1] = pbr_settings->ssao->steps; + ssaoparams[2] = (wo) ? wo->aodist : 1.0; + ssaoparams[3] = pbr_settings->ssao->factor; + GPU_shader_uniform_vector(shader, material->ssaoparamsloc, 4, 1, ssaoparams); + } } } void GPU_material_unbind(GPUMaterial *material) { if (material->pass) { + /* XXX */ + if (material->bindedcubeprobe) + GPU_texture_unbind(material->bindedcubeprobe); + if (material->bindedreflprobe) + GPU_texture_unbind(material->bindedreflprobe); + if (material->bindedrefrprobe) + GPU_texture_unbind(material->bindedrefrprobe); + if (material->bindedscenebuffer) + GPU_texture_unbind(material->bindedscenebuffer); + if (material->bindeddepthbuffer) + GPU_texture_unbind(material->bindeddepthbuffer); + if (material->bindedbackfacebuffer) + GPU_texture_unbind(material->bindedbackfacebuffer); + if (material->bindedhammersley) + GPU_texture_unbind(material->bindedhammersley); + if (material->bindedjitter) + GPU_texture_unbind(material->bindedjitter); + if (material->bindedltcmat) + GPU_texture_unbind(material->bindedltcmat); + if (material->bindedltcmag) + GPU_texture_unbind(material->bindedltcmag); + material->bound = 0; GPU_pass_unbind(material->pass); } @@ -471,11 +765,15 @@ Scene *GPU_material_scene(GPUMaterial *material) return material->scene; } -GPUMatType GPU_Material_get_type(GPUMaterial *material) +GPUMatType GPU_material_get_type(GPUMaterial *material) { return material->type; } +void GPU_material_set_type(GPUMaterial *material, GPUMatType type) +{ + material->type = type; +} void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs) { @@ -488,6 +786,61 @@ void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link) material->outlink = link; } +void GPU_material_empty_output_link(GPUMaterial *material) +{ + material->outlink = NULL; +} + +GPUNodeLink *GPU_material_get_output_link(GPUMaterial *material) +{ + return material->outlink; +} + +void GPU_material_set_lamp_normal_link(GPUMaterial *material, GPUNodeLink *link) +{ + material->lampNorLink = link; +} + +GPUNodeLink *GPU_material_get_lamp_normal_link(GPUMaterial *material) +{ + return material->lampNorLink; +} + +void GPU_material_set_lamp_position_link(GPUMaterial *material, GPUNodeLink *link) +{ + material->lampPosLink = link; +} + +GPUNodeLink *GPU_material_get_lamp_position_link(GPUMaterial *material) +{ + return material->lampPosLink; +} + +void GPU_material_set_lamp_incoming_link(GPUMaterial *material, GPUNodeLink *link) +{ + material->lampInLink = link; +} + +GPUNodeLink *GPU_material_get_lamp_incoming_link(GPUMaterial *material) +{ + return material->lampInLink; +} + +void GPU_material_set_brdf_link(GPUMaterial *material, GPUBrdfInput *brdf) +{ + material->brdf = brdf; +} + +GPUBrdfInput *GPU_material_get_brdf_link(GPUMaterial *material) +{ + return material->brdf; +} + +GPUNodeLink *GPU_get_world_horicol(void) +{ + return GPU_dynamic_uniform(GPUWorld.horicol, GPU_DYNAMIC_HORIZON_COLOR, NULL); +} + void GPU_material_enable_alpha(GPUMaterial *material) { material->alpha = 1; @@ -526,96 +879,249 @@ bool GPU_material_use_world_space_shading(GPUMaterial *mat) return BKE_scene_use_world_space_shading(mat->scene); } -static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist) +static GPUNodeLink *lamp_get_lightcolor(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink *lv) { - GPUNodeLink *visifac; + // if (lamp->use_realistic_lighting) { - /* from get_lamp_visibility */ - if (lamp->type == LA_SUN || lamp->type == LA_HEMI) { - mat->dynproperty |= DYN_LAMP_VEC; - GPU_link(mat, "lamp_visibility_sun_hemi", - GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac); - return visifac; - } - else { - mat->dynproperty |= DYN_LAMP_CO; - GPU_link(mat, "lamp_visibility_other", - GPU_builtin(GPU_VIEW_POSITION), - GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac); + /* Optimisation only run once */ + if (lamp->nl_lcol) + return lamp->nl_lcol; - if (lamp->type == LA_AREA) - return visifac; + if (lamp->la->use_nodes) { + GPUNodeLink *lamp_normal, *lamp_position, *lamp_incoming; + GPUMatType type = GPU_material_get_type(mat); - switch (lamp->falloff_type) { - case LA_FALLOFF_CONSTANT: - break; - case LA_FALLOFF_INVLINEAR: - GPU_link(mat, "lamp_falloff_invlinear", - GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), *dist, &visifac); - break; - case LA_FALLOFF_INVSQUARE: - GPU_link(mat, "lamp_falloff_invsquare", - GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), *dist, &visifac); - break; - case LA_FALLOFF_SLIDERS: - GPU_link(mat, "lamp_falloff_sliders", - GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), - GPU_dynamic_uniform(&lamp->att1, GPU_DYNAMIC_LAMP_ATT1, lamp->ob), - GPU_dynamic_uniform(&lamp->att2, GPU_DYNAMIC_LAMP_ATT2, lamp->ob), *dist, &visifac); - break; - case LA_FALLOFF_INVCOEFFICIENTS: - GPU_link(mat, "lamp_falloff_invcoefficients", - GPU_dynamic_uniform(&lamp->coeff_const, GPU_DYNAMIC_LAMP_COEFFCONST, lamp->ob), - GPU_dynamic_uniform(&lamp->coeff_lin, GPU_DYNAMIC_LAMP_COEFFLIN, lamp->ob), - GPU_dynamic_uniform(&lamp->coeff_quad, GPU_DYNAMIC_LAMP_COEFFQUAD, lamp->ob), *dist, &visifac); - break; - case LA_FALLOFF_CURVE: - { - float *array; - int size; + /* Position */ + if (lamp->type == LA_SUN || lamp->type == LA_HEMI) { + float zero = 0.0f; + GPU_link(mat, "convert_vec3_to_vec4", lv, GPU_uniform(&zero), &lamp_position); + } + else { + float one = 1.0f; + GPU_link(mat, "convert_vec3_to_vec4", GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), GPU_uniform(&one), &lamp_position); + } - curvemapping_initialize(lamp->curfalloff); - curvemapping_table_RGBA(lamp->curfalloff, &array, &size); - GPU_link(mat, "lamp_falloff_curve", - GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), - GPU_texture(size, array), *dist, &visifac); + /* Normal */ + if (lamp->type == LA_AREA) { + float vec_z[3] = {0.0f, 0.0f, -1.0f}; + GPU_link(mat, "direction_transform_m4v3", GPU_uniform(vec_z), GPU_dynamic_uniform((float*)lamp->dynmat, GPU_DYNAMIC_LAMP_DYNMAT, lamp->ob), &lamp_normal); + } + else { + GPU_link(mat, "set_rgb", lv, &lamp_normal); + } - break; + /* Incoming */ + GPU_link(mat, "set_rgb", lv, &lamp_incoming); + + /* to pass the lamp coordinates to the lamp shadertree */ + GPU_material_set_lamp_normal_link(mat, lamp_normal); + GPU_material_set_lamp_position_link(mat, lamp_position); + GPU_material_set_lamp_incoming_link(mat, lamp_incoming); + + GPU_material_set_type(mat, GPU_MATERIAL_TYPE_LAMP); + + ntreeGPUMaterialNodes(lamp->la->nodetree, mat, NODE_NEW_SHADING); + lamp->nl_lcol = GPU_material_get_output_link(mat); + GPU_material_empty_output_link(mat); + + /* Correct sun Intensity */ + if (lamp->type == LA_SUN || lamp->type == LA_HEMI) { + float factor = 100.0f; + GPU_link(mat, "shade_mul_value_v3", GPU_uniform(&factor), lamp->nl_lcol, &lamp->nl_lcol); } + + /* to switch light on and off */ + GPU_link(mat, "shade_mul_value_v3", GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob), lamp->nl_lcol, &lamp->nl_lcol); + + GPU_material_set_type(mat, type); + } + else { + GPU_link(mat, "set_rgb", GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &lamp->nl_lcol); } - if (lamp->mode & LA_SPHERE) - GPU_link(mat, "lamp_visibility_sphere", - GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), - *dist, visifac, &visifac); + return lamp->nl_lcol; + // } +} - if (lamp->type == LA_SPOT) { - GPUNodeLink *inpr; +static GPUNodeLink *lamp_get_shadowfac(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink *vn, GPUNodeLink *lv) +{ + // if (lamp->use_realistic_lighting) { - if (lamp->mode & LA_SQUARE) { - mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT; - GPU_link(mat, "lamp_visibility_spot_square", - GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), - GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), - GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr); + /* Optimisation only run once */ + if (lamp->nl_shadfac) + return lamp->nl_shadfac; + + if (GPU_lamp_has_shadow_buffer(lamp)) { + GPUNodeLink *inp; + + mat->dynproperty |= DYN_LAMP_PERSMAT; + GPU_link(mat, "shade_inp", vn, lv, &inp); + + if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { + GPU_link(mat, "test_shadowbuf_vsm", GPU_builtin(GPU_VIEW_POSITION), + GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob), + GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob), + GPU_uniform(&lamp->bias), GPU_uniform(&lamp->la->bleedbias), inp, &lamp->nl_shadfac); } else { + GPU_link(mat, "test_shadowbuf", GPU_builtin(GPU_VIEW_POSITION), + GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob), + GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob), + GPU_uniform(&lamp->bias), inp, &lamp->nl_shadfac); + } + } + else { + float one = 1.0f; + GPU_link(mat, "set_value", GPU_uniform(&one), &lamp->nl_shadfac); + } + + return lamp->nl_shadfac; + // } +} + +static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist) +{ + if (lamp->use_realistic_lighting) { + + /* Optimisation only run once */ + if (lamp->nl_lv) + *lv = lamp->nl_lv; + if (lamp->nl_dist) + *dist = lamp->nl_dist; + if (lamp->nl_visifac) + return lamp->nl_visifac; + + /* Cycles Lamp */ + if (lamp->type == LA_SUN || lamp->type == LA_HEMI) { + float sun_fac = 1.0f; + mat->dynproperty |= DYN_LAMP_VEC; + GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), &lamp->nl_lv, &lamp->nl_dist, &lamp->nl_visifac); + GPU_link(mat, "set_value", GPU_uniform(&sun_fac), &lamp->nl_visifac); + *lv = lamp->nl_lv; + *dist = lamp->nl_dist; + return lamp->nl_visifac; + } + else { + mat->dynproperty |= DYN_LAMP_CO; + GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), &lamp->nl_lv, &lamp->nl_dist, &lamp->nl_visifac); + + if (lamp->type == LA_AREA) { + mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO|DYN_LAMP_MAT; + *lv = lamp->nl_lv; + *dist = lamp->nl_dist; + return lamp->nl_visifac; + } + + if (lamp->type == LA_SPOT) { + GPUNodeLink *inpr; + mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT; GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), - GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), - GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr); + GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), + GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), lamp->nl_lv, &inpr); + GPU_link(mat, "lamp_visibility_spot", + GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), + GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), + inpr, lamp->nl_visifac, &lamp->nl_visifac); } - - GPU_link(mat, "lamp_visibility_spot", - GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), - GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), - inpr, visifac, &visifac); + + + *lv = lamp->nl_lv; + *dist = lamp->nl_dist; + return lamp->nl_visifac; } + } + else { + GPUNodeLink *visifac; + + /* BI Lamp */ + if (lamp->type == LA_SUN || lamp->type == LA_HEMI) { + mat->dynproperty |= DYN_LAMP_VEC; + GPU_link(mat, "lamp_visibility_sun_hemi", + GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac); + return visifac; + } + else { + mat->dynproperty |= DYN_LAMP_CO; + GPU_link(mat, "lamp_visibility_other", + GPU_builtin(GPU_VIEW_POSITION), + GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac); + + if (lamp->type == LA_AREA) + return visifac; + + switch (lamp->falloff_type) { + case LA_FALLOFF_CONSTANT: + break; + case LA_FALLOFF_INVLINEAR: + GPU_link(mat, "lamp_falloff_invlinear", + GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), *dist, &visifac); + break; + case LA_FALLOFF_INVSQUARE: + GPU_link(mat, "lamp_falloff_invsquare", + GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), *dist, &visifac); + break; + case LA_FALLOFF_SLIDERS: + GPU_link(mat, "lamp_falloff_sliders", + GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), + GPU_dynamic_uniform(&lamp->att1, GPU_DYNAMIC_LAMP_ATT1, lamp->ob), + GPU_dynamic_uniform(&lamp->att2, GPU_DYNAMIC_LAMP_ATT2, lamp->ob), *dist, &visifac); + break; + case LA_FALLOFF_INVCOEFFICIENTS: + GPU_link(mat, "lamp_falloff_invcoefficients", + GPU_dynamic_uniform(&lamp->coeff_const, GPU_DYNAMIC_LAMP_COEFFCONST, lamp->ob), + GPU_dynamic_uniform(&lamp->coeff_lin, GPU_DYNAMIC_LAMP_COEFFLIN, lamp->ob), + GPU_dynamic_uniform(&lamp->coeff_quad, GPU_DYNAMIC_LAMP_COEFFQUAD, lamp->ob), *dist, &visifac); + break; + case LA_FALLOFF_CURVE: + { + float *array; + int size; + + curvemapping_initialize(lamp->curfalloff); + curvemapping_table_RGBA(lamp->curfalloff, &array, &size); + GPU_link(mat, "lamp_falloff_curve", + GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), + GPU_texture(size, array), *dist, &visifac); + + break; + } + } + + if (lamp->mode & LA_SPHERE) + GPU_link(mat, "lamp_visibility_sphere", + GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), + *dist, visifac, &visifac); + + if (lamp->type == LA_SPOT) { + GPUNodeLink *inpr; - GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac); + if (lamp->mode & LA_SQUARE) { + mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT; + GPU_link(mat, "lamp_visibility_spot_square", + GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), + GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), + GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr); + } + else { + mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT; + GPU_link(mat, "lamp_visibility_spot_circle", + GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), + GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), + GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr); + } + + GPU_link(mat, "lamp_visibility_spot", + GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), + GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), + inpr, visifac, &visifac); + } + + GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac); - return visifac; + return visifac; + } } } @@ -812,7 +1318,7 @@ static void shade_light_textures(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink ** GPU_link(mat, "shade_light_texture", GPU_builtin(GPU_VIEW_POSITION), - GPU_image(mtex->tex->ima, &mtex->tex->iuser, false), + GPU_image(mtex->tex->ima, &mtex->tex->iuser, false, false), GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob), &tex_rgb); texture_rgb_blend(mat, tex_rgb, *rgb, GPU_uniform(&one), GPU_uniform(&mtex->colfac), mtex->blendtype, rgb); @@ -858,9 +1364,9 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), vn, - GPU_uniform((float *)area), - GPU_uniform(&areasize), - GPU_uniform(&lamp->k), &inp); + GPU_dynamic_uniform((float*)lamp->dynmat, GPU_DYNAMIC_LAMP_DYNMAT, lamp->ob), + GPU_dynamic_uniform(&lamp->area_size, GPU_DYNAMIC_LAMP_SIZEX, lamp->ob), + GPU_dynamic_uniform(&lamp->area_size_y, GPU_DYNAMIC_LAMP_SIZEY, lamp->ob), &inp); } is = inp; /* Lambert */ @@ -992,8 +1498,6 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac); } - if (lamp->type == LA_AREA) - GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac); GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t); @@ -1018,12 +1522,13 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) { Base *base; Scene *sce_iter; - + bool use_realistic_preview = BKE_scene_use_new_shading_nodes(shi->gpumat->scene); + for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) { Object *ob = base->object; if (ob->type == OB_LAMP) { - GPULamp *lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL); + GPULamp *lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL, use_realistic_preview); if (lamp) shade_one_light(shi, shr, lamp); } @@ -1039,7 +1544,7 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) copy_m4_m4(omat, ob_iter->obmat); copy_m4_m4(ob_iter->obmat, dob->mat); - GPULamp *lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob_iter, ob); + GPULamp *lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob_iter, ob, use_realistic_preview); if (lamp) shade_one_light(shi, shr, lamp); @@ -1245,7 +1750,7 @@ static void do_material_tex(GPUShadeInput *shi) ((tex->type == TEX_ENVMAP) && (mtex->texco == TEXCO_REFL)))) { if (tex->type == TEX_IMAGE) { - GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false), &tin, &trgb); + GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false, false), &tin, &trgb); } else { GPU_link(mat, "mtex_cube_map_refl", @@ -1345,7 +1850,7 @@ static void do_material_tex(GPUShadeInput *shi) if (tex->imaflag & TEX_NORMALMAP) { /* normalmap image */ - GPU_link(mat, "mtex_normal", texco, GPU_image(tex->ima, &tex->iuser, true), &tnor); + GPU_link(mat, "mtex_normal", texco, GPU_image(tex->ima, &tex->iuser, true, false), &tnor); if (mtex->norfac < 0.0f) GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor); @@ -1492,27 +1997,27 @@ static void do_material_tex(GPUShadeInput *shi) if (found_deriv_map) { GPU_link(mat, "mtex_bump_deriv", - texco, GPU_image(tex->ima, &tex->iuser, true), + texco, GPU_image(tex->ima, &tex->iuser, true, false), GPU_uniform(&ima_x), GPU_uniform(&ima_y), tnorfac, &dBs, &dBt); } else if (mtex->texflag & MTEX_3TAP_BUMP) GPU_link(mat, "mtex_bump_tap3", - texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac, + texco, GPU_image(tex->ima, &tex->iuser, true, false), tnorfac, &dBs, &dBt); else if (mtex->texflag & MTEX_5TAP_BUMP) GPU_link(mat, "mtex_bump_tap5", - texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac, + texco, GPU_image(tex->ima, &tex->iuser, true, false), tnorfac, &dBs, &dBt); else if (mtex->texflag & MTEX_BICUBIC_BUMP) { if (GPU_bicubic_bump_support()) { GPU_link(mat, "mtex_bump_bicubic", - texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac, + texco, GPU_image(tex->ima, &tex->iuser, true, false), tnorfac, &dBs, &dBt); } else { GPU_link(mat, "mtex_bump_tap5", - texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac, + texco, GPU_image(tex->ima, &tex->iuser, true, false), tnorfac, &dBs, &dBt); } } @@ -1522,7 +2027,7 @@ static void do_material_tex(GPUShadeInput *shi) float imag_tspace_dimension_y = aspect * imag_tspace_dimension_x; GPU_link(mat, "mtex_bump_apply_texspace", fDet, dBs, dBt, vR1, vR2, - GPU_image(tex->ima, &tex->iuser, true), texco, + GPU_image(tex->ima, &tex->iuser, true, false), texco, GPU_uniform(&imag_tspace_dimension_x), GPU_uniform(&imag_tspace_dimension_y), vNacc, &vNacc, &shi->vn); @@ -1824,6 +2329,464 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) } } +/* PBR Viewport Material Mode */ + +void GPU_brdf_input_initialize(GPUBrdfInput *brdf) +{ + memset(brdf, 0, sizeof(*brdf)); +} + +static void prep_brdf_input(GPUBrdfInput *brdf) +{ + GPUNodeLink *normal = NULL; + GPUNodeLink *color = NULL; + GPUNodeLink *roughness = NULL; + GPUNodeLink *ior = NULL; + GPUNodeLink *sigma = NULL; + GPUNodeLink *toon_size = NULL; + GPUNodeLink *toon_smooth = NULL; + GPUNodeLink *anisotropy = NULL; + GPUNodeLink *aniso_rotation = NULL; + GPUNodeLink *aniso_tangent = NULL; + + /* Normal & Tangent can't be NULL */ + if (brdf->normal) + GPU_link(brdf->mat, "set_rgb", brdf->normal, &normal); + else + GPU_link(brdf->mat, "set_rgb", GPU_builtin(GPU_VIEW_NORMAL), &normal); + + if (brdf->aniso_tangent) + GPU_link(brdf->mat, "set_rgb", brdf->aniso_tangent, &aniso_tangent); + else + GPU_link(brdf->mat, "default_tangent", GPU_builtin(GPU_VIEW_NORMAL), GPU_attribute(CD_ORCO, ""), + GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), + GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &aniso_tangent); + + if (brdf->color) + GPU_link(brdf->mat, "set_rgba", brdf->color, &color); + else + GPU_link(brdf->mat, "set_rgba_zero", &color); + + if (brdf->roughness) + GPU_link(brdf->mat, "set_value", brdf->roughness, &roughness); + else + GPU_link(brdf->mat, "set_value_zero", &roughness); + + if (brdf->ior) + GPU_link(brdf->mat, "set_value", brdf->ior, &ior); + else + GPU_link(brdf->mat, "set_value_zero", &ior); + + if (brdf->sigma) + GPU_link(brdf->mat, "set_value", brdf->sigma, &sigma); + else + GPU_link(brdf->mat, "set_value_zero", &sigma); + + if (brdf->toon_size) + GPU_link(brdf->mat, "set_value", brdf->toon_size, &toon_size); + else + GPU_link(brdf->mat, "set_value_zero", &toon_size); + + if (brdf->toon_smooth) + GPU_link(brdf->mat, "set_value", brdf->toon_smooth, &toon_smooth); + else + GPU_link(brdf->mat, "set_value_zero", &toon_smooth); + + if (brdf->anisotropy) + GPU_link(brdf->mat, "set_value", brdf->anisotropy, &anisotropy); + else + GPU_link(brdf->mat, "set_value_zero", &anisotropy); + + if (brdf->aniso_rotation) + GPU_link(brdf->mat, "set_value", brdf->aniso_rotation, &aniso_rotation); + else + GPU_link(brdf->mat, "set_value_zero", &aniso_rotation); + + GPU_link(brdf->mat, "set_rgba_zero", &brdf->output); + + brdf->normal = normal; + brdf->color = color; + brdf->roughness = roughness; + brdf->ior = ior; + brdf->sigma = sigma; + brdf->toon_size = toon_size; + brdf->toon_smooth = toon_smooth; + brdf->anisotropy = anisotropy; + brdf->aniso_rotation = aniso_rotation; + brdf->aniso_tangent = aniso_tangent; +} + +static bool do_light(GPUBrdfInput *brdf, GPULamp *lamp) +{ + if (lamp->mode & LA_NO_DIFF) + if (brdf->type == GPU_BRDF_DIFFUSE || brdf->type == GPU_BRDF_TRANSLUCENT) + return false; + + if (lamp->mode & LA_NO_SPEC) + if (!(brdf->type == GPU_BRDF_DIFFUSE || brdf->type == GPU_BRDF_TRANSLUCENT)) + return false; + + return true; +} + +static const char *brdf_light_function(GPUBrdfType brdftype, int lamptype) +{ + if (brdftype == GPU_BRDF_ANISO_GGX) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_anisotropic_ggx_sun_light"; + case LA_AREA : return "bsdf_anisotropic_ggx_area_light"; + default : return "bsdf_anisotropic_ggx_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_ANISO_BECKMANN) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_anisotropic_beckmann_sun_light"; + case LA_AREA : return "bsdf_anisotropic_beckmann_area_light"; + default : return "bsdf_anisotropic_beckmann_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_ANISO_ASHIKHMIN_SHIRLEY) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_anisotropic_ashikhmin_shirley_sun_light"; + case LA_AREA : return "bsdf_anisotropic_ashikhmin_shirley_area_light"; + default : return "bsdf_anisotropic_ashikhmin_shirley_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_GLOSSY_GGX) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_glossy_ggx_sun_light"; + case LA_AREA : return "bsdf_glossy_ggx_area_light"; + default : return "bsdf_glossy_ggx_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_GLOSSY_BECKMANN) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_glossy_beckmann_sun_light"; + case LA_AREA : return "bsdf_glossy_beckmann_area_light"; + default : return "bsdf_glossy_beckmann_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_GLOSSY_ASHIKHMIN_SHIRLEY) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_glossy_ashikhmin_shirley_sun_light"; + case LA_AREA : return "bsdf_glossy_ashikhmin_shirley_area_light"; + default : return "bsdf_glossy_ashikhmin_shirley_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_GLOSSY_SHARP) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_glossy_sharp_sun_light"; + case LA_AREA : return "bsdf_glossy_sharp_area_light"; + default : return "bsdf_glossy_sharp_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_REFRACT_GGX) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_refract_ggx_sun_light"; + case LA_AREA : return "bsdf_refract_ggx_area_light"; + default : return "bsdf_refract_ggx_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_REFRACT_BECKMANN) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_refract_beckmann_sun_light"; + case LA_AREA : return "bsdf_refract_beckmann_area_light"; + default : return "bsdf_refract_beckmann_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_REFRACT_SHARP) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_refract_sharp_sun_light"; + case LA_AREA : return "bsdf_refract_sharp_area_light"; + default : return "bsdf_refract_sharp_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_GLASS_GGX) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_glass_ggx_sun_light"; + case LA_AREA : return "bsdf_glass_ggx_area_light"; + default : return "bsdf_glass_ggx_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_GLASS_BECKMANN) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_glass_beckmann_sun_light"; + case LA_AREA : return "bsdf_glass_beckmann_area_light"; + default : return "bsdf_glass_beckmann_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_GLASS_SHARP) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_glass_sharp_sun_light"; + case LA_AREA : return "bsdf_glass_sharp_area_light"; + default : return "bsdf_glass_sharp_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_VELVET) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_velvet_sun_light"; + case LA_AREA : return "bsdf_velvet_area_light"; + default : return "bsdf_velvet_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_TRANSLUCENT) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_translucent_sun_light"; + case LA_AREA : return "bsdf_translucent_area_light"; + default : return "bsdf_translucent_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_TOON_DIFFUSE) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_toon_diffuse_sun_light"; + case LA_AREA : return "bsdf_toon_diffuse_area_light"; + default : return "bsdf_toon_diffuse_sphere_light"; + } + } + else if (brdftype == GPU_BRDF_TOON_GLOSSY) { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_toon_glossy_sun_light"; + case LA_AREA : return "bsdf_toon_glossy_area_light"; + default : return "bsdf_toon_glossy_sphere_light"; + } + } + else /* (brdftype == GPU_BRDF_DIFFUSE) */ { + switch (lamptype) { + case LA_SUN : + case LA_HEMI : return "bsdf_diffuse_sun_light"; + case LA_AREA : return "bsdf_diffuse_area_light"; + default : return "bsdf_diffuse_sphere_light"; + } + } +} + +static void shade_one_brdf_light(GPUBrdfInput *brdf, GPULamp *lamp) +{ + GPUMaterial *mat = brdf->mat; + GPUNodeLink *lv = NULL, *dist = NULL, *visifac = NULL, *vn = NULL, *view = NULL; + GPUNodeLink *shadfac = NULL, *lcol, *output; + float one = 1.0f; + + /* Early out */ + if (!do_light(brdf, lamp)) return; + + /* Lamp vector, distance and visibility factor */ + visifac = lamp_get_visibility(mat, lamp, &lv, &dist); + + /* View Position */ + if (((brdf->type == GPU_BRDF_TRANSLUCENT || + brdf->type == GPU_BRDF_DIFFUSE || + brdf->type == GPU_BRDF_GLOSSY_GGX || + brdf->type == GPU_BRDF_GLOSSY_ASHIKHMIN_SHIRLEY || + brdf->type == GPU_BRDF_GLOSSY_BECKMANN) && (lamp->type == LA_AREA)) || + ((brdf->type == GPU_BRDF_GLOSSY_GGX || + brdf->type == GPU_BRDF_REFRACT_GGX || + brdf->type == GPU_BRDF_GLASS_GGX) && (lamp->type == LA_LOCAL || lamp->type == LA_SPOT))) + GPU_link(mat, "set_rgb", GPU_builtin(GPU_VIEW_POSITION), &view); + else + GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &view); + + /* View normal */ + GPU_link(mat, "viewN_to_shadeN", brdf->normal, &vn); + + /* Lamp Color */ + lcol = lamp_get_lightcolor(mat, lamp, lv); + + /* BRDF evaluation */ + GPU_link(mat, brdf_light_function(brdf->type, lamp->type), + vn, brdf->aniso_tangent, lv, view, + GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), dist, + GPU_dynamic_uniform(&lamp->area_size, GPU_DYNAMIC_LAMP_SIZEX, lamp->ob), + GPU_dynamic_uniform(&lamp->area_size_y, GPU_DYNAMIC_LAMP_SIZEY, lamp->ob), + GPU_dynamic_uniform((float *)lamp->areavec, GPU_DYNAMIC_LAMP_AREASCALE, lamp->ob), + GPU_dynamic_uniform((float *)lamp->dynmat, GPU_DYNAMIC_LAMP_DYNMAT, lamp->ob), + brdf->roughness, brdf->ior, brdf->sigma, brdf->toon_size, brdf->toon_smooth, brdf->anisotropy, brdf->aniso_rotation, &output); + + + /* Shadowing */ + if (brdf->type != GPU_BRDF_REFRACT_GGX && + brdf->type != GPU_BRDF_GLASS_GGX && + brdf->type != GPU_BRDF_REFRACT_SHARP && + brdf->type != GPU_BRDF_GLASS_SHARP && + brdf->type != GPU_BRDF_TRANSLUCENT) { + shadfac = lamp_get_shadowfac(mat, lamp, vn, lv); + } + else { + float one = 1.0f; + GPU_link(mat, "set_value", GPU_uniform(&one), &shadfac); + } + + /* Applying shadow and lamp color */ + GPU_link(mat, "shade_mul_value", shadfac, lcol, &lcol); + GPU_link(mat, "shade_mul_value", visifac, lcol, &lcol); + GPU_link(mat, "shade_madd_clamped", brdf->output, output, lcol, &brdf->output); + + add_user_list(&mat->lamps, lamp); + add_user_list(&lamp->materials, mat->ma); +} + +static const char *brdf_env_sampling_function(GPUBrdfType brdftype) +{ + if (brdftype == GPU_BRDF_ANISO_GGX) + return "env_sampling_aniso_ggx"; + else if (brdftype == GPU_BRDF_ANISO_BECKMANN) + return "env_sampling_aniso_beckmann"; + else if (brdftype == GPU_BRDF_ANISO_ASHIKHMIN_SHIRLEY) + return "env_sampling_aniso_ashikhmin_shirley"; + else if (brdftype == GPU_BRDF_GLOSSY_GGX) + return "env_sampling_glossy_ggx"; + else if (brdftype == GPU_BRDF_GLOSSY_BECKMANN) + return "env_sampling_glossy_beckmann"; + else if (brdftype == GPU_BRDF_GLOSSY_ASHIKHMIN_SHIRLEY) + return "env_sampling_glossy_ashikhmin_shirley"; + else if (brdftype == GPU_BRDF_GLOSSY_SHARP) + return "env_sampling_glossy_sharp"; + else if (brdftype == GPU_BRDF_REFRACT_GGX) + return "env_sampling_refract_ggx"; + else if (brdftype == GPU_BRDF_REFRACT_BECKMANN) + return "env_sampling_refract_beckmann"; + else if (brdftype == GPU_BRDF_REFRACT_SHARP) + return "env_sampling_refract_sharp"; + else if (brdftype == GPU_BRDF_GLASS_GGX) + return "env_sampling_glass_ggx"; + else if (brdftype == GPU_BRDF_GLASS_BECKMANN) + return "env_sampling_glass_beckmann"; + else if (brdftype == GPU_BRDF_GLASS_SHARP) + return "env_sampling_glass_sharp"; + else if (brdftype == GPU_BRDF_VELVET) + return "env_sampling_velvet"; + else if (brdftype == GPU_BRDF_TRANSLUCENT) + return "env_sampling_translucent"; + else if (brdftype == GPU_BRDF_TRANSPARENT) + return "env_sampling_transparent"; + else if (brdftype == GPU_BRDF_TOON_DIFFUSE) + return "env_sampling_toon_diffuse"; + else if (brdftype == GPU_BRDF_TOON_GLOSSY) + return "env_sampling_toon_glossy"; + else if (brdftype == GPU_BRDF_AMBIENT_OCCLUSION) + return "env_sampling_ambient_occlusion"; + else /* (brdftype == GPU_BRDF_DIFFUSE) */ + return "env_sampling_diffuse"; +} + +static GPUNodeLink *brdf_sample_env(GPUBrdfInput *brdf) +{ + GPUMaterial *mat = brdf->mat; + GPUMatType type = GPU_material_get_type(mat); + GPUNodeLink *envlight, *ambient_occlusion; + + GPU_link(mat, "direction_transform_m4v3", brdf->normal, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &brdf->normal); + GPU_link(mat, "vect_normalize", brdf->normal, &brdf->normal); + GPU_link(mat, "direction_transform_m4v3", brdf->aniso_tangent, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &brdf->aniso_tangent); + GPU_link(mat, "vect_normalize", brdf->aniso_tangent, &brdf->aniso_tangent); + + /* Ambient Occlusion */ + if (!mat->ln_ssao) + GPU_link(mat, "ssao", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), &mat->ln_ssao); + GPU_link(mat, "set_value", mat->ln_ssao, &ambient_occlusion); + + /* Environment Sampling */ + GPU_link(mat, brdf_env_sampling_function(brdf->type), + GPU_builtin(GPU_PBR), GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), + brdf->normal, brdf->aniso_tangent, brdf->roughness, brdf->ior, brdf->sigma, + brdf->toon_size, brdf->toon_smooth, brdf->anisotropy, brdf->aniso_rotation, + ambient_occlusion, &envlight); + + /* prevent undefined result (eg dividing by 0) giving infinity inside HDR images */ + GPU_link(mat, "shade_clamp_positive", envlight, &envlight); + + return envlight; +} + +void GPU_shade_BRDF(GPUBrdfInput *brdf) +{ + Scene *scene = GPU_material_scene(brdf->mat); + GPUMaterial *mat = brdf->mat; + World *wo = scene->world; + Base *base; + Object *ob; + Scene *sce_iter; + GPULamp *lamp; + GPUNodeLink *envlight; + float one = 1.0f; + int i = 0; + bool real_shading = GPU_material_use_new_shading_nodes(mat); + + prep_brdf_input(brdf); + + /* Early out + * If there is already a valid output do not attempt to do the world sampling. + * Because the output would be overwriten when sampling the world. + * This save also some steps. */ + if (GPU_material_get_output_link(mat)) + return; + + /* Lamps */ + if ((brdf->type != GPU_BRDF_TRANSPARENT) && (brdf->type != GPU_BRDF_AMBIENT_OCCLUSION)) { + for (SETLOOPER(mat->scene, sce_iter, base)) { + ob = base->object; + + if (ob->type == OB_LAMP) { + lamp = GPU_lamp_from_blender(mat->scene, ob, NULL, real_shading); + if (lamp) + shade_one_brdf_light(brdf, lamp); + } + + if (ob->transflag & OB_DUPLI) { + DupliObject *dob; + ListBase *lb = object_duplilist(G.main->eval_ctx, mat->scene, ob); + + for (dob = lb->first; dob; dob = dob->next) { + Object *ob_iter = dob->ob; + + if (ob_iter->type == OB_LAMP) { + float omat[4][4]; + copy_m4_m4(omat, ob_iter->obmat); + copy_m4_m4(ob_iter->obmat, dob->mat); + + lamp = GPU_lamp_from_blender(mat->scene, ob_iter, ob, real_shading); + if (lamp) + shade_one_brdf_light(brdf, lamp); + + copy_m4_m4(ob_iter->obmat, omat); + } + } + + free_object_duplilist(lb); + } + } + } + + /* prevent only shadow lamps from producing negative colors.*/ + GPU_link(mat, "shade_clamp_positive", brdf->output, &brdf->output); + + /* Environement Light */ + envlight = brdf_sample_env(brdf); + + /* Combine Lighting */ + if (brdf->type == GPU_BRDF_TRANSPARENT) + GPU_link(mat, "node_bsdf_transparent", brdf->color, envlight, &brdf->output); + else + GPU_link(mat, "node_bsdf_opaque", brdf->color, envlight, brdf->output, &brdf->output); +} + static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) { GPUShadeInput shi; @@ -1838,10 +2801,28 @@ static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) static GPUNodeLink *gpu_material_diffuse_bsdf(GPUMaterial *mat, Material *ma) { static float roughness = 0.0f; + static float ambient[4] = {0.2f, 0.2f, 0.2f, 1.0f}; GPUNodeLink *outlink; - GPU_link(mat, "node_bsdf_diffuse", - GPU_uniform(&ma->r), GPU_uniform(&roughness), GPU_builtin(GPU_VIEW_NORMAL), &outlink); + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; + + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.type = GPU_BRDF_DIFFUSE; + brdf.color = GPU_uniform(&ma->r); + brdf.roughness = GPU_uniform(&roughness); + brdf.normal = GPU_builtin(GPU_VIEW_NORMAL); + + GPU_shade_BRDF(&brdf); + + outlink = brdf.output; + } + else + GPU_link(mat, "node_bsdf_diffuse_lights", + GPU_uniform(&ma->r), GPU_uniform(&roughness), GPU_builtin(GPU_VIEW_NORMAL), + GPU_builtin(GPU_VIEW_POSITION), GPU_uniform((float *)ambient), &outlink); return outlink; } @@ -1881,6 +2862,8 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv mat->scene = scene; mat->type = GPU_MATERIAL_TYPE_MESH; mat->is_opensubdiv = use_opensubdiv; + mat->is_planar_probe = false; + mat->parallax_correc = 0; if (ma->preview && ma->preview->rect[0]) { outlink = gpu_material_preview_matcap(mat, ma); @@ -1960,16 +2943,16 @@ static void do_world_tex(GPUShadeInput *shi, struct World *wo, GPUNodeLink **hor if (ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f) GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco); if (mtex->texco == TEXCO_EQUIRECTMAP) { - GPU_link(mat, "node_tex_environment_equirectangular", texco, GPU_image(tex->ima, &tex->iuser, false), &trgb); + GPU_link(mat, "node_tex_environment_equirectangular", texco, GPU_image(tex->ima, &tex->iuser, false, true), &trgb); } else if (mtex->texco == TEXCO_ANGMAP) { - GPU_link(mat, "node_tex_environment_mirror_ball", texco, GPU_image(tex->ima, &tex->iuser, false), &trgb); + GPU_link(mat, "node_tex_environment_mirror_ball", texco, GPU_image(tex->ima, &tex->iuser, false, true), &trgb); } else { if (tex->type == TEX_ENVMAP) GPU_link(mat, "mtex_cube_map", texco, GPU_cube_map(tex->ima, &tex->iuser, false), &tin, &trgb); else if (tex->type == TEX_IMAGE) - GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false), &tin, &trgb); + GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false, false), &tin, &trgb); } rgbnor = TEX_RGB; if (tex->type == TEX_IMAGE || tex->type == TEX_ENVMAP) @@ -2110,7 +3093,7 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) mat = GPU_material_construct_begin(NULL); mat->scene = scene; mat->type = GPU_MATERIAL_TYPE_WORLD; - + /* create nodes */ if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes) ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING); @@ -2135,17 +3118,26 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) return mat; } - -GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv) +GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv, bool use_realistic_preview, bool use_planar_probe, + bool use_alpha_as_depth, bool use_backface_depth, bool use_ssr, bool use_ssao, int parallax_correc) { GPUMaterial *mat; GPUNodeLink *outlink; LinkData *link; + int type = (use_realistic_preview)? GPU_MATERIAL_TYPE_MESH_REAL_SH : GPU_MATERIAL_TYPE_MESH; + bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); for (link = ma->gpumaterial.first; link; link = link->next) { GPUMaterial *current_material = (GPUMaterial *)link->data; if (current_material->scene == scene && - current_material->is_opensubdiv == use_opensubdiv) + current_material->is_opensubdiv == use_opensubdiv && + current_material->type == type && + current_material->is_alpha_as_depth == use_alpha_as_depth && + current_material->is_planar_probe == use_planar_probe && + current_material->use_backface_depth == use_backface_depth && + current_material->use_ssr == use_ssr && + current_material->use_ssao == use_ssao && + current_material->parallax_correc == parallax_correc) { return current_material; } @@ -2154,16 +3146,43 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_open /* allocate material */ mat = GPU_material_construct_begin(ma); mat->scene = scene; - mat->type = GPU_MATERIAL_TYPE_MESH; + mat->type = type; mat->is_opensubdiv = use_opensubdiv; + mat->parallax_correc = parallax_correc; + mat->is_planar_probe = use_planar_probe; + mat->is_alpha_as_depth = use_alpha_as_depth; + mat->use_backface_depth = use_backface_depth; + mat->use_ssr = use_ssr; + mat->use_ssao = use_ssao; /* render pipeline option */ - bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); if (!new_shading_nodes && (ma->mode & MA_TRANSP)) GPU_material_enable_alpha(mat); else if (new_shading_nodes && ma->alpha < 1.0f) GPU_material_enable_alpha(mat); + /* Resetting all light optimisation nodelinks */ + { + Base *base; + Scene *sce_iter; + Object *ob; + GPULamp *lamp; + + for (SETLOOPER(mat->scene, sce_iter, base)) { + ob = base->object; + if (ob->type == OB_LAMP) { + lamp = GPU_lamp_from_blender(mat->scene, ob, NULL, new_shading_nodes); + if (lamp) { + lamp->nl_lv = NULL; + lamp->nl_dist = NULL; + lamp->nl_visifac = NULL; + lamp->nl_shadfac = NULL; + lamp->nl_lcol = NULL; + } + } + } + } + if (!(scene->gm.flag & GAME_GLSL_NO_NODES) && ma->nodetree && ma->use_nodes) { /* create nodes */ if (new_shading_nodes) @@ -2224,12 +3243,23 @@ void GPU_materials_free(void) static void gpu_lamp_calc_winmat(GPULamp *lamp) { - float temp, angle, pixsize, wsize; + float temp, angle, pixsize, wsize, hsize; if (lamp->type == LA_SUN) { wsize = lamp->la->shadow_frustum_size; orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend); } + else if (lamp->type == LA_AREA) { + wsize = hsize = lamp->area_size; + + if (lamp->la->area_shape != LA_AREA_SQUARE) + hsize = lamp->area_size_y; + + wsize *= lamp->areavec[0]; + hsize *= lamp->areavec[1]; + + perspective_m4(lamp->winmat, -wsize, wsize, -hsize, hsize, lamp->d, lamp->d + lamp->clipend); + } else if (lamp->type == LA_SPOT) { angle = saacos(lamp->spotsi); temp = 0.5f * lamp->size * cosf(angle) / sinf(angle); @@ -2265,16 +3295,26 @@ void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]) lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2]; } + lamp->areavec[0] = obmat_scale[0]; + lamp->areavec[1] = obmat_scale[1]; + if (GPU_lamp_has_shadow_buffer(lamp)) { /* makeshadowbuf */ gpu_lamp_calc_winmat(lamp); } } +void GPU_lamp_update_size(GPULamp *lamp, float sizex, float sizey) +{ + lamp->area_size = sizex; + lamp->area_size_y = sizey; +} + void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy) { lamp->energy = energy; if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; + if (BKE_scene_use_new_shading_nodes(lamp->scene)) lamp->energy = 1.0f; lamp->col[0] = r; lamp->col[1] = g; @@ -2298,7 +3338,7 @@ void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend) lamp->spotbl = (1.0f - lamp->spotsi) * spotblend; } -static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) +static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp, bool use_realistic_preview) { lamp->scene = scene; lamp->ob = ob; @@ -2309,6 +3349,9 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l lamp->mode = la->mode; lamp->type = la->type; + lamp->area_size = la->area_size; + lamp->area_size_y = la->area_sizey; + lamp->energy = la->energy; if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; @@ -2343,6 +3386,15 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l /* arbitrary correction for the fact we do no soft transition */ lamp->bias *= 0.25f; + + if (use_realistic_preview) { + lamp->mode &= ~(LA_HALO | LA_NEG | LA_SPHERE | LA_SQUARE); + lamp->energy = 1.0f; + lamp->use_realistic_lighting = true; + + if (la->area_shape == LA_AREA_SQUARE) + lamp->area_size_y = la->area_size; + } } static void gpu_lamp_shadow_free(GPULamp *lamp) @@ -2369,7 +3421,7 @@ static void gpu_lamp_shadow_free(GPULamp *lamp) } } -GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) +GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par, bool use_realistic_preview) { Lamp *la; GPULamp *lamp; @@ -2389,9 +3441,10 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) BLI_addtail(&ob->gpulamp, link); la = ob->data; - gpu_lamp_from_blender(scene, ob, par, la, lamp); + gpu_lamp_from_blender(scene, ob, par, la, lamp, use_realistic_preview); - if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) || + if (((la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) && use_realistic_preview && (la->type == LA_SUN || la->type == LA_SPOT || la->type == LA_AREA)) || + (la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) || (la->type == LA_SUN && (la->mode & LA_SHAD_RAY))) { /* opengl */ @@ -2402,6 +3455,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) } if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { + /* Shadow depth map */ lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL); if (!lamp->depthtex) { @@ -2473,8 +3527,9 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) { gpu_lamp_shadow_free(lamp); - return lamp; - } + return lamp; + } + } GPU_framebuffer_restore(); @@ -2528,10 +3583,14 @@ bool GPU_lamp_has_shadow_buffer(GPULamp *lamp) void GPU_lamp_update_buffer_mats(GPULamp *lamp) { - float rangemat[4][4], persmat[4][4]; + float rangemat[4][4], persmat[4][4], tempmat[4][4]; /* initshadowbuf */ - invert_m4_m4(lamp->viewmat, lamp->obmat); + copy_m4_m4(tempmat, lamp->obmat); + if (lamp->type == LA_AREA) { + translate_m4(tempmat, 0.0, 0.0, lamp->d); + } + invert_m4_m4(lamp->viewmat, tempmat); normalize_v3(lamp->viewmat[0]); normalize_v3(lamp->viewmat[1]); normalize_v3(lamp->viewmat[2]); @@ -2572,6 +3631,10 @@ void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { GPU_shader_unbind(); GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex); + if (lamp->use_realistic_lighting) { + /* XXX Second blur to hide artifacts */ + GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex); + } } GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex); @@ -2673,7 +3736,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) int liblen, fraglen; /* TODO(sergey): How to determine whether we need OSD or not here? */ - GPUMaterial *mat = GPU_material_from_blender(scene, ma, false); + GPUMaterial *mat = GPU_material_from_blender(scene, ma, false, false, false, false, false, false, false, 0); GPUPass *pass = (mat) ? mat->pass : NULL; if (pass && pass->fragmentcode && pass->vertexcode) { diff --git a/source/blender/gpu/intern/gpu_pbr.c b/source/blender/gpu/intern/gpu_pbr.c new file mode 100644 index 00000000000..de22739db4a --- /dev/null +++ b/source/blender/gpu/intern/gpu_pbr.c @@ -0,0 +1,327 @@ +/* + * ***** 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) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Clement Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gpu_pbr.c + * \ingroup gpu + * + * Manages lut textures and render passes for pbr rendering + */ + + +#include <math.h> +#include <string.h> +#include "MEM_guardedalloc.h" + +#include "DNA_gpu_types.h" + +#include "BLI_math.h" + +#include "GPU_texture.h" +#include "GPU_framebuffer.h" +#include "GPU_pbr.h" +#include "GPU_draw.h" + +#include "gpu_codegen.h" + +#include <string.h> + +/* Structs */ + +/* Functions */ + +void GPU_scenebuf_free(GPUScreenBuffer *buf) +{ + if (buf->fb) { + GPU_framebuffer_free(buf->fb); + buf->fb = NULL; + } + if (buf->tex) { + GPU_texture_free(buf->tex); + buf->tex = NULL; + } + if (buf->depth) { + GPU_texture_free(buf->depth); + buf->depth = NULL; + } + if (buf->downsamplingfb) { + GPU_framebuffer_free(buf->downsamplingfb); + buf->downsamplingfb = NULL; + } + + MEM_freeN(buf); +} + +static GPUScreenBuffer *gpu_scenebuf_create(int width, int height, bool depth_only) +{ + GPUScreenBuffer *buf = MEM_callocN(sizeof(GPUScreenBuffer), "GPUScreenBuffer"); + + buf->w = width; + buf->h = height; + buf->depth = NULL; + + buf->fb = GPU_framebuffer_create(); + if (!buf->fb) { + GPU_scenebuf_free(buf); + return NULL; + } + + /* DOWNSAMPLING FB */ + buf->downsamplingfb = GPU_framebuffer_create(); + if (!buf->downsamplingfb) { + GPU_scenebuf_free(buf); + return NULL; + } + + if (depth_only) { + buf->tex = GPU_texture_create_depth_buffer(width, height, NULL); + if (!buf->tex) { + GPU_scenebuf_free(buf); + return NULL; + } + + if (!GPU_framebuffer_texture_attach(buf->fb, buf->tex, 0, NULL)) { + GPU_scenebuf_free(buf); + return NULL; + } + + /* check validity at the very end! */ + if (!GPU_framebuffer_check_valid(buf->fb, NULL)) { + GPU_scenebuf_free(buf); + return NULL; + } + } + else { + buf->depth = GPU_texture_create_depth_buffer(width, height, NULL); + if (!buf->depth) { + GPU_scenebuf_free(buf); + return NULL; + } + + if (!GPU_framebuffer_texture_attach(buf->fb, buf->depth, 0, NULL)) { + GPU_scenebuf_free(buf); + return NULL; + } + + buf->tex = GPU_texture_create_2D(width, height, NULL, 1, NULL); + if (!buf->tex) { + GPU_scenebuf_free(buf); + return NULL; + } + + if (!GPU_framebuffer_texture_attach(buf->fb, buf->tex, 0, NULL)) { + GPU_scenebuf_free(buf); + return NULL; + } + + /* check validity at the very end! */ + if (!GPU_framebuffer_check_valid(buf->fb, NULL)) { + GPU_scenebuf_free(buf); + return NULL; + } + } + + + GPU_framebuffer_restore(); + + return buf; +} + +GPUScreenBuffer *GPU_pbr_scene_buffer(GPUPBR *pbr, int width, int height) +{ + if (pbr->scene) { + if ((pbr->scene->w == width) && (pbr->scene->h == height)) + return pbr->scene; + else + GPU_scenebuf_free(pbr->scene); + } + + pbr->scene = gpu_scenebuf_create(width, height, false); + + return pbr->scene; +} + +GPUScreenBuffer *GPU_pbr_backface_buffer(GPUPBR *pbr, int width, int height) +{ + if (pbr->backface) { + if ((pbr->backface->w == width) && (pbr->backface->h == height)) + return pbr->backface; + else + GPU_scenebuf_free(pbr->backface); + } + + pbr->backface = gpu_scenebuf_create(width, height, true); + + return pbr->backface; +} + +void GPU_scenebuf_bind(GPUScreenBuffer* buf, float winmat[4][4], int winsize[2], float clipsta, float clipend) +{ + glDisable(GL_SCISSOR_TEST); + + GPU_texture_bind_as_framebuffer(buf->tex); + + winsize[0] = buf->w; + winsize[1] = buf->h; + + buf->clipsta = clipsta; + buf->clipend = clipend; + + { + float uvpix[4][4], ndcuv[4][4], tmp[4][4]; + + /* NDC to UVs */ + unit_m4(ndcuv); + ndcuv[0][0] = ndcuv[1][1] = ndcuv[3][0] = ndcuv[3][1] = 0.5f; + + /* UVs to pixels */ + unit_m4(uvpix); + uvpix[0][0] = buf->w; + uvpix[1][1] = buf->h; + + mul_m4_m4m4(tmp, uvpix, ndcuv); + mul_m4_m4m4(buf->pixelprojmat, tmp, winmat); + } +} + +void GPU_scenebuf_unbind(GPUScreenBuffer* buf) +{ + GPU_framebuffer_texture_unbind(buf->fb, buf->tex); + GPU_framebuffer_restore(); + glEnable(GL_SCISSOR_TEST); +} + +void GPU_scenebuf_filter_texture(GPUScreenBuffer* buf) +{ + /* MinZ Pyramid for depth */ + if (buf->depth) { + GPU_texture_bind(buf->depth, 0); + GPU_generate_mipmap(GL_TEXTURE_2D); + GPU_texture_unbind(buf->depth); + GPU_framebuffer_hiz_construction(buf->downsamplingfb, buf->depth, false); + GPU_framebuffer_texture_attach(buf->fb, buf->depth, 0, NULL); + } + else { + GPU_texture_bind(buf->tex, 0); + GPU_generate_mipmap(GL_TEXTURE_2D); + GPU_texture_unbind(buf->tex); + GPU_framebuffer_hiz_construction(buf->downsamplingfb, buf->tex, true); + GPU_framebuffer_texture_attach(buf->fb, buf->tex, 0, NULL); + } + + GPU_framebuffer_restore(); +} + +/* PBR core */ + +GPUPBR *GPU_pbr_create(void) +{ + GPUPBR *pbr = MEM_callocN(sizeof(GPUPBR), "GPUPBR"); + + pbr->hammersley = GPU_create_hammersley_sample_texture(1024); + pbr->jitter = GPU_create_random_texture(); + pbr->ltc_mat_ggx = GPU_create_ltc_mat_ggx_lut_texture(); + pbr->ltc_mag_ggx = GPU_create_ltc_mag_ggx_lut_texture(); + + return pbr; +} + +void GPU_pbr_free(GPUPBR *pbr) +{ + if (pbr->hammersley) { + GPU_texture_free(pbr->hammersley); + pbr->hammersley = NULL; + } + if (pbr->jitter) { + GPU_texture_free(pbr->jitter); + pbr->jitter = NULL; + } + if (pbr->ltc_mat_ggx) { + GPU_texture_free(pbr->ltc_mat_ggx); + pbr->ltc_mat_ggx = NULL; + } + if (pbr->ltc_mag_ggx) { + GPU_texture_free(pbr->ltc_mag_ggx); + pbr->ltc_mag_ggx = NULL; + } + + if (pbr->scene) { + GPU_scenebuf_free(pbr->scene); + } + + if (pbr->backface) { + GPU_scenebuf_free(pbr->backface); + } + + MEM_freeN(pbr); +} + +/* Settings */ + +static void gpu_pbr_init_ssr_settings(GPUSSRSettings *ssr_settings) +{ + ssr_settings->attenuation = 6.0f; + ssr_settings->thickness = 0.2f; + ssr_settings->steps = 32; +} + +static void gpu_pbr_init_ssao_settings(GPUSSAOSettings *ssao_settings) +{ + ssao_settings->factor = 1.0f; + ssao_settings->attenuation = 1.0f; + ssao_settings->distance_max = 0.2f; + ssao_settings->samples = 16; + ssao_settings->steps = 2; +} + +static void gpu_pbr_init_brdf_settings(GPUBRDFSettings *brdf_settings) +{ + brdf_settings->lodbias = -0.5f; + brdf_settings->samples = 32; +} + +void GPU_pbr_settings_validate(GPUPBRSettings *pbr_settings) +{ + if (pbr_settings->pbr_flag & GPU_PBR_FLAG_ENABLE) { + if (pbr_settings->brdf == NULL) { + GPUBRDFSettings *brdf_settings; + brdf_settings = pbr_settings->brdf = MEM_callocN(sizeof(GPUBRDFSettings), __func__); + gpu_pbr_init_brdf_settings(brdf_settings); + } + + if ((pbr_settings->pbr_flag & GPU_PBR_FLAG_SSAO) && (pbr_settings->ssao == NULL)) { + GPUSSAOSettings *ssao_settings; + ssao_settings = pbr_settings->ssao = MEM_callocN(sizeof(GPUSSAOSettings), __func__); + gpu_pbr_init_ssao_settings(ssao_settings); + } + + if ((pbr_settings->pbr_flag & GPU_PBR_FLAG_SSR) && (pbr_settings->ssr == NULL)) { + GPUSSRSettings *ssr_settings; + ssr_settings = pbr_settings->ssr = MEM_callocN(sizeof(GPUSSRSettings), __func__); + gpu_pbr_init_ssr_settings(ssr_settings); + } + } +}
\ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_probe.c b/source/blender/gpu/intern/gpu_probe.c new file mode 100644 index 00000000000..e1f5583bccb --- /dev/null +++ b/source/blender/gpu/intern/gpu_probe.c @@ -0,0 +1,685 @@ +/* + * ***** 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) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Clement Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gpu_probe.c + * \ingroup gpu + * + * Manages screen space effects inside materials and + * the necessary buffers: + * - Screen space reflection + * + * NOTICE : These are not post process effects + */ + + +#include <math.h> +#include <string.h> +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_utildefines.h" +#include "BLI_blenlib.h" + +#include "DNA_object_types.h" +#include "DNA_world_types.h" +#include "DNA_scene_types.h" + +#include "GPU_extensions.h" +#include "GPU_framebuffer.h" +#include "GPU_material.h" +#include "GPU_shader.h" +#include "GPU_texture.h" +#include "GPU_draw.h" +#include "GPU_probe.h" + +#include "gpu_codegen.h" + +#include <string.h> + +/* Structs */ + + +/* Functions */ + +static void gpu_probe_buffers_free(GPUProbe *probe) +{ + if (probe->shtex) { + GPU_texture_free(probe->shtex); + probe->shtex = NULL; + } + if (probe->fbsh) { + GPU_framebuffer_free(probe->fbsh); + probe->fbsh = NULL; + } + if (probe->tex) { + GPU_texture_free(probe->tex); + probe->tex = NULL; + } + if (probe->texreflect) { + GPU_texture_free(probe->texreflect); + probe->texreflect = NULL; + } + if (probe->texrefract) { + GPU_texture_free(probe->texrefract); + probe->texrefract = NULL; + } + if (probe->depthtex) { + GPU_texture_free(probe->depthtex); + probe->depthtex = NULL; + } + if (probe->fb) { + GPU_framebuffer_free(probe->fb); + probe->fb = NULL; + } +} + +void GPU_probe_free(ListBase *gpuprobe) +{ + GPUProbe *probe; + LinkData *link; + + for (link = gpuprobe->first; link; link = link->next) { + probe = (GPUProbe *)link->data; + + gpu_probe_buffers_free(probe); + + if (probe->shcoefs) { + MEM_freeN(probe->shcoefs); + } + + MEM_freeN(probe); + } + + BLI_freelistN(gpuprobe); +} + +static void gpu_probe_from_blender(Scene *scene, World *wo, Object *ob, GPUProbe *probe) +{ + probe->scene = scene; + probe->wo = wo; + probe->ob = ob; + probe->clipsta = 0.01f; + probe->clipend = 1000.0f; + + if (ob) { + probe->type = (ob->probetype == OB_PROBE_CUBEMAP) ? GPU_PROBE_CUBE : GPU_PROBE_PLANAR; + probe->size = ob->probesize; + } + else { + probe->type = GPU_PROBE_CUBE; + probe->size = wo->probesize; + } + + /* prevent from having an invalid framebuffer */ + CLAMP(probe->size, 4, 10240); + + if (probe->type == GPU_PROBE_CUBE) { + + /* Cubemap */ + probe->fb = GPU_framebuffer_create(); + if (!probe->fb) { + gpu_probe_buffers_free(probe); + return; + } + + probe->tex = GPU_texture_create_cube_probe(probe->size, NULL); + if (!probe->tex) { + gpu_probe_buffers_free(probe); + return; + } + + if (!GPU_framebuffer_cubeface_attach(probe->fb, probe->tex, 0, 0, NULL)) { + gpu_probe_buffers_free(probe); + return; + } + + /* depth texture */ + probe->depthtex = GPU_texture_create_depth(probe->size, probe->size, NULL); + if (!probe->depthtex) { + gpu_probe_buffers_free(probe); + return; + } + + if (!GPU_framebuffer_texture_attach(probe->fb, probe->depthtex, 0, NULL)) { + gpu_probe_buffers_free(probe); + return; + } + + if (!GPU_framebuffer_check_valid(probe->fb, NULL)) { + gpu_probe_buffers_free(probe); + return; + } + + + /* Spherical harmonic texture */ + probe->fbsh = GPU_framebuffer_create(); + if (!probe->fbsh) { + gpu_probe_buffers_free(probe); + return; + } + + probe->shtex = GPU_texture_create_sh_filter_target(NULL); + if (!probe->shtex) { + gpu_probe_buffers_free(probe); + return; + } + + if (!GPU_framebuffer_texture_attach(probe->fbsh, probe->shtex, 0, NULL)) { + gpu_probe_buffers_free(probe); + return; + } + + GPU_texture_bind_as_framebuffer(probe->shtex); + + if (!GPU_framebuffer_check_valid(probe->fbsh, NULL)) { + gpu_probe_buffers_free(probe); + return; + } + + GPU_framebuffer_texture_unbind(probe->fbsh, probe->shtex); + + } + else { + + probe->fb = GPU_framebuffer_create(); + if (!probe->fb) { + gpu_probe_buffers_free(probe); + return; + } + + /* Refraction */ + probe->texrefract = GPU_texture_create_planar_probe(probe->size, NULL); + if (!probe->texrefract) { + gpu_probe_buffers_free(probe); + return; + } + + if (!GPU_framebuffer_texture_attach(probe->fb, probe->texrefract, 0, NULL)) { + gpu_probe_buffers_free(probe); + return; + } + + GPU_framebuffer_texture_detach(probe->texrefract); + + /* Reflection */ + probe->texreflect = GPU_texture_create_planar_probe(probe->size, NULL); + if (!probe->texreflect) { + gpu_probe_buffers_free(probe); + return; + } + + if (!GPU_framebuffer_texture_attach(probe->fb, probe->texreflect, 0, NULL)) { + gpu_probe_buffers_free(probe); + return; + } + + /* depth texture */ + probe->depthtex = GPU_texture_create_depth(probe->size, probe->size, NULL); + if (!probe->depthtex) { + gpu_probe_buffers_free(probe); + return; + } + + if (!GPU_framebuffer_texture_attach(probe->fb, probe->depthtex, 0, NULL)) { + gpu_probe_buffers_free(probe); + return; + } + + if (!GPU_framebuffer_check_valid(probe->fb, NULL)) { + gpu_probe_buffers_free(probe); + return; + } + } + + /* Setting up spherical harmonics coefs */ + probe->shcoefs = MEM_mallocN(sizeof(float) * 9 * 3, "Probe Spherical Harmonics"); + memset(probe->shcoefs, 0, sizeof(float) * 9 * 3); /* Avoid funky colors in the first reflection pass */ + + GPU_framebuffer_restore(); + + GPU_probe_set_update(probe, true); +} + +GPUProbe *GPU_probe_world(Scene *scene, World *wo) +{ + GPUProbe *probe; + LinkData *link; + + for (link = wo->gpuprobe.first; link; link = link->next) + if (((GPUProbe *)link->data)->scene == scene) + return link->data; + + probe = MEM_callocN(sizeof(GPUProbe), "GPUProbe"); + + link = MEM_callocN(sizeof(LinkData), "GPUProbeLink"); + link->data = probe; + BLI_addtail(&wo->gpuprobe, link); + + gpu_probe_from_blender(scene, wo, NULL, probe); + + return probe; +} + +GPUProbe *GPU_probe_object(Scene *scene, Object *ob) +{ + GPUProbe *probe; + LinkData *link; + + for (link = ob->gpuprobe.first; link; link = link->next) { + probe = (GPUProbe *)link->data; + if (probe->scene == scene) + return link->data; + } + + probe = MEM_callocN(sizeof(GPUProbe), "GPUProbe"); + + link = MEM_callocN(sizeof(LinkData), "GPUProbeLink"); + link->data = probe; + BLI_addtail(&ob->gpuprobe, link); + + gpu_probe_from_blender(scene, NULL, ob, probe); + + return probe; +} + +static void envmap_transmatrix(float mat[4][4], int part) +{ + float tmat[4][4], tmat2[4][4], eul1[3], eul2[3], rotmat1[4][4], rotmat2[4][4]; + + eul1[0] = eul1[1] = eul1[2] = 0.0; + eul2[0] = eul2[1] = eul2[2] = 0.0; + + if (part == 0){ /* pos x */ + eul1[1] = -M_PI / 2.0; + eul2[2] = M_PI; + } + else if (part == 1) { /* neg x */ + eul1[1] = M_PI / 2.0; + eul2[2] = M_PI; + } + else if (part == 2) { /* pos y */ + eul1[0] = M_PI / 2.0; + } + else if (part == 3) { /* neg y */ + eul1[0] = -M_PI / 2.0; + } + else if (part == 4) { /* pos z */ + eul1[0] = M_PI; + } + else { /* neg z */ + eul1[2] = M_PI; + } + + copy_m4_m4(tmat, mat); + eul_to_mat4(rotmat1, eul1); + eul_to_mat4(rotmat2, eul2); + mul_m4_m4m4(tmat2, rotmat1, rotmat2); + mul_m4_m4m4(mat, tmat, tmat2); +} + +static void gpu_probe_cube_update_buffer_mats(GPUProbe *probe, int cubeface) +{ + float tempmat[4][4]; + + perspective_m4(probe->winmat, -probe->clipsta, probe->clipsta, -probe->clipsta, probe->clipsta, probe->clipsta, probe->clipend); + unit_m4(probe->obmat); + + /* Local Capture */ + if (probe->ob) + translate_m4(probe->obmat, probe->ob->obmat[3][0], probe->ob->obmat[3][1], probe->ob->obmat[3][2]); + + /* Rotating towards the right face */ + envmap_transmatrix(probe->obmat, cubeface); + + copy_m4_m4(tempmat, probe->obmat); + invert_m4_m4(probe->viewmat, tempmat); + normalize_v3(probe->viewmat[0]); + normalize_v3(probe->viewmat[1]); + normalize_v3(probe->viewmat[2]); + + mul_m4_m4m4(probe->persmat, probe->winmat, probe->viewmat); +} + +void GPU_probe_buffer_bind(GPUProbe *probe) +{ + glDisable(GL_SCISSOR_TEST); + if (probe->type == GPU_PROBE_PLANAR) { + GPU_texture_bind_as_framebuffer(probe->texreflect); + } + else + GPU_texture_bind_as_framebuffer(probe->tex); +} + +void GPU_probe_switch_fb_cubeface(GPUProbe *probe, int cubeface, float viewmat[4][4], int *winsize, float winmat[4][4]) +{ + gpu_probe_cube_update_buffer_mats(probe, cubeface); + GPU_framebuffer_cubeface_attach(probe->fb, probe->tex, 0, cubeface, NULL); + + /* set matrices */ + copy_m4_m4(viewmat, probe->viewmat); + copy_m4_m4(winmat, probe->winmat); + *winsize = probe->size; +} + +static float point_plane_dist(float point[3], float plane[3], float normal[3]) +{ + float tmp[3]; + sub_v3_v3v3(tmp, plane, point); + return fabsf(dot_v3v3(normal, tmp)); +} + +void GPU_probe_attach_planar_fb(GPUProbe *probe, float camviewmat[4][4], float camwinmat[4][4], float viewmat[4][4], int *winsize, bool refraction) +{ + float rangemat[4][4]; + float plane[4] = {0.0f, 0.0f, -1.0f, 0.0f}; + + if (refraction) + GPU_framebuffer_texture_attach(probe->fb, probe->texrefract, 0, NULL); + else + GPU_framebuffer_texture_attach(probe->fb, probe->texreflect, 0, NULL); + + /* opengl buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */ + unit_m4(rangemat); + rangemat[0][0] = 0.5f; + rangemat[1][1] = 0.5f; + rangemat[2][2] = 0.5f; + rangemat[3][0] = 0.5f; + rangemat[3][1] = 0.5f; + rangemat[3][2] = 0.5f; + + /* set matrices */ + if (!refraction) + mul_m4_m4m4(probe->viewmat, camviewmat, probe->reflectmat); + else + copy_m4_m4(probe->viewmat, camviewmat); + + mul_m4_m4m4(probe->persmat, camwinmat, probe->viewmat); + + if (!refraction) + mul_m4_m4m4(probe->reflectionmat, rangemat, probe->persmat); + + copy_m4_m4(viewmat, probe->viewmat); + *winsize = probe->size; + + /* setup clip plane */ + { + float camco[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + float planevec[4] = {0.0f, 0.0f, -1.0f, 0.0f}; + float planeco[3]; + double dplane[4]; + float dist_to_plane; + float planetocam[3]; + float invmat[4][4]; + + if (refraction) + planevec[2] = 1.0f; + + /* finding cam position */ + invert_m4_m4(invmat, camviewmat); + mul_v4_m4v4(camco, invmat, camco); + + /* mirror plane coordinates and normal vector */ + copy_v3_v3(planeco, probe->obmat[3]); + mul_v4_m4v4(planevec, probe->obmat, planevec); + normalize_v3(planevec); + + /* flipping the plane if the cam is below it */ + sub_v3_v3v3(planetocam, camco, planeco); + if (dot_v3v3(planetocam, planevec) < 0) { + planevec[0] = planevec[1] = planevec[3] = 0.0f; + planevec[2] = (refraction) ? -1.0f : 1.0f; + mul_v4_m4v4(planevec, probe->obmat, planevec); + normalize_v3(planevec); + } + + /* saved to use when shading */ + if (!refraction) + copy_v3_v3(probe->planevec, planevec); + + /* finding the distance to the clip plane */ + dist_to_plane = point_plane_dist(camco, planeco, planevec); + + /* finding the orientation of the clip plane in camera space */ + mul_v4_m4v4(planevec, camviewmat, planevec); + + planevec[3] = dist_to_plane - probe->clipsta; + + negate_v4(planevec); + + copy_v4db_v4fl(dplane, planevec); + glClipPlane(GL_CLIP_PLANE0, dplane); + glEnable(GL_CLIP_PLANE0); + } +} + +void GPU_probe_buffer_unbind(GPUProbe *probe) +{ + glDisable(GL_CLIP_PLANE0); + GPU_framebuffer_texture_unbind(probe->fb, probe->tex); + GPU_framebuffer_restore(); + glEnable(GL_SCISSOR_TEST); +} + +void GPU_probe_rebuild_mipmaps(GPUProbe *probe) +{ + if (probe->type == GPU_PROBE_CUBE) { + GPU_texture_bind(probe->tex, 0); + GPU_generate_mipmap(GL_TEXTURE_CUBE_MAP); + GPU_texture_unbind(probe->tex); + } + else if (probe->type == GPU_PROBE_PLANAR) { + GPU_texture_bind(probe->texreflect, 0); + GPU_generate_mipmap(GL_TEXTURE_2D); + GPU_texture_unbind(probe->texreflect); + + GPU_texture_bind(probe->texrefract, 0); + GPU_generate_mipmap(GL_TEXTURE_2D); + GPU_texture_unbind(probe->texrefract); + } +} + +void GPU_probe_auto_update(GPUProbe *probe) +{ + if ((probe->ob && probe->ob->probeflags & OB_PROBE_AUTO_UPDATE) || + (probe->wo && probe->wo->probeflags & WO_PROBE_AUTO_UPDATE)) + probe->update = true; +} + +void GPU_probe_set_update(GPUProbe *probe, bool val) +{ + probe->update = val; +} + +bool GPU_probe_get_update(GPUProbe *probe) +{ + return probe->update; +} + +Object *GPU_probe_get_object(GPUProbe *probe) +{ + return probe->ob; +} + +int GPU_probe_get_size(GPUProbe *probe) +{ + return probe->size; +} + +int GPU_probe_get_type(GPUProbe *probe) +{ + return (int)(probe->type); +} + +void GPU_probe_update_clip(GPUProbe *probe, float clipsta, float clipend) +{ + probe->clipsta = clipsta; + probe->clipend = clipend; +} + +void GPU_probe_update_layers(GPUProbe *probe, unsigned int lay) +{ + probe->lay = lay; +} + +unsigned int GPU_probe_get_layers(GPUProbe *probe) +{ + if (probe->ob && (probe->ob->probeflags & OB_PROBE_USE_LAYERS)) + return probe->lay; + else + return -1; +} + +void GPU_probe_update_sh_res(GPUProbe *probe, int shres) +{ + CLAMP(shres, 1, (1 << MAX_SH_SAMPLES)); + /* Finding the exponent and taking care of the float imprecision */ + probe->shres = (int)round(log((float)shres) / log(2)); +} + +void GPU_probe_update_parallax(GPUProbe *probe, float correctionmat[4][4], float obmat[4][4]) +{ + copy_v3_v3(probe->co, obmat[3]); + invert_m4_m4(probe->correctionmat, correctionmat); +} + +void GPU_probe_update_ref_plane(GPUProbe *probe, float obmat[4][4]) +{ + float mtx[4][4]; + float obmat_scale[3]; + + /* mtx is the mirror transformation */ + unit_m4(mtx); + mtx[2][2] = -1.0f; /* XY reflection plane */ + + normalize_m4_m4_ex(probe->obmat, obmat, obmat_scale); + invert_m4_m4(probe->imat, probe->obmat); + + mul_m4_m4m4(mtx, mtx, probe->imat); + mul_m4_m4m4(probe->reflectmat, probe->obmat, mtx); +} + + +/* Spherical Harmonics : Diffuse lighting */ + +void gpu_compute_sh(GPUProbe *probe) +{ + int probe_source_uniform; + GPUShader *sh_shader = GPU_shader_get_builtin_shader(GPU_SHADER_COMPUTE_SH + probe->shres); + + if (!sh_shader) + return; + + GPU_shader_bind(sh_shader); + + probe_source_uniform = GPU_shader_get_uniform(sh_shader, "probe"); + + GPU_texture_bind(probe->tex, 0); + GPU_shader_uniform_texture(sh_shader, probe_source_uniform, probe->tex); + + /* Drawing quad */ + glBegin(GL_TRIANGLE_STRIP); + glVertex3f(-1.0, -1.0, 1.0); + glVertex3f(1.0, -1.0, 1.0); + glVertex3f(-1.0, 1.0, 1.0); + glVertex3f(1.0, 1.0, 1.0); + glEnd(); + + GPU_texture_unbind(probe->tex); + + GPU_shader_unbind(); +} + +void GPU_probe_sh_compute(GPUProbe *probe) +{ + bool computesh = false; + + if (probe->ob && (probe->ob->probeflags & OB_PROBE_COMPUTE_SH)) + computesh = true; + + if (probe->wo && (probe->wo->probeflags & WO_PROBE_COMPUTE_SH)) + computesh = true; + + if (computesh && probe->type == GPU_PROBE_CUBE) { + glDisable(GL_SCISSOR_TEST); + GPU_texture_bind_as_framebuffer(probe->shtex); + gpu_compute_sh(probe); + + GPU_framebuffer_texture_unbind(probe->fbsh, probe->shtex); + + /* Only read the 9 pixels containing the coefs */ + glReadPixels(0, 0, 3, 3, GL_RGB, GL_FLOAT, probe->shcoefs); + GPU_framebuffer_restore(); + glEnable(GL_SCISSOR_TEST); + } + else if (computesh && (probe->type == GPU_PROBE_PLANAR)) { + GPUProbe *srcprobe; + /* Copy sh from other probe */ + if (probe->ob->probe) + srcprobe = GPU_probe_object(probe->scene, probe->ob->probe); + else if (probe->scene->world) + srcprobe = GPU_probe_world(probe->scene, probe->scene->world); + else { + memset(probe->shcoefs, 0, sizeof(float) * 9 * 3); + return; + } + + memcpy(probe->shcoefs, srcprobe->shcoefs, sizeof(float) * 9 * 3); + } + else { + memset(probe->shcoefs, 0, sizeof(float) * 9 * 3); + } +} + +void GPU_probe_sh_shader_bind(GPUProbe *probe) +{ + int uniformloc[9], i; + GPUShader *sh_shader = GPU_shader_get_builtin_shader(GPU_SHADER_DISPLAY_SH); + + if (!sh_shader) + return; + + GPU_shader_bind(sh_shader); + + uniformloc[0] = GPU_shader_get_uniform(sh_shader, "sh0"); + uniformloc[1] = GPU_shader_get_uniform(sh_shader, "sh1"); + uniformloc[2] = GPU_shader_get_uniform(sh_shader, "sh2"); + uniformloc[3] = GPU_shader_get_uniform(sh_shader, "sh3"); + uniformloc[4] = GPU_shader_get_uniform(sh_shader, "sh4"); + uniformloc[5] = GPU_shader_get_uniform(sh_shader, "sh5"); + uniformloc[6] = GPU_shader_get_uniform(sh_shader, "sh6"); + uniformloc[7] = GPU_shader_get_uniform(sh_shader, "sh7"); + uniformloc[8] = GPU_shader_get_uniform(sh_shader, "sh8"); + + for (i = 0; i < 9; ++i) { + GPU_shader_uniform_vector(sh_shader, uniformloc[i], 3, 1, &probe->shcoefs[i*3]); + } +} + +void GPU_probe_sh_shader_unbind(void) +{ + GPU_shader_unbind(); +}
\ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 5cfb323bc4b..226595200ca 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -61,6 +61,13 @@ extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[]; extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[]; extern char datatoc_gpu_shader_fx_depth_resolve_glsl[]; extern char datatoc_gpu_shader_fx_lib_glsl[]; +extern char datatoc_gpu_shader_fx_colormanage_frag_glsl[]; +extern char datatoc_gpu_shader_probe_sh_compute_frag_glsl[]; +extern char datatoc_gpu_shader_probe_sh_compute_vert_glsl[]; +extern char datatoc_gpu_shader_display_sh_frag_glsl[]; +extern char datatoc_gpu_shader_display_sh_vert_glsl[]; +extern char datatoc_gpu_shader_downsample_maxz_frag_glsl[]; +extern char datatoc_gpu_shader_downsample_maxz_vert_glsl[]; static struct GPUShadersGlobal { struct { @@ -68,6 +75,10 @@ static struct GPUShadersGlobal { GPUShader *sep_gaussian_blur; GPUShader *smoke; GPUShader *smoke_fire; + GPUShader *compute_sh[MAX_SH_SAMPLES]; + GPUShader *display_sh; + GPUShader *maxz_downsample; + GPUShader *minz_downsample; /* cache for shader fx. Those can exist in combinations so store them here */ GPUShader *fx_shaders[MAX_FX_SHADERS * 2]; } shaders; @@ -165,6 +176,10 @@ static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"); } + if (GLEW_ARB_shader_texture_lod) { + strcat(defines, "#extension GL_ARB_shader_texture_lod: enable\n"); + } + if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) { strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n"); } @@ -187,7 +202,14 @@ static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], bool use_opensubdiv, - bool use_new_shading) + bool use_new_shading, + bool use_box_correction, + bool use_ellipsoid_correction, + bool use_planar_probe, + bool use_alpha_as_depth, + bool use_backface_depth, + bool use_ssr, + bool use_ssao) { /* some useful defines to detect GPU type */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) { @@ -230,9 +252,35 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], UNUSED_VARS(use_opensubdiv); #endif - if (use_new_shading) { + if (use_new_shading) strcat(defines, "#define USE_NEW_SHADING\n"); - } + + if (use_box_correction) + strcat(defines, "#define CORRECTION_BOX\n"); + else if (use_ellipsoid_correction) + strcat(defines, "#define CORRECTION_ELLIPSOID\n"); + else + strcat(defines, "#define CORRECTION_NONE\n"); + + if (use_planar_probe) + strcat(defines, "#define PLANAR_PROBE\n"); + + if (use_ssr && !use_planar_probe) + strcat(defines, "#define USE_SSR\n"); + + if (use_ssao) + strcat(defines, "#define USE_SSAO\n"); + + if (use_backface_depth) + strcat(defines, "#define USE_BACKFACE\n"); + + if (use_alpha_as_depth) + strcat(defines, "#define ALPHA_AS_DEPTH\n"); + + /* XXX : this must be here for the BSDF_SAMPLES to work */ + strcat(defines, "#if __VERSION__ < 130\n" + "#define uint unsigned int\n" + "#endif\n"); return; } @@ -310,7 +358,14 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, gpu_shader_standard_defines(standard_defines, use_opensubdiv, - (flags & GPU_SHADER_FLAGS_NEW_SHADING) != 0); + (flags & GPU_SHADER_FLAGS_NEW_SHADING) != 0, + (flags & GPU_SHADER_FLAGS_PROBE_BOX_CORREC) != 0, + (flags & GPU_SHADER_FLAGS_PROBE_ELIPS_CORREC) != 0, + (flags & GPU_SHADER_FLAGS_PROBE_PLANAR) != 0, + (flags & GPU_SHADER_FLAGS_ALPHA_DEPTH) != 0, + (flags & GPU_SHADER_FLAGS_BACKFACE_DEPTH) != 0, + (flags & GPU_SHADER_FLAGS_SSR) != 0, + (flags & GPU_SHADER_FLAGS_SSAO) != 0); gpu_shader_standard_extensions(standard_extensions, geocode != NULL); if (vertexcode) { @@ -593,36 +648,73 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) { GPUShader *retval = NULL; - switch (shader) { - case GPU_SHADER_VSM_STORE: - if (!GG.shaders.vsm_store) - GG.shaders.vsm_store = GPU_shader_create( - datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, - NULL, NULL, NULL, 0, 0, 0); - retval = GG.shaders.vsm_store; - break; - case GPU_SHADER_SEP_GAUSSIAN_BLUR: - if (!GG.shaders.sep_gaussian_blur) - GG.shaders.sep_gaussian_blur = GPU_shader_create( - datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, - datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, - NULL, NULL, NULL, 0, 0, 0); - retval = GG.shaders.sep_gaussian_blur; - break; - case GPU_SHADER_SMOKE: - if (!GG.shaders.smoke) - GG.shaders.smoke = GPU_shader_create( - datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl, - NULL, NULL, NULL, 0, 0, 0); - retval = GG.shaders.smoke; - break; - case GPU_SHADER_SMOKE_FIRE: - if (!GG.shaders.smoke_fire) - GG.shaders.smoke_fire = GPU_shader_create( - datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_fire_frag_glsl, - NULL, NULL, NULL, 0, 0, 0); - retval = GG.shaders.smoke_fire; - break; + if (shader >= GPU_SHADER_COMPUTE_SH && shader < GPU_SHADER_COMPUTE_SH + MAX_SH_SAMPLES) { + int shadn = shader - GPU_SHADER_COMPUTE_SH; + + if (!GG.shaders.compute_sh[shadn]) { + char buf[32]; + int samples = (1 << shadn); + + CLAMP_MIN(samples, 1); + sprintf(buf, "#define CUBEMAP_RES %d \n", samples); + + GG.shaders.compute_sh[shadn] = GPU_shader_create( + datatoc_gpu_shader_probe_sh_compute_vert_glsl, datatoc_gpu_shader_probe_sh_compute_frag_glsl, + NULL, NULL, buf, 0, 0, 0); + } + retval = GG.shaders.compute_sh[shadn]; + } + else { + switch (shader) { + case GPU_SHADER_VSM_STORE: + if (!GG.shaders.vsm_store) + GG.shaders.vsm_store = GPU_shader_create( + datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, + NULL, NULL, NULL, 0, 0, 0); + retval = GG.shaders.vsm_store; + break; + case GPU_SHADER_SEP_GAUSSIAN_BLUR: + if (!GG.shaders.sep_gaussian_blur) + GG.shaders.sep_gaussian_blur = GPU_shader_create( + datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, + datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, + NULL, NULL, NULL, 0, 0, 0); + retval = GG.shaders.sep_gaussian_blur; + break; + case GPU_SHADER_SMOKE: + if (!GG.shaders.smoke) + GG.shaders.smoke = GPU_shader_create( + datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl, + NULL, NULL, NULL, 0, 0, 0); + retval = GG.shaders.smoke; + break; + case GPU_SHADER_SMOKE_FIRE: + if (!GG.shaders.smoke_fire) + GG.shaders.smoke_fire = GPU_shader_create( + datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_fire_frag_glsl, + NULL, NULL, NULL, 0, 0, 0); + retval = GG.shaders.smoke_fire; + break; + case GPU_SHADER_DISPLAY_SH: + if (!GG.shaders.display_sh) + GG.shaders.display_sh = GPU_shader_create( + datatoc_gpu_shader_display_sh_vert_glsl, datatoc_gpu_shader_display_sh_frag_glsl, + NULL, NULL, NULL, 0, 0, 0); + retval = GG.shaders.display_sh; + break; + case GPU_SHADER_MAXZ_DOWNSAMPLE: + if (!GG.shaders.maxz_downsample) + GG.shaders.maxz_downsample = GPU_shader_create( + datatoc_gpu_shader_downsample_maxz_vert_glsl, datatoc_gpu_shader_downsample_maxz_frag_glsl, + NULL, NULL, NULL, 0, 0, 0); + case GPU_SHADER_MINZ_DOWNSAMPLE: + if (!GG.shaders.minz_downsample) + GG.shaders.minz_downsample = GPU_shader_create( + datatoc_gpu_shader_downsample_maxz_vert_glsl, datatoc_gpu_shader_downsample_maxz_frag_glsl, + NULL, NULL, "#define MIN;\n", 0, 0, 0); + retval = GG.shaders.minz_downsample; + break; + } } if (retval == NULL) @@ -700,6 +792,10 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp) case GPU_SHADER_FX_DEPTH_RESOLVE: shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0); break; + + case GPU_SHADER_FX_COLORMANAGE: + shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_colormanage_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); + break; } GG.shaders.fx_shaders[offset] = shader; @@ -734,6 +830,28 @@ void GPU_shader_free_builtin_shaders(void) GG.shaders.smoke_fire = NULL; } + for (i = 0; i < MAX_SH_SAMPLES; ++i) { + if (GG.shaders.compute_sh[i]) { + GPU_shader_free(GG.shaders.compute_sh[i]); + GG.shaders.compute_sh[i] = NULL; + } + } + + if (GG.shaders.display_sh) { + GPU_shader_free(GG.shaders.display_sh); + GG.shaders.display_sh = NULL; + } + + if (GG.shaders.maxz_downsample) { + GPU_shader_free(GG.shaders.maxz_downsample); + GG.shaders.maxz_downsample = NULL; + } + + if (GG.shaders.minz_downsample) { + GPU_shader_free(GG.shaders.minz_downsample); + GG.shaders.minz_downsample = NULL; + } + for (i = 0; i < 2 * MAX_FX_SHADERS; ++i) { if (GG.shaders.fx_shaders[i]) { GPU_shader_free(GG.shaders.fx_shaders[i]); diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 54f0003c086..e6a9db5059a 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -32,6 +32,8 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_math_base.h" +#include "BLI_math_vector.h" +#include "BLI_rand.h" #include "BKE_global.h" @@ -41,6 +43,7 @@ #include "GPU_framebuffer.h" #include "GPU_glew.h" #include "GPU_texture.h" +#include "GPU_ltc.h" static struct GPUTextureGlobal { GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */ @@ -161,6 +164,23 @@ static GPUTexture *GPU_texture_create_nD( break; } } + else if (components == 3) { + format = GL_RGB; + switch (hdr_type) { + case GPU_HDR_NONE: + internalformat = GL_RGB8; + break; + /* the following formats rely on ARB_texture_float or OpenGL 3.0 */ + case GPU_HDR_HALF_FLOAT: + internalformat = GL_RGB16F_ARB; + break; + case GPU_HDR_FULL_FLOAT: + internalformat = GL_RGB32F_ARB; + break; + default: + break; + } + } else if (components == 2) { /* these formats rely on ARB_texture_rg or OpenGL 3.0 */ format = GL_RG; @@ -178,6 +198,22 @@ static GPUTexture *GPU_texture_create_nD( break; } } + else if (components == 1) { + format = GL_RED; + switch (hdr_type) { + case GPU_HDR_NONE: + internalformat = GL_R8; + break; + case GPU_HDR_HALF_FLOAT: + internalformat = GL_R16F; + break; + case GPU_HDR_FULL_FLOAT: + internalformat = GL_R32F; + break; + default: + break; + } + } if (fpixels && hdr_type == GPU_HDR_NONE) { type = GL_UNSIGNED_BYTE; @@ -242,6 +278,76 @@ static GPUTexture *GPU_texture_create_nD( return tex; } +static GPUTexture *GPU_texture_create_cube(int w, GPUHDRType hdr_type, char err_out[256]) +{ + GLenum type, format, internalformat; + + GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->w = w; + tex->h = w; + tex->number = -1; + tex->refcount = 1; + tex->target = GL_TEXTURE_CUBE_MAP; + tex->target_base = GL_TEXTURE_CUBE_MAP; + tex->depth = 0; + tex->fb_attachment = -1; + + glGenTextures(1, &tex->bindcode); + + if (!tex->bindcode) { + if (err_out) { + BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d", + (int)glGetError()); + } + else { + fprintf(stderr, "GPUTexture: texture create failed: %d\n", + (int)glGetError()); + } + GPU_texture_free(tex); + return NULL; + } + + if (!GPU_full_non_power_of_two_support()) { + tex->w = power_of_2_max_i(tex->w); + tex->h = power_of_2_max_i(tex->h); + } + + tex->number = 0; + glBindTexture(tex->target, tex->bindcode); + + type = GL_FLOAT; + + format = GL_RGBA; + switch (hdr_type) { + case GPU_HDR_NONE: + internalformat = GL_RGBA8; + break; + /* the following formats rely on ARB_texture_float or OpenGL 3.0 */ + case GPU_HDR_HALF_FLOAT: + internalformat = GL_RGBA16F_ARB; + break; + case GPU_HDR_FULL_FLOAT: + internalformat = GL_RGBA32F_ARB; + break; + default: + break; + } + + for (int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internalformat ,tex->w, tex->h, 0, + format, type, NULL); + + /* TODO : use global parameters */ + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(tex->target_base, GL_GENERATE_MIPMAP, GL_TRUE); + + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + return tex; +} GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels) { @@ -276,6 +382,10 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f format = GL_RGBA; internalformat = GL_RGBA8; } + else if (channels == 3) { + format = GL_RGB; + internalformat = GL_RGB16F; //For 3DLUT + } else { format = GL_RED; internalformat = GL_INTENSITY8; @@ -368,11 +478,11 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f return tex; } -GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data, double time, int mipmap) +GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data, short do_clip, double time, int mipmap) { int gputt; /* this binds a texture, so that's why to restore it to 0 */ - GLint bindcode = GPU_verify_image(ima, iuser, textarget, 0, 0, mipmap, is_data); + GLint bindcode = GPU_verify_image(ima, iuser, textarget, 0, 0, mipmap, is_data, do_clip); GPU_update_image_time(ima, time); /* see GPUInput::textarget: it can take two values - GL_TEXTURE_2D and GL_TEXTURE_CUBE_MAP @@ -436,7 +546,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap) /* this binds a texture, so that's why we restore it to 0 */ if (bindcode == 0) { - GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, 0, NULL); + GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, 0, NULL, false); } if (tex) { tex->bindcode = bindcode; @@ -512,6 +622,22 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]) return tex; } + + +GPUTexture *GPU_texture_create_depth_buffer(int w, int h, char err_out[256]) +{ + GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out); + + if (tex) { + /* Now we tweak some of the settings */ + glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE); + + GPU_texture_unbind(tex); + } + return tex; +} + + GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]) { GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out); @@ -540,9 +666,9 @@ GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]) return tex; } -GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]) +GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, bool filtering, int channels, char err_out[256]) { - GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out); + GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, channels, 0, err_out); if (tex) { /* Now we tweak some of the settings */ @@ -550,8 +676,10 @@ GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + if (!filtering) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } GPU_texture_unbind(tex); } @@ -559,9 +687,9 @@ GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, return tex; } -GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]) +GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, int channels, char err_out[256]) { - GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out); + GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, channels, 0, err_out); if (tex) { /* Now we tweak some of the settings */ @@ -575,6 +703,168 @@ GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char er return tex; } +GPUTexture *GPU_texture_create_cube_probe(int size, char err_out[256]) +{ + GPUTexture *tex = GPU_texture_create_cube(size, GPU_HDR_HALF_FLOAT, err_out); + + if (tex) + GPU_texture_unbind(tex); + + return tex; +} + +GPUTexture *GPU_texture_create_planar_probe(int size, char err_out[256]) +{ + GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_HALF_FLOAT, 4, 0, err_out); + + if (tex) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + + GPU_texture_unbind(tex); + } + + return tex; +} + +GPUTexture *GPU_texture_create_sh_filter_target(char err_out[256]) +{ + GPUTexture *tex = GPU_texture_create_nD(4, 4, 2, NULL, 0, GPU_HDR_HALF_FLOAT, 3, 0, err_out); + + if (tex) + GPU_texture_unbind(tex); + + return tex; +} + +/* ********** Utility Lut textures ********** */ + +/* Linearly Transformed Cosines */ +/* From https://eheitzresearch.wordpress.com/415-2/ */ +GPUTexture *GPU_create_ltc_mat_ggx_lut_texture(void) +{ + return GPU_texture_create_2D_procedural(64, 64, <c_mat_ggx[0], true, true, 4, NULL); +} + +GPUTexture *GPU_create_ltc_mag_ggx_lut_texture(void) +{ + return GPU_texture_create_2D_procedural(64, 64, <c_mag_ggx[0], true, true, 1, NULL); +} + +/* Van der Corput sequence */ + /* From http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html */ +static float radical_inverse(int i) { + unsigned int bits = (unsigned int)i; + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return (float)bits * 2.3283064365386963e-10f; +} + +GPUTexture *GPU_create_hammersley_sample_texture(int samples) +{ + GPUTexture *tex; + float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * samples, "hammersley_tex"); + const float samples_inv = 1.0f / samples; + int i; + + for (i = 0; i < samples; i++) { + float phi = radical_inverse(i) * 2.0f * M_PI; + texels[i][0] = cos(phi); + texels[i][1] = sinf(phi); + } + + tex = GPU_texture_create_1D_procedural(samples, (float *)texels, 2, NULL); + MEM_freeN(texels); + return tex; +} + +GPUTexture *GPU_create_random_texture(void) +{ + float random[64 * 64][2]; + int i; + + for (i = 0; i < 64 * 64; i++) { + random[i][0] = BLI_frand(); + random[i][1] = BLI_frand(); + } + + return GPU_texture_create_2D_procedural(64, 64, &random[0][0], true, false, 2, NULL); +} + +GPUTexture *GPU_create_jitter_texture(void) +{ + float jitter[64 * 64][2]; + int i; + + for (i = 0; i < 64 * 64; i++) { + jitter[i][0] = 2.0f * BLI_frand() - 1.0f; + jitter[i][1] = 2.0f * BLI_frand() - 1.0f; + normalize_v2(jitter[i]); + } + + return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], true, false, 2, NULL); +} + +#if 0 +/* concentric mapping, see "A Low Distortion Map Between Disk and Square" and + * http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */ +static GPUTexture * create_concentric_sample_texture(int side) +{ + GPUTexture *tex; + float midpoint = 0.5f * (side - 1); + float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex"); + int i, j; + + for (i = 0; i < side; i++) { + for (j = 0; j < side; j++) { + int index = (i * side + j) * 2; + float a = 1.0f - i / midpoint; + float b = 1.0f - j / midpoint; + float phi, r; + if (a * a > b * b) { + r = a; + phi = (M_PI_4) * (b / a); + } + else { + r = b; + phi = M_PI_2 - (M_PI_4) * (a / b); + } + texels[index] = r * cos(phi); + texels[index + 1] = r * sin(phi); + } + } + + tex = GPU_texture_create_1D_procedural(side * side, texels, 2, NULL); + MEM_freeN(texels); + return tex; +} +#endif + +GPUTexture *GPU_create_spiral_sample_texture(int numsamples) +{ + GPUTexture *tex; + float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsamples, "concentric_tex"); + const float numsamples_inv = 1.0f / numsamples; + int i; + /* arbitrary number to ensure we don't get conciding samples every circle */ + const float spirals = 7.357; + + for (i = 0; i < numsamples; i++) { + float r = (i + 0.5f) * numsamples_inv; + float phi = r * spirals * (float)(2.0 * M_PI); + texels[i][0] = r * cosf(phi); + texels[i][1] = r * sinf(phi); + } + + tex = GPU_texture_create_1D_procedural(numsamples, (float *)texels, 2, NULL); + MEM_freeN(texels); + return tex; +} + void GPU_invalid_tex_init(void) { const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; diff --git a/source/blender/gpu/shaders/gpu_shader_display_sh_frag.glsl b/source/blender/gpu/shaders/gpu_shader_display_sh_frag.glsl new file mode 100644 index 00000000000..c578e25e482 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_display_sh_frag.glsl @@ -0,0 +1,58 @@ +uniform vec3 sh0; +uniform vec3 sh1; +uniform vec3 sh2; +uniform vec3 sh3; +uniform vec3 sh4; +uniform vec3 sh5; +uniform vec3 sh6; +uniform vec3 sh7; +uniform vec3 sh8; + + +varying vec3 varposition; +varying vec3 varnormal; + +float linearrgb_to_srgb(float c) +{ + if(c < 0.0031308) + return (c < 0.0) ? 0.0: c * 12.92; + else + return 1.055 * pow(c, 1.0/2.4) - 0.055; +} + +void linearrgb_to_srgb(vec4 col_from, out vec4 col_to) +{ + col_to.r = linearrgb_to_srgb(col_from.r); + col_to.g = linearrgb_to_srgb(col_from.g); + col_to.b = linearrgb_to_srgb(col_from.b); + col_to.a = col_from.a; +} + +void main() +{ + vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(varposition, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + vec3 worldvec = normalize( (gl_ModelViewMatrixInverse * co).xyz ); + + /* Second order Spherical Harmonics */ + /* http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ */ + vec3 sh = vec3(0.0); + + sh += 0.282095 * sh0; + + sh += -0.488603 * worldvec.z * sh1; + sh += 0.488603 * worldvec.y * sh2; + sh += -0.488603 * worldvec.x * sh3; + + sh += 1.092548 * worldvec.x * worldvec.z * sh4; + sh += -1.092548 * worldvec.z * worldvec.y * sh5; + sh += 0.315392 * (3.0 * worldvec.y * worldvec.y - 1.0) * sh6; + sh += -1.092548 * worldvec.x * worldvec.y * sh7; + sh += 0.546274 * (worldvec.x * worldvec.x - worldvec.z * worldvec.z) * sh8; + + vec4 shcolor = vec4(sh, 1.0); + linearrgb_to_srgb(shcolor, shcolor); + gl_FragColor = shcolor; +}
\ No newline at end of file diff --git a/source/blender/gpu/shaders/gpu_shader_display_sh_vert.glsl b/source/blender/gpu/shaders/gpu_shader_display_sh_vert.glsl new file mode 100644 index 00000000000..02f627f0f21 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_display_sh_vert.glsl @@ -0,0 +1,13 @@ + +varying vec3 varposition; +varying vec3 varnormal; + +void main() +{ + /* position does not need to be transformed, we already have it */ + gl_Position = gl_Vertex; + + varposition = gl_Vertex.xyz; + + varnormal = normalize(-varposition); +}
\ No newline at end of file diff --git a/source/blender/gpu/shaders/gpu_shader_downsample_maxz_frag.glsl b/source/blender/gpu/shaders/gpu_shader_downsample_maxz_frag.glsl new file mode 100644 index 00000000000..3279023670c --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_downsample_maxz_frag.glsl @@ -0,0 +1,74 @@ +/* From http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/ */ +#extension GL_EXT_gpu_shader4 : enable + +uniform sampler2D lowermip; +uniform ivec2 lowermipsize; + +float minmax(float a, float b, float c, float d) +{ +#ifdef MIN + return min(min(a, b), min(c, d)); +#else + return max(max(a, b), max(c, d)); +#endif +} + +float minmax(float a, float b, float c) +{ +#ifdef MIN + return min(min(a, b), c); +#else + return max(max(a, b), c); +#endif +} + +float minmax(float a, float b) +{ +#ifdef MIN + return min(a, b); +#else + return max(a, b); +#endif +} + +float texelFetchLowermip(ivec2 texelPos) +{ +#if __VERSION__ < 130 + return texture2DLod(lowermip, (texelPos * lowermipsize + 0.5) / lowermipsize, 0.0).r; +#else + return texelFetch(lowermip, texelPos, 0).r; +#endif +} + +void main() +{ + vec4 texels; + ivec2 texelPos = ivec2(gl_FragCoord.xy) * 2; + texels.x = texelFetchLowermip(texelPos); + texels.y = texelFetchLowermip(texelPos + ivec2(1, 0)); + texels.z = texelFetchLowermip(texelPos + ivec2(1, 1)); + texels.w = texelFetchLowermip(texelPos + ivec2(0, 1)); + + float minmaxz = minmax(texels.x, texels.y, texels.z, texels.w); + vec3 extra; + /* if we are reducing an odd-width texture then fetch the edge texels */ + if (((lowermipsize.x & 1) != 0) && (int(gl_FragCoord.x) == lowermipsize.x-3)) { + /* if both edges are odd, fetch the top-left corner texel */ + if (((lowermipsize.y & 1) != 0) && (int(gl_FragCoord.y) == lowermipsize.y-3)) { + extra.z = texelFetchLowermip(texelPos + ivec2(-1, -1)); + minmaxz = minmax(minmaxz, extra.z); + } + extra.x = texelFetchLowermip(texelPos + ivec2(0, -1)); + extra.y = texelFetchLowermip(texelPos + ivec2(1, -1)); + minmaxz = minmax(minmaxz, extra.x, extra.y); + } + /* if we are reducing an odd-height texture then fetch the edge texels */ + else if (((lowermipsize.y & 1) != 0) && (int(gl_FragCoord.y) == lowermipsize.y-3)) { + extra.x = texelFetchLowermip(texelPos + ivec2(0, -1)); + extra.y = texelFetchLowermip(texelPos + ivec2(1, -1)); + minmaxz = minmax(minmaxz, extra.x, extra.y); + } + + gl_FragDepth = minmaxz; + gl_FragColor = vec4(1.0); +} diff --git a/source/blender/gpu/shaders/gpu_shader_downsample_maxz_vert.glsl b/source/blender/gpu/shaders/gpu_shader_downsample_maxz_vert.glsl new file mode 100644 index 00000000000..203d5322cee --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_downsample_maxz_vert.glsl @@ -0,0 +1,6 @@ + +void main() +{ + gl_Position = gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; +} diff --git a/source/blender/gpu/shaders/gpu_shader_fx_colormanage_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_colormanage_frag.glsl new file mode 100644 index 00000000000..0d06e808891 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fx_colormanage_frag.glsl @@ -0,0 +1,99 @@ +// color buffer +uniform sampler2D colorbuffer; +uniform sampler3D lut3d_texture; + +uniform float exposure; +uniform float gamma; + +uniform float lut_size = 16.0; + +uniform float displayspace_is_srgb; +uniform float is_offscreen; + +// coordinates on framebuffer in normalized (0.0-1.0) uv space +varying vec4 uvcoordsvar; + +float srgb_to_linearrgb(float c) +{ + if(c < 0.04045) + return (c < 0.0) ? 0.0: c * (1.0 / 12.92); + else + return pow((c + 0.055)*(1.0/1.055), 2.4); +} + +float linearrgb_to_srgb(float c) +{ + if(c < 0.0031308) + return (c < 0.0) ? 0.0: c * 12.92; + else + return 1.055 * pow(c, 1.0/2.4) - 0.055; +} + +void srgb_to_linearrgb(vec4 col_from, out vec4 col_to) +{ + col_to.r = srgb_to_linearrgb(col_from.r); + col_to.g = srgb_to_linearrgb(col_from.g); + col_to.b = srgb_to_linearrgb(col_from.b); + col_to.a = col_from.a; +} + +void linearrgb_to_srgb(vec4 col_from, out vec4 col_to) +{ + col_to.r = linearrgb_to_srgb(col_from.r); + col_to.g = linearrgb_to_srgb(col_from.g); + col_to.b = linearrgb_to_srgb(col_from.b); + col_to.a = col_from.a; +} + +float computeLuminance(vec3 color) +{ + return max(dot(vec3(0.30, 0.59, 0.11), color), 1e-16); +} + +vec3 computeExposedColor(vec3 color, float exposure) +{ + return exp2(exposure) * color; +} + +// Reinhard operator +vec3 tonemapReinhard(vec3 color, float saturation) +{ + float lum = computeLuminance(color); + float toneMappedLuminance = lum / (lum + 1.0); + return toneMappedLuminance * (color / lum); +} + +vec3 applyGamma(vec3 color, float gamma) +{ + gamma = max(gamma, 1e-8); + return vec3( pow(color.r, 1/gamma), pow(color.g, 1/gamma), pow(color.b, 1/gamma) ); +} + +void main() +{ + //float depth = texture2D(depthbuffer, uvcoordsvar.xy).r; + vec4 scene_col = texture2D(colorbuffer, uvcoordsvar.xy); + + if (is_offscreen == 1.0) { + // early out for Ofs. Color management is done later by OCIO + gl_FragColor = scene_col; + return; + } + + if (displayspace_is_srgb == 1.0) + srgb_to_linearrgb(scene_col, scene_col); + + /* Esposure */ + scene_col = vec4( computeExposedColor(scene_col.rgb, exposure), scene_col.a); + + /* LUT 3D in linear space */ + /* TODO find a way to apply it in gamma space to gain accuracy in the black areas */ + //linearrgb_to_srgb(scene_col, scene_col); + scene_col = vec4( texture3D(lut3d_texture, scene_col.rgb * ((lut_size + 1.0f) / lut_size) + (0.5f / lut_size) ).rgb, scene_col.a); + //srgb_to_linearrgb(scene_col, scene_col); + + /* Gamma */ + scene_col = vec4( applyGamma(scene_col.rgb, gamma), scene_col.a); + + gl_FragColor = vec4(scene_col.rgb, scene_col.a); +} diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 119bfb61fec..2b506acabef 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -9,6 +9,11 @@ float convert_rgba_to_float(vec4 color) #endif } +void convert_vec3_to_vec4(vec3 invec, float val, out vec4 outvec) +{ + outvec = vec4(invec, val); +} + float exp_blender(float f) { return pow(2.71828182846, f); @@ -157,7 +162,13 @@ void color_to_blender_normal_new_shading(vec3 color, out vec3 normal) } #define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 +#define M_2PI 6.28318530717958647 +#define M_PI2 9.86960440108935861 #define M_1_PI 0.31830988618379069 +#define M_1_PI2 0.10132118364233777 +#define M_2_PI 0.63661977236758134 +#define M_1_2PI 0.15915494309189533 /*********** SHADER NODES ***************/ @@ -267,7 +278,7 @@ void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) { outdepth = abs(co.z); outdist = length(co); - outview = normalize(co); + outview = normalize(co*vec3(1.0,1.0,-1.0)); } void lamp( @@ -2376,1234 +2387,6 @@ void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol) outcol = vec4(col.rgb, col.a * obcol.a); } -/*********** NEW SHADER UTILITIES **************/ - -float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) -{ - /* compute fresnel reflectance without explicitly computing - * the refracted direction */ - float c = abs(dot(Incoming, Normal)); - float g = eta * eta - 1.0 + c * c; - float result; - - if (g > 0.0) { - g = sqrt(g); - float A = (g - c) / (g + c); - float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); - result = 0.5 * A * A * (1.0 + B * B); - } - else { - result = 1.0; /* TIR (no refracted component) */ - } - - return result; -} - -float hypot(float x, float y) -{ - return sqrt(x * x + y * y); -} - -void generated_from_orco(vec3 orco, out vec3 generated) -{ - generated = orco * 0.5 + vec3(0.5); -} - -int floor_to_int(float x) -{ - return int(floor(x)); -} - -int quick_floor(float x) -{ - return int(x) - ((x < 0) ? 1 : 0); -} - -#ifdef BIT_OPERATIONS -float integer_noise(int n) -{ - int nn; - n = (n + 1013) & 0x7fffffff; - n = (n >> 13) ^ n; - nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; - return 0.5 * (float(nn) / 1073741824.0); -} - -uint hash(uint kx, uint ky, uint kz) -{ -#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) -#define final(a, b, c) \ -{ \ - c ^= b; c -= rot(b, 14); \ - a ^= c; a -= rot(c, 11); \ - b ^= a; b -= rot(a, 25); \ - c ^= b; c -= rot(b, 16); \ - a ^= c; a -= rot(c, 4); \ - b ^= a; b -= rot(a, 14); \ - c ^= b; c -= rot(b, 24); \ -} - // now hash the data! - uint a, b, c, len = 3u; - a = b = c = 0xdeadbeefu + (len << 2u) + 13u; - - c += kz; - b += ky; - a += kx; - final (a, b, c); - - return c; -#undef rot -#undef final -} - -uint hash(int kx, int ky, int kz) -{ - return hash(uint(kx), uint(ky), uint(kz)); -} - -float bits_to_01(uint bits) -{ - float x = float(bits) * (1.0 / float(0xffffffffu)); - return x; -} - -float cellnoise(vec3 p) -{ - int ix = quick_floor(p.x); - int iy = quick_floor(p.y); - int iz = quick_floor(p.z); - - return bits_to_01(hash(uint(ix), uint(iy), uint(iz))); -} - -vec3 cellnoise_color(vec3 p) -{ - float r = cellnoise(p); - float g = cellnoise(vec3(p.y, p.x, p.z)); - float b = cellnoise(vec3(p.y, p.z, p.x)); - - return vec3(r, g, b); -} -#endif // BIT_OPERATIONS - -float floorfrac(float x, out int i) -{ - i = floor_to_int(x); - return x - i; -} - -/*********** NEW SHADER NODES ***************/ - -#define NUM_LIGHTS 3 - -/* bsdfs */ - -void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result) -{ - /* ambient light */ - vec3 L = vec3(0.2); - - /* directional lights */ - for (int i = 0; i < NUM_LIGHTS; i++) { - vec3 light_position = gl_LightSource[i].position.xyz; - vec3 light_diffuse = gl_LightSource[i].diffuse.rgb; - - float bsdf = max(dot(N, light_position), 0.0); - L += light_diffuse * bsdf; - } - - result = vec4(L * color.rgb, 1.0); -} - -void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result) -{ - /* ambient light */ - vec3 L = vec3(0.2); - - /* directional lights */ - for (int i = 0; i < NUM_LIGHTS; i++) { - vec3 light_position = gl_LightSource[i].position.xyz; - vec3 H = gl_LightSource[i].halfVector.xyz; - vec3 light_diffuse = gl_LightSource[i].diffuse.rgb; - vec3 light_specular = gl_LightSource[i].specular.rgb; - - /* we mix in some diffuse so low roughness still shows up */ - float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / roughness); - bsdf += 0.5 * max(dot(N, light_position), 0.0); - L += light_specular * bsdf; - } - - result = vec4(L * color.rgb, 1.0); -} - -void node_bsdf_anisotropic( - vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T, - out vec4 result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, out vec4 result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_bsdf_transparent(vec4 color, out vec4 result) -{ - /* this isn't right */ - result.r = color.r; - result.g = color.g; - result.b = color.b; - result.a = 0.0; -} - -void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_subsurface_scattering( - vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, - out vec4 result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out vec4 result) -{ - result = color; -} - -void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out vec4 result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_ambient_occlusion(vec4 color, out vec4 result) -{ - result = color; -} - -/* emission */ - -void node_emission(vec4 color, float strength, vec3 N, out vec4 result) -{ - result = color * strength; -} - -/* background */ - -void background_transform_to_world(vec3 viewvec, out vec3 worldvec) -{ - vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); - - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - worldvec = (gl_ModelViewMatrixInverse * co).xyz; -} - -void node_background(vec4 color, float strength, vec3 N, out vec4 result) -{ - result = color * strength; -} - -/* closures */ - -void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader) -{ - shader = mix(shader1, shader2, fac); -} - -void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader) -{ - shader = shader1 + shader2; -} - -/* fresnel */ - -void node_fresnel(float ior, vec3 N, vec3 I, out float result) -{ - /* handle perspective/orthographic */ - vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - - float eta = max(ior, 0.00001); - result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta); -} - -/* layer_weight */ - -void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing) -{ - /* fresnel */ - float eta = max(1.0 - blend, 0.00001); - vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - - fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta); - - /* facing */ - facing = abs(dot(I_view, N)); - if (blend != 0.5) { - blend = clamp(blend, 0.0, 0.99999); - blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); - facing = pow(facing, blend); - } - facing = 1.0 - facing; -} - -/* gamma */ - -void node_gamma(vec4 col, float gamma, out vec4 outcol) -{ - outcol = col; - - if (col.r > 0.0) - outcol.r = compatible_pow(col.r, gamma); - if (col.g > 0.0) - outcol.g = compatible_pow(col.g, gamma); - if (col.b > 0.0) - outcol.b = compatible_pow(col.b, gamma); -} - -/* geometry */ - -void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf) -{ - outcol = vec4(attr, 1.0); - outvec = attr; - outf = (attr.x + attr.y + attr.z) / 3.0; -} - -void node_uvmap(vec3 attr_uv, out vec3 outvec) -{ - outvec = attr_uv; -} - -void node_geometry( - vec3 I, vec3 N, mat4 toworld, - out vec3 position, out vec3 normal, out vec3 tangent, - out vec3 true_normal, out vec3 incoming, out vec3 parametric, - out float backfacing, out float pointiness) -{ - position = (toworld * vec4(I, 1.0)).xyz; - normal = (toworld * vec4(N, 0.0)).xyz; - tangent = vec3(0.0); - true_normal = normal; - - /* handle perspective/orthographic */ - vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - incoming = -(toworld * vec4(I_view, 0.0)).xyz; - - parametric = vec3(0.0); - backfacing = (gl_FrontFacing) ? 0.0 : 1.0; - pointiness = 0.0; -} - -void node_tex_coord( - vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac, - vec3 attr_orco, vec3 attr_uv, - out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, - out vec3 camera, out vec3 window, out vec3 reflection) -{ - generated = attr_orco * 0.5 + vec3(0.5); - normal = normalize((obinvmat * (viewinvmat * vec4(N, 0.0))).xyz); - uv = attr_uv; - object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz; - camera = vec3(I.xy, -I.z); - vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0); - window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); - - vec3 shade_I; - shade_view(I, shade_I); - vec3 view_reflection = reflect(shade_I, normalize(N)); - reflection = (viewinvmat * vec4(view_reflection, 0.0)).xyz; -} - -void node_tex_coord_background( - vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac, - vec3 attr_orco, vec3 attr_uv, - out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, - out vec3 camera, out vec3 window, out vec3 reflection) -{ - vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); - - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - - co = normalize(co); - vec3 coords = (gl_ModelViewMatrixInverse * co).xyz; - - generated = coords; - normal = -coords; - uv = vec3(attr_uv.xy, 0.0); - object = coords; - - camera = vec3(co.xy, -co.z); - window = (gl_ProjectionMatrix[3][3] == 0.0) ? - vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) : - vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0); - - reflection = -coords; -} - -/* textures */ - -float calc_gradient(vec3 p, int gradient_type) -{ - float x, y, z; - x = p.x; - y = p.y; - z = p.z; - if (gradient_type == 0) { /* linear */ - return x; - } - else if (gradient_type == 1) { /* quadratic */ - float r = max(x, 0.0); - return r * r; - } - else if (gradient_type == 2) { /* easing */ - float r = min(max(x, 0.0), 1.0); - float t = r * r; - return (3.0 * t - 2.0 * t * r); - } - else if (gradient_type == 3) { /* diagonal */ - return (x + y) * 0.5; - } - else if (gradient_type == 4) { /* radial */ - return atan(y, x) / (M_PI * 2) + 0.5; - } - else { - float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0); - if (gradient_type == 5) { /* quadratic sphere */ - return r * r; - } - else if (gradient_type == 6) { /* sphere */ - return r; - } - } - return 0.0; -} - -void node_tex_gradient(vec3 co, float gradient_type, out vec4 color, out float fac) -{ - float f = calc_gradient(co, int(gradient_type)); - f = clamp(f, 0.0, 1.0); - - color = vec4(f, f, f, 1.0); - fac = f; -} - -void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac) -{ - vec3 p = co * scale; - - /* Prevent precision issues on unit coordinates. */ - p.x = (p.x + 0.000001) * 0.999999; - p.y = (p.y + 0.000001) * 0.999999; - p.z = (p.z + 0.000001) * 0.999999; - - int xi = int(abs(floor(p.x))); - int yi = int(abs(floor(p.y))); - int zi = int(abs(floor(p.z))); - - bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2))); - - color = check ? color1 : color2; - fac = check ? 1.0 : 0.0; -} - -#ifdef BIT_OPERATIONS -vec2 calc_brick_texture(vec3 p, float mortar_size, float bias, - float brick_width, float row_height, - float offset_amount, int offset_frequency, - float squash_amount, int squash_frequency) -{ - int bricknum, rownum; - float offset = 0.0; - float x, y; - - rownum = floor_to_int(p.y / row_height); - - if (offset_frequency != 0 && squash_frequency != 0) { - brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */ - offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */ - } - - bricknum = floor_to_int((p.x + offset) / brick_width); - - x = (p.x + offset) - brick_width * bricknum; - y = p.y - row_height * rownum; - - return vec2(clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0), - (x < mortar_size || y < mortar_size || - x > (brick_width - mortar_size) || - y > (row_height - mortar_size)) ? 1.0 : 0.0); -} -#endif - -void node_tex_brick(vec3 co, - vec4 color1, vec4 color2, - vec4 mortar, float scale, - float mortar_size, float bias, - float brick_width, float row_height, - float offset_amount, float offset_frequency, - float squash_amount, float squash_frequency, - out vec4 color, out float fac) -{ -#ifdef BIT_OPERATIONS - vec2 f2 = calc_brick_texture(co * scale, - mortar_size, bias, - brick_width, row_height, - offset_amount, int(offset_frequency), - squash_amount, int(squash_frequency)); - float tint = f2.x; - float f = f2.y; - if (f != 1.0) { - float facm = 1.0 - tint; - color1 = facm * color1 + tint * color2; - } - color = (f == 1.0) ? mortar : color1; - fac = f; -#else - color = vec4(1.0); - fac = 1.0; -#endif -} - -void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac) -{ - color = vec4(1.0); - fac = 1.0; -} - -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; - - color = texture2D(ima, vec2(u, v)); -} - -void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color) -{ - vec3 nco = normalize(co); - - nco.y -= 1.0; - - float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0)); - if (div > 0.0) - nco /= div; - - float u = 0.5 * (nco.x + 1.0); - float v = 0.5 * (nco.z + 1.0); - - color = texture2D(ima, vec2(u, v)); -} - -void node_tex_environment_empty(vec3 co, out vec4 color) -{ - color = vec4(1.0, 0.0, 1.0, 1.0); -} - -void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - color = texture2D(ima, co.xy); - alpha = color.a; -} - -void node_tex_image_box(vec3 texco, - vec3 nob, - sampler2D ima, - float blend, - out vec4 color, - out float alpha) -{ - /* project from direction vector to barycentric coordinates in triangles */ - nob = vec3(abs(nob.x), abs(nob.y), abs(nob.z)); - nob /= (nob.x + nob.y + nob.z); - - /* basic idea is to think of this as a triangle, each corner representing - * one of the 3 faces of the cube. in the corners we have single textures, - * in between we blend between two textures, and in the middle we a blend - * between three textures. - * - * the Nxyz values are the barycentric coordinates in an equilateral - * triangle, which in case of blending, in the middle has a smaller - * equilateral triangle where 3 textures blend. this divides things into - * 7 zones, with an if () test for each zone */ - - vec3 weight = vec3(0.0, 0.0, 0.0); - float limit = 0.5 * (1.0 + blend); - - /* first test for corners with single texture */ - if (nob.x > limit * (nob.x + nob.y) && nob.x > limit * (nob.x + nob.z)) { - weight.x = 1.0; - } - else if (nob.y > limit * (nob.x + nob.y) && nob.y > limit * (nob.y + nob.z)) { - weight.y = 1.0; - } - else if (nob.z > limit * (nob.x + nob.z) && nob.z > limit * (nob.y + nob.z)) { - weight.z = 1.0; - } - else if (blend > 0.0) { - /* in case of blending, test for mixes between two textures */ - if (nob.z < (1.0 - limit) * (nob.y + nob.x)) { - weight.x = nob.x / (nob.x + nob.y); - weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); - weight.y = 1.0 - weight.x; - } - else if (nob.x < (1.0 - limit) * (nob.y + nob.z)) { - weight.y = nob.y / (nob.y + nob.z); - weight.y = clamp((weight.y - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); - weight.z = 1.0 - weight.y; - } - else if (nob.y < (1.0 - limit) * (nob.x + nob.z)) { - weight.x = nob.x / (nob.x + nob.z); - weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); - weight.z = 1.0 - weight.x; - } - else { - /* last case, we have a mix between three */ - weight.x = ((2.0 - limit) * nob.x + (limit - 1.0)) / (2.0 * limit - 1.0); - weight.y = ((2.0 - limit) * nob.y + (limit - 1.0)) / (2.0 * limit - 1.0); - weight.z = ((2.0 - limit) * nob.z + (limit - 1.0)) / (2.0 * limit - 1.0); - } - } - else { - /* Desperate mode, no valid choice anyway, fallback to one side.*/ - weight.x = 1.0; - } - color = vec4(0); - if (weight.x > 0.0) { - color += weight.x * texture2D(ima, texco.yz); - } - if (weight.y > 0.0) { - color += weight.y * texture2D(ima, texco.xz); - } - if (weight.z > 0.0) { - color += weight.z * texture2D(ima, texco.yx); - } - - alpha = color.a; -} - -void node_tex_image_empty(vec3 co, out vec4 color, out float alpha) -{ - color = vec4(0.0); - alpha = 0.0; -} - -void node_tex_magic(vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac) -{ - vec3 p = co * scale; - float x = sin((p.x + p.y + p.z) * 5.0); - float y = cos((-p.x + p.y - p.z) * 5.0); - float z = -cos((-p.x - p.y + p.z) * 5.0); - - if (depth > 0) { - x *= distortion; - y *= distortion; - z *= distortion; - y = -cos(x - y + z); - y *= distortion; - if (depth > 1) { - x = cos(x - y - z); - x *= distortion; - if (depth > 2) { - z = sin(-x - y - z); - z *= distortion; - if (depth > 3) { - x = -cos(-x + y - z); - x *= distortion; - if (depth > 4) { - y = -sin(-x + y + z); - y *= distortion; - if (depth > 5) { - y = -cos(-x + y + z); - y *= distortion; - if (depth > 6) { - x = cos(x + y + z); - x *= distortion; - if (depth > 7) { - z = sin(x + y - z); - z *= distortion; - if (depth > 8) { - x = -cos(-x - y + z); - x *= distortion; - if (depth > 9) { - y = -sin(x - y + z); - y *= distortion; - } - } - } - } - } - } - } - } - } - } - if (distortion != 0.0) { - distortion *= 2.0; - x /= distortion; - y /= distortion; - z /= distortion; - } - - color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0); - fac = (color.x + color.y + color.z) / 3.0; -} - -#ifdef BIT_OPERATIONS -float noise_fade(float t) -{ - return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); -} - -float noise_scale3(float result) -{ - return 0.9820 * result; -} - -float noise_nerp(float t, float a, float b) -{ - return (1.0 - t) * a + t * b; -} - -float noise_grad(uint hash, float x, float y, float z) -{ - uint h = hash & 15u; - float u = h < 8u ? x : y; - float vt = ((h == 12u) || (h == 14u)) ? x : z; - float v = h < 4u ? y : vt; - return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v); -} - -float noise_perlin(float x, float y, float z) -{ - int X; float fx = floorfrac(x, X); - int Y; float fy = floorfrac(y, Y); - int Z; float fz = floorfrac(z, Z); - - float u = noise_fade(fx); - float v = noise_fade(fy); - float w = noise_fade(fz); - - float result; - - result = noise_nerp(w, noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z), fx, fy, fz), - noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz)), - noise_nerp(u, noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz), - noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz))), - noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0), - noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)), - noise_nerp(u, noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0), - noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0)))); - return noise_scale3(result); -} - -float noise(vec3 p) -{ - return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5; -} - -float snoise(vec3 p) -{ - return noise_perlin(p.x, p.y, p.z); -} - -float noise_turbulence(vec3 p, float octaves, int hard) -{ - float fscale = 1.0; - float amp = 1.0; - float sum = 0.0; - int i, n; - octaves = clamp(octaves, 0.0, 16.0); - n = int(octaves); - for (i = 0; i <= n; i++) { - float t = noise(fscale * p); - if (hard != 0) { - t = abs(2.0 * t - 1.0); - } - sum += t * amp; - amp *= 0.5; - fscale *= 2.0; - } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = noise(fscale * p); - if (hard != 0) { - t = abs(2.0 * t - 1.0); - } - float sum2 = sum + t * amp; - sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); - sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1)); - return (1.0 - rmd) * sum + rmd * sum2; - } - else { - sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); - return sum; - } -} -#endif // BIT_OPERATIONS - -void node_tex_noise(vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac) -{ -#ifdef BIT_OPERATIONS - vec3 p = co * scale; - int hard = 0; - if (distortion != 0.0) { - vec3 r, offset = vec3(13.5, 13.5, 13.5); - r.x = noise(p + offset) * distortion; - r.y = noise(p) * distortion; - r.z = noise(p - offset) * distortion; - p += r; - } - - fac = noise_turbulence(p, detail, hard); - color = vec4(fac, - noise_turbulence(vec3(p.y, p.x, p.z), detail, hard), - noise_turbulence(vec3(p.y, p.z, p.x), detail, hard), - 1); -#else // BIT_OPERATIONS - color = vec4(1.0); - fac = 1.0; -#endif // BIT_OPERATIONS -} - - -#ifdef BIT_OPERATIONS - -/* Musgrave fBm - * - * H: fractal increment parameter - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * - * from "Texturing and Modelling: A procedural approach" - */ - -float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves) -{ - float rmd; - float value = 0.0; - float pwr = 1.0; - float pwHL = pow(lacunarity, -H); - int i; - - for (i = 0; i < int(octaves); i++) { - value += snoise(p) * pwr; - pwr *= pwHL; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) - value += rmd * snoise(p) * pwr; - - return value; -} - -/* Musgrave Multifractal - * - * H: highest fractal dimension - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - */ - -float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves) -{ - float rmd; - float value = 1.0; - float pwr = 1.0; - float pwHL = pow(lacunarity, -H); - int i; - - for (i = 0; i < int(octaves); i++) { - value *= (pwr * snoise(p) + 1.0); - pwr *= pwHL; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) - value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ - - return value; -} - -/* Musgrave Heterogeneous Terrain - * - * H: fractal dimension of the roughest area - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * offset: raises the terrain from `sea level' - */ - -float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset) -{ - float value, increment, rmd; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; - int i; - - /* first unscaled octave of function; later octaves are scaled */ - value = offset + snoise(p); - p *= lacunarity; - - for (i = 1; i < int(octaves); i++) { - increment = (snoise(p) + offset) * pwr * value; - value += increment; - pwr *= pwHL; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - increment = (snoise(p) + offset) * pwr * value; - value += rmd * increment; - } - - return value; -} - -/* Hybrid Additive/Multiplicative Multifractal Terrain - * - * H: fractal dimension of the roughest area - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * offset: raises the terrain from `sea level' - */ - -float noise_musgrave_hybrid_multi_fractal(vec3 p, float H, float lacunarity, float octaves, float offset, float gain) -{ - float result, signal, weight, rmd; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; - int i; - - result = snoise(p) + offset; - weight = gain * result; - p *= lacunarity; - - for (i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { - if (weight > 1.0) - weight = 1.0; - - signal = (snoise(p) + offset) * pwr; - pwr *= pwHL; - result += weight * signal; - weight *= gain * signal; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) - result += rmd * ((snoise(p) + offset) * pwr); - - return result; -} - -/* Ridged Multifractal Terrain - * - * H: fractal dimension of the roughest area - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * offset: raises the terrain from `sea level' - */ - -float noise_musgrave_ridged_multi_fractal(vec3 p, float H, float lacunarity, float octaves, float offset, float gain) -{ - float result, signal, weight; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; - int i; - - signal = offset - abs(snoise(p)); - signal *= signal; - result = signal; - weight = 1.0; - - for (i = 1; i < int(octaves); i++) { - p *= lacunarity; - weight = clamp(signal * gain, 0.0, 1.0); - signal = offset - abs(snoise(p)); - signal *= signal; - signal *= weight; - result += signal * pwr; - pwr *= pwHL; - } - - return result; -} - -float svm_musgrave(int type, - float dimension, - float lacunarity, - float octaves, - float offset, - float intensity, - float gain, - vec3 p) -{ - if (type == 0 /*NODE_MUSGRAVE_MULTIFRACTAL*/) - return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves); - else if (type == 1 /*NODE_MUSGRAVE_FBM*/) - return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves); - else if (type == 2 /*NODE_MUSGRAVE_HYBRID_MULTIFRACTAL*/) - return intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - else if (type == 3 /*NODE_MUSGRAVE_RIDGED_MULTIFRACTAL*/) - return intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - else if (type == 4 /*NODE_MUSGRAVE_HETERO_TERRAIN*/) - return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset); - return 0.0; -} -#endif // #ifdef BIT_OPERATIONS - -void node_tex_musgrave(vec3 co, - float scale, - float detail, - float dimension, - float lacunarity, - float offset, - float gain, - float type, - out vec4 color, - out float fac) -{ -#ifdef BIT_OPERATIONS - fac = svm_musgrave(int(type), - dimension, - lacunarity, - detail, - offset, - 1.0, - gain, - co * scale); -#else - fac = 1.0; -#endif - - color = vec4(fac, fac, fac, 1.0); -} - -void node_tex_sky(vec3 co, out vec4 color) -{ - color = vec4(1.0); -} - -void node_tex_voronoi(vec3 co, float scale, float coloring, out vec4 color, out float fac) -{ -#ifdef BIT_OPERATIONS - vec3 p = co * scale; - int xx, yy, zz, xi, yi, zi; - float da[4]; - vec3 pa[4]; - - xi = floor_to_int(p[0]); - yi = floor_to_int(p[1]); - zi = floor_to_int(p[2]); - - da[0] = 1e+10; - da[1] = 1e+10; - da[2] = 1e+10; - da[3] = 1e+10; - - for (xx = xi - 1; xx <= xi + 1; xx++) { - for (yy = yi - 1; yy <= yi + 1; yy++) { - for (zz = zi - 1; zz <= zi + 1; zz++) { - vec3 ip = vec3(xx, yy, zz); - vec3 vp = cellnoise_color(ip); - vec3 pd = p - (vp + ip); - float d = dot(pd, pd); - vp += vec3(xx, yy, zz); - if (d < da[0]) { - da[3] = da[2]; - da[2] = da[1]; - da[1] = da[0]; - da[0] = d; - pa[3] = pa[2]; - pa[2] = pa[1]; - pa[1] = pa[0]; - pa[0] = vp; - } - else if (d < da[1]) { - da[3] = da[2]; - da[2] = da[1]; - da[1] = d; - - pa[3] = pa[2]; - pa[2] = pa[1]; - pa[1] = vp; - } - else if (d < da[2]) { - da[3] = da[2]; - da[2] = d; - - pa[3] = pa[2]; - pa[2] = vp; - } - else if (d < da[3]) { - da[3] = d; - pa[3] = vp; - } - } - } - } - - if (coloring == 0.0) { - fac = abs(da[0]); - color = vec4(fac, fac, fac, 1); - } - else { - color = vec4(cellnoise_color(pa[0]), 1); - fac = (color.x + color.y + color.z) * (1.0 / 3.0); - } -#else // BIT_OPERATIONS - color = vec4(1.0); - fac = 1.0; -#endif // BIT_OPERATIONS -} - -#ifdef BIT_OPERATIONS -float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile) -{ - float n; - - if (wave_type == 0) /* type bands */ - n = (p.x + p.y + p.z) * 10.0; - else /* type rings */ - n = length(p) * 20.0; - - if (distortion != 0.0) - n += distortion * noise_turbulence(p * detail_scale, detail, 0); - - if (wave_profile == 0) { /* profile sin */ - return 0.5 + 0.5 * sin(n); - } - else { /* profile saw */ - n /= 2.0 * M_PI; - n -= int(n); - return (n < 0.0) ? n + 1.0 : n; - } -} -#endif // BIT_OPERATIONS - -void node_tex_wave( - vec3 co, float scale, float distortion, float detail, float detail_scale, float wave_type, float wave_profile, - out vec4 color, out float fac) -{ -#ifdef BIT_OPERATIONS - float f; - f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile)); - - color = vec4(f, f, f, 1.0); - fac = f; -#else // BIT_OPERATIONS - color = vec4(1.0); - fac = 1; -#endif // BIT_OPERATIONS -} - -/* light path */ - -void node_light_path( - out float is_camera_ray, - out float is_shadow_ray, - out float is_diffuse_ray, - out float is_glossy_ray, - out float is_singular_ray, - out float is_reflection_ray, - out float is_transmission_ray, - out float ray_length, - out float ray_depth, - out float transparent_depth, - out float transmission_depth) -{ - is_camera_ray = 1.0; - is_shadow_ray = 0.0; - is_diffuse_ray = 0.0; - is_glossy_ray = 0.0; - is_singular_ray = 0.0; - is_reflection_ray = 0.0; - is_transmission_ray = 0.0; - ray_length = 1.0; - ray_depth = 1.0; - transparent_depth = 1.0; - transmission_depth = 1.0; -} - -void node_light_falloff(float strength, float tsmooth, out float quadratic, out float linear, out float constant) -{ - quadratic = strength; - linear = strength; - constant = strength; -} - -void node_object_info(out vec3 location, out float object_index, out float material_index, out float random) -{ - location = vec3(0.0); - object_index = 0.0; - material_index = 0.0; - random = 0.0; -} - -void node_normal_map(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) -{ - vec3 B = tangent.w * cross(normal, tangent.xyz); - - outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal; - outnormal = normalize(outnormal); -} - -void node_bump(float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result) -{ - if (invert != 0.0) { - dist *= -1.0; - } - vec3 dPdx = dFdx(surf_pos); - vec3 dPdy = dFdy(surf_pos); - - /* Get surface tangents from normal. */ - vec3 Rx = cross(dPdy, N); - vec3 Ry = cross(N, dPdx); - - /* Compute surface gradient and determinant. */ - float det = dot(dPdx, Rx); - float absdet = abs(det); - - float dHdx = dFdx(height); - float dHdy = dFdy(height); - vec3 surfgrad = dHdx * Rx + dHdy * Ry; - - strength = max(strength, 0.0); - - result = normalize(absdet * N - dist * sign(det) * surfgrad); - result = normalize(strength * result + (1.0 - strength) * N); -} - -/* output */ - -void node_output_material(vec4 surface, vec4 volume, float displacement, out vec4 result) -{ - result = surface; -} - -void node_output_world(vec4 surface, vec4 volume, out vec4 result) -{ - result = surface; -} - /* ********************** matcap style render ******************** */ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result) diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_ambient_occlusion.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_ambient_occlusion.glsl new file mode 100644 index 00000000000..a7f594a29f5 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_ambient_occlusion.glsl @@ -0,0 +1,160 @@ +/* -------- Utils Functions --------- */ +vec2 sample_disk(float nsample, float invsamplenbr) +{ + vec3 Xi = hammersley_3d(nsample, invsamplenbr); + + float x = Xi.x * Xi.y; + float y = Xi.x * Xi.z; + + return vec2(x, y); +} + +vec3 sample_hemisphere(float nsample, float invsamplenbr, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample, invsamplenbr); + + float z = Xi.x; /* cos theta */ + float r = sqrt( 1.0f - z*z ); /* sin theta */ + float x = r * Xi.y; + float y = r * Xi.z; + + Ht = vec3(x, y, z); /* Global variable */ + + return from_tangent_to_world(Ht, N, T, B); +} + +#ifdef USE_SSAO + +#if 0 /* Cheap */ + +float ssao(vec3 viewpos, vec3 viewnor, out float result) +{ + float dist = unfssaoparam.z; + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + + /* get uv of the shading point */ + vec4 projvec = gl_ProjectionMatrix * vec4(viewpos, 1.0); + vec2 uv = (projvec.xy / projvec.w) * 0.5 + 0.5; + + vec2 offset; + offset.x = gl_ProjectionMatrix[0][0] * dist / projvec.w; + offset.y = gl_ProjectionMatrix[1][1] * dist / projvec.w; + /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */ + offset *= 0.5; + + float factor = 0.0; + /* We don't need as much samples for ssao */ + for (float i = 0; i < unfssaoparam.x; i++) { + vec2 Xi = sample_disk(i, 1/unfssaoparam.x); + vec2 uvsample = uv + Xi * offset; + + if (uvsample.x > 1.0 || uvsample.x < 0.0 || uvsample.y > 1.0 || uvsample.y < 0.0) + continue; + + float sampledepth = frontface_depth_linear(ivec2(uvsample * unfclip.zw)); + + /* Background Case */ + if (sampledepth == 1.0) + continue; + + vec3 samplepos = position_from_depth(uvsample, sampledepth); + + vec3 dir = samplepos - viewpos; + float len = length(dir); + float f = dot(dir, viewnor); + + /* use minor bias here to cancel self shadowing */ + if (f > 0.05 * len + 0.0001) + factor += f / (len + len * len * len); + } + + result = saturate(1.0 - factor / unfssaoparam.x); +} + +#else /* Expensive */ + +void ssao(vec3 viewpos, vec3 viewnor, out float result) +{ + float dist = unfssaoparam.z; + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + + vec3 T; + make_orthonormals(viewnor, T, B); /* Generate tangent space */ + + float homcoord = (gl_ProjectionMatrix[3][3] == 0.0) ? gl_ProjectionMatrix[2][3] * viewpos.z : dist; + + float factor = 0.0; + float weight = 0.0; + + for (float i = 0; i < unfssaoparam.x; i++) { + vec3 Xi = sample_hemisphere(i, 1/unfssaoparam.x, viewnor, T, B); + + float pdf = dot(Xi, viewnor); + weight += pdf; + + /* Raymarch */ + /* We jitter the starting position by a percentage of the normal + * offset to a v o i d banding artifact for thin objects but + * we still finish at the same final position to a v o i d + * less sampling at the edges of the occlusion effect */ + vec3 offset = dist * Xi / unfssaoparam.y; + vec3 ray = (jitternoise.y - 0.5) * -offset; + vec3 endoffset = offset - ray; + + for (float j = unfssaoparam.y; j > 0.0; j--) { + + ray += (j == 1) ? endoffset : offset; + + vec4 co = unfpixelprojmat * vec4(ray + viewpos, 1.0); + co.xy /= co.w; + + /* Discard ray leaving screen */ + if (co.x > unfclip.z || co.x < 0.0 || co.y > unfclip.w || co.y < 0.0) + break; + + float sampledepth = frontface_depth_linear(ivec2(co.xy), 0); + + /* Background Case */ + if (sampledepth == 1.0) + continue; + + /* We have a hit */ + if (sampledepth > ray.z + viewpos.z + homcoord * 0.002 +#ifdef USE_BACKFACE + && backface_depth_linear(ivec2(co.xy), 0) < ray.z + viewpos.z +#endif + ) + { + factor += pdf; + break; + } + } + } + + result = saturate(1.0 - (factor / weight) * unfssaoparam.w); +} +#endif +#else +void ssao(vec3 viewpos, vec3 viewnor, out float result) +{ + result = 1.0; +} +#endif + + +/* -------- BSDF --------- */ + +/* -------- Preview Lights --------- */ + +/* -------- Physical Lights --------- */ + +/* -------- Image Based Lighting --------- */ + +void env_sampling_ambient_occlusion( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + result = vec3(ao_factor); +}
\ No newline at end of file diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_anisotropic.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_anisotropic.glsl new file mode 100644 index 00000000000..cad9e28037a --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_anisotropic.glsl @@ -0,0 +1,772 @@ +/* -------- Utils Functions --------- */ + +/* From + * Importance Sampling Microfacet-Based BSDFs with the Distribution of Visible Normals + * Supplemental Material 2/2 */ +vec3 sample_ggx_aniso(float nsample, float ax, float ay, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + + float tmp = sqrt( Xi.x / (1.0 - Xi.x) ); + + float x = ax * tmp * Xi.y; + float y = ay * tmp * Xi.z; + + Ht = normalize(vec3(x, y, 1.0)); /* Global variable */ + + return from_tangent_to_world(Ht, N, T, B); +} + +vec3 sample_beckmann_aniso(float nsample, float ax, float ay, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + + float tmp = sqrt( -log(Xi.x) ); + + float x = ax * tmp * Xi.y; + float y = ay * tmp * Xi.z; + + Ht = normalize(vec3(x, y, 1.0)); /* Global variable */ + + return from_tangent_to_world(Ht, N, T, B); +} + +float bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, float n_y, inout vec3 Xi, out float phi) +{ + phi = atan(sqrt((n_x + 1.0) / (n_y + 1.0)) * (Xi.z / Xi.y)); + Xi.y = cos(phi); + Xi.z = sin(phi); + return pow(Xi.x, 1.0 / (n_x * Xi.y*Xi.y + n_y * Xi.z*Xi.z + 1.0)); +} + +vec3 sample_ashikhmin_shirley_aniso(float nsample, float n_x, float n_y, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + float phi, z; + + if(Xi.x < 0.25) { /* first quadrant */ + Xi.x = 4.0 * Xi.x; + z = bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, Xi, phi); + } + else if(Xi.x < 0.5) { /* second quadrant */ + Xi.x = 4.0 * (.5 - Xi.x); + z = bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, Xi, phi); + phi = M_PI - phi; + Xi.y = cos(phi); + Xi.z = sin(phi); + } + else if(Xi.x < 0.75) { /* third quadrant */ + Xi.x = 4.0 * (Xi.x - 0.5); + z = bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, Xi, phi); + phi = M_PI + phi; + Xi.y = cos(phi); + Xi.z = sin(phi); + } + else { /* fourth quadrant */ + Xi.x = 4.0 * (1.0 - Xi.x); + z = bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, Xi, phi); + phi = M_2PI - phi; + Xi.y = cos(phi); + Xi.z = sin(phi); + } + + float r = sqrt( 1.0 - z * z ); /* sin theta */ + float x = r * Xi.y; + float y = r * Xi.z; + + Ht = vec3(x, y, z); /* Global variable */ + + return from_tangent_to_world(Ht, N, T, B); +} + +float D_ggx_aniso_opti(float NH, float XH2, float YH2, float a2, float ax2, float ay2) +{ + float tmp = NH*NH + XH2/ax2 + YH2/ay2; /* Distributing NH² */ + return M_PI * a2 * tmp*tmp; /* Doing RCP at the end */ +} + +float D_beckmann_aniso(float NH, float XH, float YH, float a2, float ax, float ay) +{ + float sx = -XH / (NH * ax); + float sy = -YH / (NH * ay); + + float NH2 = NH * NH; + + return exp(-sx*sx - sy*sy) / (M_PI * a2 * NH2 * NH2); +} + +float pdf_ggx_aniso(float NH, float XH2, float YH2, float a2, float ax2, float ay2) +{ + float D = D_ggx_aniso_opti(NH, XH2, YH2, a2, ax2, ay2); + return NH / D; +} + +float pdf_beckmann_aniso(float NH, float XH, float YH, float a2, float ax, float ay) +{ + float D = D_beckmann_aniso(NH, XH, YH, a2, ax, ay); + return NH / D; +} + +float pdf_ashikhmin_shirley_aniso(float NH, float VH, float XH2, float YH2, float n_x, float n_y) +{ + float e = (n_x * XH2 + n_y * YH2) / (1.0 - NH*NH); + float lobe = pow(NH, e); + float norm = sqrt((n_x + 1.0)*(n_y + 1.0)) * 0.125 * M_1_PI; + + return norm * lobe / VH; +} + +/* TODO : this could be precomputed */ +void prepare_aniso(vec3 N, float roughness, float rotation, inout vec3 T, inout float anisotropy, out float rough_x, out float rough_y) +{ + anisotropy = clamp(anisotropy, -0.99, 0.99); + + if (anisotropy < 0.0) { + rough_x = roughness / (1.0 + anisotropy); + rough_y = roughness * (1.0 + anisotropy); + } + else { + rough_x = roughness * (1.0 - anisotropy); + rough_y = roughness / (1.0 - anisotropy); + } + + T = axis_angle_rotation(T, N, rotation * M_2PI); /* rotate tangent around normal */ +} + +/* -------- BSDF --------- */ + +float bsdf_ggx_aniso(vec3 N, vec3 T, vec3 L, vec3 V, float roughness_x, float roughness_y) +{ + /* GGX Spec Anisotropic */ + /* A few note about notations : + * I is the cycles term for Incoming Light, Noted L here (light vector) + * Omega (O) is the cycles term for the Outgoing Light, Noted V here (View vector) */ + N = normalize(N); + vec3 X = T, Y, Z = N; /* Inside cycles Z=Normal; X=Tangent; Y=Bitangent; */ + make_orthonormals_tangent(Z, X, Y); + vec3 H = normalize(L + V); + + float ax, ax2; prepare_glossy(roughness_x, ax, ax2); + float ay, ay2; prepare_glossy(roughness_y, ay, ay2); + float a2 = ax*ay; + + float NH = max(1e-8, dot(N, H)); + float NL = max(1e-8, dot(N, L)); + float NV = max(1e-8, dot(N, V)); + float VX2 = pow(dot(V, X), 2); /* cosPhiO² */ + float VY2 = pow(dot(V, Y), 2); /* sinPhiO² */ + float LX2 = pow(dot(L, X), 2); /* cosPhiI² */ + float LY2 = pow(dot(L, Y), 2); /* sinPhiI² */ + float XH2 = pow(dot(X, H), 2); + float YH2 = pow(dot(Y, H), 2); + + /* G_Smith_GGX */ + float alphaV2 = (VX2 * ax2 + VY2 * ay2) / (VX2 + VY2); + float alphaL2 = (LX2 * ax2 + LY2 * ay2) / (LX2 + LY2); + float G = G1_Smith_GGX(NV, alphaV2) * G1_Smith_GGX(NL, alphaL2); /* Doing RCP at the end */ + + /* D_GGX */ + float D = D_ggx_aniso_opti(NH, XH2, YH2, a2, ax2, ay2); + + /* Denominator is canceled by G1_Smith */ + /* bsdf = D * G / (4.0 * NL * NV); /* Reference function */ + return NL / (D * G); /* NL to Fit cycles Equation : line. 345 in bsdf_microfacet.h */ +} + +/* This one returns the brdf already divided by the pdf */ +float bsdf_ggx_aniso_pdf(float ax2, float ay2, float LX2, float LY2, float NH, float NV, float NL, float VH, float G1_V) +{ + float alphaL2 = (LX2 * ax2 + LY2 * ay2) / (LX2 + LY2); + float G = G1_V * G1_Smith_GGX(NL, alphaL2); + + /* Denominator is canceled by G1_Smith + * brdf = D * G / (4.0 * NL * NV) + * pdf = D * NH / (4 * VH) [D canceled later by D in brdf] */ + return 4.0 * VH / (NH * G); /* brdf / pdf */ +} + +float bsdf_beckmann_aniso(vec3 N, vec3 T, vec3 L, vec3 V, float roughness_x, float roughness_y) +{ + /* Beckmann Spec Anisotropic */ + /* A few note about notations : + * I is the cycles term for Incoming Light, Noted L here (light vector) + * Omega (O) is the cycles term for the Outgoing Light, Noted V here (View vector) */ + N = normalize(N); + vec3 X = T, Y, Z = N; /* Inside cycles Z=Normal; X=Tangent; Y=Bitangent; */ + make_orthonormals_tangent(Z, X, Y); + vec3 H = normalize(L + V); + + float ax, ax2; prepare_glossy(roughness_x, ax, ax2); + float ay, ay2; prepare_glossy(roughness_y, ay, ay2); + float a2 = ax*ay; + + float NH = max(1e-8, dot(N, H)); + float NL = max(1e-8, dot(N, L)); + float NV = max(1e-8, dot(N, V)); + float VX2 = pow(dot(V, X), 2); /* cosPhiO² */ + float VY2 = pow(dot(V, Y), 2); /* sinPhiO² */ + float LX2 = pow(dot(L, X), 2); /* cosPhiI² */ + float LY2 = pow(dot(L, Y), 2); /* sinPhiI² */ + float XH = dot(X, H); + float YH = dot(Y, H); + + float alphaV2 = (VX2 * ax2 + VY2 * ay2) / (VX2 + VY2); + float alphaL2 = (LX2 * ax2 + LY2 * ay2) / (LX2 + LY2); + float G = G1_Smith_beckmann(NV, alphaV2) * G1_Smith_beckmann(NL, alphaL2); + + float D = D_beckmann_aniso(NH, XH, YH, a2, ax, ay); + + return NL * D * G * 0.25 / (NL * NV); +} + +/* This one returns the brdf already divided by the pdf */ +float bsdf_beckmann_aniso_pdf(float ax2, float ay2, float LX2, float LY2, float NH, float NV, float NL, float VH, float G1_V) +{ + float alphaL2 = (LX2 * ax2 + LY2 * ay2) / (LX2 + LY2); + float G = G1_V * G1_Smith_beckmann(NL, alphaL2); + + /* brdf = D * G / (4.0 * NL * NV) + * pdf = D * NH / (4 * VH) [D canceled later by D in brdf] */ + return G * VH / (NH * NV * NL); /* brdf / pdf */ +} + +float bsdf_ashikhmin_shirley_aniso(vec3 N, vec3 T, vec3 L, vec3 V, float roughness_x, float roughness_y) +{ + /* Ashikmin Shirley Spec Anisotropic */ + /* A few note about notations : + * I is the cycles term for Incoming Light, Noted L here (light vector) + * Omega (O) is the cycles term for the Outgoing Light, Noted V here (View vector) */ + N = normalize(N); + vec3 X = T, Y, Z = N; /* Inside cycles Z=Normal; X=Tangent; Y=Bitangent; */ + make_orthonormals_tangent(Z, X, Y); + vec3 H = normalize(L + V); + + float ax, ax2; prepare_glossy(roughness_x, ax, ax2); + float ay, ay2; prepare_glossy(roughness_y, ay, ay2); + float a2 = ax*ay; + float n_x = 2.0 / ax2 - 2.0; + float n_y = 2.0 / ay2 - 2.0; + + float NL = max(dot(N, L), 1e-6); + float NV = max(dot(N, V), 1e-6); + float NH = max(dot(N, H), 1e-6); + float VH = max(abs(dot(V, H)), 1e-6); + float XH2 = max(pow(dot(X, H), 2), 1e-6); + float YH2 = max(pow(dot(Y, H), 2), 1e-6); + + float pump = 1.0 / max(1e-6, VH * max(NL, NV)); + + float e = max(n_x * XH2 + n_y * YH2, 1e-4) / max(1.0 - NH*NH, 1e-4); /* Precision problem here */ + float lobe = pow(NH, e); + float norm = sqrt((n_x + 1.0)*(n_y + 1.0)) * 0.125 * M_1_PI; + + return NL * norm * lobe * pump; +} + +/* -------- Preview Lights --------- */ + +void node_bsdf_anisotropic_lights(vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T, vec3 V, vec4 ambient_light, out vec4 result) +{ + N = normalize(N); + shade_view(V, V); V = -V; + + float rough_x, rough_y; + prepare_aniso(N, roughness, rotation, T, anisotropy, rough_x, rough_y); + vec3 accumulator = ambient_light.rgb; + + if (max(rough_x, rough_y) <= 1e-4) { + result = vec4(accumulator * color.rgb, 1.0); //Should take roughness into account -> waiting LUT + return; + } + + /* directional lights */ + for(int i = 0; i < NUM_LIGHTS; i++) { + vec3 L = gl_LightSource[i].position.xyz; + vec3 light_color = gl_LightSource[i].specular.rgb; + + accumulator += light_color * bsdf_ggx_aniso(N, T, L, V, rough_x, rough_y); + } + + result = vec4(accumulator * color.rgb, 1.0); +} + + +/* -------- Physical Lights --------- */ + +/* ANISOTROPIC GGX */ + +void bsdf_anisotropic_ggx_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + + float rough_x, rough_y; + prepare_aniso(N, roughness, aniso_rotation, T, anisotropy, rough_x, rough_y); + + if (max(rough_x, rough_y) < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + float l_radius = l_areasizex; + + vec3 R = reflect(V, N); + float energy_conservation = 1.0; + most_representative_point(l_radius, 0.0, vec3(0.0), l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_ggx_aniso(N, T, L, V, rough_x, rough_y); + + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= sphere_energy(l_radius) * max(l_radius * l_radius, 1e-16); /* l_radius is already inside energy_conservation */ + bsdf *= M_PI; /* XXX : !!! Very Empirical, Fit cycles power */ +} + +void bsdf_anisotropic_ggx_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (max(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + + float rough_x, rough_y; + prepare_aniso(N, roughness, aniso_rotation, T, anisotropy, rough_x, rough_y); + + l_areasizex *= l_areascale.x; + l_areasizey *= l_areascale.y; + + /* Used later for Masking : Use the real Light Vector */ + vec3 lampz = normalize( (l_mat * vec4(0.0,0.0,1.0,0.0) ).xyz ); + float masking = max(dot( normalize(-L), lampz), 0.0); + + vec3 R = reflect(V, N); + + float energy_conservation = 1.0; + float max_size = max(l_areasizex, l_areasizey); + float min_size = min(l_areasizex, l_areasizey); + vec3 lampVec = (l_areasizex > l_areasizey) ? normalize( (l_mat * vec4(1.0,0.0,0.0,0.0) ).xyz ) : normalize( (l_mat * vec4(0.0,1.0,0.0,0.0) ).xyz ); + + most_representative_point(min_size/2, max_size-min_size, lampVec, l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_ggx_aniso(N, T, L, V, rough_x, rough_y); + + /* energy_conservation */ + float LineAngle = clamp( (max_size-min_size) / l_distance, 0.0, 1.0); + float energy_conservation_line = energy_conservation * ( roughness / clamp(roughness + 0.5 * LineAngle, 0.0, 1.1)); + + /* XXX : Empirical modification for low roughness matching */ + float energy_conservation_mod = energy_conservation * (1 + roughness) / ( max_size/min_size ); + energy_conservation = mix(energy_conservation_mod, energy_conservation_line, min(roughness/0.3, 0.9*(1.1-roughness)/0.1)); + + /* As we represent the Area Light by a tube light we must use a custom energy conservation */ + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= masking; + bsdf *= 23.2; /* XXX : !!! Very Empirical, Fit cycles power */ +} + +void bsdf_anisotropic_ggx_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float rough_x, rough_y; + prepare_aniso(N, roughness, aniso_rotation, T, anisotropy, rough_x, rough_y); + + /* Correct ligth shape but uniform intensity + * Does not take into account the division by costheta^3 */ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + vec3 R = reflect(V, N); + + float l_radius = l_areasizex; + float angle = atan(l_radius); + + float costheta = dot(-L, R); + float cosangle = cos(angle); + + float energy_conservation = 1.0; + most_representative_point_disk(l_radius, 1.0, R, L, roughness, energy_conservation); + + bsdf = bsdf_ggx_aniso(N, T, L, V, rough_x, rough_y); + bsdf *= energy_conservation; +} + +/* ANISOTROPIC BECKMANN */ + +void bsdf_anisotropic_beckmann_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + + float rough_x, rough_y; + prepare_aniso(N, roughness, aniso_rotation, T, anisotropy, rough_x, rough_y); + + if (max(rough_x, rough_y) < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + float l_radius = l_areasizex; + + vec3 R = reflect(V, N); + float energy_conservation = 1.0; + most_representative_point(l_radius, 0.0, vec3(0.0), l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_beckmann_aniso(N, T, L, V, rough_x, rough_y); + + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= sphere_energy(l_radius) * max(l_radius * l_radius, 1e-16); /* l_radius is already inside energy_conservation */ + bsdf *= M_PI; /* XXX : !!! Very Empirical, Fit cycles power */ +} + +void bsdf_anisotropic_beckmann_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (max(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + float rough_x, rough_y; + prepare_aniso(N, roughness, aniso_rotation, T, anisotropy, rough_x, rough_y); + + l_areasizex *= l_areascale.x; + l_areasizey *= l_areascale.y; + + /* Used later for Masking : Use the real Light Vector */ + vec3 lampz = normalize( (l_mat * vec4(0.0,0.0,1.0,0.0) ).xyz ); + float masking = max(dot( normalize(-L), lampz), 0.0); + + vec3 R = reflect(V, N); + + float energy_conservation = 1.0; + float max_size = max(l_areasizex, l_areasizey); + float min_size = min(l_areasizex, l_areasizey); + vec3 lampVec = (l_areasizex > l_areasizey) ? normalize( (l_mat * vec4(1.0,0.0,0.0,0.0) ).xyz ) : normalize( (l_mat * vec4(0.0,1.0,0.0,0.0) ).xyz ); + + most_representative_point(min_size/2, max_size-min_size, lampVec, l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_beckmann_aniso(N, T, L, V, rough_x, rough_y); + + /* energy_conservation */ + float LineAngle = clamp( (max_size-min_size) / l_distance, 0.0, 1.0); + float energy_conservation_line = energy_conservation * ( roughness / clamp(roughness + 0.5 * LineAngle, 0.0, 1.1)); + + /* XXX : Empirical modification for low roughness matching */ + float energy_conservation_mod = energy_conservation * (1 + roughness) / ( max_size/min_size ); + energy_conservation = mix(energy_conservation_mod, energy_conservation_line, min(roughness/0.3, 0.9*(1.1-roughness)/0.1)); + + /* As we represent the Area Light by a tube light we must use a custom energy conservation */ + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= masking; + bsdf *= 23.2; /* XXX : !!! Very Empirical, Fit cycles power */ +} + +void bsdf_anisotropic_beckmann_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float rough_x, rough_y; + prepare_aniso(N, roughness, aniso_rotation, T, anisotropy, rough_x, rough_y); + + /* Correct ligth shape but uniform intensity + * Does not take into account the division by costheta^3 */ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + vec3 R = reflect(V, N); + + float l_radius = l_areasizex; + float angle = atan(l_radius); + + float costheta = dot(-L, R); + float cosangle = cos(angle); + + float energy_conservation = 1.0; + most_representative_point_disk(l_radius, 1.0, R, L, roughness, energy_conservation); + + bsdf = bsdf_beckmann_aniso(N, T, L, V, rough_x, rough_y); + bsdf *= energy_conservation; +} + +/* ANISOTROPIC ASHIKHMIN SHIRLEY */ + +void bsdf_anisotropic_ashikhmin_shirley_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + + float rough_x, rough_y; + prepare_aniso(N, roughness, aniso_rotation, T, anisotropy, rough_x, rough_y); + + if (max(rough_x, rough_y) < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + float l_radius = l_areasizex; + + vec3 R = reflect(V, N); + float energy_conservation = 1.0; + most_representative_point(l_radius, 0.0, vec3(0.0), l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_ashikhmin_shirley_aniso(N, T, L, V, rough_x, rough_y); + + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= sphere_energy(l_radius) * max(l_radius * l_radius, 1e-16); /* l_radius is already inside energy_conservation */ + bsdf *= M_PI; /* XXX : !!! Very Empirical, Fit cycles power */ +} + +void bsdf_anisotropic_ashikhmin_shirley_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (max(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + float rough_x, rough_y; + prepare_aniso(N, roughness, aniso_rotation, T, anisotropy, rough_x, rough_y); + + l_areasizex *= l_areascale.x; + l_areasizey *= l_areascale.y; + + /* Used later for Masking : Use the real Light Vector */ + vec3 lampz = normalize( (l_mat * vec4(0.0,0.0,1.0,0.0) ).xyz ); + float masking = max(dot( normalize(-L), lampz), 0.0); + + vec3 R = reflect(V, N); + + float energy_conservation = 1.0; + float max_size = max(l_areasizex, l_areasizey); + float min_size = min(l_areasizex, l_areasizey); + vec3 lampVec = (l_areasizex > l_areasizey) ? normalize( (l_mat * vec4(1.0,0.0,0.0,0.0) ).xyz ) : normalize( (l_mat * vec4(0.0,1.0,0.0,0.0) ).xyz ); + + most_representative_point(min_size/2, max_size-min_size, lampVec, l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_ashikhmin_shirley_aniso(N, T, L, V, rough_x, rough_y); + + /* energy_conservation */ + float LineAngle = clamp( (max_size-min_size) / l_distance, 0.0, 1.0); + float energy_conservation_line = energy_conservation * ( roughness / clamp(roughness + 0.5 * LineAngle, 0.0, 1.1)); + + /* XXX : Empirical modification for low roughness matching */ + float energy_conservation_mod = energy_conservation * (1 + roughness) / ( max_size/min_size ); + energy_conservation = mix(energy_conservation_mod, energy_conservation_line, min(roughness/0.3, 0.9*(1.1-roughness)/0.1)); + + /* As we represent the Area Light by a tube light we must use a custom energy conservation */ + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= masking; + bsdf *= 23.2; /* XXX : !!! Very Empirical, Fit cycles power */ +} + +void bsdf_anisotropic_ashikhmin_shirley_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float rough_x, rough_y; + prepare_aniso(N, roughness, aniso_rotation, T, anisotropy, rough_x, rough_y); + + /* Correct ligth shape but uniform intensity + * Does not take into account the division by costheta^3 */ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + vec3 R = reflect(V, N); + + float l_radius = l_areasizex; + float angle = atan(l_radius); + + float costheta = dot(-L, R); + float cosangle = cos(angle); + + float energy_conservation = 1.0; + most_representative_point_disk(l_radius, 1.0, R, L, roughness, energy_conservation); + + bsdf = bsdf_ashikhmin_shirley_aniso(N, T, L, V, rough_x, rough_y); + bsdf *= energy_conservation; +} + +/* -------- Image Based Lighting --------- */ + +void env_sampling_aniso_ggx( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + float rough_x, rough_y; prepare_aniso(N, roughness, -aniso_rotation, T, anisotropy, rough_x, rough_y); + float ax, ax2; prepare_glossy(rough_x, ax, ax2); + float ay, ay2; prepare_glossy(rough_y, ay, ay2); + make_orthonormals_tangent(N, T, B); + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + + /* Precomputation */ + float max_a = min(1.0, max(ax, ay)); + float min_a = min(1.0, min(ax, ay)); + float a2 = ax*ay; + float NV = max(1e-8, abs(dot(I, N))); + float VX2 = pow(dot(I, T), 2); /* cosPhiO² */ + float VY2 = pow(dot(I, B), 2); /* sinPhiO² */ + float alphaV2 = (VX2 * ax2 + VY2 * ay2) / (VX2 + VY2); + float G1_V = G1_Smith_GGX(NV, alphaV2); + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_ggx_aniso(i, ax, ay, N, T, B); /* Microfacet normal */ + vec3 L = reflect(I, H); + float NL = dot(N, L); + + if (NL > 0.0) { + /* Step 1 : Sampling Environment */ + float NH = Ht.z; + float XH2 = Ht.x * Ht.x; + float YH2 = Ht.y * Ht.y; + + float pdf = pdf_ggx_aniso(NH, XH2, YH2, a2, ax, ay); + + vec4 sample = sample_reflect_pdf(L, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float VH = max(1e-8, -dot(I, H)); + float LX2 = pow(dot(L, T), 2); /* cosPhiI² */ + float LY2 = pow(dot(L, B), 2); /* sinPhiI² */ + float brdf_pdf = bsdf_ggx_aniso_pdf(ax2, ay2, LX2, LY2, NH, NV, NL, VH, G1_V); + + out_radiance += NL * sample * brdf_pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * specular_occlusion(NV, ao_factor, a2); +} + +void env_sampling_aniso_beckmann( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + float rough_x, rough_y; prepare_aniso(N, roughness, -aniso_rotation, T, anisotropy, rough_x, rough_y); + float ax, ax2; prepare_glossy(rough_x, ax, ax2); + float ay, ay2; prepare_glossy(rough_y, ay, ay2); + make_orthonormals_tangent(N, T, B); + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + + /* Precomputation */ + float a2 = ax*ay; + float NV = max(1e-8, abs(dot(I, N))); + float VX2 = pow(dot(I, T), 2); /* cosPhiO² */ + float VY2 = pow(dot(I, B), 2); /* sinPhiO² */ + float alphaV2 = (VX2 * ax2 + VY2 * ay2) / (VX2 + VY2); + float G1_V = G1_Smith_beckmann(NV, alphaV2); + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_beckmann_aniso(i, ax, ay, N, T, B); /* Microfacet normal */ + vec3 L = reflect(I, H); + float NL = dot(N, L); + + if (NL > 0.0) { + /* Step 1 : Sampling Environment */ + float NH = Ht.z; + float XH = Ht.x; + float YH = Ht.y; + + float pdf = pdf_beckmann_aniso(NH, XH, YH, a2, ax, ay); + + vec4 sample = sample_reflect_pdf(L, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float VH = max(1e-8, -dot(I, H)); + float LX2 = pow(dot(L, T), 2); /* cosPhiI² */ + float LY2 = pow(dot(L, B), 2); /* sinPhiI² */ + float brdf_pdf = bsdf_beckmann_aniso_pdf(ax2, ay2, LX2, LY2, NH, NV, NL, VH, G1_V); + + out_radiance += NL * sample * brdf_pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * specular_occlusion(NV, ao_factor, a2); +} + +void env_sampling_aniso_ashikhmin_shirley( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + float rough_x, rough_y; prepare_aniso(N, roughness, -aniso_rotation, T, anisotropy, rough_x, rough_y); + float ax, ax2; prepare_glossy(rough_x, ax, ax2); + float ay, ay2; prepare_glossy(rough_y, ay, ay2); + make_orthonormals_tangent(N, T, B); + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + + /* Precomputation */ + float a2 = ax*ay; + float NV = max(1e-8, abs(dot(I, N))); + float VX2 = pow(dot(I, T), 2); /* cosPhiO² */ + float VY2 = pow(dot(I, B), 2); /* sinPhiO² */ + + float n_x = 2.0 / ax2 - 2.0; + float n_y = 2.0 / ay2 - 2.0; + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_ashikhmin_shirley_aniso(i, n_x, n_y, N, T, B); /* Microfacet normal */ + float VH = dot(H, -I); + if (VH < 0.0) H = -H; + /* reflect I on H to get omega_in */ + vec3 L = I + (2.0 * VH) * H; + float NL = dot(N, L); + + if (NL > 0.0) { + /* Step 1 : Sampling Environment */ + float NH = Ht.z; + float XH2 = Ht.x * Ht.x; + float YH2 = Ht.y * Ht.y; + float VH = max(1e-8, -dot(I, H)); + + float pdf = pdf_ashikhmin_shirley_aniso(NH, VH, XH2, YH2, n_x, n_y); + + vec4 sample = sample_reflect_pdf(L, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_ashikhmin_shirley_pdf(NV, NL, VH); /* Same as isotropic */ + + out_radiance += NL * sample * brdf_pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * specular_occlusion(NV, ao_factor, a2); +}
\ No newline at end of file diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_diffuse.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_diffuse.glsl new file mode 100644 index 00000000000..a2d6b42a57c --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_diffuse.glsl @@ -0,0 +1,263 @@ +/* -------- Utils Functions --------- */ + +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( 1.0f - z*z ); /* sin theta */ + float x = r * Xi.y; + float y = r * Xi.z; + + Ht = vec3(x, y, z); /* Global variable */ + + return from_tangent_to_world(Ht, N, T, B); +} + +float pdf_hemisphere() +{ + return 0.5 * M_1_PI; +} + +/* Second order Spherical Harmonics */ +/* http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ */ +vec3 spherical_harmonics_L2(vec3 N) +{ + vec3 sh = vec3(0.0); + + sh += 0.282095 * unfsh0; + + sh += -0.488603 * N.z * unfsh1; + sh += 0.488603 * N.y * unfsh2; + sh += -0.488603 * N.x * unfsh3; + + sh += 1.092548 * N.x * N.z * unfsh4; + sh += -1.092548 * N.z * N.y * unfsh5; + sh += 0.315392 * (3.0 * N.y * N.y - 1.0) * unfsh6; + sh += -1.092548 * N.x * N.y * unfsh7; + sh += 0.546274 * (N.x * N.x - N.z * N.z) * unfsh8; + + return sh; +} + +/* -------- BSDF --------- */ + +float bsdf_lambert(float NL) +{ + return NL * M_1_PI; +} + +float bsdf_oren_nayar(float NL, float LV, float NV, float sigma) +{ + float div = 1.0 / (M_PI + ((3.0 * M_PI - 4.0) / 6.0) * sigma); + + float A = 1.0 * div; + float B = sigma * div; + + float s = LV - NL * NV; + float t = mix(1.0, max(NL, NV), step(0.0, s)); + return NL * (A + B * s / t); +} + +float bsdf_oren_nayar(vec3 N, vec3 L, vec3 V, float sigma) +{ + float NL = max(0.0, dot(N, L)); + float LV = max(0.0, dot(L, V)); + float NV = max(1e-8, dot(N, V)); + return bsdf_oren_nayar(NL, LV, NV, sigma); +} + + +/* -------- Preview Lights --------- */ + +void node_bsdf_diffuse_lights(vec4 color, float roughness, vec3 N, vec3 V, vec4 ambient_light, out vec4 result) +{ + shade_view(V, V); V = -V; + + /* ambient light */ + vec3 accumulator = ambient_light.rgb; + + /* oren_nayar approximation for ambient */ + float NV = clamp(dot(N, V), 0.0, 0.999); + float fac = 1.0 - pow(1.0 - NV, 1.3); + accumulator *= mix(1.0, 0.78, fac*roughness); + + /* directional lights */ + for(int i = 0; i < NUM_LIGHTS; i++) { + vec3 L = gl_LightSource[i].position.xyz; + vec3 light_color = gl_LightSource[i].diffuse.rgb; + + float NL = saturate(dot(N,L)); + float lambert = bsdf_lambert(NL); + float oren_nayar = bsdf_oren_nayar(N, L, V, roughness); + + accumulator += light_color * mix(lambert, oren_nayar, roughness) * M_PI; /* M_PI to make preview brighter */ + } + + result = vec4(accumulator*color.rgb, 1.0); +} + + +/* -------- Physical Lights --------- */ +/* from Sebastien Lagarde + * course_notes_moving_frostbite_to_pbr.pdf */ + +void bsdf_diffuse_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float l_radius = max(l_areasizex, 0.0001); + float costheta = clamp(dot(N, L), -0.999, 0.999); + float h = min(l_radius / l_distance , 0.9999); + float h2 = h*h; + + bsdf = 0.0; + if ( costheta * costheta > h2 ) { + bsdf = M_PI * h2 * clamp(costheta, 0.0, 1.0); + } + else { + float sintheta = sqrt(1.0 - costheta * costheta); + float x = sqrt(1.0 / h2 - 1.0); + float y = -x * ( costheta / sintheta ); + float sinthetasqrty = sintheta * sqrt(1.0 - y * y); + bsdf = (costheta * acos(y) - x * sinthetasqrty ) * h2 + atan(sinthetasqrty / x); + } + + /* Energy conservation + cycle matching */ + bsdf = max(bsdf, 0.0); + bsdf *= M_1_PI; + bsdf *= sphere_energy(l_radius); +} + +void bsdf_diffuse_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (min(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + vec3 pos = V; + V = -normalize(V); + N = -N; + + vec3 lampx, lampy, lampz; + vec2 halfsize = area_light_prepass(l_mat, l_areasizex, l_areasizey, l_areascale, lampx, lampy, lampz); + + vec3 points[4]; + area_light_points(l_coords, halfsize, lampx, lampy, points); + + bsdf = ltc_evaluate(N, V, pos, mat3(1), points); + bsdf *= step(0.0, -dot(L, lampz)); + + /* Energy conservation + cycle matching */ + bsdf *= M_1_2PI; + bsdf *= rectangle_energy(l_areasizex, l_areasizey); +} +float cot(float x){ return cos(x) / sin(x);} +float acot(float x){ return atan(1 / x);} +void bsdf_diffuse_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float l_radius = max(l_areasizex, 0.0001); + float costheta = clamp(dot(N, L), -0.999, 0.999); + float sintheta = sqrt(1.0 - costheta * costheta); + float h = 1 / l_radius; + float h2 = h * h; + + if (acos(costheta) < atan(h)) { + bsdf = M_PI * (1 / (1 + h2)) * costheta; + } + else { + float cottheta = costheta / sintheta; + float x = sqrt(1 - h2 * cottheta * cottheta); + bsdf = (-h * x + costheta * (M_PI - acos(h * cottheta))) / (1 + h2) + atan(x / h); + } + /* Energy conservation + cycle matching */ + float disk_energy = disk_energy(l_radius); + bsdf = max(bsdf, 0.0) * disk_energy; + /* TODO Refine this : + * We can try to add contribution of infinitely many point lights at the border of the disk if we know their intensity + * Border intensity should be added to the above uniform disk calculation and should be complementary */ + //bsdf += sqrt(1.0 - abs(costheta * costheta * costheta)) * saturate(M_1_2PI - disk_energy); + bsdf *= M_1_PI; + +} + + +/* -------- Image Based Lighting --------- */ + +void env_sampling_oren_nayar( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + + /* Precomputation */ + float NV = max(1e-8, abs(dot(I, N))); + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 L = sample_hemisphere(i, N, T, B); + vec3 H = normalize(L - I); + + float NL = max(0.0, dot(N, L)); + + if (NL != 0.0) { + /* Step 1 : Sampling Environment */ + float pdf = pdf_hemisphere(); + vec4 irradiance = sample_probe_pdf(L, pdf); + + /* Step 2 : Integrating BRDF*/ + float LV = max(0.0, dot(L, -I) ); + float brdf = bsdf_oren_nayar(NL, LV, NV, roughness); + + out_radiance += irradiance * brdf / pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y; +} + +void env_sampling_diffuse( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Lambert */ + vec3 lambert_diff = spherical_harmonics_L2(N); + + /* early out */ + if (roughness < 1e-5) { + result = lambert_diff * ao_factor; + return; + } + + /* Oren Nayar */ + vec3 oren_nayar_diff; + env_sampling_oren_nayar( + pbr, viewpos, invviewmat, viewmat, + N, T, roughness, ior, sigma, + toon_size, toon_smooth, anisotropy, aniso_rotation, + ao_factor, oren_nayar_diff); + + result = mix(lambert_diff, oren_nayar_diff, roughness); + + /* Apply ambient occlusion */ + result *= ao_factor; +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_glass.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_glass.glsl new file mode 100644 index 00000000000..7e51aeb5ff5 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_glass.glsl @@ -0,0 +1,345 @@ +/* -------- Utils Functions --------- */ + +float fresnel_blend(float transmit_bsdf, float reflect_bsdf, vec3 V, vec3 N, float ior) +{ + /* Fresnel Blend */ + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + float fresnel = fresnel_dielectric(V, N, eta); + + return mix(max(0.0, transmit_bsdf), reflect_bsdf, fresnel); +} + +vec3 fresnel_blend(vec3 transmit_bsdf, vec3 reflect_bsdf, vec3 V, vec3 N, float ior) +{ + /* Fresnel Blend */ + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + float fresnel = fresnel_dielectric(V, N, eta); + + return mix(transmit_bsdf, reflect_bsdf, fresnel); +} + + +/* -------- BSDF --------- */ + +/* -------- Preview Lights --------- */ + +void node_bsdf_glass_lights(vec4 color, float roughness, float ior, vec3 N, vec3 V, vec4 ambient_light, out vec4 result) +{ + node_bsdf_glossy_lights(color, roughness, N, V, ambient_light, result); +} + +/* -------- Physical Lights --------- */ + +/* GLASS GGX */ + +void bsdf_glass_ggx_sphere_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float transmit_bsdf, reflect_bsdf; + + bsdf_refract_ggx_sphere_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, transmit_bsdf); + bsdf_glossy_ggx_sphere_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, reflect_bsdf); + + bsdf = fresnel_blend(transmit_bsdf, reflect_bsdf, V, N, ior); +} + +void bsdf_glass_ggx_area_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float transmit_bsdf, reflect_bsdf; + + bsdf_refract_ggx_area_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, transmit_bsdf); + bsdf_glossy_ggx_area_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, reflect_bsdf); + + bsdf = fresnel_blend(transmit_bsdf, reflect_bsdf, V, N, ior); +} + +void bsdf_glass_ggx_sun_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float transmit_bsdf, reflect_bsdf; + + bsdf_refract_ggx_sun_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, transmit_bsdf); + bsdf_glossy_ggx_sun_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, reflect_bsdf); + + bsdf = fresnel_blend(transmit_bsdf, reflect_bsdf, V, N, ior); +} + +/* GLASS BECKMANN */ + +void bsdf_glass_beckmann_sphere_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float transmit_bsdf, reflect_bsdf; + + bsdf_refract_beckmann_sphere_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, transmit_bsdf); + bsdf_glossy_beckmann_sphere_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, reflect_bsdf); + + bsdf = fresnel_blend(transmit_bsdf, reflect_bsdf, V, N, ior); +} + +void bsdf_glass_beckmann_area_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float transmit_bsdf, reflect_bsdf; + + bsdf_refract_beckmann_area_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, transmit_bsdf); + bsdf_glossy_beckmann_area_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, reflect_bsdf); + + bsdf = fresnel_blend(transmit_bsdf, reflect_bsdf, V, N, ior); +} + +void bsdf_glass_beckmann_sun_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float transmit_bsdf, reflect_bsdf; + + bsdf_refract_beckmann_sun_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, transmit_bsdf); + bsdf_glossy_beckmann_sun_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, reflect_bsdf); + + bsdf = fresnel_blend(transmit_bsdf, reflect_bsdf, V, N, ior); +} + +/* GLASS SHARP */ + +void bsdf_glass_sharp_sphere_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float transmit_bsdf, reflect_bsdf; + + bsdf_refract_sharp_sphere_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, transmit_bsdf); + bsdf_glossy_sharp_sphere_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, reflect_bsdf); + + bsdf = fresnel_blend(transmit_bsdf, reflect_bsdf, V, N, ior); +} + +void bsdf_glass_sharp_area_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float transmit_bsdf, reflect_bsdf; + + bsdf_refract_sharp_area_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, transmit_bsdf); + bsdf_glossy_sharp_area_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, reflect_bsdf); + + bsdf = fresnel_blend(transmit_bsdf, reflect_bsdf, V, N, ior); +} + +void bsdf_glass_sharp_sun_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float transmit_bsdf, reflect_bsdf; + + bsdf_refract_sharp_sun_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, transmit_bsdf); + bsdf_glossy_sharp_sun_light(N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, roughness, ior, + sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, reflect_bsdf); + + bsdf = fresnel_blend(transmit_bsdf, reflect_bsdf, V, N, ior); +} + + +/* -------- Image Based Lighting --------- */ + +void env_sampling_glass_sharp( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + vector_prepass(viewpos, N, invviewmat, viewmat); + + /* reflection */ + vec3 R = reflect(I, N); + vec4 reflect_bsdf = sample_reflect(R); + + /* transmission */ + float eta = (gl_FrontFacing) ? 1.0/ior : ior; + vec3 Tr = refract(I, N, eta); + vec4 transmit_bsdf = sample_refract(Tr); + + result = fresnel_blend(transmit_bsdf.rgb, reflect_bsdf.rgb, I, N, ior) * specular_occlusion(dot(N,-I), ao_factor, 0.0); +} + +void env_sampling_glass_ggx( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + float a, a2; prepare_glossy(roughness, a, a2); + ior = max(ior, 1e-5); + + /* Precomputation */ + float NV = max(1e-8, abs(dot(I, N))); + float G1_V = G1_Smith_GGX(NV, a2); + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_ggx(i, a2, N, T, B); /* Microfacet normal */ + + /* TODO : For ior < 1.0 && roughness > 0.0 fresnel becomes not accurate.*/ + float fresnel = fresnel_dielectric(I, H, (dot(H, -I) < 0.0) ? 1.0/ior : ior ); + + /* reflection */ + vec3 R = reflect(I, H); + float NL = dot(N, R); + if (NL > 0.0) { + /* Step 1 : Sampling Environment */ + float NH = max(1e-8, dot(N, H)); /* cosTheta */ + float VH = max(1e-8, -dot(I, H)); + + float pdf = pdf_ggx_reflect(NH, a2); + + vec4 sample = sample_reflect_pdf(R, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_ggx_pdf(a2, NH, NL, VH, G1_V); + + /* See reflect glossy */ + out_radiance += NL * sample * brdf_pdf * fresnel; + } + + /* transmission */ + float eta = 1.0/ior; + if (dot(H, -I) < 0.0) { + H = -H; + eta = ior; + } + + vec3 Tr = refract(I, H, eta); + NL = -dot(N, Tr); + if (NL > 0.0 && fresnel != 1.0) { + /* Step 1 : Sampling Environment */ + float NH = dot(N, H); /* cosTheta */ + float VH = dot(-I, H); + float LH = dot(Tr, H); + float tmp = ior * VH + LH; + float Ht2 = tmp * tmp; + + float pdf = pdf_ggx_refract(Ht2, NH, NV, VH, LH, G1_V, a2, eta); + + vec4 sample = sample_refract_pdf(Tr, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_ggx_refract_pdf(a2, LH, NL, VH); + + out_radiance += sample * brdf_pdf * (1 - fresnel); + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * specular_occlusion(NV, ao_factor, a2); +} + +void env_sampling_glass_beckmann( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + float a, a2; prepare_glossy(roughness, a, a2); + ior = max(ior, 1e-5); + + /* Precomputation */ + float NV = max(1e-8, abs(dot(I, N))); + float G1_V = G1_Smith_GGX(NV, a2); + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_beckmann(i, a2, N, T, B); /* Microfacet normal */ + + /* TODO : For ior < 1.0 && roughness > 0.0 fresnel becomes not accurate.*/ + float fresnel = fresnel_dielectric(I, H, (dot(H, -I) < 0.0) ? 1.0/ior : ior ); + + /* reflection */ + vec3 R = reflect(I, H); + float NL = dot(N, R); + if (NL > 0.0) { + /* Step 1 : Sampling Environment */ + float NH = max(1e-8, dot(N, H)); /* cosTheta */ + float VH = max(1e-8, -dot(I, H)); + + float pdf = pdf_beckmann_reflect(NH, a2); + + vec4 sample = sample_reflect_pdf(R, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_beckmann_pdf(a2, NH, NV, NL, VH, G1_V); + + /* See reflect glossy */ + out_radiance += NL * sample * brdf_pdf * fresnel; + } + + /* transmission */ + float eta = 1.0/ior; + if (dot(H, -I) < 0.0) { + H = -H; + eta = ior; + } + + vec3 Tr = refract(I, H, eta); + NL = -dot(N, Tr); + if (NL > 0.0 && fresnel != 1.0) { + /* Step 1 : Sampling Environment */ + float NH = dot(N, H); /* cosTheta */ + float VH = dot(-I, H); + float LH = dot(Tr, H); + float tmp = ior * VH + LH; + float Ht2 = tmp * tmp; + + float pdf = pdf_beckmann_refract(Ht2, NH, NV, VH, LH, G1_V, a2, eta); + + vec4 sample = sample_refract_pdf(Tr, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_beckmann_refract_pdf(a2, LH, NL, VH); + + out_radiance += sample * brdf_pdf * (1 - fresnel); + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * specular_occlusion(NV, ao_factor, a2); +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_glossy.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_glossy.glsl new file mode 100644 index 00000000000..612f5a3fc13 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_glossy.glsl @@ -0,0 +1,710 @@ +/* -------- Utils Functions --------- */ + +vec3 sample_ggx(float nsample, float a2, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + + float z = sqrt( (1.0 - Xi.x) / ( 1.0 + a2 * Xi.x - Xi.x ) ); /* cos theta */ + float r = sqrt( 1.0 - z * z ); /* sin theta */ + float x = r * Xi.y; + float y = r * Xi.z; + + /* Global variable */ + Ht = vec3(x, y, z); + + return from_tangent_to_world(Ht, N, T, B); +} + +vec3 sample_beckmann(float nsample, float a2, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + + float z = sqrt( 1.0 / ( 1.0 - a2 * log(1.0 - Xi.x) ) ); /* cos theta */ + float r = sqrt( 1.0 - z * z ); /* sin theta */ + float x = r * Xi.y; + float y = r * Xi.z; + + /* Global variable */ + Ht = vec3(x, y, z); + + return from_tangent_to_world(Ht, N, T, B); +} + +vec3 sample_ashikhmin_shirley(float nsample, float n_x, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + + float z = pow( Xi.x, 1.0 / (n_x + 1.0) ); /* cos theta */ + float r = sqrt( 1.0 - z * z ); /* sin theta */ + float x = r * Xi.y; + float y = r * Xi.z; + + /* Global variable */ + Ht = vec3(x, y, z); + + return from_tangent_to_world(Ht, N, T, B); +} + +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 D_beckman(float NH, float a2) +{ + float NH2 = NH * NH; + return exp((NH2 - 1) / (NH2 * a2)) / (M_PI * a2 * NH2 * NH2); +} + +float pdf_ggx_reflect(float NH, float a2) +{ + return NH * a2 / D_ggx_opti(NH, a2); +} + +float pdf_beckmann_reflect(float NH, float a2) +{ + return NH * D_beckman(NH, a2); +} + +float pdf_ashikhmin_shirley_reflect(float NH, float VH, float n_x) +{ + float lobe = pow(NH, n_x); + float norm = (n_x + 1.0) * 0.125 * M_1_PI; + + return norm * lobe / VH; +} + +void prepare_glossy(float roughness, out float a, out float a2) +{ + /* Artifacts appear with roughness below this threshold */ + /* XXX TODO : find why flooring is necessary */ + a = clamp(roughness, 2e-4, 0.9999999); + a2 = max(1e-8, a*a); +} + +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 G1_Smith_beckmann(float NX, float a2) +{ + float tmp = 1 / (sqrt(a2 * (1 - NX * NX) / (NX * NX))); + return (tmp < 1.6) ? (3.535 * tmp + 2.181 * tmp * tmp) / (1 + 2.276 * tmp + 2.577 * tmp * tmp) : 1.0; +} + +/* -------- BSDF --------- */ + +float bsdf_ggx(vec3 N, vec3 L, vec3 V, float roughness) +{ + float a, a2; prepare_glossy(roughness, a, a2); + + 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 */ +} + +/* This one returns the brdf already divided by the pdf */ +float bsdf_ggx_pdf(float a2, float NH, float NL, float VH, float G1_V) +{ + float G = G1_V * G1_Smith_GGX(NL, a2); /* Doing RCP at the end */ + + /* Denominator is canceled by G1_Smith + * brdf = D * G / (4.0 * NL * NV) [denominator canceled by G] + * pdf = D * NH / (4 * VH) [D canceled later by D in brdf] */ + return 4.0 * VH / (NH * G); /* brdf / pdf */ +} + +float bsdf_beckmann(vec3 N, vec3 L, vec3 V, float roughness) +{ + float a, a2; prepare_glossy(roughness, a, a2); + + 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_beckmann(NV, a2) * G1_Smith_beckmann(NL, a2); + float D = D_beckman(NH, a2); + + return NL * D * G * 0.25 / (NL * NV); +} + +/* This one returns the brdf already divided by the pdf */ +float bsdf_beckmann_pdf(float a2, float NH, float NV, float NL, float VH, float G1_V) +{ + float G = G1_V * G1_Smith_beckmann(NL, a2); + + /* brdf = D * G / (4.0 * NL * NV) + * pdf = D * NH / (4 * VH) [D canceled later by D in brdf] */ + return G * VH / (NH * NV * NL); /* brdf / pdf */ +} + +float bsdf_ashikhmin_shirley(vec3 N, vec3 L, vec3 V, float roughness) +{ + float a, a2; prepare_glossy(roughness, a, a2); + + vec3 H = normalize(L + V); + float NL = max(dot(N, L), 1e-6); + float NV = max(dot(N, V), 1e-6); + float NH = max(dot(N, H), 1e-6); + float VH = max(abs(dot(V, H)), 1e-6); + + float pump = 1.0 / max(1e-6, VH * max(NL, NV)); + float n_x = 2.0 / a2 - 2.0; + float lobe = pow(NH, n_x); + float norm = (n_x + 1.0f) * 0.125 * M_1_PI; + + return NL * norm * lobe * pump; +} + +/* This one returns the brdf already divided by the pdf */ +float bsdf_ashikhmin_shirley_pdf(float NV, float NL, float VH) +{ + float pump = 1.0 / max(1e-6, VH * max(NL, NV)); + + return VH * pump; +} + +/* -------- Preview Lights --------- */ + +void node_bsdf_glossy_lights(vec4 color, float roughness, vec3 N, vec3 V, vec4 ambient_light, out vec4 result) +{ + vec3 accumulator = ambient_light.rgb; + + if (roughness <= 1e-4) { + result = vec4(accumulator * color.rgb, 1.0); + return; + } + + shade_view(V, V); V = -V; + N = normalize(N); + + /* directional lights */ + for(int i = 0; i < NUM_LIGHTS; i++) { + vec3 L = gl_LightSource[i].position.xyz; + vec3 light_color = gl_LightSource[i].specular.rgb; + + accumulator += light_color * bsdf_ggx(N, L, V, roughness); + } + + result = vec4(accumulator * color.rgb, 1.0); +} + +/* -------- Physical Lights --------- */ + +/* GLOSSY SHARP */ + +void bsdf_glossy_sharp_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float l_radius = l_areasizex; + L = l_distance * L; + vec3 R = -reflect(V, N); + + vec3 P = line_aligned_plane_intersect(vec3(0.0), R, L); + bsdf = (distance_squared(P, L) < l_radius * l_radius) ? 1.0 : 0.0; + + /* Energy conservation + cycle matching */ + bsdf *= sphere_energy(l_radius); +} + +void bsdf_glossy_sharp_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (max(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + L = l_distance * L; + + vec3 lampx, lampy, lampz; + vec2 halfsize = area_light_prepass(l_mat, l_areasizex, l_areasizey, l_areascale, lampx, lampy, lampz); + + /* Find the intersection point E between the reflection vector and the light plane */ + vec3 R = reflect(V, N); + vec3 E = line_plane_intersect(vec3(0.0), R, L, lampz); + + /* Project it onto the light plane */ + vec3 projection = E - L; + float A = dot(lampx, projection); + float B = dot(lampy, projection); + + bsdf = (abs(A) < halfsize.x && abs(B) < halfsize.y) ? 1.0 : 0.0; + + /* Masking */ + bsdf *= (dot(-L, lampz) > 0.0) ? 1.0 : 0.0; + bsdf *= (dot(R, lampz) > 0.0) ? 1.0 : 0.0; + + /* Energy conservation + cycle matching */ + bsdf *= rectangle_energy(l_areasizex, l_areasizey); +} + +void bsdf_glossy_sharp_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + vec3 R = reflect(V, N); + + float l_radius = l_areasizex; + float angle = atan(l_radius); + + float costheta = dot(-L, R); + float cosangle = cos(angle); + + bsdf = (costheta > cosangle) ? 1.0 : 0.0; + + /* Energy conservation + cycle matching */ + bsdf *= disk_energy(l_radius); + bsdf /= costheta * costheta * costheta; + bsdf *= M_PI; +} + +/* GLOSSY GGX */ + +void bsdf_glossy_ggx_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + +#if 1 + /* MRP is twice as fast as LTC, does not exhibit crucial artifacts and is better looking */ + float l_radius = l_areasizex; + + shade_view(V, V); + vec3 R = reflect(V, N); + + float energy_conservation = 1.0; + most_representative_point(l_radius, 0.0, vec3(0.0), l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_ggx(N, L, V, roughness); + + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= sphere_energy(l_radius) * max(l_radius * l_radius, 1e-16); /* l_radius is already inside energy_conservation */ + bsdf *= M_PI; +#else + /* LTC */ + float l_radius = max(0.007, l_areasizex); + + vec3 pos = V; + shade_view(V, V); + vec3 R = -reflect(V, N); + L = l_distance * L; + V = -V; + N = -N; + + vec3 P = line_aligned_plane_intersect(vec3(0.0), R, L); + vec3 Px = normalize(P - L) * l_radius; + vec3 Py = axis_angle_rotation(Px, R, M_PI_2); + + vec3 points[4]; + points[0] = l_coords + Px; + points[1] = l_coords - Py; + points[2] = l_coords - Px; + points[3] = l_coords + Py; + + float NV = max(dot(N, V), 1e-8); + vec2 uv = ltc_coords(NV, sqrt(roughness)); + mat3 ltcmat = ltc_matrix(uv); + + bsdf = ltc_evaluate(N, V, pos, ltcmat, points); + bsdf *= texture2D(unfltcmag, uv).r; /* Bsdf matching */ + + bsdf *= M_1_2PI; + bsdf *= sphere_energy(l_radius); +#endif +} + +void bsdf_glossy_ggx_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (min(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + vec3 pos = V; + shade_view(V, V); + V = -V; + N = -N; + + vec3 lampx, lampy, lampz; + vec2 halfsize = area_light_prepass(l_mat, l_areasizex, l_areasizey, l_areascale, lampx, lampy, lampz); + + vec3 points[4]; + area_light_points(l_coords, halfsize, lampx, lampy, points); + + float NV = max(dot(N, V), 1e-8); + vec2 uv = ltc_coords(NV, sqrt(roughness)); + mat3 ltcmat = ltc_matrix(uv); + + bsdf = ltc_evaluate(N, V, pos, ltcmat, points); + bsdf *= texture2D(unfltcmag, uv).r; /* Bsdf matching */ + + bsdf *= step(0.0, -dot(L, lampz)); + bsdf *= M_1_2PI; + bsdf *= rectangle_energy(l_areasizex, l_areasizey); +} + +void bsdf_glossy_ggx_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + /* Correct ligth shape but uniform intensity + * Does not take into account the division by costheta^3 */ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + vec3 R = reflect(V, N); + + float l_radius = l_areasizex; + float angle = atan(l_radius); + + float costheta = dot(-L, R); + float cosangle = cos(angle); + + float energy_conservation = 1.0; + most_representative_point_disk(l_radius, 1.0, R, L, roughness, energy_conservation); + + bsdf = bsdf_ggx(N, L, V, roughness); + bsdf *= energy_conservation; +} + +/* GLOSSY BECKMANN */ + +void bsdf_glossy_beckmann_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + /* MRP is twice as fast as LTC, does not exhibit crucial artifacts and is better looking */ + float l_radius = l_areasizex; + + shade_view(V, V); + vec3 R = reflect(V, N); + + float energy_conservation = 1.0; /* XXX TODO : Energy conservation is done for GGX */ + most_representative_point(l_radius, 0.0, vec3(0.0), l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_beckmann(N, L, V, roughness); + + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= sphere_energy(l_radius) * max(l_radius * l_radius, 1e-16); /* l_radius is already inside energy_conservation */ + bsdf *= M_PI; +} + +void bsdf_glossy_beckmann_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + /* TODO Make the other ltc luts */ + bsdf_glossy_ggx_area_light( N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, + l_mat, roughness, ior, sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, bsdf); +} + +void bsdf_glossy_beckmann_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + /* Correct ligth shape but uniform intensity + * Does not take into account the division by costheta^3 */ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + vec3 R = reflect(V, N); + + float l_radius = l_areasizex; + float angle = atan(l_radius); + + float costheta = dot(-L, R); + float cosangle = cos(angle); + + float energy_conservation = 1.0; + most_representative_point_disk(l_radius, 1.0, R, L, roughness, energy_conservation); + + bsdf = bsdf_beckmann(N, L, V, roughness); + bsdf *= energy_conservation; +} + +/* GLOSSY ASHIKhMIN SHIRLEY */ + +void bsdf_glossy_ashikhmin_shirley_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + /* MRP is twice as fast as LTC, does not exhibit crucial artifacts and is better looking */ + float l_radius = l_areasizex; + + shade_view(V, V); + vec3 R = reflect(V, N); + + float energy_conservation = 1.0; /* XXX TODO : Energy conservation is done for GGX */ + most_representative_point(l_radius, 0.0, vec3(0.0), l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_ashikhmin_shirley(N, L, V, roughness); + + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= sphere_energy(l_radius) * max(l_radius * l_radius, 1e-16); /* l_radius is already inside energy_conservation */ + bsdf *= M_PI; +} + +void bsdf_glossy_ashikhmin_shirley_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + /* TODO Make the other ltc luts */ + bsdf_glossy_ggx_area_light( N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, + l_mat, roughness, ior, sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, bsdf); +} + +void bsdf_glossy_ashikhmin_shirley_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + /* Correct ligth shape but uniform intensity + * Does not take into account the division by costheta^3 */ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + vec3 R = reflect(V, N); + + float l_radius = l_areasizex; + float angle = atan(l_radius); + + float costheta = dot(-L, R); + float cosangle = cos(angle); + + float energy_conservation = 1.0; + most_representative_point_disk(l_radius, 1.0, R, L, roughness, energy_conservation); + + bsdf = bsdf_ashikhmin_shirley(N, L, V, roughness); + bsdf *= energy_conservation; +} + +/* -------- Image Based Lighting --------- */ + +void env_sampling_glossy_sharp( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + + /* Precomputation */ + vec3 L = reflect(I, N); + vec3 vL = (viewmat * vec4(L, 0.0)).xyz; + + /* Probe */ + vec4 sample_probe = sample_reflect(L) * specular_occlusion(dot(N, -I), ao_factor, 0.0); + +#ifdef USE_SSR + /* SSR */ + vec2 hitpixel; vec3 hitco; float hitstep; + + bool hit = raycast(viewpos, vL, hitstep, hitpixel, hitco); + float contrib = ssr_contribution(viewpos, hitstep, hit, hitco); + + vec4 sample_ssr = bufferFetch(unfscenebuf, ivec2(hitpixel), 0); + srgb_to_linearrgb(sample_ssr, sample_ssr); + + result = mix(sample_probe.rgb, sample_ssr.rgb, contrib); + //result = mix(vec3(1.0,0.0,0.0), vec3(0.0,1.0,0.0), hit); + //result = sample_ssr.rgb * float(hit); + // result = hitco; +//result = vL.rgb; + //result = vec3(frontface_depth(ivec2(gl_FragCoord.xy), 0)); +#else + result = sample_probe.rgb; +#endif +} + +void env_sampling_glossy_ggx( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + float a, a2; prepare_glossy(roughness, a, a2); + + /* Precomputation */ + float NV = max(1e-8, abs(dot(I, N))); + float G1_V = G1_Smith_GGX(NV, a2); + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_ggx(i, a2, N, T, B); /* Microfacet normal */ + vec3 L = reflect(I, H); + float NL = dot(N, L); + + if (NL > 0.0) { + /* Step 1 : Sampling Environment */ + float NH = max(1e-8, dot(N, H)); /* cosTheta */ + float VH = max(1e-8, -dot(I, H)); + + float pdf = pdf_ggx_reflect(NH, a2); + + vec4 sample = sample_reflect_pdf(L, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_ggx_pdf(a2, NH, NL, VH, G1_V); + + out_radiance += NL * sample * brdf_pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * specular_occlusion(NV, ao_factor, a2); +} + +void env_sampling_glossy_beckmann( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + float a, a2; prepare_glossy(roughness, a, a2); + + /* Precomputation */ + float NV = max(1e-8, abs(dot(I, N))); + float G1_V = G1_Smith_beckmann(NV, a2); + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_beckmann(i, a2, N, T, B); /* Microfacet normal */ + vec3 L = reflect(I, H); + float NL = dot(N, L); + + if (NL > 0.0) { + /* Step 1 : Sampling Environment */ + float NH = max(1e-8, dot(N, H)); /* cosTheta */ + float VH = max(1e-8, -dot(I, H)); + + float pdf = pdf_beckmann_reflect(NH, a2); + + vec4 sample = sample_reflect_pdf(L, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_beckmann_pdf(a2, NH, NV, NL, VH, G1_V); + + out_radiance += NL * sample * brdf_pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * specular_occlusion(NV, ao_factor, a2); +} + +void env_sampling_glossy_ashikhmin_shirley( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + float a, a2; prepare_glossy(roughness, a, a2); + + /* Precomputation */ + float NV = max(1e-8, abs(dot(I, N))); + float n_x = 2.0 / a2 - 2.0; + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_ashikhmin_shirley(i, n_x, N, T, B); /* Microfacet normal */ + float VH = dot(H, -I); + if (VH < 0.0) H = -H; + /* reflect I on H to get omega_in */ + vec3 L = I + (2.0 * VH) * H; + float NL = dot(N, L); + + if (NL > 0.0) { + /* Step 1 : Sampling Environment */ + float NH = max(1e-8, dot(N, H)); /* cosTheta */ + VH = max(1e-8, abs(VH)); + NL = max(1e-8, NL); + + float pdf = pdf_ashikhmin_shirley_reflect(NH, VH, n_x); + + vec4 sample = sample_reflect_pdf(L, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_ashikhmin_shirley_pdf(NV, NL, VH); + + out_radiance += NL * sample * brdf_pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * specular_occlusion(NV, ao_factor, a2); +} + diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_refraction.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_refraction.glsl new file mode 100644 index 00000000000..aeecb56696a --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_refraction.glsl @@ -0,0 +1,490 @@ +/* -------- Utils Functions --------- */ + +float pdf_ggx_refract(float Ht2, float NH, float NV, float VH, float LH, float G1_V, float a2, float eta) +{ + return (VH * abs(LH)) * (eta*eta) * a2 * G1_V / (Ht2 * NV * D_ggx_opti(NH, a2)); +} + +float pdf_beckmann_refract(float Ht2, float NH, float NV, float VH, float LH, float G1_V, float a2, float eta) +{ + /* pdf = (VH * abs(LH)) * (ior*ior) * D * G(V) / (Ht2 * NV) */ + return (VH * abs(LH)) * (eta*eta) * D_beckman(NH, a2) * G1_V / (Ht2 * NV); +} + +/* -------- BSDF --------- */ + +float bsdf_ggx_refract(float Ht2, float NH, float NL, float NV, float VH, float LH, float a2, float eta) +{ + float G = G1_Smith_GGX(NV, a2) * G1_Smith_GGX(NL, a2); + float D = D_ggx_opti(NH, a2); /* Doing RCP and mul a2 at the end */ + + /* bsdf = abs(LH * VH) * (eta*eta) * G * D / (NV * Ht2); /* Reference function */ + return abs(LH * VH) * (NV * NL * 4.0) * a2 * (eta*eta) / (D * G * NV * Ht2); /* Balancing the adjustments made in G1_Smith with (NV * NL * 4.0)*/ +} + +float bsdf_ggx_refract(vec3 N, vec3 L, vec3 V, float eta, float roughness) +{ + /* GGX Spec Isotropic Transmited */ + float a, a2; prepare_glossy(roughness, a, a2); + + vec3 ht = -(eta * L + V); + vec3 Ht = normalize(ht); + float Ht2 = dot(ht, ht); + float NH = dot(N, Ht); + float NL = dot(N, -L); + float NV = dot(N, V); + float VH = dot(V, Ht); + float LH = dot(-L, Ht); + + return bsdf_ggx_refract(Ht2, NH, NL, NV, VH, LH, a2, eta); +} + +/* This one returns the brdf already divided by the pdf */ +float bsdf_ggx_refract_pdf(float a2, float LH, float NL, float VH) +{ + float G1_L = NL * 2.0 / G1_Smith_GGX(NL, a2); /* Balancing the adjustments made in G1_Smith */ + + /* brdf = abs(VH*LH) * (ior*ior) * D * G(V) * G(L) / (Ht2 * NV) + * pdf = (VH * abs(LH)) * (ior*ior) * D * G(V) / (Ht2 * NV) */ + return G1_L * abs(VH*LH) / (VH * abs(LH)); +} + +float bsdf_beckmann_refract(float Ht2, float NH, float NL, float NV, float VH, float LH, float a, float a2, float eta) +{ + float G = G1_Smith_beckmann(NV, a2) * G1_Smith_beckmann(NL, a2); + float D = D_beckman(NH, a2); + + return abs(LH * VH) * D * G * (eta*eta) / (NV * Ht2); +} + +float bsdf_beckmann_refract(vec3 N, vec3 L, vec3 V, float eta, float roughness) +{ + float a, a2; prepare_glossy(roughness, a, a2); + + vec3 ht = -(eta * L + V); + vec3 Ht = normalize(ht); + float Ht2 = dot(ht, ht); + float NH = dot(N, Ht); + float NL = dot(N, -L); + float NV = dot(N, V); + float VH = dot(V, Ht); + float LH = dot(-L, Ht); + + return bsdf_beckmann_refract(Ht2, NH, NL, NV, VH, LH, a, a2, eta); +} + +/* This one returns the brdf already divided by the pdf */ +float bsdf_beckmann_refract_pdf(float a2, float LH, float NL, float VH) +{ + /* brdf = abs(VH*LH) * (ior*ior) * D * G(V) * G(L) / (Ht2 * NV) + * pdf = (VH * abs(LH)) * (ior*ior) * D * G(V) / (Ht2 * NV) */ + return G1_Smith_beckmann(NL, a2) * abs(VH*LH) / (VH * abs(LH)); +} + +/* -------- Preview Lights --------- */ + +void node_bsdf_refraction_lights(vec4 color, float roughness, float ior, vec3 N, vec3 V, vec4 ambient_light, out vec4 result) +{ + node_bsdf_glossy_lights(color, roughness, N, V, ambient_light, result); +} + +/* -------- Physical Lights --------- */ + +/* REFRACT SHARP */ + +void bsdf_refract_sharp_sphere_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float l_radius = l_areasizex; + L = l_distance * L; + vec3 R = -refract(-V, N, (gl_FrontFacing) ? 1.0/ior : ior); + + vec3 P = line_aligned_plane_intersect(vec3(0.0), R, L); + bsdf = (distance_squared(P, L) < l_radius * l_radius) ? 1.0 : 0.0; + + /* Energy conservation + cycle matching */ + bsdf *= sphere_energy(l_radius); +} + +void bsdf_refract_sharp_area_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (max(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + L = l_distance * L; + + vec3 lampx, lampy, lampz; + vec2 halfsize = area_light_prepass(l_mat, l_areasizex, l_areasizey, l_areascale, lampx, lampy, lampz); + + /* Find the intersection point E between the reflection vector and the light plane */ + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + vec3 R = refract(-V, N, 1.0/eta); + vec3 E = line_plane_intersect(vec3(0.0), R, L, lampz); + + /* Project it onto the light plane */ + vec3 projection = E - L; + float A = dot(lampx, projection); + float B = dot(lampy, projection); + + bsdf = (abs(A) < halfsize.x && abs(B) < halfsize.y) ? 1.0 : 0.0; + + /* Masking */ + bsdf *= (dot(-L, lampz) > 0.0) ? 1.0 : 0.0; + bsdf *= (dot(-R, lampz) > 0.0) ? 1.0 : 0.0; + + /* Energy conservation + cycle matching */ + bsdf *= rectangle_energy(l_areasizex, l_areasizey); +} + +void bsdf_refract_sharp_sun_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + vec3 R = refract(-V, N, 1.0/eta); + + float l_radius = l_areasizex; + float angle = atan(l_radius); + + float costheta = dot(L, R); + float cosangle = cos(angle); + + bsdf = (costheta > cosangle) ? 1.0 : 0.0; + + /* Energy conservation + cycle matching */ + bsdf *= disk_energy(l_radius); + bsdf /= costheta * costheta * costheta; + bsdf *= M_PI; +} + +/* REFRACT GGX */ + +void bsdf_refract_ggx_sphere_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + float l_radius = l_areasizex; + + shade_view(V, V); + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + vec3 R = refract(-V, N, 1.0/eta); + + float energy_conservation = 1.0; + most_representative_point(l_radius, 0.0, vec3(0.0), l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_ggx_refract(N, L, V, eta, roughness); + + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= sphere_energy(l_radius) * max(l_radius * l_radius, 1e-16); /* l_radius is already inside energy_conservation */ + bsdf *= M_PI; /* XXX : !!! Very Empirical, Fit cycles power */ +} + +void bsdf_refract_ggx_area_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (min(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + l_areasizex *= l_areascale.x; + l_areasizey *= l_areascale.y; + + /* Used later for Masking : Use the real Light Vector */ + vec3 lampz = normalize( (l_mat * vec4(0.0,0.0,1.0,0.0) ).xyz ); //lamp projection axis + float masking = max(dot( normalize(-L), lampz), 0.0); + + float max_size = max(l_areasizex, l_areasizey); + float min_size = min(l_areasizex, l_areasizey); + vec3 lampVec = (l_areasizex > l_areasizey) ? normalize( (l_mat * vec4(1.0,0.0,0.0,0.0) ).xyz ) : normalize( (l_mat * vec4(0.0,1.0,0.0,0.0) ).xyz ); + + + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + vec3 R = refract(-V, N, 1.0/eta); + float energy_conservation = 1.0; + most_representative_point(min_size/2, max_size-min_size, lampVec, l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_ggx_refract(N, L, V, eta, roughness); + + /* energy_conservation */ + float LineAngle = clamp( (max_size-min_size) / l_distance, 0.0, 1.0); + float energy_conservation_line = energy_conservation * ( roughness / clamp(roughness + 0.5 * LineAngle, 0.0, 1.1)); + + /* XXX : Empirical modification for low roughness matching */ + float energy_conservation_mod = energy_conservation * (1 + roughness) / ( max_size/min_size ); + energy_conservation = mix(energy_conservation_mod, energy_conservation_line, min(roughness/0.3, 0.9*(1.1-roughness)/0.1)); + + /* As we represent the Area Light by a tube light we must use a custom energy conservation */ + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= masking; + bsdf *= 23.2; /* XXX : !!! Very Empirical, Fit cycles power */ +} + +void bsdf_refract_ggx_sun_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + /* Correct ligth shape but uniform intensity + * Does not take into account the division by costheta^3 */ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + vec3 R = refract(-V, N, 1.0/eta); + + float l_radius = l_areasizex; + + float energy_conservation = 1.0; + most_representative_point_disk(l_radius, 1.0, R, L, roughness, energy_conservation); + + bsdf = bsdf_ggx_refract(N, L, V, eta, roughness); + bsdf *= energy_conservation; +} + +/* REFRACT BECKMANN */ + +void bsdf_refract_beckmann_sphere_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + float l_radius = l_areasizex; + + shade_view(V, V); + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + vec3 R = refract(-V, N, 1.0/eta); + + float energy_conservation = 1.0; + most_representative_point(l_radius, 0.0, vec3(0.0), l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_beckmann_refract(N, L, V, eta, roughness); + + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= sphere_energy(l_radius) * max(l_radius * l_radius, 1e-16); /* l_radius is already inside energy_conservation */ + bsdf *= M_PI; /* XXX : !!! Very Empirical, Fit cycles power */ + bsdf *= step(0.0, dot(-L, N)); +} + +void bsdf_refract_beckmann_area_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (min(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + l_areasizex *= l_areascale.x; + l_areasizey *= l_areascale.y; + + /* Used later for Masking : Use the real Light Vector */ + vec3 lampz = normalize( (l_mat * vec4(0.0,0.0,1.0,0.0) ).xyz ); //lamp projection axis + float masking = max(dot( normalize(-L), lampz), 0.0); + + float max_size = max(l_areasizex, l_areasizey); + float min_size = min(l_areasizex, l_areasizey); + vec3 lampVec = (l_areasizex > l_areasizey) ? normalize( (l_mat * vec4(1.0,0.0,0.0,0.0) ).xyz ) : normalize( (l_mat * vec4(0.0,1.0,0.0,0.0) ).xyz ); + + + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + vec3 R = refract(-V, N, 1.0/eta); + float energy_conservation = 1.0; + most_representative_point(min_size/2, max_size-min_size, lampVec, l_distance, R, L, roughness, energy_conservation); + bsdf = bsdf_beckmann_refract(N, L, V, eta, roughness); + + /* energy_conservation */ + float LineAngle = clamp( (max_size-min_size) / l_distance, 0.0, 1.0); + float energy_conservation_line = energy_conservation * ( roughness / clamp(roughness + 0.5 * LineAngle, 0.0, 1.1)); + + /* XXX : Empirical modification for low roughness matching */ + float energy_conservation_mod = energy_conservation * (1 + roughness) / ( max_size/min_size ); + energy_conservation = mix(energy_conservation_mod, energy_conservation_line, min(roughness/0.3, 0.9*(1.1-roughness)/0.1)); + + /* As we represent the Area Light by a tube light we must use a custom energy conservation */ + bsdf *= energy_conservation / (l_distance * l_distance); + bsdf *= masking; + bsdf *= step(0.0, dot( normalize(-L), N)); + bsdf *= 23.2; /* XXX : !!! Very Empirical, Fit cycles power */ +} + +void bsdf_refract_beckmann_sun_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + /* Correct ligth shape but uniform intensity + * Does not take into account the division by costheta^3 */ + if (roughness < 1e-4 && l_areasizex == 0) { + bsdf = 0.0; + return; + } + + float eta = (gl_FrontFacing) ? ior : 1.0/ior; + vec3 R = refract(-V, N, 1.0/eta); + + float l_radius = l_areasizex; + + float energy_conservation = 1.0; + most_representative_point_disk(l_radius, 1.0, R, L, roughness, energy_conservation); + + bsdf = bsdf_beckmann_refract(N, L, V, eta, roughness); + bsdf *= energy_conservation; + bsdf *= step(0.0, dot(-L, N)); +} + +/* -------- Image Based Lighting --------- */ + +void env_sampling_refract_sharp( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + float eta = (gl_FrontFacing) ? 1.0/ior : ior; + + vec3 L = refract(I, N, eta); + + result = sample_refract(L).rgb; +} + +void env_sampling_refract_ggx( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + float a, a2; prepare_glossy(roughness, a, a2); + ior = max(ior, 1e-5); + + /* Precomputation */ + float NV = max(1e-8, abs(dot(I, N))); + float G1_V = G1_Smith_GGX(NV, a2); + + /* Early out */ + if (abs(ior - 1.0) < 1e-4) { + result = sample_transparent(); + return; + } + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_ggx(i, a2, N, T, B); /* Microfacet normal */ + float eta = 1.0/ior; + float fresnel = fresnel_dielectric(I, H, ior); + + if (dot(H, -I) < 0.0) { + H = -H; + eta = ior; + } + + vec3 L = refract(I, H, eta); + float NL = -dot(N, L); + if (NL > 0.0 && fresnel != 1.0) { + /* Step 1 : Sampling Environment */ + float NH = dot(N, H); /* cosTheta */ + float VH = dot(-I, H); + float LH = dot(L, H); + float tmp = ior * VH + LH; + float Ht2 = tmp * tmp; + + float pdf = pdf_ggx_refract(Ht2, NH, NV, VH, LH, G1_V, a2, eta); + + vec4 sample = sample_refract_pdf(L, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_ggx_refract_pdf(a2, LH, NL, VH); + + out_radiance += sample * brdf_pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y; +} + +void env_sampling_refract_beckmann( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + float a, a2; prepare_glossy(roughness, a, a2); + ior = max(ior, 1e-5); + + /* Precomputation */ + float NV = max(1e-8, abs(dot(I, N))); + float G1_V = G1_Smith_GGX(NV, a2); + + /* Early out */ + if (abs(ior - 1.0) < 1e-4) { + result = sample_transparent(); + return; + } + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 H = sample_beckmann(i, a2, N, T, B); /* Microfacet normal */ + float eta = 1.0/ior; + float fresnel = fresnel_dielectric(I, H, ior); + + if (dot(H, -I) < 0.0) { + H = -H; + eta = ior; + } + + vec3 L = refract(I, H, eta); + float NL = -dot(N, L); + if (NL > 0.0 && fresnel != 1.0) { + /* Step 1 : Sampling Environment */ + float NH = dot(N, H); /* cosTheta */ + float VH = dot(-I, H); + float LH = dot(L, H); + float tmp = ior * VH + LH; + float Ht2 = tmp * tmp; + + float pdf = pdf_beckmann_refract(Ht2, NH, NV, VH, LH, G1_V, a2, eta); + + vec4 sample = sample_refract_pdf(L, roughness, pdf); + + /* Step 2 : Integrating BRDF */ + float brdf_pdf = bsdf_beckmann_refract_pdf(a2, LH, NL, VH); + + out_radiance += sample * brdf_pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y; +}
\ No newline at end of file diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_toon.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_toon.glsl new file mode 100644 index 00000000000..7976429b3a4 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_toon.glsl @@ -0,0 +1,273 @@ +/* -------- Utils Functions --------- */ + +vec3 sample_uniform_cone(float nsample, float angle, vec3 N, vec3 T, vec3 B) +{ + vec3 Xi = hammersley_3d(nsample); + + float z = cos(angle * Xi.x); + float r = sqrt(1.0 - z*z); + float x = r * Xi.y; + float y = r * Xi.z; + + Ht = vec3(x, y, z); /* Global variable */ + + return from_tangent_to_world(Ht, N, T, B); +} + +float pdf_uniform_cone(float angle) +{ + return 0.5 * M_1_PI / (1.0 - cos(angle)); +} + +void prepare_toon(inout float tsize, inout float tsmooth, out float sample_angle) +{ + tsize = saturate(tsize) * M_PI_2; + tsmooth = saturate(tsmooth) * M_PI_2; + sample_angle = min(tsize + tsmooth, M_PI_2); +} + +float bsdf_toon_get_intensity(float max_angle, float tsmooth, float angle) +{ + if(angle < max_angle) + return 1.0; + else if(angle < (max_angle + tsmooth) && tsmooth != 0.0) + return (1.0 - (angle - max_angle)/tsmooth); + else + return 0.0; +} + +/* -------- BSDF --------- */ + +float bsdf_toon(float cosangle, float pdf, float max_angle, float tsmooth) +{ + float angle = acos(min(0.9999999, cosangle)); + float eval = bsdf_toon_get_intensity(max_angle, tsmooth, angle); + return pdf * eval; +} + +float bsdf_toon_diffuse(vec3 N, vec3 L, float sample_angle, float max_angle, float tsmooth) +{ + float NL = max(0.0, dot(N, L)); + + if(NL > 0.0) { + float pdf = pdf_uniform_cone(sample_angle); + return bsdf_toon(NL, pdf, max_angle, tsmooth); + } + + return 0.0; +} + +float bsdf_toon_glossy(vec3 N, vec3 L, vec3 V, float sample_angle, float max_angle, float tsmooth) +{ + float NL = max(0.0, dot(N, L)); + float NV = max(0.0, dot(N, V)); + + if(NV > 0.0 && NL > 0.0) { + vec3 R = -reflect(V, N); + float RL = max(0.0, dot(R, L)); + float pdf = pdf_uniform_cone(sample_angle); + return bsdf_toon(RL, pdf, max_angle, tsmooth); + } + + return 0.0; +} + + +/* -------- Preview Lights --------- */ + +void node_bsdf_toon_diffuse_lights(vec4 color, float size, float tsmooth, vec3 N, vec3 V, vec4 ambient_light, out vec4 result) +{ + shade_view(V, V); V = -V; + N = normalize(N); + float sample_angle; prepare_toon(size, tsmooth, sample_angle); + + /* ambient light */ + vec3 accumulator = ambient_light.rgb; + + /* directional lights */ + for(int i = 0; i < NUM_LIGHTS; i++) { + vec3 L = gl_LightSource[i].position.xyz; + vec3 light_color = gl_LightSource[i].diffuse.rgb; + + accumulator += light_color * bsdf_toon_diffuse(N, L, sample_angle, size, tsmooth) * M_PI; /* M_PI to make preview brighter */ + } + + result = vec4(accumulator*color.rgb, 1.0); +} + +void node_bsdf_toon_glossy_lights(vec4 color, float size, float tsmooth, vec3 N, vec3 V, vec4 ambient_light, out vec4 result) +{ + shade_view(V, V); V = -V; + N = normalize(N); + float sample_angle; prepare_toon(size, tsmooth, sample_angle); + + /* ambient light */ + vec3 accumulator = ambient_light.rgb; + + /* directional lights */ + for(int i = 0; i < NUM_LIGHTS; i++) { + vec3 L = gl_LightSource[i].position.xyz; + vec3 light_color = gl_LightSource[i].specular.rgb; + + accumulator += light_color * bsdf_toon_glossy(N, L, V, sample_angle, size, tsmooth) * M_PI; /* M_PI to make preview brighter */ + } + + result = vec4(accumulator*color.rgb, 1.0); +} + + +/* -------- Physical Lights --------- */ + +/* TOON DIFFUSE */ + +void bsdf_toon_diffuse_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float sample_angle; prepare_toon(toon_size, toon_smooth, sample_angle); + bsdf = bsdf_toon_diffuse(N, L, sample_angle, toon_size, toon_smooth); + + /* Energy conservation + cycle matching */ + bsdf *= 8.0 / (l_distance * l_distance); +} + +void bsdf_toon_diffuse_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float sample_angle; prepare_toon(toon_size, toon_smooth, sample_angle); + bsdf = bsdf_toon_diffuse(N, L, sample_angle, toon_size, toon_smooth); + + /* Energy conservation + cycle matching */ + bsdf *= 8.0 / (l_distance * l_distance); +} + +void bsdf_toon_diffuse_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float sample_angle; prepare_toon(toon_size, toon_smooth, sample_angle); + bsdf = bsdf_toon_diffuse(N, L, sample_angle, toon_size, toon_smooth); +} + +/* TOON GLOSSY */ + +void bsdf_toon_glossy_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float sample_angle; prepare_toon(toon_size, toon_smooth, sample_angle); + bsdf = bsdf_toon_glossy(N, L, V, sample_angle, toon_size, toon_smooth); +} + +void bsdf_toon_glossy_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float sample_angle; prepare_toon(toon_size, toon_smooth, sample_angle); + bsdf = bsdf_toon_glossy(N, L, V, sample_angle, toon_size, toon_smooth); + + /* Energy conservation + cycle matching */ + bsdf *= 8.0 / (l_distance * l_distance); +} + +void bsdf_toon_glossy_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float sample_angle; prepare_toon(toon_size, toon_smooth, sample_angle); + bsdf = bsdf_toon_glossy(N, L, V, sample_angle, toon_size, toon_smooth); +} + + +/* -------- Image Based Lighting --------- */ + +void env_sampling_toon_diffuse( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + float sample_angle; prepare_toon(toon_size, toon_smooth, sample_angle); + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + + /* Precomputation */ + float NV = max(0.0, dot(I, N)); + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 L = sample_uniform_cone(i, sample_angle, N, T, B); + float NL = dot(N, L); + + if (NL > 0.0) { + /* Step 1 : Sampling Environment */ + float pdf = pdf_uniform_cone(sample_angle); + vec4 irradiance = sample_probe_pdf(L, pdf); + + /* Step 2 : Integrating BRDF*/ + float brdf = bsdf_toon(NL, pdf, toon_size, toon_smooth); + + out_radiance += irradiance * brdf / pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * ao_factor; +} + +void env_sampling_toon_glossy( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + /* Setup */ + vector_prepass(viewpos, N, invviewmat, viewmat); + float sample_angle; prepare_toon(toon_size, toon_smooth, sample_angle); + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + + /* Precomputation */ + float NV = max(1e-8, dot(I, N)); + vec3 R = reflect(I, N); + + /* We are sampling aroung R so generate basis with it */ + make_orthonormals(R, T, B); /* Generate tangent space */ + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 L = sample_uniform_cone(i, sample_angle, R, T, B); + + float NL = dot(N, L); + + if (NL > 0.0) { + float RL = max(0.0, dot(R, L)); + + /* Step 1 : Sampling Environment */ + float pdf = pdf_uniform_cone(sample_angle); + vec4 irradiance = sample_reflect_pdf(L, 0.0, pdf); + + /* Step 2 : Integrating BRDF*/ + float brdf = bsdf_toon(RL, pdf, toon_size, toon_smooth); + + out_radiance += irradiance * brdf / pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * specular_occlusion(NV, ao_factor, roughness); +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_translucent.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_translucent.glsl new file mode 100644 index 00000000000..4cec442da9a --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_translucent.glsl @@ -0,0 +1,55 @@ +/* -------- Utils Functions --------- */ + +/* -------- BSDF --------- */ + +/* -------- Preview Lights --------- */ + +void node_bsdf_translucent_lights(vec4 color, vec3 N, vec3 V, vec4 ambient_light, out vec4 result) +{ + node_bsdf_diffuse_lights(color, 0.0, -N, V, ambient_light, result); +} + + +/* -------- Physical Lights --------- */ + +void bsdf_translucent_sphere_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + bsdf_diffuse_sphere_light(-N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, 0.0, ior, sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, bsdf); +} + +void bsdf_translucent_area_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + bsdf_diffuse_area_light(-N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, 0.0, ior, sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, bsdf); +} + +void bsdf_translucent_sun_light( + vec3 N, vec3 T, vec3 L, vec3 V, + vec3 l_coords, float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + bsdf_diffuse_sun_light(-N, T, L, V, l_coords, l_distance, l_areasizex, l_areasizey, l_areascale, l_mat, 0.0, ior, sigma, toon_size, toon_smooth, anisotropy, aniso_rotation, bsdf); +} + +/* -------- Image Based Lighting --------- */ + +void env_sampling_translucent( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + env_sampling_diffuse( + pbr, viewpos, invviewmat, viewmat, + -N, T, 0.0, ior, sigma, + toon_size, toon_smooth, anisotropy, aniso_rotation, + ao_factor, result); +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_transparent.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_transparent.glsl new file mode 100644 index 00000000000..a4f1725bbf7 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_transparent.glsl @@ -0,0 +1,30 @@ +/* -------- Utils Functions --------- */ + +vec3 sample_transparent() +{ +#ifndef PLANAR_PROBE + vec4 sample = textureCube(unfprobe, I); +#else + vec4 sample = texture2D(unfrefract, refpos.xy); +#endif + srgb_to_linearrgb(sample, sample); + return sample.rgb; +} + +/* -------- BSDF --------- */ + +/* -------- Preview Lights --------- */ + +/* -------- Physical Lights --------- */ + +/* -------- Image Based Lighting --------- */ + +void env_sampling_transparent( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + vector_prepass(viewpos, N, invviewmat, viewmat); + result = sample_transparent(); +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_velvet.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_velvet.glsl new file mode 100644 index 00000000000..553627edead --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_velvet.glsl @@ -0,0 +1,156 @@ +/* -------- Utils Functions --------- */ + +void prepare_velvet(float sigma, out float m_1_sig2) +{ + sigma = max(sigma, 1e-2); + m_1_sig2 = 1 / (sigma * sigma); +} + +/* -------- BSDF --------- */ + +float bsdf_ashikhmin_velvet(float NL, float NV, float NH, float VH, float m_1_sig2) +{ + float NHdivVH = NH / VH; + NHdivVH = max(NHdivVH, 1e-5); + + float fac1 = 2 * abs(NHdivVH * NV); + float fac2 = 2 * abs(NHdivVH * NL); + + float sinNH2 = 1 - NH * NH; + float sinNH4 = sinNH2 * sinNH2; + float cotan2 = (NH * NH) / sinNH2; + + float D = exp(-cotan2 * m_1_sig2) * m_1_sig2 * M_1_PI / sinNH4; + float G = min(1.0, min(fac1, fac2)); // TODO: derive G from D analytically + + return 0.25 * (D * G) / NV; +} + +float bsdf_ashikhmin_velvet(vec3 N, vec3 L, vec3 V, float m_1_sig2) +{ + vec3 H = normalize(L + V); + + float NL = max(dot(N, L), 0.0); + float NV = max(dot(N, V), 1e-5); + float NH = dot(N, H); + float VH = max(abs(dot(V, H)), 1e-5); + + if(abs(NH) < 1.0-1e-5) { + return bsdf_ashikhmin_velvet(NL, NV, NH, VH, m_1_sig2); + } + + return 0.0; +} + +/* -------- Preview Lights --------- */ + +void node_bsdf_velvet_lights(vec4 color, float sigma, vec3 N, vec3 V, vec4 ambient_light, out vec4 result) +{ + shade_view(V, V); V = -V; + float m_1_sig2; prepare_velvet(sigma, m_1_sig2); + + /* ambient light */ + vec3 accumulator = ambient_light.rgb; + + /* directional lights */ + for(int i = 0; i < NUM_LIGHTS; i++) { + vec3 L = gl_LightSource[i].position.xyz; + vec3 light_color = gl_LightSource[i].specular.rgb; + + accumulator += light_color * bsdf_ashikhmin_velvet(N, L, V, m_1_sig2); + } + + result = vec4(accumulator * color.rgb, 1.0); +} + +/* -------- Physical Lights --------- */ + +/* VELVET */ + +void bsdf_velvet_sphere_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float m_1_sig2; prepare_velvet(sigma, m_1_sig2); + + bsdf = bsdf_ashikhmin_velvet(N, L, V, m_1_sig2); + + /* Energy conservation + cycle matching */ + bsdf *= 8.0 / (l_distance * l_distance); + /* bsdf *= sphere_energy(l_radius); Velvet is using only point lights for now */ +} + +void bsdf_velvet_area_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + if (max(l_areasizex, l_areasizey) < 1e-6) { + bsdf = 0.0; + return; + } + + float m_1_sig2; prepare_velvet(sigma, m_1_sig2); + + bsdf = bsdf_ashikhmin_velvet(N, L, V, m_1_sig2); + + /* Energy conservation + cycle matching */ + bsdf *= 8.0 / (l_distance * l_distance); + + /* l_areasizex *= scale.x; + * l_areasizey *= scale.y; + * bsdf *= rectangle_energy(l_areasizex, l_areasizey); Velvet is using only point lights for now*/ +} + +void bsdf_velvet_sun_light(vec3 N, vec3 T, vec3 L, vec3 V, vec3 l_coords, + float l_distance, float l_areasizex, float l_areasizey, vec2 l_areascale, mat4 l_mat, + float roughness, float ior, float sigma, float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + out float bsdf) +{ + float m_1_sig2; prepare_velvet(sigma, m_1_sig2); + + bsdf = bsdf_ashikhmin_velvet(N, L, V, m_1_sig2); +} + + +/* -------- Image Based Lighting --------- */ + +void env_sampling_velvet( + float pbr, vec3 viewpos, mat4 invviewmat, mat4 viewmat, + vec3 N, vec3 T, float roughness, float ior, float sigma, + float toon_size, float toon_smooth, float anisotropy, float aniso_rotation, + float ao_factor, out vec3 result) +{ + vector_prepass(viewpos, N, invviewmat, viewmat); + make_orthonormals(N, T, B); /* Generate tangent space */ + setup_noise(gl_FragCoord.xy); /* Noise to dither the samples */ + + /* Precomputation */ + float m_1_sig2; prepare_velvet(sigma, m_1_sig2); + float NV = max(1e-5, abs(dot(I, N))); + + /* Integrating Envmap */ + vec4 out_radiance = vec4(0.0); + for (float i = 0; i < unfbsdfsamples.x; i++) { + vec3 L = sample_hemisphere(i, N, T, B); + vec3 H = normalize(L - I); + + float NL = dot(N, L); + float NH = dot(N, H); /* cosTheta */ + + if (NL > 0.0 && abs(NH) < 1.0-1e-5) { + /* Step 1 : Sampling Environment */ + float pdf = pdf_hemisphere(); + vec4 irradiance = sample_probe_pdf(L, pdf); + + /* Step 2 : Integrating BRDF*/ + float VH = max(abs(dot(I, H)), 1e-5); + float brdf = bsdf_ashikhmin_velvet(NL, NV, NH, VH, m_1_sig2); + + out_radiance += irradiance * brdf / pdf; + } + } + + result = out_radiance.rgb * unfbsdfsamples.y * ao_factor; +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_new_shading.glsl b/source/blender/gpu/shaders/gpu_shader_material_new_shading.glsl new file mode 100644 index 00000000000..c5b2e1f0b81 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_new_shading.glsl @@ -0,0 +1,1207 @@ +/*********** NEW SHADER NODES ***************/ + +/* Blending */ +void node_bsdf_opaque(vec4 color, vec4 ambient_light, vec4 direct_light, out vec4 result) +{ + result = vec4( (ambient_light.rgb + direct_light.rgb) * color.rgb, 1.0); +} + +void node_bsdf_transparent(vec4 color, vec4 background, out vec4 result) +{ + result = vec4( background.rgb * color.rgb, color.a); +} + +/* Others Bsdfs */ + +void node_subsurface_scattering(vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, out vec4 result) +{ + node_bsdf_diffuse_lights(color, 0.0, N, vec3(0.0), vec4(0.2), result); +} + +void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out vec4 result) +{ + result = color; +} + +void node_ambient_occlusion(vec4 color, out vec4 result) +{ + result = color; +} + +void node_holdout(out vec4 result) +{ + result = vec4(0.0); +} + +/* emission */ + +void node_emission(vec4 color, float strength, vec3 N, out vec4 result) +{ + result = color*strength; +} + +/* blackbody */ + +void node_blackbody(float T, out vec4 col) +{ + float u = ( 0.860117757 + 1.54118254e-4 * T + 1.28641212e-7 * T*T ) / ( 1.0 + 8.42420235e-4 * T + 7.08145163e-7 * T*T ); + float v = ( 0.317398726 + 4.22806245e-5 * T + 4.20481691e-8 * T*T ) / ( 1.0 - 2.89741816e-5 * T + 1.61456053e-7 * T*T ); + + float x = 3*u / ( 2*u - 8*v + 4 ); + float y = 2*v / ( 2*u - 8*v + 4 ); + float z = 1 - x - y; + + float Y = 1; + float X = Y/y * x; + float Z = Y/y * z; + + mat3 XYZtoRGB = mat3( + 3.2404542, -0.9692660, 0.0556434, + -1.5371385, 1.8760108, -0.2040259, + -0.4985314, 0.0415560, 1.0572252 + ); + + col = vec4(( XYZtoRGB * vec3( X, Y, Z ) ), 1.0); +} + +vec3 xyz_to_rgb(float x, float y, float z) +{ + return vec3( 3.240479 * x + -1.537150 * y + -0.498535 * z, + -0.969256 * x + 1.875991 * y + 0.041556 * z, + 0.055648 * x + -0.204043 * y + 1.057311 * z); +} + +// CIE colour matching functions xBar, yBar, and zBar for +// wavelengths from 380 through 780 nanometers, every 5 +// nanometers. For a wavelength lambda in this range: +// cie_colour_match[(lambda - 380) / 5][0] = xBar +// cie_colour_match[(lambda - 380) / 5][1] = yBar +// cie_colour_match[(lambda - 380) / 5][2] = zBar +uniform vec3 node_wavelength_LUT[81] = vec3[81]( + vec3(0.0014,0.0000,0.0065), vec3(0.0022,0.0001,0.0105), vec3(0.0042,0.0001,0.0201), + vec3(0.0076,0.0002,0.0362), vec3(0.0143,0.0004,0.0679), vec3(0.0232,0.0006,0.1102), + vec3(0.0435,0.0012,0.2074), vec3(0.0776,0.0022,0.3713), vec3(0.1344,0.0040,0.6456), + vec3(0.2148,0.0073,1.0391), vec3(0.2839,0.0116,1.3856), vec3(0.3285,0.0168,1.6230), + vec3(0.3483,0.0230,1.7471), vec3(0.3481,0.0298,1.7826), vec3(0.3362,0.0380,1.7721), + vec3(0.3187,0.0480,1.7441), vec3(0.2908,0.0600,1.6692), vec3(0.2511,0.0739,1.5281), + vec3(0.1954,0.0910,1.2876), vec3(0.1421,0.1126,1.0419), vec3(0.0956,0.1390,0.8130), + vec3(0.0580,0.1693,0.6162), vec3(0.0320,0.2080,0.4652), vec3(0.0147,0.2586,0.3533), + vec3(0.0049,0.3230,0.2720), vec3(0.0024,0.4073,0.2123), vec3(0.0093,0.5030,0.1582), + vec3(0.0291,0.6082,0.1117), vec3(0.0633,0.7100,0.0782), vec3(0.1096,0.7932,0.0573), + vec3(0.1655,0.8620,0.0422), vec3(0.2257,0.9149,0.0298), vec3(0.2904,0.9540,0.0203), + vec3(0.3597,0.9803,0.0134), vec3(0.4334,0.9950,0.0087), vec3(0.5121,1.0000,0.0057), + vec3(0.5945,0.9950,0.0039), vec3(0.6784,0.9786,0.0027), vec3(0.7621,0.9520,0.0021), + vec3(0.8425,0.9154,0.0018), vec3(0.9163,0.8700,0.0017), vec3(0.9786,0.8163,0.0014), + vec3(1.0263,0.7570,0.0011), vec3(1.0567,0.6949,0.0010), vec3(1.0622,0.6310,0.0008), + vec3(1.0456,0.5668,0.0006), vec3(1.0026,0.5030,0.0003), vec3(0.9384,0.4412,0.0002), + vec3(0.8544,0.3810,0.0002), vec3(0.7514,0.3210,0.0001), vec3(0.6424,0.2650,0.0000), + vec3(0.5419,0.2170,0.0000), vec3(0.4479,0.1750,0.0000), vec3(0.3608,0.1382,0.0000), + vec3(0.2835,0.1070,0.0000), vec3(0.2187,0.0816,0.0000), vec3(0.1649,0.0610,0.0000), + vec3(0.1212,0.0446,0.0000), vec3(0.0874,0.0320,0.0000), vec3(0.0636,0.0232,0.0000), + vec3(0.0468,0.0170,0.0000), vec3(0.0329,0.0119,0.0000), vec3(0.0227,0.0082,0.0000), + vec3(0.0158,0.0057,0.0000), vec3(0.0114,0.0041,0.0000), vec3(0.0081,0.0029,0.0000), + vec3(0.0058,0.0021,0.0000), vec3(0.0041,0.0015,0.0000), vec3(0.0029,0.0010,0.0000), + vec3(0.0020,0.0007,0.0000), vec3(0.0014,0.0005,0.0000), vec3(0.0010,0.0004,0.0000), + vec3(0.0007,0.0002,0.0000), vec3(0.0005,0.0002,0.0000), vec3(0.0003,0.0001,0.0000), + vec3(0.0002,0.0001,0.0000), vec3(0.0002,0.0001,0.0000), vec3(0.0001,0.0000,0.0000), + vec3(0.0001,0.0000,0.0000), vec3(0.0001,0.0000,0.0000), vec3(0.0000,0.0000,0.0000) +); + +void node_wavelength(float w, out vec4 col) +{ + float ii = (w-380.0) * (1.0/5.0); // scaled 0..80 + int i = int(ii); + vec3 color; + + if(i < 0 || i >= 80) { + color = vec3(0.0, 0.0, 0.0); + } + else { + ii -= i; + color = mix(node_wavelength_LUT[i], node_wavelength_LUT[i+1], ii); + } + + color = xyz_to_rgb(color.x, color.y, color.z); + color *= 1.0/2.52; // Empirical scale from lg to make all comps <= 1 + + /* Clamp to zero if values are smaller */ + col = vec4(max(color, vec3(0.0, 0.0, 0.0)), 1.0); + + // srgb_to_linearrgb(col, col); +} + +/* background */ + +void background_transform_to_world(vec3 viewvec, out vec3 worldvec) +{ + vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + worldvec = (gl_ModelViewMatrixInverse * co).xyz; +} + +void node_background(vec4 color, float strength, vec3 N, out vec4 result) +{ + result = color * strength; +} + +/* closures */ + +void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader) +{ + shader = mix(shader1, shader2, saturate(fac)); +} + +void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader) +{ + shader = shader1 + shader2; +} + +/* fresnel */ + +void node_fresnel(float ior, vec3 N, vec3 I, out float result) +{ + /* handle perspective/orthographic */ + vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + + float eta = max(ior, 0.00001); + result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0/eta); +} + +/* layer_weight */ + +void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing) +{ + /* fresnel */ + float eta = max(1.0 - blend, 0.00001); + vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + + fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing)? 1.0/eta : eta ); + + /* facing */ + facing = abs(dot(I_view, N)); + if (blend != 0.5) { + blend = clamp(blend, 0.0, 0.99999); + blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); + facing = pow(facing, blend); + } + facing = 1.0 - facing; +} + +/* gamma */ + +void node_gamma(vec4 col, float gamma, out vec4 outcol) +{ + outcol = col; + + if (col.r > 0.0) + outcol.r = compatible_pow(col.r, gamma); + if (col.g > 0.0) + outcol.g = compatible_pow(col.g, gamma); + if (col.b > 0.0) + outcol.b = compatible_pow(col.b, gamma); +} + +/* geometry */ + +void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf) +{ + outcol = vec4(attr, 1.0); + outvec = attr; + outf = (attr.x + attr.y + attr.z) / 3.0; +} + +void node_uvmap(vec3 attr_uv, out vec3 outvec) +{ + outvec = attr_uv; +} + +void tangent_orco_x(vec3 orco_in, out vec3 orco_out) +{ + orco_out = vec3(0.0, orco_in.z * -0.5, orco_in.y * 0.5); +} + +void tangent_orco_y(vec3 orco_in, out vec3 orco_out) +{ + orco_out = vec3(orco_in.z * -0.5, 0.0, orco_in.x * 0.5); +} + +void tangent_orco_z(vec3 orco_in, out vec3 orco_out) +{ + orco_out = vec3(orco_in.y * -0.5, orco_in.x * 0.5, 0.0); +} + +void node_tangent(vec3 N, vec3 orco, mat4 objmat, mat4 invviewmat, out vec3 T) +{ + N = (invviewmat*vec4(N, 0.0)).xyz; + T = (objmat*vec4(orco, 0.0)).xyz; + T = cross(N, normalize(cross(T, N))); +} + +void node_tangentmap(vec4 attr_tangent, mat4 toworld, out vec3 tangent) +{ + tangent = (toworld * vec4(attr_tangent.xyz, 0.0)).xyz; +} + +void default_tangent(vec3 N, vec3 orco, mat4 objmat, mat4 viewmat, mat4 invviewmat, out vec3 T) +{ + orco = vec3(orco.y * -0.5, orco.x * 0.5, 0.0); + node_tangent(N, orco, objmat, invviewmat, T); + T = (viewmat * vec4(T, 0.0)).xyz; +} + +void node_geometry(vec3 I, vec3 N, vec3 attr_orco, mat4 toworld, mat4 fromobj, + out vec3 position, out vec3 normal, out vec3 tangent, + out vec3 true_normal, out vec3 incoming, out vec3 parametric, + out float backfacing, out float pointiness) +{ + position = (toworld * vec4(I, 1.0)).xyz; + normal = (toworld * vec4(N, 0.0)).xyz; + attr_orco = vec3(attr_orco.y * -0.5, attr_orco.x * 0.5, 0.0); + node_tangent(N, attr_orco, fromobj, toworld, tangent); + true_normal = normal; + + /* handle perspective/orthographic */ + vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + incoming = -(toworld * vec4(I_view, 0.0)).xyz; + + parametric = vec3(0.0); + backfacing = (gl_FrontFacing) ? 0.0 : 1.0; + pointiness = 0.5; +} + +void node_geometry_lamp(vec3 N, vec4 P, vec3 I, mat4 toworld, + out vec3 position, out vec3 normal, out vec3 tangent, + out vec3 true_normal, out vec3 incoming, out vec3 parametric, + out float backfacing, out float pointiness) +{ + position = (toworld*P).xyz; + normal = normalize(toworld*vec4(N, 0.0)).xyz; + tangent = vec3(0.0); + true_normal = normal; + incoming = normalize(toworld*vec4(I, 0.0)).xyz; + + parametric = vec3(0.0); + backfacing = 0.0; + pointiness = 0.0; +} + +void node_tex_coord( + vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac, + vec3 attr_orco, vec3 attr_uv, + out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, + out vec3 camera, out vec3 window, out vec3 reflection) +{ + generated = attr_orco * 0.5 + vec3(0.5); + normal = normalize((obinvmat * (viewinvmat * vec4(N, 0.0))).xyz); + uv = attr_uv; + object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz; + camera = vec3(I.xy, -I.z); + vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0); + window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); + + vec3 shade_I; + shade_view(I, shade_I); + vec3 view_reflection = reflect(shade_I, normalize(N)); + reflection = (viewinvmat * vec4(view_reflection, 0.0)).xyz; +} + +void node_tex_coord_background( + vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac, + vec3 attr_orco, vec3 attr_uv, + out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, + out vec3 camera, out vec3 window, out vec3 reflection) +{ + vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + + co = normalize(co); + vec3 coords = (gl_ModelViewMatrixInverse * co).xyz; + + generated = coords; + normal = -coords; + uv = vec3(attr_uv.xy, 0.0); + object = coords; + + camera = vec3(co.xy, -co.z); + window = (gl_ProjectionMatrix[3][3] == 0.0) ? + vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) : + vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0); + + reflection = -coords; +} + +/* textures */ + +float calc_gradient(vec3 p, int gradient_type) +{ + float x, y, z; + x = p.x; + y = p.y; + z = p.z; + if (gradient_type == 0) { /* linear */ + return x; + } + else if (gradient_type == 1) { /* quadratic */ + float r = max(x, 0.0); + return r * r; + } + else if (gradient_type == 2) { /* easing */ + float r = min(max(x, 0.0), 1.0); + float t = r * r; + return (3.0 * t - 2.0 * t * r); + } + else if (gradient_type == 3) { /* diagonal */ + return (x + y) * 0.5; + } + else if (gradient_type == 4) { /* radial */ + return atan(y, x) / (M_PI * 2) + 0.5; + } + else { + float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0); + if (gradient_type == 5) { /* quadratic sphere */ + return r * r; + } + else if (gradient_type == 6) { /* sphere */ + return r; + } + } + return 0.0; +} + +void node_tex_gradient(vec3 co, float gradient_type, out vec4 color, out float fac) +{ + float f = calc_gradient(co, int(gradient_type)); + f = clamp(f, 0.0, 1.0); + + color = vec4(f, f, f, 1.0); + fac = f; +} + +void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac) +{ + vec3 p = co * scale; + + /* Prevent precision issues on unit coordinates. */ + p.x = (p.x + 0.000001) * 0.999999; + p.y = (p.y + 0.000001) * 0.999999; + p.z = (p.z + 0.000001) * 0.999999; + + int xi = int(abs(floor(p.x))); + int yi = int(abs(floor(p.y))); + int zi = int(abs(floor(p.z))); + + bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2))); + + color = check ? color1 : color2; + fac = check ? 1.0 : 0.0; +} + +#ifdef BIT_OPERATIONS +vec2 calc_brick_texture(vec3 p, float mortar_size, float bias, + float brick_width, float row_height, + float offset_amount, int offset_frequency, + float squash_amount, int squash_frequency) +{ + int bricknum, rownum; + float offset = 0.0; + float x, y; + + rownum = floor_to_int(p.y / row_height); + + if (offset_frequency != 0 && squash_frequency != 0) { + brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */ + offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */ + } + + bricknum = floor_to_int((p.x + offset) / brick_width); + + x = (p.x + offset) - brick_width * bricknum; + y = p.y - row_height * rownum; + + return vec2(clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0), + (x < mortar_size || y < mortar_size || + x > (brick_width - mortar_size) || + y > (row_height - mortar_size)) ? 1.0 : 0.0); +} +#endif + +void node_tex_brick(vec3 co, + vec4 color1, vec4 color2, + vec4 mortar, float scale, + float mortar_size, float bias, + float brick_width, float row_height, + float offset_amount, float offset_frequency, + float squash_amount, float squash_frequency, + out vec4 color, out float fac) +{ +#ifdef BIT_OPERATIONS + vec2 f2 = calc_brick_texture(co * scale, + mortar_size, bias, + brick_width, row_height, + offset_amount, int(offset_frequency), + squash_amount, int(squash_frequency)); + float tint = f2.x; + float f = f2.y; + if (f != 1.0) { + float facm = 1.0 - tint; + color1 = facm * color1 + tint * color2; + } + color = (f == 1.0) ? mortar : color1; + fac = f; +#else + color = vec4(1.0); + fac = 1.0; +#endif +} + +void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac) +{ + color = vec4(1.0); + fac = 1.0; +} + +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; + + color = texture2D(ima, vec2(u, v)); +} + +void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color) +{ + vec3 nco = normalize(co); + + nco.y -= 1.0; + + float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0)); + if(div > 0.0) + nco /= div; + + float u = 0.5 * (nco.x + 1.0); + float v = 0.5 * (nco.z + 1.0); + + color = texture2D(ima, vec2(u, v)); +} + +void node_tex_environment_empty(vec3 co, out vec4 color) +{ + color = vec4(1.0, 0.0, 1.0, 1.0); +} + +void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + color = texture2D(ima, co.xy); + alpha = color.a; +} + +void node_tex_image_closest(vec3 co, sampler2D ima, vec2 res, out vec4 color, out float alpha) +{ +#if __VERSION__ < 130 + color = texture2DLod(ima, (floor(co.xy * res) + 0.5) / res, 0.0); +#else + color = texelFetch(ima, ivec2(fract(co.xy) * res), 0); +#endif + alpha = color.a; +} + +void node_tex_image_box(vec3 texco, + vec3 nob, + sampler2D ima, + float blend, + out vec4 color, + out float alpha) +{ + /* project from direction vector to barycentric coordinates in triangles */ + nob = vec3(abs(nob.x), abs(nob.y), abs(nob.z)); + nob /= (nob.x + nob.y + nob.z); + + /* basic idea is to think of this as a triangle, each corner representing + * one of the 3 faces of the cube. in the corners we have single textures, + * in between we blend between two textures, and in the middle we a blend + * between three textures. + * + * the Nxyz values are the barycentric coordinates in an equilateral + * triangle, which in case of blending, in the middle has a smaller + * equilateral triangle where 3 textures blend. this divides things into + * 7 zones, with an if () test for each zone */ + + vec3 weight = vec3(0.0, 0.0, 0.0); + float limit = 0.5 * (1.0 + blend); + + /* first test for corners with single texture */ + if (nob.x > limit * (nob.x + nob.y) && nob.x > limit * (nob.x + nob.z)) { + weight.x = 1.0; + } + else if (nob.y > limit * (nob.x + nob.y) && nob.y > limit * (nob.y + nob.z)) { + weight.y = 1.0; + } + else if (nob.z > limit * (nob.x + nob.z) && nob.z > limit * (nob.y + nob.z)) { + weight.z = 1.0; + } + else if (blend > 0.0) { + /* in case of blending, test for mixes between two textures */ + if (nob.z < (1.0 - limit) * (nob.y + nob.x)) { + weight.x = nob.x / (nob.x + nob.y); + weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); + weight.y = 1.0 - weight.x; + } + else if (nob.x < (1.0 - limit) * (nob.y + nob.z)) { + weight.y = nob.y / (nob.y + nob.z); + weight.y = clamp((weight.y - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); + weight.z = 1.0 - weight.y; + } + else if (nob.y < (1.0 - limit) * (nob.x + nob.z)) { + weight.x = nob.x / (nob.x + nob.z); + weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); + weight.z = 1.0 - weight.x; + } + else { + /* last case, we have a mix between three */ + weight.x = ((2.0 - limit) * nob.x + (limit - 1.0)) / (2.0 * limit - 1.0); + weight.y = ((2.0 - limit) * nob.y + (limit - 1.0)) / (2.0 * limit - 1.0); + weight.z = ((2.0 - limit) * nob.z + (limit - 1.0)) / (2.0 * limit - 1.0); + } + } + else { + /* Desperate mode, no valid choice anyway, fallback to one side.*/ + weight.x = 1.0; + } + + color = vec4(0); + if (weight.x > 0.0) { + color += weight.x * texture2D(ima, texco.yz); + } + if (weight.y > 0.0) { + color += weight.y * texture2D(ima, texco.xz); + } + if (weight.z > 0.0) { + color += weight.z * texture2D(ima, texco.yx); + } + + alpha = color.a; +} + +void node_tex_image_empty(vec3 co, out vec4 color, out float alpha) +{ + color = vec4(0.0); + alpha = 0.0; +} + +void node_tex_magic(vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac) +{ + vec3 p = co * scale; + float x = sin((p.x + p.y + p.z) * 5.0); + float y = cos((-p.x + p.y - p.z) * 5.0); + float z = -cos((-p.x - p.y + p.z) * 5.0); + + if (depth > 0) { + x *= distortion; + y *= distortion; + z *= distortion; + y = -cos(x - y + z); + y *= distortion; + if (depth > 1) { + x = cos(x - y - z); + x *= distortion; + if (depth > 2) { + z = sin(-x - y - z); + z *= distortion; + if (depth > 3) { + x = -cos(-x + y - z); + x *= distortion; + if (depth > 4) { + y = -sin(-x + y + z); + y *= distortion; + if (depth > 5) { + y = -cos(-x + y + z); + y *= distortion; + if (depth > 6) { + x = cos(x + y + z); + x *= distortion; + if (depth > 7) { + z = sin(x + y - z); + z *= distortion; + if (depth > 8) { + x = -cos(-x - y + z); + x *= distortion; + if (depth > 9) { + y = -sin(x - y + z); + y *= distortion; + } + } + } + } + } + } + } + } + } + } + if (distortion != 0.0) { + distortion *= 2.0; + x /= distortion; + y /= distortion; + z /= distortion; + } + + color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0); + fac = (color.x + color.y + color.z) / 3.0; +} + +#ifdef BIT_OPERATIONS +float noise_fade(float t) +{ + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +float noise_scale3(float result) +{ + return 0.9820 * result; +} + +float noise_nerp(float t, float a, float b) +{ + return (1.0 - t) * a + t * b; +} + +float noise_grad(uint hash, float x, float y, float z) +{ + uint h = hash & 15u; + float u = h < 8u ? x : y; + float vt = ((h == 12u) || (h == 14u)) ? x : z; + float v = h < 4u ? y : vt; + return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v); +} + +float noise_perlin(float x, float y, float z) +{ + int X; float fx = floorfrac(x, X); + int Y; float fy = floorfrac(y, Y); + int Z; float fz = floorfrac(z, Z); + + float u = noise_fade(fx); + float v = noise_fade(fy); + float w = noise_fade(fz); + + float result; + + result = noise_nerp(w, noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z), fx, fy, fz), + noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz)), + noise_nerp(u, noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz), + noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz))), + noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0), + noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)), + noise_nerp(u, noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0), + noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0)))); + return noise_scale3(result); +} + +float noise(vec3 p) +{ + return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5; +} + +float snoise(vec3 p) +{ + return noise_perlin(p.x, p.y, p.z); +} + +float noise_turbulence(vec3 p, float octaves, int hard) +{ + float fscale = 1.0; + float amp = 1.0; + float sum = 0.0; + int i, n; + octaves = clamp(octaves, 0.0, 16.0); + n = int(octaves); + for (i = 0; i <= n; i++) { + float t = noise(fscale * p); + if (hard != 0) { + t = abs(2.0 * t - 1.0); + } + sum += t * amp; + amp *= 0.5; + fscale *= 2.0; + } + float rmd = octaves - floor(octaves); + if (rmd != 0.0) { + float t = noise(fscale * p); + if (hard != 0) { + t = abs(2.0 * t - 1.0); + } + float sum2 = sum + t * amp; + sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); + sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1)); + return (1.0 - rmd) * sum + rmd * sum2; + } + else { + sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); + return sum; + } +} +#endif // BIT_OPERATIONS + +void node_tex_noise(vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac) +{ +#ifdef BIT_OPERATIONS + vec3 p = co * scale; + int hard = 0; + if (distortion != 0.0) { + vec3 r, offset = vec3(13.5, 13.5, 13.5); + r.x = noise(p + offset) * distortion; + r.y = noise(p) * distortion; + r.z = noise(p - offset) * distortion; + p += r; + } + + fac = noise_turbulence(p, detail, hard); + color = vec4(fac, + noise_turbulence(vec3(p.y, p.x, p.z), detail, hard), + noise_turbulence(vec3(p.y, p.z, p.x), detail, hard), + 1); +#else // BIT_OPERATIONS + color = vec4(1.0); + fac = 1.0; +#endif // BIT_OPERATIONS +} + + +#ifdef BIT_OPERATIONS + +/* Musgrave fBm + * + * H: fractal increment parameter + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * + * from "Texturing and Modelling: A procedural approach" + */ + +float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves) +{ + float rmd; + float value = 0.0; + float pwr = 1.0; + float pwHL = pow(lacunarity, -H); + int i; + + for (i = 0; i < int(octaves); i++) { + value += snoise(p) * pwr; + pwr *= pwHL; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) + value += rmd * snoise(p) * pwr; + + return value; +} + +/* Musgrave Multifractal + * + * H: highest fractal dimension + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + */ + +float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves) +{ + float rmd; + float value = 1.0; + float pwr = 1.0; + float pwHL = pow(lacunarity, -H); + int i; + + for (i = 0; i < int(octaves); i++) { + value *= (pwr * snoise(p) + 1.0); + pwr *= pwHL; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) + value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ + + return value; +} + +/* Musgrave Heterogeneous Terrain + * + * H: fractal dimension of the roughest area + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * offset: raises the terrain from `sea level' + */ + +float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset) +{ + float value, increment, rmd; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; + int i; + + /* first unscaled octave of function; later octaves are scaled */ + value = offset + snoise(p); + p *= lacunarity; + + for (i = 1; i < int(octaves); i++) { + increment = (snoise(p) + offset) * pwr * value; + value += increment; + pwr *= pwHL; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + increment = (snoise(p) + offset) * pwr * value; + value += rmd * increment; + } + + return value; +} + +/* Hybrid Additive/Multiplicative Multifractal Terrain + * + * H: fractal dimension of the roughest area + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * offset: raises the terrain from `sea level' + */ + +float noise_musgrave_hybrid_multi_fractal(vec3 p, float H, float lacunarity, float octaves, float offset, float gain) +{ + float result, signal, weight, rmd; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; + int i; + + result = snoise(p) + offset; + weight = gain * result; + p *= lacunarity; + + for (i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { + if (weight > 1.0) + weight = 1.0; + + signal = (snoise(p) + offset) * pwr; + pwr *= pwHL; + result += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) + result += rmd * ((snoise(p) + offset) * pwr); + + return result; +} + +/* Ridged Multifractal Terrain + * + * H: fractal dimension of the roughest area + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * offset: raises the terrain from `sea level' + */ + +float noise_musgrave_ridged_multi_fractal(vec3 p, float H, float lacunarity, float octaves, float offset, float gain) +{ + float result, signal, weight; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; + int i; + + signal = offset - abs(snoise(p)); + signal *= signal; + result = signal; + weight = 1.0; + + for (i = 1; i < int(octaves); i++) { + p *= lacunarity; + weight = clamp(signal * gain, 0.0, 1.0); + signal = offset - abs(snoise(p)); + signal *= signal; + signal *= weight; + result += signal * pwr; + pwr *= pwHL; + } + + return result; +} + +float svm_musgrave(int type, + float dimension, + float lacunarity, + float octaves, + float offset, + float intensity, + float gain, + vec3 p) +{ + if (type == 0 /*NODE_MUSGRAVE_MULTIFRACTAL*/) + return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves); + else if (type == 1 /*NODE_MUSGRAVE_FBM*/) + return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves); + else if (type == 2 /*NODE_MUSGRAVE_HYBRID_MULTIFRACTAL*/) + return intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); + else if (type == 3 /*NODE_MUSGRAVE_RIDGED_MULTIFRACTAL*/) + return intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); + else if (type == 4 /*NODE_MUSGRAVE_HETERO_TERRAIN*/) + return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset); + return 0.0; +} +#endif // #ifdef BIT_OPERATIONS + +void node_tex_musgrave(vec3 co, + float scale, + float detail, + float dimension, + float lacunarity, + float offset, + float gain, + float type, + out vec4 color, + out float fac) +{ +#ifdef BIT_OPERATIONS + fac = svm_musgrave(int(type), + dimension, + lacunarity, + detail, + offset, + 1.0, + gain, + co * scale); +#else + fac = 1.0; +#endif + + color = vec4(fac, fac, fac, 1.0); +} + +void node_tex_sky(vec3 co, out vec4 color) +{ + color = vec4(1.0); +} + +void node_tex_voronoi(vec3 co, float scale, float coloring, out vec4 color, out float fac) +{ +#ifdef BIT_OPERATIONS + vec3 p = co * scale; + int xx, yy, zz, xi, yi, zi; + float da[4]; + vec3 pa[4]; + + xi = floor_to_int(p[0]); + yi = floor_to_int(p[1]); + zi = floor_to_int(p[2]); + + da[0] = 1e+10; + da[1] = 1e+10; + da[2] = 1e+10; + da[3] = 1e+10; + + for (xx = xi - 1; xx <= xi + 1; xx++) { + for (yy = yi - 1; yy <= yi + 1; yy++) { + for (zz = zi - 1; zz <= zi + 1; zz++) { + vec3 ip = vec3(xx, yy, zz); + vec3 vp = cellnoise_color(ip); + vec3 pd = p - (vp + ip); + float d = dot(pd, pd); + vp += vec3(xx, yy, zz); + if (d < da[0]) { + da[3] = da[2]; + da[2] = da[1]; + da[1] = da[0]; + da[0] = d; + pa[3] = pa[2]; + pa[2] = pa[1]; + pa[1] = pa[0]; + pa[0] = vp; + } + else if (d < da[1]) { + da[3] = da[2]; + da[2] = da[1]; + da[1] = d; + + pa[3] = pa[2]; + pa[2] = pa[1]; + pa[1] = vp; + } + else if (d < da[2]) { + da[3] = da[2]; + da[2] = d; + + pa[3] = pa[2]; + pa[2] = vp; + } + else if (d < da[3]) { + da[3] = d; + pa[3] = vp; + } + } + } + } + + if (coloring == 0.0) { + fac = abs(da[0]); + color = vec4(fac, fac, fac, 1); + } + else { + color = vec4(cellnoise_color(pa[0]), 1); + fac = (color.x + color.y + color.z) * (1.0 / 3.0); + } +#else // BIT_OPERATIONS + color = vec4(1.0); + fac = 1.0; +#endif // BIT_OPERATIONS +} + +#ifdef BIT_OPERATIONS +float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile) +{ + float n; + + if (wave_type == 0) /* type bands */ + n = (p.x + p.y + p.z) * 10.0; + else /* type rings */ + n = length(p) * 20.0; + + if (distortion != 0.0) + n += distortion * noise_turbulence(p * detail_scale, detail, 0); + + if (wave_profile == 0) { /* profile sin */ + return 0.5 + 0.5 * sin(n); + } + else { /* profile saw */ + n /= 2.0 * M_PI; + n -= int(n); + return (n < 0.0) ? n + 1.0 : n; + } +} +#endif // BIT_OPERATIONS + +void node_tex_wave( + vec3 co, float scale, float distortion, float detail, float detail_scale, float wave_type, float wave_profile, + out vec4 color, out float fac) +{ +#ifdef BIT_OPERATIONS + float f; + f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile)); + + color = vec4(f, f, f, 1.0); + fac = f; +#else // BIT_OPERATIONS + color = vec4(1.0); + fac = 1; +#endif // BIT_OPERATIONS +} + +/* light path */ + +void node_light_path( + out float is_camera_ray, + out float is_shadow_ray, + out float is_diffuse_ray, + out float is_glossy_ray, + out float is_singular_ray, + out float is_reflection_ray, + out float is_transmission_ray, + out float ray_length, + out float ray_depth, + out float transparent_depth, + out float transmission_depth) +{ + is_camera_ray = 1.0; + is_shadow_ray = 0.0; + is_diffuse_ray = 0.0; + is_glossy_ray = 0.0; + is_singular_ray = 0.0; + is_reflection_ray = 0.0; + is_transmission_ray = 0.0; + ray_length = 1.0; + ray_depth = 1.0; + transparent_depth = 1.0; + transmission_depth = 1.0; +} + +void node_light_falloff(float strength, float tsmooth, vec4 lamppos, vec3 pos, out float quadratic, out float linear, out float constant) +{ + float ray_length = length(lamppos.xyz - pos); + + if (tsmooth > 0.0) { + float squared = ray_length * ray_length; + strength *= squared / (tsmooth + squared); + } + + quadratic = strength; + linear = (strength * ray_length); + constant = (strength * ray_length * ray_length); +} + +void node_object_info(mat4 objmat, out vec3 location, out float object_index, out float material_index, out float random) +{ + location = objmat[3].xyz; + object_index = 0.0; + material_index = 0.0; + random = 0.0; +} + +void node_normal_map(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) +{ + vec3 B = tangent.w * cross(normal, tangent.xyz); + + outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal; + outnormal = normalize(outnormal); +} + +void node_bump(float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result) +{ + if (invert != 0.0) { + dist *= -1.0; + } + vec3 dPdx = dFdx(surf_pos); + vec3 dPdy = dFdy(surf_pos); + + /* Get surface tangents from normal. */ + vec3 Rx = cross(dPdy, N); + vec3 Ry = cross(N, dPdx); + + /* Compute surface gradient and determinant. */ + float det = dot(dPdx, Rx); + float absdet = abs(det); + + float dHdx = dFdx(height); + float dHdy = dFdy(height); + vec3 surfgrad = dHdx * Rx + dHdy * Ry; + + strength = max(strength, 0.0); + + result = normalize(absdet * N - dist * sign(det) * surfgrad); + result = normalize(strength * result + (1.0 - strength) * N); +} + +/* output */ + +void node_output_material(vec4 surface, vec4 volume, float displacement, out vec4 result) +{ + result = surface; +} + +void node_output_world(vec4 surface, vec4 volume, out vec4 result) +{ + result = surface; +} + +void node_output_lamp(vec4 surface, out vec4 result) +{ + result = surface; +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_utils.glsl b/source/blender/gpu/shaders/gpu_shader_material_utils.glsl new file mode 100644 index 00000000000..dd7cabfb0cd --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_utils.glsl @@ -0,0 +1,1113 @@ +/* ------- Defines -------- */ + +/* Number of default opengl lights */ +#define NUM_LIGHTS 3 + +/* SSR Maximum iterations */ +#define MAX_SSR_REFINE_STEPS 8 + +/* Importance sampling Max iterations */ +#define BSDF_SAMPLES 1024 + +/* Linearly Transformed Cosines */ +#define LTC_LUT_SIZE 64 + +/* needed for uint type and bitwise operation */ +#extension GL_EXT_gpu_shader4: enable + +/* ------- PBR Uniform --------- */ + +uniform samplerCube unfprobe; +uniform sampler2D unfreflect; +uniform sampler2D unfrefract; +uniform sampler2D unfltcmat; +uniform sampler2D unfltcmag; +uniform sampler2D unfscenebuf; +uniform sampler2D unfdepthbuf; +uniform sampler2D unfbackfacebuf; +uniform sampler2D unfjitter; +uniform sampler1D unflutsamples; +uniform float unflodfactor; +uniform vec2 unfbsdfsamples; +uniform vec3 unfsh0; +uniform vec3 unfsh1; +uniform vec3 unfsh2; +uniform vec3 unfsh3; +uniform vec3 unfsh4; +uniform vec3 unfsh5; +uniform vec3 unfsh6; +uniform vec3 unfsh7; +uniform vec3 unfsh8; +uniform vec3 unfprobepos; +uniform vec3 unfplanarvec; +uniform vec3 unfssrparam; +uniform vec4 unfssaoparam; +uniform vec4 unfclip; +uniform mat4 unfprobecorrectionmat; +uniform mat4 unfplanarreflectmat; +uniform mat4 unfpixelprojmat; + +/* ------- Global Variables -------- */ + +vec3 worldpos, refpos; +vec3 viewnor, viewi; +vec3 planarfac, planarvec; +vec3 I, B, Ht; +vec2 jitternoise = vec2(0.0); + +/* ------- Convenience functions --------- */ + +vec3 mul(mat3 m, vec3 v) { return m * v; } +mat3 mul(mat3 m1, mat3 m2) { return m1 * m2; } + +float saturate(float a) { return clamp(a, 0.0, 1.0); } +vec2 saturate(vec2 a) { return vec2(saturate(a.x), saturate(a.y)); } +vec3 saturate(vec3 a) { return vec3(saturate(a.x), saturate(a.y), saturate(a.z)); } +vec4 saturate(vec4 a) { return vec4(saturate(a.x), saturate(a.y), saturate(a.z), saturate(a.w)); } + +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 hypot(float x, float y) { return sqrt(x*x + y*y); } + +float inverse_distance(vec3 V) { return max( 1 / length(V), 1e-8); } + +vec4 bufferFetch(sampler2D buf, ivec2 texelpos, int lod) +{ +#if __VERSION__ < 130 + return texture2DLod(buf, (vec2(texelpos) + 0.5) / (unfclip.zw / exp2(float(lod))), float(lod)); +#else + return texelFetch(buf, texelpos, lod); +#endif +} + +/* --------- Noise Utils Functions --------- */ + +void generated_from_orco(vec3 orco, out vec3 generated) +{ + generated = orco * 0.5 + vec3(0.5); +} + +int floor_to_int(float x) +{ + return int(floor(x)); +} + +int quick_floor(float x) +{ + return int(x) - ((x < 0) ? 1 : 0); +} + +#ifdef BIT_OPERATIONS +float integer_noise(int n) +{ + int nn; + n = (n + 1013) & 0x7fffffff; + n = (n >> 13) ^ n; + nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return 0.5 * (float(nn) / 1073741824.0); +} + +uint hash(uint kx, uint ky, uint kz) +{ +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) +#define final(a, b, c) \ +{ \ + c ^= b; c -= rot(b, 14); \ + a ^= c; a -= rot(c, 11); \ + b ^= a; b -= rot(a, 25); \ + c ^= b; c -= rot(b, 16); \ + a ^= c; a -= rot(c, 4); \ + b ^= a; b -= rot(a, 14); \ + c ^= b; c -= rot(b, 24); \ +} + // now hash the data! + uint a, b, c, len = 3u; + a = b = c = 0xdeadbeefu + (len << 2u) + 13u; + + c += kz; + b += ky; + a += kx; + final (a, b, c); + + return c; +#undef rot +#undef final +} + +uint hash(int kx, int ky, int kz) +{ + return hash(uint(kx), uint(ky), uint(kz)); +} + +float bits_to_01(uint bits) +{ + float x = float(bits) * (1.0 / float(0xffffffffu)); + return x; +} + +float cellnoise(vec3 p) +{ + int ix = quick_floor(p.x); + int iy = quick_floor(p.y); + int iz = quick_floor(p.z); + + return bits_to_01(hash(uint(ix), uint(iy), uint(iz))); +} + +vec3 cellnoise_color(vec3 p) +{ + float r = cellnoise(p); + float g = cellnoise(vec3(p.y, p.x, p.z)); + float b = cellnoise(vec3(p.y, p.z, p.x)); + + return vec3(r, g, b); +} +#endif // BIT_OPERATIONS + +float floorfrac(float x, out int i) +{ + i = floor_to_int(x); + return x - i; +} + +/* --------- Geometric Utils Functions --------- */ + +float linear_depth(float z) +{ + if (gl_ProjectionMatrix[3][3] == 0.0) { + float zn = unfclip.x; // camera z near + float zf = unfclip.y; // camera z far + return (zn * zf) / (z * (zn - zf) + zf); + } + else { + float zf = unfclip.y; // camera z far + return (z * 2.0 - 1.0) * zf; + } +} + +float backface_depth(ivec2 texelpos, int lod) +{ + return bufferFetch(unfbackfacebuf, texelpos, lod).r; +} + +float frontface_depth(ivec2 texelpos, int lod) +{ + return bufferFetch(unfdepthbuf, texelpos, lod).r; +} + +float backface_depth_linear(ivec2 texelpos, int lod) +{ + float depth = linear_depth(bufferFetch(unfbackfacebuf, texelpos, lod).r); + + /* background case */ + if (depth == 1.0) + return -1e16; + else + return -depth; +} + +float frontface_depth_linear(ivec2 texelpos, int lod) +{ + float depth = linear_depth(bufferFetch(unfdepthbuf, texelpos, lod).r); + + /* background case */ + if (depth == 1.0) + return -1e16; + else + return -depth; +} + +vec3 position_from_depth(vec2 uv, float depth) +{ + vec3 pos; + float homcoord = gl_ProjectionMatrix[2][3] * depth + gl_ProjectionMatrix[3][3]; + pos.x = gl_ProjectionMatrixInverse[0][0] * (uv.x * 2.0 - 1.0) * homcoord; + pos.y = gl_ProjectionMatrixInverse[1][1] * (uv.y * 2.0 - 1.0) * homcoord; + pos.z = depth; + return pos; +} + +vec2 uv_from_position(vec3 position) +{ + vec4 projvec = gl_ProjectionMatrix * vec4(position, 1.0); + return (projvec.xy / projvec.w) * 0.5 + 0.5; +} + +vec3 axis_angle_rotation(vec3 point, vec3 axis, float angle) +{ + axis = normalize(axis); + float s = sin(angle); + float c = cos(angle); + float oc = 1.0 - c; + + mat3 mat = mat3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, + oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, + oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c); + + return mat * point; +} + +void viewN_to_shadeN(vec3 N, out vec3 shadeN) +{ + shadeN = normalize(-N); +} + +void make_orthonormals(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); +} + +void make_orthonormals_tangent(vec3 N, inout vec3 T, out vec3 B) +{ + B = normalize( cross(N, T) ); + T = cross(B, N); +} + +void default_coordinates(vec3 attr_orco, out vec3 generated) +{ + generated = attr_orco * 0.5 + vec3(0.5); +} + +vec3 from_tangent_to_world( vec3 vector, vec3 N, vec3 T, vec3 B) +{ + return T * vector.x + B * vector.y + N * vector.z; +} + +vec3 from_world_to_tangent( vec3 vector, vec3 N, vec3 T, vec3 B) +{ + return vec3( dot(T, vector), dot(B, vector), dot(N, vector)); +} + +float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal) +{ + return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, 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; +} + +/* from cycles ray_aligned_disk_intersect */ +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; +} + +void most_representative_point(float l_radius, float l_lenght, vec3 l_Y, + float l_distance, vec3 R, inout vec3 L, + inout float roughness, inout float energy_conservation) +{ + L = l_distance * L; + + /* Tube Light */ + if(l_lenght>0){ + roughness = max(3e-3, roughness); /* Artifacts appear with roughness below this threshold */ + + // Use Tube Light specular instead of a plane. + // Energy conservation + // asin(x) is angle to sphere, atan(x) is angle to disk, saturate(x) is free and in the middle + //float LineAngle = clamp( l_lenght / l_distance, 0.0, 1.0); + + //energy_conservation *= roughness / clamp(roughness + 0.5 * LineAngle, 0.0, 1.0); + + /* Closest point on line segment to ray */ + vec3 L01 = l_Y * l_lenght; + vec3 L0 = L - 0.5 * L01; + vec3 L1 = L + 0.5 * L01; + + /* Shortest distance */ + float a = l_lenght * l_lenght; + float b = dot(R, L01); + float t = saturate(dot( L0, b*R - L01 ) / (a - b*b)); + L = L0 + t * L01; + } + + /* Sphere Light */ + if(l_radius>0){ + roughness = max(3e-3, roughness); /* Artifacts appear with roughness below this threshold */ + + /* energy preservation */ + float SphereAngle = saturate(l_radius / l_distance); + energy_conservation *= pow(roughness / saturate(roughness + 0.5 * SphereAngle), 2.0); + + /* sphere light */ + //float dist = line_aligned_plane_intersect_dist(vec3(0.0), R, L); + float dist = dot(L, R); + vec3 closest_point_on_ray = dist * R; + vec3 center_to_ray = closest_point_on_ray - L; + /* closest point on sphere */ + L = L + center_to_ray * saturate(l_radius * inverse_distance(center_to_ray)); + } + + L = normalize(L); +} + +void most_representative_point_disk(float l_radius, float l_distance, vec3 R, inout vec3 L, + inout float roughness, inout float energy_conservation) +{ + L = l_distance * L; + + /* Sphere Light */ + if(l_radius>0){ + roughness = max(3e-3, roughness); /* Artifacts appear with roughness below this threshold */ + + /* energy preservation */ + float SphereAngle = saturate(l_radius / l_distance); + energy_conservation *= pow(roughness / saturate(roughness + 0.5 * SphereAngle), 2.0); + + /* sphere light */ + vec3 closest_point_on_ray = line_plane_intersect(vec3(0.0), R, L, -normalize(L)); + vec3 center_to_ray = closest_point_on_ray - L; + /* closest point on sphere */ + L = L + center_to_ray * saturate(l_radius * inverse_distance(center_to_ray)); + } + + L = normalize(L); +} + +vec2 area_light_prepass(mat4 lmat, inout float areasizex, inout float areasizey, vec2 areascale, out vec3 lampx, out vec3 lampy, out vec3 lampz) +{ + lampx = normalize( (lmat * vec4(1.0,0.0,0.0,0.0) ).xyz ); //lamp right axis + lampy = normalize( (lmat * vec4(0.0,1.0,0.0,0.0) ).xyz ); //lamp up axis + lampz = normalize( (lmat * vec4(0.0,0.0,1.0,0.0) ).xyz ); //lamp projection axis + + areasizex *= areascale.x; + areasizey *= areascale.y; + + return vec2(areasizex / 2.0, areasizey / 2.0); +} + + +/* ------ Linearly Transformed Cosines ------ */ +/* From https://eheitzresearch.wordpress.com/415-2/ */ + +void area_light_points(vec3 lco, vec2 halfsize, vec3 lampx, vec3 lampy, out vec3 points[4]) +{ + vec3 ex = lampx * halfsize.x; + vec3 ey = lampy * halfsize.y; + + points[0] = lco - ex + ey; + points[1] = lco + ex + ey; + points[2] = lco + ex - ey; + points[3] = lco - ex - ey; +} + +float integrate_edge(vec3 v1, vec3 v2) +{ + float cosTheta = dot(v1, v2); + cosTheta = clamp(cosTheta, -0.9999, 0.9999); + + float theta = acos(cosTheta); + float res = cross(v1, v2).z * theta / sin(theta); + + return res; +} + +int clip_quad_to_horizon(inout vec3 L[5]) +{ + /* detect clipping config */ + int config = 0; + if (L[0].z > 0.0) config += 1; + if (L[1].z > 0.0) config += 2; + if (L[2].z > 0.0) config += 4; + if (L[3].z > 0.0) config += 8; + + /* clip */ + int n = 0; + + if (config == 0) + { + /* clip all */ + } + else if (config == 1) /* V1 clip V2 V3 V4 */ + { + n = 3; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + L[2] = -L[3].z * L[0] + L[0].z * L[3]; + } + else if (config == 2) /* V2 clip V1 V3 V4 */ + { + n = 3; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + } + else if (config == 3) /* V1 V2 clip V3 V4 */ + { + n = 4; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + L[3] = -L[3].z * L[0] + L[0].z * L[3]; + } + else if (config == 4) /* V3 clip V1 V2 V4 */ + { + n = 3; + L[0] = -L[3].z * L[2] + L[2].z * L[3]; + L[1] = -L[1].z * L[2] + L[2].z * L[1]; + } + else if (config == 5) /* V1 V3 clip V2 V4) impossible */ + { + n = 0; + } + else if (config == 6) /* V2 V3 clip V1 V4 */ + { + n = 4; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + L[3] = -L[3].z * L[2] + L[2].z * L[3]; + } + else if (config == 7) /* V1 V2 V3 clip V4 */ + { + n = 5; + L[4] = -L[3].z * L[0] + L[0].z * L[3]; + L[3] = -L[3].z * L[2] + L[2].z * L[3]; + } + else if (config == 8) /* V4 clip V1 V2 V3 */ + { + n = 3; + L[0] = -L[0].z * L[3] + L[3].z * L[0]; + L[1] = -L[2].z * L[3] + L[3].z * L[2]; + L[2] = L[3]; + } + else if (config == 9) /* V1 V4 clip V2 V3 */ + { + n = 4; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + L[2] = -L[2].z * L[3] + L[3].z * L[2]; + } + else if (config == 10) /* V2 V4 clip V1 V3) impossible */ + { + n = 0; + } + else if (config == 11) /* V1 V2 V4 clip V3 */ + { + n = 5; + L[4] = L[3]; + L[3] = -L[2].z * L[3] + L[3].z * L[2]; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + } + else if (config == 12) /* V3 V4 clip V1 V2 */ + { + n = 4; + L[1] = -L[1].z * L[2] + L[2].z * L[1]; + L[0] = -L[0].z * L[3] + L[3].z * L[0]; + } + else if (config == 13) /* V1 V3 V4 clip V2 */ + { + n = 5; + L[4] = L[3]; + L[3] = L[2]; + L[2] = -L[1].z * L[2] + L[2].z * L[1]; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + } + else if (config == 14) /* V2 V3 V4 clip V1 */ + { + n = 5; + L[4] = -L[0].z * L[3] + L[3].z * L[0]; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + } + else if (config == 15) /* V1 V2 V3 V4 */ + { + n = 4; + } + + if (n == 3) + L[3] = L[0]; + if (n == 4) + L[4] = L[0]; + + return n; +} + +vec2 ltc_coords(float cosTheta, float roughness) +{ + float theta = acos(cosTheta); + vec2 coords = vec2(roughness, theta/(0.5*3.14159)); + + /* scale and bias coordinates, for correct filtered lookup */ + return coords * (LTC_LUT_SIZE - 1.0) / LTC_LUT_SIZE + 0.5 / LTC_LUT_SIZE; +} + +mat3 ltc_matrix(vec2 coord) +{ + /* load inverse matrix */ + vec4 t = texture2D(unfltcmat, coord); + mat3 Minv = mat3( + vec3( 1, 0, t.y), + vec3( 0, t.z, 0), + vec3(t.w, 0, t.x) + ); + + return Minv; +} + +float ltc_evaluate(vec3 N, vec3 V, vec3 P, mat3 Minv, vec3 points[4]) +{ + /* 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 */ + Minv = mul(Minv, transpose(mat3(T1, T2, N))); + + /* polygon (allocate 5 vertices for clipping) */ + vec3 L[5]; + L[0] = mul(Minv, points[0] - P); + L[1] = mul(Minv, points[1] - P); + L[2] = mul(Minv, points[2] - P); + L[3] = mul(Minv, points[3] - P); + + int n = clip_quad_to_horizon(L); + + if (n == 0) + return 0.0; + + /* project onto sphere */ + L[0] = normalize(L[0]); + L[1] = normalize(L[1]); + L[2] = normalize(L[2]); + L[3] = normalize(L[3]); + L[4] = normalize(L[4]); + + /* integrate */ + float sum = 0.0; + + sum += integrate_edge(L[0], L[1]); + sum += integrate_edge(L[1], L[2]); + sum += integrate_edge(L[2], L[3]); + if (n >= 4) + sum += integrate_edge(L[3], L[4]); + if (n == 5) + sum += integrate_edge(L[4], L[0]); + + return abs(sum); +} + +/* ------- Fresnel ---------*/ + +float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) +{ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + float c = abs(dot(Incoming, Normal)); + float g = eta * eta - 1.0 + c * c; + float result; + + if(g > 0.0) { + g = sqrt(g); + float A =(g - c)/(g + c); + float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0); + result = 0.5 * A * A *(1.0 + B * B); + } + else { + result = 1.0; /* TIR (no refracted component) */ + } + + return result; +} + + +/* ------- Energy Conversion for lights ------- */ +/* from Sebastien Lagarde + * course_notes_moving_frostbite_to_pbr.pdf */ + +float sphere_energy(float radius) +{ + radius = max(radius, 1e-8); + return 0.25 * M_1_PI2 / (radius*radius) /* 1/(4*r²*Pi²) */ + * M_PI2 * 10.0; /* XXX : Empirical, Fit cycles power */ +} + +float disk_energy(float radius) +{ + radius = max(radius, 1e-8); + return M_1_PI2 / (radius*radius); /* 1/(r²*Pi²) */ +} + +float tube_energy(float radius, float width) +{ + radius = max(radius, 1e-8); + return 0.5 * M_1_PI2 / (radius * (width + 2 * radius)); /* 1/(4*r²*Pi²) + 1/(2*r*w*Pi²) */ +} + +float rectangle_energy(float width, float height) +{ + return M_1_PI / (width*height) /* 1/(w*h*Pi) */ + * 80.0; /* XXX : Empirical, Fit cycles power */ +} + +/* ------- Ambient Occlusion ------- */ +/* from Sebastien Lagarde + * course_notes_moving_frostbite_to_pbr.pdf */ + +float specular_occlusion(float NV, float AO, float roughness) +{ +#ifdef USE_SSAO + return saturate(pow(NV + AO, roughness) - 1.0 + AO); +#else + return 1.0; +#endif +} + +/* ----------- Parallax Correction -------------- */ + +void parallax_correct_ray(inout vec3 L) +{ +#ifdef CORRECTION_NONE + return; +#else + vec3 localray = (unfprobecorrectionmat * vec4(L, 0.0)).xyz; + vec3 localpos = (unfprobecorrectionmat * vec4(worldpos, 1.0)).xyz; + +#ifdef CORRECTION_BOX + /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ */ + vec3 firstplane = (vec3( 1.0) - localpos) / localray; + vec3 secondplane = (vec3(-1.0) - localpos) / localray; + vec3 furthestplane = max(firstplane, secondplane); + float dist = min(furthestplane.x, min(furthestplane.y, furthestplane.z)); +#endif + +#ifdef CORRECTION_ELLIPSOID + /* ray sphere intersection */ + float a = dot(localray, localray); + float b = dot(localray, localpos); + float c = dot(localpos, localpos) - 1; + + float dist = 1e15; + float determinant = b * b - a * c; + if (determinant >= 0) + dist = (sqrt(determinant) - b) / a; +#endif + + /* Use Distance in WS directly to recover intersection */ + vec3 intersection = worldpos + L * dist; + L = intersection - unfprobepos; +#endif +} + +/* ----------- Probe sampling wrappers -------------- */ + +void vector_prepass(vec3 viewpos, vec3 worldnor, mat4 invviewmat, mat4 viewmat) +{ + worldpos = (invviewmat * vec4(viewpos, 1.0)).xyz; + + shade_view(viewpos, viewi); + direction_transform_m4v3(viewi, invviewmat, I); + +#ifdef PLANAR_PROBE + /* View Normals */ + direction_transform_m4v3(worldnor, viewmat, viewnor); + + /* transposing plane orientation to view space */ + direction_transform_m4v3(unfplanarvec, viewmat, planarvec); + + planarfac.x = dot(planarvec, vec3(1.0, 0.0, 0.0)); + planarfac.y = dot(planarvec, vec3(0.0, 1.0, 0.0)); + planarfac.z = -viewpos.z + 1.0; + + vec4 proj = unfplanarreflectmat * vec4(worldpos, 1.0); + refpos = proj.xyz/proj.w; +#endif +} + +#if 0 +float distance_based_roughness(float dist_intersection_to_shaded, float dist_intersection_to_reflectioncam, float roughness) +{ + /* from Sebastien Lagarde + * course_notes_moving_frostbite_to_pbr.pdf */ + float newroughness = clamp(roughness * dist_intersection_to_shaded / dist_intersection_to_reflectioncam, 0, roughness); + return mix(newroughness, roughness, roughness); +} +#endif + +vec2 get_distorded_refl_uv(sampler2D planarprobe, vec2 Xi) +{ + vec2 distortion = vec2(dot(viewnor, vec3(1.0, 0.0, 0.0)) - planarfac.x, + dot(viewnor, vec3(0.0, 1.0, 0.0)) - planarfac.y); + distortion += Xi; + + /* modulate intensity by distance to the viewer and by distance to the reflected object */ + float dist_view_to_shaded = planarfac.z; + float dist_intersection_to_reflectioncam = texture2D(planarprobe, refpos.xy + Xi / dist_view_to_shaded).a; + float dist_intersection_to_shaded = dist_intersection_to_reflectioncam - dist_view_to_shaded; /* depth in alpha */ + + /* test in case of background */ + if (dist_intersection_to_shaded > 0.0) { + float distortion_scale = abs(dot(viewi * dist_intersection_to_shaded, -planarvec)); + distortion *= distortion_scale / (dist_view_to_shaded + 1.0); + } + + return refpos.xy + distortion; +} + +vec4 sample_probe_pdf(vec3 cubevec, float pdf) +{ + vec4 sample; + + float lod = unflodfactor - 0.5 * log2(pdf); + + parallax_correct_ray(cubevec); + sample = textureCubeLod(unfprobe, cubevec, lod); + + srgb_to_linearrgb(sample, sample); + return sample; +} + +vec4 sample_probe_pdf(sampler2D planarprobe, vec3 cubevec, float roughness, float pdf) +{ + vec4 sample; + + float lod = unflodfactor - 0.5 * log2(pdf); + + parallax_correct_ray(cubevec); + sample = textureCubeLod(unfprobe, cubevec, lod); + +#ifdef PLANAR_PROBE + vec4 sample_plane = vec4(0.0); + vec2 co = get_distorded_refl_uv(planarprobe, Ht.xy); + if (co.x > 0.0 && co.x < 1.0 && co.y > 0.0 && co.y < 1.0) + sample_plane = texture2DLod(planarprobe, co, lod); + else + sample_plane = sample; + sample = mix(sample_plane, sample, clamp(roughness * 2.0 - 0.5, 0.0, 1.0)); +#endif + + srgb_to_linearrgb(sample, sample); + return sample; +} + +vec4 sample_reflect_pdf(vec3 L, float roughness, float pdf) +{ + return sample_probe_pdf(unfreflect, L, roughness, pdf); +} + +vec4 sample_refract_pdf(vec3 L, float roughness, float pdf) +{ + return sample_probe_pdf(unfrefract, L, roughness, pdf); +} + +vec4 sample_probe(sampler2D planarprobe, vec3 cubevec) +{ + vec4 sample; + + /* Cubemap */ + parallax_correct_ray(cubevec); + sample = textureCube(unfprobe, cubevec); + +#ifdef PLANAR_PROBE + /* Planar */ + vec2 co = get_distorded_refl_uv(planarprobe, vec2(0.0)); + if (co.x > 0.0 && co.x < 1.0 && co.y > 0.0 && co.y < 1.0) + sample = texture2D(planarprobe, co); +#endif + + srgb_to_linearrgb(sample, sample); + return sample; +} + +vec4 sample_reflect(vec3 L) +{ + return sample_probe(unfreflect, L); +} + +vec4 sample_refract(vec3 L) +{ + return sample_probe(unfrefract, L); +} + +/* ------- Sampling Random Ray -------- */ + +void setup_noise(vec2 fragcoord) +{ + const int NOISE_SIZE = 64; + ivec2 texel = ivec2(mod(fragcoord.x, NOISE_SIZE), mod(fragcoord.y, NOISE_SIZE)); +#if __VERSION__ < 130 + jitternoise = texture2DLod(unfjitter, (vec2(texel) + 0.5) / float(NOISE_SIZE), 0.0).rg; /* Global variable */ +#else + jitternoise = texelFetch(unfjitter, texel, 0).rg; /* Global variable */ +#endif +} + +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 * BSDF_SAMPLES, BSDF_SAMPLES)); + +#if __VERSION__ < 130 + Xi.yz = texture1DLod(unflutsamples, (float(u) + 0.5) / float(BSDF_SAMPLES), 0.0).rg; /* Global variable */ +#else + Xi.yz = texelFetch(unflutsamples, u, 0).rg; /* Global variable */ +#endif + return Xi; +} + +vec3 hammersley_3d(float i) +{ + return hammersley_3d(i, unfbsdfsamples.y); +} + +/* ------- Screen Space Raycasting ---------*/ + +/* By Morgan McGuire and Michael Mara at Williams College 2014 + * Released as open source under the BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * http://casual-effects.blogspot.fr/2014/08/screen-space-ray-tracing.html */ +void swapIfBigger(inout float a, inout float b) +{ + if (a > b) { + float temp = a; + a = b; + b = temp; + } +} + +#if 1 /* Linear 2D raymarching */ + +/* 2D raycast */ +bool raycast(vec3 ray_origin, vec3 ray_dir, out float hitstep, out vec2 hitpixel, out vec3 hitco) +{ + /* ssr_parameters */ + float nearz = -unfclip.x; /* Near plane distance (Negative number) */ + float farz = -unfclip.y; /* Far plane distance (Negative number) */ + + /* Clip ray to a near plane in 3D */ + float ray_length = 1e16; + if ((ray_origin.z + ray_dir.z * ray_length) > nearz) + ray_length = (nearz - ray_origin.z) / ray_dir.z; + + vec3 ray_end = ray_dir * ray_length + ray_origin; + + /* Project into screen space */ + vec4 H0 = unfpixelprojmat * vec4(ray_origin, 1.0); + vec4 H1 = unfpixelprojmat * vec4(ray_end, 1.0); + + /* There are a lot of divisions by w that can be turned into multiplications + * at some minor precision loss...and we need to interpolate these 1/w values + * anyway. */ + float k0 = 1.0 / H0.w; + float k1 = 1.0 / H1.w; + + /* Switch the original points to values that interpolate linearly in 2D */ + vec3 Q0 = ray_origin * k0; + vec3 Q1 = ray_end * k1; + + /* Screen-space endpoints */ + vec2 P0 = H0.xy * k0; + vec2 P1 = H1.xy * k1; + + /* [Optional clipping to frustum sides here] */ + + /* Initialize to off screen */ + hitpixel = vec2(-1.0, -1.0); + + /* 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 */ + P1 += vec2((distance_squared(P0, P1) < 0.0001) ? 0.01 : 0.0); + + vec2 delta = P1 - P0; + + /* Permute so that the primary iteration is in x to reduce large branches later. + * After this, "x" is the primary iteration direction and "y" is the secondary one + * If it is a more-vertical line, create a permutation that swaps x and y in the output + * and directly swizzle the inputs. */ + bool permute = false; + if (abs(delta.x) < abs(delta.y)) { + permute = true; + delta = delta.yx; + P1 = P1.yx; + P0 = P0.yx; + } + + /* Track the derivatives */ + float step_sign = sign(delta.x); + float invdx = step_sign / delta.x; + vec2 dP = vec2(step_sign, invdx * delta.y); + vec3 dQ = (Q1 - Q0) * invdx; + float dk = (k1 - k0) * invdx; + + /* Slide each value from the start of the ray to the end */ + vec4 pqk = vec4(P0, Q0.z, k0); + + /* Scale derivatives by the desired pixel stride */ + vec4 dPQK = vec4(dP, dQ.z, dk) * 1.0; + + bool hit = false; + + /* We track the ray depth at +/- 1/2 pixel to treat pixels as clip-space solid + * voxels. Because the depth at -1/2 for a given pixel will be the same as at + * +1/2 for the previous iteration, we actually only have to compute one value + * per iteration. */ + float prev_zmax = ray_origin.z; + float zmax, zmin; + + /* P1.x is never modified after this point, so pre-scale it by + * the step direction for a signed comparison */ + float end = P1.x * step_sign; + + for (hitstep = 0.0; hitstep < unfssrparam.x && !hit; hitstep++) + { + /* Ray finished & no hit*/ + if ((pqk.x * step_sign) > end) break; + + /* step through current cell */ + pqk += dPQK; + + hitpixel = permute ? pqk.yx : pqk.xy; + zmin = prev_zmax; + zmax = (dPQK.z * 0.5 + pqk.z) / (dPQK.w * 0.5 + pqk.w); + prev_zmax = zmax; + swapIfBigger(zmin, zmax); + + float frontface = frontface_depth_linear(ivec2(hitpixel), 0); + + if (zmax < frontface) { + /* Below surface */ +#ifdef USE_BACKFACE + float backface = backface_depth_linear(ivec2(hitpixel), 0); +#else + float backface = frontface - unfssrparam.z; +#endif + hit = (zmin > backface); + } + } + + /* Hit coordinate in 3D */ + hitco = (Q0 + dQ * hitstep) / pqk.w; + + return hit; +} + +#else /* Hierarchical raymarching */ + +vec3 point_on_line(vec3 origin, vec3 direction, float dist) +{ + return origin + direction * dist; +} + +vec2 get_cell(vec2 ray, vec2 cellcount) +{ + return floor(ray * cellcount); +} + +vec3 intersect_cell_boundary(vec3 o, vec3 d, vec2 cell, vec2 cellcount, vec2 crossstep, vec2 crossoffset) +{ + vec2 newcell = ((cell + crossstep) / cellcount) + crossoffset; + vec2 delta = (newcell - o.xy) / d.xy; + float t = min(delta.x, delta.y); + + return point_on_line(o, d, t); +} + +vec2 get_cell_count(float level) +{ + return floor(unfclip.zw / exp2(level)); +} + +bool crossed_cell_boundary(vec2 a, vec2 b) +{ + return (a.x != b.x) || (a.y != b.y); +} + +#define HIZ_MAX_LEVEL 8.0 + +bool raycast(vec3 ray_origin, vec3 ray_dir, out float hitstep, out vec2 hitpixel, out vec3 hitco) +{ + float miplvl = 0.0; /* Start level */ + vec2 cellcount = get_cell_count(0.0); + + /* Invert Z component so we can work with the raw depth buffer which is positive */ + ray_dir.z *= -1; + + /* scale vector such that z is 1.0f (maximum depth) */ + ray_dir = ray_dir.xyz / abs(ray_dir.z); + + vec2 crossstep, crossoffset; + vec2 cross_epsilon = vec2(0.2) / cellcount; /* Enough to get to the next cell */ + crossstep.x = (ray_dir.x > 0.0) ? 1.0 : -1.0; + crossstep.y = (ray_dir.y > 0.0) ? 1.0 : -1.0; + crossoffset = crossstep * cross_epsilon; + crossstep = saturate(crossstep); + + /* set current ray to original screen coordinate and depth */ + vec3 ray; + ray.xy = uv_from_position(ray_origin); + ray.z = frontface_depth(ivec2(ray.xy * cellcount), int(miplvl)); + + /* project ray origin to the near clip plane */ + vec3 o = point_on_line(ray, ray_dir, -ray.z); + + /* Cross first cell (texel) to not get self-intersection */ + vec2 cell = get_cell(ray.xy, cellcount); + ray = intersect_cell_boundary(o, ray_dir, cell, cellcount, crossstep, crossoffset); + + for (hitstep = 0.0; hitstep < unfssrparam.x && miplvl >= 0.0; hitstep++) + { + cellcount = get_cell_count(miplvl); + cell = get_cell(ray.xy, cellcount); + + float frontface = frontface_depth(ivec2(cell), int(miplvl)); + + /* Try intersecting the depth plane + * or stay in place if there is an intersection */ + vec3 raytmp = point_on_line(o, ray_dir, max(ray.z, frontface)); + /* Go to the next cell and go up a level */ + vec2 celltmp = get_cell(raytmp.xy, cellcount); + + /* If ray crossed a cell then it's not blocked */ + if (crossed_cell_boundary(cell, celltmp)) { + /* Go to the next cell and go up a level */ + raytmp = intersect_cell_boundary(o, ray_dir, cell, cellcount, crossstep, crossoffset); + miplvl = min(HIZ_MAX_LEVEL, miplvl + 2.0); + } + + ray = raytmp; + --miplvl; + } + + hitpixel = ray.xy * unfclip.zw; + hitco = position_from_depth(ray.xy, linear_depth(ray.z)); + + return (miplvl < 0.0 && ray.z < 1.0 && ray.z > 0.0 && ray_dir.z > 0 && ray.x > 0 && ray.x < 1 && ray.y > 0 && ray.y < 1); +} +#endif + +float ssr_contribution(vec3 ray_origin, float hitstep, bool hit, inout vec3 hitco) +{ + /* ssr_parameters */ + float maxstep = unfssrparam.x; /* Maximum number of iteration when raymarching */ + float attenuation = unfssrparam.y; /* Attenuation factor for screen edges and ray step fading */ + + /* ray step fade */ + float stepfade = saturate((1.0 - hitstep / maxstep) * attenuation); + + /* screen edges fade */ + vec4 co = gl_ProjectionMatrix * vec4(hitco, 1.0); + co.xy /= co.w; + hitco.xy = co.xy * 0.5 + 0.5; + float maxdimension = saturate(max(abs(co.x), abs(co.y))); + float screenfade = saturate((0.999999 - maxdimension) * attenuation); + + return smoothstep(0.0, 1.0, stepfade * screenfade) * float(hit); +} diff --git a/source/blender/gpu/shaders/gpu_shader_probe_sh_compute_frag.glsl b/source/blender/gpu/shaders/gpu_shader_probe_sh_compute_frag.glsl new file mode 100644 index 00000000000..6bf60407f57 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_probe_sh_compute_frag.glsl @@ -0,0 +1,108 @@ +uniform samplerCube probe; + +#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))); + +float srgb_to_linearrgb(float c) +{ + if(c < 0.04045) + return (c < 0.0) ? 0.0: c * (1.0 / 12.92); + else + return pow((c + 0.055)*(1.0/1.055), 2.4); +} + +void srgb_to_linearrgb(vec4 col_from, out vec4 col_to) +{ + col_to.r = srgb_to_linearrgb(col_from.r); + col_to.g = srgb_to_linearrgb(col_from.g); + col_to.b = srgb_to_linearrgb(col_from.b); + col_to.a = col_from.a; +} + +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); +} + +void main() +{ + const float pixstep = 1.0 / CUBEMAP_RES; + const float halfpix = pixstep / 2.0; + + vec2 pos = ceil(gl_FragCoord.xy); + + if (pos.x > 3.0 || pos.y > 3.0) { + gl_FragColor = vec4(0.0); + return; + } + + int shnbr = int(pos.x + (pos.y - 1) * 3); + float 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 shcoef; + + vec2 facecoord = vec2(x,y); + vec3 cubevec = get_cubemap_vector(facecoord, face); + float weight = texel_solid_angle(facecoord, halfpix); + + if (shnbr == 1) shcoef = 0.282095; + else if (shnbr == 2) shcoef = -0.488603 * cubevec.z * 2.0 / 3.0; + else if (shnbr == 3) shcoef = 0.488603 * cubevec.y * 2.0 / 3.0; + else if (shnbr == 4) shcoef = -0.488603 * cubevec.x * 2.0 / 3.0; + else if (shnbr == 5) shcoef = 1.092548 * cubevec.x * cubevec.z * 1.0 / 4.0; + else if (shnbr == 6) shcoef = -1.092548 * cubevec.z * cubevec.y * 1.0 / 4.0; + else if (shnbr == 7) shcoef = 0.315392 * (3.0 * cubevec.y * cubevec.y - 1.0) * 1.0 / 4.0; + else if (shnbr == 8) shcoef = 1.092548 * cubevec.x * cubevec.y * 1.0 / 4.0; + else /* (shnbr == 9) */ shcoef = 0.546274 * (cubevec.x * cubevec.x - cubevec.z * cubevec.z) * 1.0 / 4.0; + + vec4 sample = textureCubeLod(probe, cubevec, 0.0); + srgb_to_linearrgb(sample, sample); + sh += sample.rgb * shcoef * weight; + accum += weight; + } + } + } + + sh *= M_4PI / accum; + + gl_FragColor = vec4(sh, 1.0); +}
\ No newline at end of file diff --git a/source/blender/gpu/shaders/gpu_shader_probe_sh_compute_vert.glsl b/source/blender/gpu/shaders/gpu_shader_probe_sh_compute_vert.glsl new file mode 100644 index 00000000000..9f5e788d902 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_probe_sh_compute_vert.glsl @@ -0,0 +1,5 @@ +void main() +{ + /* We are using gl_FragCoord inside the fragment shader so nothing fancy here */ + gl_Position = gl_Vertex; +} diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index f7ee1ff3915..e518f250aa8 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -165,7 +165,7 @@ typedef struct Scopes { #define SCOPES_WAVEFRM_RGB 5 typedef struct ColorManagedViewSettings { - int flag, pad; + int flag, lut_is_outdated; char look[64]; /* look which is being applied when displaying buffer on the screen (prior to view transform) */ char view_transform[64]; /* view transform which is being applied when displaying buffer on the screen */ float exposure; /* fstop exposure */ @@ -176,6 +176,7 @@ typedef struct ColorManagedViewSettings { typedef struct ColorManagedDisplaySettings { char display_device[64]; + int lut_is_outdated, pad; } ColorManagedDisplaySettings; typedef struct ColorManagedColorspaceSettings { diff --git a/source/blender/makesdna/DNA_gpu_types.h b/source/blender/makesdna/DNA_gpu_types.h index 967cb7284dc..1e82fdcd10d 100644 --- a/source/blender/makesdna/DNA_gpu_types.h +++ b/source/blender/makesdna/DNA_gpu_types.h @@ -32,6 +32,8 @@ #ifndef __DNA_GPU_TYPES_H__ #define __DNA_GPU_TYPES_H__ +/* ********** GPU POST FX *********** */ + /* properties for dof effect */ typedef struct GPUDOFSettings { float focus_distance; /* focal distance for depth of field */ @@ -49,20 +51,57 @@ typedef struct GPUSSAOSettings { float distance_max; float attenuation; int samples; /* ray samples, we use presets here for easy control instead of */ - int pad; + int steps; } GPUSSAOSettings; typedef struct GPUFXSettings { GPUDOFSettings *dof; GPUSSAOSettings *ssao; char fx_flag; /* eGPUFXFlags */ - char pad[7]; + char fx_flag2; /* eGPUFXFlags */ + char pad[6]; } GPUFXSettings; /* shaderfx enables */ typedef enum eGPUFXFlags { - GPU_FX_FLAG_DOF = (1 << 0), - GPU_FX_FLAG_SSAO = (1 << 1), + GPU_FX_FLAG_DOF = (1 << 0), + GPU_FX_FLAG_SSAO = (1 << 1), + GPU_FX_FLAG_COLORMANAGEMENT = (1 << 2), } eGPUFXFlags; +/* ********** GPU PBR *********** */ + +/* Screen space reflection settings */ +typedef struct GPUSSRSettings { + float attenuation; + float thickness; + int steps; + int pad; +} GPUSSRSettings; + +/* Material surfaces and sampling settings */ +typedef struct GPUBRDFSettings { + float lodbias; + float pad; + int samples; + int pad2; +} GPUBRDFSettings; + +typedef struct GPUPBRSettings { + GPUBRDFSettings *brdf; + GPUSSRSettings *ssr; + GPUSSAOSettings *ssao; + char pbr_flag; /* eGPUPBRFlags */ + char pad[7]; +} GPUPBRSettings; + +/* pbrshader enables */ +typedef enum eGPUPBRFlags { + GPU_PBR_FLAG_ENABLE = (1 << 0), + GPU_PBR_FLAG_SSR = (1 << 1), + GPU_PBR_FLAG_SSAO = (1 << 2), + GPU_PBR_FLAG_BACKFACE = (1 << 3), + GPU_PBR_FLAG_LAYER_OVERRIDE = (1 << 4), +} eGPUPBRFlags; + #endif /* __DNA_GPU_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index b4bc26f45cd..47a41212996 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -156,6 +156,10 @@ typedef struct Image { struct Stereo3dFormat *stereo3d_format; RenderSlot render_slots[8]; /* 8 = IMA_MAX_RENDER_SLOT */ + + short last_projection; + short is_envmap; + float SH_Coefs[9][3]; } Image; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 46b30f41f5b..3a76c7f1063 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -752,6 +752,7 @@ typedef struct NodeTexEnvironment { ImageUser iuser; int color_space; int projection; + struct GPUNodeLink *normal_transform_link; int interpolation; int pad; } NodeTexEnvironment; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index d24c7faa9f5..85903cabd1a 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -286,9 +286,10 @@ typedef struct Object { unsigned int init_state; /* bit masks of initial state as recorded by the users */ ListBase gpulamp; /* runtime, for glsl lamp display only */ + ListBase gpuprobe; /* runtime, for glsl reflections */ ListBase pc_ids; ListBase *duplilist; /* for temporary dupli list storage, only for use by RNA API */ - + struct RigidBodyOb *rigidbody_object; /* settings for Bullet rigid body */ struct RigidBodyCon *rigidbody_constraint; /* settings for Bullet constraint */ @@ -299,6 +300,23 @@ typedef struct Object { LodLevel *currentlod; struct PreviewImage *preview; + + /* Probe options */ + struct Object *probe; /* the probe object used for rendering it's materials */ + struct Object *parallaxcorrect; /* the parallax bounding object used for rendering */ + struct Object *reflectionplane; + + char probeparallax; + char probeflags; + short probetype; + + float probeclipsta; + float probeclipend; + unsigned int probesize; + unsigned int probeshres; + + float probeclipbias; + int pad3[2]; } Object; /* Warning, this is not used anymore because hooks are now modifiers */ @@ -489,6 +507,27 @@ enum { OB_LOD_USE_HYST = 1 << 2, }; +/* (short) probe type */ +enum { + OB_PROBE_OBJECT = 1, + OB_PROBE_CUBEMAP = 2, + OB_PROBE_PLANAR = 3, +}; + +/* (short) probe parallax */ +enum { + OB_PROBE_PARRALAX_ELLIPSOID = 1, + OB_PROBE_PARRALAX_BOX = 2, +}; + +/* (short) probeflags */ +enum { + OB_PROBE_AUTO_UPDATE = 1 << 0, + OB_PROBE_DOUBLE_UPDATE = 1 << 1, + OB_PROBE_COMPUTE_SH = 1 << 2, + OB_PROBE_USE_LAYERS = 1 << 3, +}; + /* **************** BASE ********************* */ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 4c243507e82..dbb5f102d14 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -45,6 +45,7 @@ struct SmoothView3DStore; struct wmTimer; struct Material; struct GPUFX; +struct GPUSSR; /* This is needed to not let VC choke on near and far... old * proprietary MS extensions... */ @@ -238,6 +239,11 @@ typedef struct View3D { float stereo3d_volume_alpha; float stereo3d_convergence_alpha; + /* Pbr */ + struct Object *probe_source; /* runtime : the probe that is being updated when V3D_PROBE_CAPTURE */ + struct GPUPBRSettings pbr_settings; + struct GPUPBR *pbr; /* holds all pbr specific textures */ + /* Previous viewport draw type. * Runtime-only, set in the rendered viewport toggle operator. */ @@ -319,6 +325,10 @@ typedef struct View3D { /* View3d->flag3 (short) */ #define V3D_SHOW_WORLD (1 << 0) +#define V3D_SHOW_WORLD_DIFFUSE (1 << 1) +/*#define V3D_REALISTIC_MAT (1 << 2)*/ /* UNUSED */ +#define V3D_PROBE_CAPTURE (1 << 3) /* runtime flag */ +#define V3D_FLIP_NORMALS (1 << 4) /* invert culling during reflection pass */ /* View3D->around */ enum { diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index 5fd4c9fd407..ecfe53cae12 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -129,6 +129,12 @@ typedef struct World { struct bNodeTree *nodetree; ListBase gpumaterial; /* runtime */ + ListBase gpuprobe; /* runtime */ + + char probeflags, pad2[3]; + + unsigned int probesize, probeshres; + float pad3; } World; /* **************** WORLD ********************* */ @@ -200,5 +206,11 @@ enum { */ #define WO_DS_SHOW_TEXS (1<<2) +/* (short) probeflags */ +enum { + WO_PROBE_AUTO_UPDATE = 1 << 0, + WO_PROBE_COMPUTE_SH = 1 << 1, +}; + #endif diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 24f2d8174af..6351b4ebeeb 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -434,10 +434,13 @@ static EnumPropertyItem *rna_ColorManagedDisplaySettings_display_device_itemf( return items; } -static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) { ID *id = ptr->id.data; + ColorManagedDisplaySettings *display_settings = &scene->display_settings; + display_settings->lut_is_outdated = 1; + if (!id) return; @@ -655,9 +658,12 @@ static char *rna_ColorManagedInputColorspaceSettings_path(PointerRNA *UNUSED(ptr return BLI_sprintfN("colorspace_settings"); } -static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) { ID *id = ptr->id.data; + + ColorManagedViewSettings *view_settings = &scene->view_settings; + view_settings->lut_is_outdated = 1; if (!id) return; diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 6530e0938f6..2d967e544d6 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -246,7 +246,7 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f } GPU_create_gl_tex(bind, ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, GL_TEXTURE_2D, - (filter != GL_NEAREST && filter != GL_LINEAR), false, image); + (filter != GL_NEAREST && filter != GL_LINEAR), false, image, false); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 2cbf23973c2..194bb1eaa14 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -53,6 +53,7 @@ #include "RNA_enum_types.h" #include "rna_internal.h" +#include "GPU_shader.h" /* needed for MAX_SH_SAMPLES */ #include "BLI_sys_types.h" /* needed for intptr_t used in ED_mesh.h */ #include "ED_mesh.h" @@ -197,11 +198,88 @@ EnumPropertyItem rna_enum_object_axis_items[] = { #include "ED_curve.h" #include "ED_lattice.h" + static void rna_Object_internal_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { DAG_id_tag_update(ptr->id.data, OB_RECALC_OB); } +static int rna_Object_probe_object_poll(PointerRNA *ptr, PointerRNA value) +{ + Object *ob = (Object *)ptr->id.data; + Object *probe = (Object *)value.data; + + if (probe) { + if (probe->probetype == OB_PROBE_CUBEMAP || probe->probetype == OB_PROBE_PLANAR) { + if (probe != ob) { + if (ob->probetype == OB_PROBE_PLANAR) { + if (probe->probetype == OB_PROBE_CUBEMAP) + return 1; + } + else { + return 1; + } + } + } + } + + return 0; +} + +static PointerRNA rna_Object_probe_object_get(PointerRNA *ptr) +{ + Object *ob = (Object *)ptr->id.data; + Object *probe = ob->probe; + + if (probe) + return rna_pointer_inherit_refine(ptr, &RNA_Object, probe); + + return rna_pointer_inherit_refine(ptr, NULL, NULL); +} + +static void rna_Object_probe_object_set(PointerRNA *ptr, PointerRNA value) +{ + Object *ob = (Object *)ptr->id.data; + Object *probe = (Object *)value.data; + + if (probe) { + if (probe->probetype == OB_PROBE_CUBEMAP || probe->probetype == OB_PROBE_PLANAR) { + if (probe != ob) { + ob->probe = probe; + id_lib_extern((ID *)probe); + } + } + } + else { + ob->probe = NULL; + } +} + +static void rna_Object_probe_sh_res_set(PointerRNA *ptr, int value) +{ + Object *ob = (Object *)ptr->id.data; + + CLAMP(value, 1, (1 << MAX_SH_SAMPLES)); + CLAMP_MAX(value, ob->probesize); + /* Jumping to next value based on difference so user can use UI */ + if (value < ob->probeshres) + ob->probeshres = power_of_2_min_u(value); + else + ob->probeshres = power_of_2_max_u(value); +} + +static void rna_Object_probe_size_set(PointerRNA *ptr, int value) +{ + Object *ob = (Object *)ptr->id.data; + + CLAMP(value, 16, 10240); + ob->probesize = value; + ob->probesize &= (~15); /* round to multiple of 16 */ + + if (ob->probeshres > ob->probesize) + rna_Object_probe_sh_res_set(ptr, ob->probesize); +} + static void rna_Object_matrix_world_update(Main *bmain, Scene *scene, PointerRNA *ptr) { /* don't use compat so we get predictable rotation */ @@ -2200,7 +2278,22 @@ static void rna_def_object(BlenderRNA *brna) "Axis Angle (W+XYZ), defines a rotation around some axis defined by 3D-Vector"}, {0, NULL, 0, NULL, NULL} }; + + static EnumPropertyItem probemode_items[] = { + {0, "NONE", 0, "None", "No probe capture"}, + {OB_PROBE_OBJECT, "OBJECT", 0, "Object", "Use another object as probe"}, + {OB_PROBE_CUBEMAP, "CUBE", 0, "Cubemap", "Capture environment in all direction from the object center"}, + {OB_PROBE_PLANAR, "PLANE", 0, "Planar", "Capture environment from the symmetry camera to the XY axis plane of the object"}, + {0, NULL, 0, NULL, NULL} + }; + static EnumPropertyItem probeparallaxmode_items[] = { + {0, "NONE", 0, "None", "No parallax correction"}, + {OB_PROBE_PARRALAX_ELLIPSOID, "ELLIPSOID", 0, "Ellipsoid", "Use object bounding ellipsoid for parallax correction"}, + {OB_PROBE_PARRALAX_BOX, "BOX", 0, "Cube", "Use object bounding box for parallax correction"}, + {0, NULL, 0, NULL, NULL} + }; + static float default_quat[4] = {1, 0, 0, 0}; /* default quaternion values */ static float default_axisAngle[4] = {0, 0, 1, 0}; /* default axis-angle rotation values */ static float default_scale[3] = {1, 1, 1}; /* default scale values */ @@ -2837,6 +2930,97 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Level of Detail Levels", "A collection of detail levels to automatically switch between"); RNA_def_property_update(prop, NC_OBJECT | ND_LOD, NULL); + /* Viewport Probe */ + prop = RNA_def_property(srna, "probe_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "probetype"); + RNA_def_property_enum_items(prop, probemode_items); + RNA_def_property_ui_text(prop, "Probe Capture Type", "Type of capture for to use for the BSDFs"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "probe_object", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_pointer_sdna(prop, NULL, "probe"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Probe Object", + "Probe object that defines the environment for the BSDFs of this object's materials"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + RNA_def_property_pointer_funcs(prop, "rna_Object_probe_object_get", "rna_Object_probe_object_set", NULL, + "rna_Object_probe_object_poll"); + + prop = RNA_def_property(srna, "probe_reflection_plane", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_pointer_sdna(prop, NULL, "reflectionplane"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Reflection Plane", + "Use this object XY plane as the symmetry plane for the reflected camera"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + + prop = RNA_def_property(srna, "probe_parallax_volume", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_pointer_sdna(prop, NULL, "parallaxcorrect"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Parallax Volume", + "Use object bounds to correct reflection & refraction rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + + prop = RNA_def_property(srna, "probe_parallax_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "probeparallax"); + RNA_def_property_enum_items(prop, probeparallaxmode_items); + RNA_def_property_ui_text(prop, "Probe Parallax Type", "Parallax correction to apply to the rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + + prop = RNA_def_property(srna, "probe_refresh_auto", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "probeflags", OB_PROBE_AUTO_UPDATE); + RNA_def_property_ui_text(prop, "Probe Auto Refresh", "Cube Only : Auto update when a change in the scene occurs"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + + prop = RNA_def_property(srna, "probe_refresh_double", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "probeflags", OB_PROBE_DOUBLE_UPDATE); + RNA_def_property_ui_text(prop, "Probe Double Refresh", "Update the probe another time after all other probes have been updated"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + + prop = RNA_def_property(srna, "probe_compute_sh", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "probeflags", OB_PROBE_COMPUTE_SH); + RNA_def_property_ui_text(prop, "Compute Diffuse", "Cube Only : Enable computation of diffuse lighting"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + + prop = RNA_def_property(srna, "probe_use_layers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "probeflags", OB_PROBE_USE_LAYERS); + RNA_def_property_ui_text(prop, "Use Object Layers", "Render only the objects in the same layers"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + + prop = RNA_def_property(srna, "probe_size", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "probesize"); + RNA_def_property_range(prop, 16, 2048); + RNA_def_property_ui_text(prop, "Reflection Quality", "Resolution of the probe buffer texture"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + RNA_def_property_int_funcs(prop, NULL, "rna_Object_probe_size_set", NULL); + + prop = RNA_def_property(srna, "probe_sh_quality", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "probeshres"); + RNA_def_property_range(prop, 1, (1 << MAX_SH_SAMPLES)); + RNA_def_property_ui_text(prop, "Diffuse Quality", "Cube Only : Resolution of the diffuse precomputation."); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + RNA_def_property_int_funcs(prop, NULL, "rna_Object_probe_sh_res_set", NULL); + + prop = RNA_def_property(srna, "probe_clip_start", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "probeclipsta"); + RNA_def_property_range(prop, 0.0001f, 999999.9f); + RNA_def_property_ui_text(prop, "Clip Start", "Capture camera near clip plane"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + + prop = RNA_def_property(srna, "probe_clip_end", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "probeclipend"); + RNA_def_property_range(prop, 0.0001f, 999999.9f); + RNA_def_property_ui_text(prop, "Clip End", "Capture camera end clip plane"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + + prop = RNA_def_property(srna, "probe_clip_bias", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "probeclipbias"); + RNA_def_property_range(prop, 0.0f, 999999.9f); + RNA_def_property_ui_text(prop, "Clip Bias", "Bias applied to the clip plane"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update"); + RNA_api_object(srna); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index f2a1e0a50ab..fef9435b567 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -4842,8 +4842,12 @@ static void rna_def_gpu_ssao_fx(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Color", "Color for screen space ambient occlusion effect"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); -} + prop = RNA_def_property(srna, "steps", PROP_INT, PROP_NONE); + RNA_def_property_ui_text(prop, "Steps", "Number of steps per samples. Helps detecting thin objects when using a large occlusion distance."); + RNA_def_property_range(prop, 1, 16); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); +} static void rna_def_gpu_fx(BlenderRNA *brna) { @@ -4878,6 +4882,12 @@ static void rna_def_gpu_fx(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_SSAO); RNA_def_property_ui_text(prop, "SSAO", "Use screen space ambient occlusion of field on viewport"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update"); + + + prop = RNA_def_property(srna, "use_colormanagement", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "fx_flag2", GPU_FX_FLAG_COLORMANAGEMENT); + RNA_def_property_ui_text(prop, "Color Management", "Use color management on viewport"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUFXSettings_fx_update"); } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 1c8d4a4c818..074fc9f68bd 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -46,6 +46,8 @@ #include "DNA_mask_types.h" #include "DNA_view3d_types.h" +#include "GPU_pbr.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -526,6 +528,23 @@ static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *scene, Poi ED_view3d_shade_update(bmain, scene, v3d, sa); } +static void rna_SpaceView3D_viewport_real_shading_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + View3D *v3d = (View3D *)(ptr->data); + ScrArea *sa = rna_area_from_space(ptr); + GPU_materials_free(); + ED_view3d_shade_update(bmain, scene, v3d, sa); +} + +static void rna_SpaceView3D_world_background_shader_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + View3D *v3d = (View3D *)(ptr->data); + ScrArea *sa = rna_area_from_space(ptr); + World *world = scene->world; + GPU_material_free(&world->gpumaterial); + ED_view3d_shade_update(bmain, scene, v3d, sa); +} + static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { View3D *v3d = (View3D *)(ptr->data); @@ -733,6 +752,15 @@ static EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf(bContext *UNUSED( return stereo3d_camera_items; } + +static void rna_GPUPBRSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + GPUPBRSettings *pbr_settings = ptr->data; + + GPU_pbr_settings_validate(pbr_settings); +} + + /* Space Image Editor */ static PointerRNA rna_SpaceImageEditor_uvedit_get(PointerRNA *ptr) @@ -2297,6 +2325,108 @@ static void rna_def_backgroundImages(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove all background images"); } +static void rna_def_gpu_pbr_brdf(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "GPUBRDFSettings", NULL); + RNA_def_struct_ui_text(srna, "GPU Sampling", "Settings for GLSL materials and lights sampling"); + RNA_def_struct_ui_icon(srna, ICON_MATERIAL); + + prop = RNA_def_property(srna, "lodbias", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Bias", "Bias the LOD sampled by the ray. Higher values give more correct but noisy results."); + RNA_def_property_range(prop, -100.0f, 100.0f); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "samples", PROP_INT, PROP_NONE); + RNA_def_property_ui_text(prop, "Quality", "Define the quality of brdfs sampling."); + RNA_def_property_range(prop, 1, 1024); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); +} + +static void rna_def_gpu_pbr_ssr(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "GPUSSRSettings", NULL); + RNA_def_struct_ui_text(srna, "GPU SSR", "Settings for GPU based screen space reflections"); + RNA_def_struct_ui_icon(srna, ICON_MATERIAL); + + prop = RNA_def_property(srna, "attenuation", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Attenuation", "Attenuation for distance and screen border fade"); + RNA_def_property_range(prop, 1.0f, 20.0f); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Thickness", "If Backface Buffer is off, tells how thick a pixel is when searching for intersections."); + RNA_def_property_range(prop, 0.00001f, 100000.0f); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "steps", PROP_INT, PROP_NONE); + RNA_def_property_ui_text(prop, "Steps", "Number of pixels to travel for searching intersections"); + RNA_def_property_range(prop, 1, 256); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); +} + +static void rna_def_gpu_pbr(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + rna_def_gpu_pbr_brdf(brna); + rna_def_gpu_pbr_ssr(brna); + + srna = RNA_def_struct(brna, "GPUPBRSettings", NULL); + RNA_def_struct_ui_text(srna, "GPU PBR Settings", "Settings for GLSL PBR materials"); + RNA_def_struct_ui_icon(srna, ICON_MATERIAL); + + /* BRDF */ + prop = RNA_def_property(srna, "brdf", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "GPUBRDFSettings"); + RNA_def_property_ui_text(prop, "PBR Sampling settings", ""); + + prop = RNA_def_property(srna, "use_realistic_mat", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pbr_flag", GPU_PBR_FLAG_ENABLE); + RNA_def_property_ui_text(prop, "Realistic Material Preview", "Use a more accurate preview of the shaders in the viewport"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUPBRSettings_update"); + + /* SSR */ + prop = RNA_def_property(srna, "ssr", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "GPUSSRSettings"); + RNA_def_property_ui_text(prop, "Screen Space Reflections settings", ""); + + prop = RNA_def_property(srna, "use_ssr", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pbr_flag", GPU_PBR_FLAG_SSR); + RNA_def_property_ui_text(prop, "Screen Space Reflections", "Use screen data to reflect objects"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUPBRSettings_update"); + + /* SSAO */ + prop = RNA_def_property(srna, "ssao", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "GPUSSAOSettings"); + RNA_def_property_ui_text(prop, "Screen Space Ambient Occlusion settings", ""); + + prop = RNA_def_property(srna, "use_ssao", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pbr_flag", GPU_PBR_FLAG_SSAO); + RNA_def_property_ui_text(prop, "Material Ambient Occlusion", "Use Material Ambient Occlusion"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUPBRSettings_update"); + + /* Backface buffer */ + prop = RNA_def_property(srna, "use_backface", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pbr_flag", GPU_PBR_FLAG_BACKFACE); + RNA_def_property_ui_text(prop, "Use Backface Buffer", "Enable the calculation of pixel thickness"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUPBRSettings_update"); + + /* Material Override */ + prop = RNA_def_property(srna, "use_layer_override", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pbr_flag", GPU_PBR_FLAG_LAYER_OVERRIDE); + RNA_def_property_ui_text(prop, "Render Layer Override", "Use render layer override"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUPBRSettings_update"); +} static void rna_def_space_view3d(BlenderRNA *brna) { @@ -2567,6 +2697,11 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "World Background", "Display world colors in the background"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_world_sh", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag3", V3D_SHOW_WORLD_DIFFUSE); + RNA_def_property_ui_text(prop, "Use Diffuse Background", "Show diffuse world lighting in the background"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_world_background_shader_update"); + prop = RNA_def_property(srna, "use_occlude_geometry", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_ZBUF_SELECT); RNA_def_property_ui_text(prop, "Occlude Geometry", "Limit selection to visible (clipped with depth buffer)"); @@ -2706,6 +2841,10 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "FX Options", "Options used for real time compositing"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "pbr_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "PBR Options", "Options used for advance glsl shading"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + /* Stereo Settings */ prop = RNA_def_property(srna, "stereo_3d_eye", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "multiview_eye"); @@ -4737,6 +4876,8 @@ static void rna_def_space_clip(BlenderRNA *brna) void RNA_def_space(BlenderRNA *brna) { + rna_def_gpu_pbr(brna); + rna_def_space(brna); rna_def_space_image(brna); rna_def_space_sequencer(brna); diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index 7c1ef6b0d87..2f9d21106cd 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -36,6 +36,8 @@ #include "DNA_texture_types.h" #include "DNA_world_types.h" +#include "GPU_shader.h" /* needed for MAX_SH_SAMPLES */ + #include "WM_types.h" #ifdef RNA_RUNTIME @@ -47,6 +49,8 @@ #include "BKE_main.h" #include "BKE_texture.h" +#include "BLI_math_base.h" + #include "ED_node.h" #include "WM_api.h" @@ -56,6 +60,30 @@ static PointerRNA rna_World_lighting_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_WorldLighting, ptr->id.data); } +static void rna_World_probe_sh_res_set(PointerRNA *ptr, int value) +{ + World *wo = (World *)ptr->id.data; + + CLAMP(value, 1, (1 << MAX_SH_SAMPLES)); + CLAMP_MAX(value, wo->probesize); + /* Jumping to next value based on difference so user can use UI */ + if (value < wo->probeshres) + wo->probeshres = power_of_2_min_u(value); + else + wo->probeshres = power_of_2_max_u(value); +} + +static void rna_World_probe_size_set(PointerRNA *ptr, int value) +{ + World *wo = (World *)ptr->id.data; + + CLAMP(value, 16, 10240); + wo->probesize = value; + wo->probesize &= (~15); /* round to multiple of 16 */ + + if (wo->probeshres > wo->probesize) + rna_World_probe_sh_res_set(ptr, wo->probesize); +} static PointerRNA rna_World_mist_get(PointerRNA *ptr) { @@ -529,6 +557,31 @@ void RNA_def_world(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the world"); RNA_def_property_update(prop, 0, "rna_World_use_nodes_update"); + /* viewport probes */ + prop = RNA_def_property(srna, "probe_refresh_auto", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "probeflags", WO_PROBE_AUTO_UPDATE); + RNA_def_property_ui_text(prop, "Probe Auto Refresh", "Auto update"); + RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update"); + + prop = RNA_def_property(srna, "probe_compute_sh", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "probeflags", WO_PROBE_COMPUTE_SH); + RNA_def_property_ui_text(prop, "Compute Diffuse", "Enable computation of diffuse lighting"); + RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update"); + + prop = RNA_def_property(srna, "probe_size", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "probesize"); + RNA_def_property_range(prop, 16, 2048); + RNA_def_property_ui_text(prop, "Buffer Size", "Resolution of the probe buffer texture"); + RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update"); + RNA_def_property_int_funcs(prop, NULL, "rna_World_probe_size_set", NULL); + + prop = RNA_def_property(srna, "probe_sh_quality", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "probeshres"); + RNA_def_property_range(prop, 1, (1 << MAX_SH_SAMPLES)); + RNA_def_property_ui_text(prop, "Irradiance Precision", "Resolution of the diffuse precomputation. Should not be higher than the buffer size"); + RNA_def_property_update(prop, NC_WORLD | ND_WORLD_DRAW, "rna_World_update"); + RNA_def_property_int_funcs(prop, NULL, "rna_World_probe_sh_res_set", NULL); + rna_def_lighting(brna); rna_def_world_mist(brna); rna_def_world_mtex(brna); diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c index 878f8562619..a3e3b97be2e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c +++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c @@ -39,9 +39,37 @@ static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = { { -1, 0, "" } }; +#define IN_COLOR 0 + +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) +{ + if (in->link) + return in->link; + else + return GPU_uniform(in->vec); +} + static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL)); + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; + + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + brdf.type = GPU_BRDF_AMBIENT_OCCLUSION; + + GPU_shade_BRDF(&brdf); + + out[0].link = brdf.output; + return 1; + } + else + return GPU_stack_link(mat, "node_ambient_occlusion", in, out); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_blackbody.c b/source/blender/nodes/shader/nodes/node_shader_blackbody.c index af89a959554..449709c6825 100644 --- a/source/blender/nodes/shader/nodes/node_shader_blackbody.c +++ b/source/blender/nodes/shader/nodes/node_shader_blackbody.c @@ -38,6 +38,11 @@ static bNodeSocketTemplate sh_node_blackbody_out[] = { { -1, 0, "" } }; +static int node_gpu_blackbody(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "node_blackbody", in, out); +} + /* node type definition */ void register_node_type_sh_blackbody(void) { @@ -49,6 +54,7 @@ void register_node_type_sh_blackbody(void) node_type_socket_templates(&ntype, sh_node_blackbody_in, sh_node_blackbody_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, node_gpu_blackbody); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c index 01ca0bd6512..ba53ec3d3ec 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c @@ -44,21 +44,73 @@ static bNodeSocketTemplate sh_node_bsdf_anisotropic_out[] = { { -1, 0, "" } }; +#define IN_COLOR 0 +#define IN_ROUGHNESS 1 +#define IN_ANISOTROPY 2 +#define IN_ROTATION 3 +#define IN_NORMAL 4 +#define IN_TANGENT 5 + static void node_shader_init_anisotropic(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1 = SHD_GLOSSY_GGX; } -static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) { - if (!in[4].link) - in[4].link = GPU_builtin(GPU_VIEW_NORMAL); + if (in->link) + return in->link; else - GPU_link(mat, "direction_transform_m4v3", in[4].link, GPU_builtin(GPU_VIEW_MATRIX), &in[4].link); - - return GPU_stack_link(mat, "node_bsdf_anisotropic", in, out); + return GPU_uniform(in->vec); } +static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[IN_NORMAL].link) + in[IN_NORMAL].link = GPU_builtin(GPU_VIEW_NORMAL); + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ + GPU_link(mat, "direction_transform_m4v3", in[IN_NORMAL].link, GPU_builtin(GPU_VIEW_MATRIX), &in[IN_NORMAL].link); + } + + if (!in[IN_TANGENT].link) + GPU_link(mat, "default_tangent", GPU_builtin(GPU_VIEW_NORMAL), GPU_attribute(CD_ORCO, ""), GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &in[IN_TANGENT].link); + else { + GPU_link(mat, "direction_transform_m4v3", in[IN_TANGENT].link, GPU_builtin(GPU_VIEW_MATRIX), &in[IN_TANGENT].link); + } + + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; + + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.type = GPU_BRDF_ANISO_GGX; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + brdf.roughness = gpu_get_input_link(&in[IN_ROUGHNESS]); + brdf.anisotropy = gpu_get_input_link(&in[IN_ANISOTROPY]); + brdf.aniso_rotation = gpu_get_input_link(&in[IN_ROTATION]); + brdf.normal = gpu_get_input_link(&in[IN_NORMAL]); + brdf.aniso_tangent = gpu_get_input_link(&in[IN_TANGENT]); + + if (node->custom1 == SHD_GLOSSY_BECKMANN) + brdf.type = GPU_BRDF_ANISO_BECKMANN; + else if (node->custom1 == SHD_GLOSSY_ASHIKHMIN_SHIRLEY) + brdf.type = GPU_BRDF_ANISO_ASHIKHMIN_SHIRLEY; + else + brdf.type = GPU_BRDF_ANISO_GGX; + + GPU_shade_BRDF(&brdf); + + out[0].link = brdf.output; + return 1; + } + else + return GPU_stack_link(mat, "node_bsdf_anisotropic_lights", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_get_world_horicol());} + /* node type definition */ void register_node_type_sh_bsdf_anisotropic(void) { diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c index e86d2677a61..e1b1df743e7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c @@ -26,6 +26,10 @@ */ #include "../node_shader_util.h" +#include "BKE_node.h" +#include "BKE_scene.h" +#include "GPU_material.h" + /* **************** OUTPUT ******************** */ @@ -36,19 +40,53 @@ static bNodeSocketTemplate sh_node_bsdf_diffuse_in[] = { { -1, 0, "" } }; +#define IN_COLOR 0 +#define IN_ROUGHNESS 1 +#define IN_NORMAL 2 + static bNodeSocketTemplate sh_node_bsdf_diffuse_out[] = { { SOCK_SHADER, 0, N_("BSDF")}, { -1, 0, "" } }; -static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) { - if (!in[2].link) - in[2].link = GPU_builtin(GPU_VIEW_NORMAL); + if (in->link) + return in->link; else - GPU_link(mat, "direction_transform_m4v3", in[2].link, GPU_builtin(GPU_VIEW_MATRIX), &in[2].link); + return GPU_uniform(in->vec); +} - return GPU_stack_link(mat, "node_bsdf_diffuse", in, out); +static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[IN_NORMAL].link) + in[IN_NORMAL].link = GPU_builtin(GPU_VIEW_NORMAL); + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ + GPU_link(mat, "direction_transform_m4v3", in[IN_NORMAL].link, GPU_builtin(GPU_VIEW_MATRIX), &in[IN_NORMAL].link); + } + + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; + + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.type = GPU_BRDF_DIFFUSE; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + brdf.roughness = gpu_get_input_link(&in[IN_ROUGHNESS]); + brdf.normal = gpu_get_input_link(&in[IN_NORMAL]); + + GPU_shade_BRDF(&brdf); + + out[0].link = brdf.output; + return 1; + } + else + return GPU_stack_link(mat, "node_bsdf_diffuse_lights", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_get_world_horicol()); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c index 5569fe85489..009f3b984d0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c @@ -26,6 +26,10 @@ */ #include "../node_shader_util.h" +#include "BKE_node.h" +#include "BKE_scene.h" +#include "GPU_material.h" +#include "DNA_material_types.h" /* **************** OUTPUT ******************** */ @@ -42,19 +46,62 @@ static bNodeSocketTemplate sh_node_bsdf_glass_out[] = { { -1, 0, "" } }; +#define IN_COLOR 0 +#define IN_ROUGHNESS 1 +#define IN_IOR 2 +#define IN_NORMAL 3 + static void node_shader_init_glass(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1 = SHD_GLOSSY_BECKMANN; } -static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) { - if (!in[3].link) - in[3].link = GPU_builtin(GPU_VIEW_NORMAL); + if (in->link) + return in->link; else - GPU_link(mat, "direction_transform_m4v3", in[3].link, GPU_builtin(GPU_VIEW_MATRIX), &in[3].link); + return GPU_uniform(in->vec); +} + +static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[IN_NORMAL].link) + in[IN_NORMAL].link = GPU_builtin(GPU_VIEW_NORMAL); + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ + GPU_link(mat, "direction_transform_m4v3", in[IN_NORMAL].link, GPU_builtin(GPU_VIEW_MATRIX), &in[IN_NORMAL].link); + } + + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; - return GPU_stack_link(mat, "node_bsdf_glass", in, out); + GPU_brdf_input_initialize(&brdf); + + /* Refraction */ + brdf.mat = mat; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + brdf.roughness = gpu_get_input_link(&in[IN_ROUGHNESS]); + brdf.ior = gpu_get_input_link(&in[IN_IOR]); + brdf.normal = gpu_get_input_link(&in[IN_NORMAL]); + + if (node->custom1 == SHD_GLOSSY_BECKMANN) + brdf.type = GPU_BRDF_GLASS_BECKMANN; + else if (node->custom1 == SHD_GLOSSY_GGX) + brdf.type = GPU_BRDF_GLASS_GGX; + else + brdf.type = GPU_BRDF_GLASS_SHARP; + + GPU_shade_BRDF(&brdf); + + out[0].link = brdf.output; + return 1; + } + else + return GPU_stack_link(mat, "node_bsdf_glass_lights", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_get_world_horicol()); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c index 7e1bc971c73..c0a0231305b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c @@ -26,6 +26,10 @@ */ #include "../node_shader_util.h" +#include "BKE_node.h" +#include "BKE_scene.h" +#include "GPU_material.h" +#include "DNA_material_types.h" /* **************** OUTPUT ******************** */ @@ -36,6 +40,10 @@ static bNodeSocketTemplate sh_node_bsdf_glossy_in[] = { { -1, 0, "" } }; +#define IN_COLOR 0 +#define IN_ROUGHNESS 1 +#define IN_NORMAL 2 + static bNodeSocketTemplate sh_node_bsdf_glossy_out[] = { { SOCK_SHADER, 0, N_("BSDF")}, { -1, 0, "" } @@ -46,14 +54,52 @@ static void node_shader_init_glossy(bNodeTree *UNUSED(ntree), bNode *node) node->custom1 = SHD_GLOSSY_GGX; } -static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) { - if (!in[2].link) - in[2].link = GPU_builtin(GPU_VIEW_NORMAL); + if (in->link) + return in->link; else - GPU_link(mat, "direction_transform_m4v3", in[2].link, GPU_builtin(GPU_VIEW_MATRIX), &in[2].link); + return GPU_uniform(in->vec); +} + +static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[IN_NORMAL].link) + in[IN_NORMAL].link = GPU_builtin(GPU_VIEW_NORMAL); + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ + GPU_link(mat, "direction_transform_m4v3", in[IN_NORMAL].link, GPU_builtin(GPU_VIEW_MATRIX), &in[IN_NORMAL].link); + } + + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; + + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + brdf.roughness = gpu_get_input_link(&in[IN_ROUGHNESS]); + brdf.normal = gpu_get_input_link(&in[IN_NORMAL]); + + if (node->custom1 == SHD_GLOSSY_BECKMANN) + brdf.type = GPU_BRDF_GLOSSY_BECKMANN; + else if (node->custom1 == SHD_GLOSSY_ASHIKHMIN_SHIRLEY) + brdf.type = GPU_BRDF_GLOSSY_ASHIKHMIN_SHIRLEY; + else if (node->custom1 == SHD_GLOSSY_GGX) + brdf.type = GPU_BRDF_GLOSSY_GGX; + else + brdf.type = GPU_BRDF_GLOSSY_SHARP; + + GPU_shade_BRDF(&brdf); - return GPU_stack_link(mat, "node_bsdf_glossy", in, out); + out[0].link = brdf.output; + return 1; + } + else + return GPU_stack_link(mat, "node_bsdf_glossy_lights", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_get_world_horicol()); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c index c447f5de219..a282b3a1c74 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c @@ -26,6 +26,10 @@ */ #include "../node_shader_util.h" +#include "BKE_node.h" +#include "BKE_scene.h" +#include "GPU_material.h" +#include "DNA_material_types.h" /* **************** OUTPUT ******************** */ @@ -42,19 +46,61 @@ static bNodeSocketTemplate sh_node_bsdf_refraction_out[] = { { -1, 0, "" } }; +#define IN_COLOR 0 +#define IN_ROUGHNESS 1 +#define IN_IOR 2 +#define IN_NORMAL 3 + static void node_shader_init_refraction(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1 = SHD_GLOSSY_BECKMANN; } -static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) { - if (!in[3].link) - in[3].link = GPU_builtin(GPU_VIEW_NORMAL); + if (in->link) + return in->link; else - GPU_link(mat, "direction_transform_m4v3", in[3].link, GPU_builtin(GPU_VIEW_MATRIX), &in[3].link); + return GPU_uniform(in->vec); +} + +static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[IN_NORMAL].link) + in[IN_NORMAL].link = GPU_builtin(GPU_VIEW_NORMAL); + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ + GPU_link(mat, "direction_transform_m4v3", in[IN_NORMAL].link, GPU_builtin(GPU_VIEW_MATRIX), &in[IN_NORMAL].link); + } + + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; - return GPU_stack_link(mat, "node_bsdf_refraction", in, out); + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + brdf.roughness = gpu_get_input_link(&in[IN_ROUGHNESS]); + brdf.ior = gpu_get_input_link(&in[IN_IOR]); + brdf.normal = gpu_get_input_link(&in[IN_NORMAL]); + + if (node->custom1 == SHD_GLOSSY_BECKMANN) + brdf.type = GPU_BRDF_REFRACT_BECKMANN; + else if (node->custom1 == SHD_GLOSSY_GGX) + brdf.type = GPU_BRDF_REFRACT_GGX; + else + brdf.type = GPU_BRDF_REFRACT_SHARP; + + GPU_shade_BRDF(&brdf); + + out[0].link = brdf.output; + return 1; + } + else + return GPU_stack_link(mat, "node_bsdf_refraction_lights", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_get_world_horicol()); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c index c3510beb470..8af3fe055e1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_toon.c @@ -42,14 +42,54 @@ static bNodeSocketTemplate sh_node_bsdf_toon_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_toon(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +#define IN_COLOR 0 +#define IN_SIZE 1 +#define IN_SMOOTH 2 +#define IN_NORMAL 3 + +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) { - if (!in[3].link) - in[3].link = GPU_builtin(GPU_VIEW_NORMAL); + if (in->link) + return in->link; else - GPU_link(mat, "direction_transform_m4v3", in[3].link, GPU_builtin(GPU_VIEW_MATRIX), &in[3].link); + return GPU_uniform(in->vec); +} + +static int node_shader_gpu_bsdf_toon(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[IN_NORMAL].link) + in[IN_NORMAL].link = GPU_builtin(GPU_VIEW_NORMAL); + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ + GPU_link(mat, "direction_transform_m4v3", in[IN_NORMAL].link, GPU_builtin(GPU_VIEW_MATRIX), &in[IN_NORMAL].link); + } + + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; + + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.type = (node->custom1 == SHD_TOON_DIFFUSE) ? GPU_BRDF_TOON_DIFFUSE : GPU_BRDF_TOON_GLOSSY; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + brdf.toon_size = gpu_get_input_link(&in[IN_SIZE]); + brdf.toon_smooth = gpu_get_input_link(&in[IN_SMOOTH]); + brdf.normal = gpu_get_input_link(&in[IN_NORMAL]); + + GPU_shade_BRDF(&brdf); - return GPU_stack_link(mat, "node_bsdf_toon", in, out); + out[0].link = brdf.output; + return 1; + } + else { + if (node->custom1 == SHD_TOON_DIFFUSE) + return GPU_stack_link(mat, "node_bsdf_toon_diffuse_lights", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_get_world_horicol()); + else + return GPU_stack_link(mat, "node_bsdf_toon_glossy_lights", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_get_world_horicol()); + } } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c index 3b88d609cdb..5b8511e6df4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c @@ -26,6 +26,10 @@ */ #include "../node_shader_util.h" +#include "BKE_node.h" +#include "BKE_scene.h" +#include "GPU_material.h" +#include "DNA_material_types.h" /* **************** OUTPUT ******************** */ @@ -40,14 +44,49 @@ static bNodeSocketTemplate sh_node_bsdf_translucent_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +#define IN_COLOR 0 +#define IN_NORMAL 1 + +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) +{ + if (in->link) + return in->link; + else + return GPU_uniform(in->vec); +} + +static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - if (!in[1].link) - in[1].link = GPU_builtin(GPU_VIEW_NORMAL); + if (!in[IN_NORMAL].link) + in[IN_NORMAL].link = GPU_builtin(GPU_VIEW_NORMAL); + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ + GPU_link(mat, "direction_transform_m4v3", in[IN_NORMAL].link, GPU_builtin(GPU_VIEW_MATRIX), &in[IN_NORMAL].link); + } + + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; + float zero = 0.0f; + + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.type = GPU_BRDF_TRANSLUCENT; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + brdf.normal = gpu_get_input_link(&in[IN_NORMAL]); + brdf.roughness = GPU_uniform(&zero); + + GPU_shade_BRDF(&brdf); + + out[0].link = brdf.output; + return 1; + } else - GPU_link(mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link); + return GPU_stack_link(mat, "node_bsdf_translucent_lights", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_get_world_horicol()); - return GPU_stack_link(mat, "node_bsdf_translucent", in, out); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c index 5cb50b00e1a..377ebeabd43 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c @@ -39,9 +39,38 @@ static bNodeSocketTemplate sh_node_bsdf_transparent_out[] = { { -1, 0, "" } }; +#define IN_COLOR 0 + +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) +{ + if (in->link) + return in->link; + else + return GPU_uniform(in->vec); +} + static int node_shader_gpu_bsdf_transparent(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_bsdf_transparent", in, out); + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; + + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.type = GPU_BRDF_TRANSPARENT; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + + GPU_shade_BRDF(&brdf); + + out[0].link = brdf.output; + return 1; + } + else { + return GPU_stack_link(mat, "node_bsdf_transparent", in, out, GPU_get_world_horicol()); + } } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c index ef3d52ecbce..46c0025f2f0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c @@ -41,14 +41,47 @@ static bNodeSocketTemplate sh_node_bsdf_velvet_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +#define IN_COLOR 0 +#define IN_SIGMA 1 +#define IN_NORMAL 2 + +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) { - if (!in[2].link) - in[2].link = GPU_builtin(GPU_VIEW_NORMAL); + if (in->link) + return in->link; else - GPU_link(mat, "direction_transform_m4v3", in[2].link, GPU_builtin(GPU_VIEW_MATRIX), &in[2].link); + return GPU_uniform(in->vec); +} - return GPU_stack_link(mat, "node_bsdf_velvet", in, out); +static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[IN_NORMAL].link) + in[IN_NORMAL].link = GPU_builtin(GPU_VIEW_NORMAL); + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ + GPU_link(mat, "direction_transform_m4v3", in[IN_NORMAL].link, GPU_builtin(GPU_VIEW_MATRIX), &in[IN_NORMAL].link); + } + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + GPUBrdfInput brdf; + + GPU_brdf_input_initialize(&brdf); + + brdf.mat = mat; + brdf.type = GPU_BRDF_VELVET; + brdf.color = gpu_get_input_link(&in[IN_COLOR]); + brdf.sigma = gpu_get_input_link(&in[IN_SIGMA]); + brdf.normal = gpu_get_input_link(&in[IN_NORMAL]); + + GPU_shade_BRDF(&brdf); + + out[0].link = brdf.output; + return 1; + } + else + return GPU_stack_link(mat, "node_bsdf_velvet_lights", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_get_world_horicol()); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_emission.c b/source/blender/nodes/shader/nodes/node_shader_emission.c index 51b3d5740a7..df4771f2107 100644 --- a/source/blender/nodes/shader/nodes/node_shader_emission.c +++ b/source/blender/nodes/shader/nodes/node_shader_emission.c @@ -42,6 +42,14 @@ static bNodeSocketTemplate sh_node_emission_out[] = { static int node_shader_gpu_emission(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { + float factor = 0.01f; + + if (!in[0].link) + in[0].link = GPU_uniform(in[0].vec); + + if ( GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_LAMP ) + GPU_link(mat, "shade_mul_value", GPU_uniform(&factor), in[0].link, &in[0].link); + return GPU_stack_link(mat, "node_emission", in, out, GPU_builtin(GPU_VIEW_NORMAL)); } diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c index b50f722c71b..46c296717a4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c +++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c @@ -43,8 +43,10 @@ static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), bNodeE { if (!in[1].link) in[1].link = GPU_builtin(GPU_VIEW_NORMAL); - else + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ GPU_link(mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link); + } return GPU_stack_link(mat, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION)); } diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c index 553ea65154f..4616d726617 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geometry.c +++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c @@ -26,6 +26,7 @@ */ #include "../node_shader_util.h" + #include "GPU_material.h" /* **************** OUTPUT ******************** */ @@ -43,9 +44,19 @@ static bNodeSocketTemplate sh_node_geometry_out[] = { static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_geometry", in, out, - GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX)); + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_LAMP) { + GPUNodeLink *lamp_normal = GPU_material_get_lamp_normal_link(mat); + GPUNodeLink *lamp_position = GPU_material_get_lamp_position_link(mat); + GPUNodeLink *lamp_incoming = GPU_material_get_lamp_incoming_link(mat); + + return GPU_stack_link(mat, "node_geometry_lamp", in, out, + lamp_normal, lamp_position, lamp_incoming, + GPU_builtin(GPU_INVERSE_VIEW_MATRIX)); + } + else + return GPU_stack_link(mat, "node_geometry", in, out, + GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), + GPU_attribute(CD_ORCO, ""), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX)); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_holdout.c b/source/blender/nodes/shader/nodes/node_shader_holdout.c index ac28a2fa11b..bb14156ff4a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_holdout.c +++ b/source/blender/nodes/shader/nodes/node_shader_holdout.c @@ -38,7 +38,6 @@ static bNodeSocketTemplate sh_node_holdout_out[] = { { -1, 0, "" } }; - /* node type definition */ void register_node_type_sh_holdout(void) { diff --git a/source/blender/nodes/shader/nodes/node_shader_lamp.c b/source/blender/nodes/shader/nodes/node_shader_lamp.c index 2c96c91958e..d3483c8c826 100644 --- a/source/blender/nodes/shader/nodes/node_shader_lamp.c +++ b/source/blender/nodes/shader/nodes/node_shader_lamp.c @@ -63,7 +63,7 @@ static void node_shader_exec_lamp(void *data, int UNUSED(thread), bNode *node, b static int gpu_shader_lamp(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (node->id) { - GPULamp *lamp = GPU_lamp_from_blender(GPU_material_scene(mat), (Object *)node->id, NULL); + GPULamp *lamp = GPU_lamp_from_blender(GPU_material_scene(mat), (Object *)node->id, NULL, false); GPUNodeLink *col, *lv, *dist, *visifac, *shadow, *energy; visifac = GPU_lamp_get_data(mat, lamp, &col, &lv, &dist, &shadow, &energy); diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c index 8cbc587e339..f54145d8e66 100644 --- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c +++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c @@ -45,8 +45,10 @@ static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *UNUSED(node), b { if (!in[1].link) in[1].link = GPU_builtin(GPU_VIEW_NORMAL); - else + else { + /* Convert to view space normal in case a Normal is plugged. This is because cycles uses world normals */ GPU_link(mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link); + } return GPU_stack_link(mat, "node_layer_weight", in, out, GPU_builtin(GPU_VIEW_POSITION)); } diff --git a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c index 3aad476ea05..a08a554bb4e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c +++ b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c @@ -26,6 +26,7 @@ */ #include "../node_shader_util.h" +#include "GPU_material.h" /* **************** INPUT ********************* */ @@ -46,7 +47,17 @@ static bNodeSocketTemplate sh_node_light_falloff_out[] = { static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_light_falloff", in, out); + if (GPU_material_get_type(mat) == GPU_MATERIAL_TYPE_LAMP) { + GPUNodeLink *lampposlink = GPU_material_get_lamp_position_link(mat); + if (lampposlink) + return GPU_stack_link(mat, "node_light_falloff", in, out, lampposlink, GPU_builtin(GPU_VIEW_POSITION)); + else + return 0; + } + else { + float lamppos[4] = {0.0f}; + return GPU_stack_link(mat, "node_light_falloff", in, out, GPU_uniform((float *)lamppos), GPU_builtin(GPU_VIEW_POSITION)); + } } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c index d1905246fd4..c7cb2f63b28 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c @@ -39,7 +39,7 @@ static bNodeSocketTemplate sh_node_object_info_out[] = { static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_object_info", in, out); + return GPU_stack_link(mat, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX)); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c index c1903facb8c..0f4571eb740 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c @@ -34,6 +34,16 @@ static bNodeSocketTemplate sh_node_output_lamp_in[] = { { -1, 0, "" } }; +static int node_shader_gpu_output_lamp(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + GPUNodeLink *outlink; + + GPU_stack_link(mat, "node_output_lamp", in, out, &outlink); + GPU_material_output_link(mat, outlink); + + return 1; +} + /* node type definition */ void register_node_type_sh_output_lamp(void) { @@ -44,6 +54,7 @@ void register_node_type_sh_output_lamp(void) node_type_socket_templates(&ntype, sh_node_output_lamp_in, NULL); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, node_shader_gpu_output_lamp); /* Do not allow muting output node. */ node_type_internal_links(&ntype, NULL); diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c index 7aa7fb43221..bbcb55a027b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tangent.c +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c @@ -41,6 +41,29 @@ static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node) node->storage = attr; } +static int node_shader_gpu_tangent(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + NodeShaderTangent *attr = node->storage; + float vec[3] = {0.0f}; + + if(attr->direction_type == SHD_TANGENT_UVMAP){ + return GPU_stack_link(mat, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, ""), GPU_builtin(GPU_INVERSE_VIEW_MATRIX)); + } + else{ + GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); + + if (attr->axis == SHD_TANGENT_AXIS_X) + GPU_link(mat, "tangent_orco_x", orco, &orco); + else if (attr->axis == SHD_TANGENT_AXIS_Y) + GPU_link(mat, "tangent_orco_y", orco, &orco); + else + GPU_link(mat, "tangent_orco_z", orco, &orco); + + return GPU_stack_link(mat, "node_tangent", in, out, GPU_builtin(GPU_VIEW_NORMAL), orco, + GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX)); + } +} + /* node type definition */ void register_node_type_sh_tangent(void) { @@ -52,6 +75,7 @@ void register_node_type_sh_tangent(void) node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); node_type_init(&ntype, node_shader_init_tangent); node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage); + node_type_gpu(&ntype, node_shader_gpu_tangent); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c index be393582a42..c4f5a974b8e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c @@ -46,9 +46,9 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNod { GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ""); - GPUMatType type = GPU_Material_get_type(mat); - - if (type == GPU_MATERIAL_TYPE_MESH) { + GPUMatType type = GPU_material_get_type(mat); + + if (type == GPU_MATERIAL_TYPE_MESH || type == GPU_MATERIAL_TYPE_MESH_REAL_SH) { return GPU_stack_link(mat, "node_tex_coord", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), @@ -57,7 +57,7 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNod else { return GPU_stack_link(mat, "node_tex_coord_background", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), + GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, mtface); } } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index 2f8f95b0675..4e431374490 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -58,31 +58,29 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeE { Image *ima = (Image *)node->id; ImageUser *iuser = NULL; - NodeTexImage *tex = node->storage; + NodeTexEnvironment *tex = node->storage; int isdata = tex->color_space == SHD_COLORSPACE_NONE; + GPUMatType type = GPU_material_get_type(mat); if (!ima) return GPU_stack_link(mat, "node_tex_environment_empty", in, out); if (!in[0].link) { - GPUMatType type = GPU_Material_get_type(mat); - - if (type == GPU_MATERIAL_TYPE_MESH) + if (type == GPU_MATERIAL_TYPE_MESH || type == GPU_MATERIAL_TYPE_MESH_REAL_SH) in[0].link = GPU_builtin(GPU_VIEW_POSITION); else GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &in[0].link); } - + node_shader_gpu_tex_mapping(mat, node, in, out); if (tex->projection == SHD_PROJ_EQUIRECTANGULAR) - GPU_stack_link(mat, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata)); + GPU_stack_link(mat, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata, true)); else - GPU_stack_link(mat, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata)); + GPU_stack_link(mat, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata, false)); ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && - GPU_material_do_color_management(mat)) + if (!isdata) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 71200dfe9d3..d04dad484e9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -59,10 +59,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat Image *ima = (Image *)node->id; ImageUser *iuser = NULL; NodeTexImage *tex = node->storage; - GPUNodeLink *norm; - int isdata = tex->color_space == SHD_COLORSPACE_NONE; + bool do_clip = tex->extension == SHD_IMAGE_EXTENSION_CLIP; float blend = tex->projection_blend; if (!ima) @@ -74,9 +73,6 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat node_shader_gpu_tex_mapping(mat, node, in, out); switch (tex->projection) { - case SHD_PROJ_FLAT: - GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); - break; case SHD_PROJ_BOX: GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), @@ -84,33 +80,47 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat GPU_link(mat, "direction_transform_m4v3", norm, GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), &norm); - GPU_link(mat, "node_tex_image_box", in[0].link, - norm, - GPU_image(ima, iuser, isdata), - GPU_uniform(&blend), - &out[0].link, - &out[1].link); break; case SHD_PROJ_SPHERE: GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link); GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link); - GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); break; case SHD_PROJ_TUBE: GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link); GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link); - GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); break; + case SHD_PROJ_FLAT: + break; + } + + if (tex->projection == SHD_PROJ_BOX) { + GPU_link(mat, "node_tex_image_box", in[0].link, + norm, + GPU_image(ima, iuser, isdata, do_clip), + GPU_uniform(&blend), + &out[0].link, + &out[1].link); + } + else { + if (tex->interpolation == SHD_INTERP_CLOSEST) { + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); + + if (!ibuf) + return GPU_stack_link(mat, "node_tex_image_empty", in, out); + + float dim[2] = {(float)ibuf->x, (float)ibuf->y}; + GPU_stack_link(mat, "node_tex_image_closest", in, out, GPU_image(ima, iuser, isdata, do_clip), GPU_uniform(dim)); + BKE_image_release_ibuf(ima, ibuf, NULL); + } + else { + GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata, do_clip)); + } } - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - if ((tex->color_space == SHD_COLORSPACE_COLOR) && - ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && - GPU_material_do_color_management(mat)) + if (!isdata) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } - BKE_image_release_ibuf(ima, ibuf, NULL); return true; } diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c index b0b25a4878b..799c2436e17 100644 --- a/source/blender/nodes/shader/nodes/node_shader_texture.c +++ b/source/blender/nodes/shader/nodes/node_shader_texture.c @@ -125,7 +125,7 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, bNodeExecData *UNUS if (tex && tex->ima && (tex->type == TEX_IMAGE || tex->type == TEX_ENVMAP)) { if (tex->type == TEX_IMAGE) { - GPUNodeLink *texlink = GPU_image(tex->ima, &tex->iuser, false); + GPUNodeLink *texlink = GPU_image(tex->ima, &tex->iuser, false, false); GPU_stack_link(mat, "texture_image", in, out, texlink); } else { /* TEX_ENVMAP */ diff --git a/source/blender/nodes/shader/nodes/node_shader_wavelength.c b/source/blender/nodes/shader/nodes/node_shader_wavelength.c index 182769e2b32..5641de9d990 100644 --- a/source/blender/nodes/shader/nodes/node_shader_wavelength.c +++ b/source/blender/nodes/shader/nodes/node_shader_wavelength.c @@ -38,6 +38,12 @@ static bNodeSocketTemplate sh_node_wavelength_out[] = { { -1, 0, "" } }; +static int node_shader_gpu_wavelength(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "node_wavelength", in, out); +} + + /* node type definition */ void register_node_type_sh_wavelength(void) { @@ -49,6 +55,7 @@ void register_node_type_sh_wavelength(void) node_type_socket_templates(&ntype, sh_node_wavelength_in, sh_node_wavelength_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, node_shader_gpu_wavelength); nodeRegisterType(&ntype); } diff --git a/source/blender/python/intern/gpu_offscreen.c b/source/blender/python/intern/gpu_offscreen.c index c4863b2a92f..2941806b761 100644 --- a/source/blender/python/intern/gpu_offscreen.c +++ b/source/blender/python/intern/gpu_offscreen.c @@ -222,7 +222,7 @@ static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *a fx_settings = v3d->fx_settings; /* full copy */ - ED_view3d_draw_offscreen_init(scene, v3d); + ED_view3d_draw_offscreen_init(scene, v3d, ar); rv3d_mats = ED_view3d_mats_rv3d_backup(ar->regiondata); @@ -231,7 +231,7 @@ static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *a ED_view3d_draw_offscreen( scene, v3d, ar, GPU_offscreen_width(self->ofs), GPU_offscreen_height(self->ofs), (float(*)[4])py_mat_modelview->matrix, (float(*)[4])py_mat_projection->matrix, - false, true, true, "", + false, true, true, true, "", fx, &fx_settings, self->ofs); diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 95679b5d3a6..f112ec54e8a 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -62,7 +62,7 @@ BL_BlenderShader::~BL_BlenderShader() void BL_BlenderShader::ReloadMaterial() { - mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat, false) : NULL; + mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat, false, false, false, false, false, false, false, 0) : NULL; } void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp index fff988a07c5..9190e8f2338 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp @@ -161,7 +161,7 @@ GPULamp *RAS_OpenGLLight::GetGPULamp() KX_LightObject* kxlight = (KX_LightObject*)m_light; if (m_glsl) - return GPU_lamp_from_blender(kxlight->GetScene()->GetBlenderScene(), kxlight->GetBlenderObject(), kxlight->GetBlenderGroupObject()); + return GPU_lamp_from_blender(kxlight->GetScene()->GetBlenderScene(), kxlight->GetBlenderObject(), kxlight->GetBlenderGroupObject(), false); else return NULL; } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 3f82c513f7d..66c2fde908b 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -832,7 +832,7 @@ void RAS_OpenGLRasterizer::DrawDerivedMesh(class RAS_MeshSlot &ms) Material* blmat = current_polymat->GetBlenderMaterial(); Scene* blscene = current_polymat->GetBlenderScene(); if (!current_wireframe && blscene && blmat) - GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat, false), ¤t_gpu_attribs); + GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat, false, false, false, false, false, false, false, 0), ¤t_gpu_attribs); else memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs)); // DM draw can mess up blending mode, restore at the end |