1
1

Compare commits

...

84 Commits

Author SHA1 Message Date
Dalai Felinto
f87036e8a7 the maxz and minz shaders were not being compiled 2016-11-02 19:52:15 +01:00
Dalai Felinto
f8a1255464 Fix left over from merge
Linux did not mind with them, but luckily Linux is more strict
2016-11-01 22:00:47 +01:00
Dalai Felinto
0497b012a3 Cleanups to make the patch lean 2016-10-21 12:59:03 +00:00
Dalai Felinto
669c2801c0 'gmon.out' should have never been here 2016-10-21 12:51:27 +00:00
Dalai Felinto
d26de5c907 Merge remote-tracking branch 'origin/blender2.8' into pbr-viewport 2016-10-21 12:50:28 +00:00
Dalai Felinto
1640ea89e5 Merge remote-tracking branch 'origin/blender2.8' into pbr-viewport
Conflicts:
	source/blender/blenloader/intern/versioning_270.c
	source/blender/editors/space_view3d/drawobject.c
2016-10-21 12:29:08 +00:00
Dalai Felinto
d74f6b2204 Merge remote-tracking branch 'origin/blender2.8' into pbr-merge
Conflicts:
	source/blender/blenloader/intern/versioning_defaults.c
	source/blender/editors/space_view3d/drawobject.c
	source/blender/editors/space_view3d/space_view3d.c
	source/blender/editors/space_view3d/view3d_draw.c
	source/blender/gpu/CMakeLists.txt
	source/blender/gpu/GPU_framebuffer.h
	source/blender/gpu/GPU_material.h
	source/blender/gpu/GPU_shader.h
	source/blender/gpu/intern/gpu_codegen.c
	source/blender/gpu/intern/gpu_draw.c
	source/blender/gpu/intern/gpu_framebuffer.c
	source/blender/gpu/intern/gpu_material.c
	source/blender/gpu/intern/gpu_shader.c
	source/blender/makesdna/DNA_view3d_types.h
2016-10-20 21:40:30 +00:00
Dalai Felinto
4948b6e226 Merge remote-tracking branch 'origin/master' into pbr-merge
Conflicts:
	source/blender/editors/space_view3d/view3d_draw.c
2016-10-20 19:37:36 +00:00
Dalai Felinto
feff6b4df3 Merge commit 'e5c32844678e292a084d6d97eb2d4ba6affc217d' into pbr-merge
Conflicts:
	source/blender/gpu/shaders/gpu_shader_material.glsl
2016-10-20 18:29:32 +00:00
Dalai Felinto
12c0394a4f Merge commit '4b046c530d3e14d7737c4770b9ae07942f4c6047' into pbr-merge
Conflicts:
	source/blender/nodes/shader/nodes/node_shader_fresnel.c
2016-10-20 18:23:17 +00:00
Dalai Felinto
06b5508073 Merge commit '4b046c530d3e14d7737c4770b9ae07942f4c6047^' into pbr-merge 2016-10-20 18:16:24 +00:00
Dalai Felinto
6f81e808e3 Merge commit '2b240b0430787814316f3b3166453c6d85b017f3' into pbr-merge
Conflicts:
	release/datafiles/splash.png
	release/datafiles/splash_2x.png
	source/blender/gpu/CMakeLists.txt
	source/blender/gpu/intern/gpu_shader.c
2016-10-20 17:44:51 +00:00
Dalai Felinto
d0989e538e Merge commit '7830ec54186e8b05a366775e02c6457eb83814a3' into pbr-merge
Conflicts:
	source/blender/nodes/shader/nodes/node_shader_texture.c
2016-10-20 17:26:16 +00:00
Dalai Felinto
418b24551e Merge commit '9269574089a742130f02c0a1184a19d94f0e665d' into pbr-online
Merge conflicts fixes include fix on ob->reflectionplane for write and
read, and a few manual fixes to account for the ID remap changes

Conflicts:
	source/blender/blenkernel/intern/object.c
	source/blender/blenkernel/intern/world.c
	source/blender/blenloader/intern/writefile.c
	source/blender/editors/space_view3d/view3d_draw.c
	source/blender/gpu/GPU_draw.h
	source/blender/gpu/intern/gpu_draw.c
	source/blender/gpu/intern/gpu_material.c
	source/blender/gpu/intern/gpu_texture.c
	source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
2016-10-20 17:00:49 +00:00
Clément Fukhaut
a84794b399 Worked on HiZRaytracing 2016-09-04 18:56:03 +02:00
Clément Fukhaut
20fa91bd47 Early Hi-Z raytrace implementation (not functional yet) 2016-07-05 23:56:22 +02:00
Clément Fukhaut
ddfae3d2e1 I should sleep sometimes 2016-06-16 19:02:10 +02:00
turjuque
4cae0cb418 Fix texelFetch for older opengl version. 2016-06-16 01:47:07 +02:00
turjuque
22c83011a9 Fix Crash. 2016-06-16 01:46:36 +02:00
turjuque
d2ec40b8f5 Fixed crash with no material meshes 2016-06-06 18:29:46 +02:00
Clément Fukhaut
31d65359e8 Fix compilation error 2016-06-06 11:57:49 +02:00
Clément Fukhaut
554952d114 Remove SSR distance
Fixed Vertex shader not compiling for world nodetree
2016-06-05 19:45:50 +02:00
Clément Fukhaut
d85b6b86cf Fixed Planar reflection
Added Thickness parameter to SSR
2016-06-05 19:13:21 +02:00
Clément Fukhaut
db461850d7 Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/gpu/shaders/gpu_shader_material.glsl
2016-06-05 16:29:41 +02:00
Clément Fukhaut
d28c4d4a7c Polishing UI and added new splash 2016-06-05 15:59:05 +02:00
Clément Fukhaut
96f6372a07 Added closest filtering.
This may not be compatible with all hardware but it's texture binding independant.
2016-06-05 15:58:09 +02:00
Clément Fukhaut
9c8fbd9813 Fix transparent renders. 2016-06-05 15:56:39 +02:00
Clément Fukhaut
fbf7e5acfb -Finished SSR Integration
-Added HiZ bufffer generation for future HiZ raytracing
-Rewritten probe choosing code
-Fixed glossy aniso mistakes
2016-06-04 21:38:03 +02:00
Clément Fukhaut
d7d0166386 -Fixed SSR : Using depth buffer for increased precision but using another slot
-Fixed some typos
2016-05-31 18:08:18 +02:00
Clément Fukhaut
6ebbef4724 Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/gpu/intern/gpu_draw.c
#	source/blender/gpu/shaders/gpu_shader_material.glsl
#	source/blender/makesdna/DNA_view3d_types.h
#	source/blender/nodes/shader/nodes/node_shader_normal_map.c
#	source/blender/nodes/shader/nodes/node_shader_tex_environment.c
#	source/blender/nodes/shader/nodes/node_shader_tex_image.c
#	source/blender/nodes/shader/nodes/node_shader_tex_noise.c
#	source/blender/nodes/shader/nodes/node_shader_texture.c
2016-05-30 20:09:02 +02:00
Clément Fukhaut
bcf5e1c7f5 -Added Material Layer Override
-Unified SSAO settings
-Added GPU_ltc.h to hold the luts
-Simplier SSR Settings
-Reworked Anisotropic shaders (now matching Cycles)
-Finished adding other distributions
-Added Specular AO
2016-05-30 17:45:17 +02:00
Clément Fukhaut
4841e60261 Added ambient occlusion support in material
Algorithm is slow but high quality
Added backface buffer to compute per pixel thickness
Sampling quality is passed via uniforms and not via constants : this is a little slower but it does not need to recompile shader every time
Moved some code for organisation.
2016-05-25 19:12:13 +02:00
Clément Fukhaut
7e4d937718 Started adding beckmann distribution.
Improved Sun disk equations.
Adde Tried Ray aligned disk intersection to match cycles
but it's not working on microfacet bsdf for now.
2016-05-21 12:58:39 +02:00
Clément Fukhaut
579d16714f Fixing area light orientation. 2016-05-15 17:37:12 +02:00
Clément Fukhaut
d949b28199 Fixes Bug with invalid framebuffer operation in solid mode. 2016-05-15 00:04:24 +02:00
Clément Fukhaut
e54385f059 Implemented Linearly Transformed Cosines for area light.
Used for Glossy GGX and Diffuse only for now.
2016-05-07 03:28:28 +02:00
Clément Fukhaut
b372028836 Optimisation. Only run the shadow calculation and light color once per light per material.
Compared to once per light per bsdfs. Only for cycles material mode.
2016-05-06 19:34:46 +02:00
Clément Fukhaut
105a1d84c4 Huge codebase changes :
- Made ssfx "module" to manage screen space effects applied at material stage
- Moved probe functions to their own module
- Divided Shading glsl file into bits that are gathered when making glsl_material_library making files shorter and more organized
- Moved function generating luts and random texture to gpu_luts.c that will contains all textures needed to acheive some effects.
- GPU_PBR in GPUBuiltin is just a placeholder to trigger the uniform binding

Optimisation / correction :
- GLSL : Number of bsdf sample is now passed via an uniform instead of a #define. This means changing quality settings will no longer recompute every shaders in the scene. But this has a small perf cost.
- GLSL : Hammersley numbers are precalculated and stored inside a texture. This may have a performance impact and I will change it to a static table.
- GLSL : Random per pixel numbers are done using a texture like SSAO.
- GLSL : Lots of parameters (only for pbr) are now defined as uniform and passed at binding stage (this minimize the use of GPU_builtin).
- GLSL : most variables used in sampling algorythm are defined as global variables.
- Bsdf sampling is now using the real algorithm and not the split sum approximation (which was unecessary).

Features :
- Added toon shader support (only point light support).
- Added holdout.
2016-05-06 15:55:15 +02:00
Clément Fukhaut
80f03704e7 Fix Opengl problem on OSX 2016-05-06 15:13:30 +02:00
Clément Fukhaut
655cfca452 Implemented SSR :
- Still pretty rough implementation does only works with sharp glossy shader
- No Glossy reflection
- 2 algorithm but only one acheive decent results the other needs to be debuged.

Changed pbr settings location :
- They are now stored in structs like the FX options
2016-05-03 19:41:41 +02:00
Clément Fukhaut
7c777fe038 Oren-nayar Diffuse & Velvet Shader Environment lighting support. 2016-04-16 12:54:40 +02:00
Clément Fukhaut
81737e6cca Fix bug when capturing object with planar reflections. 2016-04-16 12:53:22 +02:00
Clément Fukhaut
515be07dd4 Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/gpu/shaders/gpu_shader_material.glsl
2016-04-11 21:24:12 +02:00
Clément Fukhaut
7750dea70e Last minute changes :
- Changed splash
- Added bypass for lamps diffuse and specular contribution
- Added probe related operators

Signed-off-by: Clément Foucault <foucault.clem@gmail.com>
2016-04-11 19:59:29 +02:00
Clément Fukhaut
f50bf4f110 Fixed color correction post process.
Signed-off-by: Clément Foucault <foucault.clem@gmail.com>
2016-04-11 19:54:39 +02:00
Clément Fukhaut
c1580b9cd4 Fixed Probe unlinking on refresh. 2016-04-05 22:24:31 +02:00
Clément Fukhaut
c112a54d2a Fix crash with world preview & icons. 2016-04-05 22:14:25 +02:00
Clément Fukhaut
1cd2d7b744 Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/gpu/intern/gpu_material.c
#	source/blender/gpu/intern/gpu_shader.c
2016-04-05 00:15:30 +02:00
Clément Fukhaut
798357ca57 Planar Probe, Probe options, Probe Parallax :
- Added Planar Reflections and Refractions:
Rough planar reflection/refraction are roughly approximated by blurring with the microfacet normal direction. We blend to a fallback cubemap for high roughness. They are also displaced using the viewnormals. This last deformation is divided by the distance to the shaded point and multiplied by the distance to the reflection plane to get contact reflections.

- Added options to probes.
Probe can now only render their layers. Diffuse can be disabled (in case of use with a lightmap). Added Operator to manualy update probes.

- Probe parallax:
Correct the rays to project it to the chosen volume (unit cube or sphere) after being corrected by the obj mat (either own or external).

- Probe updates are a bit more consistent.

- Moved PBR light UI from Cycles to Blender sources.

- Added versioning code to update old file with non breaking defaults.

Signed-off-by: Clément Foucault <foucault.clem@gmail.com>
2016-04-04 21:46:20 +02:00
Clément Fukhaut
b818de11df Fixed crash when world is absent. 2016-03-21 22:13:58 +01:00
turjuque
ef01bfd53d Fix compilation issue on linux. 2016-03-20 21:49:36 +01:00
Clément Fukhaut
bb9d7491e8 Changed Splash version number 2016-03-20 17:04:30 +01:00
Clément Fukhaut
37300f3307 Fix #3 : Clamp mix factor. 2016-03-20 16:12:46 +01:00
Clément Fukhaut
ed3a8ae7b3 Removing some debug printf 2016-03-20 15:42:22 +01:00
Clément Fukhaut
9a0e6c1883 Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	release/datafiles/splash.png
#	release/datafiles/splash_2x.png
#	source/blender/gpu/GPU_material.h
#	source/blender/gpu/shaders/gpu_shader_material.glsl
#	source/blender/makesrna/intern/rna_image_api.c
#	source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c
#	source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
#	source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c
#	source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
#	source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
#	source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c
#	source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c
#	source/blender/nodes/shader/nodes/node_shader_fresnel.c
#	source/blender/nodes/shader/nodes/node_shader_layer_weight.c
#	source/blender/nodes/shader/nodes/node_shader_normal_map.c
2016-03-20 15:25:02 +01:00
Clément Fukhaut
b6d97ce425 Viewport Probe capture for bsdf preview:
- Added a GPUProbe generated by either the world or objects in the scene.
Updating is done by tagging the GPUProbe and waiting the gpu_update_probes call.
All probes are updated if the world changes and all objects probes are updated if an object in the scene changes. This must be optimize to ensure good performance with lots of probes.
For the moment no settings are available.

- Separated bsdf sampling code inside a new file.

- Spherical harmonic computation is now done on the GPU. Using only 64*64*6 samples for now.

- Lots of code cleaning and formating.
2016-03-20 15:08:30 +01:00
Clément Fukhaut
1eb5ff3bbd Exclude Translucent surfaces from shadows. 2016-02-21 23:01:22 +01:00
Clément Fukhaut
240e995062 Merge branch 'master' of git://git.blender.org/blender 2016-02-21 22:38:57 +01:00
Clément Fukhaut
7e0cb40b48 Giving user more control over the shadows. Enabling shadows for Area lamps. 2016-02-21 21:09:27 +01:00
Clément Fukhaut
9974ada602 Merge branch 'master' of git://git.blender.org/blender 2016-02-17 22:27:20 +01:00
Clément Fukhaut
b3c3275dad Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/gpu/shaders/gpu_shader_material.glsl
2016-02-17 22:24:29 +01:00
Clément Fukhaut
8de5664a60 Added support for custom number of samples for brdfs. 2016-02-14 22:42:20 +01:00
Clément Fukhaut
52cb2981c4 Fix layer weight and light's geometry nodes 2016-02-14 22:32:30 +01:00
Clément Fukhaut
4b08c4d0ae Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/gpu/intern/gpu_material.c
#	source/blender/gpu/shaders/gpu_shader_material.glsl
2016-02-14 14:53:40 +01:00
Clément Fukhaut
bec580b0f9 Tangent node support in GLSL (only with selected uv) 2016-02-02 00:27:11 +01:00
Clément Fukhaut
e217b66505 Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/gpu/GPU_texture.h
2016-02-01 23:23:30 +01:00
Clément Fukhaut
6d33b1031a Fix bug #1 2016-01-31 21:40:19 +01:00
Clément Fukhaut
051c9c39d4 Make use of new direction_transform_m4v3. Add restriction to the display of show_world_sh. 2016-01-28 16:31:35 +01:00
Clément Fukhaut
20afa77324 Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/editors/space_view3d/drawmesh.c
#	source/blender/gpu/CMakeLists.txt
#	source/blender/gpu/GPU_draw.h
#	source/blender/gpu/GPU_material.h
#	source/blender/gpu/GPU_texture.h
#	source/blender/gpu/intern/gpu_codegen.c
#	source/blender/gpu/intern/gpu_draw.c
#	source/blender/gpu/intern/gpu_material.c
#	source/blender/gpu/intern/gpu_shader.c
#	source/blender/gpu/intern/gpu_texture.c
#	source/blender/makesrna/intern/rna_image_api.c
#	source/blender/nodes/shader/nodes/node_shader_vectTransform.c
2016-01-28 14:44:58 +01:00
Clément Fukhaut
371c289af8 Made these changes, all relative to the viewport Material mode.
-Lamp sizes are now binded with dynamic uniforms
-Added support of Anisotropic Bsdf
-Added support of Glossy Refraction Bsdf
-Added support of Glossy Glass Bsdf
-Texture noise uses the same default coordinates as cycles.
-Vector transform now works with translations (point mode).
-Vector transform now works with translations.
-Transparency for transparent Bsdf now uses the alpha input.
-Lots of code formating
-Default tangent space inside Geometry node
-Added support for Tangent node
-Object Info now output object location correctly
2016-01-28 00:46:08 +01:00
Clément Fukhaut
59295b9126 Fixing problems with macOSX opengl. Thanks to Marcelo Varanda. 2016-01-20 01:36:27 +01:00
Clément Fukhaut
f0f398c0dd Fix sun intensity and fix a bug for some graphics cards. 2016-01-18 22:18:53 +01:00
Clément Fukhaut
a3a0220d57 Using the brdf path for default material. And fixing stuff. 2016-01-08 04:06:41 +01:00
Clément Fukhaut
df63042d8f Fixing Glass shader color. 2016-01-08 03:09:32 +01:00
Clément Fukhaut
3155b440bf Fix backward compatibility. 2016-01-08 02:30:34 +01:00
Clément Fukhaut
01a258f829 Started Velvet support in viewport code. 2016-01-07 02:42:18 +01:00
turjuque
a30e73bf67 Making things work again 2016-01-06 23:29:23 +01:00
turjuque
c326d403d8 Merge branch 'master' of github.com:Hypersomniac/blender-shader
# Conflicts:
#	source/blender/gpu/GPU_material.h
#	source/blender/gpu/SConscript
#	source/blender/gpu/intern/gpu_compositing.c
#	source/blender/gpu/intern/gpu_extensions.c
#	source/blender/gpu/intern/gpu_material.c
#	source/blender/gpu/shaders/gpu_shader_material.glsl
#	source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c
#	source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c
#	source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
2016-01-06 22:19:37 +01:00
turjuque
44aeca9023 Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/editors/space_view3d/drawmesh.c
#	source/blender/gpu/GPU_extensions.h
#	source/blender/gpu/SConscript
#	source/blender/gpu/intern/gpu_compositing.c
#	source/blender/gpu/intern/gpu_extensions.c
#	source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp
2016-01-06 22:14:30 +01:00
turjuque
c89ced47bb PRB viewport : Adding lamp support and post effects. and lots of gpu stuff.
No more leaks.
2016-01-06 21:38:06 +01:00
turjuque
83aeba94c7 PRB viewport : Adding lamp support and post effects. and lots of gpu stuff. 2015-12-23 23:48:23 +01:00
turjuque
4aebb28e60 Added checkboxes for display options 2015-11-26 02:50:33 +01:00
turjuque
863923d3d0 Merge branch 'master' of git://git.blender.org/blender
# Conflicts:
#	source/blender/gpu/intern/gpu_material.c
#	source/blender/makesdna/DNA_node_types.h
2015-11-25 19:02:14 +01:00
turjuque
83a54dc2a8 PBR Implementation 2015-11-25 18:43:12 +01:00
112 changed files with 11660 additions and 1660 deletions

View File

@@ -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'}

View File

@@ -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,

View File

@@ -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"

View File

@@ -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")

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
}
}
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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);

View 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;
}

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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))

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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)

View File

@@ -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(

View File

@@ -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);

View File

@@ -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 */

File diff suppressed because one or more lines are too long

View File

@@ -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]);

View 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__ */

View 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__*/

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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

View 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);
}
}
}

View 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();
}

View File

@@ -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]);

View File

@@ -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, &ltc_mat_ggx[0], true, true, 4, NULL);
}
GPUTexture *GPU_create_ltc_mag_ggx_lut_texture(void)
{
return GPU_texture_create_2D_procedural(64, 64, &ltc_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};

View 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;
}

View 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);
}

View File

@@ -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);
}

View File

@@ -0,0 +1,6 @@
void main()
{
gl_Position = gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View 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;
}

View 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);
}

View 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);
}

View File

@@ -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;
}

View 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);
}

View File

@@ -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);
}

View File

@@ -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();
}

View 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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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);
}

View File

@@ -0,0 +1,5 @@
void main()
{
/* We are using gl_FragCoord inside the fragment shader so nothing fancy here */
gl_Position = gl_Vertex;
}

View File

@@ -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 {

View File

@@ -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__ */

View File

@@ -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;

View File

@@ -752,6 +752,7 @@ typedef struct NodeTexEnvironment {
ImageUser iuser;
int color_space;
int projection;
struct GPUNodeLink *normal_transform_link;
int interpolation;
int pad;
} NodeTexEnvironment;

View File

@@ -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 ********************* */

View File

@@ -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 {

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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");
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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);
}

View File

@@ -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)
{

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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));
}

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -38,7 +38,6 @@ static bNodeSocketTemplate sh_node_holdout_out[] = {
{ -1, 0, "" }
};
/* node type definition */
void register_node_type_sh_holdout(void)
{

View File

@@ -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);

View File

@@ -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));
}

View File

@@ -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