Compare commits
84 Commits
tmp-batch-
...
pbr-viewpo
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f87036e8a7 | ||
![]() |
f8a1255464 | ||
![]() |
0497b012a3 | ||
![]() |
669c2801c0 | ||
![]() |
d26de5c907 | ||
![]() |
1640ea89e5 | ||
![]() |
d74f6b2204 | ||
![]() |
4948b6e226 | ||
![]() |
feff6b4df3 | ||
![]() |
12c0394a4f | ||
![]() |
06b5508073 | ||
![]() |
6f81e808e3 | ||
![]() |
d0989e538e | ||
![]() |
418b24551e | ||
![]() |
a84794b399 | ||
![]() |
20fa91bd47 | ||
![]() |
ddfae3d2e1 | ||
![]() |
4cae0cb418 | ||
![]() |
22c83011a9 | ||
![]() |
d2ec40b8f5 | ||
![]() |
31d65359e8 | ||
![]() |
554952d114 | ||
![]() |
d85b6b86cf | ||
![]() |
db461850d7 | ||
![]() |
d28c4d4a7c | ||
![]() |
96f6372a07 | ||
![]() |
9c8fbd9813 | ||
![]() |
fbf7e5acfb | ||
![]() |
d7d0166386 | ||
![]() |
6ebbef4724 | ||
![]() |
bcf5e1c7f5 | ||
![]() |
4841e60261 | ||
![]() |
7e4d937718 | ||
![]() |
579d16714f | ||
![]() |
d949b28199 | ||
![]() |
e54385f059 | ||
![]() |
b372028836 | ||
![]() |
105a1d84c4 | ||
![]() |
80f03704e7 | ||
![]() |
655cfca452 | ||
![]() |
7c777fe038 | ||
![]() |
81737e6cca | ||
![]() |
515be07dd4 | ||
![]() |
7750dea70e | ||
![]() |
f50bf4f110 | ||
![]() |
c1580b9cd4 | ||
![]() |
c112a54d2a | ||
![]() |
1cd2d7b744 | ||
![]() |
798357ca57 | ||
![]() |
b818de11df | ||
![]() |
ef01bfd53d | ||
![]() |
bb9d7491e8 | ||
![]() |
37300f3307 | ||
![]() |
ed3a8ae7b3 | ||
![]() |
9a0e6c1883 | ||
![]() |
b6d97ce425 | ||
![]() |
1eb5ff3bbd | ||
![]() |
240e995062 | ||
![]() |
7e0cb40b48 | ||
![]() |
9974ada602 | ||
![]() |
b3c3275dad | ||
![]() |
8de5664a60 | ||
![]() |
52cb2981c4 | ||
![]() |
4b08c4d0ae | ||
![]() |
bec580b0f9 | ||
![]() |
e217b66505 | ||
![]() |
6d33b1031a | ||
![]() |
051c9c39d4 | ||
![]() |
20afa77324 | ||
![]() |
371c289af8 | ||
![]() |
59295b9126 | ||
![]() |
f0f398c0dd | ||
![]() |
a3a0220d57 | ||
![]() |
df63042d8f | ||
![]() |
3155b440bf | ||
![]() |
01a258f829 | ||
![]() |
a30e73bf67 | ||
![]() |
c326d403d8 | ||
![]() |
44aeca9023 | ||
![]() |
c89ced47bb | ||
![]() |
83aeba94c7 | ||
![]() |
4aebb28e60 | ||
![]() |
863923d3d0 | ||
![]() |
83a54dc2a8 |
@@ -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'}
|
||||
|
@@ -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,
|
||||
|
@@ -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"
|
||||
|
@@ -3127,6 +3127,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
|
||||
@@ -3240,6 +3245,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'}:
|
||||
@@ -3248,7 +3285,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")
|
||||
|
@@ -498,6 +498,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);
|
||||
|
||||
|
@@ -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
|
||||
@@ -392,6 +393,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);
|
||||
@@ -597,6 +600,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;
|
||||
|
||||
@@ -995,6 +1006,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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -3597,6 +3597,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -4616,6 +4617,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5162,6 +5170,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);
|
||||
}
|
||||
|
||||
@@ -6655,6 +6665,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)
|
||||
@@ -6665,7 +6676,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) {
|
||||
@@ -8981,6 +8999,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)
|
||||
|
@@ -1336,5 +1336,25 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "World", "ListBase", "gpuprobe")) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -2836,6 +2836,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;
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -111,6 +111,7 @@
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "GPU_material.h"
|
||||
#include "GPU_probe.h"
|
||||
|
||||
#include "object_intern.h"
|
||||
|
||||
@@ -1103,6 +1104,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 */
|
||||
|
@@ -271,6 +271,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);
|
||||
|
||||
|
@@ -250,6 +250,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);
|
||||
|
162
source/blender/editors/object/object_probe.c
Normal file
162
source/blender/editors/object/object_probe.c
Normal file
@@ -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;
|
||||
}
|
@@ -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);
|
||||
|
||||
|
@@ -668,7 +668,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();
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -84,6 +84,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))
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -660,7 +660,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
|
||||
if (ima) {
|
||||
if (ob_alpha > 0.0f) {
|
||||
glActiveTexture(texUnit);
|
||||
bindcode = GPU_verify_image(ima, ob->iuser, GL_TEXTURE_2D, 0, false, false, false);
|
||||
bindcode = GPU_verify_image(ima, ob->iuser, GL_TEXTURE_2D, 0, false, false, false, false);
|
||||
/* don't bother drawing the image if alpha = 0 */
|
||||
}
|
||||
|
||||
@@ -1223,7 +1223,7 @@ static void draw_transp_sun_volume(Lamp *la, unsigned pos)
|
||||
}
|
||||
#endif
|
||||
|
||||
void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
|
||||
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;
|
||||
@@ -1402,9 +1402,16 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
|
||||
gpuPopMatrix();
|
||||
}
|
||||
|
||||
if (la->type == LA_LOCAL) {
|
||||
if (la->mode & LA_SPHERE) {
|
||||
imm_drawcircball(vec, la->dist, imat, pos);
|
||||
if (BKE_scene_use_new_shading_nodes(scene)) {
|
||||
if (ELEM(la->type == LA_LOCAL, la->type == LA_SPOT)) {
|
||||
imm_drawcircball(vec, la->area_size, imat, pos);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (la->type == LA_LOCAL) {
|
||||
if (la->mode & LA_SPHERE) {
|
||||
imm_drawcircball(vec, la->dist, imat, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3813,7 +3820,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);
|
||||
@@ -3826,7 +3833,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);
|
||||
@@ -4102,7 +4109,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)
|
||||
@@ -4134,7 +4141,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;
|
||||
@@ -4226,7 +4233,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];
|
||||
@@ -4680,7 +4687,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);
|
||||
@@ -4850,10 +4857,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);
|
||||
@@ -6792,7 +6799,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:
|
||||
@@ -7496,7 +7503,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);
|
||||
|
@@ -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 "GPU_viewport.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
@@ -429,10 +432,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -462,6 +475,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) {
|
||||
@@ -479,6 +493,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;
|
||||
}
|
||||
|
||||
@@ -809,6 +830,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;
|
||||
@@ -852,6 +919,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:
|
||||
@@ -879,6 +947,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
|
||||
case ND_CONSTRAINT:
|
||||
case ND_KEYS:
|
||||
case ND_LOD:
|
||||
view3d_tag_probes_update(ar, wmn, scene);
|
||||
ED_region_tag_redraw(ar);
|
||||
break;
|
||||
}
|
||||
@@ -947,12 +1016,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;
|
||||
}
|
||||
@@ -960,6 +1031,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;
|
||||
}
|
||||
|
@@ -1304,7 +1304,7 @@ static void view3d_draw_grid(const bContext *C, ARegion *ar)
|
||||
/* ******************** non-meshes ***************** */
|
||||
|
||||
static void view3d_draw_non_mesh(
|
||||
Object *ob, Base *base, View3D *v3d,
|
||||
Scene *scene, Object *ob, Base *base, View3D *v3d,
|
||||
RegionView3D *rv3d, const unsigned char color[4])
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
@@ -1321,7 +1321,7 @@ RegionView3D *rv3d, const unsigned char color[4])
|
||||
drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, color);
|
||||
break;
|
||||
case OB_LAMP:
|
||||
drawlamp(v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, false);
|
||||
drawlamp(scene, v3d, rv3d, base, OB_SOLID, DRAW_CONSTCOLOR, color, false);
|
||||
break;
|
||||
default:
|
||||
/* TODO Viewport: handle the other cases*/
|
||||
@@ -1510,7 +1510,7 @@ static void view3d_draw_non_meshes(const bContext *C, ARegion *ar)
|
||||
color_prev = color;
|
||||
}
|
||||
|
||||
view3d_draw_non_mesh(ob, base, v3d, rv3d, color);
|
||||
view3d_draw_non_mesh(scene, ob, base, v3d, rv3d, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -101,6 +101,8 @@
|
||||
#include "GPU_compositing.h"
|
||||
#include "GPU_extensions.h"
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_probe.h"
|
||||
#include "GPU_pbr.h"
|
||||
|
||||
#include "view3d_intern.h" /* own include */
|
||||
|
||||
@@ -1855,7 +1857,7 @@ 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);
|
||||
@@ -1939,7 +1941,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);
|
||||
|
||||
@@ -1960,6 +1962,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)
|
||||
@@ -2233,11 +2602,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2245,23 +2625,36 @@ 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)) {
|
||||
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));
|
||||
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);
|
||||
|
||||
bool material_not_bound = !GPU_material_bound(gpumat);
|
||||
/* calculate full shader for background */
|
||||
GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
|
||||
|
||||
if (material_not_bound) {
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
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 */
|
||||
@@ -2274,14 +2667,19 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
|
||||
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);
|
||||
@@ -2327,7 +2725,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)
|
||||
{
|
||||
@@ -2370,15 +2768,20 @@ void ED_view3d_draw_offscreen(
|
||||
VP_legacy_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;
|
||||
@@ -2394,7 +2797,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) {
|
||||
@@ -2466,7 +2870,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);
|
||||
|
||||
@@ -2509,7 +2913,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) {
|
||||
@@ -2535,7 +2939,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);
|
||||
|
||||
@@ -2554,7 +2958,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, false, viewname,
|
||||
fx, &fx_settings, ofs);
|
||||
GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
|
||||
|
||||
@@ -2912,9 +3316,19 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie
|
||||
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;
|
||||
@@ -2938,7 +3352,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;
|
||||
@@ -2951,7 +3365,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 */
|
||||
|
@@ -149,7 +149,7 @@ bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char
|
||||
void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline);
|
||||
void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob);
|
||||
void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]);
|
||||
void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
|
||||
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);
|
||||
|
||||
|
@@ -59,8 +59,10 @@ set(SRC
|
||||
intern/gpu_framebuffer.c
|
||||
intern/gpu_immediate.c
|
||||
intern/gpu_init_exit.c
|
||||
intern/gpu_pbr.c
|
||||
intern/gpu_material.c
|
||||
intern/gpu_matrix.c
|
||||
intern/gpu_probe.c
|
||||
intern/gpu_select.c
|
||||
intern/gpu_shader.c
|
||||
intern/gpu_texture.c
|
||||
@@ -91,6 +93,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
|
||||
@@ -100,9 +114,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_batch.h
|
||||
@@ -115,8 +136,11 @@ set(SRC
|
||||
GPU_glew.h
|
||||
GPU_immediate.h
|
||||
GPU_init_exit.h
|
||||
GPU_pbr.h
|
||||
GPU_ltc.h
|
||||
GPU_material.h
|
||||
GPU_matrix.h
|
||||
GPU_probe.h
|
||||
GPU_select.h
|
||||
GPU_shader.h
|
||||
GPU_texture.h
|
||||
@@ -164,6 +188,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)
|
||||
@@ -181,7 +217,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)
|
||||
|
@@ -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(
|
||||
|
@@ -32,6 +32,8 @@
|
||||
#ifndef __GPU_DRAW_H__
|
||||
#define __GPU_DRAW_H__
|
||||
|
||||
#include "GPU_glew.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -120,6 +122,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);
|
||||
@@ -142,10 +145,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);
|
||||
|
@@ -50,6 +50,7 @@ struct GPUTexture;
|
||||
void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
|
||||
|
||||
GPUFrameBuffer *GPU_framebuffer_create(void);
|
||||
bool GPU_framebuffer_cubeface_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int cubeface);
|
||||
bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
|
||||
void GPU_framebuffer_texture_detach(struct GPUTexture *tex);
|
||||
void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
|
||||
@@ -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 */
|
||||
|
48
source/blender/gpu/GPU_ltc.h
Normal file
48
source/blender/gpu/GPU_ltc.h
Normal file
File diff suppressed because one or more lines are too long
@@ -55,6 +55,9 @@ struct GPUNodeStack;
|
||||
struct GPUMaterial;
|
||||
struct GPUTexture;
|
||||
struct GPULamp;
|
||||
struct GPUProbe;
|
||||
struct GPUPBR;
|
||||
struct GPUPBRSettings;
|
||||
struct PreviewImage;
|
||||
struct World;
|
||||
|
||||
@@ -93,6 +96,7 @@ typedef enum GPUBuiltin {
|
||||
GPU_CAMERA_TEXCO_FACTORS = (1 << 8),
|
||||
GPU_LOC_TO_VIEW_MATRIX = (1 << 9),
|
||||
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
|
||||
GPU_PBR = (1 << 15),
|
||||
} GPUBuiltin;
|
||||
|
||||
typedef enum GPUOpenGLBuiltin {
|
||||
@@ -101,8 +105,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;
|
||||
|
||||
|
||||
@@ -164,6 +170,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,
|
||||
@@ -194,7 +204,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);
|
||||
@@ -206,14 +216,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);
|
||||
|
||||
@@ -226,10 +246,14 @@ void GPU_material_bind(
|
||||
void GPU_material_bind_uniforms(
|
||||
GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
|
||||
float autobumpscale);
|
||||
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);
|
||||
@@ -238,6 +262,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 {
|
||||
@@ -306,7 +379,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);
|
||||
@@ -318,6 +391,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);
|
||||
@@ -328,6 +402,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]);
|
||||
|
85
source/blender/gpu/GPU_pbr.h
Normal file
85
source/blender/gpu/GPU_pbr.h
Normal file
@@ -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__ */
|
118
source/blender/gpu/GPU_probe.h
Normal file
118
source/blender/gpu/GPU_probe.h
Normal file
@@ -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__*/
|
@@ -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(
|
||||
@@ -116,8 +123,16 @@ typedef enum GPUBuiltinShader {
|
||||
GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH,
|
||||
GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR,
|
||||
GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR,
|
||||
|
||||
GPU_SHADER_MINZ_DOWNSAMPLE,
|
||||
GPU_SHADER_MAXZ_DOWNSAMPLE,
|
||||
GPU_SHADER_DISPLAY_SH,
|
||||
|
||||
GPU_SHADER_COMPUTE_SH = 28, /* 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);
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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[];
|
||||
@@ -402,6 +414,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
|
||||
return "unfobautobumpscale";
|
||||
else if (builtin == GPU_CAMERA_TEXCO_FACTORS)
|
||||
return "unfcameratexfactors";
|
||||
else if (builtin == GPU_PBR)
|
||||
return "unfpbr"; /* Placeholder : does not actualy contain data */
|
||||
else
|
||||
return "";
|
||||
}
|
||||
@@ -422,13 +436,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");
|
||||
@@ -495,7 +511,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) {
|
||||
@@ -515,7 +531,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);
|
||||
}
|
||||
@@ -645,12 +665,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;
|
||||
@@ -661,12 +688,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
|
||||
@@ -674,6 +700,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)
|
||||
@@ -730,7 +760,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) {
|
||||
@@ -760,6 +790,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:
|
||||
@@ -902,8 +933,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);
|
||||
|
||||
@@ -1018,7 +1062,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);
|
||||
}
|
||||
@@ -1204,6 +1248,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;
|
||||
}
|
||||
@@ -1358,7 +1403,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;
|
||||
@@ -1406,7 +1451,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();
|
||||
|
||||
@@ -1414,6 +1459,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;
|
||||
}
|
||||
@@ -1639,10 +1685,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;
|
||||
@@ -1659,10 +1712,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);
|
||||
|
||||
@@ -1673,6 +1726,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,
|
||||
@@ -1691,6 +1766,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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
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];
|
||||
|
||||
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, 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;
|
||||
MEM_freeN(lut3d);
|
||||
BKE_color_managed_view_settings_free(view_settings_mod);
|
||||
MEM_freeN(view_settings_mod);
|
||||
MEM_freeN(display_settings_mod);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -388,6 +389,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) {
|
||||
@@ -397,7 +399,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;
|
||||
}
|
||||
@@ -417,6 +422,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();
|
||||
|
||||
@@ -427,7 +435,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]) {
|
||||
@@ -457,7 +465,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 {
|
||||
@@ -467,6 +475,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) &&
|
||||
@@ -499,7 +526,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);
|
||||
@@ -604,7 +631,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;
|
||||
@@ -1054,6 +1081,7 @@ bool GPU_fx_do_composite_pass(
|
||||
}
|
||||
}
|
||||
|
||||
SWAP(GPUTexture *, target, src);
|
||||
numslots = 0;
|
||||
}
|
||||
}
|
||||
@@ -1280,6 +1308,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);
|
||||
@@ -1304,6 +1388,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)
|
||||
|
@@ -81,6 +81,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"
|
||||
|
||||
@@ -284,11 +286,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) {
|
||||
@@ -529,7 +535,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,
|
||||
@@ -561,7 +568,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;
|
||||
@@ -752,7 +759,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) {
|
||||
@@ -845,7 +852,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;
|
||||
|
||||
@@ -854,7 +861,7 @@ void GPU_create_gl_tex(
|
||||
|
||||
#if 0 /* NPOT support should be a compile-time check */
|
||||
/* 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)) ||
|
||||
@@ -896,7 +903,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;
|
||||
@@ -947,7 +954,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) {
|
||||
@@ -996,6 +1003,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());
|
||||
|
||||
@@ -1076,14 +1088,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
|
||||
}
|
||||
@@ -1115,7 +1127,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;
|
||||
@@ -1261,7 +1273,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;
|
||||
@@ -1311,7 +1323,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;
|
||||
@@ -1345,7 +1357,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;
|
||||
@@ -1601,7 +1613,7 @@ typedef struct GPUMaterialFixed {
|
||||
float spec[3];
|
||||
int hard;
|
||||
float alpha;
|
||||
} GPUMaterialFixed;
|
||||
} GPUMaterialFixed;
|
||||
|
||||
static struct GPUMaterialState {
|
||||
GPUMaterialFixed (*matbuf);
|
||||
@@ -1618,6 +1630,8 @@ static struct GPUMaterialState {
|
||||
Object *gob;
|
||||
DupliObject *dob;
|
||||
Scene *gscene;
|
||||
GPUProbe *gprobe;
|
||||
GPUPBR *gpbr;
|
||||
int glay;
|
||||
bool gscenelock;
|
||||
float (*gviewmat)[4];
|
||||
@@ -1635,6 +1649,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 */
|
||||
@@ -1713,7 +1735,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;
|
||||
@@ -1779,6 +1801,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,
|
||||
@@ -1812,22 +1844,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 */
|
||||
@@ -1835,8 +1933,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 */
|
||||
@@ -1906,7 +2012,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;
|
||||
}
|
||||
|
||||
@@ -1932,7 +2041,9 @@ int GPU_object_material_bind(int nr, void *attribs)
|
||||
|
||||
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);
|
||||
|
||||
GPU_material_bind(
|
||||
@@ -1941,6 +2052,8 @@ int GPU_object_material_bind(int nr, void *attribs)
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
@@ -2028,7 +2141,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
|
||||
@@ -2349,7 +2464,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);
|
||||
}
|
||||
|
@@ -343,7 +343,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) {
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_math_base.h"
|
||||
|
||||
#include "BKE_global.h"
|
||||
|
||||
@@ -112,7 +113,7 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
|
||||
return fb;
|
||||
}
|
||||
|
||||
bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot)
|
||||
static int gpu_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int cubeface)
|
||||
{
|
||||
GLenum attachment;
|
||||
|
||||
@@ -139,8 +140,12 @@ bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slo
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
|
||||
GG.currentfb = fb->object;
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, 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);
|
||||
|
||||
if (GPU_texture_depth(tex))
|
||||
fb->depthtex = tex;
|
||||
@@ -152,6 +157,16 @@ bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slo
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GPU_framebuffer_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int cubeface)
|
||||
{
|
||||
return gpu_framebuffer_texture_attach(fb, tex, slot, cubeface);
|
||||
}
|
||||
|
||||
bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot)
|
||||
{
|
||||
return gpu_framebuffer_texture_attach(fb, tex, slot, 0);
|
||||
}
|
||||
|
||||
void GPU_framebuffer_texture_detach(GPUTexture *tex)
|
||||
{
|
||||
GLenum attachment;
|
||||
@@ -310,6 +325,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);
|
||||
|
||||
@@ -412,6 +428,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);
|
||||
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 {
|
||||
|
File diff suppressed because it is too large
Load Diff
327
source/blender/gpu/intern/gpu_pbr.c
Normal file
327
source/blender/gpu/intern/gpu_pbr.c
Normal file
@@ -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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
685
source/blender/gpu/intern/gpu_probe.c
Normal file
685
source/blender/gpu/intern/gpu_probe.c
Normal file
@@ -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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
else
|
||||
GPU_framebuffer_texture_attach(probe->fb, probe->texreflect, 0);
|
||||
|
||||
/* 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 */
|
||||
|
||||
static 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();
|
||||
}
|
@@ -95,6 +95,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 {
|
||||
@@ -102,6 +109,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];
|
||||
/* for drawing text */
|
||||
@@ -200,6 +211,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");
|
||||
}
|
||||
@@ -221,7 +236,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)) {
|
||||
@@ -264,9 +286,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;
|
||||
}
|
||||
@@ -344,7 +392,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) {
|
||||
@@ -615,6 +670,25 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
|
||||
{
|
||||
GPUShader *retval = NULL;
|
||||
|
||||
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];
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (shader) {
|
||||
case GPU_SHADER_VSM_STORE:
|
||||
if (!GG.shaders.vsm_store)
|
||||
@@ -813,8 +887,23 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
|
||||
NULL, NULL, NULL, 0, 0, 0);
|
||||
retval = GG.shaders.point_uniform_size_uniform_color_outline_smooth_3D;
|
||||
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);
|
||||
retval = GG.shaders.maxz_downsample;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (retval == NULL)
|
||||
printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
|
||||
|
||||
@@ -890,6 +979,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;
|
||||
@@ -922,6 +1015,21 @@ void GPU_shader_free_builtin_shaders(void)
|
||||
GG.shaders.smoke_fire = 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;
|
||||
}
|
||||
|
||||
if (GG.shaders.text) {
|
||||
GPU_shader_free(GG.shaders.text);
|
||||
GG.shaders.text = NULL;
|
||||
@@ -1022,6 +1130,13 @@ void GPU_shader_free_builtin_shaders(void)
|
||||
GG.shaders.point_uniform_size_uniform_color_outline_smooth_3D = NULL;
|
||||
}
|
||||
|
||||
for (int 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;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
|
||||
if (GG.shaders.fx_shaders[i]) {
|
||||
GPU_shader_free(GG.shaders.fx_shaders[i]);
|
||||
|
@@ -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)
|
||||
{
|
||||
@@ -273,6 +379,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;
|
||||
@@ -359,11 +469,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
|
||||
@@ -427,7 +537,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;
|
||||
@@ -503,6 +613,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);
|
||||
@@ -531,9 +657,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 */
|
||||
@@ -541,8 +667,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);
|
||||
}
|
||||
@@ -550,9 +678,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 */
|
||||
@@ -566,6 +694,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};
|
||||
|
58
source/blender/gpu/shaders/gpu_shader_display_sh_frag.glsl
Normal file
58
source/blender/gpu/shaders/gpu_shader_display_sh_frag.glsl
Normal file
@@ -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;
|
||||
}
|
13
source/blender/gpu/shaders/gpu_shader_display_sh_vert.glsl
Normal file
13
source/blender/gpu/shaders/gpu_shader_display_sh_vert.glsl
Normal file
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -0,0 +1,6 @@
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_Vertex;
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
}
|
@@ -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);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
263
source/blender/gpu/shaders/gpu_shader_material_bsdf_diffuse.glsl
Normal file
263
source/blender/gpu/shaders/gpu_shader_material_bsdf_diffuse.glsl
Normal file
@@ -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;
|
||||
}
|
345
source/blender/gpu/shaders/gpu_shader_material_bsdf_glass.glsl
Normal file
345
source/blender/gpu/shaders/gpu_shader_material_bsdf_glass.glsl
Normal file
@@ -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);
|
||||
}
|
710
source/blender/gpu/shaders/gpu_shader_material_bsdf_glossy.glsl
Normal file
710
source/blender/gpu/shaders/gpu_shader_material_bsdf_glossy.glsl
Normal file
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
273
source/blender/gpu/shaders/gpu_shader_material_bsdf_toon.glsl
Normal file
273
source/blender/gpu/shaders/gpu_shader_material_bsdf_toon.glsl
Normal file
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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();
|
||||
}
|
156
source/blender/gpu/shaders/gpu_shader_material_bsdf_velvet.glsl
Normal file
156
source/blender/gpu/shaders/gpu_shader_material_bsdf_velvet.glsl
Normal file
@@ -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;
|
||||
}
|
1207
source/blender/gpu/shaders/gpu_shader_material_new_shading.glsl
Normal file
1207
source/blender/gpu/shaders/gpu_shader_material_new_shading.glsl
Normal file
File diff suppressed because it is too large
Load Diff
1113
source/blender/gpu/shaders/gpu_shader_material_utils.glsl
Normal file
1113
source/blender/gpu/shaders/gpu_shader_material_utils.glsl
Normal file
File diff suppressed because it is too large
Load Diff
108
source/blender/gpu/shaders/gpu_shader_probe_sh_compute_frag.glsl
Normal file
108
source/blender/gpu/shaders/gpu_shader_probe_sh_compute_frag.glsl
Normal file
@@ -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);
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
void main()
|
||||
{
|
||||
/* We are using gl_FragCoord inside the fragment shader so nothing fancy here */
|
||||
gl_Position = gl_Vertex;
|
||||
}
|
@@ -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 {
|
||||
|
@@ -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__ */
|
||||
|
@@ -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;
|
||||
|
||||
|
||||
|
@@ -752,6 +752,7 @@ typedef struct NodeTexEnvironment {
|
||||
ImageUser iuser;
|
||||
int color_space;
|
||||
int projection;
|
||||
struct GPUNodeLink *normal_transform_link;
|
||||
int interpolation;
|
||||
int pad;
|
||||
} NodeTexEnvironment;
|
||||
|
@@ -284,9 +284,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 */
|
||||
|
||||
@@ -297,6 +298,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 */
|
||||
@@ -484,6 +502,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 ********************* */
|
||||
|
||||
|
@@ -46,6 +46,7 @@ struct wmTimer;
|
||||
struct Material;
|
||||
struct GPUFX;
|
||||
struct GPUViewport;
|
||||
struct GPUSSR;
|
||||
|
||||
/* This is needed to not let VC choke on near and far... old
|
||||
* proprietary MS extensions... */
|
||||
@@ -243,6 +244,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.
|
||||
*/
|
||||
@@ -324,6 +330,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->tmp_compat_flag */
|
||||
enum {
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -426,10 +426,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;
|
||||
|
||||
@@ -647,9 +650,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;
|
||||
|
@@ -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);
|
||||
|
@@ -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"
|
||||
@@ -194,11 +195,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 */
|
||||
@@ -2131,7 +2209,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 */
|
||||
@@ -2761,6 +2854,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);
|
||||
}
|
||||
|
||||
|
@@ -4865,8 +4865,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)
|
||||
{
|
||||
@@ -4901,6 +4905,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");
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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"
|
||||
|
||||
@@ -540,6 +542,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);
|
||||
@@ -747,6 +766,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)
|
||||
@@ -2317,6 +2345,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)
|
||||
{
|
||||
@@ -2587,6 +2717,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)");
|
||||
@@ -2731,6 +2866,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");
|
||||
@@ -4761,6 +4900,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);
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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, "" }
|
||||
};
|
||||
|
||||
/* 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_diffuse(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
|
||||
{
|
||||
if (!in[2].link)
|
||||
in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
|
||||
else
|
||||
GPU_link(mat, "direction_transform_m4v3", in[2].link, GPU_builtin(GPU_VIEW_MATRIX), &in[2].link);
|
||||
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);
|
||||
}
|
||||
|
||||
return GPU_stack_link(mat, "node_bsdf_diffuse", 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_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 */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
return GPU_stack_link(mat, "node_bsdf_glass", in, out);
|
||||
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;
|
||||
|
||||
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 */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
return GPU_stack_link(mat, "node_bsdf_glossy", in, out);
|
||||
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);
|
||||
|
||||
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 */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
return GPU_stack_link(mat, "node_bsdf_refraction", in, out);
|
||||
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;
|
||||
|
||||
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 */
|
||||
|
@@ -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)
|
||||
{
|
||||
if (!in[3].link)
|
||||
in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
|
||||
else
|
||||
GPU_link(mat, "direction_transform_m4v3", in[3].link, GPU_builtin(GPU_VIEW_MATRIX), &in[3].link);
|
||||
#define IN_COLOR 0
|
||||
#define IN_SIZE 1
|
||||
#define IN_SMOOTH 2
|
||||
#define IN_NORMAL 3
|
||||
|
||||
return GPU_stack_link(mat, "node_bsdf_toon", in, 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->link)
|
||||
return in->link;
|
||||
else
|
||||
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);
|
||||
|
||||
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 */
|
||||
|
@@ -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)
|
||||
{
|
||||
if (!in[1].link)
|
||||
in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
|
||||
else
|
||||
GPU_link(mat, "direction_transform_m4v3", in[1].link, GPU_builtin(GPU_VIEW_MATRIX), &in[1].link);
|
||||
#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[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
|
||||
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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -41,14 +41,47 @@ static bNodeSocketTemplate sh_node_bsdf_velvet_out[] = {
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
|
||||
#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->link)
|
||||
return in->link;
|
||||
else
|
||||
return GPU_uniform(in->vec);
|
||||
}
|
||||
|
||||
static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
|
||||
{
|
||||
if (!in[2].link)
|
||||
in[2].link = GPU_builtin(GPU_VIEW_NORMAL);
|
||||
else
|
||||
GPU_link(mat, "direction_transform_m4v3", in[2].link, GPU_builtin(GPU_VIEW_MATRIX), &in[2].link);
|
||||
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_velvet", in, out);
|
||||
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 */
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
|
@@ -45,6 +45,7 @@ static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *UNUSED(node), bNodeE
|
||||
in[1].link = GPU_builtin(GPU_VIEW_NORMAL);
|
||||
}
|
||||
else if (GPU_material_use_world_space_shading(mat)) {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -38,7 +38,6 @@ static bNodeSocketTemplate sh_node_holdout_out[] = {
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
|
||||
|
||||
/* node type definition */
|
||||
void register_node_type_sh_holdout(void)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
@@ -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));
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user