Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/CMakeLists.txt133
-rw-r--r--source/blender/gpu/GPU_basic_shader.h9
-rw-r--r--source/blender/gpu/GPU_batch.h74
-rw-r--r--source/blender/gpu/GPU_buffers.h194
-rw-r--r--source/blender/gpu/GPU_compositing.h106
-rw-r--r--source/blender/gpu/GPU_debug.h18
-rw-r--r--source/blender/gpu/GPU_draw.h85
-rw-r--r--source/blender/gpu/GPU_extensions.h9
-rw-r--r--source/blender/gpu/GPU_framebuffer.h151
-rw-r--r--source/blender/gpu/GPU_glew.h4
-rw-r--r--source/blender/gpu/GPU_immediate.h58
-rw-r--r--source/blender/gpu/GPU_immediate_util.h64
-rw-r--r--source/blender/gpu/GPU_legacy_stubs.h457
-rw-r--r--source/blender/gpu/GPU_material.h188
-rw-r--r--source/blender/gpu/GPU_matrix.h190
-rw-r--r--source/blender/gpu/GPU_select.h3
-rw-r--r--source/blender/gpu/GPU_shader.h289
-rw-r--r--source/blender/gpu/GPU_texture.h139
-rw-r--r--source/blender/gpu/GPU_uniformbuffer.h59
-rw-r--r--source/blender/gpu/GPU_viewport.h130
-rw-r--r--source/blender/gpu/intern/gpu_basic_shader.c413
-rw-r--r--source/blender/gpu/intern/gpu_batch.c281
-rw-r--r--source/blender/gpu/intern/gpu_batch_presets.c236
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c1696
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c834
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h39
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c1461
-rw-r--r--source/blender/gpu/intern/gpu_debug.c700
-rw-r--r--source/blender/gpu/intern/gpu_draw.c1586
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c122
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c943
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c88
-rw-r--r--source/blender/gpu/intern/gpu_immediate_util.c424
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c18
-rw-r--r--source/blender/gpu/intern/gpu_material.c2952
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c649
-rw-r--r--source/blender/gpu/intern/gpu_select.c33
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c12
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c25
-rw-r--r--source/blender/gpu/intern/gpu_shader.c860
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.h44
-rw-r--r--source/blender/gpu/intern/gpu_texture.c1155
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.c378
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c644
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl48
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl35
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl54
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl56
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl59
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl107
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl27
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_vert.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl40
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl202
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl64
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl26
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl26
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_vert.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_frag.glsl37
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_geom.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_checker_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl54
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl60
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl68
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl44
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl67
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl52
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fire_frag.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_flat_id_frag.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl5
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl111
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl68
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl39
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl34
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl45
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_lib.glsl7
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl23
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_vert.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_geometry.glsl18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_desaturate_frag.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_frag.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl34
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl30
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl124
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl50
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl25
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl57
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl63
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl27
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl32
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl29
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl23
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl31
-rw-r--r--source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl34
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl2415
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl17
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl36
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl31
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl19
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl19
-rw-r--r--source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl7
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_frag.glsl74
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_geom.glsl37
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl36
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_text_vert.glsl17
-rw-r--r--source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex.glsl19
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex_world.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl7
160 files changed, 11610 insertions, 11983 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 885ff2ff159..481133ba984 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -31,6 +31,9 @@ set(INC
../imbuf
../makesdna
../makesrna
+ ../draw
+
+ ../editors/include
# For node muting stuff...
../nodes
@@ -39,6 +42,7 @@ set(INC
../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/smoke/extern
+ ../../../intern/gawain
)
set(INC_SYS
@@ -47,20 +51,26 @@ set(INC_SYS
set(SRC
intern/gpu_basic_shader.c
+ intern/gpu_batch.c
+ intern/gpu_batch_presets.c
intern/gpu_buffers.c
intern/gpu_codegen.c
- intern/gpu_compositing.c
intern/gpu_debug.c
intern/gpu_draw.c
intern/gpu_extensions.c
intern/gpu_framebuffer.c
+ intern/gpu_immediate.c
+ intern/gpu_immediate_util.c
intern/gpu_init_exit.c
intern/gpu_material.c
+ intern/gpu_matrix.c
intern/gpu_select.c
intern/gpu_select_pick.c
intern/gpu_select_sample_query.c
intern/gpu_shader.c
intern/gpu_texture.c
+ intern/gpu_uniformbuffer.c
+ intern/gpu_viewport.c
shaders/gpu_shader_fx_lib.glsl
shaders/gpu_shader_fx_ssao_frag.glsl
@@ -69,7 +79,6 @@ set(SRC
shaders/gpu_shader_fx_dof_hq_frag.glsl
shaders/gpu_shader_fx_dof_hq_vert.glsl
shaders/gpu_shader_fx_dof_hq_geo.glsl
- shaders/gpu_shader_fx_vert.glsl
shaders/gpu_shader_material.glsl
shaders/gpu_shader_sep_gaussian_blur_frag.glsl
shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -85,23 +94,128 @@ set(SRC
shaders/gpu_shader_smoke_vert.glsl
GPU_basic_shader.h
+ GPU_batch.h
GPU_buffers.h
- GPU_compositing.h
GPU_debug.h
GPU_draw.h
GPU_extensions.h
GPU_framebuffer.h
GPU_glew.h
+ GPU_immediate.h
+ GPU_immediate_util.h
GPU_init_exit.h
+ GPU_legacy_stubs.h
GPU_material.h
+ GPU_matrix.h
GPU_select.h
GPU_shader.h
GPU_texture.h
+ GPU_uniformbuffer.h
+ GPU_viewport.h
+
intern/gpu_codegen.h
intern/gpu_private.h
intern/gpu_select_private.h
+ intern/gpu_shader_private.h
)
+data_to_c_simple(shaders/gpu_shader_depth_only_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_uniform_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_checker_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_diag_stripes_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_simple_lighting_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_flat_id_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_base_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_base_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_shadow_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_widget_shadow_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_nodelink_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_nodelink_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_flat_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_line_dashed_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_line_dashed_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_image_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_image_rect_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_image_multi_rect_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_desaturate_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_linear_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_shuffle_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_mask_uniform_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_alpha_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_varying_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_depth_copy_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_multisample_resolve_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_normal_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_normal_smooth_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_smooth_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_passthrough_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl SRC)
+
+data_to_c_simple(shaders/gpu_shader_instance_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_screen_aligned_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_camera_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_distance_line_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_vert.glsl SRC)
+
+data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC)
+
+data_to_c_simple(shaders/gpu_shader_point_uniform_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_uniform_color_aa_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_varying_color_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl SRC)
+
+data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_front_back_ortho_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_overlay_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_overlay_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_overlay_simple_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_edges_overlay_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_simple_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_simple_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_text_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_keyframe_diamond_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC)
+
data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fire_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_smoke_frag.glsl SRC)
@@ -116,19 +230,6 @@ data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC)
-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_lib.glsl SRC)
-
-if(WITH_GAMEENGINE)
- add_definitions(-DWITH_GAMEENGINE)
-endif()
if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)
diff --git a/source/blender/gpu/GPU_basic_shader.h b/source/blender/gpu/GPU_basic_shader.h
index d9bf3d1ced3..dc378927e79 100644
--- a/source/blender/gpu/GPU_basic_shader.h
+++ b/source/blender/gpu/GPU_basic_shader.h
@@ -64,12 +64,6 @@ typedef enum GPUBasicShaderStipple {
GPU_SHADER_STIPPLE_HEXAGON = 3,
GPU_SHADER_STIPPLE_DIAG_STRIPES = 4,
GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP = 5,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW = 6,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW_SWAP = 7,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN = 8,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN_SWAP = 9,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER = 10,
- GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER_SWAP = 11
} GPUBasicShaderStipple;
void GPU_basic_shaders_init(void);
@@ -132,9 +126,6 @@ void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id);
void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern);
void GPU_basic_shader_line_width(float line_width);
-bool GPU_basic_shader_use_glsl_get(void);
-void GPU_basic_shader_use_glsl_set(bool enabled);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
new file mode 100644
index 00000000000..b706bdbf189
--- /dev/null
+++ b/source/blender/gpu/GPU_batch.h
@@ -0,0 +1,74 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Batched geometry rendering is powered by the Gawain library.
+ * This file contains any additions or modifications specific to Blender.
+ */
+
+#ifndef __GPU_BATCH_H__
+#define __GPU_BATCH_H__
+
+#include "../../../intern/gawain/gawain/gwn_batch.h"
+#include "../../../intern/gawain/gawain/gwn_batch_private.h"
+
+struct rctf;
+
+// TODO: CMake magic to do this:
+// #include "gawain/batch.h"
+
+#include "BLI_compiler_attrs.h"
+#include "BLI_sys_types.h"
+
+#include "GPU_shader.h"
+
+/* Extend GWN_batch_program_set to use Blender’s library of built-in shader programs. */
+
+/* gpu_batch.c */
+void GWN_batch_program_set_builtin(Gwn_Batch *batch, GPUBuiltinShader shader_id) ATTR_NONNULL(1);
+
+Gwn_Batch *GPU_batch_tris_from_poly_2d_encoded(
+ const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
+ const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+
+void gpu_batch_init(void);
+void gpu_batch_exit(void);
+
+/* gpu_batch_presets.c */
+/* Only use by draw manager. Use the presets function instead for interface. */
+Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res) ATTR_WARN_UNUSED_RESULT;
+/* Replacement for gluSphere */
+Gwn_Batch *GPU_batch_preset_sphere(int lod) ATTR_WARN_UNUSED_RESULT;
+Gwn_Batch *GPU_batch_preset_sphere_wire(int lod) ATTR_WARN_UNUSED_RESULT;
+
+void gpu_batch_presets_init(void);
+void gpu_batch_presets_register(Gwn_Batch *preset_batch);
+void gpu_batch_presets_reset(void);
+void gpu_batch_presets_exit(void);
+
+#endif /* __GPU_BATCH_H__ */
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index 6ffaa29ead6..f496c92f283 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -32,191 +32,19 @@
#ifndef __GPU_BUFFERS_H__
#define __GPU_BUFFERS_H__
-#ifdef DEBUG
-/* #define DEBUG_VBO(X) printf(X)*/
-# define DEBUG_VBO(X)
-#else
-# define DEBUG_VBO(X)
-#endif
-
#include <stddef.h>
struct BMesh;
struct CCGElem;
struct CCGKey;
struct DMFlagMat;
-struct DerivedMesh;
-struct GSet;
-struct GPUVertPointLink;
-struct GPUDrawObject;
struct GridCommonGPUBuffer;
-struct PBVH;
+struct GSet;
+struct MLoop;
+struct MLoopTri;
+struct MPoly;
struct MVert;
-
-typedef struct GPUBuffer {
- size_t size; /* in bytes */
- unsigned int id; /* used with vertex buffer objects */
-} GPUBuffer;
-
-typedef struct GPUBufferMaterial {
- /* range of points used for this material */
- unsigned int start;
- unsigned int totelements;
- unsigned int totloops;
- unsigned int *polys; /* array of polygons for this material */
- unsigned int totpolys; /* total polygons in polys */
- unsigned int totvisiblepolys; /* total visible polygons */
-
- /* original material index */
- short mat_nr;
-} GPUBufferMaterial;
-
-void GPU_buffer_material_finalize(struct GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat);
-
-/* meshes are split up by material since changing materials requires
- * GL state changes that can't occur in the middle of drawing an
- * array.
- *
- * some simplifying assumptions are made:
- * - all quads are treated as two triangles.
- * - no vertex sharing is used; each triangle gets its own copy of the
- * vertices it uses (this makes it easy to deal with a vertex used
- * by faces with different properties, such as smooth/solid shading,
- * different MCols, etc.)
- *
- * to avoid confusion between the original MVert vertices and the
- * arrays of OpenGL vertices, the latter are referred to here and in
- * the source as `points'. similarly, the OpenGL triangles generated
- * for MFaces are referred to as triangles rather than faces.
- */
-typedef struct GPUDrawObject {
- GPUBuffer *points;
- GPUBuffer *normals;
- GPUBuffer *uv;
- GPUBuffer *uv_tex;
- GPUBuffer *colors;
- GPUBuffer *edges;
- GPUBuffer *uvedges;
- GPUBuffer *triangles; /* triangle index buffer */
-
- /* for each original vertex, the list of related points */
- struct GPUVertPointLink *vert_points;
-
- /* see: USE_GPU_POINT_LINK define */
-#if 0
- /* storage for the vert_points lists */
- struct GPUVertPointLink *vert_points_mem;
- int vert_points_usage;
-#endif
-
- int colType;
-
- GPUBufferMaterial *materials;
- int totmaterial;
-
- unsigned int tot_triangle_point;
- unsigned int tot_loose_point;
- /* different than total loops since ngons get tesselated still */
- unsigned int tot_loop_verts;
-
- /* caches of the original DerivedMesh values */
- unsigned int totvert;
- unsigned int totedge;
-
- unsigned int loose_edge_offset;
- unsigned int tot_loose_edge_drawn;
- unsigned int tot_edge_drawn;
-
- /* for subsurf, offset where drawing of interior edges starts */
- unsigned int interior_offset;
- unsigned int totinterior;
-} GPUDrawObject;
-
-/* currently unused */
-// #define USE_GPU_POINT_LINK
-
-typedef struct GPUVertPointLink {
-#ifdef USE_GPU_POINT_LINK
- struct GPUVertPointLink *next;
-#endif
- /* -1 means uninitialized */
- int point_index;
-} GPUVertPointLink;
-
-
-
-/* used for GLSL materials */
-typedef struct GPUAttrib {
- int index;
- int info_index;
- int size;
- int type;
-} GPUAttrib;
-
-void GPU_global_buffer_pool_free(void);
-void GPU_global_buffer_pool_free_unused(void);
-
-GPUBuffer *GPU_buffer_alloc(size_t size);
-void GPU_buffer_free(GPUBuffer *buffer);
-
-void GPU_drawobject_free(struct DerivedMesh *dm);
-
-/* flag that controls data type to fill buffer with, a modifier will prepare. */
-typedef enum {
- GPU_BUFFER_VERTEX = 0,
- GPU_BUFFER_NORMAL,
- GPU_BUFFER_COLOR,
- GPU_BUFFER_UV,
- GPU_BUFFER_UV_TEXPAINT,
- GPU_BUFFER_EDGE,
- GPU_BUFFER_UVEDGE,
- GPU_BUFFER_TRIANGLES
-} GPUBufferType;
-
-typedef enum {
- GPU_BINDING_ARRAY = 0,
- GPU_BINDING_INDEX = 1,
-} GPUBindingType;
-
-typedef enum {
- GPU_ATTR_INFO_SRGB = (1 << 0),
-} GPUAttrInfo;
-
-/* called before drawing */
-void GPU_vertex_setup(struct DerivedMesh *dm);
-void GPU_normal_setup(struct DerivedMesh *dm);
-void GPU_uv_setup(struct DerivedMesh *dm);
-void GPU_texpaint_uv_setup(struct DerivedMesh *dm);
-/* colType is the cddata MCol type to use! */
-void GPU_color_setup(struct DerivedMesh *dm, int colType);
-void GPU_buffer_bind_as_color(GPUBuffer *buffer);
-void GPU_edge_setup(struct DerivedMesh *dm); /* does not mix with other data */
-void GPU_uvedge_setup(struct DerivedMesh *dm);
-
-void GPU_triangle_setup(struct DerivedMesh *dm);
-
-int GPU_attrib_element_size(GPUAttrib data[], int numdata);
-void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata, int element_size);
-
-void GPU_buffer_bind(GPUBuffer *buffer, GPUBindingType binding);
-void GPU_buffer_unbind(GPUBuffer *buffer, GPUBindingType binding);
-
-/* can't lock more than one buffer at once */
-void *GPU_buffer_lock(GPUBuffer *buffer, GPUBindingType binding);
-void *GPU_buffer_lock_stream(GPUBuffer *buffer, GPUBindingType binding);
-void GPU_buffer_unlock(GPUBuffer *buffer, GPUBindingType binding);
-
-/* switch color rendering on=1/off=0 */
-void GPU_color_switch(int mode);
-
-/* used for drawing edges */
-void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count);
-
-/* called after drawing */
-void GPU_buffers_unbind(void);
-
-/* only unbind interleaved data */
-void GPU_interleaved_attrib_unbind(void);
+struct PBVH;
/* Buffers for non-DerivedMesh drawing */
typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
@@ -263,14 +91,10 @@ void GPU_pbvh_grid_buffers_update(
const int update_flags);
/* draw */
-void GPU_pbvh_buffers_draw(
- GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe, bool fast);
+struct Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast);
-/* debug PBVH draw*/
-void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf);
-void GPU_pbvh_BB_draw_init(void);
-void GPU_pbvh_BB_draw_end(void);
+/* debug PBVH draw */
+void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos);
bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, struct GSet *bm_faces, bool show_diffuse_color);
bool GPU_pbvh_buffers_mask_changed(GPU_PBVH_Buffers *buffers, bool show_mask);
@@ -278,4 +102,6 @@ bool GPU_pbvh_buffers_mask_changed(GPU_PBVH_Buffers *buffers, bool show_mask);
void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers);
void GPU_pbvh_multires_buffers_free(struct GridCommonGPUBuffer **grid_common_gpu_buffer);
+void GPU_pbvh_fix_linking(void);
+
#endif
diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h
deleted file mode 100644
index d506d91a9aa..00000000000
--- a/source/blender/gpu/GPU_compositing.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * ***** 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): Antony Riakiotakis.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file GPU_compositing.h
- * \ingroup gpu
- */
-
-#ifndef __GPU_COMPOSITING_H__
-#define __GPU_COMPOSITING_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* opaque handle for framebuffer compositing effects (defined in gpu_compositing.c )*/
-typedef struct GPUFX GPUFX;
-struct GPUDOFSettings;
-struct GPUSSAOSettings;
-struct GPUOffScreen;
-struct GPUFXSettings;
-struct rcti;
-struct Scene;
-struct GPUShader;
-enum eGPUFXFlags;
-
-/**** Public API *****/
-
-typedef enum GPUFXShaderEffect {
- /* Screen space ambient occlusion shader */
- GPU_SHADER_FX_SSAO = 1,
-
- /* depth of field passes. Yep, quite a complex effect */
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE = 2,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO = 3,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE = 4,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR = 5,
- GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE = 6,
-
- /* high quality */
- GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE = 7,
- GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO = 8,
- GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE = 9,
-
- GPU_SHADER_FX_DEPTH_RESOLVE = 10,
-} GPUFXShaderEffect;
-
-/* keep in synch with enum above! */
-#define MAX_FX_SHADERS 11
-
-/* generate a new FX compositor */
-GPUFX *GPU_fx_compositor_create(void);
-
-/* destroy a text compositor */
-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);
-
-/* do compositing on the fx passes that have been initialized */
-bool GPU_fx_do_composite_pass(
- GPUFX *fx, float projmat[4][4], bool is_persp,
- struct Scene *scene, struct GPUOffScreen *ofs);
-
-/* bind new depth buffer for XRay pass */
-void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray);
-
-/* resolve a final depth buffer by compositing the XRay and normal depth buffers */
-void GPU_fx_compositor_XRay_resolve(GPUFX *fx);
-
-void GPU_fx_compositor_init_dof_settings(struct GPUDOFSettings *dof);
-void GPU_fx_compositor_init_ssao_settings(struct GPUSSAOSettings *ssao);
-
-
-/* initialize and cache the shader unform interface for effects */
-void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect effect);
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __GPU_COMPOSITING_H__
diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h
index 61b2bc591ce..c7a99d33654 100644
--- a/source/blender/gpu/GPU_debug.h
+++ b/source/blender/gpu/GPU_debug.h
@@ -41,24 +41,6 @@ extern "C" {
/* prints something if debug mode is active only */
void GPU_print_error_debug(const char *str);
-/* replacement for gluErrorString */
-const char *gpuErrorString(GLenum err);
-
-/* prints current OpenGL state */
-void GPU_state_print(void);
-
-void GPU_assert_no_gl_errors(const char *file, int line, const char *str);
-
-# define GPU_ASSERT_NO_GL_ERRORS(str) GPU_assert_no_gl_errors(__FILE__, __LINE__, (str))
-
-# define GPU_CHECK_ERRORS_AROUND(glProcCall) \
- ( \
- GPU_ASSERT_NO_GL_ERRORS("Pre: " #glProcCall), \
- (glProcCall), \
- GPU_ASSERT_NO_GL_ERRORS("Post: " #glProcCall) \
- )
-
-
/* inserts a debug marker message for the debug context messaging system */
void GPU_string_marker(const char *str);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 90b65af87c8..e26d973142b 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -39,76 +39,31 @@ extern "C" {
struct ImBuf;
struct Image;
struct ImageUser;
-struct MTexPoly;
struct Object;
struct Scene;
+struct ViewLayer;
struct View3D;
struct RegionView3D;
struct SmokeModifierData;
struct DupliObject;
-/* OpenGL drawing functions related to shading. These are also
- * shared with the game engine, where there were previously
- * duplicates of some of these functions. */
+#include "DNA_object_enums.h"
+
+/* OpenGL drawing functions related to shading. */
/* Initialize
* - sets the default Blender opengl state, if in doubt, check
* the contents of this function
- * - this is called when starting Blender, for opengl rendering,
- * and for switching back from the game engine for example. */
+ * - this is called when starting Blender, for opengl rendering. */
void GPU_state_init(void);
-/* Material drawing
- * - first the state is initialized by a particular object and
- * it's materials
- * - after this, materials can be quickly enabled by their number,
- * GPU_object_material_bind returns 0 if drawing should be skipped
- * - after drawing, the material must be disabled again */
-
-void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
- struct Scene *scene, struct Object *ob, bool glsl, bool *do_alpha_after);
-void GPU_end_object_materials(void);
-bool GPU_object_materials_check(void);
-
-int GPU_object_material_bind(int nr, void *attribs);
-void GPU_object_material_unbind(void);
-int GPU_object_material_visible(int nr, void *attribs);
-
-void GPU_begin_dupli_object(struct DupliObject *dob);
-void GPU_end_dupli_object(void);
-
-void GPU_material_diffuse_get(int nr, float diff[4]);
-bool GPU_material_use_matcaps_get(void);
-
-void GPU_set_material_alpha_blend(int alphablend);
-int GPU_get_material_alpha_blend(void);
-
-/* TexFace drawing
- * - this is mutually exclusive with material drawing, a mesh should
- * be drawn using one or the other
- * - passing NULL clears the state again */
-
-int GPU_set_tpage(struct MTexPoly *mtexpoly, int mipmap, int transp);
-void GPU_clear_tpage(bool force);
+/* Programmable point size
+ * - shaders set their own point size when enabled
+ * - use glPointSize when disabled */
-/* Lights
- * - returns how many lights were enabled
- * - this affects fixed functions materials and texface, not glsl */
-
-int GPU_default_lights(void);
-int GPU_scene_object_lights(
- struct Scene *scene, struct Object *ob,
- int lay, float viewmat[4][4], int ortho);
-
-/* Text render
- * - based on moving uv coordinates */
-
-void GPU_render_text(
- struct MTexPoly *mtexpoly, int mode,
- const char *textstr, int textlen, unsigned int *col,
- const float *v_quad[4], const float *uv_quad[4],
- int glattrib);
+void GPU_enable_program_point_size(void);
+void GPU_disable_program_point_size(void);
/* Mipmap settings
* - these will free textures on changes */
@@ -131,11 +86,9 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap);
* - these deal with images bound as opengl textures */
void GPU_paint_update_image(struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h);
-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, bool compare, bool mipmap, bool is_data);
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);
@@ -155,17 +108,23 @@ void GPU_create_smoke(struct SmokeModifierData *smd, int highres);
/* Delayed free of OpenGL buffers by main thread */
void GPU_free_unused_buffers(void);
-#ifdef WITH_OPENSUBDIV
-struct DerivedMesh;
-void GPU_draw_update_fvar_offset(struct DerivedMesh *dm);
-#endif
-
/* utilities */
void GPU_select_index_set(int index);
void GPU_select_index_get(int index, int *r_col);
int GPU_select_to_index(unsigned int col);
void GPU_select_to_index_array(unsigned int *col, const unsigned int size);
+typedef enum eGPUAttribMask {
+ GPU_DEPTH_BUFFER_BIT = (1 << 0),
+ GPU_ENABLE_BIT = (1 << 1),
+ GPU_SCISSOR_BIT = (1 << 2),
+ GPU_VIEWPORT_BIT = (1 << 3),
+ GPU_BLEND_BIT = (1 << 4),
+} eGPUAttribMask;
+
+void gpuPushAttrib(eGPUAttribMask mask);
+void gpuPopAttrib(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 31ad8243c4b..d36b0ea15be 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -38,21 +38,16 @@ extern "C" {
/* GPU extensions support */
-void GPU_extensions_disable(void);
-
-bool GPU_legacy_support(void);
bool GPU_full_non_power_of_two_support(void);
-bool GPU_display_list_support(void);
bool GPU_bicubic_bump_support(void);
-bool GPU_geometry_shader_support(void);
-bool GPU_geometry_shader_support_via_extension(void);
-bool GPU_instanced_drawing_support(void);
int GPU_max_texture_size(void);
int GPU_max_textures(void);
float GPU_max_texture_anisotropy(void);
int GPU_max_color_texture_samples(void);
int GPU_max_cube_map_size(void);
+int GPU_max_ubo_binds(void);
+int GPU_max_ubo_size(void);
int GPU_color_depth(void);
void GPU_get_dfdy_factors(float fac[2]);
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index 2719b8fa6a8..61dd899f3d9 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -36,48 +36,163 @@
extern "C" {
#endif
+struct GPUTexture;
+
+typedef struct GPUAttachment {
+ struct GPUTexture *tex;
+ int mip, layer;
+} GPUAttachment;
+
+typedef enum GPUFrameBufferBits {
+ GPU_COLOR_BIT = (1 << 0),
+ GPU_DEPTH_BIT = (1 << 1),
+ GPU_STENCIL_BIT = (1 << 2),
+} GPUFrameBufferBits;
+
typedef struct GPUFrameBuffer GPUFrameBuffer;
typedef struct GPUOffScreen GPUOffScreen;
-struct GPUTexture;
/* GPU Framebuffer
* - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
* multiple FBO's may be created, to get around limitations on the number
* of attached textures and the dimension requirements.
- * - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
- * be called before rendering to the window framebuffer again */
-
-void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
+ * - actual FBO creation & config is deferred until GPU_framebuffer_bind or
+ * GPU_framebuffer_check_valid to allow creation & config while another
+ * opengl context is bound (since FBOs are not shared between ogl contexts).
+ */
GPUFrameBuffer *GPU_framebuffer_create(void);
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, char err_out[256]);
-void GPU_framebuffer_texture_detach(struct GPUTexture *tex);
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);
+void GPU_framebuffer_bind(GPUFrameBuffer *fb);
+void GPU_framebuffer_restore(void);
+
+bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
+/* internal use only */
+unsigned int GPU_framebuffer_current_get(void);
-bool GPU_framebuffer_bound(GPUFrameBuffer *fb);
+#define GPU_FRAMEBUFFER_FREE_SAFE(fb) do { \
+ if (fb != NULL) { \
+ GPU_framebuffer_free(fb); \
+ fb = NULL; \
+ } \
+} while (0)
-void GPU_framebuffer_restore(void);
-void GPU_framebuffer_blur(
- GPUFrameBuffer *fb, struct GPUTexture *tex,
- GPUFrameBuffer *blurfb, struct GPUTexture *blurtex);
+/* Framebuffer setup : You need to call GPU_framebuffer_bind for theses
+ * to be effective. */
+
+void GPU_framebuffer_texture_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
+void GPU_framebuffer_texture_layer_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
+void GPU_framebuffer_texture_cubeface_attach(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
+void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, struct GPUTexture *tex);
+void GPU_framebuffer_texture_detach_slot(
+ GPUFrameBuffer *fb, struct GPUTexture *tex, int type);
+
+/**
+ * How to use GPU_framebuffer_ensure_config().
+ *
+ * Example :
+ * GPU_framebuffer_ensure_config(&fb, {
+ * GPU_ATTACHMENT_TEXTURE(depth), // must be depth buffer
+ * GPU_ATTACHMENT_TEXTURE(tex1),
+ * GPU_ATTACHMENT_TEXTURE_CUBEFACE(tex2, 0),
+ * GPU_ATTACHMENT_TEXTURE_LAYER_MIP(tex2, 0, 0)
+ * })
+ *
+ * Note : Unspecified attachements (i.e: those beyond the last
+ * GPU_ATTACHMENT_* in GPU_framebuffer_ensure_config list)
+ * are left unchanged.
+ * Note : Make sure that the dimensions of your textures matches
+ * otherwise you will have an invalid framebuffer error.
+ **/
+#define GPU_framebuffer_ensure_config(_fb, ...) do { \
+ if (*(_fb) == NULL) { \
+ *(_fb) = GPU_framebuffer_create(); \
+ } \
+ GPUAttachment config[] = __VA_ARGS__; \
+ GPU_framebuffer_config_array(*(_fb), config, (sizeof(config) / sizeof(GPUAttachment))); \
+} while (0)
+
+void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_ct);
+
+#define GPU_ATTACHMENT_NONE \
+ {.tex = NULL, .layer = -1, .mip = 0}
+#define GPU_ATTACHMENT_LEAVE \
+ {.tex = NULL, .layer = -1, .mip = -1}
+#define GPU_ATTACHMENT_TEXTURE(_tex) \
+ {.tex = _tex, .layer = -1, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_MIP(_tex, _mip) \
+ {.tex = _tex, .layer = -1, .mip = _mip}
+#define GPU_ATTACHMENT_TEXTURE_LAYER(_tex, _layer) \
+ {.tex = _tex, .layer = _layer, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_LAYER_MIP(_tex, _layer, _mip) \
+ {.tex = _tex, .layer = _layer, .mip = _mip}
+#define GPU_ATTACHMENT_TEXTURE_CUBEFACE(_tex, _face) \
+ {.tex = _tex, .layer = _face, .mip = 0}
+#define GPU_ATTACHMENT_TEXTURE_CUBEFACE_MIP(_tex, _face, _mip) \
+ {.tex = _tex, .layer = _face, .mip = _mip}
+
+/* Framebuffer operations */
+
+void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h);
+
+void GPU_framebuffer_clear(
+ GPUFrameBuffer *fb, GPUFrameBufferBits buffers,
+ const float clear_col[4], float clear_depth, unsigned int clear_stencil);
+
+#define GPU_framebuffer_clear_color(fb, col) \
+ GPU_framebuffer_clear(fb, GPU_COLOR_BIT, col, 0.0f, 0x00)
+
+#define GPU_framebuffer_clear_depth(fb, depth) \
+ GPU_framebuffer_clear(fb, GPU_DEPTH_BIT, NULL, depth, 0x00)
+
+#define GPU_framebuffer_clear_color_depth(fb, col, depth) \
+ GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT, col, depth, 0x00)
+
+#define GPU_framebuffer_clear_stencil(fb, stencil) \
+ GPU_framebuffer_clear(fb, GPU_STENCIL_BIT, NULL, 0.0f, stencil)
+
+#define GPU_framebuffer_clear_depth_stencil(fb, depth, stencil) \
+ GPU_framebuffer_clear(fb, GPU_DEPTH_BIT | GPU_STENCIL_BIT, NULL, depth, stencil)
+
+#define GPU_framebuffer_clear_color_depth_stencil(fb, col, depth, stencil) \
+ GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT, col, depth, stencil)
+
+void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data);
+void GPU_framebuffer_read_color(
+ GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data);
+
+void GPU_framebuffer_blit(
+ GPUFrameBuffer *fb_read, int read_slot,
+ GPUFrameBuffer *fb_write, int write_slot,
+ GPUFrameBufferBits blit_buffers);
+
+void GPU_framebuffer_recursive_downsample(
+ GPUFrameBuffer *fb, int max_lvl,
+ void (*callback)(void *userData, int level), void *userData);
/* GPU OffScreen
* - wrapper around framebuffer and texture for simple offscreen drawing
- * - changes size if graphics card can't support it */
+ */
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]);
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples,
+ bool depth, bool high_bitdepth, char err_out[256]);
void GPU_offscreen_free(GPUOffScreen *ofs);
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
+void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y);
int GPU_offscreen_width(const GPUOffScreen *ofs);
int GPU_offscreen_height(const GPUOffScreen *ofs);
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs);
+struct GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs);
+
+void GPU_offscreen_viewport_data_get(
+ GPUOffScreen *ofs,
+ GPUFrameBuffer **r_fb, struct GPUTexture **r_color, struct GPUTexture **r_depth);
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/GPU_glew.h b/source/blender/gpu/GPU_glew.h
index 94217863fd6..afe1c9763ad 100644
--- a/source/blender/gpu/GPU_glew.h
+++ b/source/blender/gpu/GPU_glew.h
@@ -34,4 +34,8 @@
#include "glew-mx.h"
+#ifndef WITH_LEGACY_OPENGL
+#include "GPU_legacy_stubs.h"
+#endif
+
#endif /* __GPU_GLEW_H__ */
diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h
new file mode 100644
index 00000000000..2a2692e6baf
--- /dev/null
+++ b/source/blender/gpu/GPU_immediate.h
@@ -0,0 +1,58 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* Immediate mode rendering is powered by the Gawain library.
+ * This file contains any additions or modifications specific to Blender.
+ */
+
+#ifndef __GPU_IMMEDIATE_H__
+#define __GPU_IMMEDIATE_H__
+
+#include "../../../intern/gawain/gawain/gwn_immediate.h"
+#include "../../../intern/gawain/gawain/gwn_imm_util.h"
+
+// TODO: CMake magic to do this:
+// #include "gawain/gwn_immediate.h"
+// #include "gawain/gwn_imm_util.h"
+
+#include "GPU_shader.h"
+
+/* Extend immBindProgram to use Blender’s library of built-in shader programs.
+ * Use immUnbindProgram() when done. */
+void immBindBuiltinProgram(GPUBuiltinShader shader_id);
+
+/*
+ * Extend immUniformColor to take Blender's themes
+ */
+void immUniformThemeColor(int color_id);
+void immUniformThemeColor3(int color_id);
+void immUniformThemeColorShade(int color_id, int offset);
+void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset);
+void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int offset);
+void immUniformThemeColorBlend(int color_id1, int color_id2, float fac);
+void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);
+
+#endif /* __GPU_IMMEDIATE_H__ */
diff --git a/source/blender/gpu/GPU_immediate_util.h b/source/blender/gpu/GPU_immediate_util.h
new file mode 100644
index 00000000000..c31d477ff5b
--- /dev/null
+++ b/source/blender/gpu/GPU_immediate_util.h
@@ -0,0 +1,64 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_immediate_util.h
+ * \ingroup gpu
+ *
+ * Utility drawing functions (rough equivalent to OpenGL's GLU)
+ */
+
+#ifndef __GPU_IMMEDIATE_UTIL_H__
+#define __GPU_IMMEDIATE_UTIL_H__
+
+void imm_cpack(uint x);
+
+void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments);
+void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float radius, int nsegments);
+
+void imm_draw_circle_wire_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments);
+void imm_draw_circle_fill_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments);
+
+/* use this version when Gwn_VertFormat has a vec3 position */
+void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments);
+void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegments);
+
+void imm_draw_disk_partial_fill_2d(
+ uint pos, float x, float y,
+ float radius_inner, float radius_outer, int nsegments, float start, float sweep);
+
+void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2);
+void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2);
+
+void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2);
+
+void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3]);
+void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3]);
+
+void imm_draw_cylinder_fill_normal_3d(
+ uint pos, uint nor, float base, float top, float height,
+ int slices, int stacks);
+void imm_draw_cylinder_wire_3d(
+ uint pos, float base, float top, float height,
+ int slices, int stacks);
+void imm_draw_cylinder_fill_3d(
+ uint pos, float base, float top, float height,
+ int slices, int stacks);
+
+#endif /* __GPU_IMMEDIATE_UTIL_H__ */
diff --git a/source/blender/gpu/GPU_legacy_stubs.h b/source/blender/gpu/GPU_legacy_stubs.h
new file mode 100644
index 00000000000..a195eac9eec
--- /dev/null
+++ b/source/blender/gpu/GPU_legacy_stubs.h
@@ -0,0 +1,457 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation, Dalai Felinto.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_legacy_stubs.h
+ * \ingroup gpu
+ *
+ * This is to mark the transition to OpenGL core profile
+ * The idea is to allow Blender 2.8 to be built with OpenGL 3.3 even if it means breaking things
+ *
+ * This file should be removed in the future
+ */
+
+#ifndef __GPU_LEGACY_STUBS_H__
+#define __GPU_LEGACY_STUBS_H__
+
+#if defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+# pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#include <stdlib.h> /* for abort(). */
+
+#include "BLI_utildefines.h"
+
+/**
+ * Empty function, use for breakpoint when a depreacated
+ * OpenGL function is called.
+ */
+static void gl_deprecated(void)
+{
+ BLI_assert(true);
+}
+
+#define _GL_BOOL BLI_INLINE GLboolean
+#define _GL_BOOL_RET { \
+ gl_deprecated(); \
+ return false; \
+}
+
+#define _GL_ENUM BLI_INLINE GLenum
+#define _GL_ENUM_RET { \
+ gl_deprecated(); \
+ return 0; \
+}
+
+#define _GL_INT BLI_INLINE GLint
+#define _GL_INT_RET { \
+ gl_deprecated(); \
+ return 0; \
+}
+
+
+#define _GL_UINT BLI_INLINE GLuint
+#define _GL_UINT_RET { \
+ gl_deprecated(); \
+ return 0; \
+}
+
+#define _GL_VOID BLI_INLINE void
+#define _GL_VOID_RET { \
+ gl_deprecated(); \
+}
+
+static bool disable_enable_check(GLenum cap)
+{
+ const bool is_deprecated = \
+ ELEM(
+ cap,
+ GL_ALPHA_TEST,
+ GL_LINE_STIPPLE,
+ GL_POINT_SPRITE,
+ GL_TEXTURE_1D,
+ GL_TEXTURE_2D,
+ GL_TEXTURE_GEN_S,
+ GL_TEXTURE_GEN_T,
+ -1
+ );
+
+ if (is_deprecated) {
+ gl_deprecated();
+ }
+
+ return is_deprecated;
+}
+
+_GL_VOID USE_CAREFULLY_glDisable (GLenum cap)
+{
+ if (!disable_enable_check(cap)) {
+ glDisable(cap);
+ }
+}
+#define glDisable USE_CAREFULLY_glDisable
+
+_GL_VOID USE_CAREFULLY_glEnable (GLenum cap)
+{
+ if (!disable_enable_check(cap)) {
+ glEnable(cap);
+ }
+}
+#define glEnable USE_CAREFULLY_glEnable
+
+/**
+ * Hand written cases
+ */
+
+_GL_VOID DO_NOT_USE_glClientActiveTexture (GLenum texture) _GL_VOID_RET
+
+
+/**
+ * List automatically generated from `gl-deprecated.h` and `glew.h`
+ */
+
+/**
+ * ENUM values
+ */
+#define DO_NOT_USE_GL_CURRENT_FOG_COORDINATE 0
+#define DO_NOT_USE_GL_FOG_COORDINATE 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_POINTER 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_STRIDE 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_ARRAY_TYPE 0
+#define DO_NOT_USE_GL_FOG_COORDINATE_SOURCE 0
+#define DO_NOT_USE_GL_POINT_SIZE_GRANULARITY 0
+#define DO_NOT_USE_GL_POINT_SIZE_RANGE 0
+#define DO_NOT_USE_GL_SOURCE0_ALPHA 0
+#define DO_NOT_USE_GL_SOURCE0_RGB 0
+#define DO_NOT_USE_GL_SOURCE1_ALPHA 0
+#define DO_NOT_USE_GL_SOURCE1_RGB 0
+#define DO_NOT_USE_GL_SOURCE2_ALPHA 0
+#define DO_NOT_USE_GL_SOURCE2_RGB 0
+
+/**
+ * Functions
+ */
+_GL_VOID DO_NOT_USE_glAccum (GLenum op, GLfloat value) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glAlphaFunc (GLenum func, GLclampf ref) _GL_VOID_RET
+_GL_BOOL DO_NOT_USE_glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences) _GL_BOOL_RET
+_GL_VOID DO_NOT_USE_glArrayElement (GLint i) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glBegin (GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glCallList (GLuint list) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glCallLists (GLsizei n, GLenum type, const void *lists) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glClearIndex (GLfloat c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glClipPlane (GLenum plane, const GLdouble *equation) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3b (GLbyte red, GLbyte green, GLbyte blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3bv (const GLbyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3d (GLdouble red, GLdouble green, GLdouble blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3f (GLfloat red, GLfloat green, GLfloat blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3i (GLint red, GLint green, GLint blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3s (GLshort red, GLshort green, GLshort blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3ub (GLubyte red, GLubyte green, GLubyte blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3ubv (const GLubyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3ui (GLuint red, GLuint green, GLuint blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3uiv (const GLuint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3us (GLushort red, GLushort green, GLushort blue) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor3usv (const GLushort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4bv (const GLbyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4i (GLint red, GLint green, GLint blue, GLint alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4ubv (const GLubyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4uiv (const GLuint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColor4usv (const GLushort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColorMaterial (GLenum face, GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glDeleteLists (GLuint list, GLsizei range) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glDisableClientState (GLenum array) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEdgeFlag (GLboolean flag) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEdgeFlagPointer (GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEdgeFlagv (const GLboolean *flag) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEnableClientState (GLenum array) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEnd (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEndList (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord1d (GLdouble u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord1dv (const GLdouble *u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord1f (GLfloat u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord1fv (const GLfloat *u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord2d (GLdouble u, GLdouble v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord2dv (const GLdouble *u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord2f (GLfloat u, GLfloat v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalCoord2fv (const GLfloat *u) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalMesh1 (GLenum mode, GLint i1, GLint i2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalPoint1 (GLint i) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glEvalPoint2 (GLint i, GLint j) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFogf (GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFogfv (GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFogi (GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFogiv (GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) _GL_VOID_RET
+_GL_UINT DO_NOT_USE_glGenLists (GLsizei range) _GL_UINT_RET
+_GL_VOID DO_NOT_USE_glGetClipPlane (GLenum plane, GLdouble *equation) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetLightfv (GLenum light, GLenum pname, GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetLightiv (GLenum light, GLenum pname, GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMapdv (GLenum target, GLenum query, GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMapfv (GLenum target, GLenum query, GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMapiv (GLenum target, GLenum query, GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetMaterialiv (GLenum face, GLenum pname, GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetPixelMapfv (GLenum map, GLfloat *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetPixelMapuiv (GLenum map, GLuint *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetPixelMapusv (GLenum map, GLushort *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetPolygonStipple (GLubyte *mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexEnviv (GLenum target, GLenum pname, GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glGetTexGeniv (GLenum coord, GLenum pname, GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexMask (GLuint mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexPointer (GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexd (GLdouble c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexdv (const GLdouble *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexf (GLfloat c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexfv (const GLfloat *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexi (GLint c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexiv (const GLint *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexs (GLshort c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexsv (const GLshort *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexub (GLubyte c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glIndexubv (const GLubyte *c) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glInitNames (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glInterleavedArrays (GLenum format, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_BOOL DO_NOT_USE_glIsList (GLuint list) _GL_BOOL_RET
+_GL_VOID DO_NOT_USE_glLightModelf (GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightModelfv (GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightModeli (GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightModeliv (GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightf (GLenum light, GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightfv (GLenum light, GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLighti (GLenum light, GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLightiv (GLenum light, GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLineStipple (GLint factor, GLushort pattern) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glListBase (GLuint base) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLoadIdentity (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLoadMatrixd (const GLdouble *m) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLoadMatrixf (const GLfloat *m) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glLoadName (GLuint name) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMapGrid1d (GLint un, GLdouble u1, GLdouble u2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMapGrid1f (GLint un, GLfloat u1, GLfloat u2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMaterialf (GLenum face, GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMaterialfv (GLenum face, GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMateriali (GLenum face, GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMaterialiv (GLenum face, GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMatrixMode (GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMultMatrixd (const GLdouble *m) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glMultMatrixf (const GLfloat *m) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNewList (GLuint list, GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3bv (const GLbyte *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3i (GLint nx, GLint ny, GLint nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3s (GLshort nx, GLshort ny, GLshort nz) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormal3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glNormalPointer (GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPassThrough (GLfloat token) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelTransferf (GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelTransferi (GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPixelZoom (GLfloat xfactor, GLfloat yfactor) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPolygonStipple (const GLubyte *mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPopAttrib (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPopClientAttrib (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPopMatrix (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPopName (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPushAttrib (GLbitfield mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPushClientAttrib (GLbitfield mask) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPushMatrix (void) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glPushName (GLuint name) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2d (GLdouble x, GLdouble y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2f (GLfloat x, GLfloat y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2i (GLint x, GLint y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2s (GLshort x, GLshort y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos2sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3d (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3f (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3i (GLint x, GLint y, GLint z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3s (GLshort x, GLshort y, GLshort z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4i (GLint x, GLint y, GLint z, GLint w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRasterPos4sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectdv (const GLdouble *v1, const GLdouble *v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectfv (const GLfloat *v1, const GLfloat *v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRecti (GLint x1, GLint y1, GLint x2, GLint y2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectiv (const GLint *v1, const GLint *v2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRectsv (const GLshort *v1, const GLshort *v2) _GL_VOID_RET
+_GL_INT DO_NOT_USE_glRenderMode (GLenum mode) _GL_INT_RET
+_GL_VOID DO_NOT_USE_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glScaled (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glScalef (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glSelectBuffer (GLsizei size, GLuint *buffer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glShadeModel (GLenum mode) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1d (GLdouble s) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1f (GLfloat s) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1i (GLint s) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1s (GLshort s) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord1sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2d (GLdouble s, GLdouble t) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2f (GLfloat s, GLfloat t) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2i (GLint s, GLint t) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2s (GLshort s, GLshort t) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord2sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3d (GLdouble s, GLdouble t, GLdouble r) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3i (GLint s, GLint t, GLint r) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3s (GLshort s, GLshort t, GLshort r) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4i (GLint s, GLint t, GLint r, GLint q) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoord4sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexEnvf (GLenum target, GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexEnvi (GLenum target, GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexEnviv (GLenum target, GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGend (GLenum coord, GLenum pname, GLdouble param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGendv (GLenum coord, GLenum pname, const GLdouble *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGenf (GLenum coord, GLenum pname, GLfloat param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGeni (GLenum coord, GLenum pname, GLint param) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTexGeniv (GLenum coord, GLenum pname, const GLint *params) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTranslated (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glTranslatef (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2d (GLdouble x, GLdouble y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2f (GLfloat x, GLfloat y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2i (GLint x, GLint y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2s (GLshort x, GLshort y) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex2sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3d (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3f (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3i (GLint x, GLint y, GLint z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3s (GLshort x, GLshort y, GLshort z) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex3sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4dv (const GLdouble *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4fv (const GLfloat *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4i (GLint x, GLint y, GLint z, GLint w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4iv (const GLint *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertex4sv (const GLshort *v) _GL_VOID_RET
+_GL_VOID DO_NOT_USE_glVertexPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET
+
+/**
+ * End of automatically generated list
+ */
+
+
+
+#undef _GL_BOOL
+#undef _GL_BOOL_RET
+#undef _GL_ENUM
+#undef _GL_ENUM_RET
+#undef _GL_INT
+#undef _GL_INT_RET
+#undef _GL_UINT
+#undef _GL_UINT_RET
+#undef _GL_VOID
+#undef _GL_VOID_RET
+
+#if defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
+
+#endif /* __GPU_LEGACY_STUBS_H__ */
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index e229afd3323..95492016f25 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -43,30 +43,33 @@ extern "C" {
struct Image;
struct ImageUser;
+struct ListBase;
struct Material;
struct Object;
-struct Image;
struct Scene;
-struct SceneRenderLayer;
struct GPUVertexAttribs;
struct GPUNode;
struct GPUNodeLink;
struct GPUNodeStack;
struct GPUMaterial;
struct GPUTexture;
+struct GPUUniformBuffer;
struct GPULamp;
struct PreviewImage;
struct World;
+struct bNode;
+struct bNodeTree;
typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
typedef struct GPUMaterial GPUMaterial;
-typedef struct GPULamp GPULamp;
+
typedef struct GPUParticleInfo GPUParticleInfo;
/* Functions to create GPU Materials nodes */
typedef enum GPUType {
+ /* Keep in sync with GPU_DATATYPE_STR */
/* The value indicates the number of elements in each type */
GPU_NONE = 0,
GPU_FLOAT = 1,
@@ -76,9 +79,16 @@ typedef enum GPUType {
GPU_MAT3 = 9,
GPU_MAT4 = 16,
+ /* Values not in GPU_DATATYPE_STR */
GPU_TEX2D = 1002,
- GPU_SHADOW2D = 1003,
- GPU_TEXCUBE = 1004,
+ GPU_TEX3D = 1003,
+ GPU_SHADOW2D = 1004,
+ GPU_TEXCUBE = 1005,
+
+ /* GLSL Struct types */
+ GPU_CLOSURE = 1006,
+
+ /* Opengl Attributes */
GPU_ATTRIB = 3001
} GPUType;
@@ -98,7 +108,10 @@ typedef enum GPUBuiltin {
GPU_PARTICLE_ANG_VELOCITY = (1 << 12),
GPU_LOC_TO_VIEW_MATRIX = (1 << 13),
GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14),
- GPU_OBJECT_INFO = (1 << 15)
+ GPU_OBJECT_INFO = (1 << 15),
+ GPU_VOLUME_DENSITY = (1 << 16),
+ GPU_VOLUME_FLAME = (1 << 17),
+ GPU_VOLUME_TEMPERATURE = (1 << 18)
} GPUBuiltin;
typedef enum GPUOpenGLBuiltin {
@@ -123,14 +136,19 @@ typedef enum GPUBlendMode {
typedef struct GPUNodeStack {
GPUType type;
- const char *name;
float vec[4];
struct GPUNodeLink *link;
bool hasinput;
bool hasoutput;
short sockettype;
+ bool end;
} GPUNodeStack;
+typedef enum GPUMaterialStatus {
+ GPU_MAT_FAILED = 0,
+ GPU_MAT_QUEUED,
+ GPU_MAT_SUCCESS,
+} GPUMaterialStatus;
#define GPU_DYNAMIC_GROUP_FROM_TYPE(f) ((f) & 0xFFFF0000)
@@ -141,6 +159,7 @@ typedef struct GPUNodeStack {
#define GPU_DYNAMIC_GROUP_MIST 0x00050000
#define GPU_DYNAMIC_GROUP_WORLD 0x00060000
#define GPU_DYNAMIC_GROUP_MAT 0x00070000
+#define GPU_DYNAMIC_UBO 0x00080000
typedef enum GPUDynamicType {
@@ -200,6 +219,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_uniform_buffer(float *num, GPUType gputype);
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data);
GPUNodeLink *GPU_cube_map(struct Image *ima, struct ImageUser *iuser, bool is_data);
GPUNodeLink *GPU_image_preview(struct PreviewImage *prv);
@@ -210,150 +230,48 @@ GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin);
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, ...);
+bool GPU_stack_link(GPUMaterial *mat, struct bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...);
+GPUNodeLink *GPU_uniformbuffer_link_out(
+ struct GPUMaterial *mat, struct bNode *node,
+ struct GPUNodeStack *stack, const int index);
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link);
-void GPU_material_enable_alpha(GPUMaterial *material);
GPUBuiltin GPU_get_material_builtins(GPUMaterial *material);
-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);
+void GPU_material_sss_profile_create(GPUMaterial *material, float *radii, short *falloff_type, float *sharpness);
+struct GPUUniformBuffer *GPU_material_sss_profile_get(
+ GPUMaterial *material, int sample_ct, struct GPUTexture **tex_profile);
-GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
-GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
+/* High level functions to create and use GPU materials */
+GPUMaterial *GPU_material_from_nodetree_find(
+ struct ListBase *gpumaterials, const void *engine_type, int options);
+GPUMaterial *GPU_material_from_nodetree(
+ struct Scene *scene, struct bNodeTree *ntree, struct ListBase *gpumaterials, const void *engine_type, int options);
+void GPU_material_generate_pass(
+ GPUMaterial *mat, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines);
void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
-bool GPU_lamp_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
-void GPU_material_bind(
- GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
- float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
-void GPU_material_bind_uniforms(
- GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
- float autobumpscale, GPUParticleInfo *pi, float object_info[3]);
-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);
+struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
+struct ListBase *GPU_material_get_inputs(GPUMaterial *material);
+GPUMaterialStatus GPU_material_status(GPUMaterial *mat);
+
+struct GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material);
+void GPU_material_create_uniform_buffer(GPUMaterial *material, struct ListBase *inputs);
+void GPU_material_uniform_buffer_tag_dirty(struct ListBase *gpumaterials);
void GPU_material_vertex_attributes(GPUMaterial *material,
struct GPUVertexAttribs *attrib);
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);
-
-/* Exported shading */
-
-typedef struct GPUShadeInput {
- GPUMaterial *gpumat;
- struct Material *mat;
-
- GPUNodeLink *rgb, *specrgb, *vn, *view, *vcol, *ref;
- GPUNodeLink *alpha, *refl, *spec, *emit, *har, *amb;
- GPUNodeLink *spectra, *mir, *refcol;
-} GPUShadeInput;
-
-typedef struct GPUShadeResult {
- GPUNodeLink *diff, *spec, *combined, *alpha;
-} GPUShadeResult;
-
-void GPU_shadeinput_set(GPUMaterial *mat, struct Material *ma, GPUShadeInput *shi);
-void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr);
-
-/* Export GLSL shader */
-
-typedef enum GPUDataType {
- GPU_DATA_NONE = 0,
- GPU_DATA_1I = 1, /* 1 integer */
- GPU_DATA_1F = 2,
- GPU_DATA_2F = 3,
- GPU_DATA_3F = 4,
- GPU_DATA_4F = 5,
- GPU_DATA_9F = 6,
- GPU_DATA_16F = 7,
- GPU_DATA_4UB = 8,
-} GPUDataType;
-
-/* this structure gives information of each uniform found in the shader */
-typedef struct GPUInputUniform {
- struct GPUInputUniform *next, *prev;
- char varname[32]; /* name of uniform in shader */
- GPUDynamicType type; /* type of uniform, data format and calculation derive from it */
- GPUDataType datatype; /* type of uniform data */
- struct Object *lamp; /* when type=GPU_DYNAMIC_LAMP_... or GPU_DYNAMIC_SAMPLER_2DSHADOW */
- struct Image *image; /* when type=GPU_DYNAMIC_SAMPLER_2DIMAGE */
- struct Material *material;/* when type=GPU_DYNAMIC_MAT_... */
- int texnumber; /* when type=GPU_DYNAMIC_SAMPLER, texture number: 0.. */
- unsigned char *texpixels; /* for internally generated texture, pixel data in RGBA format */
- int texsize; /* size in pixel of the texture in texpixels buffer:
- * for 2D textures, this is S and T size (square texture) */
-} GPUInputUniform;
-
-typedef struct GPUInputAttribute {
- struct GPUInputAttribute *next, *prev;
- char varname[32]; /* name of attribute in shader */
- int type; /* from CustomData.type, data type derives from it */
- GPUDataType datatype; /* type of attribute data */
- const char *name; /* layer name */
- int number; /* generic attribute number */
-} GPUInputAttribute;
-
-typedef struct GPUShaderExport {
- ListBase uniforms;
- ListBase attributes;
- char *vertex;
- char *fragment;
-} GPUShaderExport;
-
-GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma);
-void GPU_free_shader_export(GPUShaderExport *shader);
-
-/* Lamps */
-
-GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
-void GPU_lamp_free(struct Object *ob);
-
-bool GPU_lamp_has_shadow_buffer(GPULamp *lamp);
-void GPU_lamp_update_buffer_mats(GPULamp *lamp);
-void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]);
-void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp);
-int GPU_lamp_shadow_buffer_type(GPULamp *lamp);
-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_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);
-void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend);
-int GPU_lamp_shadow_layer(GPULamp *lamp);
-GPUNodeLink *GPU_lamp_get_data(
- GPUMaterial *mat, GPULamp *lamp,
- 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]);
-void GPU_ambient_update_color(float color[3]);
-void GPU_zenith_update_color(float color[3]);
-
-struct GPUParticleInfo
-{
- float scalprops[4];
- float location[4];
- float velocity[3];
- float angular_velocity[3];
-};
-
-#ifdef WITH_OPENSUBDIV
-struct DerivedMesh;
-void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
- struct DerivedMesh *dm);
-#endif
+bool GPU_material_use_domain_surface(GPUMaterial *mat);
+bool GPU_material_use_domain_volume(GPUMaterial *mat);
+
+void GPU_pass_cache_garbage_collect(void);
+void GPU_pass_cache_free(void);
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
new file mode 100644
index 00000000000..f22c0cd5c4d
--- /dev/null
+++ b/source/blender/gpu/GPU_matrix.h
@@ -0,0 +1,190 @@
+/*
+ * ***** 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) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Alexandr Kuznetsov, Jason Wilkins, Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/GPU_matrix.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_MATRIX_H__
+#define __GPU_MATRIX_H__
+
+#include "BLI_sys_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Gwn_ShaderInterface;
+
+void gpuMatrixReset(void); /* to Identity transform & empty stack */
+
+/* ModelView Matrix (2D or 3D) */
+
+void gpuPushMatrix(void); /* TODO: PushCopy vs PushIdentity? */
+void gpuPopMatrix(void);
+
+void gpuLoadIdentity(void);
+
+void gpuScaleUniform(float factor);
+
+
+/* 3D ModelView Matrix */
+
+void gpuLoadMatrix(const float m[4][4]);
+void gpuMultMatrix(const float m[4][4]);
+
+void gpuTranslate3f(float x, float y, float z);
+void gpuTranslate3fv(const float vec[3]);
+void gpuScale3f(float x, float y, float z);
+void gpuScale3fv(const float vec[3]);
+void gpuRotate3f(float deg, float x, float y, float z); /* axis of rotation should be a unit vector */
+void gpuRotate3fv(float deg, const float axis[3]); /* axis of rotation should be a unit vector */
+void gpuRotateAxis(float deg, char axis); /* TODO: enum for axis? */
+
+void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ);
+/* TODO: variant that takes eye[3], center[3], up[3] */
+
+
+/* 2D ModelView Matrix */
+
+void gpuTranslate2f(float x, float y);
+void gpuTranslate2fv(const float vec[2]);
+void gpuScale2f(float x, float y);
+void gpuScale2fv(const float vec[2]);
+void gpuRotate2D(float deg);
+
+/* Projection Matrix (2D or 3D) */
+
+void gpuPushProjectionMatrix(void);
+void gpuPopProjectionMatrix(void);
+
+/* 3D Projection Matrix */
+
+void gpuLoadIdentityProjectionMatrix(void);
+void gpuLoadProjectionMatrix(const float m[4][4]);
+
+void gpuOrtho(float left, float right, float bottom, float top, float near, float far);
+void gpuFrustum(float left, float right, float bottom, float top, float near, float far);
+void gpuPerspective(float fovy, float aspect, float near, float far);
+
+/* 3D Projection between Window and World Space */
+
+void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3]);
+bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3]);
+
+/* 2D Projection Matrix */
+
+void gpuOrtho2D(float left, float right, float bottom, float top);
+
+
+/* functions to get matrix values */
+const float (*gpuGetModelViewMatrix(float m[4][4]))[4];
+const float (*gpuGetProjectionMatrix(float m[4][4]))[4];
+const float (*gpuGetModelViewProjectionMatrix(float m[4][4]))[4];
+
+const float (*gpuGetNormalMatrix(float m[3][3]))[3];
+const float (*gpuGetNormalMatrixInverse(float m[3][3]))[3];
+
+
+/* set uniform values for currently bound shader */
+void gpuBindMatrices(const struct Gwn_ShaderInterface *);
+bool gpuMatricesDirty(void); /* since last bind */
+
+
+/* Python API needs to be able to inspect the stack so errors raise exceptions instead of crashing. */
+#ifdef USE_GPU_PY_MATRIX_API
+int GPU_matrix_stack_level_get_model_view(void);
+int GPU_matrix_stack_level_get_projection(void);
+/* static assert ensures this doesn't change! */
+#define GPU_PY_MATRIX_STACK_LEN 31
+#endif /* USE_GPU_PY_MATRIX_API */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef SUPPRESS_GENERIC_MATRIX_API
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+#define _GPU_MAT3_CONST_CAST(x) (_Generic((x), \
+ void *: (const float (*)[3])(x), \
+ float *: (const float (*)[3])(x), \
+ float [9]: (const float (*)[3])(x), \
+ float (*)[4]: (const float (*)[3])(x), \
+ float [4][4]: (const float (*)[3])(x), \
+ const void *: (const float (*)[3])(x), \
+ const float *: (const float (*)[3])(x), \
+ const float [9]: (const float (*)[3])(x), \
+ const float (*)[3]: (const float (*)[3])(x), \
+ const float [3][3]: (const float (*)[3])(x)) \
+)
+#define _GPU_MAT3_CAST(x) (_Generic((x), \
+ void *: (float (*)[3])(x), \
+ float *: (float (*)[3])(x), \
+ float [9]: (float (*)[3])(x), \
+ float (*)[3]: (float (*)[3])(x), \
+ float [3][3]: (float (*)[3])(x)) \
+)
+#define _GPU_MAT4_CONST_CAST(x) (_Generic((x), \
+ void *: (const float (*)[4])(x), \
+ float *: (const float (*)[4])(x), \
+ float [16]: (const float (*)[4])(x), \
+ float (*)[4]: (const float (*)[4])(x), \
+ float [4][4]: (const float (*)[4])(x), \
+ const void *: (const float (*)[4])(x), \
+ const float *: (const float (*)[4])(x), \
+ const float [16]: (const float (*)[4])(x), \
+ const float (*)[4]: (const float (*)[4])(x), \
+ const float [4][4]: (const float (*)[4])(x)) \
+)
+#define _GPU_MAT4_CAST(x) (_Generic((x), \
+ void *: (float (*)[4])(x), \
+ float *: (float (*)[4])(x), \
+ float [16]: (float (*)[4])(x), \
+ float (*)[4]: (float (*)[4])(x), \
+ float [4][4]: (float (*)[4])(x)) \
+)
+#else
+# define _GPU_MAT3_CONST_CAST(x) (const float (*)[3])(x)
+# define _GPU_MAT3_CAST(x) (float (*)[3])(x)
+# define _GPU_MAT4_CONST_CAST(x) (const float (*)[4])(x)
+# define _GPU_MAT4_CAST(x) (float (*)[4])(x)
+#endif /* C11 */
+
+/* make matrix inputs generic, to avoid warnings */
+# define gpuMultMatrix(x) gpuMultMatrix(_GPU_MAT4_CONST_CAST(x))
+# define gpuLoadMatrix(x) gpuLoadMatrix(_GPU_MAT4_CONST_CAST(x))
+# define gpuLoadProjectionMatrix(x) gpuLoadProjectionMatrix(_GPU_MAT4_CONST_CAST(x))
+# define gpuGetModelViewMatrix(x) gpuGetModelViewMatrix(_GPU_MAT4_CAST(x))
+# define gpuGetProjectionMatrix(x) gpuGetProjectionMatrix(_GPU_MAT4_CAST(x))
+# define gpuGetModelViewProjectionMatrix(x) gpuGetModelViewProjectionMatrix(_GPU_MAT4_CAST(x))
+# define gpuGetNormalMatrix(x) gpuGetNormalMatrix(_GPU_MAT3_CAST(x))
+# define gpuGetNormalMatrixInverse(x) gpuGetNormalMatrixInverse(_GPU_MAT3_CAST(x))
+#endif /* SUPPRESS_GENERIC_MATRIX_API */
+
+#endif /* __GPU_MATRIX_H__ */
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index 53f480bccd7..f1342a1f6b8 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -57,4 +57,7 @@ void GPU_select_cache_begin(void);
void GPU_select_cache_load_id(void);
void GPU_select_cache_end(void);
+/* utilities */
+const uint *GPU_select_buffer_near(const uint *buffer, int hits);
+
#endif
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 5b94db6e120..f831d495ad0 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -38,6 +38,7 @@ extern "C" {
typedef struct GPUShader GPUShader;
struct GPUTexture;
+struct GPUUniformBuffer;
/* GPU Shader
* - only for fragment shaders now
@@ -49,34 +50,51 @@ enum {
GPU_SHADER_FLAGS_NEW_SHADING = (1 << 1),
};
+typedef enum GPUShaderTFBType {
+ GPU_SHADER_TFB_NONE = 0, /* Transform feedback unsupported. */
+ GPU_SHADER_TFB_POINTS = 1,
+ GPU_SHADER_TFB_LINES = 2,
+ GPU_SHADER_TFB_TRIANGLES = 3,
+} GPUShaderTFBType;
+
GPUShader *GPU_shader_create(
const char *vertexcode,
const char *fragcode,
const char *geocode,
const char *libcode,
- const char *defines,
- int input, int output, int number);
+ const char *defines);
GPUShader *GPU_shader_create_ex(
const char *vertexcode,
const char *fragcode,
const char *geocode,
const char *libcode,
const char *defines,
- int input, int output, int number,
- const int flags);
+ const int flags,
+ const GPUShaderTFBType tf_type,
+ const char **tf_names,
+ const int tf_count);
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
void GPU_shader_unbind(void);
+/* Returns true if transform feedback was succesfully enabled. */
+bool GPU_shader_transform_feedback_enable(GPUShader *shader, unsigned int vbo_id);
+void GPU_shader_transform_feedback_disable(GPUShader *shader);
+
+int GPU_shader_get_program(GPUShader *shader);
+
void *GPU_shader_get_interface(GPUShader *shader);
-void GPU_shader_set_interface(GPUShader *shader, void *interface);
+
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
+int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
+int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
int arraysize, const float *value);
void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
int arraysize, const int *value);
+void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo);
void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex);
void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
@@ -85,15 +103,264 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name);
/* Builtin/Non-generated shaders */
typedef enum GPUBuiltinShader {
- GPU_SHADER_VSM_STORE = 0,
- GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
- GPU_SHADER_SMOKE = 2,
- GPU_SHADER_SMOKE_FIRE = 3,
- GPU_SHADER_SMOKE_COBA = 4,
+ GPU_SHADER_VSM_STORE,
+ GPU_SHADER_SEP_GAUSSIAN_BLUR,
+ GPU_SHADER_SMOKE,
+ GPU_SHADER_SMOKE_FIRE,
+ GPU_SHADER_SMOKE_COBA,
+
+ /* specialized drawing */
+ GPU_SHADER_TEXT,
+ GPU_SHADER_TEXT_SIMPLE,
+ GPU_SHADER_EDGES_FRONT_BACK_PERSP,
+ GPU_SHADER_EDGES_FRONT_BACK_ORTHO,
+ GPU_SHADER_EDGES_OVERLAY_SIMPLE,
+ GPU_SHADER_EDGES_OVERLAY,
+ GPU_SHADER_KEYFRAME_DIAMOND,
+ GPU_SHADER_SIMPLE_LIGHTING,
+ GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR,
+ GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR,
+ GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA,
+
+ /* for simple 2D drawing */
+ /**
+ * Take a single color for all the vertices and a 2D position for each vertex.
+ *
+ * \param color: uniform vec4
+ * \param pos: in vec2
+ */
+ GPU_SHADER_2D_UNIFORM_COLOR,
+ /**
+ * Take a 2D position and color for each vertex without color interpolation.
+ *
+ * \param color: in vec4
+ * \param pos: in vec2
+ */
+ GPU_SHADER_2D_FLAT_COLOR,
+ /**
+ * Take a 2D position and color for each vertex with linear interpolation in window space.
+ *
+ * \param color: in vec4
+ * \param pos: in vec2
+ */
+ GPU_SHADER_2D_SMOOTH_COLOR,
+ GPU_SHADER_2D_SMOOTH_COLOR_DITHER,
+ GPU_SHADER_2D_IMAGE,
+ GPU_SHADER_2D_IMAGE_COLOR,
+ GPU_SHADER_2D_IMAGE_DESATURATE_COLOR,
+ GPU_SHADER_2D_IMAGE_ALPHA_COLOR,
+ GPU_SHADER_2D_IMAGE_ALPHA,
+ GPU_SHADER_2D_IMAGE_RECT_COLOR,
+ GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR,
+ GPU_SHADER_2D_IMAGE_MULTISAMPLE_2,
+ GPU_SHADER_2D_IMAGE_MULTISAMPLE_4,
+ GPU_SHADER_2D_IMAGE_MULTISAMPLE_8,
+ GPU_SHADER_2D_IMAGE_MULTISAMPLE_16,
+ GPU_SHADER_2D_CHECKER,
+ GPU_SHADER_2D_DIAG_STRIPES,
+ /* for simple 3D drawing */
+ /**
+ * Take a single color for all the vertices and a 3D position for each vertex.
+ *
+ * \param color: uniform vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_UNIFORM_COLOR,
+ GPU_SHADER_3D_UNIFORM_COLOR_U32,
+ GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE,
+ /**
+ * Take a 3D position and color for each vertex without color interpolation.
+ *
+ * \param color: in vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_FLAT_COLOR,
+ GPU_SHADER_3D_FLAT_COLOR_U32, /* use for select-id's */
+ /**
+ * Take a 3D position and color for each vertex with perspective correct interpolation.
+ *
+ * \param color: in vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_SMOOTH_COLOR,
+ /**
+ * Take a 3D position for each vertex and output only depth.
+ *
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_DEPTH_ONLY,
+ GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR,
+ /* basic image drawing */
+ GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB,
+ GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR,
+ GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR,
+ /**
+ * Draw texture with alpha. Take a 3D positon and a 2D texture coordinate for each vertex.
+ *
+ * \param alpha: uniform float
+ * \param image: uniform sampler2D
+ * \param texCoord: in vec2
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_IMAGE_MODULATE_ALPHA,
+ /**
+ * Draw linearized depth texture relate to near and far distances.
+ * Take a 3D positon and a 2D texture coordinate for each vertex.
+ *
+ * \param znear: uniform float
+ * \param zfar: uniform float
+ * \param image: uniform sampler2D
+ * \param texCoord: in vec2
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_IMAGE_DEPTH,
+ GPU_SHADER_3D_IMAGE_DEPTH_COPY,
+ /* stereo 3d */
+ GPU_SHADER_2D_IMAGE_INTERLACE,
+ /* points */
+ /**
+ * Draw round points with a hardcoded size.
+ * Take a single color for all the vertices and a 2D position for each vertex.
+ *
+ * \param color: uniform vec4
+ * \param pos: in vec2
+ */
+ GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR,
+ /**
+ * Draw round points with a constant size.
+ * Take a single color for all the vertices and a 2D position for each vertex.
+ *
+ * \param size: uniform float
+ * \param color: uniform vec4
+ * \param pos: in vec2
+ */
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA,
+ /**
+ * Draw round points with a constant size and an outline.
+ * Take a single color for all the vertices and a 2D position for each vertex.
+ *
+ * \param size: uniform float
+ * \param outlineWidth: uniform float
+ * \param color: uniform vec4
+ * \param outlineColor: uniform vec4
+ * \param pos: in vec2
+ */
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA,
+ /**
+ * Draw round points with a constant size and an outline. Take a 2D position and a color for each vertex.
+ *
+ * \param size: uniform float
+ * \param outlineWidth: uniform float
+ * \param outlineColor: uniform vec4
+ * \param color: in vec4
+ * \param pos: in vec2
+ */
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA,
+ /**
+ * Draw round points with a constant size and an outline. Take a 2D position and a color for each vertex.
+ *
+ * \param size: in float
+ * \param color: in vec4
+ * \param pos: in vec2
+ */
+ GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR,
+ /**
+ * Draw round points with a hardcoded size.
+ * Take a single color for all the vertices and a 3D position for each vertex.
+ *
+ * \param color: uniform vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR,
+ /**
+ * Draw round points with a hardcoded size.
+ * Take a single color for all the vertices and a 3D position for each vertex.
+ *
+ * \param color: uniform vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR,
+ /**
+ * Draw round points with a constant size.
+ * Take a single color for all the vertices and a 3D position for each vertex.
+ *
+ * \param size: uniform float
+ * \param color: uniform vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA,
+ /**
+ * Draw round points with a constant size and an outline.
+ * Take a single color for all the vertices and a 3D position for each vertex.
+ *
+ * \param size: uniform float
+ * \param outlineWidth: uniform float
+ * \param color: uniform vec4
+ * \param outlineColor: uniform vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA,
+ /**
+ * Draw round points with a constant size and an outline.
+ * Take a single color for all the vertices and a 3D position for each vertex.
+ *
+ * \param color: uniform vec4
+ * \param size: in float
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR,
+ /**
+ * Draw round points with a constant size and an outline. Take a 3D position and a color for each vertex.
+ *
+ * \param size: in float
+ * \param color: in vec4
+ * \param pos: in vec3
+ */
+ GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR,
+ /* lines */
+ GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR,
+ GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR,
+ /* lamp drawing */
+ GPU_SHADER_3D_GROUNDPOINT,
+ GPU_SHADER_3D_GROUNDLINE,
+ GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR,
+ /* bone drawing */
+ GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR,
+ GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR,
+ /* camera drawing */
+ GPU_SHADER_CAMERA,
+ /* distance in front of objects */
+ GPU_SHADER_DISTANCE_LINES,
+ /* axis name */
+ GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS,
+ GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED,
+ /* instance */
+ GPU_SHADER_INSTANCE_UNIFORM_COLOR,
+ GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE, /* Uniformly scaled */
+ GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, /* Uniformly scaled */
+ GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE,
+ GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR,
+ /* specialized for UI drawing */
+ GPU_SHADER_2D_WIDGET_BASE,
+ GPU_SHADER_2D_WIDGET_BASE_INST,
+ GPU_SHADER_2D_WIDGET_SHADOW,
+ GPU_SHADER_2D_NODELINK,
+ GPU_SHADER_2D_NODELINK_INST,
+
+ GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;
+/* Keep these in sync with:
+ * gpu_shader_image_interlace_frag.glsl
+ * gpu_shader_image_rect_interlace_frag.glsl
+ **/
+typedef enum GPUInterlaceShader {
+ GPU_SHADER_INTERLACE_ROW = 0,
+ GPU_SHADER_INTERLACE_COLUMN = 1,
+ GPU_SHADER_INTERLACE_CHECKER = 2,
+} GPUInterlaceShader;
+
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
-GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
void GPU_shader_free_builtin_shaders(void);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 756fe79151b..cc66b5dbf9b 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -39,6 +39,7 @@ extern "C" {
struct Image;
struct ImageUser;
struct PreviewImage;
+struct Gwn_VertBuf;
struct GPUFrameBuffer;
typedef struct GPUTexture GPUTexture;
@@ -55,25 +56,114 @@ typedef struct GPUTexture GPUTexture;
* - if created with from_blender, will not free the texture
*/
-typedef enum GPUHDRType {
- GPU_HDR_NONE = 0,
- GPU_HDR_HALF_FLOAT = 1,
- GPU_HDR_FULL_FLOAT = (1 << 1),
-} GPUHDRType;
-
-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_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]);
+/* Wrapper to supported OpenGL/Vulkan texture internal storage
+ * If you need a type just uncomment it. Be aware that some formats
+ * are not supported by renderbuffers. All of the following formats
+ * are part of the OpenGL 3.3 core
+ * specification. */
+typedef enum GPUTextureFormat {
+ /* Formats texture & renderbuffer */
+ GPU_RGBA8UI,
+ GPU_RGBA8I,
+ GPU_RGBA8,
+ GPU_RGBA32UI,
+ GPU_RGBA32I,
+ GPU_RGBA32F,
+ GPU_RGBA16UI,
+ GPU_RGBA16I,
+ GPU_RGBA16F,
+ GPU_RGBA16,
+ GPU_RG8UI,
+ GPU_RG8I,
+ GPU_RG8,
+ GPU_RG32UI,
+ GPU_RG32I,
+ GPU_RG32F,
+ GPU_RG16UI,
+ GPU_RG16I,
+ GPU_RG16F,
+ GPU_RG16,
+ GPU_R8UI,
+ GPU_R8I,
+ GPU_R8,
+ GPU_R32UI,
+ GPU_R32I,
+ GPU_R32F,
+ GPU_R16UI,
+ GPU_R16I,
+ GPU_R16F,
+ GPU_R16, /* Max texture buffer format. */
+
+ /* Special formats texture & renderbuffer */
+#if 0
+ GPU_RGB10_A2,
+ GPU_RGB10_A2UI,
+ GPU_DEPTH32F_STENCIL8,
+#endif
+ GPU_R11F_G11F_B10F,
+ GPU_DEPTH24_STENCIL8,
+
+ /* Texture only format */
+ GPU_RGB16F,
+#if 0
+ GPU_RGBA16_SNORM,
+ GPU_RGBA8_SNORM,
+ GPU_RGB32F,
+ GPU_RGB32I,
+ GPU_RGB32UI,
+ GPU_RGB16_SNORM,
+ GPU_RGB16I,
+ GPU_RGB16UI,
+ GPU_RGB16,
+ GPU_RGB8_SNORM,
+ GPU_RGB8,
+ GPU_RGB8I,
+ GPU_RGB8UI,
+ GPU_RG16_SNORM,
+ GPU_RG8_SNORM,
+ GPU_R16_SNORM,
+ GPU_R8_SNORM,
+#endif
+
+ /* Special formats texture only */
+#if 0
+ GPU_SRGB8_A8,
+ GPU_SRGB8,
+ GPU_RGB9_E5,
+ GPU_COMPRESSED_RG_RGTC2,
+ GPU_COMPRESSED_SIGNED_RG_RGTC2,
+ GPU_COMPRESSED_RED_RGTC1,
+ GPU_COMPRESSED_SIGNED_RED_RGTC1,
+#endif
+
+ /* Depth Formats */
+ GPU_DEPTH_COMPONENT32F,
+ GPU_DEPTH_COMPONENT24,
+ GPU_DEPTH_COMPONENT16,
+} GPUTextureFormat;
+
+unsigned int GPU_texture_memory_usage_get(void);
+
+GPUTexture *GPU_texture_create_1D(
+ int w, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D(
+ int w, int h, GPUTextureFormat data_type, const float *pixels, 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]);
+ int w, int h, GPUTextureFormat data_type, const float *pixels, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_array(
+ int w, int h, int d, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_3D(
+ int w, int h, int d, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_cube(
+ int w, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_from_vertbuf(struct Gwn_VertBuf *vert);
+
GPUTexture *GPU_texture_from_blender(
struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time, int mipmap);
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
+
+void GPU_texture_update(GPUTexture *tex, const float *pixels);
+
void GPU_invalid_tex_init(void);
void GPU_invalid_tex_bind(int mode);
void GPU_invalid_tex_free(void);
@@ -81,21 +171,28 @@ void GPU_invalid_tex_free(void);
void GPU_texture_free(GPUTexture *tex);
void GPU_texture_ref(GPUTexture *tex);
-
void GPU_texture_bind(GPUTexture *tex, int number);
void GPU_texture_unbind(GPUTexture *tex);
int GPU_texture_bound_number(GPUTexture *tex);
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter);
+void GPU_texture_generate_mipmap(GPUTexture *tex);
+void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare);
+void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter);
+void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter);
+void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat);
-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);
+void GPU_texture_attach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment);
+int GPU_texture_detach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb);
int GPU_texture_target(const GPUTexture *tex);
int GPU_texture_width(const GPUTexture *tex);
int GPU_texture_height(const GPUTexture *tex);
-int GPU_texture_depth(const GPUTexture *tex);
+GPUTextureFormat GPU_texture_format(const GPUTexture *tex);
+int GPU_texture_samples(const GPUTexture *tex);
+bool GPU_texture_cube(const GPUTexture *tex);
+bool GPU_texture_depth(const GPUTexture *tex);
+bool GPU_texture_stencil(const GPUTexture *tex);
+bool GPU_texture_integer(const GPUTexture *tex);
int GPU_texture_opengl_bindcode(const GPUTexture *tex);
#ifdef __cplusplus
diff --git a/source/blender/gpu/GPU_uniformbuffer.h b/source/blender/gpu/GPU_uniformbuffer.h
new file mode 100644
index 00000000000..c2480f8ba03
--- /dev/null
+++ b/source/blender/gpu/GPU_uniformbuffer.h
@@ -0,0 +1,59 @@
+/*
+ * ***** 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_uniformbuffer.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_UNIFORMBUFFER_H__
+#define __GPU_UNIFORMBUFFER_H__
+
+struct ListBase;
+
+typedef struct GPUUniformBuffer GPUUniformBuffer;
+typedef struct GPUUniformBufferDynamicItem GPUUniformBufferDynamicItem;
+
+GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256]);
+GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(struct ListBase *inputs, char err_out[256]);
+
+void GPU_uniformbuffer_free(GPUUniformBuffer *ubo);
+
+void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data);
+void GPU_uniformbuffer_dynamic_update(GPUUniformBuffer *ubo_);
+
+void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number);
+void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo);
+
+int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo);
+
+bool GPU_uniformbuffer_is_empty(GPUUniformBuffer *ubo);
+bool GPU_uniformbuffer_is_dirty(GPUUniformBuffer *ubo);
+void GPU_uniformbuffer_tag_dirty(GPUUniformBuffer *ubo);
+
+#define GPU_UBO_BLOCK_NAME "nodeTree"
+
+#endif /* __GPU_UNIFORMBUFFER_H__ */
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
new file mode 100644
index 00000000000..921cd0e7369
--- /dev/null
+++ b/source/blender/gpu/GPU_viewport.h
@@ -0,0 +1,130 @@
+/*
+ * ***** 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):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_viewport.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_VIEWPORT_H__
+#define __GPU_VIEWPORT_H__
+
+#include <stdbool.h>
+
+#include "DNA_vec_types.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_texture.h"
+
+#define GPU_INFO_SIZE 512 /* IMA_MAX_RENDER_TEXT */
+
+typedef struct GPUViewport GPUViewport;
+
+/* Contains memory pools informations */
+typedef struct ViewportMemoryPool {
+ struct BLI_mempool *calls;
+ struct BLI_mempool *states;
+ struct BLI_mempool *shgroups;
+ struct BLI_mempool *uniforms;
+ struct BLI_mempool *passes;
+} ViewportMemoryPool;
+
+/* All FramebufferLists are just the same pointers with different names */
+typedef struct FramebufferList {
+ struct GPUFrameBuffer *framebuffers[0];
+} FramebufferList;
+
+typedef struct TextureList {
+ struct GPUTexture *textures[0];
+} TextureList;
+
+typedef struct PassList {
+ struct DRWPass *passes[0];
+} PassList;
+
+typedef struct StorageList {
+ void *storage[0]; /* custom structs from the engine */
+} StorageList;
+
+typedef struct ViewportEngineData {
+ void *engine_type;
+
+ FramebufferList *fbl;
+ TextureList *txl;
+ PassList *psl;
+ StorageList *stl;
+ char info[GPU_INFO_SIZE];
+
+ /* we may want to put this elsewhere */
+ struct DRWTextStore *text_draw_cache;
+
+ /* Profiling data */
+ double init_time;
+ double render_time;
+ double background_time;
+} ViewportEngineData;
+
+typedef struct ViewportEngineData_Info {
+ int fbl_len;
+ int txl_len;
+ int psl_len;
+ int stl_len;
+} ViewportEngineData_Info;
+
+GPUViewport *GPU_viewport_create(void);
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
+void GPU_viewport_unbind(GPUViewport *viewport);
+void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect);
+void GPU_viewport_free(GPUViewport *viewport);
+
+GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs);
+void GPU_viewport_clear_from_offscreen(GPUViewport *viewport);
+
+ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport);
+struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport);
+
+void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type);
+void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type);
+void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport);
+void *GPU_viewport_texture_list_get(GPUViewport *viewport);
+void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]);
+void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]);
+
+/* Profiling */
+double *GPU_viewport_cache_time_get(GPUViewport *viewport);
+
+void GPU_viewport_tag_update(GPUViewport *viewport);
+bool GPU_viewport_do_update(GPUViewport *viewport);
+
+GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport);
+
+/* Texture pool */
+GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int format);
+
+bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash);
+void GPU_viewport_cache_release(GPUViewport *viewport);
+
+#endif // __GPU_VIEWPORT_H__
diff --git a/source/blender/gpu/intern/gpu_basic_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c
index 8505bd847a0..620a06ae606 100644
--- a/source/blender/gpu/intern/gpu_basic_shader.c
+++ b/source/blender/gpu/intern/gpu_basic_shader.c
@@ -140,114 +140,6 @@ const GLubyte stipple_checker_8px[128] = {
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
-const GLubyte stipple_interlace_row[128] = {
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};
-
-const GLubyte stipple_interlace_row_swap[128] = {
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};
-
-const GLubyte stipple_interlace_column[128] = {
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
- 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
-
-const GLubyte stipple_interlace_column_swap[128] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
- 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
-
-const GLubyte stipple_interlace_checker[128] = {
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
- 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa};
-
-const GLubyte stipple_interlace_checker_swap[128] = {
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
- 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55};
-
const GLubyte stipple_hexagon[128] = {
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
@@ -267,24 +159,6 @@ const GLubyte stipple_hexagon[128] = {
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22};
/* ********************************************* */
-/* GLSL State */
-
-static bool USE_GLSL = false;
-
-/**
- * \note this isn't part of the basic shader API,
- * only set from the command line once on startup.
- */
-void GPU_basic_shader_use_glsl_set(bool enabled)
-{
- USE_GLSL = enabled;
-}
-
-bool GPU_basic_shader_use_glsl_get(void)
-{
- return USE_GLSL;
-}
-
/* Init / exit */
void GPU_basic_shaders_init(void)
@@ -316,31 +190,6 @@ static bool solid_compatible_lighting(void)
return ((directional & enabled) == enabled);
}
-#if 0
-static int detect_options()
-{
- GLint two_sided;
- int options = 0;
-
- if (glIsEnabled(GL_TEXTURE_2D))
- options |= GPU_SHADER_TEXTURE_2D;
- if (glIsEnabled(GL_TEXTURE_RECTANGLE))
- options |= GPU_SHADER_TEXTURE_RECT;
- GPU_SHADER_TEXTURE_RECT
- if (glIsEnabled(GL_COLOR_MATERIAL))
- options |= GPU_SHADER_USE_COLOR;
-
- if (glIsEnabled(GL_LIGHTING))
- options |= GPU_SHADER_LIGHTING;
-
- glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, &two_sided);
- if (two_sided == GL_TRUE)
- options |= GPU_SHADER_TWO_SIDED;
-
- return options;
-}
-#endif
-
static GPUShader *gpu_basic_shader(int options)
{
/* glsl code */
@@ -388,7 +237,7 @@ static GPUShader *gpu_basic_shader(int options)
datatoc_gpu_shader_basic_frag_glsl,
geom_glsl,
NULL,
- defines, 0, 0, 0);
+ defines);
if (shader) {
/* set texture map to first texture unit */
@@ -420,102 +269,16 @@ static void gpu_basic_shader_uniform_autoset(GPUShader *shader, int options)
void GPU_basic_shader_bind(int options)
{
- if (USE_GLSL) {
- if (options) {
- const int bound_options = GPU_MATERIAL_STATE.bound_options;
-
- /* texture options need to be set for basic shader too */
- if (options & GPU_SHADER_TEXTURE_2D) {
- glEnable(GL_TEXTURE_2D);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_2D) {
- glDisable(GL_TEXTURE_2D);
- }
-
- if (options & GPU_SHADER_TEXTURE_RECT) {
- glEnable(GL_TEXTURE_RECTANGLE);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_RECT) {
- glDisable(GL_TEXTURE_RECTANGLE);
- }
-
- GPUShader *shader = gpu_basic_shader(options);
+ if (options) {
+ GPUShader *shader = gpu_basic_shader(options);
- if (shader) {
- GPU_shader_bind(shader);
- gpu_basic_shader_uniform_autoset(shader, options);
- }
- }
- else {
- GPU_shader_unbind();
+ if (shader) {
+ GPU_shader_bind(shader);
+ gpu_basic_shader_uniform_autoset(shader, options);
}
}
else {
- const int bound_options = GPU_MATERIAL_STATE.bound_options;
-
- if (options & GPU_SHADER_LIGHTING) {
- glEnable(GL_LIGHTING);
-
- if (options & GPU_SHADER_USE_COLOR)
- glEnable(GL_COLOR_MATERIAL);
- else
- glDisable(GL_COLOR_MATERIAL);
-
- if (options & GPU_SHADER_TWO_SIDED)
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
- else
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
- }
- else if (bound_options & GPU_SHADER_LIGHTING) {
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
- }
-
- if (options & GPU_SHADER_TEXTURE_2D) {
- GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_2D) {
- if ((options & GPU_SHADER_TEXTURE_RECT) == 0) {
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
- glDisable(GL_TEXTURE_2D);
- }
-
- if (options & GPU_SHADER_TEXTURE_RECT) {
- GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
- glEnable(GL_TEXTURE_RECTANGLE);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_RECT) {
- if ((options & GPU_SHADER_TEXTURE_2D) == 0) {
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
- glDisable(GL_TEXTURE_RECTANGLE);
- }
-
- if ((options & GPU_SHADER_LINE) && (options & GPU_SHADER_STIPPLE)) {
- glEnable(GL_LINE_STIPPLE);
- }
- else if ((bound_options & GPU_SHADER_LINE) && (bound_options & GPU_SHADER_STIPPLE)) {
- glDisable(GL_LINE_STIPPLE);
- }
-
- if (((options & GPU_SHADER_LINE) == 0) && (options & GPU_SHADER_STIPPLE)) {
- glEnable(GL_POLYGON_STIPPLE);
- }
- else if (((bound_options & GPU_SHADER_LINE) == 0) && (bound_options & GPU_SHADER_STIPPLE)) {
- glDisable(GL_POLYGON_STIPPLE);
- }
-
- if (options & GPU_SHADER_FLAT_NORMAL) {
- glShadeModel(GL_FLAT);
- }
- else if (bound_options & GPU_SHADER_FLAT_NORMAL) {
- glShadeModel(GL_SMOOTH);
- }
+ GPU_shader_unbind();
}
GPU_MATERIAL_STATE.bound_options = options;
@@ -544,175 +307,37 @@ void GPU_basic_shader_colors(
const float diffuse[3], const float specular[3],
int shininess, float alpha)
{
- float gl_diffuse[4], gl_specular[4];
-
- if (diffuse)
- copy_v3_v3(gl_diffuse, diffuse);
- else
- zero_v3(gl_diffuse);
- gl_diffuse[3] = alpha;
-
- if (specular)
- copy_v3_v3(gl_specular, specular);
- else
- zero_v3(gl_specular);
- gl_specular[3] = 1.0f;
-
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gl_specular);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128));
+ UNUSED_VARS(diffuse, specular, shininess, alpha);
+ return;
}
void GPU_basic_shader_light_set(int light_num, GPULightData *light)
{
- int light_bit = (1 << light_num);
-
- /* note that light position is affected by the current modelview matrix! */
-
- GPU_MATERIAL_STATE.lights_enabled &= ~light_bit;
- GPU_MATERIAL_STATE.lights_directional &= ~light_bit;
-
- if (light) {
- float position[4], diffuse[4], specular[4];
-
- glEnable(GL_LIGHT0 + light_num);
-
- /* position */
- if (light->type == GPU_LIGHT_SUN) {
- copy_v3_v3(position, light->direction);
- position[3] = 0.0f;
- }
- else {
- copy_v3_v3(position, light->position);
- position[3] = 1.0f;
- }
- glLightfv(GL_LIGHT0 + light_num, GL_POSITION, position);
-
- /* energy */
- copy_v3_v3(diffuse, light->diffuse);
- copy_v3_v3(specular, light->specular);
- diffuse[3] = 1.0f;
- specular[3] = 1.0f;
- glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, diffuse);
- glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, specular);
-
- /* attenuation */
- if (light->type == GPU_LIGHT_SUN) {
- glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, 1.0f);
- glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, 0.0f);
- glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, 0.0f);
- }
- else {
- glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation);
- glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation);
- glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation);
- }
-
- /* spot */
- glLightfv(GL_LIGHT0 + light_num, GL_SPOT_DIRECTION, light->direction);
- if (light->type == GPU_LIGHT_SPOT) {
- glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, light->spot_cutoff);
- glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, light->spot_exponent);
- }
- else {
- glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, 180.0f);
- glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, 0.0f);
- }
-
- GPU_MATERIAL_STATE.lights_enabled |= light_bit;
- if (position[3] == 0.0f)
- GPU_MATERIAL_STATE.lights_directional |= light_bit;
- }
- else {
- /* TODO(sergey): Needs revisit. */
- if (USE_GLSL || true) {
- /* glsl shader needs these zero to skip them */
- const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
-
- glLightfv(GL_LIGHT0 + light_num, GL_POSITION, zero);
- glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, zero);
- glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, zero);
- }
-
- glDisable(GL_LIGHT0 + light_num);
- }
+ UNUSED_VARS(light_num, light);
+ return;
}
void GPU_basic_shader_light_set_viewer(bool local)
{
- glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (local) ? GL_TRUE: GL_FALSE);
+ UNUSED_VARS(local);
+ return;
}
void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id)
{
- if (USE_GLSL) {
- glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
- }
- else {
- switch (stipple_id) {
- case GPU_SHADER_STIPPLE_HALFTONE:
- glPolygonStipple(stipple_halftone);
- return;
- case GPU_SHADER_STIPPLE_QUARTTONE:
- glPolygonStipple(stipple_quarttone);
- return;
- case GPU_SHADER_STIPPLE_CHECKER_8PX:
- glPolygonStipple(stipple_checker_8px);
- return;
- case GPU_SHADER_STIPPLE_HEXAGON:
- glPolygonStipple(stipple_hexagon);
- return;
- case GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP:
- glPolygonStipple(stipple_diag_stripes_neg);
- return;
- case GPU_SHADER_STIPPLE_DIAG_STRIPES:
- glPolygonStipple(stipple_diag_stripes_pos);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW:
- glPolygonStipple(stipple_interlace_row);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW_SWAP:
- glPolygonStipple(stipple_interlace_row_swap);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN:
- glPolygonStipple(stipple_interlace_column);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN_SWAP:
- glPolygonStipple(stipple_interlace_column_swap);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER:
- glPolygonStipple(stipple_interlace_checker);
- return;
- case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER_SWAP:
- glPolygonStipple(stipple_interlace_checker_swap);
- return;
- default:
- glPolygonStipple(stipple_hexagon);
- return;
- }
- }
+ glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
}
void GPU_basic_shader_line_width(float line_width)
{
- if (USE_GLSL) {
- GPU_MATERIAL_STATE.line_width = line_width;
- if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) {
- glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width);
- }
- }
- else {
- glLineWidth(line_width);
+ GPU_MATERIAL_STATE.line_width = line_width;
+ if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) {
+ glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width);
}
}
void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern)
{
- if (USE_GLSL) {
- glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor);
- glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern);
- }
- else {
- glLineStipple(stipple_factor, stipple_pattern);
- }
+ glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor);
+ glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern);
}
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
new file mode 100644
index 00000000000..59d88e81822
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -0,0 +1,281 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_batch.c
+ * \ingroup gpu
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_rect.h"
+#include "BLI_math.h"
+#include "BLI_polyfill_2d.h"
+#include "BLI_sort_utils.h"
+
+
+#include "GPU_batch.h" /* own include */
+#include "gpu_shader_private.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+void GWN_batch_program_set_builtin(Gwn_Batch *batch, GPUBuiltinShader shader_id)
+{
+ GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
+ GWN_batch_program_set(batch, shader->program, shader->interface);
+}
+
+/** \} */
+
+
+
+/* -------------------------------------------------------------------- */
+/** \name Batch Creation
+ * \{ */
+
+/**
+ * Creates triangles from a byte-array of polygons.
+ *
+ * See 'make_shape_2d_from_blend.py' utility to create data to pass to this function.
+ *
+ * \param polys_flat: Pairs of X, Y coordinates (repeating to signify closing the polygon).
+ * \param polys_flat_len: Length of the array (must be an even number).
+ * \param rect: Optional region to map the byte 0..255 coords to. When not set use -1..1.
+ */
+Gwn_Batch *GPU_batch_tris_from_poly_2d_encoded(
+ const uchar *polys_flat, uint polys_flat_len, const rctf *rect)
+{
+ const uchar (*polys)[2] = (const void *)polys_flat;
+ const uint polys_len = polys_flat_len / 2;
+ BLI_assert(polys_flat_len == polys_len * 2);
+
+ /* Over alloc in both cases */
+ float (*verts)[2] = MEM_mallocN(sizeof(*verts) * polys_len, __func__);
+ float (*verts_step)[2] = verts;
+ uint (*tris)[3] = MEM_mallocN(sizeof(*tris) * polys_len, __func__);
+ uint (*tris_step)[3] = tris;
+
+ const float range_uchar[2] = {
+ (rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f,
+ (rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f,
+ };
+ const float min_uchar[2] = {
+ (rect ? rect->xmin : -1.0f),
+ (rect ? rect->ymin : -1.0f),
+ };
+
+ uint i_poly = 0;
+ uint i_vert = 0;
+ while (i_poly != polys_len) {
+ for (uint j = 0; j < 2; j++) {
+ verts[i_vert][j] = min_uchar[j] + ((float)polys[i_poly][j] * range_uchar[j]);
+ }
+ i_vert++;
+ i_poly++;
+ if (polys[i_poly - 1][0] == polys[i_poly][0] &&
+ polys[i_poly - 1][1] == polys[i_poly][1])
+ {
+ const uint verts_step_len = (&verts[i_vert]) - verts_step;
+ BLI_assert(verts_step_len >= 3);
+ const uint tris_len = (verts_step_len - 2);
+ BLI_polyfill_calc(verts_step, verts_step_len, -1, tris_step);
+ /* offset indices */
+ if (verts_step != verts) {
+ uint *t = tris_step[0];
+ const uint offset = (verts_step - verts);
+ uint tot = tris_len * 3;
+ while (tot--) {
+ *t += offset;
+ t++;
+ }
+ BLI_assert(t == tris_step[tris_len]);
+ }
+ verts_step += verts_step_len;
+ tris_step += tris_len;
+ i_poly++;
+ /* ignore the duplicate point */
+ }
+ }
+
+ /* We have vertices and tris, make a batch from this. */
+ static Gwn_VertFormat format = {0};
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ const uint verts_len = (verts_step - verts);
+ const uint tris_len = (tris_step - tris);
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, verts_len);
+
+ Gwn_VertBufRaw pos_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+
+ for (uint i = 0; i < verts_len; i++) {
+ copy_v2_v2(GWN_vertbuf_raw_step(&pos_step), verts[i]);
+ }
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tris_len, verts_len);
+ for (uint i = 0; i < tris_len; i++) {
+ GWN_indexbuf_add_tri_verts(&elb, UNPACK3(tris[i]));
+ }
+ Gwn_IndexBuf *indexbuf = GWN_indexbuf_build(&elb);
+
+ MEM_freeN(tris);
+ MEM_freeN(verts);
+
+ return GWN_batch_create_ex(
+ GWN_PRIM_TRIS, vbo,
+ indexbuf,
+ GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+}
+
+Gwn_Batch *GPU_batch_wire_from_poly_2d_encoded(
+ const uchar *polys_flat, uint polys_flat_len, const rctf *rect)
+{
+ const uchar (*polys)[2] = (const void *)polys_flat;
+ const uint polys_len = polys_flat_len / 2;
+ BLI_assert(polys_flat_len == polys_len * 2);
+
+ /* Over alloc */
+ /* Lines are pairs of (x, y) byte locations packed into an int32_t. */
+ int32_t *lines = MEM_mallocN(sizeof(*lines) * polys_len, __func__);
+ int32_t *lines_step = lines;
+
+ const float range_uchar[2] = {
+ (rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f,
+ (rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f,
+ };
+ const float min_uchar[2] = {
+ (rect ? rect->xmin : -1.0f),
+ (rect ? rect->ymin : -1.0f),
+ };
+
+ uint i_poly_prev = 0;
+ uint i_poly = 0;
+ while (i_poly != polys_len) {
+ i_poly++;
+ if (polys[i_poly - 1][0] == polys[i_poly][0] &&
+ polys[i_poly - 1][1] == polys[i_poly][1])
+ {
+ const uchar (*polys_step)[2] = polys + i_poly_prev;
+ const uint polys_step_len = i_poly - i_poly_prev;
+ BLI_assert(polys_step_len >= 2);
+ for (uint i_prev = polys_step_len - 1, i = 0; i < polys_step_len; i_prev = i++) {
+ union {
+ uint8_t as_u8[4];
+ uint16_t as_u16[2];
+ uint32_t as_u32;
+ } data;
+ data.as_u16[0] = *((const uint16_t *)polys_step[i_prev]);
+ data.as_u16[1] = *((const uint16_t *)polys_step[i]);
+ if (data.as_u16[0] > data.as_u16[1]) {
+ SWAP(uint16_t, data.as_u16[0], data.as_u16[1]);
+ }
+ *lines_step = data.as_u32;
+ lines_step++;
+ }
+ i_poly++;
+ i_poly_prev = i_poly;
+ /* ignore the duplicate point */
+ }
+ }
+
+ uint lines_len = lines_step - lines;
+
+ /* Hide Lines (we could make optional) */
+ {
+ qsort(lines, lines_len, sizeof(int32_t), BLI_sortutil_cmp_int);
+ lines_step = lines;
+
+ if (lines[0] != lines[1]) {
+ *lines_step++ = lines[0];
+ }
+ for (uint i_prev = 0, i = 1; i < lines_len; i_prev = i++) {
+ if (lines[i] != lines[i_prev]) {
+ *lines_step++ = lines[i];
+ }
+ }
+ lines_len = lines_step - lines;
+ }
+
+ /* We have vertices and tris, make a batch from this. */
+ static Gwn_VertFormat format = {0};
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ const uint vbo_len_capacity = lines_len * 2;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+ Gwn_VertBufRaw pos_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+
+ for (uint i = 0; i < lines_len; i++) {
+ union {
+ uint8_t as_u8_pair[2][2];
+ uint32_t as_u32;
+ } data;
+ data.as_u32 = lines[i];
+ for (uint k = 0; k < 2; k++) {
+ float *pos_v2 = GWN_vertbuf_raw_step(&pos_step);
+ for (uint j = 0; j < 2; j++) {
+ pos_v2[j] = min_uchar[j] + ((float)data.as_u8_pair[k][j] * range_uchar[j]);
+ }
+ }
+ }
+ BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
+ MEM_freeN(lines);
+ return GWN_batch_create_ex(
+ GWN_PRIM_LINES, vbo,
+ NULL,
+ GWN_BATCH_OWNS_VBO);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Init/Exit
+ * \{ */
+
+void gpu_batch_init(void)
+{
+ gpu_batch_presets_init();
+}
+
+void gpu_batch_exit(void)
+{
+ gpu_batch_presets_exit();
+}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c
new file mode 100644
index 00000000000..10cbd16490b
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_batch_presets.c
@@ -0,0 +1,236 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_batch_presets.c
+ * \ingroup gpu
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_threads.h"
+#include "BLI_listbase.h"
+#include "MEM_guardedalloc.h"
+
+#include "UI_interface.h"
+
+#include "GPU_batch.h"
+#include "gpu_shader_private.h"
+
+/* Struct to store 3D Batches and their format */
+static struct {
+ struct {
+ Gwn_Batch *sphere_high;
+ Gwn_Batch *sphere_med;
+ Gwn_Batch *sphere_low;
+ Gwn_Batch *sphere_wire_low;
+ Gwn_Batch *sphere_wire_med;
+ } batch;
+
+ Gwn_VertFormat format;
+
+ struct {
+ uint pos, nor;
+ } attr_id;
+} g_presets_3d = {{0}};
+
+static ListBase presets_list = {NULL, NULL};
+
+/* -------------------------------------------------------------------- */
+/** \name 3D Primitives
+ * \{ */
+
+static Gwn_VertFormat *preset_3D_format(void)
+{
+ if (g_presets_3d.format.attrib_ct == 0) {
+ Gwn_VertFormat *format = &g_presets_3d.format;
+ g_presets_3d.attr_id.pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ g_presets_3d.attr_id.nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+ return &g_presets_3d.format;
+}
+
+static void batch_sphere_lat_lon_vert(
+ Gwn_VertBufRaw *pos_step, Gwn_VertBufRaw *nor_step,
+ float lat, float lon)
+{
+ float pos[3];
+ pos[0] = sinf(lat) * cosf(lon);
+ pos[1] = cosf(lat);
+ pos[2] = sinf(lat) * sinf(lon);
+ copy_v3_v3(GWN_vertbuf_raw_step(pos_step), pos);
+ copy_v3_v3(GWN_vertbuf_raw_step(nor_step), pos);
+}
+
+/* Replacement for gluSphere */
+Gwn_Batch *gpu_batch_sphere(int lat_res, int lon_res)
+{
+ const float lon_inc = 2 * M_PI / lon_res;
+ const float lat_inc = M_PI / lat_res;
+ float lon, lat;
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(preset_3D_format());
+ const uint vbo_len = (lat_res - 1) * lon_res * 6;
+ GWN_vertbuf_data_alloc(vbo, vbo_len);
+
+ Gwn_VertBufRaw pos_step, nor_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step);
+ GWN_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step);
+
+ lon = 0.0f;
+ for (int i = 0; i < lon_res; i++, lon += lon_inc) {
+ lat = 0.0f;
+ for (int j = 0; j < lat_res; j++, lat += lat_inc) {
+ if (j != lat_res - 1) { /* Pole */
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon + lon_inc);
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon);
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon);
+ }
+
+ if (j != 0) { /* Pole */
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon + lon_inc);
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon + lon_inc);
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon);
+ }
+ }
+ }
+
+ BLI_assert(vbo_len == GWN_vertbuf_raw_used(&pos_step));
+ BLI_assert(vbo_len == GWN_vertbuf_raw_used(&nor_step));
+
+ return GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+}
+
+static Gwn_Batch *batch_sphere_wire(int lat_res, int lon_res)
+{
+ const float lon_inc = 2 * M_PI / lon_res;
+ const float lat_inc = M_PI / lat_res;
+ float lon, lat;
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(preset_3D_format());
+ const uint vbo_len = (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2);
+ GWN_vertbuf_data_alloc(vbo, vbo_len);
+
+ Gwn_VertBufRaw pos_step, nor_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step);
+ GWN_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step);
+
+ lon = 0.0f;
+ for (int i = 0; i < lon_res; i++, lon += lon_inc) {
+ lat = 0.0f;
+ for (int j = 0; j < lat_res; j++, lat += lat_inc) {
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon);
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon);
+
+ if (j != lat_res - 1) { /* Pole */
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon + lon_inc);
+ batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon);
+ }
+ }
+ }
+
+ BLI_assert(vbo_len == GWN_vertbuf_raw_used(&pos_step));
+ BLI_assert(vbo_len == GWN_vertbuf_raw_used(&nor_step));
+
+ return GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+}
+
+Gwn_Batch *GPU_batch_preset_sphere(int lod)
+{
+ BLI_assert(lod >= 0 && lod <= 2);
+ BLI_assert(BLI_thread_is_main());
+
+ if (lod == 0) {
+ return g_presets_3d.batch.sphere_low;
+ }
+ else if (lod == 1) {
+ return g_presets_3d.batch.sphere_med;
+ }
+ else {
+ return g_presets_3d.batch.sphere_high;
+ }
+}
+
+Gwn_Batch *GPU_batch_preset_sphere_wire(int lod)
+{
+ BLI_assert(lod >= 0 && lod <= 1);
+ BLI_assert(BLI_thread_is_main());
+
+ if (lod == 0) {
+ return g_presets_3d.batch.sphere_wire_low;
+ }
+ else {
+ return g_presets_3d.batch.sphere_wire_med;
+ }
+}
+
+/** \} */
+
+
+void gpu_batch_presets_init(void)
+{
+ /* Hard coded resolution */
+ g_presets_3d.batch.sphere_low = gpu_batch_sphere(8, 16);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_low);
+
+ g_presets_3d.batch.sphere_med = gpu_batch_sphere(16, 10);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_med);
+
+ g_presets_3d.batch.sphere_high = gpu_batch_sphere(32, 24);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_high);
+
+ g_presets_3d.batch.sphere_wire_low = batch_sphere_wire(6, 8);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_low);
+
+ g_presets_3d.batch.sphere_wire_med = batch_sphere_wire(8, 16);
+ gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_med);
+}
+
+void gpu_batch_presets_register(Gwn_Batch *preset_batch)
+{
+ BLI_addtail(&presets_list, BLI_genericNodeN(preset_batch));
+}
+
+void gpu_batch_presets_reset(void)
+{
+ /* Reset vao caches for these every time we switch opengl context.
+ * This way they will draw correctly for each window. */
+ LinkData *link = presets_list.first;
+ for (link = presets_list.first; link; link = link->next) {
+ Gwn_Batch *preset = link->data;
+ gwn_batch_vao_cache_clear(preset);
+ }
+}
+
+void gpu_batch_presets_exit(void)
+{
+ LinkData *link;
+ while ((link = BLI_pophead(&presets_list))) {
+ Gwn_Batch *preset = link->data;
+ GWN_batch_discard(preset);
+ MEM_freeN(link);
+ }
+}
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 38e847da967..9d2a0ceef4d 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -35,8 +35,6 @@
#include <stddef.h>
#include <string.h>
-#include "GPU_glew.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_bitmap.h"
@@ -55,914 +53,29 @@
#include "GPU_buffers.h"
#include "GPU_draw.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_batch.h"
#include "bmesh.h"
-typedef enum {
- GPU_BUFFER_VERTEX_STATE = (1 << 0),
- GPU_BUFFER_NORMAL_STATE = (1 << 1),
- GPU_BUFFER_TEXCOORD_UNIT_0_STATE = (1 << 2),
- GPU_BUFFER_TEXCOORD_UNIT_2_STATE = (1 << 3),
- GPU_BUFFER_COLOR_STATE = (1 << 4),
- GPU_BUFFER_ELEMENT_STATE = (1 << 5),
-} GPUBufferState;
-
-typedef struct {
- GLenum gl_buffer_type;
- int num_components; /* number of data components for one vertex */
-} GPUBufferTypeSettings;
-
-
-static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type);
-
-static const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
- /* vertex */
- {GL_ARRAY_BUFFER, 3},
- /* normal */
- {GL_ARRAY_BUFFER, 4}, /* we copy 3 shorts per normal but we add a fourth for alignment */
- /* mcol */
- {GL_ARRAY_BUFFER, 4},
- /* uv */
- {GL_ARRAY_BUFFER, 2},
- /* uv for texpaint */
- {GL_ARRAY_BUFFER, 4},
- /* edge */
- {GL_ELEMENT_ARRAY_BUFFER, 2},
- /* uv edge */
- {GL_ELEMENT_ARRAY_BUFFER, 4},
- /* triangles, 1 point since we are allocating from tottriangle points, which account for all points */
- {GL_ELEMENT_ARRAY_BUFFER, 1},
-};
-
-#define MAX_GPU_ATTRIB_DATA 32
-
-#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
-
-static GPUBufferState GLStates = 0;
-static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
-
static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
/* multires global buffer, can be used for many grids having the same grid size */
typedef struct GridCommonGPUBuffer {
- GPUBuffer *mres_buffer;
+ Gwn_IndexBuf *mres_buffer;
int mres_prev_gridsize;
- GLenum mres_prev_index_type;
unsigned mres_prev_totquad;
} GridCommonGPUBuffer;
-void GPU_buffer_material_finalize(GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat)
-{
- int i, curmat, curelement;
-
- /* count the number of materials used by this DerivedMesh */
- for (i = 0; i < totmat; i++) {
- if (matinfo[i].totelements > 0)
- gdo->totmaterial++;
- }
-
- /* allocate an array of materials used by this DerivedMesh */
- gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
- "GPUDrawObject.materials");
-
- /* initialize the materials array */
- for (i = 0, curmat = 0, curelement = 0; i < totmat; i++) {
- if (matinfo[i].totelements > 0) {
- gdo->materials[curmat] = matinfo[i];
- gdo->materials[curmat].start = curelement;
- gdo->materials[curmat].mat_nr = i;
- gdo->materials[curmat].polys = MEM_mallocN(sizeof(int) * matinfo[i].totpolys, "GPUBufferMaterial.polys");
-
- curelement += matinfo[i].totelements;
- curmat++;
- }
- }
-
- MEM_freeN(matinfo);
-}
-
-
-/* stores recently-deleted buffers so that new buffers won't have to
- * be recreated as often
- *
- * only one instance of this pool is created, stored in
- * gpu_buffer_pool
- *
- * note that the number of buffers in the pool is usually limited to
- * MAX_FREE_GPU_BUFFERS, but this limit may be exceeded temporarily
- * when a GPUBuffer is released outside the main thread; due to OpenGL
- * restrictions it cannot be immediately released
- */
-typedef struct GPUBufferPool {
- /* number of allocated buffers stored */
- int totbuf;
- /* actual allocated length of the arrays */
- int maxsize;
- GPUBuffer **buffers;
-} GPUBufferPool;
-#define MAX_FREE_GPU_BUFFERS 8
-
-/* create a new GPUBufferPool */
-static GPUBufferPool *gpu_buffer_pool_new(void)
-{
- GPUBufferPool *pool;
-
- pool = MEM_callocN(sizeof(GPUBufferPool), "GPUBuffer_Pool");
-
- pool->maxsize = MAX_FREE_GPU_BUFFERS;
- pool->buffers = MEM_mallocN(sizeof(*pool->buffers) * pool->maxsize,
- "GPUBufferPool.buffers");
- return pool;
-}
-
-/* remove a GPUBuffer from the pool (does not free the GPUBuffer) */
-static void gpu_buffer_pool_remove_index(GPUBufferPool *pool, int index)
-{
- int i;
-
- if (!pool || index < 0 || index >= pool->totbuf)
- return;
-
- /* shift entries down, overwriting the buffer at `index' */
- for (i = index; i < pool->totbuf - 1; i++)
- pool->buffers[i] = pool->buffers[i + 1];
-
- /* clear the last entry */
- if (pool->totbuf > 0)
- pool->buffers[pool->totbuf - 1] = NULL;
-
- pool->totbuf--;
-}
-
-/* delete the last entry in the pool */
-static void gpu_buffer_pool_delete_last(GPUBufferPool *pool)
-{
- GPUBuffer *last;
-
- if (pool->totbuf <= 0)
- return;
-
- /* get the last entry */
- if (!(last = pool->buffers[pool->totbuf - 1]))
- return;
-
- /* delete the buffer's data */
- glDeleteBuffers(1, &last->id);
-
- /* delete the buffer and remove from pool */
- MEM_freeN(last);
- pool->totbuf--;
- pool->buffers[pool->totbuf] = NULL;
-}
-
-/* free a GPUBufferPool; also frees the data in the pool's
- * GPUBuffers */
-static void gpu_buffer_pool_free(GPUBufferPool *pool)
-{
- if (!pool)
- return;
-
- while (pool->totbuf)
- gpu_buffer_pool_delete_last(pool);
-
- MEM_freeN(pool->buffers);
- MEM_freeN(pool);
-}
-
-static void gpu_buffer_pool_free_unused(GPUBufferPool *pool)
-{
- if (!pool)
- return;
-
- BLI_mutex_lock(&buffer_mutex);
-
- while (pool->totbuf)
- gpu_buffer_pool_delete_last(pool);
-
- BLI_mutex_unlock(&buffer_mutex);
-}
-
-static GPUBufferPool *gpu_buffer_pool = NULL;
-static GPUBufferPool *gpu_get_global_buffer_pool(void)
-{
- /* initialize the pool */
- if (!gpu_buffer_pool)
- gpu_buffer_pool = gpu_buffer_pool_new();
-
- return gpu_buffer_pool;
-}
-
-void GPU_global_buffer_pool_free(void)
-{
- gpu_buffer_pool_free(gpu_buffer_pool);
- gpu_buffer_pool = NULL;
-}
-
-void GPU_global_buffer_pool_free_unused(void)
-{
- gpu_buffer_pool_free_unused(gpu_buffer_pool);
-}
-
-/* get a GPUBuffer of at least `size' bytes; uses one from the buffer
- * pool if possible, otherwise creates a new one
- *
- * Thread-unsafe version for internal usage only.
- */
-static GPUBuffer *gpu_buffer_alloc_intern(size_t size)
-{
- GPUBufferPool *pool;
- GPUBuffer *buf;
- int i, bestfit = -1;
- size_t bufsize;
-
- /* bad case, leads to leak of buf since buf->pointer will allocate
- * NULL, leading to return without cleanup. In any case better detect early
- * psy-fi */
- if (size == 0)
- return NULL;
-
- pool = gpu_get_global_buffer_pool();
-
- /* not sure if this buffer pool code has been profiled much,
- * seems to me that the graphics driver and system memory
- * management might do this stuff anyway. --nicholas
- */
-
- /* check the global buffer pool for a recently-deleted buffer
- * that is at least as big as the request, but not more than
- * twice as big */
- for (i = 0; i < pool->totbuf; i++) {
- bufsize = pool->buffers[i]->size;
-
- /* check for an exact size match */
- if (bufsize == size) {
- bestfit = i;
- break;
- }
- /* smaller buffers won't fit data and buffers at least
- * twice as big are a waste of memory */
- else if (bufsize > size && size > (bufsize / 2)) {
- /* is it closer to the required size than the
- * last appropriate buffer found. try to save
- * memory */
- if (bestfit == -1 || pool->buffers[bestfit]->size > bufsize) {
- bestfit = i;
- }
- }
- }
-
- /* if an acceptable buffer was found in the pool, remove it
- * from the pool and return it */
- if (bestfit != -1) {
- buf = pool->buffers[bestfit];
- gpu_buffer_pool_remove_index(pool, bestfit);
- return buf;
- }
-
- /* no acceptable buffer found in the pool, create a new one */
- buf = MEM_callocN(sizeof(GPUBuffer), "GPUBuffer");
- buf->size = size;
-
- glGenBuffers(1, &buf->id);
- glBindBuffer(GL_ARRAY_BUFFER, buf->id);
- glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- return buf;
-}
-
-/* Same as above, but safe for threading. */
-GPUBuffer *GPU_buffer_alloc(size_t size)
-{
- GPUBuffer *buffer;
-
- if (size == 0) {
- /* Early out, no lock needed in this case. */
- return NULL;
- }
-
- BLI_mutex_lock(&buffer_mutex);
- buffer = gpu_buffer_alloc_intern(size);
- BLI_mutex_unlock(&buffer_mutex);
-
- return buffer;
-}
-
-/* release a GPUBuffer; does not free the actual buffer or its data,
- * but rather moves it to the pool of recently-freed buffers for
- * possible re-use
- *
- * Thread-unsafe version for internal usage only.
- */
-static void gpu_buffer_free_intern(GPUBuffer *buffer)
-{
- GPUBufferPool *pool;
- int i;
-
- if (!buffer)
- return;
-
- pool = gpu_get_global_buffer_pool();
-
- /* free the last used buffer in the queue if no more space, but only
- * if we are in the main thread. for e.g. rendering or baking it can
- * happen that we are in other thread and can't call OpenGL, in that
- * case cleanup will be done GPU_buffer_pool_free_unused */
- if (BLI_thread_is_main()) {
- /* in main thread, safe to decrease size of pool back
- * down to MAX_FREE_GPU_BUFFERS */
- while (pool->totbuf >= MAX_FREE_GPU_BUFFERS)
- gpu_buffer_pool_delete_last(pool);
- }
- else {
- /* outside of main thread, can't safely delete the
- * buffer, so increase pool size */
- if (pool->maxsize == pool->totbuf) {
- pool->maxsize += MAX_FREE_GPU_BUFFERS;
- pool->buffers = MEM_reallocN(pool->buffers,
- sizeof(GPUBuffer *) * pool->maxsize);
- }
- }
-
- /* shift pool entries up by one */
- for (i = pool->totbuf; i > 0; i--)
- pool->buffers[i] = pool->buffers[i - 1];
-
- /* insert the buffer into the beginning of the pool */
- pool->buffers[0] = buffer;
- pool->totbuf++;
-}
-
-/* Same as above, but safe for threading. */
-void GPU_buffer_free(GPUBuffer *buffer)
-{
- if (!buffer) {
- /* Early output, no need to lock in this case, */
- return;
- }
-
- BLI_mutex_lock(&buffer_mutex);
- gpu_buffer_free_intern(buffer);
- BLI_mutex_unlock(&buffer_mutex);
-}
-
-void GPU_drawobject_free(DerivedMesh *dm)
-{
- GPUDrawObject *gdo;
- int i;
-
- if (!dm || !(gdo = dm->drawObject))
- return;
-
- for (i = 0; i < gdo->totmaterial; i++) {
- if (gdo->materials[i].polys)
- MEM_freeN(gdo->materials[i].polys);
- }
-
- MEM_freeN(gdo->materials);
- if (gdo->vert_points)
- MEM_freeN(gdo->vert_points);
-#ifdef USE_GPU_POINT_LINK
- MEM_freeN(gdo->vert_points_mem);
-#endif
- GPU_buffer_free(gdo->points);
- GPU_buffer_free(gdo->normals);
- GPU_buffer_free(gdo->uv);
- GPU_buffer_free(gdo->uv_tex);
- GPU_buffer_free(gdo->colors);
- GPU_buffer_free(gdo->edges);
- GPU_buffer_free(gdo->uvedges);
- GPU_buffer_free(gdo->triangles);
-
- MEM_freeN(gdo);
- dm->drawObject = NULL;
-}
-
-static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, size_t size)
-{
- /* try freeing an entry from the pool
- * and reallocating the buffer */
- gpu_buffer_free_intern(buffer);
-
- buffer = NULL;
-
- while (pool->totbuf && !buffer) {
- gpu_buffer_pool_delete_last(pool);
- buffer = gpu_buffer_alloc_intern(size);
- }
-
- return buffer;
-}
-
-static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
- int type, void *user, GPUBuffer *buffer)
-{
- GPUBufferPool *pool;
- float *varray;
- int *mat_orig_to_new;
- int i;
- const GPUBufferTypeSettings *ts = &gpu_buffer_type_settings[type];
- GLenum target = ts->gl_buffer_type;
- size_t size = gpu_buffer_size_from_type(dm, type);
- GLboolean uploaded;
-
- pool = gpu_get_global_buffer_pool();
-
- BLI_mutex_lock(&buffer_mutex);
-
- /* alloc a GPUBuffer; fall back to legacy mode on failure */
- if (!buffer) {
- if (!(buffer = gpu_buffer_alloc_intern(size))) {
- BLI_mutex_unlock(&buffer_mutex);
- return NULL;
- }
- }
-
- mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
- "GPU_buffer_setup.mat_orig_to_new");
- for (i = 0; i < object->totmaterial; i++) {
- /* map from original material index to new
- * GPUBufferMaterial index */
- mat_orig_to_new[object->materials[i].mat_nr] = i;
- }
-
- /* bind the buffer and discard previous data,
- * avoids stalling gpu */
- glBindBuffer(target, buffer->id);
- glBufferData(target, buffer->size, NULL, GL_STATIC_DRAW);
-
- /* attempt to map the buffer */
- if (!(varray = glMapBuffer(target, GL_WRITE_ONLY))) {
- buffer = gpu_try_realloc(pool, buffer, size);
-
- /* allocation still failed; unfortunately we need to exit */
- if (!(buffer && (varray = glMapBuffer(target, GL_WRITE_ONLY)))) {
- if (buffer)
- gpu_buffer_free_intern(buffer);
- BLI_mutex_unlock(&buffer_mutex);
- return NULL;
- }
- }
-
- uploaded = GL_FALSE;
-
- /* attempt to upload the data to the VBO */
- while (uploaded == GL_FALSE) {
- dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user);
- /* glUnmapBuffer returns GL_FALSE if
- * the data store is corrupted; retry
- * in that case */
- uploaded = glUnmapBuffer(target);
- }
- glBindBuffer(target, 0);
-
- MEM_freeN(mat_orig_to_new);
-
- BLI_mutex_unlock(&buffer_mutex);
-
- return buffer;
-}
-
-/* get the GPUDrawObject buffer associated with a type */
-static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBufferType type)
-{
- switch (type) {
- case GPU_BUFFER_VERTEX:
- return &gdo->points;
- case GPU_BUFFER_NORMAL:
- return &gdo->normals;
- case GPU_BUFFER_COLOR:
- return &gdo->colors;
- case GPU_BUFFER_UV:
- return &gdo->uv;
- case GPU_BUFFER_UV_TEXPAINT:
- return &gdo->uv_tex;
- case GPU_BUFFER_EDGE:
- return &gdo->edges;
- case GPU_BUFFER_UVEDGE:
- return &gdo->uvedges;
- case GPU_BUFFER_TRIANGLES:
- return &gdo->triangles;
- default:
- return NULL;
- }
-}
-
-/* get the amount of space to allocate for a buffer of a particular type */
-static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
-{
- const int components = gpu_buffer_type_settings[type].num_components;
- switch (type) {
- case GPU_BUFFER_VERTEX:
- return sizeof(float) * components * (dm->drawObject->tot_loop_verts + dm->drawObject->tot_loose_point);
- case GPU_BUFFER_NORMAL:
- return sizeof(short) * components * dm->drawObject->tot_loop_verts;
- case GPU_BUFFER_COLOR:
- return sizeof(char) * components * dm->drawObject->tot_loop_verts;
- case GPU_BUFFER_UV:
- return sizeof(float) * components * dm->drawObject->tot_loop_verts;
- case GPU_BUFFER_UV_TEXPAINT:
- return sizeof(float) * components * dm->drawObject->tot_loop_verts;
- case GPU_BUFFER_EDGE:
- return sizeof(int) * components * dm->drawObject->totedge;
- case GPU_BUFFER_UVEDGE:
- return sizeof(int) * components * dm->drawObject->tot_loop_verts;
- case GPU_BUFFER_TRIANGLES:
- return sizeof(int) * components * dm->drawObject->tot_triangle_point;
- default:
- return -1;
- }
-}
-
-/* call gpu_buffer_setup with settings for a particular type of buffer */
-static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type, GPUBuffer *buf)
-{
- void *user_data = NULL;
-
- /* special handling for MCol and UV buffers */
- if (type == GPU_BUFFER_COLOR) {
- if (!(user_data = DM_get_loop_data_layer(dm, dm->drawObject->colType)))
- return NULL;
- }
- else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) {
- if (!DM_get_loop_data_layer(dm, CD_MLOOPUV))
- return NULL;
- }
-
- buf = gpu_buffer_setup(dm, dm->drawObject, type, user_data, buf);
-
- return buf;
-}
-
-/* get the buffer of `type', initializing the GPUDrawObject and
- * buffer if needed */
-static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type, bool update)
-{
- GPUBuffer **buf;
-
- if (!dm->drawObject)
- dm->drawObject = dm->gpuObjectNew(dm);
-
- buf = gpu_drawobject_buffer_from_type(dm->drawObject, type);
- if (!(*buf))
- *buf = gpu_buffer_setup_type(dm, type, NULL);
- else if (update)
- *buf = gpu_buffer_setup_type(dm, type, *buf);
-
- return *buf;
-}
-
-void GPU_vertex_setup(DerivedMesh *dm)
-{
- if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX, false))
- return;
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->points->id);
- glVertexPointer(3, GL_FLOAT, 0, 0);
-
- GLStates |= GPU_BUFFER_VERTEX_STATE;
-}
-
-void GPU_normal_setup(DerivedMesh *dm)
-{
- if (!gpu_buffer_setup_common(dm, GPU_BUFFER_NORMAL, false))
- return;
-
- glEnableClientState(GL_NORMAL_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->normals->id);
- glNormalPointer(GL_SHORT, 4 * sizeof(short), 0);
-
- GLStates |= GPU_BUFFER_NORMAL_STATE;
-}
-
-void GPU_uv_setup(DerivedMesh *dm)
-{
- if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV, false))
- return;
-
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->uv->id);
- glTexCoordPointer(2, GL_FLOAT, 0, 0);
-
- GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE;
-}
-
-void GPU_texpaint_uv_setup(DerivedMesh *dm)
-{
- if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV_TEXPAINT, false))
- return;
-
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->uv_tex->id);
- glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
- glClientActiveTexture(GL_TEXTURE2);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), BUFFER_OFFSET(2 * sizeof(float)));
- glClientActiveTexture(GL_TEXTURE0);
-
- GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_2_STATE;
-}
-
-
-void GPU_color_setup(DerivedMesh *dm, int colType)
-{
- bool update = false;
-
- if (!dm->drawObject) {
- /* XXX Not really nice, but we need a valid gpu draw object to set the colType...
- * Else we would have to add a new param to gpu_buffer_setup_common. */
- dm->drawObject = dm->gpuObjectNew(dm);
- dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW;
- dm->drawObject->colType = colType;
- }
- /* In paint mode, dm may stay the same during stroke, however we still want to update colors!
- * Also check in case we changed color type (i.e. which MCol cdlayer we use). */
- else if ((dm->dirty & DM_DIRTY_MCOL_UPDATE_DRAW) || (colType != dm->drawObject->colType)) {
- update = true;
- dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW;
- dm->drawObject->colType = colType;
- }
-
- if (!gpu_buffer_setup_common(dm, GPU_BUFFER_COLOR, update))
- return;
-
- glEnableClientState(GL_COLOR_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->colors->id);
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
-
- GLStates |= GPU_BUFFER_COLOR_STATE;
-}
-
-void GPU_buffer_bind_as_color(GPUBuffer *buffer)
-{
- glEnableClientState(GL_COLOR_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, buffer->id);
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
-
- GLStates |= GPU_BUFFER_COLOR_STATE;
-}
-
-
-void GPU_edge_setup(DerivedMesh *dm)
-{
- if (!gpu_buffer_setup_common(dm, GPU_BUFFER_EDGE, false))
- return;
-
- if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX, false))
- return;
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->points->id);
- glVertexPointer(3, GL_FLOAT, 0, 0);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dm->drawObject->edges->id);
-
- GLStates |= (GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_ELEMENT_STATE);
-}
-
-void GPU_uvedge_setup(DerivedMesh *dm)
-{
- if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UVEDGE, false))
- return;
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->uvedges->id);
- glVertexPointer(2, GL_FLOAT, 0, 0);
-
- GLStates |= GPU_BUFFER_VERTEX_STATE;
-}
-
-void GPU_triangle_setup(struct DerivedMesh *dm)
-{
- if (!gpu_buffer_setup_common(dm, GPU_BUFFER_TRIANGLES, false))
- return;
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dm->drawObject->triangles->id);
- GLStates |= GPU_BUFFER_ELEMENT_STATE;
-}
-
-static int gpu_typesize(int type)
-{
- switch (type) {
- case GL_FLOAT:
- return sizeof(float);
- case GL_INT:
- return sizeof(int);
- case GL_UNSIGNED_INT:
- return sizeof(unsigned int);
- case GL_BYTE:
- return sizeof(char);
- case GL_UNSIGNED_BYTE:
- return sizeof(unsigned char);
- default:
- return 0;
- }
-}
-
-int GPU_attrib_element_size(GPUAttrib data[], int numdata)
-{
- int i, elementsize = 0;
-
- for (i = 0; i < numdata; i++) {
- int typesize = gpu_typesize(data[i].type);
- if (typesize != 0)
- elementsize += typesize * data[i].size;
- }
- return elementsize;
-}
-
-void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata, int element_size)
-{
- int i;
- int elementsize;
- size_t offset = 0;
-
- for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
- if (attribData[i].index != -1) {
- glDisableVertexAttribArray(attribData[i].index);
- }
- else
- break;
- }
- if (element_size == 0)
- elementsize = GPU_attrib_element_size(data, numdata);
- else
- elementsize = element_size;
-
- glBindBuffer(GL_ARRAY_BUFFER, buffer->id);
-
- for (i = 0; i < numdata; i++) {
- glEnableVertexAttribArray(data[i].index);
- int info = 0;
- if (data[i].type == GL_UNSIGNED_BYTE) {
- info |= GPU_ATTR_INFO_SRGB;
- }
- glUniform1i(data[i].info_index, info);
-
- glVertexAttribPointer(data[i].index, data[i].size, data[i].type,
- GL_TRUE, elementsize, BUFFER_OFFSET(offset));
- offset += data[i].size * gpu_typesize(data[i].type);
-
- attribData[i].index = data[i].index;
- attribData[i].size = data[i].size;
- attribData[i].type = data[i].type;
- }
-
- attribData[numdata].index = -1;
-}
-
-void GPU_interleaved_attrib_unbind(void)
-{
- int i;
- for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
- if (attribData[i].index != -1) {
- glDisableVertexAttribArray(attribData[i].index);
- }
- else
- break;
- }
- attribData[0].index = -1;
-}
-
-void GPU_buffers_unbind(void)
-{
- int i;
-
- if (GLStates & GPU_BUFFER_VERTEX_STATE)
- glDisableClientState(GL_VERTEX_ARRAY);
- if (GLStates & GPU_BUFFER_NORMAL_STATE)
- glDisableClientState(GL_NORMAL_ARRAY);
- if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_0_STATE)
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_2_STATE) {
- glClientActiveTexture(GL_TEXTURE2);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glClientActiveTexture(GL_TEXTURE0);
- }
- if (GLStates & GPU_BUFFER_COLOR_STATE)
- glDisableClientState(GL_COLOR_ARRAY);
- if (GLStates & GPU_BUFFER_ELEMENT_STATE)
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
- GLStates &= ~(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE |
- GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_2_STATE |
- GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE);
-
- for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
- if (attribData[i].index != -1) {
- glDisableVertexAttribArray(attribData[i].index);
- }
- else
- break;
- }
- attribData[0].index = -1;
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-}
-
-void GPU_color_switch(int mode)
-{
- if (mode) {
- if (!(GLStates & GPU_BUFFER_COLOR_STATE))
- glEnableClientState(GL_COLOR_ARRAY);
- GLStates |= GPU_BUFFER_COLOR_STATE;
- }
- else {
- if (GLStates & GPU_BUFFER_COLOR_STATE)
- glDisableClientState(GL_COLOR_ARRAY);
- GLStates &= ~GPU_BUFFER_COLOR_STATE;
- }
-}
-
-static int gpu_binding_type_gl[] =
-{
- GL_ARRAY_BUFFER,
- GL_ELEMENT_ARRAY_BUFFER
-};
-
-void *GPU_buffer_lock(GPUBuffer *buffer, GPUBindingType binding)
-{
- float *varray;
- int bindtypegl;
-
- if (!buffer)
- return 0;
-
- bindtypegl = gpu_binding_type_gl[binding];
- glBindBuffer(bindtypegl, buffer->id);
- varray = glMapBuffer(bindtypegl, GL_WRITE_ONLY);
- return varray;
-}
-
-void *GPU_buffer_lock_stream(GPUBuffer *buffer, GPUBindingType binding)
-{
- float *varray;
- int bindtypegl;
-
- if (!buffer)
- return 0;
-
- bindtypegl = gpu_binding_type_gl[binding];
- glBindBuffer(bindtypegl, buffer->id);
- /* discard previous data, avoid stalling gpu */
- glBufferData(bindtypegl, buffer->size, 0, GL_STREAM_DRAW);
- varray = glMapBuffer(bindtypegl, GL_WRITE_ONLY);
- return varray;
-}
-
-void GPU_buffer_unlock(GPUBuffer *UNUSED(buffer), GPUBindingType binding)
-{
- int bindtypegl = gpu_binding_type_gl[binding];
- /* note: this operation can fail, could return
- * an error code from this function? */
- glUnmapBuffer(bindtypegl);
- glBindBuffer(bindtypegl, 0);
-}
-
-void GPU_buffer_bind(GPUBuffer *buffer, GPUBindingType binding)
-{
- int bindtypegl = gpu_binding_type_gl[binding];
- glBindBuffer(bindtypegl, buffer->id);
-}
-
-void GPU_buffer_unbind(GPUBuffer *UNUSED(buffer), GPUBindingType binding)
-{
- int bindtypegl = gpu_binding_type_gl[binding];
- glBindBuffer(bindtypegl, 0);
-}
-
-/* used for drawing edges */
-void GPU_buffer_draw_elements(GPUBuffer *UNUSED(elements), unsigned int mode, int start, int count)
-{
- glDrawElements(mode, count, GL_UNSIGNED_INT, BUFFER_OFFSET(start * sizeof(unsigned int)));
-}
-
-
/* XXX: the rest of the code in this file is used for optimized PBVH
* drawing and doesn't interact at all with the buffer code above */
-/* Convenience struct for building the VBO. */
-typedef struct {
- float co[3];
- short no[3];
-
- /* inserting this to align the 'color' field to a four-byte
- * boundary; drastically increases viewport performance on my
- * drivers (Gallium/Radeon) --nicholasbishop */
- char pad[2];
-
- unsigned char color[3];
-} VertexBufferFormat;
-
struct GPU_PBVH_Buffers {
- /* opengl buffer handles */
- GPUBuffer *vert_buf, *index_buf, *index_buf_fast;
- GLenum index_type;
+ Gwn_IndexBuf *index_buf, *index_buf_fast;
+ Gwn_VertBuf *vert_buf;
- int *baseelemarray;
- void **baseindex;
+ Gwn_Batch *triangles;
+ Gwn_Batch *triangles_fast;
/* mesh pointers in case buffer allocation fails */
const MPoly *mpoly;
@@ -995,10 +108,73 @@ struct GPU_PBVH_Buffers {
bool show_diffuse_color;
bool show_mask;
- bool use_matcaps;
float diffuse_color[4];
};
+static struct {
+ uint pos, nor, col;
+} g_vbo_id = {0};
+
+static void gpu_material_diffuse_get(int UNUSED(nr), float diff[4])
+{
+ /* TODO: sculpt diffuse color option not supported in 2.8 yet. */
+ diff[0] = 0.8f;
+ diff[1] = 0.8f;
+ diff[2] = 0.8f;
+ diff[3] = 1.0f;
+}
+
+/* Allocates a non-initialized buffer to be sent to GPU.
+ * Return is false it indicates that the memory map failed. */
+static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, unsigned int vert_ct)
+{
+ if (buffers->vert_buf == NULL) {
+ /* Initialize vertex buffer */
+ /* match 'VertexBufferFormat' */
+
+ static Gwn_VertFormat format = {0};
+ if (format.attrib_ct == 0) {
+ g_vbo_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ g_vbo_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ g_vbo_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ }
+#if 0
+ buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_DYNAMIC);
+ GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct);
+ }
+ else if (vert_ct != buffers->vert_buf->vertex_ct) {
+ GWN_vertbuf_data_resize(buffers->vert_buf, vert_ct);
+ }
+#else
+ buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC);
+ }
+ GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct);
+#endif
+ return buffers->vert_buf->data != NULL;
+}
+
+static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers)
+{
+ /* force flushing to the GPU */
+ if (buffers->vert_buf->data) {
+ GWN_vertbuf_use(buffers->vert_buf);
+ }
+
+ if (buffers->triangles == NULL) {
+ buffers->triangles = GWN_batch_create(
+ GWN_PRIM_TRIS, buffers->vert_buf,
+ /* can be NULL */
+ buffers->index_buf);
+ }
+
+ if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) {
+ buffers->triangles_fast = GWN_batch_create(
+ GWN_PRIM_TRIS, buffers->vert_buf,
+ /* can be NULL */
+ buffers->index_buf_fast);
+ }
+}
+
static float gpu_color_from_mask(float mask)
{
return 1.0f - mask * 0.75f;
@@ -1040,25 +216,20 @@ void GPU_pbvh_mesh_buffers_update(
{
const bool show_diffuse_color = (update_flags & GPU_PBVH_BUFFERS_SHOW_DIFFUSE_COLOR) != 0;
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
- VertexBufferFormat *vert_data;
- int i;
buffers->vmask = vmask;
buffers->show_diffuse_color = show_diffuse_color;
buffers->show_mask = show_mask;
- buffers->use_matcaps = GPU_material_use_matcaps_get();
{
int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3));
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 0.8f};
- if (buffers->use_matcaps)
- diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
- else if (show_diffuse_color) {
+ if (show_diffuse_color) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
const MPoly *mp = &buffers->mpoly[lt->poly];
- GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
+ gpu_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
}
copy_v4_v4(buffers->diffuse_color, diffuse_color);
@@ -1067,35 +238,29 @@ void GPU_pbvh_mesh_buffers_update(
rgba_float_to_uchar(diffuse_color_ub, diffuse_color);
/* Build VBO */
- if (buffers->vert_buf)
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totelem);
- vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY);
-
- if (vert_data) {
+ if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) {
/* Vertex data is shared if smooth-shaded, but separate
* copies are made for flat shading because normals
* shouldn't be shared. */
if (buffers->smooth) {
- for (i = 0; i < totvert; ++i) {
+ for (uint i = 0; i < totvert; ++i) {
const MVert *v = &mvert[vert_indices[i]];
- VertexBufferFormat *out = vert_data + i;
-
- copy_v3_v3(out->co, v->co);
- memcpy(out->no, v->no, sizeof(short) * 3);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, i, v->co);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, i, v->no);
}
- for (i = 0; i < buffers->face_indices_len; i++) {
+ for (uint i = 0; i < buffers->face_indices_len; i++) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
for (uint j = 0; j < 3; j++) {
- VertexBufferFormat *out = vert_data + face_vert_indices[i][j];
-
+ int vidx = face_vert_indices[i][j];
if (vmask && show_mask) {
- uint v_index = buffers->mloop[lt->tri[j]].v;
- gpu_color_from_mask_copy(vmask[v_index], diffuse_color, out->color);
+ int v_index = buffers->mloop[lt->tri[j]].v;
+ uchar color_ub[3];
+ gpu_color_from_mask_copy(vmask[v_index], diffuse_color, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, color_ub);
}
else {
- copy_v3_v3_uchar(out->color, diffuse_color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, diffuse_color_ub);
}
}
}
@@ -1104,8 +269,9 @@ void GPU_pbvh_mesh_buffers_update(
/* calculate normal for each polygon only once */
unsigned int mpoly_prev = UINT_MAX;
short no[3];
+ int vbo_index = 0;
- for (i = 0; i < buffers->face_indices_len; ++i) {
+ for (uint i = 0; i < buffers->face_indices_len; i++) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
const unsigned int vtri[3] = {
buffers->mloop[lt->tri[0]].v,
@@ -1136,22 +302,17 @@ void GPU_pbvh_mesh_buffers_update(
for (uint j = 0; j < 3; j++) {
const MVert *v = &mvert[vtri[j]];
- VertexBufferFormat *out = vert_data;
- copy_v3_v3(out->co, v->co);
- copy_v3_v3_short(out->no, no);
- copy_v3_v3_uchar(out->color, color_ub);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, v->co);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
- vert_data++;
+ vbo_index++;
}
}
}
- GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
- }
- else {
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = NULL;
+ gpu_pbvh_batch_init(buffers);
}
}
@@ -1166,16 +327,20 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(
const int face_indices_len)
{
GPU_PBVH_Buffers *buffers;
- unsigned short *tri_data;
- int i, j, tottri;
+ int i, tottri;
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
- buffers->index_type = GL_UNSIGNED_SHORT;
+
+ /* smooth or flat for all */
+#if 0
buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH;
+#else
+ /* for DrawManager we dont support mixed smooth/flat */
+ buffers->smooth = (mpoly[0].flag & ME_SMOOTH) != 0;
+#endif
buffers->show_diffuse_color = false;
buffers->show_mask = true;
- buffers->use_matcaps = false;
/* Count the number of visible triangles */
for (i = 0, tottri = 0; i < face_indices_len; ++i) {
@@ -1200,35 +365,28 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(
* shading requires separate vertex normals so an index buffer is
* can't be used there. */
if (buffers->smooth) {
- buffers->index_buf = GPU_buffer_alloc(sizeof(unsigned short) * tottri * 3);
- buffers->is_index_buf_global = false;
- }
-
- if (buffers->index_buf) {
/* Fill the triangle buffer */
- tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX);
- if (tri_data) {
- for (i = 0; i < face_indices_len; ++i) {
- const MLoopTri *lt = &looptri[face_indices[i]];
-
- /* Skip hidden faces */
- if (paint_is_face_hidden(lt, mvert, mloop))
- continue;
-
- for (j = 0; j < 3; ++j) {
- *tri_data = face_vert_indices[i][j];
- tri_data++;
- }
- }
- GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
+ buffers->index_buf = NULL;
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, INT_MAX);
+
+ for (i = 0; i < face_indices_len; ++i) {
+ const MLoopTri *lt = &looptri[face_indices[i]];
+
+ /* Skip hidden faces */
+ if (paint_is_face_hidden(lt, mvert, mloop))
+ continue;
+
+ GWN_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i]));
}
- else {
- if (!buffers->is_index_buf_global) {
- GPU_buffer_free(buffers->index_buf);
- }
- buffers->index_buf = NULL;
- buffers->is_index_buf_global = false;
+ buffers->index_buf = GWN_indexbuf_build(&elb);
+ }
+ else {
+ if (!buffers->is_index_buf_global) {
+ GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
}
+ buffers->index_buf = NULL;
+ buffers->is_index_buf_global = false;
}
buffers->tot_tri = tottri;
@@ -1251,61 +409,59 @@ void GPU_pbvh_grid_buffers_update(
{
const bool show_diffuse_color = (update_flags & GPU_PBVH_BUFFERS_SHOW_DIFFUSE_COLOR) != 0;
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
- VertexBufferFormat *vert_data;
int i, j, k, x, y;
buffers->show_diffuse_color = show_diffuse_color;
buffers->show_mask = show_mask;
- buffers->use_matcaps = GPU_material_use_matcaps_get();
buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
/* Build VBO */
- if (buffers->vert_buf) {
+ if (buffers->index_buf) {
const int has_mask = key->has_mask;
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
- if (buffers->use_matcaps)
- diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
- else if (show_diffuse_color) {
+ if (show_diffuse_color) {
const DMFlagMat *flags = &grid_flag_mats[grid_indices[0]];
- GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
+ gpu_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
}
copy_v4_v4(buffers->diffuse_color, diffuse_color);
- vert_data = GPU_buffer_lock_stream(buffers->vert_buf, GPU_BINDING_ARRAY);
- if (vert_data) {
+ uint vbo_index_offset = 0;
+ /* Build VBO */
+ if (gpu_pbvh_vert_buf_data_set(buffers, totgrid * key->grid_area)) {
for (i = 0; i < totgrid; ++i) {
- VertexBufferFormat *vd = vert_data;
CCGElem *grid = grids[grid_indices[i]];
+ int vbo_index = vbo_index_offset;
for (y = 0; y < key->grid_size; y++) {
for (x = 0; x < key->grid_size; x++) {
CCGElem *elem = CCG_grid_elem(key, grid, x, y);
-
- copy_v3_v3(vd->co, CCG_elem_co(key, elem));
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem));
+
if (buffers->smooth) {
- normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem));
+ short no_short[3];
+ normal_float_to_short_v3(no_short, CCG_elem_no(key, elem));
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
if (has_mask) {
+ uchar color_ub[3];
if (show_mask) {
gpu_color_from_mask_copy(*CCG_elem_mask(key, elem),
- diffuse_color, vd->color);
+ diffuse_color, color_ub);
}
else {
- unit_float_to_uchar_clamp_v3(vd->color, diffuse_color);
+ unit_float_to_uchar_clamp_v3(color_ub, diffuse_color);
}
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
}
}
- vd++;
+ vbo_index += 1;
}
}
if (!buffers->smooth) {
- /* for flat shading, recalc normals and set the last vertex of
- * each triangle in the index buffer to have the flat normal as
- * that is what opengl will use */
for (j = 0; j < key->grid_size - 1; j++) {
for (k = 0; k < key->grid_size - 1; k++) {
CCGElem *elems[4] = {
@@ -1322,10 +478,13 @@ void GPU_pbvh_grid_buffers_update(
CCG_elem_co(key, elems[2]),
CCG_elem_co(key, elems[3]));
- vd = vert_data + (j + 1) * key->grid_size + k;
- normal_float_to_short_v3(vd->no, fno);
+ vbo_index = vbo_index_offset + ((j + 1) * key->grid_size + k);
+ short no_short[3];
+ normal_float_to_short_v3(no_short, fno);
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short);
if (has_mask) {
+ uchar color_ub[3];
if (show_mask) {
gpu_color_from_mask_quad_copy(key,
elems[0],
@@ -1333,24 +492,21 @@ void GPU_pbvh_grid_buffers_update(
elems[2],
elems[3],
diffuse_color,
- vd->color);
+ color_ub);
}
else {
- unit_float_to_uchar_clamp_v3(vd->color, diffuse_color);
+ unit_float_to_uchar_clamp_v3(color_ub, diffuse_color);
}
+ GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub);
}
}
}
}
- vert_data += key->grid_area;
+ vbo_index_offset += key->grid_area;
}
- GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
- }
- else {
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = NULL;
+ gpu_pbvh_batch_init(buffers);
}
}
@@ -1365,57 +521,54 @@ void GPU_pbvh_grid_buffers_update(
/* Build the element array buffer of grid indices using either
* unsigned shorts or unsigned ints. */
-#define FILL_QUAD_BUFFER(type_, tot_quad_, buffer_) \
+#define FILL_QUAD_BUFFER(max_vert_, tot_quad_, buffer_) \
{ \
- type_ *tri_data; \
int offset = 0; \
int i, j, k; \
- buffer_ = GPU_buffer_alloc(sizeof(type_) * (tot_quad_) * 6); \
+ \
+ Gwn_IndexBufBuilder elb; \
+ GWN_indexbuf_init( \
+ &elb, GWN_PRIM_TRIS, tot_quad_ * 2, max_vert_); \
\
/* Fill the buffer */ \
- tri_data = GPU_buffer_lock(buffer_, GPU_BINDING_INDEX); \
- if (tri_data) { \
- for (i = 0; i < totgrid; ++i) { \
- BLI_bitmap *gh = NULL; \
- if (grid_hidden) \
- gh = grid_hidden[(grid_indices)[i]]; \
+ for (i = 0; i < totgrid; ++i) { \
+ BLI_bitmap *gh = NULL; \
+ if (grid_hidden) \
+ gh = grid_hidden[(grid_indices)[i]]; \
\
- for (j = 0; j < gridsize - 1; ++j) { \
- for (k = 0; k < gridsize - 1; ++k) { \
- /* Skip hidden grid face */ \
- if (gh && \
- paint_is_grid_face_hidden(gh, \
- gridsize, k, j)) \
- continue; \
- \
- *(tri_data++) = offset + j * gridsize + k + 1; \
- *(tri_data++) = offset + j * gridsize + k; \
- *(tri_data++) = offset + (j + 1) * gridsize + k; \
- \
- *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \
- *(tri_data++) = offset + j * gridsize + k + 1; \
- *(tri_data++) = offset + (j + 1) * gridsize + k; \
- } \
- } \
- \
- offset += gridsize * gridsize; \
+ for (j = 0; j < gridsize - 1; ++j) { \
+ for (k = 0; k < gridsize - 1; ++k) { \
+ /* Skip hidden grid face */ \
+ if (gh && paint_is_grid_face_hidden( \
+ gh, gridsize, k, j)) \
+ { \
+ continue; \
+ } \
+ GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
+ GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k); \
+ GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
+ \
+ GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k + 1); \
+ GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \
+ GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \
+ } \
} \
- GPU_buffer_unlock(buffer_, GPU_BINDING_INDEX); \
- } \
- else { \
- GPU_buffer_free(buffer_); \
- (buffer_) = NULL; \
+ \
+ offset += gridsize * gridsize; \
} \
+ buffer_ = GWN_indexbuf_build(&elb); \
} (void)0
/* end FILL_QUAD_BUFFER */
-static GPUBuffer *gpu_get_grid_buffer(
- int gridsize, GLenum *index_type, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer)
+static Gwn_IndexBuf *gpu_get_grid_buffer(
+ int gridsize, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer,
+ /* remove this arg when gawain gets base-vertex support! */
+ int totgrid)
{
/* used in the FILL_QUAD_BUFFER macro */
BLI_bitmap * const *grid_hidden = NULL;
const int *grid_indices = NULL;
- int totgrid = 1;
+ // int totgrid = 1;
GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer;
@@ -1423,65 +576,48 @@ static GPUBuffer *gpu_get_grid_buffer(
*grid_common_gpu_buffer = gridbuff = MEM_mallocN(sizeof(GridCommonGPUBuffer), __func__);
gridbuff->mres_buffer = NULL;
gridbuff->mres_prev_gridsize = -1;
- gridbuff->mres_prev_index_type = 0;
gridbuff->mres_prev_totquad = 0;
}
/* VBO is already built */
if (gridbuff->mres_buffer && gridbuff->mres_prev_gridsize == gridsize) {
- *index_type = gridbuff->mres_prev_index_type;
*totquad = gridbuff->mres_prev_totquad;
return gridbuff->mres_buffer;
}
/* we can't reuse old, delete the existing buffer */
else if (gridbuff->mres_buffer) {
- GPU_buffer_free(gridbuff->mres_buffer);
+ GWN_indexbuf_discard(gridbuff->mres_buffer);
+ gridbuff->mres_buffer = NULL;
}
/* Build new VBO */
- *totquad = (gridsize - 1) * (gridsize - 1);
+ *totquad = (gridsize - 1) * (gridsize - 1) * totgrid;
+ int max_vert = gridsize * gridsize * totgrid;
- if (gridsize * gridsize < USHRT_MAX) {
- *index_type = GL_UNSIGNED_SHORT;
- FILL_QUAD_BUFFER(unsigned short, *totquad, gridbuff->mres_buffer);
- }
- else {
- *index_type = GL_UNSIGNED_INT;
- FILL_QUAD_BUFFER(unsigned int, *totquad, gridbuff->mres_buffer);
- }
+ FILL_QUAD_BUFFER(max_vert, *totquad, gridbuff->mres_buffer);
gridbuff->mres_prev_gridsize = gridsize;
- gridbuff->mres_prev_index_type = *index_type;
gridbuff->mres_prev_totquad = *totquad;
return gridbuff->mres_buffer;
}
-#define FILL_FAST_BUFFER(type_) \
+#define FILL_FAST_BUFFER() \
{ \
- type_ *buffer; \
- buffers->index_buf_fast = GPU_buffer_alloc(sizeof(type_) * 6 * totgrid); \
- buffer = GPU_buffer_lock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
- if (buffer) { \
- int i; \
- for (i = 0; i < totgrid; i++) { \
- int currentquad = i * 6; \
- buffer[currentquad] = i * gridsize * gridsize + gridsize - 1; \
- buffer[currentquad + 1] = i * gridsize * gridsize; \
- buffer[currentquad + 2] = (i + 1) * gridsize * gridsize - gridsize; \
- buffer[currentquad + 3] = (i + 1) * gridsize * gridsize - 1; \
- buffer[currentquad + 4] = i * gridsize * gridsize + gridsize - 1; \
- buffer[currentquad + 5] = (i + 1) * gridsize * gridsize - gridsize; \
- } \
- GPU_buffer_unlock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
- } \
- else { \
- GPU_buffer_free(buffers->index_buf_fast); \
- buffers->index_buf_fast = NULL; \
+ Gwn_IndexBufBuilder elb; \
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, 6 * totgrid, INT_MAX); \
+ for (int i = 0; i < totgrid; i++) { \
+ GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
+ GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize); \
+ GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
+ GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - 1); \
+ GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \
+ GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \
} \
+ buffers->index_buf_fast = GWN_indexbuf_build(&elb); \
} (void)0
GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
- int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key,
+ int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *UNUSED(key),
GridCommonGPUBuffer **grid_common_gpu_buffer)
{
GPU_PBVH_Buffers *buffers;
@@ -1494,7 +630,6 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
buffers->show_diffuse_color = false;
buffers->show_mask = true;
- buffers->use_matcaps = false;
/* Count the number of quads */
totquad = BKE_pbvh_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize);
@@ -1504,39 +639,26 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
return buffers;
/* create and fill indices of the fast buffer too */
- if (totgrid * gridsize * gridsize < USHRT_MAX) {
- FILL_FAST_BUFFER(unsigned short);
- }
- else {
- FILL_FAST_BUFFER(unsigned int);
- }
+ FILL_FAST_BUFFER();
if (totquad == fully_visible_totquad) {
buffers->index_buf = gpu_get_grid_buffer(
- gridsize, &buffers->index_type, &buffers->tot_quad, grid_common_gpu_buffer);
+ gridsize, &buffers->tot_quad, grid_common_gpu_buffer, totgrid);
buffers->has_hidden = false;
buffers->is_index_buf_global = true;
}
else {
+ uint max_vert = totgrid * gridsize * gridsize;
buffers->tot_quad = totquad;
- if (totgrid * gridsize * gridsize < USHRT_MAX) {
- buffers->index_type = GL_UNSIGNED_SHORT;
- FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf);
- }
- else {
- buffers->index_type = GL_UNSIGNED_INT;
- FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf);
- }
+ FILL_QUAD_BUFFER(max_vert, totquad, buffers->index_buf);
- buffers->has_hidden = true;
+ buffers->has_hidden = false;
buffers->is_index_buf_global = false;
}
+#ifdef USE_BASE_ELEM
/* Build coord/normal VBO */
- if (buffers->index_buf)
- buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totgrid * key->grid_area);
-
if (GLEW_ARB_draw_elements_base_vertex /* 3.2 */) {
int i;
buffers->baseelemarray = MEM_mallocN(sizeof(int) * totgrid * 2, "GPU_PBVH_Buffers.baseelemarray");
@@ -1547,6 +669,7 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
buffers->baseindex[i] = NULL;
}
}
+#endif
return buffers;
}
@@ -1559,32 +682,44 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(
* index '*v_index' in the 'vert_data' array and '*v_index' is
* incremented.
*/
-static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
- VertexBufferFormat *vert_data,
- int *v_index,
- const float fno[3],
- const float *fmask,
- const int cd_vert_mask_offset,
- const float diffuse_color[4],
- const bool show_mask)
+static void gpu_bmesh_vert_to_buffer_copy__gwn(
+ BMVert *v,
+ Gwn_VertBuf *vert_buf,
+ int *v_index,
+ const float fno[3],
+ const float *fmask,
+ const int cd_vert_mask_offset,
+ const float diffuse_color[4],
+ const bool show_mask)
{
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- VertexBufferFormat *vd = &vert_data[*v_index];
/* Set coord, normal, and mask */
- copy_v3_v3(vd->co, v->co);
- normal_float_to_short_v3(vd->no, fno ? fno : v->no);
+ GWN_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co);
- float effective_mask;
- if (show_mask) {
- effective_mask = fmask ? *fmask
- : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
- }
- else {
- effective_mask = 0.0f;
+ {
+ short no_short[3];
+ normal_float_to_short_v3(no_short, fno ? fno : v->no);
+ GWN_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short);
}
- gpu_color_from_mask_copy(effective_mask, diffuse_color, vd->color);
+ {
+ uchar color_ub[3];
+ float effective_mask;
+ if (show_mask) {
+ effective_mask = fmask ? *fmask
+ : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
+ }
+ else {
+ effective_mask = 0.0f;
+ }
+
+ gpu_color_from_mask_copy(
+ effective_mask,
+ diffuse_color,
+ color_ub);
+ GWN_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, color_ub);
+ }
/* Assign index for use in the triangle index buffer */
/* note: caller must set: bm->elem_index_dirty |= BM_VERT; */
@@ -1643,8 +778,6 @@ void GPU_pbvh_bmesh_buffers_update(
{
const bool show_diffuse_color = (update_flags & GPU_PBVH_BUFFERS_SHOW_DIFFUSE_COLOR) != 0;
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
- VertexBufferFormat *vert_data;
- void *tri_data;
int tottri, totvert, maxvert = 0;
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
@@ -1653,7 +786,6 @@ void GPU_pbvh_bmesh_buffers_update(
buffers->show_diffuse_color = show_diffuse_color;
buffers->show_mask = show_mask;
- buffers->use_matcaps = GPU_material_use_matcaps_get();
/* Count visible triangles */
tottri = gpu_bmesh_face_visible_count(bm_faces);
@@ -1670,27 +802,19 @@ void GPU_pbvh_bmesh_buffers_update(
return;
}
- if (buffers->use_matcaps)
- diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
- else if (show_diffuse_color) {
+ if (show_diffuse_color) {
/* due to dynamic nature of dyntopo, only get first material */
GSetIterator gs_iter;
BMFace *f;
BLI_gsetIterator_init(&gs_iter, bm_faces);
f = BLI_gsetIterator_getKey(&gs_iter);
- GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ gpu_material_diffuse_get(f->mat_nr + 1, diffuse_color);
}
copy_v4_v4(buffers->diffuse_color, diffuse_color);
- /* Initialize vertex buffer */
- if (buffers->vert_buf)
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totvert);
-
/* Fill vertex buffer */
- vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY);
- if (vert_data) {
+ if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) {
int v_index = 0;
if (buffers->smooth) {
@@ -1701,17 +825,19 @@ void GPU_pbvh_bmesh_buffers_update(
bm->elem_index_dirty |= BM_VERT;
GSET_ITER (gs_iter, bm_unique_verts) {
- gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter),
- vert_data, &v_index, NULL, NULL,
- cd_vert_mask_offset, diffuse_color,
- show_mask);
+ gpu_bmesh_vert_to_buffer_copy__gwn(
+ BLI_gsetIterator_getKey(&gs_iter),
+ buffers->vert_buf, &v_index, NULL, NULL,
+ cd_vert_mask_offset, diffuse_color,
+ show_mask);
}
GSET_ITER (gs_iter, bm_other_verts) {
- gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter),
- vert_data, &v_index, NULL, NULL,
- cd_vert_mask_offset, diffuse_color,
- show_mask);
+ gpu_bmesh_vert_to_buffer_copy__gwn(
+ BLI_gsetIterator_getKey(&gs_iter),
+ buffers->vert_buf, &v_index, NULL, NULL,
+ cd_vert_mask_offset, diffuse_color,
+ show_mask);
}
maxvert = v_index;
@@ -1741,10 +867,11 @@ void GPU_pbvh_bmesh_buffers_update(
fmask /= 3.0f;
for (i = 0; i < 3; i++) {
- gpu_bmesh_vert_to_buffer_copy(v[i], vert_data,
- &v_index, f->no, &fmask,
- cd_vert_mask_offset, diffuse_color,
- show_mask);
+ gpu_bmesh_vert_to_buffer_copy__gwn(
+ v[i], buffers->vert_buf,
+ &v_index, f->no, &fmask,
+ cd_vert_mask_offset, diffuse_color,
+ show_mask);
}
}
}
@@ -1752,32 +879,26 @@ void GPU_pbvh_bmesh_buffers_update(
buffers->tot_tri = tottri;
}
- GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
-
/* gpu_bmesh_vert_to_buffer_copy sets dirty index values */
bm->elem_index_dirty |= BM_VERT;
}
else {
/* Memory map failed */
- GPU_buffer_free(buffers->vert_buf);
- buffers->vert_buf = NULL;
return;
}
if (buffers->smooth) {
- const int use_short = (maxvert < USHRT_MAX);
+ /* Fill the triangle buffer */
+ buffers->index_buf = NULL;
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, maxvert);
/* Initialize triangle index buffer */
- if (buffers->index_buf && !buffers->is_index_buf_global)
- GPU_buffer_free(buffers->index_buf);
buffers->is_index_buf_global = false;
- buffers->index_buf = GPU_buffer_alloc((use_short ?
- sizeof(unsigned short) :
- sizeof(unsigned int)) * 3 * tottri);
/* Fill triangle index buffer */
- tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX);
- if (tri_data) {
+
+ {
GSetIterator gs_iter;
GSET_ITER (gs_iter, bm_faces) {
@@ -1789,46 +910,30 @@ void GPU_pbvh_bmesh_buffers_update(
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
- BMVert *v = l_iter->v;
- if (use_short) {
- unsigned short *elem = tri_data;
- (*elem) = BM_elem_index_get(v);
- elem++;
- tri_data = elem;
- }
- else {
- unsigned int *elem = tri_data;
- (*elem) = BM_elem_index_get(v);
- elem++;
- tri_data = elem;
- }
+ GWN_indexbuf_add_generic_vert(&elb, BM_elem_index_get(l_iter->v));
} while ((l_iter = l_iter->next) != l_first);
}
}
- GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
-
buffers->tot_tri = tottri;
- buffers->index_type = (use_short ?
- GL_UNSIGNED_SHORT :
- GL_UNSIGNED_INT);
- }
- else {
- /* Memory map failed */
- if (!buffers->is_index_buf_global) {
- GPU_buffer_free(buffers->index_buf);
+
+ if (buffers->index_buf == NULL) {
+ buffers->index_buf = GWN_indexbuf_build(&elb);
+ }
+ else {
+ GWN_indexbuf_build_in_place(&elb, buffers->index_buf);
}
- buffers->index_buf = NULL;
- buffers->is_index_buf_global = false;
}
}
else if (buffers->index_buf) {
if (!buffers->is_index_buf_global) {
- GPU_buffer_free(buffers->index_buf);
+ GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
}
buffers->index_buf = NULL;
buffers->is_index_buf_global = false;
}
+
+ gpu_pbvh_batch_init(buffers);
}
GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
@@ -1840,172 +945,31 @@ GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading)
buffers->smooth = smooth_shading;
buffers->show_diffuse_color = false;
buffers->show_mask = true;
- buffers->use_matcaps = false;
return buffers;
}
-void GPU_pbvh_buffers_draw(
- GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe, bool fast)
+Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast)
{
- bool do_fast = fast && buffers->index_buf_fast;
- /* sets material from the first face, to solve properly face would need to
- * be sorted in buckets by materials */
- if (setMaterial) {
- if (buffers->face_indices_len) {
- const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
- const MPoly *mp = &buffers->mpoly[lt->poly];
- if (!setMaterial(mp->mat_nr + 1, NULL))
- return;
- }
- else if (buffers->totgrid) {
- const DMFlagMat *f = &buffers->grid_flag_mats[buffers->grid_indices[0]];
- if (!setMaterial(f->mat_nr + 1, NULL))
- return;
- }
- else {
- if (!setMaterial(1, NULL))
- return;
- }
- }
-
- if (buffers->vert_buf) {
- char *base = NULL;
- char *index_base = NULL;
- /* weak inspection of bound options, should not be necessary ideally */
- const int bound_options_old = GPU_basic_shader_bound_options();
- int bound_options_new = 0;
- glEnableClientState(GL_VERTEX_ARRAY);
- if (!wireframe) {
- glEnableClientState(GL_NORMAL_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
-
- bound_options_new |= GPU_SHADER_USE_COLOR;
- }
-
- GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY);
-
- if (do_fast) {
- GPU_buffer_bind(buffers->index_buf_fast, GPU_BINDING_INDEX);
- }
- else if (buffers->index_buf) {
- GPU_buffer_bind(buffers->index_buf, GPU_BINDING_INDEX);
- }
-
- if (wireframe) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- }
- else {
- if ((buffers->smooth == false) && (buffers->face_indices_len == 0)) {
- bound_options_new |= GPU_SHADER_FLAT_NORMAL;
- }
- }
-
- if (bound_options_new & ~bound_options_old) {
- GPU_basic_shader_bind(bound_options_old | bound_options_new);
- }
-
- if (buffers->tot_quad) {
- const char *offset = base;
- const bool drawall = !(buffers->has_hidden || do_fast);
-
- if (GLEW_ARB_draw_elements_base_vertex && drawall) {
-
- glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, co));
- if (!wireframe) {
- glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, no));
- glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, color));
- }
-
- glMultiDrawElementsBaseVertex(GL_TRIANGLES, buffers->baseelemarray, buffers->index_type,
- (const void * const *)buffers->baseindex,
- buffers->totgrid, &buffers->baseelemarray[buffers->totgrid]);
- }
- else {
- int i, last = drawall ? buffers->totgrid : 1;
-
- /* we could optimize this to one draw call, but it would need more memory */
- for (i = 0; i < last; i++) {
- glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, co));
- if (!wireframe) {
- glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, no));
- glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
- offset + offsetof(VertexBufferFormat, color));
- }
-
- if (do_fast)
- glDrawElements(GL_TRIANGLES, buffers->totgrid * 6, buffers->index_type, index_base);
- else
- glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, index_base);
-
- offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
- }
- }
- }
- else if (buffers->tot_tri) {
- int totelem = buffers->tot_tri * 3;
-
- glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
- (void *)(base + offsetof(VertexBufferFormat, co)));
-
- if (!wireframe) {
- glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
- (void *)(base + offsetof(VertexBufferFormat, no)));
- glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
- (void *)(base + offsetof(VertexBufferFormat, color)));
- }
-
- if (buffers->index_buf)
- glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, index_base);
- else
- glDrawArrays(GL_TRIANGLES, 0, totelem);
- }
-
- if (wireframe)
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- GPU_buffer_unbind(buffers->vert_buf, GPU_BINDING_ARRAY);
- if (buffers->index_buf || do_fast)
- GPU_buffer_unbind(do_fast ? buffers->index_buf_fast : buffers->index_buf, GPU_BINDING_INDEX);
-
- glDisableClientState(GL_VERTEX_ARRAY);
- if (!wireframe) {
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- }
-
- if (bound_options_new & ~bound_options_old) {
- GPU_basic_shader_bind(bound_options_old);
- }
- }
+ return (fast && buffers->triangles_fast) ?
+ buffers->triangles_fast : buffers->triangles;
}
-bool GPU_pbvh_buffers_diffuse_changed(
- GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
+bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
{
float diffuse_color[4];
- bool use_matcaps = GPU_material_use_matcaps_get();
if (buffers->show_diffuse_color != show_diffuse_color)
return true;
- if (buffers->use_matcaps != use_matcaps)
- return true;
-
- if ((buffers->show_diffuse_color == false) || use_matcaps)
+ if (buffers->show_diffuse_color == false)
return false;
if (buffers->looptri) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
const MPoly *mp = &buffers->mpoly[lt->poly];
- GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
+ gpu_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
}
else if (buffers->use_bmesh) {
/* due to dynamic nature of dyntopo, only get first material */
@@ -2015,7 +979,7 @@ bool GPU_pbvh_buffers_diffuse_changed(
BLI_gsetIterator_init(&gs_iter, bm_faces);
f = BLI_gsetIterator_getKey(&gs_iter);
- GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ gpu_material_diffuse_get(f->mat_nr + 1, diffuse_color);
}
else {
return false;
@@ -2024,7 +988,7 @@ bool GPU_pbvh_buffers_diffuse_changed(
else {
const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]];
- GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
+ gpu_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
}
return !equals_v3v3(diffuse_color, buffers->diffuse_color);
@@ -2038,16 +1002,20 @@ bool GPU_pbvh_buffers_mask_changed(GPU_PBVH_Buffers *buffers, bool show_mask)
void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
{
if (buffers) {
- if (buffers->vert_buf)
- GPU_buffer_free(buffers->vert_buf);
- if (buffers->index_buf && !buffers->is_index_buf_global)
- GPU_buffer_free(buffers->index_buf);
- if (buffers->index_buf_fast)
- GPU_buffer_free(buffers->index_buf_fast);
+ GWN_BATCH_DISCARD_SAFE(buffers->triangles);
+ GWN_BATCH_DISCARD_SAFE(buffers->triangles_fast);
+ if (!buffers->is_index_buf_global) {
+ GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
+ }
+ GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast);
+ GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+
+#ifdef USE_BASE_ELEM
if (buffers->baseelemarray)
MEM_freeN(buffers->baseelemarray);
if (buffers->baseindex)
MEM_freeN(buffers->baseindex);
+#endif
MEM_freeN(buffers);
}
@@ -2060,7 +1028,7 @@ void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer
if (gridbuff) {
if (gridbuff->mres_buffer) {
BLI_mutex_lock(&buffer_mutex);
- gpu_buffer_free_intern(gridbuff->mres_buffer);
+ GWN_INDEXBUF_DISCARD_SAFE(gridbuff->mres_buffer);
BLI_mutex_unlock(&buffer_mutex);
}
MEM_freeN(gridbuff);
@@ -2069,59 +1037,61 @@ void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer
}
/* debug function, draws the pbvh BB */
-void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf)
+void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos)
{
- const float quads[4][4][3] = {
- {
- {min[0], min[1], min[2]},
- {max[0], min[1], min[2]},
- {max[0], min[1], max[2]},
- {min[0], min[1], max[2]}
- },
+ if (leaf)
+ immUniformColor4f(0.0, 1.0, 0.0, 0.5);
+ else
+ immUniformColor4f(1.0, 0.0, 0.0, 0.5);
- {
- {min[0], min[1], min[2]},
- {min[0], max[1], min[2]},
- {min[0], max[1], max[2]},
- {min[0], min[1], max[2]}
- },
+ /* TODO(merwin): revisit this after we have mutable VertexBuffers
+ * could keep a static batch & index buffer, change the VBO contents per draw
+ */
- {
- {max[0], max[1], min[2]},
- {max[0], min[1], min[2]},
- {max[0], min[1], max[2]},
- {max[0], max[1], max[2]}
- },
+ immBegin(GWN_PRIM_LINES, 24);
- {
- {max[0], max[1], min[2]},
- {min[0], max[1], min[2]},
- {min[0], max[1], max[2]},
- {max[0], max[1], max[2]}
- },
- };
+ /* top */
+ immVertex3f(pos, min[0], min[1], max[2]);
+ immVertex3f(pos, min[0], max[1], max[2]);
- if (leaf)
- glColor4f(0.0, 1.0, 0.0, 0.5);
- else
- glColor4f(1.0, 0.0, 0.0, 0.5);
+ immVertex3f(pos, min[0], max[1], max[2]);
+ immVertex3f(pos, max[0], max[1], max[2]);
- glVertexPointer(3, GL_FLOAT, 0, &quads[0][0][0]);
- glDrawArrays(GL_QUADS, 0, 16);
-}
+ immVertex3f(pos, max[0], max[1], max[2]);
+ immVertex3f(pos, max[0], min[1], max[2]);
-void GPU_pbvh_BB_draw_init(void)
-{
- glPushAttrib(GL_ENABLE_BIT);
- glDisable(GL_CULL_FACE);
- glEnableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glEnable(GL_BLEND);
+ immVertex3f(pos, max[0], min[1], max[2]);
+ immVertex3f(pos, min[0], min[1], max[2]);
+
+ /* bottom */
+ immVertex3f(pos, min[0], min[1], min[2]);
+ immVertex3f(pos, min[0], max[1], min[2]);
+
+ immVertex3f(pos, min[0], max[1], min[2]);
+ immVertex3f(pos, max[0], max[1], min[2]);
+
+ immVertex3f(pos, max[0], max[1], min[2]);
+ immVertex3f(pos, max[0], min[1], min[2]);
+
+ immVertex3f(pos, max[0], min[1], min[2]);
+ immVertex3f(pos, min[0], min[1], min[2]);
+
+ /* sides */
+ immVertex3f(pos, min[0], min[1], min[2]);
+ immVertex3f(pos, min[0], min[1], max[2]);
+
+ immVertex3f(pos, min[0], max[1], min[2]);
+ immVertex3f(pos, min[0], max[1], max[2]);
+
+ immVertex3f(pos, max[0], max[1], min[2]);
+ immVertex3f(pos, max[0], max[1], max[2]);
+
+ immVertex3f(pos, max[0], min[1], min[2]);
+ immVertex3f(pos, max[0], min[1], max[2]);
+
+ immEnd();
}
-void GPU_pbvh_BB_draw_end(void)
+void GPU_pbvh_fix_linking()
{
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glPopAttrib();
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index b5512aa108d..f182f08f4a9 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -36,17 +36,23 @@
#include "DNA_customdata_types.h"
#include "DNA_image_types.h"
#include "DNA_material_types.h"
+#include "DNA_node_types.h"
#include "BLI_blenlib.h"
+#include "BLI_hash_mm2a.h"
+#include "BLI_linklist.h"
#include "BLI_utildefines.h"
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
+#include "PIL_time.h"
+
#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_uniformbuffer.h"
#include "BLI_sys_types.h" /* for intptr_t support */
@@ -62,6 +68,50 @@ extern char datatoc_gpu_shader_geometry_glsl[];
static char *glsl_material_library = NULL;
+/* -------------------- GPUPass Cache ------------------ */
+/**
+ * Internal shader cache: This prevent the shader recompilation / stall when
+ * using undo/redo AND also allows for GPUPass reuse if the Shader code is the
+ * same for 2 different Materials. Unused GPUPasses are free by Garbage collection.
+ **/
+
+static LinkNode *pass_cache = NULL; /* GPUPass */
+
+static uint32_t gpu_pass_hash(const char *vert, const char *geom, const char *frag, const char *defs)
+{
+ BLI_HashMurmur2A hm2a;
+ BLI_hash_mm2a_init(&hm2a, 0);
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)frag, strlen(frag));
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)vert, strlen(vert));
+ if (defs)
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)defs, strlen(defs));
+ if (geom)
+ BLI_hash_mm2a_add(&hm2a, (unsigned char *)geom, strlen(geom));
+
+ return BLI_hash_mm2a_end(&hm2a);
+}
+
+/* Search by hash then by exact string match. */
+static GPUPass *gpu_pass_cache_lookup(
+ const char *vert, const char *geom, const char *frag, const char *defs, uint32_t hash)
+{
+ for (LinkNode *ln = pass_cache; ln; ln = ln->next) {
+ GPUPass *pass = (GPUPass *)ln->link;
+ if (pass->hash == hash) {
+ /* Note: Could be made faster if that becomes a real bottleneck. */
+ if ((defs != NULL) && (strcmp(pass->defines, defs) != 0)) { /* Pass */ }
+ else if ((geom != NULL) && (strcmp(pass->geometrycode, geom) != 0)) { /* Pass */ }
+ else if ((strcmp(pass->fragmentcode, frag) == 0) &&
+ (strcmp(pass->vertexcode, vert) == 0))
+ {
+ return pass;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* -------------------- GPU Codegen ------------------ */
/* type definitions and constants */
@@ -88,7 +138,7 @@ typedef struct GPUFunction {
/* Indices match the GPUType enum */
static const char *GPU_DATATYPE_STR[17] = {
"", "float", "vec2", "vec3", "vec4",
- NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4",
+ NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"
};
/* GLSL code parsing for finding function definitions.
@@ -172,7 +222,7 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
/* test for type */
type = GPU_NONE;
- for (i = 1; i <= 16; i++) {
+ for (i = 1; i < ARRAY_SIZE(GPU_DATATYPE_STR); i++) {
if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
type = i;
break;
@@ -188,6 +238,13 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
if (!type && gpu_str_prefix(code, "sampler2D")) {
type = GPU_TEX2D;
}
+ if (!type && gpu_str_prefix(code, "sampler3D")) {
+ type = GPU_TEX3D;
+ }
+
+ if (!type && gpu_str_prefix(code, "Closure")) {
+ type = GPU_CLOSURE;
+ }
if (type) {
/* add parameter */
@@ -350,6 +407,8 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t
BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name);
else if (from == GPU_FLOAT)
BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name);
+ else /* can happen with closure */
+ BLI_dynstr_append(ds, name);
}
}
@@ -412,6 +471,12 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
return "unfparticleangvel";
else if (builtin == GPU_OBJECT_INFO)
return "unfobjectinfo";
+ else if (builtin == GPU_VOLUME_DENSITY)
+ return "sampdensity";
+ else if (builtin == GPU_VOLUME_FLAME)
+ return "sampflame";
+ else if (builtin == GPU_VOLUME_TEMPERATURE)
+ return "unftemperature";
else
return "";
}
@@ -500,12 +565,16 @@ static void codegen_set_unique_ids(ListBase *nodes)
BLI_ghash_free(definehash, NULL, NULL);
}
-static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
+/**
+ * It will create an UBO for GPUMaterial if there is any GPU_DYNAMIC_UBO.
+ */
+static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, ListBase *nodes)
{
GPUNode *node;
GPUInput *input;
const char *name;
int builtins = 0;
+ ListBase ubo_inputs = {NULL, NULL};
/* print uniforms */
for (node = nodes->first; node; node = node->next) {
@@ -525,7 +594,14 @@ 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 (gpu_str_prefix(name, "samp")) {
+ if ((input->builtin == GPU_VOLUME_DENSITY) ||
+ (input->builtin == GPU_VOLUME_FLAME))
+ {
+ BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", name);
+ }
+ }
+ else if (gpu_str_prefix(name, "unf")) {
BLI_dynstr_appendf(ds, "uniform %s %s;\n",
GPU_DATATYPE_STR[input->type], name);
}
@@ -536,14 +612,23 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
}
}
}
+ else if (input->source == GPU_SOURCE_STRUCT) {
+ /* Add other struct here if needed. */
+ BLI_dynstr_appendf(ds, "Closure strct%d = CLOSURE_DEFAULT;\n", input->id);
+ }
else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
- if (input->dynamicvec) {
+ if (input->dynamictype == GPU_DYNAMIC_UBO) {
+ if (!input->link) {
+ /* We handle the UBOuniforms separately. */
+ BLI_addtail(&ubo_inputs, BLI_genericNodeN(input));
+ }
+ }
+ else if (input->dynamicvec) {
/* only create uniforms for dynamic vectors */
BLI_dynstr_appendf(ds, "uniform %s unf%d;\n",
GPU_DATATYPE_STR[input->type], input->id);
}
else {
- /* for others use const so the compiler can do folding */
BLI_dynstr_appendf(ds, "const %s cons%d = ",
GPU_DATATYPE_STR[input->type], input->id);
codegen_print_datatype(ds, input->type, input->vec);
@@ -569,6 +654,22 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
}
}
+ /* Handle the UBO block separately. */
+ if ((material != NULL) && !BLI_listbase_is_empty(&ubo_inputs)) {
+ GPU_material_create_uniform_buffer(material, &ubo_inputs);
+
+ /* Inputs are sorted */
+ BLI_dynstr_appendf(ds, "\nlayout (std140) uniform %s {\n", GPU_UBO_BLOCK_NAME);
+
+ for (LinkData *link = ubo_inputs.first; link; link = link->next) {
+ input = link->data;
+ BLI_dynstr_appendf(ds, "\t%s unf%d;\n",
+ GPU_DATATYPE_STR[input->type], input->id);
+ }
+ BLI_dynstr_append(ds, "};\n");
+ BLI_freelistN(&ubo_inputs);
+ }
+
BLI_dynstr_append(ds, "\n");
return builtins;
@@ -594,8 +695,13 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
/* declare temporary variables for node output storage */
for (output = node->outputs.first; output; output = output->next) {
- BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
- GPU_DATATYPE_STR[output->type], output->id);
+ if (output->type == GPU_CLOSURE) {
+ BLI_dynstr_appendf(ds, "\tClosure tmp%d;\n", output->id);
+ }
+ else {
+ BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
+ GPU_DATATYPE_STR[output->type], output->id);
+ }
}
}
@@ -622,11 +728,26 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
"tmp", input->link->output->id);
}
else if (input->source == GPU_SOURCE_BUILTIN) {
- if (input->builtin == GPU_VIEW_NORMAL)
+ if (input->builtin == GPU_INVERSE_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "viewinv");
+ else if (input->builtin == GPU_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "viewmat");
+ else if (input->builtin == GPU_CAMERA_TEXCO_FACTORS)
+ BLI_dynstr_append(ds, "camtexfac");
+ else if (input->builtin == GPU_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "objmat");
+ else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "objinv");
+ else if (input->builtin == GPU_VIEW_POSITION)
+ BLI_dynstr_append(ds, "viewposition");
+ else if (input->builtin == GPU_VIEW_NORMAL)
BLI_dynstr_append(ds, "facingnormal");
else
BLI_dynstr_append(ds, GPU_builtin_name(input->builtin));
}
+ else if (input->source == GPU_SOURCE_STRUCT) {
+ BLI_dynstr_appendf(ds, "strct%d", input->id);
+ }
else if (input->source == GPU_SOURCE_VEC_UNIFORM) {
if (input->dynamicvec)
BLI_dynstr_appendf(ds, "unf%d", input->id);
@@ -655,12 +776,11 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ");\n");
}
- BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
- codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
+ BLI_dynstr_appendf(ds, "\n\treturn tmp%d", finaloutput->id);
BLI_dynstr_append(ds, ";\n");
}
-static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
+static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUOutput *output)
{
DynStr *ds = BLI_dynstr_new();
char *code;
@@ -677,17 +797,29 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
#endif
codegen_set_unique_ids(nodes);
- builtins = codegen_print_uniforms_functions(ds, nodes);
+ builtins = codegen_process_uniforms_functions(material, ds, nodes);
#if 0
if (G.debug & G_DEBUG)
BLI_dynstr_appendf(ds, "/* %s */\n", name);
#endif
- BLI_dynstr_append(ds, "void main()\n{\n");
-
+ BLI_dynstr_append(ds, "Closure nodetree_exec(void)\n{\n");
+
+ if (builtins & GPU_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 viewmat = ViewMatrix;\n");
+ if (builtins & GPU_CAMERA_TEXCO_FACTORS)
+ BLI_dynstr_append(ds, "\tvec4 camtexfac = CameraTexCoFactors;\n");
+ if (builtins & GPU_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 objmat = ModelMatrix;\n");
+ if (builtins & GPU_INVERSE_OBJECT_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 objinv = ModelMatrixInverse;\n");
+ if (builtins & GPU_INVERSE_VIEW_MATRIX)
+ BLI_dynstr_append(ds, "\tmat4 viewinv = ViewMatrixInverse;\n");
if (builtins & GPU_VIEW_NORMAL)
- BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? varnormal: -varnormal;\n");
+ BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? viewNormal: -viewNormal;\n");
+ if (builtins & GPU_VIEW_POSITION)
+ BLI_dynstr_append(ds, "\tvec3 viewposition = viewPosition;\n");
/* Calculate tangent space. */
#ifdef WITH_OPENSUBDIV
@@ -722,6 +854,17 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
BLI_dynstr_append(ds, "}\n");
+ /* XXX This cannot go into gpu_shader_material.glsl because main() would be parsed and generate error */
+ /* Old glsl mode compat. */
+ BLI_dynstr_append(ds, "#ifndef NODETREE_EXEC\n");
+ BLI_dynstr_append(ds, "out vec4 fragColor;\n");
+ BLI_dynstr_append(ds, "void main()\n");
+ BLI_dynstr_append(ds, "{\n");
+ BLI_dynstr_append(ds, "\tClosure cl = nodetree_exec();\n");
+ BLI_dynstr_append(ds, "\tfragColor = vec4(cl.radiance, cl.opacity);\n");
+ BLI_dynstr_append(ds, "}\n");
+ BLI_dynstr_append(ds, "#endif\n\n");
+
/* create shader */
code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@@ -733,103 +876,152 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
return code;
}
-static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
+static const char *attrib_prefix_get(CustomDataType type)
+{
+ switch (type) {
+ case CD_ORCO: return "orco";
+ case CD_MTFACE: return "u";
+ case CD_TANGENT: return "t";
+ case CD_MCOL: return "c";
+ case CD_AUTO_FROM_NAME: return "a";
+ default: BLI_assert(false && "Gwn_VertAttr Prefix type not found : This should not happen!"); return "";
+ }
+}
+
+static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool use_geom)
{
DynStr *ds = BLI_dynstr_new();
GPUNode *node;
GPUInput *input;
char *code;
- char *vertcode = NULL;
-
+
+ /* Hairs uv and col attribs are passed by bufferTextures. */
+ BLI_dynstr_append(ds,
+ "#ifdef HAIR_SHADER\n"
+ "#define DEFINE_ATTRIB(type, attr) uniform samplerBuffer attr\n"
+ "#else\n"
+ "#define DEFINE_ATTRIB(type, attr) in type attr\n"
+ "#endif\n"
+ );
+
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) {
-#ifdef WITH_OPENSUBDIV
- bool skip_opensubdiv = ELEM(input->attribtype, CD_MTFACE, CD_TANGENT);
- if (skip_opensubdiv) {
- BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
+ /* XXX FIXME : see notes in mesh_render_data_create() */
+ /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
+ if (input->attribtype == CD_ORCO) {
+ /* orco is computed from local positions, see bellow */
+ BLI_dynstr_appendf(ds, "uniform vec3 OrcoTexCoFactors[2];\n");
}
-#endif
- BLI_dynstr_appendf(ds, "%s %s att%d;\n",
- GLEW_VERSION_3_0 ? "in" : "attribute",
- GPU_DATATYPE_STR[input->type], input->attribid);
- BLI_dynstr_appendf(ds, "uniform int att%d_info;\n", input->attribid);
- BLI_dynstr_appendf(ds, "%s %s var%d;\n",
- GLEW_VERSION_3_0 ? "out" : "varying",
- GPU_DATATYPE_STR[input->type], input->attribid);
-#ifdef WITH_OPENSUBDIV
- if (skip_opensubdiv) {
- BLI_dynstr_appendf(ds, "#endif\n");
+ else if (input->attribname[0] == '\0') {
+ BLI_dynstr_appendf(ds, "DEFINE_ATTRIB(%s, %s);\n", GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype));
+ BLI_dynstr_appendf(ds, "#define att%d %s\n", input->attribid, attrib_prefix_get(input->attribtype));
}
-#endif
+ else {
+ unsigned int hash = BLI_ghashutil_strhash_p(input->attribname);
+ BLI_dynstr_appendf(ds, "DEFINE_ATTRIB(%s, %s%u);\n",
+ GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype), hash);
+ BLI_dynstr_appendf(ds, "#define att%d %s%u\n",
+ input->attribid, attrib_prefix_get(input->attribtype), hash);
+ /* Auto attrib can be vertex color byte buffer.
+ * We need to know and convert them to linear space in VS. */
+ if (!use_geom && input->attribtype == CD_AUTO_FROM_NAME) {
+ BLI_dynstr_appendf(ds, "uniform bool ba%u;\n", hash);
+ BLI_dynstr_appendf(ds, "#define att%d_is_srgb ba%u\n", input->attribid, hash);
+ }
+ }
+ BLI_dynstr_appendf(ds, "out %s var%d%s;\n",
+ GPU_DATATYPE_STR[input->type], input->attribid, use_geom ? "g" : "");
}
}
}
BLI_dynstr_append(ds, "\n");
- switch (type) {
- case GPU_MATERIAL_TYPE_MESH:
- vertcode = datatoc_gpu_shader_vertex_glsl;
- break;
- case GPU_MATERIAL_TYPE_WORLD:
- vertcode = datatoc_gpu_shader_vertex_world_glsl;
- break;
- default:
- fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
- break;
+ BLI_dynstr_append(ds,
+ "#define ATTRIB\n"
+ "uniform mat3 NormalMatrix;\n"
+ "uniform mat4 ModelMatrixInverse;\n"
+ "vec3 srgb_to_linear_attrib(vec3 c) {\n"
+ "\tc = max(c, vec3(0.0));\n"
+ "\tvec3 c1 = c * (1.0 / 12.92);\n"
+ "\tvec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));\n"
+ "\treturn mix(c1, c2, step(vec3(0.04045), c));\n"
+ "}\n\n"
+ );
+
+ /* Prototype because defined later. */
+ BLI_dynstr_append(ds,
+ "vec2 hair_get_customdata_vec2(const samplerBuffer);\n"
+ "vec3 hair_get_customdata_vec3(const samplerBuffer);\n"
+ "vec4 hair_get_customdata_vec4(const samplerBuffer);\n"
+ "vec3 hair_get_strand_pos(void);\n"
+ "\n"
+ );
+
+ BLI_dynstr_append(ds, "void pass_attrib(in vec3 position) {\n");
+
+ BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
+
+ 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) {
+ if (input->attribtype == CD_TANGENT) {
+ /* Not supported by hairs */
+ BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n",
+ input->attribid, use_geom ? "g" : "");
+ }
+ else if (input->attribtype == CD_ORCO) {
+ BLI_dynstr_appendf(ds, "\tvar%d%s = OrcoTexCoFactors[0] + (ModelMatrixInverse * vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1];\n",
+ input->attribid, use_geom ? "g" : "");
+ }
+ else {
+ BLI_dynstr_appendf(ds, "\tvar%d%s = hair_get_customdata_%s(att%d);\n",
+ input->attribid, use_geom ? "g" : "", GPU_DATATYPE_STR[input->type], input->attribid);
+ }
+ }
+ }
}
- BLI_dynstr_append(ds, vertcode);
-
- for (node = nodes->first; node; node = node->next)
- for (input = node->inputs.first; input; input = input->next)
+ BLI_dynstr_append(ds, "#else /* MESH_SHADER */\n");
+
+ 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) {
if (input->attribtype == CD_TANGENT) { /* silly exception */
-#ifdef WITH_OPENSUBDIV
- BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
-#endif
BLI_dynstr_appendf(
- ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n",
- input->attribid, input->attribid);
+ ds, "\tvar%d%s.xyz = normalize(NormalMatrix * att%d.xyz);\n",
+ input->attribid, use_geom ? "g" : "", input->attribid);
BLI_dynstr_appendf(
- ds, "\tvar%d.w = att%d.w;\n",
- input->attribid, input->attribid);
-#ifdef WITH_OPENSUBDIV
- BLI_dynstr_appendf(ds, "#endif\n");
-#endif
+ ds, "\tvar%d%s.w = att%d.w;\n",
+ input->attribid, use_geom ? "g" : "", input->attribid);
}
- else {
-#ifdef WITH_OPENSUBDIV
- bool is_mtface = input->attribtype == CD_MTFACE;
- if (is_mtface) {
- BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
- }
-#endif
- BLI_dynstr_appendf(ds, "\tset_var_from_attr(att%d, att%d_info, var%d);\n",
- input->attribid, input->attribid, input->attribid);
-#ifdef WITH_OPENSUBDIV
- if (is_mtface) {
- BLI_dynstr_appendf(ds, "#endif\n");
- }
-#endif
+ else if (input->attribtype == CD_ORCO) {
+ BLI_dynstr_appendf(ds, "\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n",
+ input->attribid, use_geom ? "g" : "");
}
- }
- /* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */
- else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
- if (input->oglbuiltin == GPU_MATCAP_NORMAL) {
- /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
- * between shader stages and we want the full range of the normal */
- BLI_dynstr_appendf(ds, "\tvec3 matcapcol = vec3(0.5) * varnormal + vec3(0.5);\n");
- BLI_dynstr_appendf(ds, "\tgl_FrontSecondaryColor = vec4(matcapcol, 1.0);\n");
+ else if (input->attribtype == CD_MCOL) {
+ BLI_dynstr_appendf(ds, "\tvar%d%s = srgb_to_linear_attrib(att%d);\n",
+ input->attribid, use_geom ? "g" : "", input->attribid);
}
- else if (input->oglbuiltin == GPU_COLOR) {
- BLI_dynstr_appendf(ds, "\tgl_FrontColor = gl_Color;\n");
+ else if (input->attribtype == CD_AUTO_FROM_NAME) {
+ BLI_dynstr_appendf(ds, "\tvar%d%s = (att%d_is_srgb) ? srgb_to_linear_attrib(att%d) : att%d;\n",
+ input->attribid, use_geom ? "g" : "",
+ input->attribid, input->attribid, input->attribid);
+ }
+ else {
+ BLI_dynstr_appendf(ds, "\tvar%d%s = att%d;\n",
+ input->attribid, use_geom ? "g" : "", input->attribid);
}
}
+ }
+ }
+ BLI_dynstr_append(ds, "#endif /* HAIR_SHADER */\n");
BLI_dynstr_append(ds, "}\n");
+ BLI_dynstr_append(ds, vert_code);
+
code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@@ -841,65 +1033,49 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
return code;
}
-static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
+static char *code_generate_geometry(ListBase *nodes, const char *geom_code)
{
-#ifdef WITH_OPENSUBDIV
- if (use_opensubdiv) {
- DynStr *ds = BLI_dynstr_new();
- GPUNode *node;
- GPUInput *input;
- char *code;
+ DynStr *ds = BLI_dynstr_new();
+ GPUNode *node;
+ GPUInput *input;
+ char *code;
- /* Generate varying declarations. */
- 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) {
- if (input->attribtype == CD_MTFACE) {
- /* NOTE: For now we are using varying on purpose,
- * otherwise we are not able to write to the varying.
- */
- BLI_dynstr_appendf(ds, "%s %s var%d%s;\n",
- "varying",
- GPU_DATATYPE_STR[input->type],
- input->attribid,
- "");
- BLI_dynstr_appendf(ds, "uniform int fvar%d_offset;\n",
- input->attribid);
- }
- }
- }
- }
+ /* Create prototype because attributes cannot be declared before layout. */
+ BLI_dynstr_appendf(ds, "void pass_attrib(in int vert);\n");
+ BLI_dynstr_append(ds, "#define ATTRIB\n");
- BLI_dynstr_append(ds, datatoc_gpu_shader_geometry_glsl);
+ BLI_dynstr_append(ds, geom_code);
- /* Generate varying assignments. */
- 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) {
- if (input->attribtype == CD_MTFACE) {
- BLI_dynstr_appendf(
- ds,
- "\tINTERP_FACE_VARYING_ATT_2(var%d, "
- "int(texelFetch(FVarDataOffsetBuffer, fvar%d_offset).r), st);\n",
- input->attribid,
- input->attribid);
- }
- }
+ /* Generate varying declarations. */
+ 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) {
+ BLI_dynstr_appendf(ds, "in %s var%dg[];\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
+ BLI_dynstr_appendf(ds, "out %s var%d;\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
}
}
+ }
- BLI_dynstr_append(ds, "}\n");
- code = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
+ /* Generate varying assignments. */
+ BLI_dynstr_appendf(ds, "void pass_attrib(in int vert) {\n");
+ 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) {
+ /* TODO let shader choose what to do depending on what the attrib is. */
+ BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", input->attribid, input->attribid);
+ }
+ }
+ }
+ BLI_dynstr_append(ds, "}\n");
- //if (G.debug & G_DEBUG) printf("%s\n", code);
+ code = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
- return code;
- }
-#else
- UNUSED_VARS(nodes, use_opensubdiv);
-#endif
- return NULL;
+ return code;
}
void GPU_code_generate_glsl_lib(void)
@@ -928,15 +1104,13 @@ GPUShader *GPU_pass_shader(GPUPass *pass)
return pass->shader;
}
-static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
+static void gpu_nodes_extract_dynamic_inputs(GPUShader *shader, ListBase *inputs, ListBase *nodes)
{
- GPUShader *shader = pass->shader;
GPUNode *node;
GPUInput *next, *input;
- ListBase *inputs = &pass->inputs;
int extract, z;
- memset(inputs, 0, sizeof(*inputs));
+ BLI_listbase_clear(inputs);
if (!shader)
return;
@@ -951,26 +1125,9 @@ static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
/* attributes don't need to be bound, they already have
* an id that the drawing functions will use */
if (input->source == GPU_SOURCE_ATTRIB) {
-#ifdef WITH_OPENSUBDIV
- /* We do need mtface attributes for later, so we can
- * update face-varuing variables offset in the texture
- * buffer for proper sampling from the shader.
- *
- * We don't do anything about attribute itself, we
- * only use it to learn which uniform name is to be
- * updated.
- *
- * TODO(sergey): We can add ad extra uniform input
- * for the offset, which will be purely internal and
- * which would avoid having such an exceptions.
- */
- if (input->attribtype != CD_MTFACE) {
- continue;
- }
-#else
continue;
-#endif
}
+
if (input->source == GPU_SOURCE_BUILTIN ||
input->source == GPU_SOURCE_OPENGL_BUILTIN)
{
@@ -995,14 +1152,6 @@ static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
if (extract)
input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
-#ifdef WITH_OPENSUBDIV
- if (input->source == GPU_SOURCE_ATTRIB &&
- input->attribtype == CD_MTFACE)
- {
- extract = 1;
- }
-#endif
-
/* extract nodes */
if (extract) {
BLI_remlink(&node->inputs, input);
@@ -1014,11 +1163,10 @@ static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
GPU_shader_unbind();
}
-void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
+void GPU_pass_bind(GPUPass *pass, ListBase *inputs, double time, int mipmap)
{
GPUInput *input;
GPUShader *shader = pass->shader;
- ListBase *inputs = &pass->inputs;
if (!shader)
return;
@@ -1043,11 +1191,10 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
}
}
-void GPU_pass_update_uniforms(GPUPass *pass)
+void GPU_pass_update_uniforms(GPUPass *pass, ListBase *inputs)
{
GPUInput *input;
GPUShader *shader = pass->shader;
- ListBase *inputs = &pass->inputs;
if (!shader)
return;
@@ -1068,11 +1215,10 @@ void GPU_pass_update_uniforms(GPUPass *pass)
}
}
-void GPU_pass_unbind(GPUPass *pass)
+void GPU_pass_unbind(GPUPass *pass, ListBase *inputs)
{
GPUInput *input;
GPUShader *shader = pass->shader;
- ListBase *inputs = &pass->inputs;
if (!shader)
return;
@@ -1135,7 +1281,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
name = outnode->name;
input = outnode->inputs.first;
- if ((STREQ(name, "set_value") || STREQ(name, "set_rgb")) &&
+ if ((STREQ(name, "set_value") || STREQ(name, "set_rgb") || STREQ(name, "set_rgba")) &&
(input->type == type))
{
input = MEM_dupallocN(outnode->inputs.first);
@@ -1194,7 +1340,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
#if 0
input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
#endif
- input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
+ input->tex = GPU_texture_create_2D(link->texturesize, 1, GPU_RGBA8, link->ptr1, NULL);
input->textarget = GL_TEXTURE_2D;
MEM_freeN(link->ptr1);
@@ -1235,6 +1381,12 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname));
MEM_freeN(link);
}
+ else if (type == GPU_CLOSURE) {
+ input->type = type;
+ input->source = GPU_SOURCE_STRUCT;
+
+ MEM_freeN(link);
+ }
else {
/* uniform vector */
input->type = type;
@@ -1246,21 +1398,100 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
input->dynamictype = link->dynamictype;
input->dynamicdata = link->ptr2;
}
+
MEM_freeN(link);
}
BLI_addtail(&node->inputs, input);
}
-static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
+
+static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type)
+{
+ switch (type) {
+ case SOCK_FLOAT:
+ return "set_value";
+ case SOCK_VECTOR:
+ return "set_rgb";
+ case SOCK_RGBA:
+ return "set_rgba";
+ default:
+ BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype");
+ return NULL;
+ }
+}
+
+/**
+ * Link stack uniform buffer.
+ * This is called for the input/output sockets that are note connected.
+ */
+static GPUNodeLink *gpu_uniformbuffer_link(
+ GPUMaterial *mat, bNode *node, GPUNodeStack *stack, const int index, const eNodeSocketInOut in_out)
{
- GPUNodeLink *link;
+ bNodeSocket *socket;
+
+ /* Some nodes can have been create on the fly and does
+ * not have an original to point to. (i.e. the bump from
+ * ntree_shader_relink_displacement). In this case just
+ * revert to static constant folding. */
+ if (node->original == NULL) {
+ return NULL;
+ }
+
+ if (in_out == SOCK_IN) {
+ socket = BLI_findlink(&node->original->inputs, index);
+ }
+ else {
+ socket = BLI_findlink(&node->original->outputs, index);
+ }
+
+ BLI_assert(socket != NULL);
+ BLI_assert(socket->in_out == in_out);
+
+ if ((socket->flag & SOCK_HIDE_VALUE) == 0) {
+ GPUNodeLink *link;
+ switch (socket->type) {
+ case SOCK_FLOAT:
+ {
+ bNodeSocketValueFloat *socket_data = socket->default_value;
+ link = GPU_uniform_buffer(&socket_data->value, GPU_FLOAT);
+ break;
+ }
+ case SOCK_VECTOR:
+ {
+ bNodeSocketValueRGBA *socket_data = socket->default_value;
+ link = GPU_uniform_buffer(socket_data->value, GPU_VEC3);
+ break;
+ }
+ case SOCK_RGBA:
+ {
+ bNodeSocketValueRGBA *socket_data = socket->default_value;
+ link = GPU_uniform_buffer(socket_data->value, GPU_VEC4);
+ break;
+ }
+ default:
+ return NULL;
+ break;
+ }
+
+ if (in_out == SOCK_IN) {
+ GPU_link(mat, gpu_uniform_set_function_from_type(socket->type), link, &stack->link);
+ }
+ return link;
+ }
+ return NULL;
+}
+static void gpu_node_input_socket(GPUMaterial *material, bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index)
+{
if (sock->link) {
gpu_node_input_link(node, sock->link, sock->type);
}
+ else if ((material != NULL) && (gpu_uniformbuffer_link(material, bnode, sock, index, SOCK_IN) != NULL)) {
+ gpu_node_input_link(node, sock->link, sock->type);
+ }
else {
- link = GPU_node_link_create();
+ GPUNodeLink *link = GPU_node_link_create();
link->ptr1 = sock->vec;
gpu_node_input_link(node, link, sock->type);
}
@@ -1286,7 +1517,7 @@ static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **lin
BLI_addtail(&node->outputs, output);
}
-static void gpu_inputs_free(ListBase *inputs)
+void GPU_inputs_free(ListBase *inputs)
{
GPUInput *input;
@@ -1304,7 +1535,7 @@ static void gpu_node_free(GPUNode *node)
{
GPUOutput *output;
- gpu_inputs_free(&node->inputs);
+ GPU_inputs_free(&node->inputs);
for (output = node->outputs.first; output; output = output->next)
if (output->link) {
@@ -1327,7 +1558,7 @@ static void gpu_nodes_free(ListBase *nodes)
/* vertex attributes */
-static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
+void GPU_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs)
{
GPUNode *node;
GPUInput *input;
@@ -1368,26 +1599,20 @@ static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *a
}
}
-static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
-{
- GPUNode *node;
- GPUInput *input;
-
- *builtin = 0;
-
- for (node = nodes->first; node; node = node->next)
- for (input = node->inputs.first; input; input = input->next)
- if (input->source == GPU_SOURCE_BUILTIN)
- *builtin |= input->builtin;
-}
-
/* varargs linking */
GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
{
GPUNodeLink *link = GPU_node_link_create();
- link->attribtype = type;
+ /* Fall back to the UV layer, which matches old behavior. */
+ if (type == CD_AUTO_FROM_NAME && name[0] == '\0') {
+ link->attribtype = CD_MTFACE;
+ }
+ else {
+ link->attribtype = type;
+ }
+
link->attribname = name;
return link;
@@ -1416,6 +1641,21 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *d
return link;
}
+/**
+ * Add uniform to UBO struct of GPUMaterial.
+ */
+GPUNodeLink *GPU_uniform_buffer(float *num, GPUType gputype)
+{
+ GPUNodeLink *link = GPU_node_link_create();
+ link->ptr1 = num;
+ link->ptr2 = NULL;
+ link->dynamic = true;
+ link->dynamictype = GPU_DYNAMIC_UBO;
+ link->type = gputype;
+
+ return link;
+}
+
GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
{
GPUNodeLink *link = GPU_node_link_create();
@@ -1526,7 +1766,7 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
return true;
}
-bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
+bool GPU_stack_link(GPUMaterial *material, bNode *bnode, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...)
{
GPUNode *node;
GPUFunction *function;
@@ -1545,16 +1785,20 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
totout = 0;
if (in) {
- for (i = 0; in[i].type != GPU_NONE; i++) {
- gpu_node_input_socket(node, &in[i]);
- totin++;
+ for (i = 0; !in[i].end; i++) {
+ if (in[i].type != GPU_NONE) {
+ gpu_node_input_socket(material, bnode, node, &in[i], i);
+ totin++;
+ }
}
}
-
+
if (out) {
- for (i = 0; out[i].type != GPU_NONE; i++) {
- gpu_node_output(node, out[i].type, &out[i].link);
- totout++;
+ for (i = 0; !out[i].end; i++) {
+ if (out[i].type != GPU_NONE) {
+ gpu_node_output(node, out[i].type, &out[i].link);
+ totout++;
+ }
}
}
@@ -1572,7 +1816,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
if (totin == 0) {
link = va_arg(params, GPUNodeLink *);
if (link->socket)
- gpu_node_input_socket(node, link->socket);
+ gpu_node_input_socket(NULL, NULL, node, link->socket, -1);
else
gpu_node_input_link(node, link, function->paramtype[i]);
}
@@ -1582,8 +1826,8 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
}
va_end(params);
- gpu_material_add_node(mat, node);
-
+ gpu_material_add_node(material, node);
+
return true;
}
@@ -1608,6 +1852,11 @@ int GPU_link_changed(GPUNodeLink *link)
return 0;
}
+GPUNodeLink *GPU_uniformbuffer_link_out(GPUMaterial *mat, bNode *node, GPUNodeStack *stack, const int index)
+{
+ return gpu_uniformbuffer_link(mat, node, stack, index, SOCK_OUT);
+}
+
/* Pass create/free */
static void gpu_nodes_tag(GPUNodeLink *link)
@@ -1628,7 +1877,7 @@ static void gpu_nodes_tag(GPUNodeLink *link)
gpu_nodes_tag(input->link);
}
-static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
+void GPU_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
{
GPUNode *node, *next;
@@ -1647,91 +1896,97 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
}
}
-GPUPass *GPU_generate_pass(
- ListBase *nodes, GPUNodeLink *outlink,
- GPUVertexAttribs *attribs, int *builtins,
- const GPUMatType type, const char *UNUSED(name),
- const bool use_opensubdiv,
- const bool use_new_shading)
+GPUPass *GPU_generate_pass_new(
+ GPUMaterial *material,
+ GPUNodeLink *frag_outlink, struct GPUVertexAttribs *attribs,
+ ListBase *nodes, ListBase *inputs,
+ const char *vert_code, const char *geom_code,
+ const char *frag_lib, const char *defines)
{
+ char *vertexcode, *geometrycode, *fragmentcode;
GPUShader *shader;
GPUPass *pass;
- char *vertexcode, *geometrycode, *fragmentcode;
-#if 0
- if (!FUNCTION_LIB) {
- GPU_nodes_free(nodes);
- return NULL;
+ /* prune unused nodes */
+ GPU_nodes_prune(nodes, frag_outlink);
+
+ GPU_nodes_get_vertex_attributes(nodes, attribs);
+
+ /* generate code */
+ char *fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output);
+ char *tmp = BLI_strdupcat(frag_lib, glsl_material_library);
+
+ vertexcode = code_generate_vertex(nodes, vert_code, (geom_code != NULL));
+ geometrycode = (geom_code) ? code_generate_geometry(nodes, geom_code) : NULL;
+ fragmentcode = BLI_strdupcat(tmp, fragmentgen);
+
+ MEM_freeN(fragmentgen);
+ MEM_freeN(tmp);
+
+ /* Cache lookup: Reuse shaders already compiled */
+ uint32_t hash = gpu_pass_hash(vertexcode, geometrycode, fragmentcode, defines);
+ pass = gpu_pass_cache_lookup(vertexcode, geometrycode, fragmentcode, defines, hash);
+ if (pass) {
+ /* Cache hit. Reuse the same GPUPass and GPUShader. */
+ shader = pass->shader;
+ pass->refcount += 1;
+
+ MEM_SAFE_FREE(vertexcode);
+ MEM_SAFE_FREE(fragmentcode);
+ MEM_SAFE_FREE(geometrycode);
+ }
+ else {
+ /* Cache miss. (Re)compile the shader. */
+ shader = GPU_shader_create(vertexcode,
+ fragmentcode,
+ geometrycode,
+ NULL,
+ defines);
+
+ /* We still create a pass even if shader compilation
+ * fails to avoid trying to compile again and again. */
+ pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
+ pass->shader = shader;
+ pass->refcount = 1;
+ pass->hash = hash;
+ pass->vertexcode = vertexcode;
+ pass->fragmentcode = fragmentcode;
+ pass->geometrycode = geometrycode;
+ pass->libcode = glsl_material_library;
+ pass->defines = (defines) ? BLI_strdup(defines) : NULL;
+
+ BLI_linklist_prepend(&pass_cache, pass);
}
-#endif
- /* prune unused nodes */
- gpu_nodes_prune(nodes, outlink);
-
- gpu_nodes_get_vertex_attributes(nodes, attribs);
- gpu_nodes_get_builtin_flag(nodes, builtins);
-
- /* generate code and compile with opengl */
- fragmentcode = code_generate_fragment(nodes, outlink->output);
- vertexcode = code_generate_vertex(nodes, type);
- geometrycode = code_generate_geometry(nodes, use_opensubdiv);
-
- int flags = GPU_SHADER_FLAGS_NONE;
- if (use_opensubdiv) {
- flags |= GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV;
- }
- if (use_new_shading) {
- flags |= GPU_SHADER_FLAGS_NEW_SHADING;
- }
- shader = GPU_shader_create_ex(vertexcode,
- fragmentcode,
- geometrycode,
- glsl_material_library,
- NULL,
- 0,
- 0,
- 0,
- flags);
-
- /* failed? */
+ /* did compilation failed ? */
if (!shader) {
- if (fragmentcode)
- MEM_freeN(fragmentcode);
- if (vertexcode)
- MEM_freeN(vertexcode);
- memset(attribs, 0, sizeof(*attribs));
- memset(builtins, 0, sizeof(*builtins));
gpu_nodes_free(nodes);
+ /* Pass will not be used. Don't increment refcount. */
+ pass->refcount--;
return NULL;
}
-
- /* create pass */
- pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
-
- pass->output = outlink->output;
- pass->shader = shader;
- pass->fragmentcode = fragmentcode;
- pass->geometrycode = geometrycode;
- pass->vertexcode = vertexcode;
- pass->libcode = glsl_material_library;
-
- /* extract dynamic inputs and throw away nodes */
- gpu_nodes_extract_dynamic_inputs(pass, nodes);
- gpu_nodes_free(nodes);
+ else {
+ gpu_nodes_extract_dynamic_inputs(shader, inputs, nodes);
+ return pass;
+ }
+}
- return pass;
+void GPU_pass_release(GPUPass *pass)
+{
+ BLI_assert(pass->refcount > 0);
+ pass->refcount--;
}
-void GPU_pass_free(GPUPass *pass)
+static void gpu_pass_free(GPUPass *pass)
{
- GPU_shader_free(pass->shader);
- gpu_inputs_free(&pass->inputs);
- if (pass->fragmentcode)
- MEM_freeN(pass->fragmentcode);
- if (pass->geometrycode)
- MEM_freeN(pass->geometrycode);
- if (pass->vertexcode)
- MEM_freeN(pass->vertexcode);
+ BLI_assert(pass->refcount == 0);
+ if (pass->shader) {
+ GPU_shader_free(pass->shader);
+ }
+ MEM_SAFE_FREE(pass->fragmentcode);
+ MEM_SAFE_FREE(pass->geometrycode);
+ MEM_SAFE_FREE(pass->vertexcode);
+ MEM_SAFE_FREE(pass->defines);
MEM_freeN(pass);
}
@@ -1740,3 +1995,34 @@ void GPU_pass_free_nodes(ListBase *nodes)
gpu_nodes_free(nodes);
}
+void GPU_pass_cache_garbage_collect(void)
+{
+ static int lasttime = 0;
+ const int shadercollectrate = 60; /* hardcoded for now. */
+ int ctime = (int)PIL_check_seconds_timer();
+
+ if (ctime < shadercollectrate + lasttime)
+ return;
+
+ lasttime = ctime;
+
+ LinkNode *next, **prev_ln = &pass_cache;
+ for (LinkNode *ln = pass_cache; ln; ln = next) {
+ GPUPass *pass = (GPUPass *)ln->link;
+ next = ln->next;
+ if (pass->refcount == 0) {
+ gpu_pass_free(pass);
+ /* Remove from list */
+ MEM_freeN(ln);
+ *prev_ln = next;
+ }
+ else {
+ prev_ln = &ln->next;
+ }
+ }
+}
+
+void GPU_pass_cache_free(void)
+{
+ BLI_linklist_free(pass_cache, (LinkNodeFreeFP)gpu_pass_free);
+}
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 7af17f9122d..328da36c3de 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -57,7 +57,8 @@ typedef enum GPUDataSource {
GPU_SOURCE_OPENGL_BUILTIN,
GPU_SOURCE_TEX_PIXEL,
GPU_SOURCE_TEX,
- GPU_SOURCE_ATTRIB
+ GPU_SOURCE_ATTRIB,
+ GPU_SOURCE_STRUCT
} GPUDataSource;
typedef enum {
@@ -156,35 +157,45 @@ typedef struct GPUInput {
} GPUInput;
struct GPUPass {
- struct GPUPass *next, *prev;
-
- ListBase inputs;
- struct GPUOutput *output;
struct GPUShader *shader;
char *fragmentcode;
char *geometrycode;
char *vertexcode;
+ char *defines;
const char *libcode;
+ unsigned int refcount; /* Orphaned GPUPasses gets freed by the garbage collector. */
+ uint32_t hash; /* Identity hash generated from all GLSL code. */
};
typedef struct GPUPass GPUPass;
-GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
- struct GPUVertexAttribs *attribs, int *builtin,
- const GPUMatType type, const char *name,
- const bool use_opensubdiv,
- const bool use_new_shading);
+GPUPass *GPU_generate_pass_new(
+ GPUMaterial *material,
+ GPUNodeLink *frag_outlink, struct GPUVertexAttribs *attribs,
+ ListBase *nodes, ListBase *inputs,
+ const char *vert_code, const char *geom_code,
+ const char *frag_lib, const char *defines);
+GPUPass *GPU_generate_pass(
+ ListBase *nodes, ListBase *inputs, struct GPUNodeLink *outlink,
+ struct GPUVertexAttribs *attribs, int *builtin,
+ const GPUMatType type, const char *name,
+ const bool use_opensubdiv);
struct GPUShader *GPU_pass_shader(GPUPass *pass);
-void GPU_pass_bind(GPUPass *pass, double time, int mipmap);
-void GPU_pass_update_uniforms(GPUPass *pass);
-void GPU_pass_unbind(GPUPass *pass);
+void GPU_nodes_get_vertex_attributes(ListBase *nodes, struct GPUVertexAttribs *attribs);
+void GPU_nodes_prune(ListBase *nodes, struct GPUNodeLink *outlink);
-void GPU_pass_free(GPUPass *pass);
+void GPU_pass_bind(GPUPass *pass, ListBase *inputs, double time, int mipmap);
+void GPU_pass_update_uniforms(GPUPass *pass, ListBase *inputs);
+void GPU_pass_unbind(GPUPass *pass, ListBase *inputs);
+
+void GPU_pass_release(GPUPass *pass);
void GPU_pass_free_nodes(ListBase *nodes);
+void GPU_inputs_free(ListBase *inputs);
+
void gpu_codegen_init(void);
void gpu_codegen_exit(void);
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
deleted file mode 100644
index 2f2a16f9e1d..00000000000
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ /dev/null
@@ -1,1461 +0,0 @@
-/*
- * ***** 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): Antony Riakiotakis.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/gpu/intern/gpu_compositing.c
- * \ingroup gpu
- *
- * System that manages framebuffer compositing.
- */
-
-#include "BLI_sys_types.h"
-#include "BLI_rect.h"
-#include "BLI_math.h"
-
-#include "BLI_rand.h"
-
-#include "DNA_vec_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_gpu_types.h"
-
-#include "GPU_compositing.h"
-#include "GPU_extensions.h"
-#include "GPU_framebuffer.h"
-#include "GPU_glew.h"
-#include "GPU_shader.h"
-#include "GPU_texture.h"
-
-#include "MEM_guardedalloc.h"
-
-static const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
-static const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
-
-
-/* shader interfaces (legacy GL 2 style, without uniform buffer objects) */
-
-typedef struct {
- int ssao_uniform;
- int ssao_color_uniform;
- int color_uniform;
- int depth_uniform;
- int viewvecs_uniform;
- int ssao_sample_params_uniform;
- int ssao_concentric_tex;
- int ssao_jitter_uniform;
-} GPUSSAOShaderInterface;
-
-typedef struct {
- int invrendertargetdim_uniform;
- int color_uniform;
- int dof_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFHQPassOneInterface;
-
-typedef struct {
- int rendertargetdim_uniform;
- int color_uniform;
- int coc_uniform;
- int select_uniform;
- int dof_uniform;
-} GPUDOFHQPassTwoInterface;
-
-typedef struct {
- int dof_uniform;
- int invrendertargetdim_uniform;
- int color_uniform;
- int far_uniform;
- int near_uniform;
- int viewvecs_uniform;
- int depth_uniform;
-} GPUDOFHQPassThreeInterface;
-
-typedef struct {
- int dof_uniform;
- int invrendertargetdim_uniform;
- int color_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFPassOneInterface;
-
-typedef struct {
- int dof_uniform;
- int invrendertargetdim_uniform;
- int color_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFPassTwoInterface;
-
-typedef struct {
- int near_coc_downsampled;
- int near_coc_blurred;
-} GPUDOFPassThreeInterface;
-
-typedef struct {
- int near_coc_downsampled;
- int invrendertargetdim_uniform;
-} GPUDOFPassFourInterface;
-
-typedef struct {
- int medium_blurred_uniform;
- int high_blurred_uniform;
- int dof_uniform;
- int invrendertargetdim_uniform;
- int original_uniform;
- int depth_uniform;
- int viewvecs_uniform;
-} GPUDOFPassFiveInterface;
-
-typedef struct {
- int depth_uniform;
-} GPUDepthResolveInterface;
-
-
-struct GPUFX {
- /* we borrow the term gbuffer from deferred rendering however this is just a regular
- * depth/color framebuffer. Could be extended later though */
- GPUFrameBuffer *gbuffer;
-
- /* dimensions of the gbuffer */
- int gbuffer_dim[2];
-
- /* texture bound to the first color attachment of the gbuffer */
- GPUTexture *color_buffer;
-
- /* second texture used for ping-pong compositing */
- GPUTexture *color_buffer_sec;
- /* texture bound to the depth attachment of the gbuffer */
- GPUTexture *depth_buffer;
- GPUTexture *depth_buffer_xray;
-
- /* texture used for jittering for various effects */
- GPUTexture *jitter_buffer;
-
- /* all those buffers below have to coexist.
- * Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */
- int dof_downsampled_w;
- int dof_downsampled_h;
-
- /* texture used for near coc and color blurring calculation */
- GPUTexture *dof_near_coc_buffer;
- /* blurred near coc buffer. */
- GPUTexture *dof_near_coc_blurred_buffer;
- /* final near coc buffer. */
- GPUTexture *dof_near_coc_final_buffer;
-
- /* half size blur buffer */
- GPUTexture *dof_half_downsampled_near;
- GPUTexture *dof_half_downsampled_far;
- /* high quality dof texture downsamplers. 6 levels means 64 pixels wide - should be enough */
- GPUTexture *dof_nearfar_coc;
- GPUTexture *dof_near_blur;
- GPUTexture *dof_far_blur;
-
- /* for high quality we use again a spiral texture with radius adapted */
- bool dof_high_quality;
-
- /* texture used for ssao */
- int ssao_sample_count_cache;
- GPUTexture *ssao_spiral_samples_tex;
-
-
- GPUFXSettings settings;
-
- /* or-ed flags of enabled effects */
- int effects;
-
- /* number of passes, needed to detect if ping pong buffer allocation is needed */
- int num_passes;
-
- /* we have a stencil, restore the previous state */
- bool restore_stencil;
-
- 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)
-{
- 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, NULL);
- MEM_freeN(texels);
- return tex;
-}
-#endif
-
-static GPUTexture *create_spiral_sample_texture(int numsaples)
-{
- GPUTexture *tex;
- float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
- const float numsaples_inv = 1.0f / numsaples;
- int i;
- /* arbitrary number to ensure we don't get conciding samples every circle */
- const float spirals = 7.357;
-
- for (i = 0; i < numsaples; i++) {
- float r = (i + 0.5f) * numsaples_inv;
- float phi = r * spirals * (float)(2.0 * M_PI);
- texels[i][0] = r * cosf(phi);
- texels[i][1] = r * sinf(phi);
- }
-
- tex = GPU_texture_create_1D_procedural(numsaples, (float *)texels, NULL);
- MEM_freeN(texels);
- return tex;
-}
-
-/* generate a new FX compositor */
-GPUFX *GPU_fx_compositor_create(void)
-{
- GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
-
- glGenBuffers(1, &fx->vbuffer);
- glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
- glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STATIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * sizeof(float), fullscreencos);
- glBufferSubData(GL_ARRAY_BUFFER, 8 * sizeof(float), 8 * sizeof(float), fullscreenuvs);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- return fx;
-}
-
-static void cleanup_fx_dof_buffers(GPUFX *fx)
-{
- if (fx->dof_near_coc_blurred_buffer) {
- GPU_texture_free(fx->dof_near_coc_blurred_buffer);
- fx->dof_near_coc_blurred_buffer = NULL;
- }
- if (fx->dof_near_coc_buffer) {
- GPU_texture_free(fx->dof_near_coc_buffer);
- fx->dof_near_coc_buffer = NULL;
- }
- if (fx->dof_near_coc_final_buffer) {
- GPU_texture_free(fx->dof_near_coc_final_buffer);
- fx->dof_near_coc_final_buffer = NULL;
- }
-
- if (fx->dof_half_downsampled_near) {
- GPU_texture_free(fx->dof_half_downsampled_near);
- fx->dof_half_downsampled_near = NULL;
- }
- if (fx->dof_half_downsampled_far) {
- GPU_texture_free(fx->dof_half_downsampled_far);
- fx->dof_half_downsampled_far = NULL;
- }
- if (fx->dof_nearfar_coc) {
- GPU_texture_free(fx->dof_nearfar_coc);
- fx->dof_nearfar_coc = NULL;
- }
- if (fx->dof_near_blur) {
- GPU_texture_free(fx->dof_near_blur);
- fx->dof_near_blur = NULL;
- }
- if (fx->dof_far_blur) {
- GPU_texture_free(fx->dof_far_blur);
- fx->dof_far_blur = NULL;
- }
-}
-
-static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
-{
- if (fx->color_buffer) {
- GPU_framebuffer_texture_detach(fx->color_buffer);
- GPU_texture_free(fx->color_buffer);
- fx->color_buffer = NULL;
- }
-
- if (fx->color_buffer_sec) {
- GPU_framebuffer_texture_detach(fx->color_buffer_sec);
- GPU_texture_free(fx->color_buffer_sec);
- fx->color_buffer_sec = NULL;
- }
-
- if (fx->depth_buffer) {
- GPU_framebuffer_texture_detach(fx->depth_buffer);
- GPU_texture_free(fx->depth_buffer);
- fx->depth_buffer = NULL;
- }
-
- if (fx->depth_buffer_xray) {
- GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
- GPU_texture_free(fx->depth_buffer_xray);
- fx->depth_buffer_xray = NULL;
- }
-
- cleanup_fx_dof_buffers(fx);
-
- if (fx->ssao_spiral_samples_tex) {
- GPU_texture_free(fx->ssao_spiral_samples_tex);
- fx->ssao_spiral_samples_tex = NULL;
- }
-
- if (fx->jitter_buffer && do_fbo) {
- GPU_texture_free(fx->jitter_buffer);
- fx->jitter_buffer = NULL;
- }
-
- if (fx->gbuffer && do_fbo) {
- GPU_framebuffer_free(fx->gbuffer);
- fx->gbuffer = NULL;
- }
-}
-
-/* destroy a text compositor */
-void GPU_fx_compositor_destroy(GPUFX *fx)
-{
- cleanup_fx_gl_data(fx, true);
- glDeleteBuffers(1, &fx->vbuffer);
- 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)
-{
- int w = BLI_rcti_size_x(rect), h = BLI_rcti_size_y(rect);
- char err_out[256];
- int num_passes = 0;
- char fx_flag;
-
- fx->effects = 0;
-
- if (!GLEW_EXT_framebuffer_object)
- return false;
-
- if (!fx_settings) {
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- fx_flag = fx_settings->fx_flag;
-
- /* disable effects if no options passed for them */
- if (!fx_settings->dof) {
- fx_flag &= ~GPU_FX_FLAG_DOF;
- }
- if (!fx_settings->ssao || fx_settings->ssao->samples < 1) {
- fx_flag &= ~GPU_FX_FLAG_SSAO;
- }
-
- if (!fx_flag) {
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- /* scissor is missing when drawing offscreen, in that case, dimensions match exactly. In opposite case
- * add one to match viewport dimensions */
- if (scissor_rect) {
- w++;
- h++;
- }
-
- fx->num_passes = 0;
- /* dof really needs a ping-pong buffer to work */
- if (fx_flag & GPU_FX_FLAG_DOF)
- num_passes++;
-
- if (fx_flag & GPU_FX_FLAG_SSAO)
- num_passes++;
-
- if (!fx->gbuffer) {
- fx->gbuffer = GPU_framebuffer_create();
-
- if (!fx->gbuffer) {
- return false;
- }
- }
-
- /* try creating the jitter texture */
- if (!fx->jitter_buffer)
- fx->jitter_buffer = 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]) {
- cleanup_fx_gl_data(fx, false);
-
- if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
- printf(".256%s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
-
- if (fx_flag & GPU_FX_FLAG_SSAO) {
- if (fx_settings->ssao->samples != fx->ssao_sample_count_cache || !fx->ssao_spiral_samples_tex) {
- if (fx_settings->ssao->samples < 1)
- fx_settings->ssao->samples = 1;
-
- fx->ssao_sample_count_cache = fx_settings->ssao->samples;
-
- if (fx->ssao_spiral_samples_tex) {
- GPU_texture_free(fx->ssao_spiral_samples_tex);
- }
-
- fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples);
- }
- }
- else {
- if (fx->ssao_spiral_samples_tex) {
- GPU_texture_free(fx->ssao_spiral_samples_tex);
- fx->ssao_spiral_samples_tex = NULL;
- }
- }
-
- /* create textures for dof effect */
- if (fx_flag & GPU_FX_FLAG_DOF) {
- bool dof_high_quality = (fx_settings->dof->high_quality != 0) &&
- GPU_geometry_shader_support() && GPU_instanced_drawing_support();
-
- /* cleanup buffers if quality setting has changed (no need to keep more buffers around than necessary ) */
- if (dof_high_quality != fx->dof_high_quality)
- cleanup_fx_dof_buffers(fx);
-
- if (dof_high_quality) {
- fx->dof_downsampled_w = w / 2;
- fx->dof_downsampled_h = h / 2;
-
- if (!fx->dof_half_downsampled_near || !fx->dof_nearfar_coc || !fx->dof_near_blur ||
- !fx->dof_far_blur || !fx->dof_half_downsampled_far)
- {
-
- if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
-
- if (!(fx->dof_near_blur = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
-
- if (!(fx->dof_far_blur = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
- }
- else {
- fx->dof_downsampled_w = w / 4;
- fx->dof_downsampled_h = h / 4;
-
- if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
-
- if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
- }
-
- fx->dof_high_quality = dof_high_quality;
- }
- else {
- /* cleanup unnecessary buffers */
- cleanup_fx_dof_buffers(fx);
- }
-
- /* we need to pass data between shader stages, allocate an extra color buffer */
- if (num_passes > 1) {
- if (!fx->color_buffer_sec) {
- if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
- printf(".256%s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return false;
- }
- }
- }
- else {
- if (fx->color_buffer_sec) {
- GPU_framebuffer_texture_detach(fx->color_buffer_sec);
- GPU_texture_free(fx->color_buffer_sec);
- fx->color_buffer_sec = NULL;
- }
- }
-
- /* bind the buffers */
-
- /* first depth buffer, because system assumes read/write buffers */
- if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out))
- printf("%.256s\n", err_out);
-
- if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out))
- printf("%.256s\n", err_out);
-
- if (!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
- printf("%.256s\n", err_out);
-
- GPU_texture_bind_as_framebuffer(fx->color_buffer);
-
- /* enable scissor test. It's needed to ensure sculpting works correctly */
- if (scissor_rect) {
- int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
- int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
- glPushAttrib(GL_SCISSOR_BIT);
- glEnable(GL_SCISSOR_TEST);
- glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
- w_sc, h_sc);
- fx->restore_stencil = true;
- }
- else {
- fx->restore_stencil = false;
- }
-
- fx->effects = fx_flag;
-
- if (fx_settings)
- fx->settings = *fx_settings;
- fx->gbuffer_dim[0] = w;
- fx->gbuffer_dim[1] = h;
-
- fx->num_passes = num_passes;
-
- return true;
-}
-
-static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOffScreen *ofs, GPUTexture *target)
-{
- if ((*passes_left)-- == 1) {
- GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
- if (ofs) {
- GPU_offscreen_bind(ofs, false);
- }
- else
- GPU_framebuffer_restore();
- }
- else {
- /* bind the ping buffer to the color buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, NULL);
- }
-}
-
-void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray)
-{
- char err_out[256];
-
- if (do_xray) {
- if (!fx->depth_buffer_xray &&
- !(fx->depth_buffer_xray = GPU_texture_create_depth(fx->gbuffer_dim[0], fx->gbuffer_dim[1], err_out)))
- {
- printf("%.256s\n", err_out);
- cleanup_fx_gl_data(fx, true);
- return;
- }
- }
- else {
- if (fx->depth_buffer_xray) {
- GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
- GPU_texture_free(fx->depth_buffer_xray);
- fx->depth_buffer_xray = NULL;
- }
- return;
- }
-
- GPU_framebuffer_texture_detach(fx->depth_buffer);
-
- /* first depth buffer, because system assumes read/write buffers */
- if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out))
- printf("%.256s\n", err_out);
-}
-
-
-void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
-{
- GPUShader *depth_resolve_shader;
- GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
-
- /* attach regular framebuffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, NULL);
-
- /* full screen quad where we will always write to depth buffer */
- glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
- glDepthFunc(GL_ALWAYS);
- /* disable scissor from sculpt if any */
- glDisable(GL_SCISSOR_TEST);
- /* disable writing to color buffer, it's depth only pass */
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- /* set up quad buffer */
- glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
- glVertexPointer(2, GL_FLOAT, 0, NULL);
- glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float)));
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);
-
- if (depth_resolve_shader) {
- GPUDepthResolveInterface *interface = GPU_shader_get_interface(depth_resolve_shader);
-
- GPU_shader_bind(depth_resolve_shader);
-
- GPU_texture_bind(fx->depth_buffer_xray, 0);
- GPU_texture_filter_mode(fx->depth_buffer_xray, false, true);
- GPU_shader_uniform_texture(depth_resolve_shader, interface->depth_uniform, fx->depth_buffer_xray);
-
- /* draw */
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- /* disable bindings */
- GPU_texture_filter_mode(fx->depth_buffer_xray, true, false);
- GPU_texture_unbind(fx->depth_buffer_xray);
-
- GPU_shader_unbind();
- }
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glPopAttrib();
-}
-
-
-bool GPU_fx_do_composite_pass(
- GPUFX *fx, float projmat[4][4], bool is_persp,
- struct Scene *scene, struct GPUOffScreen *ofs)
-{
- GPUTexture *src, *target;
- int numslots = 0;
- float invproj[4][4];
- int i;
- float dfdyfac[2];
- /* number of passes left. when there are no more passes, the result is passed to the frambuffer */
- int passes_left = fx->num_passes;
- /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
- float viewvecs[3][4] = {
- {-1.0f, -1.0f, -1.0f, 1.0f},
- {1.0f, -1.0f, -1.0f, 1.0f},
- {-1.0f, 1.0f, -1.0f, 1.0f}
- };
-
- if (fx->effects == 0)
- return false;
-
- GPU_get_dfdy_factors(dfdyfac);
- /* first, unbind the render-to-texture framebuffer */
- GPU_framebuffer_texture_detach(fx->color_buffer);
- GPU_framebuffer_texture_detach(fx->depth_buffer);
-
- if (fx->restore_stencil)
- glPopAttrib();
-
- src = fx->color_buffer;
- target = fx->color_buffer_sec;
-
- /* set up quad buffer */
- glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
- glVertexPointer(2, GL_FLOAT, 0, NULL);
- glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float)));
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- /* full screen FX pass */
-
- /* invert the view matrix */
- invert_m4_m4(invproj, projmat);
-
- /* convert the view vectors to view space */
- for (i = 0; i < 3; i++) {
- mul_m4_v4(invproj, viewvecs[i]);
- /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
- if (is_persp)
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
- viewvecs[i][3] = 1.0;
- }
-
- /* we need to store the differences */
- viewvecs[1][0] -= viewvecs[0][0];
- viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
-
- /* calculate a depth offset as well */
- if (!is_persp) {
- float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
- mul_m4_v4(invproj, vec_far);
- mul_v3_fl(vec_far, 1.0f / vec_far[3]);
- viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
- }
-
- /* set invalid color in case shader fails */
- glColor3f(1.0, 0.0, 1.0);
- glDisable(GL_DEPTH_TEST);
-
- /* ssao pass */
- if (fx->effects & GPU_FX_FLAG_SSAO) {
- GPUShader *ssao_shader;
- ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
- if (ssao_shader) {
- const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
- /* adjust attenuation to be scale invariant */
- float attenuation = fx_ssao->attenuation / (fx_ssao->distance_max * fx_ssao->distance_max);
- float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, attenuation, 0.0f};
- float sample_params[3];
-
- sample_params[0] = fx->ssao_sample_count_cache;
- /* multiplier so we tile the random texture on screen */
- sample_params[1] = fx->gbuffer_dim[0] / 64.0;
- sample_params[2] = fx->gbuffer_dim[1] / 64.0;
-
- ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1];
-
- GPUSSAOShaderInterface *interface = GPU_shader_get_interface(ssao_shader);
-
- GPU_shader_bind(ssao_shader);
-
- GPU_shader_uniform_vector(ssao_shader, interface->ssao_uniform, 4, 1, ssao_params);
- GPU_shader_uniform_vector(ssao_shader, interface->ssao_color_uniform, 4, 1, fx_ssao->color);
- GPU_shader_uniform_vector(ssao_shader, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
- GPU_shader_uniform_vector(ssao_shader, interface->ssao_sample_params_uniform, 3, 1, sample_params);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(ssao_shader, interface->color_uniform, src);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
- GPU_shader_uniform_texture(ssao_shader, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(fx->jitter_buffer, numslots++);
- GPU_shader_uniform_texture(ssao_shader, interface->ssao_jitter_uniform, fx->jitter_buffer);
-
- GPU_texture_bind(fx->ssao_spiral_samples_tex, numslots++);
- GPU_shader_uniform_texture(ssao_shader, interface->ssao_concentric_tex, fx->ssao_spiral_samples_tex);
-
- /* draw */
- gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- /* disable bindings */
- GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
- GPU_texture_unbind(fx->depth_buffer);
- GPU_texture_unbind(fx->jitter_buffer);
- GPU_texture_unbind(fx->ssao_spiral_samples_tex);
-
- /* 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;
- }
- }
-
- /* second pass, dof */
- if (fx->effects & GPU_FX_FLAG_DOF) {
- const GPUDOFSettings *fx_dof = fx->settings.dof;
- float dof_params[4];
- float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
- /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
- * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
- * because the shader reads coordinates in world space, which is in blender units.
- * Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */
- float scale_camera = 0.001f / scale;
- /* we want radius here for the aperture number */
- float aperture = 0.5f * scale_camera * fx_dof->focal_length / fx_dof->fstop;
-
- dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length /
- (fx_dof->focus_distance - scale_camera * fx_dof->focal_length));
- dof_params[1] = fx_dof->focus_distance;
- dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
- dof_params[3] = fx_dof->num_blades;
-
- if (fx->dof_high_quality) {
- GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3;
-
- /* custom shaders close to the effect described in CryEngine 3 Graphics Gems */
- dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE, is_persp);
- dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO, is_persp);
- dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE, is_persp);
-
- /* error occured, restore framebuffers and return */
- if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) {
- GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
- GPU_framebuffer_restore();
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- GPU_shader_unbind();
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- return false;
- }
-
- /* pass first, downsample the color buffer to near/far targets and calculate coc texture */
- {
- float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
-
- GPUDOFHQPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1);
-
- GPU_shader_bind(dof_shader_pass1);
-
- GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, false);
- GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(src, numslots++);
- /* disable filtering for the texture so custom downsample can do the right thing */
- GPU_texture_filter_mode(src, false, false);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, src);
-
- /* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, NULL);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, NULL);
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, NULL);
- /* binding takes care of setting the viewport to the downsampled size */
- GPU_framebuffer_slots_bind(fx->gbuffer, 0);
-
- GPU_framebuffer_check_valid(fx->gbuffer, NULL);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- /* disable bindings */
- GPU_texture_filter_mode(src, false, true);
- GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near);
- GPU_framebuffer_texture_detach(fx->dof_half_downsampled_far);
- GPU_framebuffer_texture_detach(fx->dof_nearfar_coc);
- GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_half_downsampled_near);
-
- numslots = 0;
- }
-
- /* second pass, shoot quads for every pixel in the downsampled buffers, scaling according
- * to circle of confusion */
- {
- int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h};
- float selection[2] = {0.0f, 1.0f};
-
- GPUDOFHQPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2);
-
- GPU_shader_bind(dof_shader_pass2);
-
- GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector_int(dof_shader_pass2, interface->rendertargetdim_uniform, 2, 1, rendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
-
- GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->coc_uniform, fx->dof_nearfar_coc);
-
- GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
- GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_far);
- GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false);
-
- /* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, NULL);
- GPU_texture_bind_as_framebuffer(fx->dof_far_blur);
-
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
- glPointSize(1.0f);
- /* have to clear the buffer unfortunately */
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
- /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
-
- GPU_texture_unbind(fx->dof_half_downsampled_far);
- GPU_framebuffer_texture_detach(fx->dof_far_blur);
-
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near);
- GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false);
-
- selection[0] = 1.0f;
- selection[1] = 0.0f;
-
- GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, NULL);
- /* have to clear the buffer unfortunately */
- glClear(GL_COLOR_BUFFER_BIT);
- /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
-
- /* disable bindings */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_BLEND);
-
- GPU_framebuffer_texture_detach(fx->dof_near_blur);
-
- GPU_texture_unbind(fx->dof_half_downsampled_near);
- GPU_texture_unbind(fx->dof_nearfar_coc);
-
- GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur);
- }
-
- /* third pass, accumulate the near/far blur fields */
- {
- float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
-
- GPUDOFHQPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3);
-
- GPU_shader_bind(dof_shader_pass3);
-
- GPU_shader_uniform_vector(dof_shader_pass3, interface->dof_uniform, 4, 1, dof_params);
-
- GPU_shader_uniform_vector(dof_shader_pass3, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass3, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(fx->dof_near_blur, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->near_uniform, fx->dof_near_blur);
- GPU_texture_filter_mode(fx->dof_near_blur, false, true);
-
- GPU_texture_bind(fx->dof_far_blur, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->far_uniform, fx->dof_far_blur);
- GPU_texture_filter_mode(fx->dof_far_blur, false, true);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, false);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->color_uniform, src);
-
- /* if this is the last pass, prepare for rendering on the frambuffer */
- gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_blur);
- GPU_texture_unbind(fx->dof_far_blur);
- GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- /* 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();
- }
- }
-
- numslots = 0;
- }
- }
- else {
- GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
-
- /* DOF effect has many passes but most of them are performed
- * on a texture whose dimensions are 4 times less than the original
- * (16 times lower than original screen resolution).
- * Technique used is not very exact but should be fast enough and is based
- * on "Practical Post-Process Depth of Field"
- * see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
- dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
- dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
- dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
- dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
- dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);
-
- /* error occured, restore framebuffers and return */
- if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
- GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
- GPU_framebuffer_restore();
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- GPU_shader_unbind();
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- return false;
- }
-
- /* pass first, first level of blur in low res buffer */
- {
- float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
-
- GPUDOFPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1);
-
- GPU_shader_bind(dof_shader_pass1);
-
- GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass1, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass1, interface->color_uniform, src);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
- GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
-
- /* target is the downsampled coc buffer */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
- /* binding takes care of setting the viewport to the downsampled size */
- GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- /* disable bindings */
- GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
- numslots = 0;
- }
-
- /* second pass, gaussian blur the downsampled image */
- {
- float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
- 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
- float tmp = invrendertargetdim[0];
- invrendertargetdim[0] = 0.0f;
-
- GPUDOFPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2);
-
- dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
-
- /* Blurring vertically */
- GPU_shader_bind(dof_shader_pass2);
-
- GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass2, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->depth_uniform, fx->depth_buffer);
-
- GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_buffer);
-
- /* use final buffer as a temp here */
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
-
- /* Drawing quad */
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- /* *unbind/detach */
- GPU_texture_unbind(fx->dof_near_coc_buffer);
- GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
-
- /* Blurring horizontally */
- invrendertargetdim[0] = tmp;
- invrendertargetdim[1] = 0.0f;
- GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-
- GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_final_buffer);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- /* *unbind/detach */
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- GPU_texture_unbind(fx->dof_near_coc_final_buffer);
- GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);
-
- dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
-
- numslots = 0;
- }
-
- /* third pass, calculate near coc */
- {
- GPUDOFPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3);
-
- GPU_shader_bind(dof_shader_pass3);
-
- GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_downsampled, fx->dof_near_coc_buffer);
-
- GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_blurred, fx->dof_near_coc_blurred_buffer);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_coc_buffer);
- GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
-
- /* unbinding here restores the size to the original */
- GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
-
- numslots = 0;
- }
-
- /* fourth pass blur final coc once to eliminate discontinuities */
- {
- float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
- 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
-
- GPUDOFPassFourInterface *interface = GPU_shader_get_interface(dof_shader_pass4);
-
- GPU_shader_bind(dof_shader_pass4);
-
- GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass4, interface->near_coc_downsampled, fx->dof_near_coc_final_buffer);
- GPU_shader_uniform_vector(dof_shader_pass4, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
-
- GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_coc_final_buffer);
-
- /* unbinding here restores the size to the original */
- GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
- GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
-
- numslots = 0;
- }
-
- /* final pass, merge blurred layers according to final calculated coc */
- {
- float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
-
- GPUDOFPassFiveInterface *interface = GPU_shader_get_interface(dof_shader_pass5);
-
- GPU_shader_bind(dof_shader_pass5);
-
- GPU_shader_uniform_vector(dof_shader_pass5, interface->dof_uniform, 4, 1, dof_params);
- GPU_shader_uniform_vector(dof_shader_pass5, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
- GPU_shader_uniform_vector(dof_shader_pass5, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
-
- GPU_texture_bind(src, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->original_uniform, src);
-
- GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
-
- GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->medium_blurred_uniform, fx->dof_near_coc_buffer);
-
- GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
- GPU_shader_uniform_texture(dof_shader_pass5, interface->depth_uniform, fx->depth_buffer);
-
- /* if this is the last pass, prepare for rendering on the frambuffer */
- gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- /* disable bindings */
- GPU_texture_unbind(fx->dof_near_coc_buffer);
- GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
- GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
- GPU_texture_unbind(fx->depth_buffer);
-
- /* 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(GPUTexture *, target, src);
- numslots = 0;
- }
- }
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- GPU_shader_unbind();
-
- return true;
-}
-
-void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
-{
- fx_dof->fstop = 128.0f;
- fx_dof->focal_length = 1.0f;
- fx_dof->focus_distance = 1.0f;
- fx_dof->sensor = 1.0f;
- fx_dof->num_blades = 6;
-}
-
-void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
-{
- fx_ssao->factor = 1.0f;
- fx_ssao->distance_max = 0.2f;
- fx_ssao->attenuation = 1.0f;
- fx_ssao->samples = 20;
-}
-
-void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect effect)
-{
- if (!shader)
- return;
-
- switch (effect) {
- case GPU_SHADER_FX_SSAO:
- {
- GPUSSAOShaderInterface *interface = MEM_mallocN(sizeof(GPUSSAOShaderInterface), "GPUSSAOShaderInterface");
-
- interface->ssao_uniform = GPU_shader_get_uniform(shader, "ssao_params");
- interface->ssao_color_uniform = GPU_shader_get_uniform(shader, "ssao_color");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- interface->ssao_sample_params_uniform = GPU_shader_get_uniform(shader, "ssao_sample_params");
- interface->ssao_concentric_tex = GPU_shader_get_uniform(shader, "ssao_concentric_tex");
- interface->ssao_jitter_uniform = GPU_shader_get_uniform(shader, "jitter_tex");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
- {
- GPUDOFHQPassOneInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassOneInterface), "GPUDOFHQPassOneInterface");
-
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
- {
- GPUDOFHQPassTwoInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassTwoInterface), "GPUDOFHQPassTwoInterface");
-
- interface->rendertargetdim_uniform = GPU_shader_get_uniform(shader, "rendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->coc_uniform = GPU_shader_get_uniform(shader, "cocbuffer");
- interface->select_uniform = GPU_shader_get_uniform(shader, "layerselection");
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
- {
- GPUDOFHQPassThreeInterface *interface = MEM_mallocN(sizeof(GPUDOFHQPassThreeInterface), "GPUDOFHQPassThreeInterface");
-
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->far_uniform = GPU_shader_get_uniform(shader, "farbuffer");
- interface->near_uniform = GPU_shader_get_uniform(shader, "nearbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
- {
- GPUDOFPassOneInterface *interface = MEM_mallocN(sizeof(GPUDOFPassOneInterface), "GPUDOFPassOneInterface");
-
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
- {
- GPUDOFPassTwoInterface *interface = MEM_mallocN(sizeof(GPUDOFPassTwoInterface), "GPUDOFPassTwoInterface");
-
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->color_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
- {
- GPUDOFPassThreeInterface *interface = MEM_mallocN(sizeof(GPUDOFPassThreeInterface), "GPUDOFPassThreeInterface");
-
- interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->near_coc_blurred = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
- {
- GPUDOFPassFourInterface *interface = MEM_mallocN(sizeof(GPUDOFPassFourInterface), "GPUDOFPassFourInterface");
-
- interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
- {
- GPUDOFPassFiveInterface *interface = MEM_mallocN(sizeof(GPUDOFPassFiveInterface), "GPUDOFPassFiveInterface");
-
- interface->medium_blurred_uniform = GPU_shader_get_uniform(shader, "mblurredcolorbuffer");
- interface->high_blurred_uniform = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
- interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- interface->original_uniform = GPU_shader_get_uniform(shader, "colorbuffer");
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
-
- case GPU_SHADER_FX_DEPTH_RESOLVE:
- {
- GPUDepthResolveInterface *interface = MEM_mallocN(sizeof(GPUDepthResolveInterface), "GPUDepthResolveInterface");
-
- interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
-
- GPU_shader_set_interface(shader, interface);
- break;
- }
-
- default:
- break;
- }
-}
-
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
index 859aab9565f..8aea87ef659 100644
--- a/source/blender/gpu/intern/gpu_debug.c
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -20,7 +20,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): Brecht Van Lommel, Jason Wilkins.
+ * Contributor(s): Brecht Van Lommel, Jason Wilkins, Mike Erwin.
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -44,122 +44,18 @@
#include <stdlib.h>
#include <string.h>
-#define CASE_CODE_RETURN_STR(code) case code: return #code;
+#ifndef __APPLE__ /* only non-Apple systems implement OpenGL debug callbacks */
-static const char *gpu_gl_error_symbol(GLenum err)
-{
- switch (err) {
- CASE_CODE_RETURN_STR(GL_NO_ERROR)
- CASE_CODE_RETURN_STR(GL_INVALID_ENUM)
- CASE_CODE_RETURN_STR(GL_INVALID_VALUE)
- CASE_CODE_RETURN_STR(GL_INVALID_OPERATION)
- CASE_CODE_RETURN_STR(GL_STACK_OVERFLOW)
- CASE_CODE_RETURN_STR(GL_STACK_UNDERFLOW)
- CASE_CODE_RETURN_STR(GL_OUT_OF_MEMORY)
-
-#if GL_ARB_imaging
- CASE_CODE_RETURN_STR(GL_TABLE_TOO_LARGE)
-#endif
-
-#if defined(WITH_GLU)
- CASE_CODE_RETURN_STR(GLU_INVALID_ENUM)
- CASE_CODE_RETURN_STR(GLU_INVALID_VALUE)
- CASE_CODE_RETURN_STR(GLU_OUT_OF_MEMORY)
-#endif
+/* control whether we use older AMD_debug_output extension
+ * some supported GPU + OS combos do not have the newer extensions */
+# define LEGACY_DEBUG 1
- default:
- return "<unknown error>";
- }
-}
-
-#undef CASE_CODE_RETURN_STR
-
-
-static bool gpu_report_gl_errors(const char *file, int line, const char *str)
-{
- GLenum gl_error = glGetError();
-
- if (gl_error == GL_NO_ERROR) {
- return true;
- }
- else {
- /* glGetError should have cleared the error flag, so if we get the
- * same flag twice that means glGetError itself probably triggered
- * the error. This happens on Windows if the GL context is invalid.
- */
- {
- GLenum new_error = glGetError();
- if (gl_error == new_error) {
- fprintf(stderr, "GL: Possible context invalidation issue\n");
- return false;
- }
- }
-
- fprintf(stderr,
- "%s:%d: ``%s'' -> GL Error (0x%04X - %s): %s\n",
- file, line, str, gl_error,
- gpu_gl_error_symbol(gl_error),
- gpuErrorString(gl_error));
-
- return false;
- }
-}
-
-
-const char *gpuErrorString(GLenum err)
-{
- switch (err) {
- case GL_NO_ERROR:
- return "No Error";
-
- case GL_INVALID_ENUM:
- return "Invalid Enumeration";
-
- case GL_INVALID_VALUE:
- return "Invalid Value";
-
- case GL_INVALID_OPERATION:
- return "Invalid Operation";
-
- case GL_STACK_OVERFLOW:
- return "Stack Overflow";
-
- case GL_STACK_UNDERFLOW:
- return "Stack Underflow";
-
- case GL_OUT_OF_MEMORY:
- return "Out of Memory";
-
-#if GL_ARB_imaging
- case GL_TABLE_TOO_LARGE:
- return "Table Too Large";
-#endif
-
-#if defined(WITH_GLU)
- case GLU_INVALID_ENUM:
- return "Invalid Enum (GLU)";
-
- case GLU_INVALID_VALUE:
- return "Invalid Value (GLU)";
-
- case GLU_OUT_OF_MEMORY:
- return "Out of Memory (GLU)";
-#endif
-
- default:
- return "<unknown error>";
- }
-}
-
-
-/* Debug callbacks need the same calling convention as OpenGL functions.
- */
-#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
- /* Win32 but not WinCE */
-# define APIENTRY __stdcall
-#else
-# define APIENTRY
-#endif
+/* Debug callbacks need the same calling convention as OpenGL functions. */
+# if defined(_WIN32)
+# define APIENTRY __stdcall
+# else
+# define APIENTRY
+# endif
static const char *source_name(GLenum source)
@@ -189,32 +85,11 @@ static const char *message_type_name(GLenum message)
}
}
-static const char *category_name_amd(GLenum category)
-{
- switch (category) {
- case GL_DEBUG_CATEGORY_API_ERROR_AMD: return "API error";
- case GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD: return "window system";
- case GL_DEBUG_CATEGORY_DEPRECATION_AMD: return "deprecated behavior";
- case GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD: return "undefined behavior";
- case GL_DEBUG_CATEGORY_PERFORMANCE_AMD: return "performance";
- case GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD: return "shader compiler";
- case GL_DEBUG_CATEGORY_APPLICATION_AMD: return "application";
- case GL_DEBUG_CATEGORY_OTHER_AMD: return "other";
- default: return "???";
- }
-}
-
-
static void APIENTRY gpu_debug_proc(
GLenum source, GLenum type, GLuint UNUSED(id),
GLenum severity, GLsizei UNUSED(length),
const GLchar *message, const GLvoid *UNUSED(userParm))
{
- if (type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR) {
- /* Blender 2.7x uses OpenGL 2.1, we don't care if features are deprecated */
- return;
- }
-
bool backtrace = false;
switch (severity) {
@@ -233,18 +108,28 @@ static void APIENTRY gpu_debug_proc(
}
}
+# if LEGACY_DEBUG
+
+static const char *category_name_amd(GLenum category)
+{
+ switch (category) {
+ case GL_DEBUG_CATEGORY_API_ERROR_AMD: return "API error";
+ case GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD: return "window system";
+ case GL_DEBUG_CATEGORY_DEPRECATION_AMD: return "deprecated behavior";
+ case GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD: return "undefined behavior";
+ case GL_DEBUG_CATEGORY_PERFORMANCE_AMD: return "performance";
+ case GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD: return "shader compiler";
+ case GL_DEBUG_CATEGORY_APPLICATION_AMD: return "application";
+ case GL_DEBUG_CATEGORY_OTHER_AMD: return "other";
+ default: return "???";
+ }
+}
-#ifndef GLEW_ES_ONLY
static void APIENTRY gpu_debug_proc_amd(
GLuint UNUSED(id), GLenum category,
GLenum severity, GLsizei UNUSED(length),
const GLchar *message, GLvoid *UNUSED(userParm))
{
- if (category == GL_DEBUG_CATEGORY_DEPRECATION_AMD) {
- /* Blender 2.7x uses OpenGL 2.1, we don't care if features are deprecated */
- return;
- }
-
bool backtrace = false;
switch (severity) {
@@ -261,148 +146,88 @@ static void APIENTRY gpu_debug_proc_amd(
fflush(stderr);
}
}
-#endif
+# endif /* LEGACY_DEBUG */
-
-#undef APIENTRY
+# undef APIENTRY
+#endif /* not Apple */
void gpu_debug_init(void)
{
+#ifdef __APPLE__
+ fprintf(stderr, "OpenGL debug callback is not available on Apple.\n");
+#else /* not Apple */
const char success[] = "Successfully hooked OpenGL debug callback.";
-#if !defined(WITH_GLEW_ES) && !defined(GLEW_ES_ONLY)
- if (GLEW_VERSION_4_3) {
- fprintf(stderr, "Using OpenGL 4.3 debug facilities\n");
- glEnable(GL_DEBUG_OUTPUT);
- glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, mxGetCurrentContext());
- glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
- GPU_string_marker(success);
- return;
- }
-#endif
-
- if (GLEW_KHR_debug) {
-#ifndef GLEW_ES_ONLY
- fprintf(stderr, "Using KHR_debug extension\n");
+ if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
+ fprintf(stderr, "Using %s\n", GLEW_VERSION_4_3 ? "OpenGL 4.3 debug facilities" : "KHR_debug extension");
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, NULL);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
-#endif
- return;
}
-
-#ifndef GLEW_ES_ONLY
- if (GLEW_ARB_debug_output) {
+ else if (GLEW_ARB_debug_output) {
fprintf(stderr, "Using ARB_debug_output extension\n");
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallbackARB((GLDEBUGPROCARB)gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageCallbackARB((GLDEBUGPROCARB)gpu_debug_proc, NULL);
glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
-
- return;
}
-
- if (GLEW_AMD_debug_output) {
+# if LEGACY_DEBUG
+ else if (GLEW_AMD_debug_output) {
fprintf(stderr, "Using AMD_debug_output extension\n");
- glDebugMessageCallbackAMD(gpu_debug_proc_amd, mxGetCurrentContext());
+ glDebugMessageCallbackAMD(gpu_debug_proc_amd, NULL);
glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
-
- return;
}
-#endif
-
- fprintf(stderr, "Failed to hook OpenGL debug callback.\n");
-
- return;
+# endif
+ else {
+ fprintf(stderr, "Failed to hook OpenGL debug callback.\n");
+ }
+#endif /* not Apple */
}
void gpu_debug_exit(void)
{
-#ifndef WITH_GLEW_ES
-#ifndef GLEW_ES_ONLY
- if (GLEW_VERSION_4_3) {
- glDebugMessageCallback(NULL, NULL);
-
- return;
- }
-#endif
-#endif
-
- if (GLEW_KHR_debug) {
-#ifndef GLEW_ES_ONLY
+#ifndef __APPLE__
+ if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
glDebugMessageCallback(NULL, NULL);
-#endif
- return;
}
-
-#ifndef GLEW_ES_ONLY
- if (GLEW_ARB_debug_output) {
+ else if (GLEW_ARB_debug_output) {
glDebugMessageCallbackARB(NULL, NULL);
-
- return;
}
-
- if (GLEW_AMD_debug_output) {
+# if LEGACY_DEBUG
+ else if (GLEW_AMD_debug_output) {
glDebugMessageCallbackAMD(NULL, NULL);
-
- return;
}
+# endif
#endif
-
- return;
}
void GPU_string_marker(const char *buf)
{
-#ifndef WITH_GLEW_ES
-#ifndef GLEW_ES_ONLY
- if (GLEW_VERSION_4_3) {
- glDebugMessageInsert(
- GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
- GL_DEBUG_SEVERITY_NOTIFICATION, -1, buf);
-
- return;
- }
-#endif
-#endif
-
- if (GLEW_KHR_debug) {
-#ifndef GLEW_ES_ONLY
+#ifdef __APPLE__
+ UNUSED_VARS(buf);
+#else /* not Apple */
+ if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
glDebugMessageInsert(
GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
GL_DEBUG_SEVERITY_NOTIFICATION, -1, buf);
-#endif
- return;
}
-
-#ifndef GLEW_ES_ONLY
- if (GLEW_ARB_debug_output) {
+ else if (GLEW_ARB_debug_output) {
glDebugMessageInsertARB(
GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0,
GL_DEBUG_SEVERITY_LOW_ARB, -1, buf);
-
- return;
}
-
- if (GLEW_AMD_debug_output) {
+# if LEGACY_DEBUG
+ else if (GLEW_AMD_debug_output) {
glDebugMessageInsertAMD(
GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0,
0, buf);
-
- return;
}
-
- if (GLEW_GREMEDY_string_marker) {
- glStringMarkerGREMEDY(0, buf);
-
- return;
- }
-#endif
+# endif
+#endif /* not Apple */
}
void GPU_print_error_debug(const char *str)
@@ -410,406 +235,3 @@ void GPU_print_error_debug(const char *str)
if (G.debug & G_DEBUG)
fprintf(stderr, "GPU: %s\n", str);
}
-
-
-void GPU_assert_no_gl_errors(const char *file, int line, const char *str)
-{
- if (G.debug) {
- GLboolean gl_ok = gpu_report_gl_errors(file, line, str);
-
- BLI_assert(gl_ok);
- (void) gl_ok;
- }
-}
-
-
-static void gpu_state_print_fl_ex(const char *name, GLenum type)
-{
-#define MAX_ARRAY_SIZE 64
-
- const unsigned char err_mark[4] = {0xff, 0xff, 0xff, 0xff};
-
- float value[MAX_ARRAY_SIZE];
- int a;
-
- memset(value, 0xff, sizeof(value));
- glGetFloatv(type, value);
-
- if (glGetError() == GL_NO_ERROR) {
- printf("%s: ", name);
- for (a = 0; a < MAX_ARRAY_SIZE; a++) {
- if (memcmp(&value[a], err_mark, sizeof(value[a])) == 0) {
- break;
- }
- printf("%.2f ", value[a]);
- }
- printf("\n");
- }
-
-#undef MAX_ARRAY_SIZE
-}
-
-#define gpu_state_print_fl(val) gpu_state_print_fl_ex(#val, val)
-
-void GPU_state_print(void)
-{
- GPU_ASSERT_NO_GL_ERRORS("GPU_state_print"); /* clear any errors */
-
- gpu_state_print_fl(GL_ACCUM_ALPHA_BITS);
- gpu_state_print_fl(GL_ACCUM_BLUE_BITS);
- gpu_state_print_fl(GL_ACCUM_CLEAR_VALUE);
- gpu_state_print_fl(GL_ACCUM_GREEN_BITS);
- gpu_state_print_fl(GL_ACCUM_RED_BITS);
- gpu_state_print_fl(GL_ACTIVE_TEXTURE);
- gpu_state_print_fl(GL_ALIASED_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_ALIASED_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_ALPHA_BIAS);
- gpu_state_print_fl(GL_ALPHA_BITS);
- gpu_state_print_fl(GL_ALPHA_SCALE);
- gpu_state_print_fl(GL_ALPHA_TEST);
- gpu_state_print_fl(GL_ALPHA_TEST_FUNC);
- gpu_state_print_fl(GL_ALPHA_TEST_REF);
- gpu_state_print_fl(GL_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_AUTO_NORMAL);
- gpu_state_print_fl(GL_AUX_BUFFERS);
- gpu_state_print_fl(GL_BLEND);
- gpu_state_print_fl(GL_BLEND_COLOR);
- gpu_state_print_fl(GL_BLEND_DST_ALPHA);
- gpu_state_print_fl(GL_BLEND_DST_RGB);
- gpu_state_print_fl(GL_BLEND_EQUATION_ALPHA);
- gpu_state_print_fl(GL_BLEND_EQUATION_RGB);
- gpu_state_print_fl(GL_BLEND_SRC_ALPHA);
- gpu_state_print_fl(GL_BLEND_SRC_RGB);
- gpu_state_print_fl(GL_BLUE_BIAS);
- gpu_state_print_fl(GL_BLUE_BITS);
- gpu_state_print_fl(GL_BLUE_SCALE);
- gpu_state_print_fl(GL_CLIENT_ACTIVE_TEXTURE);
- gpu_state_print_fl(GL_CLIENT_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_CLIP_PLANE0);
- gpu_state_print_fl(GL_COLOR_ARRAY);
- gpu_state_print_fl(GL_COLOR_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_COLOR_ARRAY_SIZE);
- gpu_state_print_fl(GL_COLOR_ARRAY_STRIDE);
- gpu_state_print_fl(GL_COLOR_ARRAY_TYPE);
- gpu_state_print_fl(GL_COLOR_CLEAR_VALUE);
- gpu_state_print_fl(GL_COLOR_LOGIC_OP);
- gpu_state_print_fl(GL_COLOR_MATERIAL);
- gpu_state_print_fl(GL_COLOR_MATERIAL_FACE);
- gpu_state_print_fl(GL_COLOR_MATERIAL_PARAMETER);
- gpu_state_print_fl(GL_COLOR_MATRIX);
- gpu_state_print_fl(GL_COLOR_MATRIX_STACK_DEPTH);
- gpu_state_print_fl(GL_COLOR_SUM);
- gpu_state_print_fl(GL_COLOR_TABLE);
- gpu_state_print_fl(GL_COLOR_WRITEMASK);
- gpu_state_print_fl(GL_NUM_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_CONVOLUTION_1D);
- gpu_state_print_fl(GL_CONVOLUTION_2D);
- gpu_state_print_fl(GL_CULL_FACE);
- gpu_state_print_fl(GL_CULL_FACE_MODE);
- gpu_state_print_fl(GL_CURRENT_COLOR);
- gpu_state_print_fl(GL_CURRENT_FOG_COORD);
- gpu_state_print_fl(GL_CURRENT_INDEX);
- gpu_state_print_fl(GL_CURRENT_NORMAL);
- gpu_state_print_fl(GL_CURRENT_PROGRAM);
- gpu_state_print_fl(GL_CURRENT_RASTER_COLOR);
- gpu_state_print_fl(GL_CURRENT_RASTER_DISTANCE);
- gpu_state_print_fl(GL_CURRENT_RASTER_INDEX);
- gpu_state_print_fl(GL_CURRENT_RASTER_POSITION);
- gpu_state_print_fl(GL_CURRENT_RASTER_POSITION_VALID);
- gpu_state_print_fl(GL_CURRENT_RASTER_SECONDARY_COLOR);
- gpu_state_print_fl(GL_CURRENT_RASTER_TEXTURE_COORDS);
- gpu_state_print_fl(GL_CURRENT_SECONDARY_COLOR);
- gpu_state_print_fl(GL_CURRENT_TEXTURE_COORDS);
- gpu_state_print_fl(GL_DEPTH_BIAS);
- gpu_state_print_fl(GL_DEPTH_BITS);
- gpu_state_print_fl(GL_DEPTH_CLEAR_VALUE);
- gpu_state_print_fl(GL_DEPTH_FUNC);
- gpu_state_print_fl(GL_DEPTH_RANGE);
- gpu_state_print_fl(GL_DEPTH_SCALE);
- gpu_state_print_fl(GL_DEPTH_TEST);
- gpu_state_print_fl(GL_DEPTH_WRITEMASK);
- gpu_state_print_fl(GL_DITHER);
- gpu_state_print_fl(GL_DOUBLEBUFFER);
- gpu_state_print_fl(GL_DRAW_BUFFER);
- gpu_state_print_fl(GL_DRAW_BUFFER0);
- gpu_state_print_fl(GL_EDGE_FLAG);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_STRIDE);
- gpu_state_print_fl(GL_ELEMENT_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_FEEDBACK_BUFFER_SIZE);
- gpu_state_print_fl(GL_FEEDBACK_BUFFER_TYPE);
- gpu_state_print_fl(GL_FOG);
- gpu_state_print_fl(GL_FOG_COLOR);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_STRIDE);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_TYPE);
- gpu_state_print_fl(GL_FOG_COORD_SRC);
- gpu_state_print_fl(GL_FOG_DENSITY);
- gpu_state_print_fl(GL_FOG_END);
- gpu_state_print_fl(GL_FOG_HINT);
- gpu_state_print_fl(GL_FOG_INDEX);
- gpu_state_print_fl(GL_FOG_MODE);
- gpu_state_print_fl(GL_FOG_START);
- gpu_state_print_fl(GL_FRAGMENT_PROGRAM_ARB); /* TODO: remove ARB program support */
- gpu_state_print_fl(GL_FRAGMENT_SHADER_DERIVATIVE_HINT);
- gpu_state_print_fl(GL_FRONT_FACE);
- gpu_state_print_fl(GL_GENERATE_MIPMAP_HINT);
- gpu_state_print_fl(GL_GREEN_BIAS);
- gpu_state_print_fl(GL_GREEN_BITS);
- gpu_state_print_fl(GL_GREEN_SCALE);
- gpu_state_print_fl(GL_HISTOGRAM);
- gpu_state_print_fl(GL_INDEX_ARRAY);
- gpu_state_print_fl(GL_INDEX_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_INDEX_ARRAY_STRIDE);
- gpu_state_print_fl(GL_INDEX_ARRAY_TYPE);
- gpu_state_print_fl(GL_INDEX_BITS);
- gpu_state_print_fl(GL_INDEX_CLEAR_VALUE);
- gpu_state_print_fl(GL_INDEX_LOGIC_OP);
- gpu_state_print_fl(GL_INDEX_MODE);
- gpu_state_print_fl(GL_INDEX_OFFSET);
- gpu_state_print_fl(GL_INDEX_SHIFT);
- gpu_state_print_fl(GL_INDEX_WRITEMASK);
- gpu_state_print_fl(GL_LIGHT0);
- gpu_state_print_fl(GL_LIGHT1);
- gpu_state_print_fl(GL_LIGHT2);
- gpu_state_print_fl(GL_LIGHT3);
- gpu_state_print_fl(GL_LIGHT4);
- gpu_state_print_fl(GL_LIGHT5);
- gpu_state_print_fl(GL_LIGHT6);
- gpu_state_print_fl(GL_LIGHT7);
- gpu_state_print_fl(GL_LIGHTING);
- gpu_state_print_fl(GL_LIGHT_MODEL_AMBIENT);
- gpu_state_print_fl(GL_LIGHT_MODEL_COLOR_CONTROL);
- gpu_state_print_fl(GL_LIGHT_MODEL_LOCAL_VIEWER);
- gpu_state_print_fl(GL_LIGHT_MODEL_TWO_SIDE);
- gpu_state_print_fl(GL_LINE_SMOOTH);
- gpu_state_print_fl(GL_LINE_SMOOTH_HINT);
- gpu_state_print_fl(GL_LINE_STIPPLE);
- gpu_state_print_fl(GL_LINE_STIPPLE_PATTERN);
- gpu_state_print_fl(GL_LINE_STIPPLE_REPEAT);
- gpu_state_print_fl(GL_LINE_WIDTH);
- gpu_state_print_fl(GL_LINE_WIDTH_GRANULARITY);
- gpu_state_print_fl(GL_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_LIST_BASE);
- gpu_state_print_fl(GL_LIST_INDEX);
- gpu_state_print_fl(GL_LIST_MODE);
- gpu_state_print_fl(GL_LOGIC_OP);
- gpu_state_print_fl(GL_LOGIC_OP_MODE);
- gpu_state_print_fl(GL_MAP1_COLOR_4);
- gpu_state_print_fl(GL_MAP1_GRID_DOMAIN);
- gpu_state_print_fl(GL_MAP1_GRID_SEGMENTS);
- gpu_state_print_fl(GL_MAP1_INDEX);
- gpu_state_print_fl(GL_MAP1_NORMAL);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_1);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_2);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_3);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_4);
- gpu_state_print_fl(GL_MAP1_VERTEX_3);
- gpu_state_print_fl(GL_MAP1_VERTEX_4);
- gpu_state_print_fl(GL_MAP2_COLOR_4);
- gpu_state_print_fl(GL_MAP2_GRID_DOMAIN);
- gpu_state_print_fl(GL_MAP2_GRID_SEGMENTS);
- gpu_state_print_fl(GL_MAP2_INDEX);
- gpu_state_print_fl(GL_MAP2_NORMAL);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_1);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_2);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_3);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_4);
- gpu_state_print_fl(GL_MAP2_VERTEX_3);
- gpu_state_print_fl(GL_MAP2_VERTEX_4);
- gpu_state_print_fl(GL_MAP_COLOR);
- gpu_state_print_fl(GL_MAP_STENCIL);
- gpu_state_print_fl(GL_MATRIX_MODE);
- gpu_state_print_fl(GL_MAX_3D_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_CLIP_PLANES);
- gpu_state_print_fl(GL_MAX_COLOR_MATRIX_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_CUBE_MAP_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_DRAW_BUFFERS);
- gpu_state_print_fl(GL_MAX_ELEMENTS_INDICES);
- gpu_state_print_fl(GL_MAX_ELEMENTS_VERTICES);
- gpu_state_print_fl(GL_MAX_EVAL_ORDER);
- gpu_state_print_fl(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
- gpu_state_print_fl(GL_MAX_LIGHTS);
- gpu_state_print_fl(GL_MAX_LIST_NESTING);
- gpu_state_print_fl(GL_MAX_MODELVIEW_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_NAME_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_PIXEL_MAP_TABLE);
- gpu_state_print_fl(GL_MAX_PROJECTION_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_TEXTURE_COORDS);
- gpu_state_print_fl(GL_MAX_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_TEXTURE_LOD_BIAS);
- gpu_state_print_fl(GL_MAX_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_TEXTURE_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_TEXTURE_UNITS);
- gpu_state_print_fl(GL_MAX_VARYING_FLOATS);
- gpu_state_print_fl(GL_MAX_VERTEX_ATTRIBS);
- gpu_state_print_fl(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
- gpu_state_print_fl(GL_MAX_VIEWPORT_DIMS);
- gpu_state_print_fl(GL_MINMAX);
- gpu_state_print_fl(GL_MODELVIEW_MATRIX);
- gpu_state_print_fl(GL_MODELVIEW_STACK_DEPTH);
- gpu_state_print_fl(GL_MULTISAMPLE);
- gpu_state_print_fl(GL_NAME_STACK_DEPTH);
- gpu_state_print_fl(GL_NORMALIZE);
- gpu_state_print_fl(GL_NORMAL_ARRAY);
- gpu_state_print_fl(GL_NORMAL_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_NORMAL_ARRAY_STRIDE);
- gpu_state_print_fl(GL_NORMAL_ARRAY_TYPE);
- gpu_state_print_fl(GL_NUM_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_PACK_ALIGNMENT);
- gpu_state_print_fl(GL_PACK_IMAGE_HEIGHT);
- gpu_state_print_fl(GL_PACK_LSB_FIRST);
- gpu_state_print_fl(GL_PACK_ROW_LENGTH);
- gpu_state_print_fl(GL_PACK_SKIP_IMAGES);
- gpu_state_print_fl(GL_PACK_SKIP_PIXELS);
- gpu_state_print_fl(GL_PACK_SKIP_ROWS);
- gpu_state_print_fl(GL_PACK_SWAP_BYTES);
- gpu_state_print_fl(GL_PERSPECTIVE_CORRECTION_HINT);
- gpu_state_print_fl(GL_PIXEL_MAP_A_TO_A_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_B_TO_B_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_G_TO_G_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_A_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_B_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_G_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_I_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_R_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_R_TO_R_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_S_TO_S_SIZE);
- gpu_state_print_fl(GL_PIXEL_PACK_BUFFER_BINDING);
- gpu_state_print_fl(GL_PIXEL_UNPACK_BUFFER_BINDING);
- gpu_state_print_fl(GL_POINT_DISTANCE_ATTENUATION);
- gpu_state_print_fl(GL_POINT_FADE_THRESHOLD_SIZE);
- gpu_state_print_fl(GL_POINT_SIZE);
- gpu_state_print_fl(GL_POINT_SIZE_GRANULARITY);
- gpu_state_print_fl(GL_POINT_SIZE_MAX);
- gpu_state_print_fl(GL_POINT_SIZE_MIN);
- gpu_state_print_fl(GL_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_POINT_SMOOTH);
- gpu_state_print_fl(GL_POINT_SMOOTH_HINT);
- gpu_state_print_fl(GL_POINT_SPRITE);
- gpu_state_print_fl(GL_POLYGON_MODE);
- gpu_state_print_fl(GL_POLYGON_OFFSET_FACTOR);
- gpu_state_print_fl(GL_POLYGON_OFFSET_FILL);
- gpu_state_print_fl(GL_POLYGON_OFFSET_LINE);
- gpu_state_print_fl(GL_POLYGON_OFFSET_POINT);
- gpu_state_print_fl(GL_POLYGON_OFFSET_UNITS);
- gpu_state_print_fl(GL_POLYGON_SMOOTH);
- gpu_state_print_fl(GL_POLYGON_SMOOTH_HINT);
- gpu_state_print_fl(GL_POLYGON_STIPPLE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_COLOR_TABLE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_COLOR_TABLE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_RED_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_RED_SCALE);
- gpu_state_print_fl(GL_PROJECTION_MATRIX);
- gpu_state_print_fl(GL_PROJECTION_STACK_DEPTH);
- gpu_state_print_fl(GL_READ_BUFFER);
- gpu_state_print_fl(GL_RED_BIAS);
- gpu_state_print_fl(GL_RED_BITS);
- gpu_state_print_fl(GL_RED_SCALE);
- gpu_state_print_fl(GL_RENDER_MODE);
- gpu_state_print_fl(GL_RESCALE_NORMAL);
- gpu_state_print_fl(GL_RGBA_MODE);
- gpu_state_print_fl(GL_SAMPLES);
- gpu_state_print_fl(GL_SAMPLE_BUFFERS);
- gpu_state_print_fl(GL_SAMPLE_COVERAGE_INVERT);
- gpu_state_print_fl(GL_SAMPLE_COVERAGE_VALUE);
- gpu_state_print_fl(GL_SCISSOR_BOX);
- gpu_state_print_fl(GL_SCISSOR_TEST);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_SIZE);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_STRIDE);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_TYPE);
- gpu_state_print_fl(GL_SELECTION_BUFFER_SIZE);
- gpu_state_print_fl(GL_SEPARABLE_2D);
- gpu_state_print_fl(GL_SHADE_MODEL);
- gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_GRANULARITY);
- gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_GRANULARITY);
- gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_STENCIL_BACK_FAIL);
- gpu_state_print_fl(GL_STENCIL_BACK_FUNC);
- gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_FAIL);
- gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_PASS);
- gpu_state_print_fl(GL_STENCIL_BACK_REF);
- gpu_state_print_fl(GL_STENCIL_BACK_VALUE_MASK);
- gpu_state_print_fl(GL_STENCIL_BACK_WRITEMASK);
- gpu_state_print_fl(GL_STENCIL_BITS);
- gpu_state_print_fl(GL_STENCIL_CLEAR_VALUE);
- gpu_state_print_fl(GL_STENCIL_FAIL);
- gpu_state_print_fl(GL_STENCIL_FUNC);
- gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_FAIL);
- gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_PASS);
- gpu_state_print_fl(GL_STENCIL_REF);
- gpu_state_print_fl(GL_STENCIL_TEST);
- gpu_state_print_fl(GL_STENCIL_VALUE_MASK);
- gpu_state_print_fl(GL_STENCIL_WRITEMASK);
- gpu_state_print_fl(GL_STEREO);
- gpu_state_print_fl(GL_SUBPIXEL_BITS);
- gpu_state_print_fl(GL_TEXTURE_1D);
- gpu_state_print_fl(GL_TEXTURE_2D);
- gpu_state_print_fl(GL_TEXTURE_3D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_1D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_2D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_3D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_CUBE_MAP);
- gpu_state_print_fl(GL_TEXTURE_COMPRESSION_HINT);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_SIZE);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_STRIDE);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_TYPE);
- gpu_state_print_fl(GL_TEXTURE_CUBE_MAP);
- gpu_state_print_fl(GL_TEXTURE_GEN_Q);
- gpu_state_print_fl(GL_TEXTURE_GEN_R);
- gpu_state_print_fl(GL_TEXTURE_GEN_S);
- gpu_state_print_fl(GL_TEXTURE_GEN_T);
- gpu_state_print_fl(GL_TEXTURE_MATRIX);
- gpu_state_print_fl(GL_TEXTURE_STACK_DEPTH);
- gpu_state_print_fl(GL_TRANSPOSE_COLOR_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_MODELVIEW_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_PROJECTION_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_TEXTURE_MATRIX);
- gpu_state_print_fl(GL_UNPACK_ALIGNMENT);
- gpu_state_print_fl(GL_UNPACK_IMAGE_HEIGHT);
- gpu_state_print_fl(GL_UNPACK_LSB_FIRST);
- gpu_state_print_fl(GL_UNPACK_ROW_LENGTH);
- gpu_state_print_fl(GL_UNPACK_SKIP_IMAGES);
- gpu_state_print_fl(GL_UNPACK_SKIP_PIXELS);
- gpu_state_print_fl(GL_UNPACK_SKIP_ROWS);
- gpu_state_print_fl(GL_UNPACK_SWAP_BYTES);
- gpu_state_print_fl(GL_VERTEX_ARRAY);
- gpu_state_print_fl(GL_VERTEX_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_VERTEX_ARRAY_SIZE);
- gpu_state_print_fl(GL_VERTEX_ARRAY_STRIDE);
- gpu_state_print_fl(GL_VERTEX_ARRAY_TYPE);
- gpu_state_print_fl(GL_VERTEX_PROGRAM_POINT_SIZE);
- gpu_state_print_fl(GL_VERTEX_PROGRAM_TWO_SIDE);
- gpu_state_print_fl(GL_VIEWPORT);
- gpu_state_print_fl(GL_ZOOM_X);
- gpu_state_print_fl(GL_ZOOM_Y);
-}
-
-#undef gpu_state_print_fl
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 514f2f71bd7..7bfebb702a1 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -31,15 +31,13 @@
* Utility functions for dealing with OpenGL texture & material context,
* mipmap generation and light objects.
*
- * These are some obscure rendering functions shared between the
- * game engine and the blender, in this module to avoid duplication
+ * These are some obscure rendering functions shared between the game engine (not anymore)
+ * and the blender, in this module to avoid duplication
* and abstract them away from the rest a bit.
*/
#include <string.h>
-#include "GPU_glew.h"
-
#include "BLI_blenlib.h"
#include "BLI_hash.h"
#include "BLI_linklist.h"
@@ -72,15 +70,12 @@
#include "BKE_node.h"
#include "BKE_scene.h"
#include "BKE_DerivedMesh.h"
-#ifdef WITH_GAMEENGINE
-# include "BKE_object.h"
-#endif
#include "GPU_basic_shader.h"
-#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_material.h"
+#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -99,141 +94,20 @@
extern Material defmaterial; /* from material.c */
-/* Text Rendering */
-
-static void gpu_mcol(unsigned int ucol)
-{
- /* mcol order is swapped */
- const char *cp = (char *)&ucol;
- glColor3ub(cp[3], cp[2], cp[1]);
-}
-
-void GPU_render_text(
- MTexPoly *mtexpoly, int mode,
- const char *textstr, int textlen, unsigned int *col,
- const float *v_quad[4], const float *uv_quad[4],
- int glattrib)
-{
- if ((mode & GEMAT_TEXT) && (textlen > 0) && mtexpoly->tpage) {
- const float *v1 = v_quad[0];
- const float *v2 = v_quad[1];
- const float *v3 = v_quad[2];
- const float *v4 = v_quad[3];
- Image *ima = (Image *)mtexpoly->tpage;
- const size_t textlen_st = textlen;
- float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
-
- /* multiline */
- float line_start = 0.0f, line_height;
-
- if (v4)
- line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]);
- else
- line_height = max_fff(v1[1], v2[1], v3[1]) - min_fff(v1[1], v2[1], v3[1]);
- line_height *= 1.2f; /* could be an option? */
- /* end multiline */
-
-
- /* color has been set */
- if (mtexpoly->mode & TF_OBCOL)
- col = NULL;
- else if (!col)
- glColor3f(1.0f, 1.0f, 1.0f);
-
- glPushMatrix();
-
- /* get the tab width */
- ImBuf *first_ibuf = BKE_image_get_first_ibuf(ima);
- matrixGlyph(first_ibuf, ' ', &centerx, &centery,
- &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
-
- float advance_tab = advance * 4; /* tab width could also be an option */
-
-
- for (size_t index = 0; index < textlen_st; ) {
- unsigned int character;
- float uv[4][2];
-
- /* lets calculate offset stuff */
- character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index);
-
- if (character == '\n') {
- glTranslatef(line_start, -line_height, 0.0f);
- line_start = 0.0f;
- continue;
- }
- else if (character == '\t') {
- glTranslatef(advance_tab, 0.0f, 0.0f);
- line_start -= advance_tab; /* so we can go back to the start of the line */
- continue;
-
- }
- else if (character > USHRT_MAX) {
- /* not much we can do here bmfonts take ushort */
- character = '?';
- }
-
- /* space starts at offset 1 */
- /* character = character - ' ' + 1; */
- matrixGlyph(first_ibuf, character, & centerx, &centery,
- &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
-
- uv[0][0] = (uv_quad[0][0] - centerx) * sizex + transx;
- uv[0][1] = (uv_quad[0][1] - centery) * sizey + transy;
- uv[1][0] = (uv_quad[1][0] - centerx) * sizex + transx;
- uv[1][1] = (uv_quad[1][1] - centery) * sizey + transy;
- uv[2][0] = (uv_quad[2][0] - centerx) * sizex + transx;
- uv[2][1] = (uv_quad[2][1] - centery) * sizey + transy;
-
- glBegin(GL_POLYGON);
- if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[0]);
- else glTexCoord2fv(uv[0]);
- if (col) gpu_mcol(col[0]);
- glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
-
- if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[1]);
- else glTexCoord2fv(uv[1]);
- if (col) gpu_mcol(col[1]);
- glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
-
- if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[2]);
- else glTexCoord2fv(uv[2]);
- if (col) gpu_mcol(col[2]);
- glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
-
- if (v4) {
- uv[3][0] = (uv_quad[3][0] - centerx) * sizex + transx;
- uv[3][1] = (uv_quad[3][1] - centery) * sizey + transy;
-
- if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[3]);
- else glTexCoord2fv(uv[3]);
- if (col) gpu_mcol(col[3]);
- glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
- }
- glEnd();
-
- glTranslatef(advance, 0.0f, 0.0f);
- line_start -= advance; /* so we can go back to the start of the line */
- }
- glPopMatrix();
-
- BKE_image_release_ibuf(ima, first_ibuf, NULL);
- }
-}
-
-/* Checking powers of two for images since OpenGL ES requires it */
-
+//* Checking powers of two for images since OpenGL ES requires it */
+#ifdef WITH_DDS
static bool is_power_of_2_resolution(int w, int h)
{
return is_power_of_2_i(w) && is_power_of_2_i(h);
}
+#endif
static bool is_over_resolution_limit(GLenum textarget, int w, int h)
{
int size = (textarget == GL_TEXTURE_2D) ?
GPU_max_texture_size() : GPU_max_cube_map_size();
int reslimit = (U.glreslimit != 0) ?
- min_ii(U.glreslimit, size) : size;
+ min_ii(U.glreslimit, size) : size;
return (w > reslimit || h > reslimit);
}
@@ -253,10 +127,6 @@ static int smaller_power_of_2_limit(int num)
/* Current OpenGL state caching for GPU_set_tpage */
static struct GPUTextureState {
- int curtile, tile;
- int curtilemode, tilemode;
- int curtileXRep, tileXRep;
- int curtileYRep, tileYRep;
Image *ima, *curima;
/* also controls min/mag filtering */
@@ -269,8 +139,7 @@ static struct GPUTextureState {
int alphablend;
float anisotropic;
int gpu_mipmap;
- MTexPoly *lasttface;
-} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.0f, 0, NULL};
+} GTS = {NULL, NULL, 1, 0, 0, -1, 1.0f, 0};
/* Mipmap settings */
@@ -279,36 +148,13 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap)
int old_value = GTS.gpu_mipmap;
/* only actually enable if it's supported */
- GTS.gpu_mipmap = gpu_mipmap && GLEW_EXT_framebuffer_object;
+ GTS.gpu_mipmap = gpu_mipmap;
if (old_value != GTS.gpu_mipmap) {
GPU_free_images();
}
}
-static 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;
-
- /* 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) {
- target_enabled = glIsEnabled(target);
- if (!target_enabled)
- glEnable(target);
- }
-
- /* TODO: simplify when we transition to GL >= 3 */
- if (GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object)
- glGenerateMipmap(target);
- else if (GLEW_EXT_framebuffer_object)
- glGenerateMipmapEXT(target);
-
- if (is_ati && !target_enabled)
- glDisable(target);
-}
-
void GPU_set_mipmap(bool mipmap)
{
if (GTS.domipmap != mipmap) {
@@ -381,28 +227,6 @@ float GPU_get_anisotropic(void)
/* Set OpenGL state for an MTFace */
-static void gpu_make_repbind(Image *ima)
-{
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- if (ibuf == NULL)
- return;
-
- if (ima->repbind) {
- glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
- MEM_freeN(ima->repbind);
- ima->repbind = NULL;
- ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
- }
-
- ima->totbind = ima->xrep * ima->yrep;
-
- if (ima->totbind > 1) {
- ima->repbind = MEM_callocN(sizeof(int) * ima->totbind, "repbind");
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
-}
-
static unsigned int *gpu_get_image_bindcode(Image *ima, GLenum textarget)
{
unsigned int *bind = 0;
@@ -415,104 +239,6 @@ static unsigned int *gpu_get_image_bindcode(Image *ima, GLenum textarget)
return bind;
}
-void GPU_clear_tpage(bool force)
-{
- if (GTS.lasttface == NULL && !force)
- return;
-
- GTS.lasttface = NULL;
- GTS.curtile = 0;
- GTS.curima = NULL;
- if (GTS.curtilemode != 0) {
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- }
- GTS.curtilemode = 0;
- GTS.curtileXRep = 0;
- GTS.curtileYRep = 0;
- GTS.alphablend = -1;
-
- glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_TEXTURE_GEN_S);
- glDisable(GL_TEXTURE_GEN_T);
- glDisable(GL_ALPHA_TEST);
-}
-
-static void gpu_set_alpha_blend(GPUBlendMode alphablend)
-{
- if (alphablend == GPU_BLEND_SOLID) {
- glDisable(GL_BLEND);
- glDisable(GL_ALPHA_TEST);
- glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- else if (alphablend == GPU_BLEND_ADD) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
- glDisable(GL_ALPHA_TEST);
- glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- }
- else if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ALPHA_SORT)) {
- glEnable(GL_BLEND);
- glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
-
- /* for OpenGL render we use the alpha channel, this makes alpha blend correct */
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-
- /* if U.glalphaclip == 1.0, some cards go bonkers...
- * turn off alpha test in this case */
-
- /* added after 2.45 to clip alpha */
- if (U.glalphaclip == 1.0f) {
- glDisable(GL_ALPHA_TEST);
- }
- else {
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, U.glalphaclip);
- }
- }
- else if (alphablend == GPU_BLEND_CLIP) {
- glDisable(GL_BLEND);
- glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, 0.5f);
- }
- else if (alphablend == GPU_BLEND_ALPHA_TO_COVERAGE) {
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, U.glalphaclip);
- glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- }
-}
-
-static void gpu_verify_alpha_blend(int alphablend)
-{
- /* verify alpha blending modes */
- if (GTS.alphablend == alphablend)
- return;
-
- gpu_set_alpha_blend(alphablend);
- GTS.alphablend = alphablend;
-}
-
-static void gpu_verify_reflection(Image *ima)
-{
- if (ima && (ima->flag & IMA_REFLECT)) {
- /* enable reflection mapping */
- glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
- glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
-
- glEnable(GL_TEXTURE_GEN_S);
- glEnable(GL_TEXTURE_GEN_T);
- }
- else {
- /* disable reflection mapping */
- glDisable(GL_TEXTURE_GEN_S);
- glDisable(GL_TEXTURE_GEN_T);
- }
-}
-
typedef struct VerifyThreadData {
ImBuf *ibuf;
float *srgb_frect;
@@ -534,8 +260,6 @@ static void gpu_verify_high_bit_srgb_buffer_slice(float *srgb_frect,
ibuf->x, height,
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);
}
static void verify_thread_do(void *data_v,
@@ -567,7 +291,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, bool compare, bool mipmap, bool is_data)
{
unsigned int *bind = NULL;
int tpx = 0, tpy = 0;
@@ -577,46 +301,12 @@ int GPU_verify_image(
/* flag to determine whether deep format is used */
bool use_high_bit_depth = false, do_color_management = false;
- /* initialize tile mode and number of repeats */
GTS.ima = ima;
- GTS.tilemode = (ima && (ima->tpageflag & (IMA_TILES | IMA_TWINANIM)));
- GTS.tileXRep = 0;
- GTS.tileYRep = 0;
-
- /* setting current tile according to frame */
- if (ima && (ima->tpageflag & IMA_TWINANIM))
- GTS.tile = ima->lastframe;
- else
- GTS.tile = tftile;
-
- GTS.tile = MAX2(0, GTS.tile);
-
- if (ima) {
- GTS.tileXRep = ima->xrep;
- GTS.tileYRep = ima->yrep;
- }
- /* if same image & tile, we're done */
- if (compare && ima == GTS.curima && GTS.curtile == GTS.tile &&
- GTS.tilemode == GTS.curtilemode && GTS.curtileXRep == GTS.tileXRep &&
- GTS.curtileYRep == GTS.tileYRep)
- {
+ if (compare && ima == GTS.curima) {
return (ima != NULL);
}
- /* if tiling mode or repeat changed, change texture matrix to fit */
- if (GTS.tilemode != GTS.curtilemode || GTS.curtileXRep != GTS.tileXRep ||
- GTS.curtileYRep != GTS.tileYRep)
- {
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
-
- if (ima && (ima->tpageflag & IMA_TILES))
- glScalef(ima->xrep, ima->yrep, 1.0f);
-
- glMatrixMode(GL_MODELVIEW);
- }
-
/* check if we have a valid image */
if (ima == NULL || ima->ok == 0)
return 0;
@@ -652,48 +342,8 @@ int GPU_verify_image(
GPU_free_image(ima);
ima->tpageflag &= ~IMA_TPAGE_REFRESH;
}
-
- if (GTS.tilemode) {
- /* tiled mode */
- if (ima->repbind == NULL) gpu_make_repbind(ima);
- if (GTS.tile >= ima->totbind) GTS.tile = 0;
-
- /* this happens when you change repeat buttons */
- if (ima->repbind && textarget == GL_TEXTURE_2D) bind = &ima->repbind[GTS.tile];
- else bind = gpu_get_image_bindcode(ima, textarget);
-
- if (*bind == 0) {
- short texwindx = ibuf->x / ima->xrep;
- short texwindy = ibuf->y / ima->yrep;
-
- if (GTS.tile >= ima->xrep * ima->yrep)
- GTS.tile = ima->xrep * ima->yrep - 1;
-
- short texwinsy = GTS.tile / ima->xrep;
- short texwinsx = GTS.tile - texwinsy * ima->xrep;
-
- texwinsx *= texwindx;
- texwinsy *= texwindy;
-
- tpx = texwindx;
- tpy = texwindy;
- if (use_high_bit_depth) {
- if (do_color_management) {
- srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "floar_buf_col_cor");
- gpu_verify_high_bit_srgb_buffer(srgb_frect, ibuf);
- frect = srgb_frect + (4 * (texwinsy * ibuf->x + texwinsx));
- }
- else {
- frect = ibuf->rect_float + (ibuf->channels * (texwinsy * ibuf->x + texwinsx));
- }
- }
- else {
- rect = ibuf->rect + texwinsy * ibuf->x + texwinsx;
- }
- }
- }
- else {
+ {
/* regular image mode */
bind = gpu_get_image_bindcode(ima, textarget);
@@ -722,57 +372,22 @@ int GPU_verify_image(
const int rectw = tpx;
const int recth = tpy;
- unsigned *tilerect = NULL;
- float *ftilerect = NULL;
-
- /* for tiles, copy only part of image into buffer */
- if (GTS.tilemode) {
- if (use_high_bit_depth) {
- ftilerect = MEM_mallocN(rectw * recth * sizeof(*ftilerect), "tilerect");
-
- for (int y = 0; y < recth; y++) {
- const float *frectrow = &frect[y * ibuf->x];
- float *ftilerectrow = &ftilerect[y * rectw];
-
- memcpy(ftilerectrow, frectrow, tpx * sizeof(*frectrow));
- }
-
- frect = ftilerect;
- }
- else {
- tilerect = MEM_mallocN(rectw * recth * sizeof(*tilerect), "tilerect");
-
- for (int y = 0; y < recth; y++) {
- const unsigned *rectrow = &rect[y * ibuf->x];
- unsigned *tilerectrow = &tilerect[y * rectw];
-
- memcpy(tilerectrow, rectrow, tpx * sizeof(*rectrow));
- }
-
- rect = tilerect;
- }
- }
-
#ifdef WITH_DDS
if (ibuf->ftype == IMB_FTYPE_DDS)
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);
-
+
/* mark as non-color data texture */
if (*bind) {
if (is_data)
- ima->tpageflag |= IMA_GLBIND_IS_DATA;
+ ima->tpageflag |= IMA_GLBIND_IS_DATA;
else
- ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
+ ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
}
/* clean up */
- if (tilerect)
- MEM_freeN(tilerect);
- if (ftilerect)
- MEM_freeN(ftilerect);
if (srgb_frect)
MEM_freeN(srgb_frect);
@@ -858,30 +473,6 @@ void GPU_create_gl_tex(
int tpx = rectw;
int tpy = recth;
- /* scale if not a power of two. this is not strictly necessary for newer
- * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures
- * 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)) ||
- is_over_resolution_limit(textarget, rectw, recth)))
- {
- rectw = smaller_power_of_2_limit(rectw);
- recth = smaller_power_of_2_limit(recth);
-
- if (use_high_bit_depth) {
- ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
- IMB_scaleImBuf(ibuf, rectw, recth);
-
- frect = ibuf->rect_float;
- }
- else {
- ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
- IMB_scaleImBuf(ibuf, rectw, recth);
-
- rect = ibuf->rect;
- }
- }
-
/* create image */
glGenTextures(1, (GLuint *)bind);
glBindTexture(textarget, *bind);
@@ -889,7 +480,7 @@ void GPU_create_gl_tex(
if (textarget == GL_TEXTURE_2D) {
if (use_high_bit_depth) {
if (GLEW_ARB_texture_float)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
}
@@ -900,7 +491,7 @@ void GPU_create_gl_tex(
if (GPU_get_mipmap() && mipmap) {
if (GTS.gpu_mipmap) {
- gpu_generate_mipmap(GL_TEXTURE_2D);
+ glGenerateMipmap(GL_TEXTURE_2D);
}
else {
int i;
@@ -918,7 +509,7 @@ void GPU_create_gl_tex(
ImBuf *mip = ibuf->mipmap[i - 1];
if (use_high_bit_depth) {
if (GLEW_ARB_texture_float)
- glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F_ARB, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
else
glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
}
@@ -940,7 +531,7 @@ void GPU_create_gl_tex(
if (h == w && is_power_of_2_i(h) && !is_over_resolution_limit(textarget, h, w)) {
void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth, use_high_bit_depth);
- GLenum informat = use_high_bit_depth ? (GLEW_ARB_texture_float ? GL_RGBA16F_ARB : GL_RGBA16) : GL_RGBA8;
+ GLenum informat = use_high_bit_depth ? (GLEW_ARB_texture_float ? GL_RGBA16F : GL_RGBA16) : GL_RGBA8;
GLenum type = use_high_bit_depth ? GL_FLOAT : GL_UNSIGNED_BYTE;
if (cube_map)
@@ -951,7 +542,7 @@ void GPU_create_gl_tex(
if (GPU_get_mipmap() && mipmap) {
if (GTS.gpu_mipmap) {
- gpu_generate_mipmap(GL_TEXTURE_CUBE_MAP);
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
}
else {
if (!ibuf) {
@@ -975,7 +566,7 @@ void GPU_create_gl_tex(
if (mip_cube_map) {
for (int j = 0; j < 6; j++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i,
- informat, mipw, miph, 0, GL_RGBA, type, mip_cube_map[j]);
+ informat, mipw, miph, 0, GL_RGBA, type, mip_cube_map[j]);
}
}
gpu_del_cube_map(mip_cube_map);
@@ -1056,7 +647,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
size = ((width + 3) / 4) * ((height + 3) / 4) * blocksize;
glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height,
- 0, size, ibuf->dds_data.data + offset);
+ 0, size, ibuf->dds_data.data + offset);
offset += size;
width >>= 1;
@@ -1091,62 +682,6 @@ void GPU_create_gl_tex_compressed(
}
#endif
}
-static void gpu_verify_repeat(Image *ima)
-{
- /* set either clamp or repeat in X/Y */
- if (ima->tpageflag & IMA_CLAMP_U)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- else
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-
- if (ima->tpageflag & IMA_CLAMP_V)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- else
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-}
-
-int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend)
-{
- /* check if we need to clear the state */
- if (mtexpoly == NULL) {
- GPU_clear_tpage(false);
- return 0;
- }
-
- Image *ima = mtexpoly->tpage;
- GTS.lasttface = mtexpoly;
-
- gpu_verify_alpha_blend(alphablend);
- gpu_verify_reflection(ima);
-
- if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, mtexpoly->tile, 1, mipmap, false)) {
- GTS.curtile = GTS.tile;
- GTS.curima = GTS.ima;
- GTS.curtilemode = GTS.tilemode;
- GTS.curtileXRep = GTS.tileXRep;
- GTS.curtileYRep = GTS.tileYRep;
-
- glEnable(GL_TEXTURE_2D);
- }
- else {
- glDisable(GL_TEXTURE_2D);
-
- GTS.curtile = 0;
- GTS.curima = NULL;
- GTS.curtilemode = 0;
- GTS.curtileXRep = 0;
- GTS.curtileYRep = 0;
-
- return 0;
- }
-
- gpu_verify_repeat(ima);
-
- /* Did this get lost in the image recode? */
- /* BKE_image_tag_time(ima);*/
-
- return 1;
-}
/* these two functions are called on entering and exiting texture paint mode,
* temporary disabling/enabling mipmapping on all images for quick texture
@@ -1206,9 +741,7 @@ void GPU_paint_set_mipmap(bool mipmap)
/* check if image has been downscaled and do scaled partial update */
static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
{
- if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) ||
- is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y))
- {
+ if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) {
int x_limit = smaller_power_of_2_limit(ibuf->x);
int y_limit = smaller_power_of_2_limit(ibuf->y);
@@ -1261,7 +794,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);
+ glGenerateMipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -1277,8 +810,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
{
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
- if (ima->repbind ||
- (!GTS.gpu_mipmap && GPU_get_mipmap()) ||
+ if ((!GTS.gpu_mipmap && GPU_get_mipmap()) ||
(ima->bindcode[TEXTARGET_TEXTURE_2D] == 0) ||
(ibuf == NULL) ||
(w == 0) || (h == 0))
@@ -1296,7 +828,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf");
bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0;
IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
-
+
if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
MEM_freeN(buffer);
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -1311,7 +843,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);
+ glGenerateMipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -1337,7 +869,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
- GL_UNSIGNED_BYTE, ibuf->rect);
+ GL_UNSIGNED_BYTE, ibuf->rect);
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
@@ -1345,7 +877,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);
+ glGenerateMipmap(GL_TEXTURE_2D);
}
else {
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
@@ -1355,61 +887,6 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
BKE_image_release_ibuf(ima, ibuf, NULL);
}
-void GPU_update_images_framechange(void)
-{
- for (Image *ima = G.main->image.first; ima; ima = ima->id.next) {
- if (ima->tpageflag & IMA_TWINANIM) {
- if (ima->twend >= ima->xrep * ima->yrep)
- ima->twend = ima->xrep * ima->yrep - 1;
-
- /* check: is bindcode not in the array? free. (to do) */
-
- ima->lastframe++;
- if (ima->lastframe > ima->twend)
- ima->lastframe = ima->twsta;
- }
- }
-}
-
-int GPU_update_image_time(Image *ima, double time)
-{
- if (!ima)
- return 0;
-
- if (ima->lastupdate < 0)
- ima->lastupdate = 0;
-
- if (ima->lastupdate > (float)time)
- ima->lastupdate = (float)time;
-
- int inc = 0;
-
- if (ima->tpageflag & IMA_TWINANIM) {
- if (ima->twend >= ima->xrep * ima->yrep) ima->twend = ima->xrep * ima->yrep - 1;
-
- /* check: is the bindcode not in the array? Then free. (still to do) */
-
- float diff = (float)((float)time - ima->lastupdate);
- inc = (int)(diff * (float)ima->animspeed);
-
- ima->lastupdate += ((float)inc / (float)ima->animspeed);
-
- int newframe = ima->lastframe + inc;
-
- if (newframe > (int)ima->twend) {
- if (ima->twend - ima->twsta != 0)
- newframe = (int)ima->twsta - 1 + (newframe - ima->twend) % (ima->twend - ima->twsta);
- else
- newframe = ima->twsta;
- }
-
- ima->lastframe = newframe;
- }
-
- return inc;
-}
-
-
void GPU_free_smoke(SmokeModifierData *smd)
{
if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
@@ -1437,31 +914,60 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
if (smoke_has_colors(sds->fluid)) {
float *data = MEM_callocN(sizeof(float) * sds->total_cells * 4, "smokeColorTexture");
smoke_get_rgba(sds->fluid, data, 0);
- sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data);
+ sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], GPU_RGBA8, data, NULL);
MEM_freeN(data);
}
/* density only */
else {
- sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_density(sds->fluid));
+ sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2],
+ GPU_R8, smoke_get_density(sds->fluid), NULL);
+
+ /* Swizzle the RGBA components to read the Red channel so
+ * that the shader stay the same for colored and non color
+ * density textures. */
+ GPU_texture_bind(sds->tex, 0);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
+ GPU_texture_unbind(sds->tex);
}
- sds->tex_flame = (smoke_has_fuel(sds->fluid)) ? GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_flame(sds->fluid)) : NULL;
+ sds->tex_flame = (smoke_has_fuel(sds->fluid)) ?
+ GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2],
+ GPU_R8, smoke_get_flame(sds->fluid), NULL) :
+ NULL;
}
else if (!sds->tex && highres) {
/* rgba texture for color + density */
if (smoke_turbulence_has_colors(sds->wt)) {
float *data = MEM_callocN(sizeof(float) * smoke_turbulence_get_cells(sds->wt) * 4, "smokeColorTexture");
smoke_turbulence_get_rgba(sds->wt, data, 0);
- sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data);
+ sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], GPU_RGBA8, data, NULL);
MEM_freeN(data);
}
/* density only */
else {
- sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_density(sds->wt));
+ sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2],
+ GPU_R8, smoke_turbulence_get_density(sds->wt), NULL);
+
+ /* Swizzle the RGBA components to read the Red channel so
+ * that the shader stay the same for colored and non color
+ * density textures. */
+ GPU_texture_bind(sds->tex, 0);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
+ GPU_texture_unbind(sds->tex);
}
- sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ? GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_flame(sds->wt)) : NULL;
+ sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ?
+ GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2],
+ GPU_R8, smoke_turbulence_get_flame(sds->wt), NULL) :
+ NULL;
}
- sds->tex_shadow = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, sds->shadow);
+ sds->tex_shadow = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2],
+ GPU_R8, sds->shadow, NULL);
}
#else // WITH_SMOKE
(void)highres;
@@ -1499,9 +1005,6 @@ void GPU_free_unused_buffers(void)
BLI_linklist_free(image_free_queue, NULL);
image_free_queue = NULL;
- /* vbo buffers */
- GPU_global_buffer_pool_free_unused();
-
BLI_thread_unlock(LOCK_OPENGL);
}
@@ -1525,14 +1028,6 @@ void GPU_free_image(Image *ima)
}
}
- /* free repeated image binding */
- if (ima->repbind) {
- glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
-
- MEM_freeN(ima->repbind);
- ima->repbind = NULL;
- }
-
ima->tpageflag &= ~(IMA_MIPMAP_COMPLETE | IMA_GLBIND_IS_DATA);
}
@@ -1576,7 +1071,7 @@ void GPU_free_images_old(void)
if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) {
/* If it's in GL memory, deallocate and set time tag to current time
* This gives textures a "second chance" to be used before dying. */
- if (BKE_image_has_bindcode(ima) || ima->repbind) {
+ if (BKE_image_has_bindcode(ima)) {
GPU_free_image(ima);
ima->lastused = ctime;
}
@@ -1589,679 +1084,7 @@ void GPU_free_images_old(void)
}
}
-
-/* OpenGL Materials */
-
-#define FIXEDMAT 8
-
-/* OpenGL state caching for materials */
-
-typedef struct GPUMaterialFixed {
- float diff[3];
- float spec[3];
- int hard;
- float alpha;
-} GPUMaterialFixed;
-
-static struct GPUMaterialState {
- GPUMaterialFixed (*matbuf);
- GPUMaterialFixed matbuf_fixed[FIXEDMAT];
- int totmat;
-
- /* set when called inside GPU_begin_object_materials / GPU_end_object_materials
- * otherwise calling GPU_object_material_bind returns zero */
- bool is_enabled;
-
- Material **gmatbuf;
- Material *gmatbuf_fixed[FIXEDMAT];
- Material *gboundmat;
- Object *gob;
- DupliObject *dob;
- Scene *gscene;
- int glay;
- bool gscenelock;
- float (*gviewmat)[4];
- float (*gviewinv)[4];
- float (*gviewcamtexcofac);
-
- bool backface_culling;
- bool two_sided_lighting;
-
- GPUBlendMode *alphablend;
- GPUBlendMode alphablend_fixed[FIXEDMAT];
- bool use_alpha_pass, is_alpha_pass;
- bool use_matcaps;
-
- int lastmatnr, lastretval;
- GPUBlendMode lastalphablend;
- bool is_opensubdiv;
-} GMS = {NULL};
-
-/* fixed function material, alpha handed by caller */
-static void gpu_material_to_fixed(
- GPUMaterialFixed *smat, const Material *bmat, const int gamma, const Object *ob,
- const int new_shading_nodes, const bool dimdown)
-{
- if (bmat->mode & MA_SHLESS) {
- copy_v3_v3(smat->diff, &bmat->r);
-
- if (gamma)
- linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
-
- zero_v3(smat->spec);
- smat->alpha = 1.0f;
- smat->hard = 0;
- }
- else if (new_shading_nodes) {
- copy_v3_v3(smat->diff, &bmat->r);
- copy_v3_v3(smat->spec, &bmat->specr);
- smat->alpha = 1.0f;
- smat->hard = CLAMPIS(bmat->har, 0, 128);
-
- if (dimdown) {
- mul_v3_fl(smat->diff, 0.8f);
- mul_v3_fl(smat->spec, 0.5f);
- }
-
- if (gamma) {
- linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
- linearrgb_to_srgb_v3_v3(smat->spec, smat->spec);
- }
- }
- else {
- mul_v3_v3fl(smat->diff, &bmat->r, bmat->ref + bmat->emit);
-
- if (bmat->shade_flag & MA_OBCOLOR)
- mul_v3_v3(smat->diff, ob->col);
-
- mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec);
- smat->hard = CLAMPIS(bmat->har, 1, 128);
- smat->alpha = 1.0f;
-
- if (gamma) {
- linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
- linearrgb_to_srgb_v3_v3(smat->spec, smat->spec);
- }
- }
-}
-
-static Material *gpu_active_node_material(Material *ma)
-{
- if (ma && ma->use_nodes && ma->nodetree) {
- bNode *node = nodeGetActiveID(ma->nodetree, ID_MA);
-
- if (node)
- return (Material *)node->id;
- else
- return NULL;
- }
-
- return ma;
-}
-
-void GPU_begin_dupli_object(DupliObject *dob)
-{
- GMS.dob = dob;
-}
-
-void GPU_end_dupli_object(void)
-{
- GMS.dob = NULL;
-}
-
-void GPU_begin_object_materials(
- View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob,
- bool glsl, bool *do_alpha_after)
-{
- Material *ma;
- GPUMaterial *gpumat;
- GPUBlendMode alphablend;
- DupliObject *dob;
- int a;
- const bool gamma = BKE_scene_check_color_management_enabled(scene);
- const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
- const bool use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) != 0; /* assumes v3d->defmaterial->preview is set */
- bool use_opensubdiv = false;
-
-#ifdef WITH_OPENSUBDIV
- {
- DerivedMesh *derivedFinal = NULL;
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_btmesh;
- if (em != NULL) {
- derivedFinal = em->derivedFinal;
- }
- else {
- derivedFinal = ob->derivedFinal;
- }
- }
- else {
- derivedFinal = ob->derivedFinal;
- }
-
- if (derivedFinal != NULL && derivedFinal->type == DM_TYPE_CCGDM) {
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) derivedFinal;
- use_opensubdiv = ccgdm->useGpuBackend;
- }
- }
-#endif
-
-#ifdef WITH_GAMEENGINE
- if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
- ob = BKE_object_lod_matob_get(ob, scene);
- }
-#endif
-
- /* initialize state */
- /* DupliObject must be restored */
- dob = GMS.dob;
- memset(&GMS, 0, sizeof(GMS));
- GMS.is_enabled = true;
- GMS.dob = dob;
- GMS.lastmatnr = -1;
- GMS.lastretval = -1;
- GMS.lastalphablend = GPU_BLEND_SOLID;
- GMS.use_matcaps = use_matcap;
-
- GMS.backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0;
-
- GMS.two_sided_lighting = false;
- if (ob && ob->type == OB_MESH)
- GMS.two_sided_lighting = (((Mesh *)ob->data)->flag & ME_TWOSIDED) != 0;
-
- GMS.gob = ob;
- GMS.gscene = scene;
- GMS.is_opensubdiv = use_opensubdiv;
- GMS.totmat = use_matcap ? 1 : ob->totcol + 1; /* materials start from 1, default material is 0 */
- GMS.glay = (v3d->localvd) ? v3d->localvd->lay : v3d->lay; /* keep lamps visible in local view */
- GMS.gscenelock = (v3d->scenelock != 0);
- GMS.gviewmat = rv3d->viewmat;
- GMS.gviewinv = rv3d->viewinv;
- GMS.gviewcamtexcofac = rv3d->viewcamtexcofac;
-
- /* alpha pass setup. there's various cases to handle here:
- * - object transparency on: only solid materials draw in the first pass,
- * and only transparent in the second 'alpha' pass.
- * - object transparency off: for glsl we draw both in a single pass, and
- * for solid we don't use transparency at all. */
- GMS.use_alpha_pass = (do_alpha_after != NULL);
- GMS.is_alpha_pass = (v3d->transp != false);
- if (GMS.use_alpha_pass)
- *do_alpha_after = false;
-
- if (GMS.totmat > FIXEDMAT) {
- GMS.matbuf = MEM_callocN(sizeof(GPUMaterialFixed) * GMS.totmat, "GMS.matbuf");
- GMS.gmatbuf = MEM_callocN(sizeof(*GMS.gmatbuf) * GMS.totmat, "GMS.matbuf");
- GMS.alphablend = MEM_callocN(sizeof(*GMS.alphablend) * GMS.totmat, "GMS.matbuf");
- }
- else {
- GMS.matbuf = GMS.matbuf_fixed;
- GMS.gmatbuf = GMS.gmatbuf_fixed;
- GMS.alphablend = GMS.alphablend_fixed;
- }
-
- /* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */
- if (use_matcap) {
- GMS.gmatbuf[0] = v3d->defmaterial;
- GPU_material_matcap(scene, v3d->defmaterial, use_opensubdiv);
-
- /* do material 1 too, for displists! */
- memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
-
- GMS.alphablend[0] = GPU_BLEND_SOLID;
- }
- else {
-
- /* no materials assigned? */
- if (ob->totcol == 0) {
- gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 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.alphablend[0] = GPU_BLEND_SOLID;
- }
-
- /* setup materials */
- for (a = 1; a <= ob->totcol; a++) {
- /* find a suitable material */
- ma = give_current_material(ob, a);
- if (!glsl && !new_shading_nodes) ma = gpu_active_node_material(ma);
- if (ma == NULL) ma = &defmaterial;
-
- /* create glsl material if requested */
- gpumat = glsl ? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv) : NULL;
-
- if (gpumat) {
- /* do glsl only if creating it succeed, else fallback */
- GMS.gmatbuf[a] = ma;
- alphablend = GPU_material_alpha_blend(gpumat, ob->col);
- }
- else {
- /* fixed function opengl materials */
- gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes, false);
-
- if (GMS.use_alpha_pass && ((ma->mode & MA_TRANSP) || (new_shading_nodes && ma->alpha != 1.0f))) {
- GMS.matbuf[a].alpha = ma->alpha;
- alphablend = (ma->alpha == 1.0f) ? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
- }
- else {
- GMS.matbuf[a].alpha = 1.0f;
- alphablend = GPU_BLEND_SOLID;
- }
- }
-
- /* setting 'do_alpha_after = true' indicates this object needs to be
- * drawn in a second alpha pass for improved blending */
- if (do_alpha_after && !GMS.is_alpha_pass)
- if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
- *do_alpha_after = true;
-
- GMS.alphablend[a] = alphablend;
- }
- }
-
- /* let's start with a clean state */
- GPU_object_material_unbind();
-}
-
-static int gpu_get_particle_info(GPUParticleInfo *pi)
-{
- DupliObject *dob = GMS.dob;
- if (dob->particle_system) {
- int ind;
- if (dob->persistent_id[0] < dob->particle_system->totpart)
- ind = dob->persistent_id[0];
- else {
- ind = dob->particle_system->child[dob->persistent_id[0] - dob->particle_system->totpart].parent;
- }
- if (ind >= 0) {
- ParticleData *p = &dob->particle_system->particles[ind];
-
- pi->scalprops[0] = ind;
- pi->scalprops[1] = GMS.gscene->r.cfra - p->time;
- pi->scalprops[2] = p->lifetime;
- pi->scalprops[3] = p->size;
-
- copy_v3_v3(pi->location, p->state.co);
- pi->location[3] = BLI_hash_int_01(ind);
-
- copy_v3_v3(pi->velocity, p->state.vel);
- copy_v3_v3(pi->angular_velocity, p->state.ave);
- return 1;
- }
- else return 0;
- }
- else
- return 0;
-}
-
-static void GPU_get_object_info(float oi[3], Material *mat)
-{
- Object *ob = GMS.gob;
- oi[0] = ob->index;
- oi[1] = mat->index;
- unsigned int random;
- if (GMS.dob) {
- random = GMS.dob->random_id;
- }
- else {
- random = BLI_hash_int_2d(BLI_hash_string(GMS.gob->id.name + 2), 0);
- }
- oi[2] = random * (1.0f / (float)0xFFFFFFFF);
-}
-
-int GPU_object_material_bind(int nr, void *attribs)
-{
- GPUVertexAttribs *gattribs = attribs;
-
- /* no GPU_begin_object_materials, use default material */
- if (!GMS.matbuf) {
- memset(&GMS, 0, sizeof(GMS));
-
- float diffuse[3], specular[3];
- mul_v3_v3fl(diffuse, &defmaterial.r, defmaterial.ref + defmaterial.emit);
- mul_v3_v3fl(specular, &defmaterial.specr, defmaterial.spec);
- GPU_basic_shader_colors(diffuse, specular, 35, 1.0f);
-
- if (GMS.two_sided_lighting)
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_TWO_SIDED);
- else
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
-
- return 0;
- }
-
- /* prevent index to use un-initialized array items */
- if (nr >= GMS.totmat)
- nr = 0;
-
- if (gattribs)
- memset(gattribs, 0, sizeof(*gattribs));
-
- /* keep current material */
- if (nr == GMS.lastmatnr)
- return GMS.lastretval;
-
- /* 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));
- GMS.gboundmat = NULL;
- }
-
- /* draw materials with alpha in alpha pass */
- GMS.lastmatnr = nr;
- GMS.lastretval = 1;
-
- if (GMS.use_alpha_pass) {
- GMS.lastretval = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
- if (GMS.is_alpha_pass)
- GMS.lastretval = !GMS.lastretval;
- }
- else
- GMS.lastretval = !GMS.is_alpha_pass;
-
- if (GMS.lastretval) {
- /* for alpha pass, use alpha blend */
- GPUBlendMode alphablend = GMS.alphablend[nr];
-
- if (gattribs && GMS.gmatbuf[nr]) {
- /* bind glsl material and get attributes */
- Material *mat = GMS.gmatbuf[nr];
- GPUParticleInfo partile_info;
- float object_info[3] = {0};
-
- float auto_bump_scale;
-
- GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv);
- GPU_material_vertex_attributes(gpumat, gattribs);
-
- if (GMS.dob) {
- gpu_get_particle_info(&partile_info);
- }
-
- if (GPU_get_material_builtins(gpumat) & GPU_OBJECT_INFO) {
- GPU_get_object_info(object_info, mat);
- }
-
- GPU_material_bind(
- gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT),
- GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);
-
- auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info, object_info);
- GMS.gboundmat = mat;
-
- /* for glsl use alpha blend mode, unless it's set to solid and
- * we are already drawing in an alpha pass */
- if (mat->game.alpha_blend != GPU_BLEND_SOLID)
- alphablend = mat->game.alpha_blend;
-
- if (GMS.is_alpha_pass) glDepthMask(1);
-
- if (GMS.backface_culling) {
- if (mat->game.flag)
- glEnable(GL_CULL_FACE);
- else
- glDisable(GL_CULL_FACE);
- }
-
- if (GMS.use_matcaps)
- glColor3f(1.0f, 1.0f, 1.0f);
- }
- else {
- /* or do fixed function opengl material */
- GPU_basic_shader_colors(
- GMS.matbuf[nr].diff,
- GMS.matbuf[nr].spec, GMS.matbuf[nr].hard, GMS.matbuf[nr].alpha);
-
- if (GMS.two_sided_lighting)
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_TWO_SIDED);
- else
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
- }
-
- /* set (alpha) blending mode */
- GPU_set_material_alpha_blend(alphablend);
- }
-
- return GMS.lastretval;
-}
-
-int GPU_object_material_visible(int nr, void *attribs)
-{
- GPUVertexAttribs *gattribs = attribs;
- int visible;
-
- if (!GMS.matbuf)
- return 0;
-
- if (gattribs)
- memset(gattribs, 0, sizeof(*gattribs));
-
- if (nr >= GMS.totmat)
- nr = 0;
-
- if (GMS.use_alpha_pass) {
- visible = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
- if (GMS.is_alpha_pass)
- visible = !visible;
- }
- else
- visible = !GMS.is_alpha_pass;
-
- return visible;
-}
-
-void GPU_set_material_alpha_blend(int alphablend)
-{
- if (GMS.lastalphablend == alphablend)
- return;
-
- gpu_set_alpha_blend(alphablend);
- GMS.lastalphablend = alphablend;
-}
-
-int GPU_get_material_alpha_blend(void)
-{
- return GMS.lastalphablend;
-}
-
-void GPU_object_material_unbind(void)
-{
- GMS.lastmatnr = -1;
- GMS.lastretval = 1;
-
- if (GMS.gboundmat) {
- if (GMS.backface_culling)
- 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));
- GMS.gboundmat = NULL;
- }
- else
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-
- GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
-}
-
-void GPU_material_diffuse_get(int nr, float diff[4])
-{
- /* prevent index to use un-initialized array items */
- if (nr >= GMS.totmat)
- nr = 0;
-
- /* no GPU_begin_object_materials, use default material */
- if (!GMS.matbuf) {
- mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit);
- }
- else {
- copy_v3_v3(diff, GMS.matbuf[nr].diff);
- diff[3] = GMS.matbuf[nr].alpha;
- }
-}
-
-bool GPU_material_use_matcaps_get(void)
-{
- return GMS.use_matcaps;
-}
-
-bool GPU_object_materials_check(void)
-{
- return GMS.is_enabled;
-}
-
-void GPU_end_object_materials(void)
-{
- GPU_object_material_unbind();
-
- GMS.is_enabled = false;
-
- if (GMS.matbuf && GMS.matbuf != GMS.matbuf_fixed) {
- MEM_freeN(GMS.matbuf);
- MEM_freeN(GMS.gmatbuf);
- MEM_freeN(GMS.alphablend);
- }
-
- GMS.matbuf = NULL;
- GMS.gmatbuf = NULL;
- GMS.alphablend = NULL;
- GMS.two_sided_lighting = false;
-
- /* resetting the texture matrix after the scaling needed for tiled textures */
- if (GTS.tilemode) {
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- }
-}
-
-/* Lights */
-
-int GPU_default_lights(void)
-{
- /* initialize */
- if (U.light[0].flag == 0 && U.light[1].flag == 0 && U.light[2].flag == 0) {
- U.light[0].flag = 1;
- U.light[0].vec[0] = -0.3; U.light[0].vec[1] = 0.3; U.light[0].vec[2] = 0.9;
- U.light[0].col[0] = 0.8; U.light[0].col[1] = 0.8; U.light[0].col[2] = 0.8;
- U.light[0].spec[0] = 0.5; U.light[0].spec[1] = 0.5; U.light[0].spec[2] = 0.5;
- U.light[0].spec[3] = 1.0;
-
- U.light[1].flag = 0;
- U.light[1].vec[0] = 0.5; U.light[1].vec[1] = 0.5; U.light[1].vec[2] = 0.1;
- U.light[1].col[0] = 0.4; U.light[1].col[1] = 0.4; U.light[1].col[2] = 0.8;
- U.light[1].spec[0] = 0.3; U.light[1].spec[1] = 0.3; U.light[1].spec[2] = 0.5;
- U.light[1].spec[3] = 1.0;
-
- U.light[2].flag = 0;
- U.light[2].vec[0] = 0.3; U.light[2].vec[1] = -0.3; U.light[2].vec[2] = -0.2;
- U.light[2].col[0] = 0.8; U.light[2].col[1] = 0.5; U.light[2].col[2] = 0.4;
- U.light[2].spec[0] = 0.5; U.light[2].spec[1] = 0.4; U.light[2].spec[2] = 0.3;
- U.light[2].spec[3] = 1.0;
- }
-
- GPU_basic_shader_light_set_viewer(false);
-
- int count = 0;
-
- for (int a = 0; a < 8; a++) {
- if (a < 3 && U.light[a].flag) {
- GPULightData light = {0};
-
- light.type = GPU_LIGHT_SUN;
-
- normalize_v3_v3(light.direction, U.light[a].vec);
- copy_v3_v3(light.diffuse, U.light[a].col);
- copy_v3_v3(light.specular, U.light[a].spec);
-
- GPU_basic_shader_light_set(a, &light);
-
- count++;
- }
- else
- GPU_basic_shader_light_set(a, NULL);
- }
-
- return count;
-}
-
-int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][4], int ortho)
-{
- /* disable all lights */
- for (int count = 0; count < 8; count++)
- GPU_basic_shader_light_set(count, NULL);
-
- /* view direction for specular is not computed correct by default in
- * opengl, so we set the settings ourselves */
- GPU_basic_shader_light_set_viewer(!ortho);
-
- int count = 0;
-
- for (Base *base = scene->base.first; base; base = base->next) {
- if (base->object->type != OB_LAMP)
- continue;
-
- if (!(base->lay & lay) || !(base->lay & ob->lay))
- continue;
-
- Lamp *la = base->object->data;
-
- /* setup lamp transform */
- glPushMatrix();
- glLoadMatrixf((float *)viewmat);
-
- /* setup light */
- GPULightData light = {0};
-
- mul_v3_v3fl(light.diffuse, &la->r, la->energy);
- mul_v3_v3fl(light.specular, &la->r, la->energy);
-
- if (la->type == LA_SUN) {
- /* directional sun light */
- light.type = GPU_LIGHT_SUN;
- normalize_v3_v3(light.direction, base->object->obmat[2]);
- }
- else {
- /* other lamps with position attenuation */
- copy_v3_v3(light.position, base->object->obmat[3]);
-
- light.constant_attenuation = 1.0f;
- light.linear_attenuation = la->att1 / la->dist;
- light.quadratic_attenuation = la->att2 / (la->dist * la->dist);
-
- if (la->type == LA_SPOT) {
- light.type = GPU_LIGHT_SPOT;
- negate_v3_v3(light.direction, base->object->obmat[2]);
- normalize_v3(light.direction);
- light.spot_cutoff = RAD2DEGF(la->spotsize * 0.5f);
- light.spot_exponent = 128.0f * la->spotblend;
- }
- else
- light.type = GPU_LIGHT_POINT;
- }
-
- GPU_basic_shader_light_set(count, &light);
-
- glPopMatrix();
-
- count++;
- if (count == 8)
- break;
- }
-
- return count;
-}
-
-static void gpu_multisample(bool enable)
+static void gpu_disable_multisample(void)
{
#ifdef __linux__
/* changing multisample from the default (enabled) causes problems on some
@@ -2277,115 +1100,51 @@ static void gpu_multisample(bool enable)
}
if (toggle_ok) {
- if (enable)
- glEnable(GL_MULTISAMPLE);
- else
- glDisable(GL_MULTISAMPLE);
+ glDisable(GL_MULTISAMPLE);
}
#else
- if (enable)
- glEnable(GL_MULTISAMPLE);
- else
- glDisable(GL_MULTISAMPLE);
+ glDisable(GL_MULTISAMPLE);
#endif
}
/* Default OpenGL State
*
- * This is called on startup, for opengl offscreen render and to restore state
- * for the game engine. Generally we should always return to this state when
+ * This is called on startup, for opengl offscreen render.
+ * Generally we should always return to this state when
* temporarily modifying the state for drawing, though that are (undocumented)
* exceptions that we should try to get rid of. */
void GPU_state_init(void)
{
- float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
- float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
-
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 35);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-
- GPU_default_lights();
-
+ GPU_disable_program_point_size();
+
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+
glDepthFunc(GL_LEQUAL);
- /* scaling matrices */
- glEnable(GL_NORMALIZE);
- glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
- glDisable(GL_FOG);
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LOGIC_OP);
+ glDisable(GL_COLOR_LOGIC_OP);
glDisable(GL_STENCIL_TEST);
- glDisable(GL_TEXTURE_1D);
- glDisable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- /* default disabled, enable should be local per function */
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
- glPixelTransferi(GL_RED_SCALE, 1);
- glPixelTransferi(GL_RED_BIAS, 0);
- glPixelTransferi(GL_GREEN_SCALE, 1);
- glPixelTransferi(GL_GREEN_BIAS, 0);
- glPixelTransferi(GL_BLUE_SCALE, 1);
- glPixelTransferi(GL_BLUE_BIAS, 0);
- glPixelTransferi(GL_ALPHA_SCALE, 1);
- glPixelTransferi(GL_ALPHA_BIAS, 0);
-
- glPixelTransferi(GL_DEPTH_BIAS, 0);
- glPixelTransferi(GL_DEPTH_SCALE, 1);
- glDepthRange(0.0, 1.0);
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
+ glDepthRange(0.0, 1.0);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glDisable(GL_CULL_FACE);
- gpu_multisample(false);
-
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ gpu_disable_multisample();
}
-#ifdef WITH_OPENSUBDIV
-/* Update face-varying variables offset which might be
- * different from mesh to mesh sharing the same material.
- */
-void GPU_draw_update_fvar_offset(DerivedMesh *dm)
+void GPU_enable_program_point_size(void)
{
- /* Sanity check to be sure we only do this for OpenSubdiv draw. */
- BLI_assert(dm->type == DM_TYPE_CCGDM);
- BLI_assert(GMS.is_opensubdiv);
-
- for (int i = 0; i < GMS.totmat; ++i) {
- Material *material = GMS.gmatbuf[i];
- GPUMaterial *gpu_material;
-
- if (material == NULL) {
- continue;
- }
-
- gpu_material = GPU_material_from_blender(GMS.gscene,
- material,
- GMS.is_opensubdiv);
-
- GPU_material_update_fvar_offset(gpu_material, dm);
- }
+ glEnable(GL_PROGRAM_POINT_SIZE);
}
-#endif
+void GPU_disable_program_point_size(void)
+{
+ glDisable(GL_PROGRAM_POINT_SIZE);
+}
/** \name Framebuffer color depth, for selection codes
* \{ */
@@ -2502,10 +1261,10 @@ void GPU_select_to_index_array(unsigned int *col, const unsigned int size)
{
#define INDEX_BUF_ARRAY(INDEX_FROM_BUF_BITS) \
for (i = size; i--; col++) { \
- if ((c = *col)) { \
- *col = INDEX_FROM_BUF_BITS(c); \
- } \
- } ((void)0)
+ if ((c = *col)) { \
+ *col = INDEX_FROM_BUF_BITS(c); \
+ } \
+ } ((void)0)
if (size > 0) {
unsigned int i, c;
@@ -2533,4 +1292,173 @@ void GPU_select_to_index_array(unsigned int *col, const unsigned int size)
#undef INDEX_BUF_ARRAY
}
+#define STATE_STACK_DEPTH 16
+
+typedef struct {
+ eGPUAttribMask mask;
+
+ /* GL_ENABLE_BIT */
+ unsigned int is_blend : 1;
+ unsigned int is_cull_face : 1;
+ unsigned int is_depth_test : 1;
+ unsigned int is_dither : 1;
+ unsigned int is_lighting : 1;
+ unsigned int is_line_smooth : 1;
+ unsigned int is_color_logic_op : 1;
+ unsigned int is_multisample : 1;
+ unsigned int is_polygon_offset_line : 1;
+ unsigned int is_polygon_offset_fill : 1;
+ unsigned int is_polygon_smooth : 1;
+ unsigned int is_sample_alpha_to_coverage : 1;
+ unsigned int is_scissor_test : 1;
+ unsigned int is_stencil_test : 1;
+
+ bool is_clip_plane[6];
+
+ /* GL_DEPTH_BUFFER_BIT */
+ /* unsigned int is_depth_test : 1; */
+ int depth_func;
+ double depth_clear_value;
+ bool depth_write_mask;
+
+ /* GL_SCISSOR_BIT */
+ int scissor_box[4];
+ /* unsigned int is_scissor_test : 1; */
+
+ /* GL_VIEWPORT_BIT */
+ int viewport[4];
+ double near_far[2];
+} GPUAttribValues;
+
+typedef struct {
+ GPUAttribValues attrib_stack[STATE_STACK_DEPTH];
+ unsigned int top;
+} GPUAttribStack;
+
+static GPUAttribStack state = {
+ .top = 0
+};
+
+#define AttribStack state
+#define Attrib state.attrib_stack[state.top]
+
+/**
+ * Replacement for glPush/PopAttributes
+ *
+ * We don't need to cover all the options of legacy OpenGL
+ * but simply the ones used by Blender.
+ */
+void gpuPushAttrib(eGPUAttribMask mask)
+{
+ Attrib.mask = mask;
+
+ if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
+ Attrib.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ glGetIntegerv(GL_DEPTH_FUNC, &Attrib.depth_func);
+ glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Attrib.depth_clear_value);
+ glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Attrib.depth_write_mask);
+ }
+
+ if ((mask & GPU_ENABLE_BIT) != 0) {
+ Attrib.is_blend = glIsEnabled(GL_BLEND);
+
+ for (int i = 0; i < 6; i++) {
+ Attrib.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
+ }
+
+ Attrib.is_cull_face = glIsEnabled(GL_CULL_FACE);
+ Attrib.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ Attrib.is_dither = glIsEnabled(GL_DITHER);
+ Attrib.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH);
+ Attrib.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
+ Attrib.is_multisample = glIsEnabled(GL_MULTISAMPLE);
+ Attrib.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE);
+ Attrib.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL);
+ Attrib.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH);
+ Attrib.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ Attrib.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ Attrib.is_stencil_test = glIsEnabled(GL_STENCIL_TEST);
+ }
+
+ if ((mask & GPU_SCISSOR_BIT) != 0) {
+ Attrib.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Attrib.scissor_box);
+ }
+
+ if ((mask & GPU_VIEWPORT_BIT) != 0) {
+ glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Attrib.near_far);
+ glGetIntegerv(GL_VIEWPORT, (GLint *)&Attrib.viewport);
+ }
+
+ if ((mask & GPU_BLEND_BIT) != 0) {
+ Attrib.is_blend = glIsEnabled(GL_BLEND);
+ }
+
+ BLI_assert(AttribStack.top < STATE_STACK_DEPTH);
+ AttribStack.top++;
+}
+
+static void restore_mask(GLenum cap, const bool value)
+{
+ if (value) {
+ glEnable(cap);
+ }
+ else {
+ glDisable(cap);
+ }
+}
+
+void gpuPopAttrib(void)
+{
+ BLI_assert(AttribStack.top > 0);
+ AttribStack.top--;
+
+ GLint mask = Attrib.mask;
+
+ if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
+ restore_mask(GL_DEPTH_TEST, Attrib.is_depth_test);
+ glDepthFunc(Attrib.depth_func);
+ glClearDepth(Attrib.depth_clear_value);
+ glDepthMask(Attrib.depth_write_mask);
+ }
+
+ if ((mask & GPU_ENABLE_BIT) != 0) {
+ restore_mask(GL_BLEND, Attrib.is_blend);
+
+ for (int i = 0; i < 6; i++) {
+ restore_mask(GL_CLIP_PLANE0 + i, Attrib.is_clip_plane[i]);
+ }
+
+ restore_mask(GL_CULL_FACE, Attrib.is_cull_face);
+ restore_mask(GL_DEPTH_TEST, Attrib.is_depth_test);
+ restore_mask(GL_DITHER, Attrib.is_dither);
+ restore_mask(GL_LINE_SMOOTH, Attrib.is_line_smooth);
+ restore_mask(GL_COLOR_LOGIC_OP, Attrib.is_color_logic_op);
+ restore_mask(GL_MULTISAMPLE, Attrib.is_multisample);
+ restore_mask(GL_POLYGON_OFFSET_LINE, Attrib.is_polygon_offset_line);
+ restore_mask(GL_POLYGON_OFFSET_FILL, Attrib.is_polygon_offset_fill);
+ restore_mask(GL_POLYGON_SMOOTH, Attrib.is_polygon_smooth);
+ restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Attrib.is_sample_alpha_to_coverage);
+ restore_mask(GL_SCISSOR_TEST, Attrib.is_scissor_test);
+ restore_mask(GL_STENCIL_TEST, Attrib.is_stencil_test);
+ }
+
+ if ((mask & GPU_VIEWPORT_BIT) != 0) {
+ glViewport(Attrib.viewport[0], Attrib.viewport[1], Attrib.viewport[2], Attrib.viewport[3]);
+ glDepthRange(Attrib.near_far[0], Attrib.near_far[1]);
+ }
+
+ if ((mask & GPU_SCISSOR_BIT) != 0) {
+ restore_mask(GL_SCISSOR_TEST, Attrib.is_scissor_test);
+ glScissor(Attrib.scissor_box[0], Attrib.scissor_box[1], Attrib.scissor_box[2], Attrib.scissor_box[3]);
+ }
+
+ if ((mask & GPU_BLEND_BIT) != 0) {
+ restore_mask(GL_BLEND, Attrib.is_blend);
+ }
+}
+
+#undef Attrib
+#undef AttribStack
+
/** \} */
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index e0ce87d0e68..73e86c1b391 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -56,14 +56,11 @@
/* Extensions support */
/* -- extension: version of GL that absorbs it
+ * EXT_gpu_shader4: 3.0
* ARB_framebuffer object: 3.0
- * EXT_framebuffer_object: 3.0
- * EXT_framebuffer_blit: 3.0
- * EXT_framebuffer_multisample: 3.0
* EXT_framebuffer_multisample_blit_scaled: ???
* ARB_draw_instanced: 3.1
* ARB_texture_multisample: 3.2
- * EXT_geometry_shader4: 3.2
* ARB_texture_query_lod: 4.0
*/
@@ -71,7 +68,8 @@ static struct GPUGlobal {
GLint maxtexsize;
GLint maxcubemapsize;
GLint maxtextures;
- bool extdisabled;
+ GLint maxubosize;
+ GLint maxubobinds;
int colordepth;
int samples_color_texture_max;
GPUDeviceType device;
@@ -93,11 +91,6 @@ bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
/* GPU Extensions */
-void GPU_extensions_disable(void)
-{
- GG.extdisabled = true;
-}
-
int GPU_max_texture_size(void)
{
return GG.maxtexsize;
@@ -123,6 +116,16 @@ int GPU_max_cube_map_size(void)
return GG.maxcubemapsize;
}
+int GPU_max_ubo_binds(void)
+{
+ return GG.maxubobinds;
+}
+
+int GPU_max_ubo_size(void)
+{
+ return GG.maxubosize;
+}
+
void GPU_get_dfdy_factors(float fac[2])
{
copy_v2_v2(fac, GG.dfdyfactors);
@@ -130,8 +133,11 @@ void GPU_get_dfdy_factors(float fac[2])
void gpu_extensions_init(void)
{
- /* BLI_assert(GLEW_VERSION_2_1); */
- /* ^-- maybe a bit extreme? */
+ /* during 2.8 development each platform has its own OpenGL minimum requirements
+ * final 2.8 release will be unified on OpenGL 3.3 core profile, no required extensions
+ * see developer.blender.org/T49012 for details
+ */
+ BLI_assert(GLEW_VERSION_3_3);
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
@@ -143,11 +149,22 @@ void gpu_extensions_init(void)
else
GG.max_anisotropy = 1.0f;
+ glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds);
+ glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
+
+#ifndef NDEBUG
+ GLint ret;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &ret);
+ /* We expect FRONT_LEFT to be the default buffer. */
+ BLI_assert(ret == GL_FRAMEBUFFER_DEFAULT);
+#endif
+
GLint r, g, b;
- glGetIntegerv(GL_RED_BITS, &r);
- glGetIntegerv(GL_GREEN_BITS, &g);
- glGetIntegerv(GL_BLUE_BITS, &b);
- GG.colordepth = r + g + b; /* assumes same depth for RGB */
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &r);
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &g);
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &b);
+ GG.colordepth = r + g + b; /* Assumes same depth for RGB. */
if (GLEW_VERSION_3_2 || GLEW_ARB_texture_multisample) {
glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max);
@@ -201,10 +218,6 @@ void gpu_extensions_init(void)
GG.driver = GPU_DRIVER_ANY;
}
- /* make sure double side isn't used by default and only getting enabled in places where it's
- * really needed to prevent different unexpected behaviors like with intel gme965 card (sergey) */
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
-
#ifdef _WIN32
GG.os = GPU_OS_WIN;
#elif defined(__APPLE__)
@@ -246,43 +259,6 @@ void gpu_extensions_exit(void)
GPU_invalid_tex_free();
}
-bool GPU_legacy_support(void)
-{
- /* return whether or not current GL context is compatible with legacy OpenGL */
- static bool checked = false;
- static bool support = true;
-
- if (!checked) {
- if (GLEW_VERSION_3_2) {
- GLint profile;
- glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
-
- if (G.debug & G_DEBUG_GPU) {
- printf("GL_CONTEXT_PROFILE_MASK = %#x (%s profile)\n", (unsigned int)profile,
- (profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) ? "compatibility" :
- (profile & GL_CONTEXT_CORE_PROFILE_BIT) ? "core" : "unknown");
- }
-
- if (profile == 0) {
- /* workaround for nVidia's Linux driver */
- support = GLEW_ARB_compatibility;
- }
- else {
- support = profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT;
- }
- }
- else if (GLEW_VERSION_3_1) {
- support = GLEW_ARB_compatibility;
- }
-
- /* any OpenGL version <= 3.0 is legacy, so support remains true */
-
- checked = true;
- }
-
- return support;
-}
-
bool GPU_full_non_power_of_two_support(void)
{
/* always supported on full GL but still relevant for OpenGL ES 2.0 where
@@ -290,39 +266,11 @@ bool GPU_full_non_power_of_two_support(void)
return true;
}
-bool GPU_display_list_support(void)
-{
- /* deprecated in GL 3
- * supported on older GL and compatibility profile
- * still queried by game engine
- */
- return true;
-}
-
bool GPU_bicubic_bump_support(void)
{
return GLEW_VERSION_4_0 || (GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0);
}
-bool GPU_geometry_shader_support(void)
-{
- /* in GL 3.2 geometry shaders are fully supported
- * core profile clashes with our other shaders so accept compatibility only
- * other GL versions can use EXT_geometry_shader4 if available
- */
- return (GLEW_VERSION_3_2 && GPU_legacy_support()) || GLEW_EXT_geometry_shader4;
-}
-
-bool GPU_geometry_shader_support_via_extension(void)
-{
- return GLEW_EXT_geometry_shader4 && !(GLEW_VERSION_3_2 && GPU_legacy_support());
-}
-
-bool GPU_instanced_drawing_support(void)
-{
- return GLEW_VERSION_3_1 || GLEW_ARB_draw_instanced;
-}
-
int GPU_color_depth(void)
{
return GG.colordepth;
@@ -330,12 +278,14 @@ int GPU_color_depth(void)
bool GPU_mem_stats_supported(void)
{
- return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
+ return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM);
}
void GPU_mem_stats_get(int *totalmem, int *freemem)
{
+ /* TODO(merwin): use Apple's platform API to get this info */
+
if (GLEW_NVX_gpu_memory_info) {
/* returned value in Kb */
glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index e7a8beae5cc..75576c35f51 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -28,70 +28,138 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_threads.h"
#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
#include "BKE_global.h"
-#include "GPU_debug.h"
-#include "GPU_glew.h"
+#include "GPU_batch.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
+#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
-static struct GPUFrameBufferGlobal {
- GLuint currentfb;
-} GG = {0};
+static ThreadLocal(GLuint) g_currentfb;
-/* Number of maximum output slots.
- * We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
-#define GPU_FB_MAX_SLOTS 4
+typedef enum {
+ GPU_FB_DEPTH_ATTACHMENT = 0,
+ GPU_FB_DEPTH_STENCIL_ATTACHMENT,
+ GPU_FB_COLOR_ATTACHMENT0,
+ GPU_FB_COLOR_ATTACHMENT1,
+ GPU_FB_COLOR_ATTACHMENT2,
+ GPU_FB_COLOR_ATTACHMENT3,
+ GPU_FB_COLOR_ATTACHMENT4,
+ /* Number of maximum output slots.
+ * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate). */
+ /* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to
+ * the maximum number of COLOR attachments specified by glDrawBuffers. */
+ GPU_FB_MAX_ATTACHEMENT
+} GPUAttachmentType;
+
+#define GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHEMENT - GPU_FB_COLOR_ATTACHMENT0)
+
+#define GPU_FB_DIRTY_DRAWBUFFER (1 << 15)
+
+#define GPU_FB_ATTACHEMENT_IS_DIRTY(flag, type) ((flag & (1 << type)) != 0)
+#define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type))
struct GPUFrameBuffer {
GLuint object;
- GPUTexture *colortex[GPU_FB_MAX_SLOTS];
- GPUTexture *depthtex;
+ GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT];
+ uint16_t dirty_flag;
+ int width, height;
+ bool multisample;
+ /* TODO Check that we always use the right context when binding
+ * (FBOs are not shared accross ogl contexts). */
+ // void *ctx;
};
+static GLenum convert_attachment_type_to_gl(GPUAttachmentType type)
+{
+ static const GLenum table[] = {
+ [GPU_FB_DEPTH_ATTACHMENT] = GL_DEPTH_ATTACHMENT,
+ [GPU_FB_DEPTH_STENCIL_ATTACHMENT] = GL_DEPTH_STENCIL_ATTACHMENT,
+ [GPU_FB_COLOR_ATTACHMENT0] = GL_COLOR_ATTACHMENT0,
+ [GPU_FB_COLOR_ATTACHMENT1] = GL_COLOR_ATTACHMENT1,
+ [GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2,
+ [GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3,
+ [GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4
+ };
+ return table[type];
+}
+
+static GPUAttachmentType attachment_type_from_tex(GPUTexture *tex, int slot)
+{
+ switch (GPU_texture_format(tex)) {
+ case GPU_DEPTH_COMPONENT32F:
+ case GPU_DEPTH_COMPONENT24:
+ case GPU_DEPTH_COMPONENT16:
+ return GPU_FB_DEPTH_ATTACHMENT;
+ case GPU_DEPTH24_STENCIL8:
+ return GPU_FB_DEPTH_STENCIL_ATTACHMENT;
+ default:
+ return GPU_FB_COLOR_ATTACHMENT0 + slot;
+ }
+}
+
+static GLenum convert_buffer_bits_to_gl(GPUFrameBufferBits bits)
+{
+ GLbitfield mask = 0;
+ mask |= (bits & GPU_DEPTH_BIT) ? GL_DEPTH_BUFFER_BIT : 0;
+ mask |= (bits & GPU_STENCIL_BIT) ? GL_STENCIL_BUFFER_BIT : 0;
+ mask |= (bits & GPU_COLOR_BIT) ? GL_COLOR_BUFFER_BIT : 0;
+ return mask;
+}
+
+static GPUTexture *framebuffer_get_depth_tex(GPUFrameBuffer *fb)
+{
+ if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex)
+ return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex;
+ else
+ return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex;;
+}
+
+static GPUTexture *framebuffer_get_color_tex(GPUFrameBuffer *fb, int slot)
+{
+ return fb->attachments[GPU_FB_COLOR_ATTACHMENT0 + slot].tex;
+}
+
static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
{
+ const char *format = "GPUFrameBuffer: framebuffer status %s\n";
const char *err = "unknown";
+#define format_status(X) \
+ case GL_FRAMEBUFFER_##X: err = "GL_FRAMEBUFFER_"#X; \
+ break;
+
switch (status) {
- case GL_FRAMEBUFFER_COMPLETE_EXT:
- break;
- case GL_INVALID_OPERATION:
- err = "Invalid operation";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- err = "Incomplete attachment";
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- err = "Unsupported framebuffer format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- err = "Missing attachment";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- err = "Attached images must have same dimensions";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- err = "Attached images must have same format";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- err = "Missing draw buffer";
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- err = "Missing read buffer";
- break;
+ /* success */
+ format_status(COMPLETE)
+ /* errors shared by OpenGL desktop & ES */
+ format_status(INCOMPLETE_ATTACHMENT)
+ format_status(INCOMPLETE_MISSING_ATTACHMENT)
+ format_status(UNSUPPORTED)
+#if 0 /* for OpenGL ES only */
+ format_status(INCOMPLETE_DIMENSIONS)
+#else /* for desktop GL only */
+ format_status(INCOMPLETE_DRAW_BUFFER)
+ format_status(INCOMPLETE_READ_BUFFER)
+ format_status(INCOMPLETE_MULTISAMPLE)
+ format_status(UNDEFINED)
+#endif
}
+#undef format_status
+
if (err_out) {
- BLI_snprintf(err_out, 256, "GPUFrameBuffer: framebuffer incomplete error %d '%s'",
- (int)status, err);
+ BLI_snprintf(err_out, 256, format, err);
}
else {
- fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d '%s'\n",
- (int)status, err);
+ fprintf(stderr, format, err);
}
}
@@ -99,348 +167,480 @@ static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
GPUFrameBuffer *GPU_framebuffer_create(void)
{
- GPUFrameBuffer *fb;
+ /* We generate the FB object later at first use in order to
+ * create the framebuffer in the right opengl context. */
+ return MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");;
+}
- if (!(GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object ||
- (GLEW_EXT_framebuffer_object && GLEW_EXT_framebuffer_blit)))
- {
- return NULL;
+static void gpu_framebuffer_init(GPUFrameBuffer *fb)
+{
+ glGenFramebuffers(1, &fb->object);
+}
+
+void GPU_framebuffer_free(GPUFrameBuffer *fb)
+{
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; type++) {
+ if (fb->attachments[type].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[type].tex);
+ }
}
-
- fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
- glGenFramebuffersEXT(1, &fb->object);
- if (!fb->object) {
- fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n",
- (int)glGetError());
- GPU_framebuffer_free(fb);
- return NULL;
+ /* This restores the framebuffer if it was bound */
+ glDeleteFramebuffers(1, &fb->object);
+
+ if (g_currentfb == fb->object) {
+ g_currentfb = 0;
}
- /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- glReadBuffer(GL_NONE);
- glDrawBuffer(GL_NONE);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-
- return fb;
+ MEM_freeN(fb);
}
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
-{
- GLenum attachment;
- GLenum error;
+/* ---------- Attach ----------- */
- if (slot >= GPU_FB_MAX_SLOTS) {
+static void gpu_framebuffer_texture_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+{
+ if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) {
fprintf(stderr,
"Attaching to index %d framebuffer slot unsupported. "
- "Use at most %d\n", slot, GPU_FB_MAX_SLOTS);
- return 0;
- }
-
- if ((G.debug & G_DEBUG)) {
- if (GPU_texture_bound_number(tex) != -1) {
- fprintf(stderr,
- "Feedback loop warning!: "
- "Attempting to attach texture to framebuffer while still bound to texture unit for drawing!\n");
- }
+ "Use at most %d\n", slot, GPU_FB_MAX_COLOR_ATTACHMENT);
+ return;
}
- if (GPU_texture_depth(tex))
- attachment = GL_DEPTH_ATTACHMENT_EXT;
- else
- attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- GG.currentfb = fb->object;
+ GPUAttachmentType type = attachment_type_from_tex(tex, slot);
+ GPUAttachment *attachment = &fb->attachments[type];
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
-
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
- GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0);
-
- error = glGetError();
+ if ((attachment->tex == tex) &&
+ (attachment->mip == mip) &&
+ (attachment->layer == layer))
+ {
+ return; /* Exact same texture already bound here. */
+ }
+ else if (attachment->tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, attachment->tex);
+ }
- if (error == GL_INVALID_OPERATION) {
- GPU_framebuffer_restore();
- gpu_print_framebuffer_error(error, err_out);
- return 0;
+ if (attachment->tex == NULL) {
+ GPU_texture_attach_framebuffer(tex, fb, type);
}
- if (GPU_texture_depth(tex))
- fb->depthtex = tex;
- else
- fb->colortex[slot] = tex;
+ attachment->tex = tex;
+ attachment->mip = mip;
+ attachment->layer = layer;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
+}
- GPU_texture_framebuffer_set(tex, fb, slot);
+void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
+{
+ gpu_framebuffer_texture_attach_ex(fb, tex, slot, -1, mip);
+}
- return 1;
+void GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
+{
+ /* NOTE: We could support 1D ARRAY texture. */
+ BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_2D_ARRAY);
+ gpu_framebuffer_texture_attach_ex(fb, tex, slot, layer, mip);
}
-void GPU_framebuffer_texture_detach(GPUTexture *tex)
+void GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip)
{
- GLenum attachment;
- GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
- int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+ BLI_assert(GPU_texture_cube(tex));
+ gpu_framebuffer_texture_attach_ex(fb, tex, slot, face, mip);
+}
- if (!fb)
- return;
+/* ---------- Detach ----------- */
- if (GG.currentfb != fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- GG.currentfb = fb->object;
- }
+void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *fb, GPUTexture *tex, int type)
+{
+ GPUAttachment *attachment = &fb->attachments[type];
- if (GPU_texture_depth(tex)) {
- fb->depthtex = NULL;
- attachment = GL_DEPTH_ATTACHMENT_EXT;
- }
- else {
- BLI_assert(fb->colortex[fb_attachment] == tex);
- fb->colortex[fb_attachment] = NULL;
- attachment = GL_COLOR_ATTACHMENT0_EXT + fb_attachment;
+ if (attachment->tex != tex) {
+ fprintf(stderr,
+ "Warning, attempting to detach Texture %p from framebuffer %p "
+ "but texture is not attached.\n", tex, fb);
+ return;
}
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, GPU_texture_target(tex), 0, 0);
+ attachment->tex = NULL;
+ GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type);
+}
- GPU_texture_framebuffer_set(tex, NULL, -1);
+void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
+{
+ GPUAttachmentType type = GPU_texture_detach_framebuffer(tex, fb);
+ GPU_framebuffer_texture_detach_slot(fb, tex, type);
}
-void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
+/* ---------- Config (Attach & Detach) ----------- */
+
+/**
+ * First GPUAttachment in *config is always the depth/depth_stencil buffer.
+ * Following GPUAttachments are color buffers.
+ * Setting GPUAttachment.mip to -1 will leave the texture in this slot.
+ * Setting GPUAttachment.tex to NULL will detach the texture in this slot.
+ **/
+void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_ct)
{
- GPUFrameBuffer *fb = GPU_texture_framebuffer(tex);
- int fb_attachment = GPU_texture_framebuffer_attachment(tex);
+ if (config[0].tex) {
+ BLI_assert(GPU_texture_depth(config[0].tex));
+ gpu_framebuffer_texture_attach_ex(fb, config[0].tex, 0, config[0].layer, config[0].mip);
+ }
+ else if (config[0].mip == -1) {
+ /* Leave texture attached */
+ }
+ else if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex);
+ }
+ else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex);
+ }
- if (!fb) {
- fprintf(stderr, "Error, texture not bound to framebuffer!\n");
- return;
+ int slot = 0;
+ for (int i = 1; i < config_ct; ++i, ++slot) {
+ if (config[i].tex != NULL) {
+ BLI_assert(GPU_texture_depth(config[i].tex) == false);
+ gpu_framebuffer_texture_attach_ex(fb, config[i].tex, slot, config[i].layer, config[i].mip);
+ }
+ else if (config[i].mip != -1) {
+ GPUTexture *tex = framebuffer_get_color_tex(fb, slot);
+ if (tex != NULL) {
+ GPU_framebuffer_texture_detach(fb, tex);
+ }
+ }
}
+}
- /* push attributes */
- glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
+/* ---------- Bind / Restore ----------- */
- /* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+static void gpu_framebuffer_attachment_attach(GPUAttachment *attach, GPUAttachmentType attach_type)
+{
+ int tex_bind = GPU_texture_opengl_bindcode(attach->tex);
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
- if (GPU_texture_depth(tex)) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
+ if (attach->layer > -1) {
+ if (GPU_texture_cube(attach->tex)) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer,
+ tex_bind, attach->mip);
+ }
+ else {
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer);
+ }
}
else {
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + fb_attachment);
- }
-
- if (GPU_texture_target(tex) == GL_TEXTURE_2D_MULTISAMPLE) {
- glEnable(GL_MULTISAMPLE);
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip);
}
+}
- /* push matrices and set default viewport and matrix */
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- GG.currentfb = fb->object;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment), GPUAttachmentType attach_type)
+{
+ GLenum gl_attachment = convert_attachment_type_to_gl(attach_type);
+ glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0);
}
-void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
+static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb)
{
- int numslots = 0, i;
- GLenum attachments[4];
-
- if (!fb->colortex[slot]) {
- fprintf(stderr, "Error, framebuffer slot empty!\n");
- return;
- }
-
- for (i = 0; i < 4; i++) {
- if (fb->colortex[i]) {
- attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
+ GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
+ int numslots = 0;
+
+ BLI_assert(g_currentfb == fb->object);
+
+ /* Update attachments */
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+
+ if (type >= GPU_FB_COLOR_ATTACHMENT0) {
+ if (fb->attachments[type].tex) {
+ gl_attachments[numslots] = convert_attachment_type_to_gl(type);
+ }
+ else {
+ gl_attachments[numslots] = GL_NONE;
+ }
numslots++;
}
+
+ if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type) == false) {
+ continue;
+ }
+ else if (fb->attachments[type].tex != NULL) {
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
+
+ fb->multisample = (GPU_texture_samples(fb->attachments[type].tex) > 0);
+ fb->width = GPU_texture_width(fb->attachments[type].tex);
+ fb->height = GPU_texture_height(fb->attachments[type].tex);
+ }
+ else {
+ gpu_framebuffer_attachment_detach(&fb->attachments[type], type);
+ }
}
-
- /* push attributes */
- glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
- glDisable(GL_SCISSOR_TEST);
+ fb->dirty_flag = 0;
- /* bind framebuffer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ /* Update draw buffers (color targets)
+ * This state is saved in the FBO */
+ if (numslots)
+ glDrawBuffers(numslots, gl_attachments);
+ else
+ glDrawBuffer(GL_NONE);
+}
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffers(numslots, attachments);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+void GPU_framebuffer_bind(GPUFrameBuffer *fb)
+{
+ if (fb->object == 0)
+ gpu_framebuffer_init(fb);
- /* push matrices and set default viewport and matrix */
- glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
- GG.currentfb = fb->object;
+ if (g_currentfb != fb->object)
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-}
+ g_currentfb = fb->object;
+ if (fb->dirty_flag != 0)
+ gpu_framebuffer_update_attachments(fb);
-void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
-{
- /* restore matrix */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ /* TODO manually check for errors? */
+#if 0
+ char err_out[256];
+ if (!GPU_framebuffer_check_valid(fb, err_out)) {
+ printf("Invalid %s\n", err_out);
+ }
+#endif
+
+ if (fb->multisample)
+ glEnable(GL_MULTISAMPLE);
- /* restore attributes */
- glPopAttrib();
+ glViewport(0, 0, fb->width, fb->height);
}
-void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
+void GPU_framebuffer_restore(void)
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- /* last bound prevails here, better allow explicit control here too */
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
-
- /* push matrices and set default viewport and matrix */
- glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
- GG.currentfb = fb->object;
- GG.currentfb = fb->object;
+ if (g_currentfb != 0) {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ g_currentfb = 0;
+ }
}
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
{
- return fb->object == GG.currentfb;
+ return (fb->object == g_currentfb) && (fb->object != 0);
+}
+
+unsigned int GPU_framebuffer_current_get(void)
+{
+ return g_currentfb;
}
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
{
- GLenum status;
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- GG.currentfb = fb->object;
-
- /* Clean glError buffer. */
- while (glGetError() != GL_NO_ERROR) {}
-
- status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ if (!GPU_framebuffer_bound(fb))
+ GPU_framebuffer_bind(fb);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
GPU_framebuffer_restore();
gpu_print_framebuffer_error(status, err_out);
return false;
}
-
+
return true;
}
-void GPU_framebuffer_free(GPUFrameBuffer *fb)
+/* ---------- Framebuffer Operations ----------- */
+
+#define CHECK_FRAMEBUFFER_IS_BOUND(_fb) \
+ BLI_assert(GPU_framebuffer_bound(_fb)); \
+ UNUSED_VARS_NDEBUG(_fb);
+
+/* Needs to be done after binding. */
+void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h)
{
- int i;
- if (fb->depthtex)
- GPU_framebuffer_texture_detach(fb->depthtex);
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
- for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
- if (fb->colortex[i]) {
- GPU_framebuffer_texture_detach(fb->colortex[i]);
- }
- }
+ glViewport(x, y, w, h);
+}
- if (fb->object) {
- glDeleteFramebuffersEXT(1, &fb->object);
+void GPU_framebuffer_clear(
+ GPUFrameBuffer *fb, GPUFrameBufferBits buffers,
+ const float clear_col[4], float clear_depth, unsigned int clear_stencil)
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
- if (GG.currentfb == fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- GG.currentfb = 0;
- }
+ if (buffers & GPU_COLOR_BIT) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
+ }
+ if (buffers & GPU_DEPTH_BIT) {
+ glDepthMask(GL_TRUE);
+ glClearDepth(clear_depth);
+ }
+ if (buffers & GPU_STENCIL_BIT) {
+ glStencilMask(clear_stencil);
}
- MEM_freeN(fb);
+ GLbitfield mask = convert_buffer_bits_to_gl(buffers);
+ glClear(mask);
}
-void GPU_framebuffer_restore(void)
+void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data)
+{
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ GLenum type = GL_DEPTH_COMPONENT;
+ glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+}
+
+void GPU_framebuffer_read_color(
+ GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data)
{
- if (GG.currentfb != 0) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- GG.currentfb = 0;
+ CHECK_FRAMEBUFFER_IS_BOUND(fb);
+
+ GLenum type;
+ switch (channels) {
+ case 1: type = GL_RED; break;
+ case 2: type = GL_RG; break;
+ case 3: type = GL_RGB; break;
+ case 4: type = GL_RGBA; break;
+ default:
+ BLI_assert(false && "wrong number of read channels");
+ return;
}
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
}
-void GPU_framebuffer_blur(
- GPUFrameBuffer *fb, GPUTexture *tex,
- GPUFrameBuffer *blurfb, GPUTexture *blurtex)
+/* read_slot and write_slot are only used for color buffers. */
+void GPU_framebuffer_blit(
+ GPUFrameBuffer *fb_read, int read_slot,
+ GPUFrameBuffer *fb_write, int write_slot,
+ GPUFrameBufferBits blit_buffers)
{
- const float scaleh[2] = {1.0f / GPU_texture_width(blurtex), 0.0f};
- const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(tex)};
+ BLI_assert(blit_buffers != 0);
- GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
- int scale_uniform, texture_source_uniform;
+ GLuint prev_fb = g_currentfb;
- if (!blur_shader)
- return;
+ /* Framebuffers must be up to date. This simplify this function. */
+ if (fb_read->dirty_flag != 0 || fb_read->object == 0) {
+ GPU_framebuffer_bind(fb_read);
+ }
+ if (fb_write->dirty_flag != 0 || fb_write->object == 0) {
+ GPU_framebuffer_bind(fb_write);
+ }
- scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
- texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
-
- /* Blurring horizontally */
+ const bool do_color = (blit_buffers & GPU_COLOR_BIT);
+ const bool do_depth = (blit_buffers & GPU_DEPTH_BIT);
+ const bool do_stencil = (blit_buffers & GPU_STENCIL_BIT);
- /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
- * pushing unnecessary matrices onto the OpenGL stack. */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-
- /* avoid warnings from texture binding */
- GG.currentfb = blurfb->object;
-
- GPU_shader_bind(blur_shader);
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
- glViewport(0, 0, GPU_texture_width(blurtex), GPU_texture_height(blurtex));
-
- /* Preparing to draw quad */
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glDisable(GL_DEPTH_TEST);
-
- GPU_texture_bind(tex, 0);
-
- /* Drawing quad */
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
-
- /* Blurring vertically */
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
-
- GG.currentfb = fb->object;
-
- glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
- GPU_texture_bind(blurtex, 0);
+ GPUTexture *read_tex = (do_depth || do_stencil)
+ ? framebuffer_get_depth_tex(fb_read)
+ : framebuffer_get_color_tex(fb_read, read_slot);
+ GPUTexture *write_tex = (do_depth || do_stencil)
+ ? framebuffer_get_depth_tex(fb_write)
+ : framebuffer_get_color_tex(fb_write, read_slot);
+
+ if (do_depth) {
+ BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex));
+ BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
+ }
+ if (do_stencil) {
+ BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex));
+ BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex));
+ }
+ if (GPU_texture_samples(write_tex) != 0 ||
+ GPU_texture_samples(read_tex) != 0)
+ {
+ /* Can only blit multisample textures to another texture of the same size. */
+ BLI_assert((fb_read->width == fb_write->width) &&
+ (fb_read->height == fb_write->height));
+ }
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
+
+ if (do_color) {
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + read_slot);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + write_slot);
+ /* XXX we messed with the glDrawBuffer, this will reset the
+ * glDrawBuffers the next time we bind fb_write. */
+ fb_write->dirty_flag = GPU_FB_DIRTY_DRAWBUFFER;
+ }
+
+ GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers);
+
+ glBlitFramebuffer(0, 0, fb_read->width, fb_read->height,
+ 0, 0, fb_write->width, fb_write->height,
+ mask, GL_NEAREST);
+
+ /* Restore previous framebuffer */
+ if (fb_write->object == prev_fb) {
+ GPU_framebuffer_bind(fb_write); /* To update drawbuffers */
+ }
+ else {
+ glBindFramebuffer(GL_FRAMEBUFFER, prev_fb);
+ g_currentfb = prev_fb;
+ }
+}
+
+/**
+ * Use this if you need to custom downsample your texture and use the previous mip level as input.
+ * This function only takes care of the correct texture handling. It execute the callback for each texture level.
+ **/
+void GPU_framebuffer_recursive_downsample(
+ GPUFrameBuffer *fb, int max_lvl,
+ void (*callback)(void *userData, int level), void *userData)
+{
+ /* Framebuffer must be up to date and bound. This simplify this function. */
+ if (g_currentfb != fb->object || fb->dirty_flag != 0 || fb->object == 0) {
+ GPU_framebuffer_bind(fb);
+ }
+ /* HACK: We make the framebuffer appear not bound in order to
+ * not trigger any error in GPU_texture_bind(). */
+ GLuint prev_fb = g_currentfb;
+ g_currentfb = 0;
+
+ int i;
+ int current_dim[2] = {fb->width, fb->height};
+ for (i = 1; i < max_lvl + 1; i++) {
+ /* calculate next viewport size */
+ current_dim[0] = max_ii(current_dim[0] / 2, 1);
+ current_dim[1] = max_ii(current_dim[1] / 2, 1);
+
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* bind next level for rendering but first restrict fetches only to previous level */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+ /* copy attachment and replace miplevel. */
+ GPUAttachment attachment = fb->attachments[type];
+ attachment.mip = i;
+ gpu_framebuffer_attachment_attach(&attachment, type);
+ }
+ }
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
+ BLI_assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ glViewport(0, 0, current_dim[0], current_dim[1]);
+ callback(userData, i);
+
+ if (current_dim[0] == 1 && current_dim[1] == 1)
+ break;
+ }
- GPU_shader_unbind();
+ for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
+ if (fb->attachments[type].tex != NULL) {
+ /* reset mipmap level range */
+ GPUTexture *tex = fb->attachments[type].tex;
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1);
+ GPU_texture_unbind(tex);
+ /* Reattach original level */
+ /* NOTE: This is not necessary but this makes the FBO config
+ * remain in sync with the GPUFrameBuffer config. */
+ gpu_framebuffer_attachment_attach(&fb->attachments[type], type);
+ }
+ }
+
+ g_currentfb = prev_fb;
}
/* GPUOffScreen */
@@ -451,63 +651,42 @@ struct GPUOffScreen {
GPUTexture *depth;
};
-GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256])
+GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256])
{
GPUOffScreen *ofs;
ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
- ofs->fb = GPU_framebuffer_create();
- if (!ofs->fb) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
+ ofs->color = GPU_texture_create_2D_multisample(width, height,
+ (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out);
- if (samples) {
- if (!GLEW_EXT_framebuffer_multisample ||
- !GLEW_ARB_texture_multisample ||
- /* Only needed for GPU_offscreen_read_pixels.
- * We could add an arg if we intend to use multi-sample
- * offscreen buffers w/o reading their pixels */
- !GLEW_EXT_framebuffer_blit ||
- /* This is required when blitting from a multi-sampled buffers,
- * even though we're not scaling. */
- !GLEW_EXT_framebuffer_multisample_blit_scaled)
- {
- samples = 0;
- }
+ if (depth) {
+ ofs->depth = GPU_texture_create_2D_multisample(width, height, GPU_DEPTH24_STENCIL8, NULL, samples, err_out);
}
- ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out);
- if (!ofs->depth) {
+ if ((depth && !ofs->depth) || !ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
+ gpuPushAttrib(GPU_VIEWPORT_BIT);
- ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
- if (!ofs->color) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
+ GPU_framebuffer_ensure_config(&ofs->fb, {
+ GPU_ATTACHMENT_TEXTURE(ofs->depth),
+ GPU_ATTACHMENT_TEXTURE(ofs->color)
+ });
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
- GPU_offscreen_free(ofs);
- return NULL;
- }
-
/* check validity at the very end! */
if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
GPU_offscreen_free(ofs);
+ gpuPopAttrib();
return NULL;
}
GPU_framebuffer_restore();
+ gpuPopAttrib();
+
return ofs;
}
@@ -525,20 +704,37 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
{
- glDisable(GL_SCISSOR_TEST);
- if (save)
- GPU_texture_bind_as_framebuffer(ofs->color);
- else {
- GPU_framebuffer_bind_no_save(ofs->fb, 0);
+ if (save) {
+ gpuPushAttrib(GPU_SCISSOR_BIT | GPU_VIEWPORT_BIT);
}
+ glDisable(GL_SCISSOR_TEST);
+ GPU_framebuffer_bind(ofs->fb);
}
-void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
+void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
{
- if (restore)
- GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
+ if (restore) {
+ gpuPopAttrib();
+ }
+}
+
+void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y)
+{
+ const int w = GPU_texture_width(ofs->color);
+ const int h = GPU_texture_height(ofs->color);
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->fb->object);
+ GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
+
+ if (status == GL_FRAMEBUFFER_COMPLETE) {
+ glBlitFramebuffer(0, 0, w, h, x, y, x + w, y + h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ }
+ else {
+ gpu_print_framebuffer_error(status, NULL);
+ }
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
@@ -546,74 +742,46 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
const int w = GPU_texture_width(ofs->color);
const int h = GPU_texture_height(ofs->color);
+ BLI_assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT);
+
if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) {
/* For a multi-sample texture,
* we need to create an intermediate buffer to blit to,
* before its copied using 'glReadPixels' */
-
- /* not needed since 'ofs' needs to be bound to the framebuffer already */
-// #define USE_FBO_CTX_SWITCH
-
GLuint fbo_blit = 0;
GLuint tex_blit = 0;
- GLenum status;
/* create texture for new 'fbo_blit' */
glGenTextures(1, &tex_blit);
- if (!tex_blit) {
- goto finally;
- }
-
glBindTexture(GL_TEXTURE_2D, tex_blit);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, type, 0);
-
-#ifdef USE_FBO_CTX_SWITCH
- /* read from multi-sample buffer */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, ofs->color->fb->object);
- glFramebufferTexture2DEXT(
- GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + ofs->color->fb_attachment,
- GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
- status = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- goto finally;
- }
-#endif
+ glTexImage2D(GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8,
+ w, h, 0, GL_RGBA, type, 0);
/* write into new single-sample buffer */
- glGenFramebuffersEXT(1, &fbo_blit);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_blit);
- glFramebufferTexture2DEXT(
- GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_2D, tex_blit, 0);
- status = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ glGenFramebuffers(1, &fbo_blit);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit);
+ glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tex_blit, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
goto finally;
}
/* perform the copy */
- glBlitFramebufferEXT(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
/* read the results */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo_blit);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit);
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
-#ifdef USE_FBO_CTX_SWITCH
/* restore the original frame-bufer */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ofs->color->fb->object);
-#undef USE_FBO_CTX_SWITCH
-#endif
-
+ glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object);
finally:
/* cleanup */
- if (tex_blit) {
- glDeleteTextures(1, &tex_blit);
- }
- if (fbo_blit) {
- glDeleteFramebuffersEXT(1, &fbo_blit);
- }
-
- GPU_ASSERT_NO_GL_ERRORS("Read Multi-Sample Pixels");
+ glDeleteTextures(1, &tex_blit);
+ glDeleteFramebuffers(1, &fbo_blit);
}
else {
glReadPixels(0, 0, w, h, GL_RGBA, type, pixels);
@@ -630,8 +798,17 @@ int GPU_offscreen_height(const GPUOffScreen *ofs)
return GPU_texture_height(ofs->color);
}
-int GPU_offscreen_color_texture(const GPUOffScreen *ofs)
+GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs)
{
- return GPU_texture_opengl_bindcode(ofs->color);
+ return ofs->color;
}
+/* only to be used by viewport code! */
+void GPU_offscreen_viewport_data_get(
+ GPUOffScreen *ofs,
+ GPUFrameBuffer **r_fb, GPUTexture **r_color, GPUTexture **r_depth)
+{
+ *r_fb = ofs->fb;
+ *r_color = ofs->color;
+ *r_depth = ofs->depth;
+}
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
new file mode 100644
index 00000000000..5f22b7f9279
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -0,0 +1,88 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "UI_resources.h"
+#include "BLI_utildefines.h"
+
+#include "gpu_shader_private.h"
+
+void immBindBuiltinProgram(GPUBuiltinShader shader_id)
+{
+ GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
+ immBindProgram(shader->program, shader->interface);
+}
+
+void immUniformThemeColor(int color_id)
+{
+ float color[4];
+ UI_GetThemeColor4fv(color_id, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColor3(int color_id)
+{
+ float color[3];
+ UI_GetThemeColor3fv(color_id, color);
+ immUniformColor3fv(color);
+}
+
+void immUniformThemeColorShade(int color_id, int offset)
+{
+ float color[4];
+ UI_GetThemeColorShade4fv(color_id, offset, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset)
+{
+ float color[4];
+ UI_GetThemeColorShadeAlpha4fv(color_id, color_offset, alpha_offset, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int offset)
+{
+ float color[4];
+ UI_GetThemeColorBlendShade4fv(color_id1, color_id2, fac, offset, color);
+ immUniformColor4fv(color);
+}
+
+void immUniformThemeColorBlend(int color_id1, int color_id2, float fac)
+{
+ uint8_t color[3];
+ UI_GetThemeColorBlend3ubv(color_id1, color_id2, fac, color);
+ immUniformColor3ubv(color);
+}
+
+void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
+{
+ unsigned char col[4];
+ UI_GetThemeColorShadeAlpha4ubv(colorid, coloffset, alphaoffset, col);
+ immUniformColor4ub(col[0], col[1], col[2], col[3]);
+}
diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c
new file mode 100644
index 00000000000..bad878ef4bf
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_immediate_util.c
@@ -0,0 +1,424 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/intern/gpu_immediate_util.c
+ * \ingroup gpu
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
+static const float cube_coords[8][3] = {
+ {-1, -1, -1},
+ {-1, -1, +1},
+ {-1, +1, -1},
+ {-1, +1, +1},
+ {+1, -1, -1},
+ {+1, -1, +1},
+ {+1, +1, -1},
+ {+1, +1, +1},
+};
+static const int cube_quad_index[6][4] = {
+ {0, 1, 3, 2},
+ {0, 2, 6, 4},
+ {0, 4, 5, 1},
+ {1, 5, 7, 3},
+ {2, 3, 7, 6},
+ {4, 6, 7, 5},
+};
+static const int cube_line_index[12][2] = {
+ {0, 1},
+ {0, 2},
+ {0, 4},
+ {1, 3},
+ {1, 5},
+ {2, 3},
+ {2, 6},
+ {3, 7},
+ {4, 5},
+ {4, 6},
+ {5, 7},
+ {6, 7},
+};
+
+/**
+ * Pack color into 3 bytes
+ *
+ * This define converts a numerical value to the equivalent 24-bit
+ * color, while not being endian-sensitive. On little-endians, this
+ * is the same as doing a 'naive' indexing, on big-endian, it is not!
+ *
+ * \note BGR format (i.e. 0xBBGGRR)...
+ *
+ * \param x color.
+ */
+void imm_cpack(unsigned int x)
+{
+ immUniformColor3ub(((x) & 0xFF),
+ (((x) >> 8) & 0xFF),
+ (((x) >> 16) & 0xFF));
+}
+
+static void imm_draw_circle(
+ Gwn_PrimType prim_type, const uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
+{
+ immBegin(prim_type, nsegments);
+ for (int i = 0; i < nsegments; ++i) {
+ const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
+ immVertex2f(shdr_pos, x + (rad_x * cosf(angle)), y + (rad_y * sinf(angle)));
+ }
+ immEnd();
+}
+
+/**
+ * Draw a circle outline with the given \a radius.
+ * The circle is centered at \a x, \a y and drawn in the XY plane.
+ *
+ * \param shdr_pos The vertex attribute number for position.
+ * \param x Horizontal center.
+ * \param y Vertical center.
+ * \param radius The circle's radius.
+ * \param nsegments The number of segments to use in drawing (more = smoother).
+ */
+void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle(GWN_PRIM_LINE_LOOP, shdr_pos, x, y, rad, rad, nsegments);
+}
+
+/**
+ * Draw a filled circle with the given \a radius.
+ * The circle is centered at \a x, \a y and drawn in the XY plane.
+ *
+ * \param shdr_pos The vertex attribute number for position.
+ * \param x Horizontal center.
+ * \param y Vertical center.
+ * \param radius The circle's radius.
+ * \param nsegments The number of segments to use in drawing (more = smoother).
+ */
+void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle(GWN_PRIM_TRI_FAN, shdr_pos, x, y, rad, rad, nsegments);
+}
+
+void imm_draw_circle_wire_aspect_2d(uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
+{
+ imm_draw_circle(GWN_PRIM_LINE_LOOP, shdr_pos, x, y, rad_x, rad_y, nsegments);
+}
+void imm_draw_circle_fill_aspect_2d(uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments)
+{
+ imm_draw_circle(GWN_PRIM_TRI_FAN, shdr_pos, x, y, rad_x, rad_y, nsegments);
+}
+
+/**
+ * \note We could have `imm_draw_lined_disk_partial` but currently there is no need.
+ */
+static void imm_draw_disk_partial(
+ Gwn_PrimType prim_type, unsigned pos, float x, float y,
+ float rad_inner, float rad_outer, int nsegments, float start, float sweep)
+{
+ /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */
+ const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2);
+ const float angle_end = -(DEG2RADF(sweep) - angle_start);
+ nsegments += 1;
+ immBegin(prim_type, nsegments * 2);
+ for (int i = 0; i < nsegments; ++i) {
+ const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1)));
+ const float angle_sin = sinf(angle);
+ const float angle_cos = cosf(angle);
+ immVertex2f(pos, x + rad_inner * angle_cos, y + rad_inner * angle_sin);
+ immVertex2f(pos, x + rad_outer * angle_cos, y + rad_outer * angle_sin);
+ }
+ immEnd();
+}
+
+/**
+ * Draw a filled arc with the given inner and outer radius.
+ * The circle is centered at \a x, \a y and drawn in the XY plane.
+ *
+ * \note Arguments are `gluPartialDisk` compatible.
+ *
+ * \param pos: The vertex attribute number for position.
+ * \param x: Horizontal center.
+ * \param y: Vertical center.
+ * \param radius_inner: The inner circle's radius.
+ * \param radius_outer: The outer circle's radius (can be zero).
+ * \param nsegments: The number of segments to use in drawing (more = smoother).
+ * \param start: Specifies the starting angle, in degrees, of the disk portion.
+ * \param sweep: Specifies the sweep angle, in degrees, of the disk portion.
+ */
+void imm_draw_disk_partial_fill_2d(
+ unsigned pos, float x, float y,
+ float rad_inner, float rad_outer, int nsegments, float start, float sweep)
+{
+ imm_draw_disk_partial(GWN_PRIM_TRI_STRIP, pos, x, y, rad_inner, rad_outer, nsegments, start, sweep);
+}
+
+static void imm_draw_circle_3D(
+ Gwn_PrimType prim_type, unsigned pos, float x, float y,
+ float rad, int nsegments)
+{
+ immBegin(prim_type, nsegments);
+ for (int i = 0; i < nsegments; ++i) {
+ float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments);
+ immVertex3f(pos, x + rad * cosf(angle), y + rad * sinf(angle), 0.0f);
+ }
+ immEnd();
+}
+
+void imm_draw_circle_wire_3d(unsigned pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle_3D(GWN_PRIM_LINE_LOOP, pos, x, y, rad, nsegments);
+}
+
+void imm_draw_circle_fill_3d(unsigned pos, float x, float y, float rad, int nsegments)
+{
+ imm_draw_circle_3D(GWN_PRIM_TRI_FAN, pos, x, y, rad, nsegments);
+}
+
+/**
+* Draw a lined box.
+*
+* \param pos The vertex attribute number for position.
+* \param x1 left.
+* \param y1 bottom.
+* \param x2 right.
+* \param y2 top.
+*/
+void imm_draw_box_wire_2d(unsigned pos, float x1, float y1, float x2, float y2)
+{
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y1);
+ immEnd();
+}
+
+void imm_draw_box_wire_3d(unsigned pos, float x1, float y1, float x2, float y2)
+{
+ /* use this version when Gwn_VertFormat has a vec3 position */
+ immBegin(GWN_PRIM_LINE_LOOP, 4);
+ immVertex3f(pos, x1, y1, 0.0f);
+ immVertex3f(pos, x1, y2, 0.0f);
+ immVertex3f(pos, x2, y2, 0.0f);
+ immVertex3f(pos, x2, y1, 0.0f);
+ immEnd();
+}
+
+/**
+ * Draw a standard checkerboard to indicate transparent backgrounds.
+ */
+void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2)
+{
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
+
+ immUniform4f("color1", 0.15f, 0.15f, 0.15f, 1.0f);
+ immUniform4f("color2", 0.2f, 0.2f, 0.2f, 1.0f);
+ immUniform1i("size", 8);
+
+ immRectf(pos, x1, y1, x2, y2);
+
+ immUnbindProgram();
+}
+
+void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3])
+{
+ float coords[ARRAY_SIZE(cube_coords)][3];
+
+ for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
+ madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect);
+ }
+
+ immBegin(GWN_PRIM_TRIS, ARRAY_SIZE(cube_quad_index) * 3 * 2);
+ for (int i = 0; i < ARRAY_SIZE(cube_quad_index); i++) {
+ immVertex3fv(pos, coords[cube_quad_index[i][0]]);
+ immVertex3fv(pos, coords[cube_quad_index[i][1]]);
+ immVertex3fv(pos, coords[cube_quad_index[i][2]]);
+
+ immVertex3fv(pos, coords[cube_quad_index[i][0]]);
+ immVertex3fv(pos, coords[cube_quad_index[i][2]]);
+ immVertex3fv(pos, coords[cube_quad_index[i][3]]);
+ }
+ immEnd();
+}
+
+void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3])
+{
+ float coords[ARRAY_SIZE(cube_coords)][3];
+
+ for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) {
+ madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect);
+ }
+
+ immBegin(GWN_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 2);
+ for (int i = 0; i < ARRAY_SIZE(cube_line_index); i++) {
+ immVertex3fv(pos, coords[cube_line_index[i][0]]);
+ immVertex3fv(pos, coords[cube_line_index[i][1]]);
+ }
+ immEnd();
+}
+
+/**
+* Draw a cylinder. Replacement for gluCylinder.
+* _warning_ : Slow, better use it only if you no other choices.
+*
+* \param pos The vertex attribute number for position.
+* \param nor The vertex attribute number for normal.
+* \param base Specifies the radius of the cylinder at z = 0.
+* \param top Specifies the radius of the cylinder at z = height.
+* \param height Specifies the height of the cylinder.
+* \param slices Specifies the number of subdivisions around the z axis.
+* \param stacks Specifies the number of subdivisions along the z axis.
+*/
+void imm_draw_cylinder_fill_normal_3d(
+ unsigned int pos, unsigned int nor, float base, float top, float height, int slices, int stacks)
+{
+ immBegin(GWN_PRIM_TRIS, 6 * slices * stacks);
+ for (int i = 0; i < slices; ++i) {
+ const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
+ const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
+ const float cos1 = cosf(angle1);
+ const float sin1 = sinf(angle1);
+ const float cos2 = cosf(angle2);
+ const float sin2 = sinf(angle2);
+
+ for (int j = 0; j < stacks; ++j) {
+ float fac1 = (float)j / (float)stacks;
+ float fac2 = (float)(j + 1) / (float)stacks;
+ float r1 = base * (1.f - fac1) + top * fac1;
+ float r2 = base * (1.f - fac2) + top * fac2;
+ float h1 = height * ((float)j / (float)stacks);
+ float h2 = height * ((float)(j + 1) / (float)stacks);
+
+ float v1[3] = {r1 *cos2, r1 * sin2, h1};
+ float v2[3] = {r2 *cos2, r2 * sin2, h2};
+ float v3[3] = {r2 *cos1, r2 * sin1, h2};
+ float v4[3] = {r1 *cos1, r1 * sin1, h1};
+ float n1[3], n2[3];
+
+ /* calc normals */
+ sub_v3_v3v3(n1, v2, v1);
+ normalize_v3(n1);
+ n1[0] = cos1; n1[1] = sin1; n1[2] = 1 - n1[2];
+
+ sub_v3_v3v3(n2, v3, v4);
+ normalize_v3(n2);
+ n2[0] = cos2; n2[1] = sin2; n2[2] = 1 - n2[2];
+
+ /* first tri */
+ immAttrib3fv(nor, n2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immAttrib3fv(nor, n1);
+ immVertex3fv(pos, v3);
+
+ /* second tri */
+ immVertex3fv(pos, v3);
+ immVertex3fv(pos, v4);
+ immAttrib3fv(nor, n2);
+ immVertex3fv(pos, v1);
+ }
+ }
+ immEnd();
+}
+
+void imm_draw_cylinder_wire_3d(unsigned int pos, float base, float top, float height, int slices, int stacks)
+{
+ immBegin(GWN_PRIM_LINES, 6 * slices * stacks);
+ for (int i = 0; i < slices; ++i) {
+ const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
+ const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
+ const float cos1 = cosf(angle1);
+ const float sin1 = sinf(angle1);
+ const float cos2 = cosf(angle2);
+ const float sin2 = sinf(angle2);
+
+ for (int j = 0; j < stacks; ++j) {
+ float fac1 = (float)j / (float)stacks;
+ float fac2 = (float)(j + 1) / (float)stacks;
+ float r1 = base * (1.f - fac1) + top * fac1;
+ float r2 = base * (1.f - fac2) + top * fac2;
+ float h1 = height * ((float)j / (float)stacks);
+ float h2 = height * ((float)(j + 1) / (float)stacks);
+
+ float v1[3] = {r1 * cos2, r1 * sin2, h1};
+ float v2[3] = {r2 * cos2, r2 * sin2, h2};
+ float v3[3] = {r2 * cos1, r2 * sin1, h2};
+ float v4[3] = {r1 * cos1, r1 * sin1, h1};
+
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+
+ immVertex3fv(pos, v2);
+ immVertex3fv(pos, v3);
+
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v4);
+ }
+ }
+ immEnd();
+}
+
+void imm_draw_cylinder_fill_3d(unsigned int pos, float base, float top, float height, int slices, int stacks)
+{
+ immBegin(GWN_PRIM_TRIS, 6 * slices * stacks);
+ for (int i = 0; i < slices; ++i) {
+ const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices);
+ const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices);
+ const float cos1 = cosf(angle1);
+ const float sin1 = sinf(angle1);
+ const float cos2 = cosf(angle2);
+ const float sin2 = sinf(angle2);
+
+ for (int j = 0; j < stacks; ++j) {
+ float fac1 = (float)j / (float)stacks;
+ float fac2 = (float)(j + 1) / (float)stacks;
+ float r1 = base * (1.f - fac1) + top * fac1;
+ float r2 = base * (1.f - fac2) + top * fac2;
+ float h1 = height * ((float)j / (float)stacks);
+ float h2 = height * ((float)(j + 1) / (float)stacks);
+
+ float v1[3] = {r1 * cos2, r1 * sin2, h1};
+ float v2[3] = {r2 * cos2, r2 * sin2, h2};
+ float v3[3] = {r2 * cos1, r2 * sin1, h2};
+ float v4[3] = {r1 * cos1, r1 * sin1, h1};
+
+ /* first tri */
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immVertex3fv(pos, v3);
+
+ /* second tri */
+ immVertex3fv(pos, v3);
+ immVertex3fv(pos, v4);
+ immVertex3fv(pos, v1);
+ }
+ }
+ immEnd();
+}
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index c72c83b6b07..c2f14687ff5 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -30,8 +30,10 @@
*/
#include "BLI_sys_types.h"
+#include "GPU_buffers.h"
#include "GPU_init_exit.h" /* interface */
-
+#include "GPU_immediate.h"
+#include "GPU_batch.h"
#include "BKE_global.h"
#include "intern/gpu_codegen.h"
@@ -59,14 +61,28 @@ void GPU_init(void)
if (G.debug & G_DEBUG_GPU)
gpu_debug_init();
+ gpu_batch_init();
+
+ if (!G.background) {
+ immInit();
+ }
+
+ GPU_pbvh_fix_linking();
}
void GPU_exit(void)
{
+ if (!G.background) {
+ immDestroy();
+ }
+
+ gpu_batch_exit();
+
if (G.debug & G_DEBUG_GPU)
gpu_debug_exit();
+
gpu_codegen_exit();
gpu_extensions_exit(); /* must come last */
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index edb6c9a29f9..769c60f8e61 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -45,16 +45,17 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_rand.h"
#include "BKE_anim.h"
#include "BKE_colorband.h"
#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_scene.h"
-#include "BKE_group.h"
#include "IMB_imbuf_types.h"
@@ -63,6 +64,9 @@
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_uniformbuffer.h"
+
+#include "DRW_engine.h"
#include "gpu_codegen.h"
@@ -72,32 +76,17 @@
/* Structs */
-typedef enum DynMatProperty {
- DYN_LAMP_CO = 1,
- DYN_LAMP_VEC = 2,
- DYN_LAMP_IMAT = 4,
- DYN_LAMP_PERSMAT = 8,
-} DynMatProperty;
-
-static struct GPUWorld {
- float mistenabled;
- float mistype;
- float miststart;
- float mistdistance;
- float mistintensity;
- float mistcol[4];
- float horicol[3];
- float ambcol[4];
- float zencol[3];
-} GPUWorld;
-
struct GPUMaterial {
- Scene *scene;
+ Scene *scene; /* DEPRECATED was only usefull for lamps */
Material *ma;
/* material for mesh surface, worlds or something else.
* some code generation is done differently depending on the use case */
- int type;
+ int type; /* DEPRECATED */
+ GPUMaterialStatus status;
+
+ const void *engine_type; /* attached engine type */
+ int options; /* to identify shader variations (shadow, probe, world background...) */
/* for creating the material */
ListBase nodes;
@@ -105,6 +94,7 @@ struct GPUMaterial {
/* for binding the material */
GPUPass *pass;
+ ListBase inputs; /* GPUInput */
GPUVertexAttribs attribs;
int builtins;
int alpha, obcolalpha;
@@ -124,360 +114,69 @@ struct GPUMaterial {
int objectinfoloc;
- ListBase lamps;
- bool bound;
-
bool is_opensubdiv;
-};
-
-struct GPULamp {
- Scene *scene;
- Object *ob;
- Object *par;
- Lamp *la;
-
- int type, mode, lay, hide;
-
- float dynenergy, dyncol[3];
- float energy, col[3];
-
- float co[3], vec[3];
- float dynco[3], dynvec[3];
- float obmat[4][4];
- float imat[4][4];
- float dynimat[4][4];
- float spotsi, spotbl, k;
- float spotvec[2];
- float dyndist, dynatt1, dynatt2;
- float dist, att1, att2;
- float coeff_const, coeff_lin, coeff_quad;
- float shadow_color[3];
-
- float bias, d, clipend;
- int size;
-
- int falloff_type;
- struct CurveMapping *curfalloff;
-
- float winmat[4][4];
- float viewmat[4][4];
- float persmat[4][4];
- float dynpersmat[4][4];
-
- GPUFrameBuffer *fb;
- GPUFrameBuffer *blurfb;
- GPUTexture *tex;
- GPUTexture *depthtex;
- GPUTexture *blurtex;
-
- ListBase materials;
+ /* XXX: Should be in Material. But it depends on the output node
+ * used and since the output selection is difference for GPUMaterial...
+ */
+ int domain;
+
+ /* Used by 2.8 pipeline */
+ GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
+
+ /* Eevee SSS */
+ GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */
+ GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */
+ float *sss_radii; /* UBO containing SSS profile. */
+ int sss_samples;
+ short int *sss_falloff;
+ float *sss_sharpness;
+ bool sss_dirty;
};
-/* Forward declaration so shade_light_textures() can use this, while still keeping the code somewhat organized */
-static void texture_rgb_blend(
- GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg,
- int blendtype, GPUNodeLink **in);
+enum {
+ GPU_DOMAIN_SURFACE = (1 << 0),
+ GPU_DOMAIN_VOLUME = (1 << 1),
+ GPU_DOMAIN_SSS = (1 << 2)
+};
/* Functions */
-static GPUMaterial *GPU_material_construct_begin(Material *ma)
-{
- GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
-
- material->ma = ma;
-
- return material;
-}
-
-static void gpu_material_set_attrib_id(GPUMaterial *material)
-{
- GPUVertexAttribs *attribs = &material->attribs;
- GPUPass *pass = material->pass;
- if (!pass) {
- attribs->totlayer = 0;
- return;
- }
-
- GPUShader *shader = GPU_pass_shader(pass);
- if (!shader) {
- attribs->totlayer = 0;
- return;
- }
-
- /* convert from attribute number to the actual id assigned by opengl,
- * in case the attrib does not get a valid index back, it was probably
- * removed by the glsl compiler by dead code elimination */
-
- int b = 0;
- for (int a = 0; a < attribs->totlayer; a++) {
- char name[32];
- BLI_snprintf(name, sizeof(name), "att%d", attribs->layer[a].attribid);
- attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
-
- BLI_snprintf(name, sizeof(name), "att%d_info", attribs->layer[a].attribid);
- attribs->layer[a].glinfoindoex = GPU_shader_get_uniform(shader, name);
-
- if (attribs->layer[a].glindex >= 0) {
- attribs->layer[b] = attribs->layer[a];
- b++;
- }
- }
-
- attribs->totlayer = b;
-}
-
-static int gpu_material_construct_end(GPUMaterial *material, const char *passname)
-{
- if (material->outlink) {
- GPUNodeLink *outlink = material->outlink;
- material->pass = GPU_generate_pass(&material->nodes, outlink,
- &material->attribs, &material->builtins, material->type,
- passname,
- material->is_opensubdiv,
- GPU_material_use_new_shading_nodes(material));
-
- if (!material->pass)
- return 0;
-
- gpu_material_set_attrib_id(material);
-
- GPUShader *shader = GPU_pass_shader(material->pass);
-
- if (material->builtins & GPU_VIEW_MATRIX)
- material->viewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_VIEW_MATRIX));
- if (material->builtins & GPU_INVERSE_VIEW_MATRIX)
- material->invviewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_VIEW_MATRIX));
- if (material->builtins & GPU_OBJECT_MATRIX)
- material->obmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_MATRIX));
- if (material->builtins & GPU_INVERSE_OBJECT_MATRIX)
- material->invobmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_OBJECT_MATRIX));
- if (material->builtins & GPU_LOC_TO_VIEW_MATRIX)
- material->localtoviewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_LOC_TO_VIEW_MATRIX));
- if (material->builtins & GPU_INVERSE_LOC_TO_VIEW_MATRIX)
- material->invlocaltoviewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_LOC_TO_VIEW_MATRIX));
- if (material->builtins & GPU_OBCOLOR)
- material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR));
- if (material->builtins & GPU_AUTO_BUMPSCALE)
- material->obautobumpscaleloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_AUTO_BUMPSCALE));
- if (material->builtins & GPU_CAMERA_TEXCO_FACTORS)
- material->cameratexcofacloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_CAMERA_TEXCO_FACTORS));
- if (material->builtins & GPU_PARTICLE_SCALAR_PROPS)
- material->partscalarpropsloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_SCALAR_PROPS));
- if (material->builtins & GPU_PARTICLE_LOCATION)
- material->partcoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_LOCATION));
- if (material->builtins & GPU_PARTICLE_VELOCITY)
- material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY));
- if (material->builtins & GPU_PARTICLE_ANG_VELOCITY)
- material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY));
- if (material->builtins & GPU_OBJECT_INFO)
- material->objectinfoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_INFO));
- return 1;
- }
- else {
- GPU_pass_free_nodes(&material->nodes);
- }
-
- return 0;
-}
-
void GPU_material_free(ListBase *gpumaterial)
{
for (LinkData *link = gpumaterial->first; link; link = link->next) {
GPUMaterial *material = link->data;
- if (material->pass)
- GPU_pass_free(material->pass);
-
- for (LinkData *nlink = material->lamps.first; nlink; nlink = nlink->next) {
- GPULamp *lamp = nlink->data;
-
- if (material->ma) {
- Material *ma = material->ma;
-
- LinkData *next = NULL;
- for (LinkData *mlink = lamp->materials.first; mlink; mlink = next) {
- next = mlink->next;
- if (mlink->data == ma)
- BLI_freelinkN(&lamp->materials, mlink);
- }
- }
- }
-
- BLI_freelistN(&material->lamps);
-
- MEM_freeN(material);
- }
+ /* Cancel / wait any pending lazy compilation. */
+ DRW_deferred_shader_remove(material);
- BLI_freelistN(gpumaterial);
-}
+ GPU_pass_free_nodes(&material->nodes);
+ GPU_inputs_free(&material->inputs);
-bool GPU_lamp_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
-{
- if (lamp->hide)
- return false;
- else if (srl && srl->light_override)
- return BKE_group_object_exists(srl->light_override, lamp->ob);
- else if (ma && ma->group)
- return BKE_group_object_exists(ma->group, lamp->ob);
- else
- return true;
-}
+ if (material->pass)
+ GPU_pass_release(material->pass);
-void GPU_material_bind(
- GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
- float viewmat[4][4], float viewinv[4][4], float camerafactors[4], bool scenelock)
-{
- if (material->pass) {
- GPUShader *shader = GPU_pass_shader(material->pass);
- SceneRenderLayer *srl = scenelock ? BLI_findlink(&material->scene->r.layers, material->scene->r.actlay) : NULL;
-
- if (srl)
- viewlay &= srl->lay;
-
- /* handle layer lamps */
- if (material->type == GPU_MATERIAL_TYPE_MESH) {
- for (LinkData *nlink = material->lamps.first; nlink; nlink = nlink->next) {
- GPULamp *lamp = nlink->data;
-
- if ((lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay)) &&
- GPU_lamp_visible(lamp, srl, material->ma))
- {
- lamp->dynenergy = lamp->energy;
- copy_v3_v3(lamp->dyncol, lamp->col);
- }
- else {
- lamp->dynenergy = 0.0f;
- lamp->dyncol[0] = lamp->dyncol[1] = lamp->dyncol[2] = 0.0f;
- }
-
- if (material->dynproperty & DYN_LAMP_VEC) {
- copy_v3_v3(lamp->dynvec, lamp->vec);
- normalize_v3(lamp->dynvec);
- negate_v3(lamp->dynvec);
- mul_mat3_m4_v3(viewmat, lamp->dynvec);
- }
-
- if (material->dynproperty & DYN_LAMP_CO) {
- copy_v3_v3(lamp->dynco, lamp->co);
- mul_m4_v3(viewmat, lamp->dynco);
- }
-
- if (material->dynproperty & DYN_LAMP_IMAT) {
- mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
- }
-
- if (material->dynproperty & DYN_LAMP_PERSMAT) {
- /* The lamp matrices are already updated if we're using shadow buffers */
- if (!GPU_lamp_has_shadow_buffer(lamp)) {
- GPU_lamp_update_buffer_mats(lamp);
- }
- mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
- }
- }
+ if (material->ubo != NULL) {
+ GPU_uniformbuffer_free(material->ubo);
}
-
- /* note material must be bound before setting uniforms */
- GPU_pass_bind(material->pass, time, mipmap);
- /* handle per material built-ins */
- if (material->builtins & GPU_VIEW_MATRIX) {
- GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float *)viewmat);
- }
- if (material->builtins & GPU_INVERSE_VIEW_MATRIX) {
- GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float *)viewinv);
- }
- if (material->builtins & GPU_CAMERA_TEXCO_FACTORS) {
- if (camerafactors) {
- GPU_shader_uniform_vector(shader, material->cameratexcofacloc, 4, 1, (float *)camerafactors);
- }
- else {
- /* use default, no scaling no offset */
- float borders[4] = {1.0f, 1.0f, 0.0f, 0.0f};
- GPU_shader_uniform_vector(shader, material->cameratexcofacloc, 4, 1, (float *)borders);
- }
+ if (material->sss_tex_profile != NULL) {
+ GPU_texture_free(material->sss_tex_profile);
}
- GPU_pass_update_uniforms(material->pass);
-
- material->bound = 1;
- }
-}
-
-GPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
-{
- return material->builtins;
-}
-
-void GPU_material_bind_uniforms(
- GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4],
- float autobumpscale, GPUParticleInfo *pi, float object_info[3])
-{
- if (material->pass) {
- GPUShader *shader = GPU_pass_shader(material->pass);
- float invmat[4][4], col[4];
- float localtoviewmat[4][4];
- float invlocaltoviewmat[4][4];
-
- /* handle per object builtins */
- if (material->builtins & GPU_OBJECT_MATRIX) {
- GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float *)obmat);
- }
- if (material->builtins & GPU_INVERSE_OBJECT_MATRIX) {
- invert_m4_m4(invmat, obmat);
- GPU_shader_uniform_vector(shader, material->invobmatloc, 16, 1, (float *)invmat);
- }
- if (material->builtins & GPU_LOC_TO_VIEW_MATRIX) {
- if (viewmat) {
- mul_m4_m4m4(localtoviewmat, viewmat, obmat);
- GPU_shader_uniform_vector(shader, material->localtoviewmatloc, 16, 1, (float *)localtoviewmat);
- }
- }
- if (material->builtins & GPU_INVERSE_LOC_TO_VIEW_MATRIX) {
- if (viewmat) {
- mul_m4_m4m4(localtoviewmat, viewmat, obmat);
- invert_m4_m4(invlocaltoviewmat, localtoviewmat);
- GPU_shader_uniform_vector(shader, material->invlocaltoviewmatloc, 16, 1, (float *)invlocaltoviewmat);
- }
- }
- if (material->builtins & GPU_OBCOLOR) {
- copy_v4_v4(col, obcol);
- CLAMP(col[3], 0.0f, 1.0f);
- GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col);
- }
- if (material->builtins & GPU_AUTO_BUMPSCALE) {
- GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale);
- }
- if (material->builtins & GPU_PARTICLE_SCALAR_PROPS) {
- GPU_shader_uniform_vector(shader, material->partscalarpropsloc, 4, 1, pi->scalprops);
- }
- if (material->builtins & GPU_PARTICLE_LOCATION) {
- GPU_shader_uniform_vector(shader, material->partcoloc, 4, 1, pi->location);
- }
- if (material->builtins & GPU_PARTICLE_VELOCITY) {
- GPU_shader_uniform_vector(shader, material->partvel, 3, 1, pi->velocity);
- }
- if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) {
- GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity);
- }
- if (material->builtins & GPU_OBJECT_INFO) {
- GPU_shader_uniform_vector(shader, material->objectinfoloc, 3, 1, object_info);
+ if (material->sss_profile != NULL) {
+ GPU_uniformbuffer_free(material->sss_profile);
}
+ MEM_freeN(material);
}
-}
-void GPU_material_unbind(GPUMaterial *material)
-{
- if (material->pass) {
- material->bound = 0;
- GPU_pass_unbind(material->pass);
- }
+ BLI_freelistN(gpumaterial);
}
-bool GPU_material_bound(GPUMaterial *material)
+GPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
{
- return material->bound;
+ return material->builtins;
}
Scene *GPU_material_scene(GPUMaterial *material)
@@ -490,1735 +189,478 @@ GPUMatType GPU_Material_get_type(GPUMaterial *material)
return material->type;
}
-
-void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
+GPUPass *GPU_material_get_pass(GPUMaterial *material)
{
- *attribs = material->attribs;
+ return material->pass;
}
-void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
+ListBase *GPU_material_get_inputs(GPUMaterial *material)
{
- if (!material->outlink)
- material->outlink = link;
+ return &material->inputs;
}
-void GPU_material_enable_alpha(GPUMaterial *material)
+GPUUniformBuffer *GPU_material_get_uniform_buffer(GPUMaterial *material)
{
- material->alpha = 1;
+ return material->ubo;
}
-GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4])
+/**
+ * Create dynamic UBO from parameters
+ * \param ListBase of BLI_genericNodeN(GPUInput)
+ */
+void GPU_material_create_uniform_buffer(GPUMaterial *material, ListBase *inputs)
{
- if (material->alpha || (material->obcolalpha && obcol[3] < 1.0f))
- return GPU_BLEND_ALPHA;
- else
- return GPU_BLEND_SOLID;
+ material->ubo = GPU_uniformbuffer_dynamic_create(inputs, NULL);
}
-void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
+void GPU_material_uniform_buffer_tag_dirty(ListBase *gpumaterials)
{
- BLI_addtail(&material->nodes, node);
+ for (LinkData *link = gpumaterials->first; link; link = link->next) {
+ GPUMaterial *material = link->data;
+ if (material->ubo != NULL) {
+ GPU_uniformbuffer_tag_dirty(material->ubo);
+ }
+ if (material->sss_profile != NULL) {
+ material->sss_dirty = true;
+ }
+ }
}
-/* Code generation */
+/* Eevee Subsurface scattering. */
+/* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */
-bool GPU_material_do_color_management(GPUMaterial *mat)
-{
- if (!BKE_scene_check_color_management_enabled(mat->scene))
- return false;
+#define SSS_SAMPLES 65
+#define SSS_EXPONENT 2.0f /* Importance sampling exponent */
- return true;
-}
+typedef struct GPUSssKernelData {
+ float kernel[SSS_SAMPLES][4];
+ float param[3], max_radius;
+ int samples;
+} GPUSssKernelData;
-bool GPU_material_use_new_shading_nodes(GPUMaterial *mat)
+static void sss_calculate_offsets(GPUSssKernelData *kd, int count, float exponent)
{
- return BKE_scene_use_new_shading_nodes(mat->scene);
-}
-
-bool GPU_material_use_world_space_shading(GPUMaterial *mat)
-{
- return BKE_scene_use_world_space_shading(mat->scene);
+ float step = 2.0f / (float)(count - 1);
+ for (int i = 0; i < count; i++) {
+ float o = ((float)i) * step - 1.0f;
+ float sign = (o < 0.0f) ? -1.0f : 1.0f;
+ float ofs = sign * fabsf(powf(o, exponent));
+ kd->kernel[i][3] = ofs;
+ }
}
-static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist)
+#define GAUSS_TRUNCATE 12.46f
+static float gaussian_profile(float r, float radius)
{
- GPUNodeLink *visifac;
-
- /* from get_lamp_visibility */
- if (lamp->type == LA_SUN || lamp->type == LA_HEMI) {
- mat->dynproperty |= DYN_LAMP_VEC;
- GPU_link(mat, "lamp_visibility_sun_hemi",
- GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac);
- return visifac;
- }
- else {
- mat->dynproperty |= DYN_LAMP_CO;
- GPU_link(mat, "lamp_visibility_other",
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac);
-
- if (lamp->type == LA_AREA)
- return visifac;
-
- switch (lamp->falloff_type) {
- case LA_FALLOFF_CONSTANT:
- break;
- case LA_FALLOFF_INVLINEAR:
- GPU_link(mat, "lamp_falloff_invlinear",
- GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), *dist, &visifac);
- break;
- case LA_FALLOFF_INVSQUARE:
- GPU_link(mat, "lamp_falloff_invsquare",
- GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), *dist, &visifac);
- break;
- case LA_FALLOFF_SLIDERS:
- GPU_link(mat, "lamp_falloff_sliders",
- GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob),
- GPU_dynamic_uniform(&lamp->att1, GPU_DYNAMIC_LAMP_ATT1, lamp->ob),
- GPU_dynamic_uniform(&lamp->att2, GPU_DYNAMIC_LAMP_ATT2, lamp->ob), *dist, &visifac);
- break;
- case LA_FALLOFF_INVCOEFFICIENTS:
- GPU_link(mat, "lamp_falloff_invcoefficients",
- GPU_dynamic_uniform(&lamp->coeff_const, GPU_DYNAMIC_LAMP_COEFFCONST, lamp->ob),
- GPU_dynamic_uniform(&lamp->coeff_lin, GPU_DYNAMIC_LAMP_COEFFLIN, lamp->ob),
- GPU_dynamic_uniform(&lamp->coeff_quad, GPU_DYNAMIC_LAMP_COEFFQUAD, lamp->ob), *dist, &visifac);
- break;
- case LA_FALLOFF_CURVE:
- {
- float *array;
- int size;
-
- curvemapping_initialize(lamp->curfalloff);
- curvemapping_table_RGBA(lamp->curfalloff, &array, &size);
- GPU_link(mat, "lamp_falloff_curve",
- GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob),
- GPU_texture(size, array), *dist, &visifac);
-
- break;
- }
- }
-
- if (lamp->mode & LA_SPHERE)
- GPU_link(mat, "lamp_visibility_sphere",
- GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob),
- *dist, visifac, &visifac);
-
- if (lamp->type == LA_SPOT) {
- GPUNodeLink *inpr;
+ const float v = radius * radius * (0.25f * 0.25f);
+ const float Rm = sqrtf(v * GAUSS_TRUNCATE);
- if (lamp->mode & LA_SQUARE) {
- mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT;
- GPU_link(mat, "lamp_visibility_spot_square",
- GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob),
- GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob),
- GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr);
- }
- else {
- mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_IMAT;
- GPU_link(mat, "lamp_visibility_spot_circle",
- GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob),
- GPU_dynamic_uniform((float *)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob),
- GPU_dynamic_uniform((float *)lamp->spotvec, GPU_DYNAMIC_LAMP_SPOTSCALE, lamp->ob), *lv, &inpr);
- }
-
- GPU_link(mat, "lamp_visibility_spot",
- GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob),
- GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTBLEND, lamp->ob),
- inpr, visifac, &visifac);
- }
-
- GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac);
-
- return visifac;
+ if (r >= Rm) {
+ return 0.0f;
}
+ return expf(-r * r / (2.0f * v)) / (2.0f * M_PI * v);
}
-#if 0
-static void area_lamp_vectors(LampRen *lar)
+#define BURLEY_TRUNCATE 16.0f
+#define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE)
+static float burley_profile(float r, float d)
{
- float xsize = 0.5f * lar->area_size, ysize = 0.5f * lar->area_sizey;
-
- /* make it smaller, so area light can be multisampled */
- float multifac = 1.0f / sqrtf((float)lar->ray_totsamp);
- xsize *= multifac;
- ysize *= multifac;
-
- /* corner vectors */
- lar->area[0][0] = lar->co[0] - xsize * lar->mat[0][0] - ysize * lar->mat[1][0];
- lar->area[0][1] = lar->co[1] - xsize * lar->mat[0][1] - ysize * lar->mat[1][1];
- lar->area[0][2] = lar->co[2] - xsize * lar->mat[0][2] - ysize * lar->mat[1][2];
-
- /* corner vectors */
- lar->area[1][0] = lar->co[0] - xsize * lar->mat[0][0] + ysize * lar->mat[1][0];
- lar->area[1][1] = lar->co[1] - xsize * lar->mat[0][1] + ysize * lar->mat[1][1];
- lar->area[1][2] = lar->co[2] - xsize * lar->mat[0][2] + ysize * lar->mat[1][2];
-
- /* corner vectors */
- lar->area[2][0] = lar->co[0] + xsize * lar->mat[0][0] + ysize * lar->mat[1][0];
- lar->area[2][1] = lar->co[1] + xsize * lar->mat[0][1] + ysize * lar->mat[1][1];
- lar->area[2][2] = lar->co[2] + xsize * lar->mat[0][2] + ysize * lar->mat[1][2];
-
- /* corner vectors */
- lar->area[3][0] = lar->co[0] + xsize * lar->mat[0][0] - ysize * lar->mat[1][0];
- lar->area[3][1] = lar->co[1] + xsize * lar->mat[0][1] - ysize * lar->mat[1][1];
- lar->area[3][2] = lar->co[2] + xsize * lar->mat[0][2] - ysize * lar->mat[1][2];
- /* only for correction button size, matrix size works on energy */
- lar->areasize = lar->dist * lar->dist / (4.0f * xsize * ysize);
+ float exp_r_3_d = expf(-r / (3.0f * d));
+ float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
+ return (exp_r_d + exp_r_3_d) / (4.0f * d);
}
-#endif
-static void ramp_blend(
- GPUMaterial *mat, GPUNodeLink *fac, GPUNodeLink *col1, GPUNodeLink *col2, int type,
- GPUNodeLink **r_col)
+static float cubic_profile(float r, float radius, float sharpness)
{
- static const char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub",
- "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light",
- "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat",
- "mix_val", "mix_color", "mix_soft", "mix_linear"};
-
- GPU_link(mat, names[type], fac, col1, col2, r_col);
-}
+ float Rm = radius * (1.0f + sharpness);
-static void BKE_colorband_eval_blend(
- GPUMaterial *mat, ColorBand *coba, GPUNodeLink *fac, float rampfac, int type,
- GPUNodeLink *incol, GPUNodeLink **r_col)
-{
- GPUNodeLink *tmp, *alpha, *col;
- float *array;
- int size;
-
- /* do colorband */
- BKE_colorband_evaluate_table_rgba(coba, &array, &size);
- GPU_link(mat, "valtorgb", fac, GPU_texture(size, array), &col, &tmp);
-
- /* use alpha in fac */
- GPU_link(mat, "mtex_alpha_from_col", col, &alpha);
- GPU_link(mat, "math_multiply", alpha, GPU_uniform(&rampfac), &fac);
-
- /* blending method */
- ramp_blend(mat, fac, incol, col, type, r_col);
-}
-
-static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff)
-{
- Material *ma = shi->mat;
- GPUMaterial *mat = shi->gpumat;
-
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS)) {
- if (ma->ramp_col) {
- if (ma->rampin_col == MA_RAMP_IN_RESULT) {
- GPUNodeLink *fac;
- GPU_link(mat, "ramp_rgbtobw", *diff, &fac);
-
- /* colorband + blend */
- BKE_colorband_eval_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, *diff, diff);
- }
- }
+ if (r >= Rm) {
+ return 0.0f;
}
-}
+ /* custom variation with extra sharpness, to match the previous code */
+ const float y = 1.0f / (1.0f + sharpness);
+ float Rmy, ry, ryinv;
-static void add_to_diffuse(
- GPUMaterial *mat, Material *ma, GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *rgb,
- GPUNodeLink **r_diff)
-{
- GPUNodeLink *fac, *tmp, *addcol;
-
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) &&
- ma->ramp_col && (ma->mode & MA_RAMP_COL))
- {
- /* MA_RAMP_IN_RESULT is exceptional */
- if (ma->rampin_col == MA_RAMP_IN_RESULT) {
- addcol = shi->rgb;
- }
- else {
- /* input */
- switch (ma->rampin_col) {
- case MA_RAMP_IN_ENERGY:
- GPU_link(mat, "ramp_rgbtobw", rgb, &fac);
- break;
- case MA_RAMP_IN_SHADER:
- fac = is;
- break;
- case MA_RAMP_IN_NOR:
- GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
- break;
- default:
- GPU_link(mat, "set_value_zero", &fac);
- break;
- }
+ Rmy = powf(Rm, y);
+ ry = powf(r, y);
+ ryinv = (r > 0.0f) ? powf(r, y - 1.0f) : 0.0f;
- /* colorband + blend */
- BKE_colorband_eval_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, shi->rgb, &addcol);
- }
- }
- else
- addcol = shi->rgb;
+ const float Rmy5 = (Rmy * Rmy) * (Rmy * Rmy) * Rmy;
+ const float f = Rmy - ry;
+ const float num = f * (f * f) * (y * ryinv);
- /* output to */
- GPU_link(mat, "shade_madd", *r_diff, rgb, addcol, r_diff);
+ return (10.0f * num) / (Rmy5 * M_PI);
}
-static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec)
+static float eval_profile(float r, short falloff_type, float sharpness, float param)
{
- Material *ma = shi->mat;
- GPUMaterial *mat = shi->gpumat;
+ r = fabsf(r);
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) &&
- ma->ramp_spec && ma->rampin_spec == MA_RAMP_IN_RESULT)
+ if (falloff_type == SHD_SUBSURFACE_BURLEY ||
+ falloff_type == SHD_SUBSURFACE_RANDOM_WALK)
{
- GPUNodeLink *fac;
- GPU_link(mat, "ramp_rgbtobw", *spec, &fac);
-
- /* colorband + blend */
- BKE_colorband_eval_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec);
+ return burley_profile(r, param) / BURLEY_TRUNCATE_CDF;
}
-}
-
-static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec)
-{
- Material *ma = shi->mat;
- GPUMaterial *mat = shi->gpumat;
- GPUNodeLink *fac, *tmp;
-
- *spec = shi->specrgb;
-
- /* MA_RAMP_IN_RESULT is exception */
- if (ma->ramp_spec && (ma->rampin_spec != MA_RAMP_IN_RESULT)) {
-
- /* input */
- switch (ma->rampin_spec) {
- case MA_RAMP_IN_ENERGY:
- fac = t;
- break;
- case MA_RAMP_IN_SHADER:
- fac = is;
- break;
- case MA_RAMP_IN_NOR:
- GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
- break;
- default:
- GPU_link(mat, "set_value_zero", &fac);
- break;
- }
-
- /* colorband + blend */
- BKE_colorband_eval_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec);
+ else if (falloff_type == SHD_SUBSURFACE_CUBIC) {
+ return cubic_profile(r, param, sharpness);
+ }
+ else {
+ return gaussian_profile(r, param);
}
}
-static void add_user_list(ListBase *list, void *data)
-{
- LinkData *link = MEM_callocN(sizeof(LinkData), "GPULinkData");
- link->data = data;
- BLI_addtail(list, link);
-}
-
-static void shade_light_textures(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **rgb)
+/* Resolution for each sample of the precomputed kernel profile */
+#define INTEGRAL_RESOLUTION 32
+static float eval_integral(float x0, float x1, short falloff_type, float sharpness, float param)
{
- for (int i = 0; i < MAX_MTEX; ++i) {
- MTex *mtex = lamp->la->mtex[i];
-
- if (mtex && mtex->tex && (mtex->tex->type & TEX_IMAGE) && mtex->tex->ima) {
- mat->dynproperty |= DYN_LAMP_PERSMAT;
-
- float one = 1.0f;
- GPUNodeLink *tex_rgb;
+ const float range = x1 - x0;
+ const float step = range / INTEGRAL_RESOLUTION;
+ float integral = 0.0f;
- GPU_link(mat, "shade_light_texture",
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_image(mtex->tex->ima, &mtex->tex->iuser, false),
- GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
- &tex_rgb);
- texture_rgb_blend(mat, tex_rgb, *rgb, GPU_uniform(&one), GPU_uniform(&mtex->colfac), mtex->blendtype, rgb);
- }
+ for (int i = 0; i < INTEGRAL_RESOLUTION; ++i) {
+ float x = x0 + range * ((float)i + 0.5f) / (float)INTEGRAL_RESOLUTION;
+ float y = eval_profile(x, falloff_type, sharpness, param);
+ integral += y * step;
}
+
+ return integral;
}
+#undef INTEGRAL_RESOLUTION
-static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp)
+static void compute_sss_kernel(
+ GPUSssKernelData *kd, float *radii, int sample_ct, int falloff_type, float sharpness)
{
- Material *ma = shi->mat;
- GPUMaterial *mat = shi->gpumat;
- GPUNodeLink *lv, *dist, *is, *inp, *i;
- GPUNodeLink *outcol, *specfac, *t, *shadfac = NULL, *lcol;
- float one = 1.0f;
-
- if ((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW))
- return;
-
- GPUNodeLink *vn = shi->vn;
- GPUNodeLink *view = shi->view;
+ float rad[3];
+ /* Minimum radius */
+ rad[0] = MAX2(radii[0], 1e-15f);
+ rad[1] = MAX2(radii[1], 1e-15f);
+ rad[2] = MAX2(radii[2], 1e-15f);
- GPUNodeLink *visifac = lamp_get_visibility(mat, lamp, &lv, &dist);
+ /* Christensen-Burley fitting */
+ float l[3], d[3];
-#if 0
- if (ma->mode & MA_TANGENT_V)
- GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);
-#endif
-
- GPU_link(mat, "shade_inp", vn, lv, &inp);
+ if (falloff_type == SHD_SUBSURFACE_BURLEY ||
+ falloff_type == SHD_SUBSURFACE_RANDOM_WALK)
+ {
+ mul_v3_v3fl(l, rad, 0.25f * M_1_PI);
+ const float A = 1.0f;
+ const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
+ /* XXX 0.6f Out of nowhere to match cycles! Empirical! Can be tweak better. */
+ mul_v3_v3fl(d, l, 0.6f / s);
+ mul_v3_v3fl(rad, d, BURLEY_TRUNCATE);
+ kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
- if (lamp->mode & LA_NO_DIFF) {
- GPU_link(mat, "shade_is_no_diffuse", &is);
+ copy_v3_v3(kd->param, d);
}
- else if (lamp->type == LA_HEMI) {
- GPU_link(mat, "shade_is_hemi", inp, &is);
+ else if (falloff_type == SHD_SUBSURFACE_CUBIC) {
+ copy_v3_v3(kd->param, rad);
+ mul_v3_fl(rad, 1.0f + sharpness);
+ kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
}
else {
- if (lamp->type == LA_AREA) {
- float area[4][4] = {{0.0f}}, areasize = 0.0f;
-
- mat->dynproperty |= DYN_LAMP_VEC | DYN_LAMP_CO;
- GPU_link(mat, "shade_inp_area",
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob),
- GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), vn,
- GPU_uniform((float *)area),
- GPU_uniform(&areasize),
- GPU_uniform(&lamp->k), &inp);
- }
+ kd->max_radius = MAX3(rad[0], rad[1], rad[2]);
- is = inp; /* Lambert */
-
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS)) {
- if (ma->diff_shader == MA_DIFF_ORENNAYAR)
- GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view,
- GPU_uniform(&ma->roughness), &is);
- else if (ma->diff_shader == MA_DIFF_TOON)
- GPU_link(mat, "shade_diffuse_toon", vn, lv, view,
- GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
- else if (ma->diff_shader == MA_DIFF_MINNAERT)
- GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view,
- GPU_uniform(&ma->darkness), &is);
- else if (ma->diff_shader == MA_DIFF_FRESNEL)
- GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view,
- GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
- }
+ copy_v3_v3(kd->param, rad);
}
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS))
- if (ma->shade_flag & MA_CUBIC)
- GPU_link(mat, "shade_cubic", is, &is);
-
- i = is;
- GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i);
-
- GPU_link(mat, "set_rgb", GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &lcol);
- shade_light_textures(mat, lamp, &lcol);
- GPU_link(mat, "shade_mul_value_v3",
- GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob), lcol, &lcol);
-
-#if 0
- if (ma->mode & MA_TANGENT_VN)
- GPU_link(mat, "shade_tangent_v_spec", GPU_attribute(CD_TANGENT, ""), &vn);
-#endif
+ /* Compute samples locations on the 1d kernel [-1..1] */
+ sss_calculate_offsets(kd, sample_ct, SSS_EXPONENT);
- /* this replaces if (i > 0.0) conditional until that is supported */
- /* done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i); */
-
- if ((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) {
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS)) {
- mat->dynproperty |= DYN_LAMP_PERSMAT;
-
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- GPU_link(mat, "test_shadowbuf_vsm",
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
- GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
- GPU_uniform(&lamp->bias), GPU_uniform(&lamp->la->bleedbias), inp, &shadfac);
- }
- else {
- GPU_link(mat, "test_shadowbuf",
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
- GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
- GPU_uniform(&lamp->bias), inp, &shadfac);
- }
-
- if (lamp->mode & LA_ONLYSHADOW) {
- GPUNodeLink *shadrgb;
- GPU_link(mat, "shade_only_shadow", i, shadfac,
- GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob),
- GPU_uniform(lamp->shadow_color), &shadrgb);
-
- if (!(lamp->mode & LA_NO_DIFF)) {
- GPU_link(mat, "shade_only_shadow_diffuse", shadrgb, shi->rgb,
- shr->diff, &shr->diff);
- }
-
- if (!(lamp->mode & LA_NO_SPEC)) {
- GPU_link(mat, "shade_only_shadow_specular", shadrgb, shi->specrgb,
- shr->spec, &shr->spec);
- }
-
- add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, shi->gpumat->ma);
- return;
- }
- }
- }
- else if ((mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && (lamp->mode & LA_ONLYSHADOW)) {
- add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, shi->gpumat->ma);
- return;
- }
- else
- GPU_link(mat, "set_value", GPU_uniform(&one), &shadfac);
-
- if (GPU_link_changed(shi->refl) || ma->ref != 0.0f) {
- if (!(lamp->mode & LA_NO_DIFF)) {
- GPUNodeLink *rgb;
- GPU_link(mat, "shade_mul_value", i, lcol, &rgb);
- GPU_link(mat, "mtex_value_invert", shadfac, &shadfac);
- GPU_link(mat, "mix_mult", shadfac, rgb, GPU_uniform(lamp->shadow_color), &rgb);
- GPU_link(mat, "mtex_value_invert", shadfac, &shadfac);
- add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff);
- }
- }
+ /* Weights sum for normalization */
+ float sum[3] = {0.0f, 0.0f, 0.0f};
- if (mat->scene->gm.flag & GAME_GLSL_NO_SHADERS) {
- /* pass */
- }
- else if (!(lamp->mode & LA_NO_SPEC) && !(lamp->mode & LA_ONLYSHADOW) &&
- (GPU_link_changed(shi->spec) || ma->spec != 0.0f))
- {
- if (lamp->type == LA_HEMI) {
- GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t);
- GPU_link(mat, "shade_add_spec", t, lcol, shi->specrgb, &outcol);
- GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
+ /* Compute integral of each sample footprint */
+ for (int i = 0; i < sample_ct; i++) {
+ float x0, x1;
+
+ if (i == 0) {
+ x0 = kd->kernel[0][3] - fabsf(kd->kernel[0][3] - kd->kernel[1][3]) / 2.0f;
}
else {
- if (ma->spec_shader == MA_SPEC_PHONG) {
- GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac);
- }
- else if (ma->spec_shader == MA_SPEC_COOKTORR) {
- GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac);
- }
- else if (ma->spec_shader == MA_SPEC_BLINN) {
- GPU_link(mat, "shade_blinn_spec", vn, lv, view,
- GPU_uniform(&ma->refrac), shi->har, &specfac);
- }
- else if (ma->spec_shader == MA_SPEC_WARDISO) {
- GPU_link(mat, "shade_wardiso_spec", vn, lv, view,
- GPU_uniform(&ma->rms), &specfac);
- }
- else {
- GPU_link(mat, "shade_toon_spec", vn, lv, view,
- GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac);
- }
-
- if (lamp->type == LA_AREA)
- GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac);
-
- GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t);
-
- if (ma->mode & MA_RAMP_SPEC) {
- GPUNodeLink *spec;
- do_specular_ramp(shi, specfac, t, &spec);
- GPU_link(mat, "shade_add_spec", t, lcol, spec, &outcol);
- GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
- }
- else {
- GPU_link(mat, "shade_add_spec", t, lcol, shi->specrgb, &outcol);
- GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
- }
+ x0 = (kd->kernel[i - 1][3] + kd->kernel[i][3]) / 2.0f;
}
- }
- add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, shi->gpumat->ma);
-}
-
-static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
-{
- Base *base;
- Scene *sce_iter;
-
- for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) {
- Object *ob = base->object;
-
- if (ob->type == OB_LAMP) {
- GPULamp *lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL);
- if (lamp)
- shade_one_light(shi, shr, lamp);
+ if (i == sample_ct - 1) {
+ x1 = kd->kernel[sample_ct - 1][3] + fabsf(kd->kernel[sample_ct - 2][3] - kd->kernel[sample_ct - 1][3]) / 2.0f;
+ }
+ else {
+ x1 = (kd->kernel[i][3] + kd->kernel[i + 1][3]) / 2.0f;
}
- if (ob->transflag & OB_DUPLI) {
- ListBase *lb = object_duplilist(G.main->eval_ctx, shi->gpumat->scene, ob);
-
- for (DupliObject *dob = lb->first; dob; dob = dob->next) {
- Object *ob_iter = dob->ob;
+ x0 *= kd->max_radius;
+ x1 *= kd->max_radius;
- if (ob_iter->type == OB_LAMP) {
- float omat[4][4];
- copy_m4_m4(omat, ob_iter->obmat);
- copy_m4_m4(ob_iter->obmat, dob->mat);
+ kd->kernel[i][0] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[0]);
+ kd->kernel[i][1] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[1]);
+ kd->kernel[i][2] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[2]);
- GPULamp *lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob_iter, ob);
- if (lamp)
- shade_one_light(shi, shr, lamp);
+ sum[0] += kd->kernel[i][0];
+ sum[1] += kd->kernel[i][1];
+ sum[2] += kd->kernel[i][2];
+ }
- copy_m4_m4(ob_iter->obmat, omat);
- }
+ for (int i = 0; i < 3; ++i) {
+ if (sum[i] > 0.0f) {
+ /* Normalize */
+ for (int j = 0; j < sample_ct; j++) {
+ kd->kernel[j][i] /= sum[i];
}
-
- free_object_duplilist(lb);
+ }
+ else {
+ /* Avoid 0 kernel sum. */
+ kd->kernel[sample_ct / 2][i] = 1.0f;
}
}
- /* prevent only shadow lamps from producing negative colors.*/
- GPU_link(shi->gpumat, "shade_clamp_positive", shr->spec, &shr->spec);
- GPU_link(shi->gpumat, "shade_clamp_positive", shr->diff, &shr->diff);
-}
-
-static void texture_rgb_blend(
- GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg,
- int blendtype, GPUNodeLink **in)
-{
- switch (blendtype) {
- case MTEX_BLEND:
- GPU_link(mat, "mtex_rgb_blend", out, tex, fact, facg, in);
- break;
- case MTEX_MUL:
- GPU_link(mat, "mtex_rgb_mul", out, tex, fact, facg, in);
- break;
- case MTEX_SCREEN:
- GPU_link(mat, "mtex_rgb_screen", out, tex, fact, facg, in);
- break;
- case MTEX_OVERLAY:
- GPU_link(mat, "mtex_rgb_overlay", out, tex, fact, facg, in);
- break;
- case MTEX_SUB:
- GPU_link(mat, "mtex_rgb_sub", out, tex, fact, facg, in);
- break;
- case MTEX_ADD:
- GPU_link(mat, "mtex_rgb_add", out, tex, fact, facg, in);
- break;
- case MTEX_DIV:
- GPU_link(mat, "mtex_rgb_div", out, tex, fact, facg, in);
- break;
- case MTEX_DIFF:
- GPU_link(mat, "mtex_rgb_diff", out, tex, fact, facg, in);
- break;
- case MTEX_DARK:
- GPU_link(mat, "mtex_rgb_dark", out, tex, fact, facg, in);
- break;
- case MTEX_LIGHT:
- GPU_link(mat, "mtex_rgb_light", out, tex, fact, facg, in);
- break;
- case MTEX_BLEND_HUE:
- GPU_link(mat, "mtex_rgb_hue", out, tex, fact, facg, in);
- break;
- case MTEX_BLEND_SAT:
- GPU_link(mat, "mtex_rgb_sat", out, tex, fact, facg, in);
- break;
- case MTEX_BLEND_VAL:
- GPU_link(mat, "mtex_rgb_val", out, tex, fact, facg, in);
- break;
- case MTEX_BLEND_COLOR:
- GPU_link(mat, "mtex_rgb_color", out, tex, fact, facg, in);
- break;
- case MTEX_SOFT_LIGHT:
- GPU_link(mat, "mtex_rgb_soft", out, tex, fact, facg, in);
- break;
- case MTEX_LIN_LIGHT:
- GPU_link(mat, "mtex_rgb_linear", out, tex, fact, facg, in);
- break;
- default:
- GPU_link(mat, "set_rgb_zero", &in);
- break;
+ /* Put center sample at the start of the array (to sample first) */
+ float tmpv[4];
+ copy_v4_v4(tmpv, kd->kernel[sample_ct / 2]);
+ for (int i = sample_ct / 2; i > 0; i--) {
+ copy_v4_v4(kd->kernel[i], kd->kernel[i - 1]);
}
-}
+ copy_v4_v4(kd->kernel[0], tmpv);
-static void texture_value_blend(
- GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg,
- int blendtype, GPUNodeLink **in)
-{
- switch (blendtype) {
- case MTEX_BLEND:
- GPU_link(mat, "mtex_value_blend", out, tex, fact, facg, in);
- break;
- case MTEX_MUL:
- GPU_link(mat, "mtex_value_mul", out, tex, fact, facg, in);
- break;
- case MTEX_SCREEN:
- GPU_link(mat, "mtex_value_screen", out, tex, fact, facg, in);
- break;
- case MTEX_SUB:
- GPU_link(mat, "mtex_value_sub", out, tex, fact, facg, in);
- break;
- case MTEX_ADD:
- GPU_link(mat, "mtex_value_add", out, tex, fact, facg, in);
- break;
- case MTEX_DIV:
- GPU_link(mat, "mtex_value_div", out, tex, fact, facg, in);
- break;
- case MTEX_DIFF:
- GPU_link(mat, "mtex_value_diff", out, tex, fact, facg, in);
- break;
- case MTEX_DARK:
- GPU_link(mat, "mtex_value_dark", out, tex, fact, facg, in);
- break;
- case MTEX_LIGHT:
- GPU_link(mat, "mtex_value_light", out, tex, fact, facg, in);
- break;
- default:
- GPU_link(mat, "set_value_zero", &in);
- break;
- }
+ kd->samples = sample_ct;
}
-static void do_material_tex(GPUShadeInput *shi)
+#define INTEGRAL_RESOLUTION 512
+static void compute_sss_translucence_kernel(
+ const GPUSssKernelData *kd, int resolution, short falloff_type, float sharpness, float **output)
{
- Material *ma = shi->mat;
- GPUMaterial *mat = shi->gpumat;
- MTex *mtex;
- Tex *tex;
- GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac;
- GPUNodeLink *texco_norm, *texco_orco, *texco_object;
- GPUNodeLink *texco_global, *texco_uv = NULL;
- GPUNodeLink *newnor, *orn;
- float one = 1.0f;
- int rgbnor, talpha;
- bool init_done = false;
- int iBumpSpacePrev = 0; /* Not necessary, quieting gcc warning. */
- GPUNodeLink *vNorg, *vNacc, *fPrevMagnitude;
- int iFirstTimeNMap = 1;
- bool found_deriv_map = false;
-
- GPU_link(mat, "set_value", GPU_uniform(&one), &stencil);
-
- GPU_link(mat, "texco_norm", GPU_builtin(GPU_VIEW_NORMAL), &texco_norm);
- GPU_link(mat, "texco_orco", GPU_attribute(CD_ORCO, ""), &texco_orco);
- GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
- GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
- GPU_builtin(GPU_VIEW_POSITION), &texco_object);
-#if 0
- GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent);
-#endif
- GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
- GPU_builtin(GPU_VIEW_POSITION), &texco_global);
-
- orn = texco_norm;
-
- /* go over texture slots */
- for (int tex_nr = 0; tex_nr < MAX_MTEX; tex_nr++) {
- /* separate tex switching */
- if (ma->septex & (1 << tex_nr)) continue;
-
- if (ma->mtex[tex_nr]) {
- mtex = ma->mtex[tex_nr];
-
- tex = mtex->tex;
- if (tex == NULL) continue;
-
- /* which coords */
- if (mtex->texco == TEXCO_ORCO)
- texco = texco_orco;
- else if (mtex->texco == TEXCO_OBJECT)
- texco = texco_object;
- else if (mtex->texco == TEXCO_NORM)
- texco = orn;
- else if (mtex->texco == TEXCO_TANGENT)
- texco = texco_object;
- else if (mtex->texco == TEXCO_GLOB)
- texco = texco_global;
- else if (mtex->texco == TEXCO_REFL) {
- GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
- texco = shi->ref;
- }
- else if (mtex->texco == TEXCO_UV) {
- if (1) { //!(texco_uv && strcmp(mtex->uvname, lastuvname) == 0)) {
- GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv);
- /*lastuvname = mtex->uvname;*/ /*UNUSED*/
- }
- texco = texco_uv;
- }
- else
- continue;
-
- /* in case of uv, this would just undo a multiplication in texco_uv */
- if (mtex->texco != TEXCO_UV)
- GPU_link(mat, "mtex_2d_mapping", texco, &texco);
-
- if (mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f)
- GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco);
-
- float ofs[3] = {
- mtex->ofs[0] + 0.5f - 0.5f * mtex->size[0],
- mtex->ofs[1] + 0.5f - 0.5f * mtex->size[1],
- 0.0f
- };
-
- if (ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f)
- GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco);
-
- talpha = 0;
-
- if (tex && tex->ima &&
- ((tex->type == TEX_IMAGE) ||
- ((tex->type == TEX_ENVMAP) && (mtex->texco == TEXCO_REFL))))
- {
- if (tex->type == TEX_IMAGE) {
- GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false), &tin, &trgb);
- }
- else {
- GPU_link(mat, "mtex_cube_map_refl",
- GPU_cube_map(tex->ima, &tex->iuser, false), shi->view, shi->vn,
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
- GPU_builtin(GPU_VIEW_MATRIX), &tin, &trgb);
- }
- rgbnor = TEX_RGB;
-
- talpha = ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0);
- }
- else {
- continue;
- }
+ float (*texels)[4];
+ texels = MEM_callocN(sizeof(float) * 4 * resolution, "compute_sss_translucence_kernel");
+ *output = (float *)texels;
- /* texture output */
- if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
- GPU_link(mat, "mtex_rgbtoint", trgb, &tin);
- rgbnor -= TEX_RGB;
- }
+ /* Last texel should be black, hence the - 1. */
+ for (int i = 0; i < resolution - 1; ++i) {
+ /* Distance from surface. */
+ float d = kd->max_radius * ((float)i + 0.00001f) / ((float)resolution);
- if (mtex->texflag & MTEX_NEGATIVE) {
- if (rgbnor & TEX_RGB)
- GPU_link(mat, "mtex_rgb_invert", trgb, &trgb);
- else
- GPU_link(mat, "mtex_value_invert", tin, &tin);
- }
+ /* For each distance d we compute the radiance incomming from an hypothetic parallel plane. */
+ /* Compute radius of the footprint on the hypothetic plane */
+ float r_fp = sqrtf(kd->max_radius * kd->max_radius - d * d);
+ float r_step = r_fp / INTEGRAL_RESOLUTION;
+ float area_accum = 0.0f;
+ for (float r = 0.0f; r < r_fp; r += r_step) {
+ /* Compute distance to the "shading" point through the medium. */
+ /* r_step * 0.5f to put sample between the area borders */
+ float dist = hypotf(r + r_step * 0.5f, d);
- if (mtex->texflag & MTEX_STENCIL) {
- if (rgbnor & TEX_RGB)
- GPU_link(mat, "mtex_rgb_stencil", stencil, trgb, &stencil, &trgb);
- else
- GPU_link(mat, "mtex_value_stencil", stencil, tin, &stencil, &tin);
- }
+ float profile[3];
+ profile[0] = eval_profile(dist, falloff_type, sharpness, kd->param[0]);
+ profile[1] = eval_profile(dist, falloff_type, sharpness, kd->param[1]);
+ profile[2] = eval_profile(dist, falloff_type, sharpness, kd->param[2]);
- /* mapping */
- if (mtex->mapto & (MAP_COL | MAP_COLSPEC | MAP_COLMIR)) {
- /* stencil maps on the texture control slider, not texture intensity value */
- if ((rgbnor & TEX_RGB) == 0) {
- GPU_link(mat, "set_rgb", GPU_uniform(&mtex->r), &tcol);
- }
- else {
- GPU_link(mat, "set_rgba", trgb, &tcol);
-
- if (mtex->mapto & MAP_ALPHA)
- GPU_link(mat, "set_value", stencil, &tin);
- else if (talpha)
- GPU_link(mat, "mtex_alpha_from_col", trgb, &tin);
- else
- GPU_link(mat, "set_value_one", &tin);
- }
-
- if ((tex->type == TEX_IMAGE) ||
- ((tex->type == TEX_ENVMAP) && (mtex->texco == TEXCO_REFL)))
- {
- if (GPU_material_do_color_management(mat)) {
- GPU_link(mat, "srgb_to_linearrgb", tcol, &tcol);
- }
- }
-
- if (mtex->mapto & MAP_COL) {
- GPUNodeLink *colfac;
-
- if (mtex->colfac == 1.0f) colfac = stencil;
- else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colfac), stencil, &colfac);
-
- texture_rgb_blend(mat, tcol, shi->rgb, tin, colfac, mtex->blendtype, &shi->rgb);
- }
-
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_COLSPEC)) {
- GPUNodeLink *colspecfac;
-
- if (mtex->colspecfac == 1.0f) colspecfac = stencil;
- else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colspecfac), stencil, &colspecfac);
-
- texture_rgb_blend(mat, tcol, shi->specrgb, tin, colspecfac, mtex->blendtype, &shi->specrgb);
- }
-
- if (mtex->mapto & MAP_COLMIR) {
- GPUNodeLink *colmirfac;
-
- if (mtex->mirrfac == 1.0f) colmirfac = stencil;
- else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->mirrfac), stencil, &colmirfac);
-
- /* exception for envmap only */
- if (tex->type == TEX_ENVMAP && mtex->blendtype == MTEX_BLEND) {
- GPU_link(mat, "mtex_mirror", tcol, shi->refcol, tin, colmirfac, &shi->refcol);
- }
- else
- texture_rgb_blend(mat, tcol, shi->mir, tin, colmirfac, mtex->blendtype, &shi->mir);
- }
- }
-
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) {
- if (tex->type == TEX_IMAGE) {
- found_deriv_map = tex->imaflag & TEX_DERIVATIVEMAP;
-
- if (tex->imaflag & TEX_NORMALMAP) {
- /* normalmap image */
- GPU_link(mat, "mtex_normal", texco, GPU_image(tex->ima, &tex->iuser, true), &tnor);
-
- if (mtex->norfac < 0.0f)
- GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor);
-
- if (mtex->normapspace == MTEX_NSPACE_TANGENT) {
- if (iFirstTimeNMap != 0) {
- // use unnormalized normal (this is how we bake it - closer to gamedev)
- GPUNodeLink *vNegNorm;
- GPU_link(mat, "vec_math_negate",
- GPU_builtin(GPU_VIEW_NORMAL), &vNegNorm);
- GPU_link(mat, "mtex_nspace_tangent",
- GPU_attribute(CD_TANGENT, ""), vNegNorm, tnor, &newnor);
- iFirstTimeNMap = 0;
- }
- else { /* otherwise use accumulated perturbations */
- GPU_link(mat, "mtex_nspace_tangent",
- GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor);
- }
- }
- else if (mtex->normapspace == MTEX_NSPACE_OBJECT) {
- /* transform normal by object then view matrix */
- GPU_link(mat, "mtex_nspace_object", tnor, &newnor);
- }
- else if (mtex->normapspace == MTEX_NSPACE_WORLD) {
- /* transform normal by view matrix */
- GPU_link(mat, "mtex_nspace_world", GPU_builtin(GPU_VIEW_MATRIX), tnor, &newnor);
- }
- else {
- /* no transform, normal in camera space */
- newnor = tnor;
- }
-
- float norfac = min_ff(fabsf(mtex->norfac), 1.0f);
-
- if (norfac == 1.0f && !GPU_link_changed(stencil)) {
- shi->vn = newnor;
- }
- else {
- tnorfac = GPU_uniform(&norfac);
-
- if (GPU_link_changed(stencil))
- GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac);
-
- GPU_link(mat, "mtex_blend_normal", tnorfac, shi->vn, newnor, &shi->vn);
- }
-
- }
- else if (found_deriv_map ||
- (mtex->texflag & (MTEX_3TAP_BUMP | MTEX_5TAP_BUMP | MTEX_BICUBIC_BUMP)))
- {
- /* ntap bumpmap image */
- int iBumpSpace;
- float ima_x, ima_y;
-
- float imag_tspace_dimension_x = 1024.0f; /* only used for texture space variant */
- float aspect = 1.0f;
-
- GPUNodeLink *vR1, *vR2;
- GPUNodeLink *dBs, *dBt, *fDet;
-
- float hScale = 0.1f; /* compatibility adjustment factor for all bumpspace types */
- if (mtex->texflag & MTEX_BUMP_TEXTURESPACE)
- hScale = 13.0f; /* factor for scaling texspace bumps */
- else if (found_deriv_map)
- hScale = 1.0f;
-
- /* resolve texture resolution */
- if ((mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
- ima_x = 512.0f; ima_y = 512.0f; /* prevent calling textureSize, glsl 1.3 only */
- if (ibuf) {
- ima_x = ibuf->x;
- ima_y = ibuf->y;
- aspect = (float)ima_y / ima_x;
- }
- BKE_image_release_ibuf(tex->ima, ibuf, NULL);
- }
-
- /* The negate on norfac is done because the
- * normal in the renderer points inward which corresponds
- * to inverting the bump map. Should this ever change
- * this negate must be removed. */
- float norfac = -hScale * mtex->norfac;
- if (found_deriv_map) {
- float fVirtDim = sqrtf(fabsf(ima_x * mtex->size[0] * ima_y * mtex->size[1]));
- norfac /= MAX2(fVirtDim, FLT_EPSILON);
- }
-
- tnorfac = GPU_uniform(&norfac);
-
- if (found_deriv_map)
- GPU_link(mat, "math_multiply", tnorfac, GPU_builtin(GPU_AUTO_BUMPSCALE), &tnorfac);
-
- if (GPU_link_changed(stencil))
- GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac);
-
- if (!init_done) {
- /* copy shi->vn to vNorg and vNacc, set magnitude to 1 */
- GPU_link(mat, "mtex_bump_normals_init", shi->vn, &vNorg, &vNacc, &fPrevMagnitude);
- iBumpSpacePrev = 0;
- init_done = true;
- }
-
- // find current bump space
- if (mtex->texflag & MTEX_BUMP_OBJECTSPACE)
- iBumpSpace = 1;
- else if (mtex->texflag & MTEX_BUMP_TEXTURESPACE)
- iBumpSpace = 2;
- else
- iBumpSpace = 4; /* ViewSpace */
-
- /* re-initialize if bump space changed */
- if (iBumpSpacePrev != iBumpSpace) {
- GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION);
-
- if (mtex->texflag & MTEX_BUMP_OBJECTSPACE)
- GPU_link(mat, "mtex_bump_init_objspace",
- surf_pos, vNorg,
- GPU_builtin(GPU_VIEW_MATRIX),
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
- GPU_builtin(GPU_OBJECT_MATRIX),
- GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
- fPrevMagnitude, vNacc,
- &fPrevMagnitude, &vNacc,
- &vR1, &vR2, &fDet);
-
- else if (mtex->texflag & MTEX_BUMP_TEXTURESPACE)
- GPU_link(mat, "mtex_bump_init_texturespace",
- surf_pos, vNorg,
- fPrevMagnitude, vNacc,
- &fPrevMagnitude, &vNacc,
- &vR1, &vR2, &fDet);
-
- else
- GPU_link(mat, "mtex_bump_init_viewspace",
- surf_pos, vNorg,
- fPrevMagnitude, vNacc,
- &fPrevMagnitude, &vNacc,
- &vR1, &vR2, &fDet);
-
- iBumpSpacePrev = iBumpSpace;
- }
-
-
- if (found_deriv_map) {
- GPU_link(mat, "mtex_bump_deriv",
- texco, GPU_image(tex->ima, &tex->iuser, true),
- GPU_uniform(&ima_x), GPU_uniform(&ima_y), tnorfac,
- &dBs, &dBt);
- }
- else if (mtex->texflag & MTEX_3TAP_BUMP)
- GPU_link(mat, "mtex_bump_tap3",
- texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
- &dBs, &dBt);
- else if (mtex->texflag & MTEX_5TAP_BUMP)
- GPU_link(mat, "mtex_bump_tap5",
- texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
- &dBs, &dBt);
- else if (mtex->texflag & MTEX_BICUBIC_BUMP) {
- if (GPU_bicubic_bump_support()) {
- GPU_link(mat, "mtex_bump_bicubic",
- texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
- &dBs, &dBt);
- }
- else {
- GPU_link(mat, "mtex_bump_tap5",
- texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
- &dBs, &dBt);
- }
- }
-
-
- if (mtex->texflag & MTEX_BUMP_TEXTURESPACE) {
- float imag_tspace_dimension_y = aspect * imag_tspace_dimension_x;
- GPU_link(mat, "mtex_bump_apply_texspace",
- fDet, dBs, dBt, vR1, vR2,
- GPU_image(tex->ima, &tex->iuser, true), texco,
- GPU_uniform(&imag_tspace_dimension_x),
- GPU_uniform(&imag_tspace_dimension_y), vNacc,
- &vNacc, &shi->vn);
- }
- else
- GPU_link(mat, "mtex_bump_apply",
- fDet, dBs, dBt, vR1, vR2, vNacc,
- &vNacc, &shi->vn);
-
- }
- }
-
- GPU_link(mat, "vec_math_negate", shi->vn, &orn);
- }
+ /* Since the profile and configuration are radially symetrical we
+ * can just evaluate it once and weight it accordingly */
+ float r_next = r + r_step;
+ float disk_area = (M_PI * r_next * r_next) - (M_PI * r * r);
- if ((mtex->mapto & MAP_VARS)) {
- if (rgbnor & TEX_RGB) {
- if (talpha)
- GPU_link(mat, "mtex_alpha_from_col", trgb, &tin);
- else
- GPU_link(mat, "mtex_rgbtoint", trgb, &tin);
- }
-
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_REF) {
- GPUNodeLink *difffac;
-
- if (mtex->difffac == 1.0f) difffac = stencil;
- else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->difffac), stencil, &difffac);
-
- texture_value_blend(
- mat, GPU_uniform(&mtex->def_var), shi->refl, tin, difffac,
- mtex->blendtype, &shi->refl);
- GPU_link(mat, "mtex_value_clamp_positive", shi->refl, &shi->refl);
- }
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_SPEC) {
- GPUNodeLink *specfac;
-
- if (mtex->specfac == 1.0f) specfac = stencil;
- else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->specfac), stencil, &specfac);
-
- texture_value_blend(
- mat, GPU_uniform(&mtex->def_var), shi->spec, tin, specfac,
- mtex->blendtype, &shi->spec);
- GPU_link(mat, "mtex_value_clamp_positive", shi->spec, &shi->spec);
- }
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_EMIT) {
- GPUNodeLink *emitfac;
-
- if (mtex->emitfac == 1.0f) emitfac = stencil;
- else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->emitfac), stencil, &emitfac);
-
- texture_value_blend(
- mat, GPU_uniform(&mtex->def_var), shi->emit, tin, emitfac,
- mtex->blendtype, &shi->emit);
- GPU_link(mat, "mtex_value_clamp_positive", shi->emit, &shi->emit);
- }
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_HAR) {
- GPUNodeLink *hardfac;
-
- if (mtex->hardfac == 1.0f) hardfac = stencil;
- else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->hardfac), stencil, &hardfac);
-
- GPU_link(mat, "mtex_har_divide", shi->har, &shi->har);
- texture_value_blend(
- mat, GPU_uniform(&mtex->def_var), shi->har, tin, hardfac,
- mtex->blendtype, &shi->har);
- GPU_link(mat, "mtex_har_multiply_clamp", shi->har, &shi->har);
- }
- if (mtex->mapto & MAP_ALPHA) {
- GPUNodeLink *alphafac;
-
- if (mtex->alphafac == 1.0f) alphafac = stencil;
- else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->alphafac), stencil, &alphafac);
-
- texture_value_blend(
- mat, GPU_uniform(&mtex->def_var), shi->alpha, tin, alphafac,
- mtex->blendtype, &shi->alpha);
- GPU_link(mat, "mtex_value_clamp", shi->alpha, &shi->alpha);
- }
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_AMB) {
- GPUNodeLink *ambfac;
-
- if (mtex->ambfac == 1.0f) ambfac = stencil;
- else GPU_link(mat, "math_multiply", GPU_uniform(&mtex->ambfac), stencil, &ambfac);
-
- texture_value_blend(
- mat, GPU_uniform(&mtex->def_var), shi->amb, tin, ambfac,
- mtex->blendtype, &shi->amb);
- GPU_link(mat, "mtex_value_clamp", shi->amb, &shi->amb);
- }
- }
+ mul_v3_fl(profile, disk_area);
+ add_v3_v3(texels[i], profile);
+ area_accum += disk_area;
}
+ /* Normalize over the disk. */
+ mul_v3_fl(texels[i], 1.0f / (area_accum));
}
-}
-
-void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi)
-{
- float one = 1.0f;
-
- memset(shi, 0, sizeof(*shi));
-
- shi->gpumat = mat;
- shi->mat = ma;
-
- GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&ma->r, GPU_DYNAMIC_MAT_DIFFRGB, ma), &shi->rgb);
- GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&ma->specr, GPU_DYNAMIC_MAT_SPECRGB, ma), &shi->specrgb);
- GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&ma->mirr, GPU_DYNAMIC_MAT_MIR, ma), &shi->mir);
- GPU_link(mat, "set_rgba_zero", &shi->refcol);
- GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn);
-
- if (mat->alpha)
- GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->alpha, GPU_DYNAMIC_MAT_ALPHA, ma), &shi->alpha);
- else
- GPU_link(mat, "set_value", GPU_uniform(&one), &shi->alpha);
-
- GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->ref, GPU_DYNAMIC_MAT_REF, ma), &shi->refl);
- GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->spec, GPU_DYNAMIC_MAT_SPEC, ma), &shi->spec);
- GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->emit, GPU_DYNAMIC_MAT_EMIT, ma), &shi->emit);
- GPU_link(mat, "set_value", GPU_dynamic_uniform((float *)&ma->har, GPU_DYNAMIC_MAT_HARD, ma), &shi->har);
- GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->amb, GPU_DYNAMIC_MAT_AMB, ma), &shi->amb);
- GPU_link(mat, "set_value", GPU_uniform(&ma->spectra), &shi->spectra);
- GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view);
- GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol);
- if (GPU_material_do_color_management(mat))
- GPU_link(mat, "srgb_to_linearrgb", shi->vcol, &shi->vcol);
- GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
-}
-void GPU_mist_update_enable(short enable)
-{
- GPUWorld.mistenabled = (float)enable;
-}
+ /* Normalize */
+ for (int j = resolution - 2; j > 0; j--) {
+ texels[j][0] /= (texels[0][0] > 0.0f) ? texels[0][0] : 1.0f;
+ texels[j][1] /= (texels[0][1] > 0.0f) ? texels[0][1] : 1.0f;
+ texels[j][2] /= (texels[0][2] > 0.0f) ? texels[0][2] : 1.0f;
+ }
-void GPU_mist_update_values(int type, float start, float dist, float inten, float color[3])
-{
- GPUWorld.mistype = (float)type;
- GPUWorld.miststart = start;
- GPUWorld.mistdistance = dist;
- GPUWorld.mistintensity = inten;
- copy_v3_v3(GPUWorld.mistcol, color);
- GPUWorld.mistcol[3] = 1.0f;
-}
+ /* First texel should be white */
+ texels[0][0] = (texels[0][0] > 0.0f) ? 1.0f : 0.0f;
+ texels[0][1] = (texels[0][1] > 0.0f) ? 1.0f : 0.0f;
+ texels[0][2] = (texels[0][2] > 0.0f) ? 1.0f : 0.0f;
-void GPU_horizon_update_color(float color[3])
-{
- copy_v3_v3(GPUWorld.horicol, color);
+ /* dim the last few texels for smoother transition */
+ mul_v3_fl(texels[resolution - 2], 0.25f);
+ mul_v3_fl(texels[resolution - 3], 0.5f);
+ mul_v3_fl(texels[resolution - 4], 0.75f);
}
+#undef INTEGRAL_RESOLUTION
-void GPU_ambient_update_color(float color[3])
+void GPU_material_sss_profile_create(GPUMaterial *material, float *radii, short *falloff_type, float *sharpness)
{
- copy_v3_v3(GPUWorld.ambcol, color);
- GPUWorld.ambcol[3] = 1.0f;
-}
+ material->sss_radii = radii;
+ material->sss_falloff = falloff_type;
+ material->sss_sharpness = sharpness;
+ material->sss_dirty = true;
-void GPU_zenith_update_color(float color[3])
-{
- copy_v3_v3(GPUWorld.zencol, color);
+ /* Update / Create UBO */
+ if (material->sss_profile == NULL) {
+ material->sss_profile = GPU_uniformbuffer_create(sizeof(GPUSssKernelData), NULL, NULL);
+ }
}
-void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
+struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material, int sample_ct, GPUTexture **tex_profile)
{
- GPUMaterial *mat = shi->gpumat;
- GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac;
- Material *ma = shi->mat;
- World *world = mat->scene->world;
- float linfac, logfac;
-
- memset(shr, 0, sizeof(*shr));
-
- if (ma->mode & MA_VERTEXCOLP)
- shi->rgb = shi->vcol;
-
- do_material_tex(shi);
-
- if ((mat->scene->gm.flag & GAME_GLSL_NO_LIGHTS) || (ma->mode & MA_SHLESS)) {
- GPU_link(mat, "set_rgb", shi->rgb, &shr->diff);
- GPU_link(mat, "set_rgb_zero", &shr->spec);
- GPU_link(mat, "set_value", shi->alpha, &shr->alpha);
- shr->combined = shr->diff;
- }
- else {
- if (GPU_link_changed(shi->emit) || ma->emit != 0.0f) {
- if ((ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == MA_VERTEXCOL) {
- GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit);
- GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff);
- }
- else
- GPU_link(mat, "shade_mul_value", shi->emit, shi->rgb, &shr->diff);
- }
- else
- GPU_link(mat, "set_rgb_zero", &shr->diff);
+ if (material->sss_radii == NULL)
+ return NULL;
- GPU_link(mat, "set_rgb_zero", &shr->spec);
+ if (material->sss_dirty || (material->sss_samples != sample_ct)) {
+ GPUSssKernelData kd;
- material_lights(shi, shr);
+ float sharpness = (material->sss_sharpness != NULL) ? *material->sss_sharpness : 0.0f;
- shr->combined = shr->diff;
+ /* XXX Black magic but it seems to fit. Maybe because we integrate -1..1 */
+ sharpness *= 0.5f;
- GPU_link(mat, "set_value", shi->alpha, &shr->alpha);
+ compute_sss_kernel(&kd, material->sss_radii, sample_ct, *material->sss_falloff, sharpness);
- if (world) {
- /* exposure correction */
- if (world->exp != 0.0f || world->range != 1.0f) {
- linfac = 1.0f + powf((2.0f * world->exp + 0.5f), -10);
- logfac = logf((linfac - 1.0f) / linfac) / world->range;
+ /* Update / Create UBO */
+ GPU_uniformbuffer_update(material->sss_profile, &kd);
- GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac);
- GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac);
+ /* Update / Create Tex */
+ float *translucence_profile;
+ compute_sss_translucence_kernel(&kd, 64, *material->sss_falloff, sharpness, &translucence_profile);
- GPU_link(mat, "shade_exposure_correct", shr->combined,
- ulinfac, ulogfac, &shr->combined);
- GPU_link(mat, "shade_exposure_correct", shr->spec,
- ulinfac, ulogfac, &shr->spec);
- }
-
- /* environment lighting */
- if (!(mat->scene->gm.flag & GAME_GLSL_NO_ENV_LIGHTING) &&
- (world->mode & WO_ENV_LIGHT) &&
- (mat->scene->r.mode & R_SHADOW) &&
- !BKE_scene_use_new_shading_nodes(mat->scene))
- {
- if ((world->ao_env_energy != 0.0f) && (GPU_link_changed(shi->amb) || ma->amb != 0.0f) &&
- (GPU_link_changed(shi->refl) || ma->ref != 0.0f))
- {
- if (world->aocolor != WO_AOPLAIN) {
- if (!(is_zero_v3(&world->horr) & is_zero_v3(&world->zenr))) {
- GPUNodeLink *fcol, *f;
- GPU_link(mat, "math_multiply", shi->amb, shi->refl, &f);
- GPU_link(mat, "math_multiply", f, GPU_uniform(&world->ao_env_energy), &f);
- GPU_link(mat, "shade_mul_value", f, shi->rgb, &fcol);
- GPU_link(mat, "env_apply", shr->combined,
- GPU_dynamic_uniform(GPUWorld.horicol, GPU_DYNAMIC_HORIZON_COLOR, NULL),
- GPU_dynamic_uniform(GPUWorld.zencol, GPU_DYNAMIC_ZENITH_COLOR, NULL), fcol,
- GPU_builtin(GPU_VIEW_MATRIX), shi->vn, &shr->combined);
- }
- }
- else {
- GPUNodeLink *f;
- GPU_link(mat, "math_multiply", shi->amb, shi->refl, &f);
- GPU_link(mat, "math_multiply", f, GPU_uniform(&world->ao_env_energy), &f);
- GPU_link(mat, "shade_maddf", shr->combined, f, shi->rgb, &shr->combined);
- }
- }
- }
-
- /* ambient color */
- if (GPU_link_changed(shi->amb) || ma->amb != 0.0f) {
- GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb),
- GPU_dynamic_uniform(GPUWorld.ambcol, GPU_DYNAMIC_AMBIENT_COLOR, NULL),
- &shr->combined);
- }
+ if (material->sss_tex_profile != NULL) {
+ GPU_texture_free(material->sss_tex_profile);
}
- if (ma->mode & MA_TRANSP && (ma->mode & (MA_ZTRANSP | MA_RAYTRANSP))) {
- if (GPU_link_changed(shi->spectra) || ma->spectra != 0.0f) {
- GPU_link(mat, "alpha_spec_correction", shr->spec, shi->spectra,
- shi->alpha, &shr->alpha);
- }
- }
+ material->sss_tex_profile = GPU_texture_create_1D(64, GPU_RGBA16F, translucence_profile, NULL);
- if (ma->mode & MA_RAMP_COL) ramp_diffuse_result(shi, &shr->combined);
- if (ma->mode & MA_RAMP_SPEC) ramp_spec_result(shi, &shr->spec);
+ MEM_freeN(translucence_profile);
- if (GPU_link_changed(shi->refcol))
- GPU_link(mat, "shade_add_mirror", shi->mir, shi->refcol, shr->combined, &shr->combined);
-
- if (GPU_link_changed(shi->spec) || ma->spec != 0.0f)
- GPU_link(mat, "shade_add", shr->combined, shr->spec, &shr->combined);
+ material->sss_samples = sample_ct;
+ material->sss_dirty = false;
}
- GPU_link(mat, "mtex_alpha_to_col", shr->combined, shr->alpha, &shr->combined);
-
- if (ma->shade_flag & MA_OBCOLOR)
- GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined);
-
- if (!(ma->mode & MA_NOMIST)) {
- GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION),
- GPU_dynamic_uniform(&GPUWorld.mistenabled, GPU_DYNAMIC_MIST_ENABLE, NULL),
- GPU_dynamic_uniform(&GPUWorld.miststart, GPU_DYNAMIC_MIST_START, NULL),
- GPU_dynamic_uniform(&GPUWorld.mistdistance, GPU_DYNAMIC_MIST_DISTANCE, NULL),
- GPU_dynamic_uniform(&GPUWorld.mistype, GPU_DYNAMIC_MIST_TYPE, NULL),
- GPU_dynamic_uniform(&GPUWorld.mistintensity, GPU_DYNAMIC_MIST_INTENSITY, NULL), &mistfac);
-
- GPU_link(mat, "mix_blend", mistfac, shr->combined,
- GPU_dynamic_uniform(GPUWorld.mistcol, GPU_DYNAMIC_MIST_COLOR, NULL), &shr->combined);
+ if (tex_profile != NULL) {
+ *tex_profile = material->sss_tex_profile;
}
+ return material->sss_profile;
+}
- if (!mat->alpha) {
- if (world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f))
- GPU_link(mat, "shade_world_mix", GPU_dynamic_uniform(GPUWorld.horicol, GPU_DYNAMIC_HORIZON_COLOR, NULL),
- shr->combined, &shr->combined);
-
- GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined);
- }
+#undef SSS_EXPONENT
+#undef SSS_SAMPLES
- if (ma->shade_flag & MA_OBCOLOR) {
- mat->obcolalpha = 1;
- GPU_link(mat, "shade_alpha_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined);
- }
+void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
+{
+ *attribs = material->attribs;
}
-static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma)
+void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
{
- GPUShadeInput shi;
- GPUShadeResult shr;
-
- GPU_shadeinput_set(mat, ma, &shi);
- GPU_shaderesult_set(&shi, &shr);
-
- return shr.combined;
+ if (!material->outlink)
+ material->outlink = link;
}
-static GPUNodeLink *gpu_material_diffuse_bsdf(GPUMaterial *mat, Material *ma)
+void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
{
- static float roughness = 0.0f;
- GPUNodeLink *outlink;
-
- GPU_link(mat, "node_bsdf_diffuse",
- GPU_uniform(&ma->r), GPU_uniform(&roughness), GPU_builtin(GPU_VIEW_NORMAL), &outlink);
-
- return outlink;
+ BLI_addtail(&material->nodes, node);
}
-static GPUNodeLink *gpu_material_preview_matcap(GPUMaterial *mat, Material *ma)
+/* Return true if the material compilation has not yet begin or begin. */
+GPUMaterialStatus GPU_material_status(GPUMaterial *mat)
{
- GPUNodeLink *outlink;
-
- /* some explanations here:
- * matcap normal holds the normal remapped to the 0.0 - 1.0 range. To take advantage of flat shading, we abuse
- * the built in secondary color of opengl. Color is just the regular color, which should include mask value too.
- * This also needs flat shading so we use the primary opengl color built-in */
- GPU_link(mat, "material_preview_matcap", GPU_uniform(&ma->r), GPU_image_preview(ma->preview),
- GPU_opengl_builtin(GPU_MATCAP_NORMAL), GPU_opengl_builtin(GPU_COLOR), &outlink);
-
- return outlink;
+ return mat->status;
}
-/* new solid draw mode with glsl matcaps */
-GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv)
-{
- GPUMaterial *mat;
- GPUNodeLink *outlink;
- LinkData *link;
-
- for (link = ma->gpumaterial.first; link; link = link->next) {
- GPUMaterial *current_material = (GPUMaterial *)link->data;
- if (current_material->scene == scene &&
- current_material->is_opensubdiv == use_opensubdiv)
- {
- return current_material;
- }
- }
-
- /* allocate material */
- mat = GPU_material_construct_begin(ma);
- mat->scene = scene;
- mat->type = GPU_MATERIAL_TYPE_MESH;
- mat->is_opensubdiv = use_opensubdiv;
+/* Code generation */
- if (ma->preview && ma->preview->rect[0]) {
- outlink = gpu_material_preview_matcap(mat, ma);
- }
- else {
- outlink = gpu_material_diffuse_bsdf(mat, ma);
- }
-
- GPU_material_output_link(mat, outlink);
+bool GPU_material_do_color_management(GPUMaterial *mat)
+{
+ if (!BKE_scene_check_color_management_enabled(mat->scene))
+ return false;
- gpu_material_construct_end(mat, "matcap_pass");
-
- /* note that even if building the shader fails in some way, we still keep
- * it to avoid trying to compile again and again, and simple do not use
- * the actual shader on drawing */
-
- link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
- link->data = mat;
- BLI_addtail(&ma->gpumaterial, link);
-
- return mat;
+ return true;
}
-static void do_world_tex(GPUShadeInput *shi, struct World *wo, GPUNodeLink **hor, GPUNodeLink **zen, GPUNodeLink **blend)
+bool GPU_material_use_domain_surface(GPUMaterial *mat)
{
- GPUMaterial *mat = shi->gpumat;
- GPUNodeLink *texco, *tin, *trgb, *stencil, *tcol, *zenfac;
- MTex *mtex;
- Tex *tex;
- float ofs[3], zero = 0.0f;
- int tex_nr, rgbnor;
-
- GPU_link(mat, "set_value_one", &stencil);
- /* go over texture slots */
- for (tex_nr = 0; tex_nr < MAX_MTEX; tex_nr++) {
- if (wo->mtex[tex_nr]) {
- mtex = wo->mtex[tex_nr];
- tex = mtex->tex;
- if (tex == NULL || !tex->ima || (tex->type != TEX_IMAGE && tex->type != TEX_ENVMAP))
- continue;
- /* which coords */
- if (mtex->texco == TEXCO_VIEW || mtex->texco == TEXCO_GLOB) {
- if (tex->type == TEX_IMAGE)
- texco = GPU_builtin(GPU_VIEW_POSITION);
- else if (tex->type == TEX_ENVMAP)
- GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &texco);
- }
- else if (mtex->texco == TEXCO_EQUIRECTMAP || mtex->texco == TEXCO_ANGMAP) {
- if ((tex->type == TEX_IMAGE && wo->skytype & WO_SKYREAL) || tex->type == TEX_ENVMAP)
- GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &texco);
- else
- texco = GPU_builtin(GPU_VIEW_POSITION);
- }
- else
- continue;
- GPU_link(mat, "texco_norm", texco, &texco);
- if (tex->type == TEX_IMAGE && !(wo->skytype & WO_SKYREAL)) {
- GPU_link(mat, "mtex_2d_mapping", texco, &texco);
- }
- if (mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f) {
- float size[3] = { mtex->size[0], mtex->size[1], mtex->size[2] };
- if (tex->type == TEX_ENVMAP) {
- size[1] = mtex->size[2];
- size[2] = mtex->size[1];
- }
- GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(size), &texco);
- }
- ofs[0] = mtex->ofs[0] + 0.5f - 0.5f * mtex->size[0];
- if (tex->type == TEX_ENVMAP) {
- ofs[1] = -mtex->ofs[2] + 0.5f - 0.5f * mtex->size[2];
- ofs[2] = mtex->ofs[1] + 0.5f - 0.5f * mtex->size[1];
- }
- else {
- ofs[1] = mtex->ofs[1] + 0.5f - 0.5f * mtex->size[1];
- ofs[2] = 0.0;
- }
- if (ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f)
- GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco);
- if (mtex->texco == TEXCO_EQUIRECTMAP) {
- GPU_link(mat, "node_tex_environment_equirectangular", texco, GPU_image(tex->ima, &tex->iuser, false), &trgb);
- }
- else if (mtex->texco == TEXCO_ANGMAP) {
- GPU_link(mat, "node_tex_environment_mirror_ball", texco, GPU_image(tex->ima, &tex->iuser, false), &trgb);
- }
- else {
- if (tex->type == TEX_ENVMAP)
- GPU_link(mat, "mtex_cube_map", texco, GPU_cube_map(tex->ima, &tex->iuser, false), &tin, &trgb);
- else if (tex->type == TEX_IMAGE)
- GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false), &tin, &trgb);
- }
- rgbnor = TEX_RGB;
- if (tex->type == TEX_IMAGE || tex->type == TEX_ENVMAP)
- if (GPU_material_do_color_management(mat))
- GPU_link(mat, "srgb_to_linearrgb", trgb, &trgb);
- /* texture output */
- if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) {
- GPU_link(mat, "mtex_rgbtoint", trgb, &tin);
- rgbnor -= TEX_RGB;
- }
- if (mtex->texflag & MTEX_NEGATIVE) {
- if (rgbnor & TEX_RGB)
- GPU_link(mat, "mtex_rgb_invert", trgb, &trgb);
- else
- GPU_link(mat, "mtex_value_invert", tin, &tin);
- }
- if (mtex->texflag & MTEX_STENCIL) {
- if (rgbnor & TEX_RGB)
- GPU_link(mat, "mtex_rgb_stencil", stencil, trgb, &stencil, &trgb);
- else
- GPU_link(mat, "mtex_value_stencil", stencil, tin, &stencil, &tin);
- }
- else {
- if (rgbnor & TEX_RGB)
- GPU_link(mat, "mtex_alpha_multiply_value", trgb, stencil, &trgb);
- else
- GPU_link(mat, "math_multiply", stencil, tin, &tin);
- }
- /* color mapping */
- if (mtex->mapto & (WOMAP_HORIZ + WOMAP_ZENUP + WOMAP_ZENDOWN)) {
- if ((rgbnor & TEX_RGB) == 0)
- GPU_link(mat, "set_rgb", GPU_uniform(&mtex->r), &trgb);
- else
- GPU_link(mat, "mtex_alpha_from_col", trgb, &tin);
- GPU_link(mat, "set_rgb", trgb, &tcol);
- if (mtex->mapto & WOMAP_HORIZ) {
- texture_rgb_blend(mat, tcol, *hor, tin, GPU_uniform(&mtex->colfac), mtex->blendtype, hor);
- }
- if (mtex->mapto & (WOMAP_ZENUP + WOMAP_ZENDOWN)) {
- GPU_link(mat, "set_value_zero", &zenfac);
- if (wo->skytype & WO_SKYREAL) {
- if (mtex->mapto & WOMAP_ZENUP) {
- if (mtex->mapto & WOMAP_ZENDOWN) {
- GPU_link(mat, "world_zen_mapping", shi->view, GPU_uniform(&mtex->zenupfac),
- GPU_uniform(&mtex->zendownfac), &zenfac);
- }
- else {
- GPU_link(mat, "world_zen_mapping", shi->view, GPU_uniform(&mtex->zenupfac),
- GPU_uniform(&zero), &zenfac);
- }
- }
- else if (mtex->mapto & WOMAP_ZENDOWN) {
- GPU_link(mat, "world_zen_mapping", shi->view, GPU_uniform(&zero),
- GPU_uniform(&mtex->zendownfac), &zenfac);
- }
- }
- else {
- if (mtex->mapto & WOMAP_ZENUP)
- GPU_link(mat, "set_value", GPU_uniform(&mtex->zenupfac), &zenfac);
- else if (mtex->mapto & WOMAP_ZENDOWN)
- GPU_link(mat, "set_value", GPU_uniform(&mtex->zendownfac), &zenfac);
- }
- texture_rgb_blend(mat, tcol, *zen, tin, zenfac, mtex->blendtype, zen);
- }
- }
- if (mtex->mapto & WOMAP_BLEND && wo->skytype & WO_SKYBLEND) {
- if (rgbnor & TEX_RGB)
- GPU_link(mat, "mtex_rgbtoint", trgb, &tin);
- texture_value_blend(mat, GPU_uniform(&mtex->def_var), *blend, tin, GPU_uniform(&mtex->blendfac), mtex->blendtype, blend);
- }
- }
- }
+ return (mat->domain & GPU_DOMAIN_SURFACE);
}
-static void gpu_material_old_world(struct GPUMaterial *mat, struct World *wo)
+bool GPU_material_use_domain_volume(GPUMaterial *mat)
{
- GPUShadeInput shi;
- GPUShadeResult shr;
- GPUNodeLink *hor, *zen, *ray, *blend;
-
- shi.gpumat = mat;
+ return (mat->domain & GPU_DOMAIN_VOLUME);
+}
- for (int i = 0; i < MAX_MTEX; i++) {
- if (wo->mtex[i] && wo->mtex[i]->tex) {
- wo->skytype |= WO_SKYTEX;
- break;
- }
- }
- if ((wo->skytype & (WO_SKYBLEND + WO_SKYTEX)) == 0) {
- GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&wo->horr, GPU_DYNAMIC_HORIZON_COLOR, NULL), &shr.combined);
- }
- else {
- GPU_link(mat, "set_rgb_zero", &shi.rgb);
- GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &ray);
- if (wo->skytype & WO_SKYPAPER)
- GPU_link(mat, "world_paper_view", GPU_builtin(GPU_VIEW_POSITION), &shi.view);
- else
- GPU_link(mat, "shade_view", ray, &shi.view);
- if (wo->skytype & WO_SKYBLEND) {
- if (wo->skytype & WO_SKYPAPER) {
- if (wo->skytype & WO_SKYREAL)
- GPU_link(mat, "world_blend_paper_real", GPU_builtin(GPU_VIEW_POSITION), &blend);
- else
- GPU_link(mat, "world_blend_paper", GPU_builtin(GPU_VIEW_POSITION), &blend);
- }
- else {
- if (wo->skytype & WO_SKYREAL)
- GPU_link(mat, "world_blend_real", ray, &blend);
- else
- GPU_link(mat, "world_blend", ray, &blend);
- }
- }
- else {
- GPU_link(mat, "set_value_zero", &blend);
+GPUMaterial *GPU_material_from_nodetree_find(
+ ListBase *gpumaterials, const void *engine_type, int options)
+{
+ for (LinkData *link = gpumaterials->first; link; link = link->next) {
+ GPUMaterial *current_material = (GPUMaterial *)link->data;
+ if (current_material->engine_type == engine_type &&
+ current_material->options == options)
+ {
+ return current_material;
}
- GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&wo->horr, GPU_DYNAMIC_HORIZON_COLOR, NULL), &hor);
- GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&wo->zenr, GPU_DYNAMIC_ZENITH_COLOR, NULL), &zen);
- do_world_tex(&shi, wo, &hor, &zen, &blend);
- if (wo->skytype & WO_SKYBLEND)
- GPU_link(mat, "node_mix_shader", blend, hor, zen, &shi.rgb);
- else
- GPU_link(mat, "set_rgb", hor, &shi.rgb);
- GPU_link(mat, "set_rgb", shi.rgb, &shr.combined);
}
- GPU_material_output_link(mat, shr.combined);
+
+ return NULL;
}
-GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
+/**
+ * \note Caller must use #GPU_material_from_nodetree_find to re-use existing materials,
+ * This is enforced since constructing other arguments to this function may be expensive
+ * so only do this when they are needed.
+ */
+GPUMaterial *GPU_material_from_nodetree(
+ Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options)
{
LinkData *link;
- GPUMaterial *mat;
+ bool has_volume_output, has_surface_output;
- for (link = wo->gpumaterial.first; link; link = link->next)
- if (((GPUMaterial *)link->data)->scene == scene)
- return link->data;
+ /* Caller must re-use materials. */
+ BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
/* allocate material */
- mat = GPU_material_construct_begin(NULL);
+ GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");;
mat->scene = scene;
- mat->type = GPU_MATERIAL_TYPE_WORLD;
-
- /* create nodes */
- if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes) {
- ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING);
+ mat->engine_type = engine_type;
+ mat->options = options;
+
+ ntreeGPUMaterialNodes(ntree, mat, NODE_NEW_SHADING | NODE_NEWER_SHADING);
+ ntreeGPUMaterialDomain(ntree, &has_surface_output, &has_volume_output);
+
+ if (has_surface_output) {
+ mat->domain |= GPU_DOMAIN_SURFACE;
}
- else {
- gpu_material_old_world(mat, wo);
+ if (has_volume_output) {
+ mat->domain |= GPU_DOMAIN_VOLUME;
}
- if (GPU_material_do_color_management(mat))
- if (mat->outlink)
- GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
+ if (mat->outlink) {
+ /* Prune the unused nodes and extract attribs before compiling so the
+ * generated VBOs are ready to accept the future shader. */
+ GPU_nodes_prune(&mat->nodes, mat->outlink);
+ GPU_nodes_get_vertex_attributes(&mat->nodes, &mat->attribs);
+ mat->status = GPU_MAT_QUEUED;
+ }
- gpu_material_construct_end(mat, wo->id.name);
-
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
* the actual shader on drawing */
link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
link->data = mat;
- BLI_addtail(&wo->gpumaterial, link);
+ BLI_addtail(gpumaterials, link);
return mat;
}
-
-GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
+void GPU_material_generate_pass(
+ GPUMaterial *mat, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
{
- GPUMaterial *mat;
- GPUNodeLink *outlink;
- LinkData *link;
-
- for (link = ma->gpumaterial.first; link; link = link->next) {
- GPUMaterial *current_material = (GPUMaterial *)link->data;
- if (current_material->scene == scene &&
- current_material->is_opensubdiv == use_opensubdiv)
- {
- return current_material;
- }
- }
-
- /* allocate material */
- mat = GPU_material_construct_begin(ma);
- mat->scene = scene;
- mat->type = GPU_MATERIAL_TYPE_MESH;
- mat->is_opensubdiv = use_opensubdiv;
-
- /* render pipeline option */
- bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
- if (!new_shading_nodes && (ma->mode & MA_TRANSP))
- GPU_material_enable_alpha(mat);
- else if (new_shading_nodes && ma->alpha < 1.0f)
- GPU_material_enable_alpha(mat);
-
- if (!(scene->gm.flag & GAME_GLSL_NO_NODES) && ma->nodetree && ma->use_nodes) {
- /* create nodes */
- if (new_shading_nodes)
- ntreeGPUMaterialNodes(ma->nodetree, mat, NODE_NEW_SHADING);
- else
- ntreeGPUMaterialNodes(ma->nodetree, mat, NODE_OLD_SHADING);
+ BLI_assert(mat->pass == NULL); /* Only run once! */
+ if (mat->outlink) {
+ mat->pass = GPU_generate_pass_new(
+ mat, mat->outlink, &mat->attribs, &mat->nodes, &mat->inputs, vert_code, geom_code, frag_lib, defines);
+ mat->status = (mat->pass) ? GPU_MAT_SUCCESS : GPU_MAT_FAILED;
}
else {
- if (new_shading_nodes) {
- /* create simple diffuse material instead of nodes */
- outlink = gpu_material_diffuse_bsdf(mat, ma);
- }
- else {
- /* create blender material */
- outlink = GPU_blender_material(mat, ma);
- }
-
- GPU_material_output_link(mat, outlink);
+ mat->status = GPU_MAT_FAILED;
}
-
- if (GPU_material_do_color_management(mat))
- if (mat->outlink)
- GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
-
- gpu_material_construct_end(mat, ma->id.name);
-
- /* note that even if building the shader fails in some way, we still keep
- * it to avoid trying to compile again and again, and simple do not use
- * the actual shader on drawing */
-
- link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
- link->data = mat;
- BLI_addtail(&ma->gpumaterial, link);
-
- return mat;
}
void GPU_materials_free(void)
{
- Object *ob;
Material *ma;
World *wo;
extern Material defmaterial;
@@ -2230,684 +672,4 @@ void GPU_materials_free(void)
GPU_material_free(&wo->gpumaterial);
GPU_material_free(&defmaterial.gpumaterial);
-
- for (ob = G.main->object.first; ob; ob = ob->id.next)
- GPU_lamp_free(ob);
-}
-
-/* Lamps and shadow buffers */
-
-static void gpu_lamp_calc_winmat(GPULamp *lamp)
-{
- float temp, angle, pixsize, wsize;
-
- if (lamp->type == LA_SUN) {
- wsize = lamp->la->shadow_frustum_size;
- orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
- }
- else if (lamp->type == LA_SPOT) {
- angle = saacos(lamp->spotsi);
- temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
- pixsize = lamp->d / temp;
- wsize = pixsize * 0.5f * lamp->size;
- /* compute shadows according to X and Y scaling factors */
- perspective_m4(
- lamp->winmat,
- -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
- -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
- lamp->d, lamp->clipend);
- }
-}
-
-void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
-{
- float mat[4][4];
- float obmat_scale[3];
-
- lamp->lay = lay;
- lamp->hide = hide;
-
- normalize_m4_m4_ex(mat, obmat, obmat_scale);
-
- copy_v3_v3(lamp->vec, mat[2]);
- copy_v3_v3(lamp->co, mat[3]);
- copy_m4_m4(lamp->obmat, mat);
- invert_m4_m4(lamp->imat, mat);
-
- if (lamp->type == LA_SPOT) {
- /* update spotlamp scale on X and Y axis */
- lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
- lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
- }
-
- if (GPU_lamp_has_shadow_buffer(lamp)) {
- /* makeshadowbuf */
- gpu_lamp_calc_winmat(lamp);
- }
-}
-
-void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
-{
- lamp->energy = energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = r;
- lamp->col[1] = g;
- lamp->col[2] = b;
-}
-
-void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
- float coeff_const, float coeff_lin, float coeff_quad)
-{
- lamp->dist = distance;
- lamp->att1 = att1;
- lamp->att2 = att2;
- lamp->coeff_const = coeff_const;
- lamp->coeff_lin = coeff_lin;
- lamp->coeff_quad = coeff_quad;
}
-
-void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
-{
- lamp->spotsi = cosf(spotsize * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
-}
-
-static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
-{
- lamp->scene = scene;
- lamp->ob = ob;
- lamp->par = par;
- lamp->la = la;
-
- /* add_render_lamp */
- lamp->mode = la->mode;
- lamp->type = la->type;
-
- lamp->energy = la->energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = la->r;
- lamp->col[1] = la->g;
- lamp->col[2] = la->b;
-
- GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
-
- lamp->spotsi = la->spotsize;
- if (lamp->mode & LA_HALO)
- if (lamp->spotsi > DEG2RADF(170.0f))
- lamp->spotsi = DEG2RADF(170.0f);
- lamp->spotsi = cosf(lamp->spotsi * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
- lamp->k = la->k;
-
- lamp->dist = la->dist;
- lamp->falloff_type = la->falloff_type;
- lamp->att1 = la->att1;
- lamp->att2 = la->att2;
- lamp->coeff_const = la->coeff_const;
- lamp->coeff_lin = la->coeff_lin;
- lamp->coeff_quad = la->coeff_quad;
- lamp->curfalloff = la->curfalloff;
-
- /* initshadowbuf */
- lamp->bias = 0.02f * la->bias;
- lamp->size = la->bufsize;
- lamp->d = la->clipsta;
- lamp->clipend = la->clipend;
-
- /* arbitrary correction for the fact we do no soft transition */
- lamp->bias *= 0.25f;
-}
-
-static void gpu_lamp_shadow_free(GPULamp *lamp)
-{
- if (lamp->tex) {
- GPU_texture_free(lamp->tex);
- lamp->tex = NULL;
- }
- if (lamp->depthtex) {
- GPU_texture_free(lamp->depthtex);
- lamp->depthtex = NULL;
- }
- if (lamp->fb) {
- GPU_framebuffer_free(lamp->fb);
- lamp->fb = NULL;
- }
- if (lamp->blurtex) {
- GPU_texture_free(lamp->blurtex);
- lamp->blurtex = NULL;
- }
- if (lamp->blurfb) {
- GPU_framebuffer_free(lamp->blurfb);
- lamp->blurfb = NULL;
- }
-}
-
-GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
-{
- Lamp *la;
- GPULamp *lamp;
- LinkData *link;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = (GPULamp *)link->data;
-
- if (lamp->par == par && lamp->scene == scene)
- return link->data;
- }
-
- lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
-
- link = MEM_callocN(sizeof(LinkData), "GPULampLink");
- link->data = lamp;
- BLI_addtail(&ob->gpulamp, link);
-
- la = ob->data;
- gpu_lamp_from_blender(scene, ob, par, la, lamp);
-
- if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
- (la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
- {
- /* opengl */
- lamp->fb = GPU_framebuffer_create();
- if (!lamp->fb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- /* Shadow depth map */
- lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->depthtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* Shadow color map */
- lamp->tex = GPU_texture_create_vsm_shadow_map(lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* FBO and texture for blurring */
- lamp->blurfb = GPU_framebuffer_create();
- if (!lamp->blurfb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL);
- if (!lamp->blurtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* we need to properly bind to test for completeness */
- GPU_texture_bind_as_framebuffer(lamp->blurtex);
-
- if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
- }
- else {
- lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
- }
-
- GPU_framebuffer_restore();
-
- lamp->shadow_color[0] = la->shdwr;
- lamp->shadow_color[1] = la->shdwg;
- lamp->shadow_color[2] = la->shdwb;
- }
- else {
- lamp->shadow_color[0] = 1.0;
- lamp->shadow_color[1] = 1.0;
- lamp->shadow_color[2] = 1.0;
- }
-
- return lamp;
-}
-
-void GPU_lamp_free(Object *ob)
-{
- GPULamp *lamp;
- LinkData *link;
- LinkData *nlink;
- Material *ma;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = link->data;
-
- while (lamp->materials.first) {
- nlink = lamp->materials.first;
- ma = nlink->data;
- BLI_freelinkN(&lamp->materials, nlink);
-
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
- }
-
- gpu_lamp_shadow_free(lamp);
-
- MEM_freeN(lamp);
- }
-
- BLI_freelistN(&ob->gpulamp);
-}
-
-bool GPU_lamp_has_shadow_buffer(GPULamp *lamp)
-{
- return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
- !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
- lamp->tex && lamp->fb);
-}
-
-void GPU_lamp_update_buffer_mats(GPULamp *lamp)
-{
- float rangemat[4][4], persmat[4][4];
-
- /* initshadowbuf */
- invert_m4_m4(lamp->viewmat, lamp->obmat);
- normalize_v3(lamp->viewmat[0]);
- normalize_v3(lamp->viewmat[1]);
- normalize_v3(lamp->viewmat[2]);
-
- /* makeshadowbuf */
- mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat);
-
- /* opengl depth 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;
-
- mul_m4_m4m4(lamp->persmat, rangemat, persmat);
-}
-
-void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4])
-{
- GPU_lamp_update_buffer_mats(lamp);
-
- /* opengl */
- glDisable(GL_SCISSOR_TEST);
- GPU_texture_bind_as_framebuffer(lamp->tex);
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
- GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
-
- /* set matrices */
- copy_m4_m4(viewmat, lamp->viewmat);
- copy_m4_m4(winmat, lamp->winmat);
- *winsize = lamp->size;
-}
-
-void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
-{
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- GPU_shader_unbind();
- GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
- }
-
- GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
- GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
-}
-
-int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
-{
- return lamp->la->shadowmap_type;
-}
-
-int GPU_lamp_shadow_bind_code(GPULamp *lamp)
-{
- return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1;
-}
-
-float *GPU_lamp_dynpersmat(GPULamp *lamp)
-{
- return &lamp->dynpersmat[0][0];
-}
-
-int GPU_lamp_shadow_layer(GPULamp *lamp)
-{
- if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW)))
- return lamp->lay;
- else
- return -1;
-}
-
-GPUNodeLink *GPU_lamp_get_data(
- GPUMaterial *mat, GPULamp *lamp,
- GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy)
-{
- GPUNodeLink *visifac;
-
- *r_col = GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob);
- *r_energy = GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob);
- visifac = lamp_get_visibility(mat, lamp, r_lv, r_dist);
-
- shade_light_textures(mat, lamp, r_col);
-
- if (GPU_lamp_has_shadow_buffer(lamp)) {
- GPUNodeLink *vn, *inp;
-
- GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &vn);
- GPU_link(mat, "shade_inp", vn, *r_lv, &inp);
- mat->dynproperty |= DYN_LAMP_PERSMAT;
-
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- GPU_link(mat, "shadows_only_vsm",
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
- GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
- GPU_uniform(&lamp->bias), GPU_uniform(&lamp->la->bleedbias),
- GPU_uniform(lamp->shadow_color), inp, r_shadow);
- }
- else {
- GPU_link(mat, "shadows_only",
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
- GPU_dynamic_uniform((float *)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
- GPU_uniform(&lamp->bias), GPU_uniform(lamp->shadow_color), inp, r_shadow);
- }
- }
- else {
- GPU_link(mat, "set_rgb_one", r_shadow);
- }
-
- /* ensure shadow buffer and lamp textures will be updated */
- add_user_list(&mat->lamps, lamp);
- add_user_list(&lamp->materials, mat->ma);
-
- return visifac;
-}
-
-/* export the GLSL shader */
-
-GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
-{
- static struct {
- GPUBuiltin gputype;
- GPUDynamicType dynamictype;
- GPUDataType datatype;
- } builtins[] = {
- { GPU_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWMAT, GPU_DATA_16F },
- { GPU_INVERSE_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWIMAT, GPU_DATA_16F },
- { GPU_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_MAT, GPU_DATA_16F },
- { GPU_INVERSE_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_IMAT, GPU_DATA_16F },
- { GPU_LOC_TO_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_LOCTOVIEWMAT, GPU_DATA_16F },
- { GPU_INVERSE_LOC_TO_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_LOCTOVIEWIMAT, GPU_DATA_16F },
- { GPU_OBCOLOR, GPU_DYNAMIC_OBJECT_COLOR, GPU_DATA_4F },
- { GPU_AUTO_BUMPSCALE, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE, GPU_DATA_1F },
- { 0 }
- };
-
- GPUShaderExport *shader = NULL;
- GPUInput *input;
- int liblen, fraglen;
-
- /* TODO(sergey): How to determine whether we need OSD or not here? */
- GPUMaterial *mat = GPU_material_from_blender(scene, ma, false);
- GPUPass *pass = (mat) ? mat->pass : NULL;
-
- if (pass && pass->fragmentcode && pass->vertexcode) {
- shader = MEM_callocN(sizeof(GPUShaderExport), "GPUShaderExport");
-
- for (input = pass->inputs.first; input; input = input->next) {
- GPUInputUniform *uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
-
- if (input->ima) {
- /* image sampler uniform */
- uniform->type = GPU_DYNAMIC_SAMPLER_2DIMAGE;
- uniform->datatype = GPU_DATA_1I;
- uniform->image = input->ima;
- uniform->texnumber = input->texid;
- BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
- }
- else if (input->tex) {
- /* generated buffer */
- uniform->texnumber = input->texid;
- uniform->datatype = GPU_DATA_1I;
- BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
-
- switch (input->textype) {
- case GPU_SHADOW2D:
- uniform->type = GPU_DYNAMIC_SAMPLER_2DSHADOW;
- uniform->lamp = input->dynamicdata;
- break;
- case GPU_TEX2D:
- if (GPU_texture_opengl_bindcode(input->tex)) {
- uniform->type = GPU_DYNAMIC_SAMPLER_2DBUFFER;
- glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(input->tex));
- uniform->texsize = GPU_texture_width(input->tex) * GPU_texture_height(input->tex);
- uniform->texpixels = MEM_mallocN(uniform->texsize * 4, "RGBApixels");
- glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, uniform->texpixels);
- glBindTexture(GL_TEXTURE_2D, 0);
- }
- break;
-
- case GPU_NONE:
- case GPU_TEXCUBE:
- case GPU_FLOAT:
- case GPU_VEC2:
- case GPU_VEC3:
- case GPU_VEC4:
- case GPU_MAT3:
- case GPU_MAT4:
- case GPU_ATTRIB:
- break;
- }
- }
- else {
- uniform->type = input->dynamictype;
- BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
- switch (input->type) {
- case GPU_FLOAT:
- uniform->datatype = GPU_DATA_1F;
- break;
- case GPU_VEC2:
- uniform->datatype = GPU_DATA_2F;
- break;
- case GPU_VEC3:
- uniform->datatype = GPU_DATA_3F;
- break;
- case GPU_VEC4:
- uniform->datatype = GPU_DATA_4F;
- break;
- case GPU_MAT3:
- uniform->datatype = GPU_DATA_9F;
- break;
- case GPU_MAT4:
- uniform->datatype = GPU_DATA_16F;
- break;
-
- case GPU_NONE:
- case GPU_TEX2D:
- case GPU_TEXCUBE:
- case GPU_SHADOW2D:
- case GPU_ATTRIB:
- break;
- }
-
- if (GPU_DYNAMIC_GROUP_FROM_TYPE(uniform->type) == GPU_DYNAMIC_GROUP_LAMP)
- uniform->lamp = input->dynamicdata;
-
- if (GPU_DYNAMIC_GROUP_FROM_TYPE(uniform->type) == GPU_DYNAMIC_GROUP_MAT)
- uniform->material = input->dynamicdata;
- }
-
- if (uniform->type != GPU_DYNAMIC_NONE)
- BLI_addtail(&shader->uniforms, uniform);
- else
- MEM_freeN(uniform);
- }
-
- /* process builtin uniform */
- for (int i = 0; builtins[i].gputype; i++) {
- if (mat->builtins & builtins[i].gputype) {
- GPUInputUniform *uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
- uniform->type = builtins[i].dynamictype;
- uniform->datatype = builtins[i].datatype;
- BLI_strncpy(uniform->varname, GPU_builtin_name(builtins[i].gputype), sizeof(uniform->varname));
- BLI_addtail(&shader->uniforms, uniform);
- }
- }
-
- /* now link fragment shader with library shader */
- /* TBD: remove the function that are not used in the main function */
- liblen = (pass->libcode) ? strlen(pass->libcode) : 0;
- fraglen = strlen(pass->fragmentcode);
- shader->fragment = (char *)MEM_mallocN(liblen + fraglen + 1, "GPUFragShader");
- if (pass->libcode)
- memcpy(shader->fragment, pass->libcode, liblen);
- memcpy(&shader->fragment[liblen], pass->fragmentcode, fraglen);
- shader->fragment[liblen + fraglen] = 0;
-
- // export the attribute
- for (int i = 0; i < mat->attribs.totlayer; i++) {
- GPUInputAttribute *attribute = MEM_callocN(sizeof(GPUInputAttribute), "GPUInputAttribute");
- attribute->type = mat->attribs.layer[i].type;
- attribute->number = mat->attribs.layer[i].glindex;
- BLI_snprintf(attribute->varname, sizeof(attribute->varname), "att%d", mat->attribs.layer[i].attribid);
-
- switch (attribute->type) {
- case CD_TANGENT:
- attribute->datatype = GPU_DATA_4F;
- break;
- case CD_MTFACE:
- attribute->datatype = GPU_DATA_2F;
- attribute->name = mat->attribs.layer[i].name;
- break;
- case CD_MCOL:
- attribute->datatype = GPU_DATA_4UB;
- attribute->name = mat->attribs.layer[i].name;
- break;
- case CD_ORCO:
- attribute->datatype = GPU_DATA_3F;
- break;
- }
-
- if (attribute->datatype != GPU_DATA_NONE)
- BLI_addtail(&shader->attributes, attribute);
- else
- MEM_freeN(attribute);
- }
-
- /* export the vertex shader */
- shader->vertex = BLI_strdup(pass->vertexcode);
- }
-
- return shader;
-}
-
-void GPU_free_shader_export(GPUShaderExport *shader)
-{
- if (shader == NULL)
- return;
-
- for (GPUInputUniform *uniform = shader->uniforms.first; uniform; uniform = uniform->next)
- if (uniform->texpixels)
- MEM_freeN(uniform->texpixels);
-
- BLI_freelistN(&shader->uniforms);
- BLI_freelistN(&shader->attributes);
-
- if (shader->vertex)
- MEM_freeN(shader->vertex);
- if (shader->fragment)
- MEM_freeN(shader->fragment);
-
- MEM_freeN(shader);
-}
-
-#ifdef WITH_OPENSUBDIV
-void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
- DerivedMesh *dm)
-{
- GPUPass *pass = gpu_material->pass;
- GPUShader *shader = (pass != NULL ? pass->shader : NULL);
- ListBase *inputs = (pass != NULL ? &pass->inputs : NULL);
- GPUInput *input;
-
- if (shader == NULL) {
- return;
- }
-
- GPU_shader_bind(shader);
-
- for (input = inputs->first;
- input != NULL;
- input = input->next)
- {
- if (input->source == GPU_SOURCE_ATTRIB &&
- input->attribtype == CD_MTFACE)
- {
- char name[64];
- /* TODO(sergey): This will work for until names are
- * consistent, we'll need to solve this somehow in the future.
- */
- int layer_index;
- int location;
-
- if (input->attribname[0] != '\0') {
- layer_index = CustomData_get_named_layer(&dm->loopData,
- CD_MLOOPUV,
- input->attribname);
- }
- else {
- layer_index = CustomData_get_active_layer(&dm->loopData,
- CD_MLOOPUV);
- }
-
- BLI_snprintf(name, sizeof(name),
- "fvar%d_offset",
- input->attribid);
- location = GPU_shader_get_uniform(shader, name);
- GPU_shader_uniform_int(shader, location, layer_index);
- }
- }
-
- GPU_shader_unbind();
-}
-#endif
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
new file mode 100644
index 00000000000..b6214f2778b
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -0,0 +1,649 @@
+/*
+ * ***** 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 ipmlied 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) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Alexandr Kuznetsov, Jason Wilkins, Mike Erwin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/intern/gpu_matrix.c
+ * \ingroup gpu
+ */
+
+#include "../../../intern/gawain/gawain/gwn_shader_interface.h"
+
+#define SUPPRESS_GENERIC_MATRIX_API
+#define USE_GPU_PY_MATRIX_API /* only so values are declared */
+#include "GPU_matrix.h"
+#undef USE_GPU_PY_MATRIX_API
+
+#include "BLI_math_matrix.h"
+#include "BLI_math_rotation.h"
+#include "BLI_math_vector.h"
+
+
+#define DEBUG_MATRIX_BIND 0
+
+#define MATRIX_STACK_DEPTH 32
+
+typedef float Mat4[4][4];
+typedef float Mat3[3][3];
+
+typedef struct MatrixStack {
+ Mat4 stack[MATRIX_STACK_DEPTH];
+ unsigned int top;
+} MatrixStack;
+
+typedef struct {
+ MatrixStack model_view_stack;
+ MatrixStack projection_stack;
+
+ bool dirty;
+
+ /* TODO: cache of derived matrices (Normal, MVP, inverse MVP, etc)
+ * generate as needed for shaders, invalidate when original matrices change
+ *
+ * TODO: separate Model from View transform? Batches/objects have model,
+ * camera/eye has view & projection
+ */
+} MatrixState;
+
+#define MATRIX_4X4_IDENTITY {{1.0f, 0.0f, 0.0f, 0.0f}, \
+ {0.0f, 1.0f, 0.0f, 0.0f}, \
+ {0.0f, 0.0f, 1.0f, 0.0f}, \
+ {0.0f, 0.0f, 0.0f, 1.0f}}
+
+static MatrixState state = {
+ .model_view_stack = {{MATRIX_4X4_IDENTITY}, 0},
+ .projection_stack = {{MATRIX_4X4_IDENTITY}, 0},
+ .dirty = true
+};
+
+#undef MATRIX_4X4_IDENTITY
+
+#define ModelViewStack state.model_view_stack
+#define ModelView ModelViewStack.stack[ModelViewStack.top]
+
+#define ProjectionStack state.projection_stack
+#define Projection ProjectionStack.stack[ProjectionStack.top]
+
+void gpuMatrixReset(void)
+{
+ state.model_view_stack.top = 0;
+ state.projection_stack.top = 0;
+ unit_m4(ModelView);
+ unit_m4(Projection);
+ state.dirty = true;
+}
+
+#ifdef WITH_GPU_SAFETY
+
+/* Check if matrix is numerically good */
+static void checkmat(cosnt float *m)
+{
+ const int n = 16;
+ for (int i = 0; i < n; i++) {
+#if _MSC_VER
+ BLI_assert(_finite(m[i]));
+#else
+ BLI_assert(!isinf(m[i]));
+#endif
+ }
+}
+
+#define CHECKMAT(m) checkmat((const float*)m)
+
+#else
+
+#define CHECKMAT(m)
+
+#endif
+
+
+void gpuPushMatrix(void)
+{
+ BLI_assert(ModelViewStack.top + 1 < MATRIX_STACK_DEPTH);
+ ModelViewStack.top++;
+ copy_m4_m4(ModelView, ModelViewStack.stack[ModelViewStack.top - 1]);
+}
+
+void gpuPopMatrix(void)
+{
+ BLI_assert(ModelViewStack.top > 0);
+ ModelViewStack.top--;
+ state.dirty = true;
+}
+
+void gpuPushProjectionMatrix(void)
+{
+ BLI_assert(ProjectionStack.top + 1 < MATRIX_STACK_DEPTH);
+ ProjectionStack.top++;
+ copy_m4_m4(Projection, ProjectionStack.stack[ProjectionStack.top - 1]);
+}
+
+void gpuPopProjectionMatrix(void)
+{
+ BLI_assert(ProjectionStack.top > 0);
+ ProjectionStack.top--;
+ state.dirty = true;
+}
+
+void gpuLoadMatrix(const float m[4][4])
+{
+ copy_m4_m4(ModelView, m);
+ CHECKMAT(ModelView3D);
+ state.dirty = true;
+}
+
+void gpuLoadIdentityProjectionMatrix(void)
+{
+ unit_m4(Projection);
+ CHECKMAT(Projection3D);
+ state.dirty = true;
+}
+
+void gpuLoadProjectionMatrix(const float m[4][4])
+{
+ copy_m4_m4(Projection, m);
+ CHECKMAT(Projection3D);
+ state.dirty = true;
+}
+
+void gpuLoadIdentity(void)
+{
+ unit_m4(ModelView);
+ state.dirty = true;
+}
+
+void gpuTranslate2f(float x, float y)
+{
+ Mat4 m;
+ unit_m4(m);
+ m[3][0] = x;
+ m[3][1] = y;
+ gpuMultMatrix(m);
+}
+
+void gpuTranslate2fv(const float vec[2])
+{
+ gpuTranslate2f(vec[0], vec[1]);
+}
+
+void gpuTranslate3f(float x, float y, float z)
+{
+#if 1
+ translate_m4(ModelView, x, y, z);
+ CHECKMAT(ModelView);
+#else /* above works well in early testing, below is generic version */
+ Mat4 m;
+ unit_m4(m);
+ m[3][0] = x;
+ m[3][1] = y;
+ m[3][2] = z;
+ gpuMultMatrix(m);
+#endif
+ state.dirty = true;
+}
+
+void gpuTranslate3fv(const float vec[3])
+{
+ gpuTranslate3f(vec[0], vec[1], vec[2]);
+}
+
+void gpuScaleUniform(float factor)
+{
+ Mat4 m;
+ scale_m4_fl(m, factor);
+ gpuMultMatrix(m);
+}
+
+void gpuScale2f(float x, float y)
+{
+ Mat4 m = {{0.0f}};
+ m[0][0] = x;
+ m[1][1] = y;
+ m[2][2] = 1.0f;
+ m[3][3] = 1.0f;
+ gpuMultMatrix(m);
+}
+
+void gpuScale2fv(const float vec[2])
+{
+ gpuScale2f(vec[0], vec[1]);
+}
+
+void gpuScale3f(float x, float y, float z)
+{
+ Mat4 m = {{0.0f}};
+ m[0][0] = x;
+ m[1][1] = y;
+ m[2][2] = z;
+ m[3][3] = 1.0f;
+ gpuMultMatrix(m);
+}
+
+void gpuScale3fv(const float vec[3])
+{
+ gpuScale3f(vec[0], vec[1], vec[2]);
+}
+
+void gpuMultMatrix(const float m[4][4])
+{
+ mul_m4_m4_post(ModelView, m);
+ CHECKMAT(ModelView);
+ state.dirty = true;
+}
+
+void gpuRotate2D(float deg)
+{
+ /* essentially RotateAxis('Z')
+ * TODO: simpler math for 2D case
+ */
+ rotate_m4(ModelView, 'Z', DEG2RADF(deg));
+}
+
+void gpuRotate3f(float deg, float x, float y, float z)
+{
+ const float axis[3] = {x, y, z};
+ gpuRotate3fv(deg, axis);
+}
+
+void gpuRotate3fv(float deg, const float axis[3])
+{
+ Mat4 m;
+ axis_angle_to_mat4(m, axis, DEG2RADF(deg));
+ gpuMultMatrix(m);
+}
+
+void gpuRotateAxis(float deg, char axis)
+{
+ /* rotate_m4 works in place */
+ rotate_m4(ModelView, axis, DEG2RADF(deg));
+ CHECKMAT(ModelView);
+ state.dirty = true;
+}
+
+static void mat4_ortho_set(float m[4][4], float left, float right, float bottom, float top, float near, float far)
+{
+ m[0][0] = 2.0f / (right - left);
+ m[1][0] = 0.0f;
+ m[2][0] = 0.0f;
+ m[3][0] = -(right + left) / (right - left);
+
+ m[0][1] = 0.0f;
+ m[1][1] = 2.0f / (top - bottom);
+ m[2][1] = 0.0f;
+ m[3][1] = -(top + bottom) / (top - bottom);
+
+ m[0][2] = 0.0f;
+ m[1][2] = 0.0f;
+ m[2][2] = -2.0f / (far - near);
+ m[3][2] = -(far + near) / (far - near);
+
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = 0.0f;
+ m[3][3] = 1.0f;
+
+ state.dirty = true;
+}
+
+static void mat4_frustum_set(float m[4][4], float left, float right, float bottom, float top, float near, float far)
+{
+ m[0][0] = 2.0f * near / (right - left);
+ m[1][0] = 0.0f;
+ m[2][0] = (right + left) / (right - left);
+ m[3][0] = 0.0f;
+
+ m[0][1] = 0.0f;
+ m[1][1] = 2.0f * near / (top - bottom);
+ m[2][1] = (top + bottom) / (top - bottom);
+ m[3][1] = 0.0f;
+
+ m[0][2] = 0.0f;
+ m[1][2] = 0.0f;
+ m[2][2] = -(far + near) / (far - near);
+ m[3][2] = -2.0f * far * near / (far - near);
+
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = -1.0f;
+ m[3][3] = 0.0f;
+
+ state.dirty = true;
+}
+
+static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3])
+{
+/* This function is loosely based on Mesa implementation.
+ *
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+ float side[3];
+
+ normalize_v3(lookdir);
+
+ cross_v3_v3v3(side, lookdir, camup);
+
+ normalize_v3(side);
+
+ cross_v3_v3v3(camup, side, lookdir);
+
+ m[0][0] = side[0];
+ m[1][0] = side[1];
+ m[2][0] = side[2];
+ m[3][0] = 0.0f;
+
+ m[0][1] = camup[0];
+ m[1][1] = camup[1];
+ m[2][1] = camup[2];
+ m[3][1] = 0.0f;
+
+ m[0][2] = -lookdir[0];
+ m[1][2] = -lookdir[1];
+ m[2][2] = -lookdir[2];
+ m[3][2] = 0.0f;
+
+ m[0][3] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][3] = 0.0f;
+ m[3][3] = 1.0f;
+
+ state.dirty = true;
+}
+
+void gpuOrtho(float left, float right, float bottom, float top, float near, float far)
+{
+ mat4_ortho_set(Projection, left, right, bottom, top, near, far);
+ CHECKMAT(Projection);
+ state.dirty = true;
+}
+
+void gpuOrtho2D(float left, float right, float bottom, float top)
+{
+ Mat4 m;
+ mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f);
+ CHECKMAT(Projection2D);
+ state.dirty = true;
+}
+
+void gpuFrustum(float left, float right, float bottom, float top, float near, float far)
+{
+ mat4_frustum_set(Projection, left, right, bottom, top, near, far);
+ CHECKMAT(Projection);
+ state.dirty = true;
+}
+
+void gpuPerspective(float fovy, float aspect, float near, float far)
+{
+ float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near;
+ float half_width = half_height * aspect;
+ gpuFrustum(-half_width, +half_width, -half_height, +half_height, near, far);
+}
+
+void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
+{
+ Mat4 cm;
+ float lookdir[3];
+ float camup[3] = {upX, upY, upZ};
+
+ lookdir[0] = centerX - eyeX;
+ lookdir[1] = centerY - eyeY;
+ lookdir[2] = centerZ - eyeZ;
+
+ mat4_look_from_origin(cm, lookdir, camup);
+
+ gpuMultMatrix(cm);
+ gpuTranslate3f(-eyeX, -eyeY, -eyeZ);
+}
+
+void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3])
+{
+ float v[4];
+
+ mul_v4_m4v3(v, model, world);
+ mul_m4_v4(proj, v);
+
+ if (v[3] != 0.0f) {
+ mul_v3_fl(v, 1.0f / v[3]);
+ }
+
+ win[0] = view[0] + (view[2] * (v[0] + 1)) * 0.5f;
+ win[1] = view[1] + (view[3] * (v[1] + 1)) * 0.5f;
+ win[2] = (v[2] + 1) * 0.5f;
+}
+
+bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3])
+{
+ float pm[4][4];
+ float in[4];
+ float out[4];
+
+ mul_m4_m4m4(pm, proj, model);
+
+ if (!invert_m4(pm)) {
+ zero_v3(world);
+ return false;
+ }
+
+ in[0] = win[0];
+ in[1] = win[1];
+ in[2] = win[2];
+ in[3] = 1;
+
+ /* Map x and y from window coordinates */
+ in[0] = (in[0] - view[0]) / view[2];
+ in[1] = (in[1] - view[1]) / view[3];
+
+ /* Map to range -1 to +1 */
+ in[0] = 2 * in[0] - 1;
+ in[1] = 2 * in[1] - 1;
+ in[2] = 2 * in[2] - 1;
+
+ mul_v4_m4v3(out, pm, in);
+
+ if (out[3] == 0.0f) {
+ copy_v3_v3(world, out);
+ return false;
+ }
+
+ mul_v3_v3fl(world, out, 1.0f / out[3]);
+ return true;
+}
+
+const float (*gpuGetModelViewMatrix(float m[4][4]))[4]
+{
+ if (m) {
+ copy_m4_m4(m, ModelView);
+ return m;
+ }
+ else {
+ return ModelView;
+ }
+}
+
+const float (*gpuGetProjectionMatrix(float m[4][4]))[4]
+{
+ if (m) {
+ copy_m4_m4(m, Projection);
+ return m;
+ }
+ else {
+ return Projection;
+ }
+}
+
+const float (*gpuGetModelViewProjectionMatrix(float m[4][4]))[4]
+{
+ if (m == NULL) {
+ static Mat4 temp;
+ m = temp;
+ }
+
+ mul_m4_m4m4(m, Projection, ModelView);
+ return m;
+}
+
+const float (*gpuGetNormalMatrix(float m[3][3]))[3]
+{
+ if (m == NULL) {
+ static Mat3 temp3;
+ m = temp3;
+ }
+
+ copy_m3_m4(m, (const float (*)[4])gpuGetModelViewMatrix(NULL));
+
+ invert_m3(m);
+ transpose_m3(m);
+
+ return m;
+}
+
+const float (*gpuGetNormalMatrixInverse(float m[3][3]))[3]
+{
+ if (m == NULL) {
+ static Mat3 temp3;
+ m = temp3;
+ }
+
+ gpuGetNormalMatrix(m);
+ invert_m3(m);
+
+ return m;
+}
+
+void gpuBindMatrices(const Gwn_ShaderInterface *shaderface)
+{
+ /* set uniform values to matrix stack values
+ * call this before a draw call if desired matrices are dirty
+ * call glUseProgram before this, as glUniform expects program to be bound
+ */
+
+ const Gwn_ShaderInput *MV = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_MODELVIEW);
+ const Gwn_ShaderInput *P = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_PROJECTION);
+ const Gwn_ShaderInput *MVP = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_MVP);
+
+ const Gwn_ShaderInput *N = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_NORMAL);
+ const Gwn_ShaderInput *MV_inv = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_MODELVIEW_INV);
+ const Gwn_ShaderInput *P_inv = GWN_shaderinterface_uniform_builtin(shaderface, GWN_UNIFORM_PROJECTION_INV);
+
+ if (MV) {
+#if DEBUG_MATRIX_BIND
+ puts("setting MV matrix");
+#endif
+
+ glUniformMatrix4fv(MV->location, 1, GL_FALSE, (const float *)gpuGetModelViewMatrix(NULL));
+ }
+
+ if (P) {
+#if DEBUG_MATRIX_BIND
+ puts("setting P matrix");
+#endif
+
+ glUniformMatrix4fv(P->location, 1, GL_FALSE, (const float *)gpuGetProjectionMatrix(NULL));
+ }
+
+ if (MVP) {
+#if DEBUG_MATRIX_BIND
+ puts("setting MVP matrix");
+#endif
+
+ glUniformMatrix4fv(MVP->location, 1, GL_FALSE, (const float *)gpuGetModelViewProjectionMatrix(NULL));
+ }
+
+ if (N) {
+#if DEBUG_MATRIX_BIND
+ puts("setting normal matrix");
+#endif
+
+ glUniformMatrix3fv(N->location, 1, GL_FALSE, (const float *)gpuGetNormalMatrix(NULL));
+ }
+
+ if (MV_inv) {
+ Mat4 m;
+ gpuGetModelViewMatrix(m);
+ invert_m4(m);
+ glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float *)m);
+ }
+
+ if (P_inv) {
+ Mat4 m;
+ gpuGetProjectionMatrix(m);
+ invert_m4(m);
+ glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float *)m);
+ }
+
+ state.dirty = false;
+}
+
+bool gpuMatricesDirty(void)
+{
+ return state.dirty;
+}
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Python API Helpers
+ * \{ */
+BLI_STATIC_ASSERT(GPU_PY_MATRIX_STACK_LEN + 1 == MATRIX_STACK_DEPTH, "define mismatch");
+
+/* Return int since caller is may subtract. */
+
+int GPU_matrix_stack_level_get_model_view(void)
+{
+ return (int)state.model_view_stack.top;
+}
+
+int GPU_matrix_stack_level_get_projection(void)
+{
+ return (int)state.projection_stack.top;
+}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 291a552a041..7023e44d289 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -187,12 +187,7 @@ uint GPU_select_end(void)
*/
bool GPU_select_query_check_active(void)
{
- return ((U.gpu_select_method == USER_SELECT_USE_OCCLUSION_QUERY) ||
- ((U.gpu_select_method == USER_SELECT_AUTO) &&
- (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) ||
- /* unsupported by nouveau, gallium 0.4, see: T47940 */
- GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE))));
-
+ return ELEM(U.gpu_select_method, USER_SELECT_USE_OCCLUSION_QUERY, USER_SELECT_AUTO);
}
/* ----------------------------------------------------------------------------
@@ -232,3 +227,29 @@ bool GPU_select_is_cached(void)
{
return g_select_state.use_cache && gpu_select_pick_is_cached();
}
+
+
+/* ----------------------------------------------------------------------------
+ * Utilities
+ */
+
+/**
+ * Helper function, nothing special but avoids doing inline since hit's aren't sorted by depth
+ * and purpose of 4x buffer indices isn't so clear.
+ *
+ * Note that comparing depth as uint is fine.
+ */
+const uint *GPU_select_buffer_near(const uint *buffer, int hits)
+{
+ const uint *buffer_near = NULL;
+ uint depth_min = (uint)-1;
+ for (int i = 0; i < hits; i++) {
+ if (buffer[1] < depth_min) {
+ BLI_assert(buffer[3] != -1);
+ depth_min = buffer[1];
+ buffer_near = buffer;
+ }
+ buffer += 4;
+ }
+ return buffer_near;
+}
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index 3e65e2987e6..953f6daf805 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -31,6 +31,8 @@
#include <stdlib.h>
#include <float.h>
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
#include "GPU_select.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
@@ -316,8 +318,8 @@ void gpu_select_pick_begin(
/* Restrict OpenGL operations for when we don't have cache */
if (ps->is_cached == false) {
+ gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT);
- glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
/* disable writing to the framebuffer */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
@@ -334,12 +336,8 @@ void gpu_select_pick_begin(
glDepthFunc(GL_LEQUAL);
}
- /* set just in case */
- glPixelTransferf(GL_DEPTH_BIAS, 0.0);
- glPixelTransferf(GL_DEPTH_SCALE, 1.0);
-
float viewport[4];
- glGetFloatv(GL_SCISSOR_BOX, viewport);
+ glGetFloatv(GL_VIEWPORT, viewport);
ps->src.clip_rect = *input;
ps->src.rect_len = rect_len;
@@ -542,7 +540,7 @@ uint gpu_select_pick_end(void)
/* force finishing last pass */
gpu_select_pick_load_id(ps->gl.prev_id);
}
- glPopAttrib();
+ gpuPopAttrib();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index 9bb96ea67a2..919ccbea2e9 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -32,6 +32,8 @@
#include <stdlib.h>
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
#include "GPU_select.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
@@ -42,6 +44,8 @@
#include "BLI_utildefines.h"
+#include "PIL_time.h"
+
#include "gpu_select_private.h"
@@ -94,15 +98,15 @@ void gpu_select_query_begin(
g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), "gpu selection ids");
glGenQueries(g_query_state.num_of_queries, g_query_state.queries);
- glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
+ gpuPushAttrib(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT | GPU_SCISSOR_BIT);
/* disable writing to the framebuffer */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
/* In order to save some fill rate we minimize the viewport using rect.
- * We need to get the region of the scissor so that our geometry doesn't
+ * We need to get the region of the viewport so that our geometry doesn't
* get rejected before the depth test. Should probably cull rect against
- * scissor for viewport but this is a rare case I think */
- glGetFloatv(GL_SCISSOR_BOX, viewport);
+ * the viewport but this is a rare case I think */
+ glGetFloatv(GL_VIEWPORT, viewport);
glViewport(viewport[0], viewport[1], BLI_rcti_size_x(input), BLI_rcti_size_y(input));
/* occlusion queries operates on fragments that pass tests and since we are interested on all
@@ -171,7 +175,16 @@ uint gpu_select_query_end(void)
}
for (i = 0; i < g_query_state.active_query; i++) {
- uint result;
+ uint result = 0;
+ /* Wait until the result is available. */
+ while (result == 0) {
+ glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT_AVAILABLE, &result);
+ if (result == 0) {
+ /* (fclem) Not sure if this is better than calling
+ * glGetQueryObjectuiv() indefinitely. */
+ PIL_sleep_ms(1);
+ }
+ }
glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result);
if (result > 0) {
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
@@ -206,7 +219,7 @@ uint gpu_select_query_end(void)
glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries);
MEM_freeN(g_query_state.queries);
MEM_freeN(g_query_state.id);
- glPopAttrib();
+ gpuPopAttrib();
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
return hits;
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index b579f87698c..2068c5a6a75 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -30,22 +30,129 @@
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
#include "BLI_math_vector.h"
+#include "BLI_path_util.h"
+#include "BKE_appdir.h"
#include "BKE_global.h"
-#include "GPU_compositing.h"
-#include "GPU_debug.h"
+#include "DNA_space_types.h"
+
#include "GPU_extensions.h"
-#include "GPU_glew.h"
+#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
-#include "GPU_material.h"
+#include "GPU_uniformbuffer.h"
+
+#include "gpu_shader_private.h"
-/* TODO(sergey): Find better default values for this constants. */
-#define MAX_DEFINE_LENGTH 1024
-#define MAX_EXT_DEFINE_LENGTH 1024
+/* Adjust these constants as needed. */
+#define MAX_DEFINE_LENGTH 256
+#define MAX_EXT_DEFINE_LENGTH 256
/* Non-generated shaders */
+extern char datatoc_gpu_shader_depth_only_frag_glsl[];
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_checker_frag_glsl[];
+extern char datatoc_gpu_shader_diag_stripes_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_flat_color_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl[];
+extern char datatoc_gpu_shader_flat_color_frag_glsl[];
+extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[];
+extern char datatoc_gpu_shader_flat_id_frag_glsl[];
+extern char datatoc_gpu_shader_2D_vert_glsl[];
+extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_uniform_alpha_vert_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
+extern char datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl[];
+extern char datatoc_gpu_shader_2D_image_vert_glsl[];
+extern char datatoc_gpu_shader_2D_image_rect_vert_glsl[];
+extern char datatoc_gpu_shader_2D_image_multi_rect_vert_glsl[];
+extern char datatoc_gpu_shader_2D_widget_base_vert_glsl[];
+extern char datatoc_gpu_shader_2D_widget_base_frag_glsl[];
+extern char datatoc_gpu_shader_2D_widget_shadow_vert_glsl[];
+extern char datatoc_gpu_shader_2D_widget_shadow_frag_glsl[];
+extern char datatoc_gpu_shader_2D_nodelink_frag_glsl[];
+extern char datatoc_gpu_shader_2D_nodelink_vert_glsl[];
+
+extern char datatoc_gpu_shader_3D_image_vert_glsl[];
+extern char datatoc_gpu_shader_image_frag_glsl[];
+extern char datatoc_gpu_shader_image_linear_frag_glsl[];
+extern char datatoc_gpu_shader_image_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_desaturate_frag_glsl[];
+extern char datatoc_gpu_shader_image_varying_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_alpha_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_interlace_frag_glsl[];
+extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
+extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[];
+extern char datatoc_gpu_shader_image_depth_copy_frag_glsl[];
+extern char datatoc_gpu_shader_image_multisample_resolve_frag_glsl[];
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_3D_normal_vert_glsl[];
+extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_normal_flat_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
+extern char datatoc_gpu_shader_3D_passthrough_vert_glsl[];
+extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[];
+
+extern char datatoc_gpu_shader_instance_vert_glsl[];
+extern char datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_variying_size_variying_id_vert_glsl[];
+extern char datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_screen_aligned_vert_glsl[];
+extern char datatoc_gpu_shader_instance_camera_vert_glsl[];
+extern char datatoc_gpu_shader_instance_distance_line_vert_glsl[];
+extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[];
+extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_mball_handles_vert_glsl[];
+
+extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
+extern char datatoc_gpu_shader_3D_groundline_geom_glsl[];
+
+extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_aa_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl[];
+extern char datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl[];
+extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
+extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_varying_size_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl[];
+
+extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[];
+extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[];
+extern char datatoc_gpu_shader_2D_line_dashed_geom_glsl[];
+extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl[];
+extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl[];
+
+extern char datatoc_gpu_shader_edges_front_back_persp_vert_glsl[];
+extern char datatoc_gpu_shader_edges_front_back_persp_geom_glsl[];
+extern char datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl[];
+extern char datatoc_gpu_shader_edges_front_back_ortho_vert_glsl[];
+extern char datatoc_gpu_shader_edges_overlay_vert_glsl[];
+extern char datatoc_gpu_shader_edges_overlay_geom_glsl[];
+extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[];
+extern char datatoc_gpu_shader_edges_overlay_frag_glsl[];
+extern char datatoc_gpu_shader_text_vert_glsl[];
+extern char datatoc_gpu_shader_text_geom_glsl[];
+extern char datatoc_gpu_shader_text_frag_glsl[];
+extern char datatoc_gpu_shader_text_simple_vert_glsl[];
+extern char datatoc_gpu_shader_text_simple_geom_glsl[];
+extern char datatoc_gpu_shader_keyframe_diamond_vert_glsl[];
+extern char datatoc_gpu_shader_keyframe_diamond_frag_glsl[];
+
extern char datatoc_gpu_shader_fire_frag_glsl[];
extern char datatoc_gpu_shader_smoke_vert_glsl[];
extern char datatoc_gpu_shader_smoke_frag_glsl[];
@@ -53,51 +160,23 @@ extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
-extern char datatoc_gpu_shader_fx_vert_glsl[];
-extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
-extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
-extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
-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[];
-
-static struct GPUShadersGlobal {
- struct {
- GPUShader *vsm_store;
- GPUShader *sep_gaussian_blur;
- GPUShader *smoke;
- GPUShader *smoke_fire;
- GPUShader *smoke_coba;
- /* cache for shader fx. Those can exist in combinations so store them here */
- GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
- } shaders;
-} GG = {{NULL}};
-
-/* GPUShader */
-
-struct GPUShader {
- GLuint program; /* handle for full program (links shader stages below) */
-
- GLuint vertex; /* handle for vertex shader */
- GLuint geometry; /* handle for geometry shader */
- GLuint fragment; /* handle for fragment shader */
-
- int totattrib; /* total number of attributes */
- int uniforms; /* required uniforms */
-
- void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */
-};
+
+/* cache of built-in shaders (each is created on first use) */
+static GPUShader *builtin_shaders[GPU_NUM_BUILTIN_SHADERS] = { NULL };
+
+typedef struct {
+ const char *vert;
+ const char *frag;
+ const char *geom; /* geometry stage runs between vert & frag, but is less common, so it goes last */
+} GPUShaderStages;
static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
{
- int i;
int line = 1;
fprintf(stderr, "GPUShader: %s error:\n", task);
- for (i = 0; i < totcode; i++) {
+ for (int i = 0; i < totcode; i++) {
const char *c, *pos, *end = code[i] + strlen(code[i]);
if (G.debug & G_DEBUG) {
@@ -120,76 +199,23 @@ static void shader_print_errors(const char *task, const char *log, const char **
static const char *gpu_shader_version(void)
{
- if (GLEW_VERSION_3_2) {
- if (GLEW_ARB_compatibility) {
- return "#version 150 compatibility\n";
- /* highest version that is widely supported
- * gives us native geometry shaders!
- * use compatibility profile so we can continue using builtin shader input/output names
- */
- }
- else {
- return "#version 130\n";
- /* latest version that is compatible with existing shaders */
- }
- }
- else if (GLEW_VERSION_3_1) {
- if (GLEW_ARB_compatibility) {
- return "#version 140\n";
- /* also need the ARB_compatibility extension, handled below */
- }
- else {
- return "#version 130\n";
- /* latest version that is compatible with existing shaders */
- }
- }
- else if (GLEW_VERSION_3_0) {
- return "#version 130\n";
- /* GLSL 1.3 has modern syntax/keywords/datatypes so use if available
- * older features are deprecated but still available without compatibility extension or profile
- */
- }
- else {
- return "#version 120\n";
- /* minimum supported */
- }
+ return "#version 330\n";
}
-
-static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_geometry_shader)
+static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH])
{
/* enable extensions for features that are not part of our base GLSL version
* don't use an extension for something already available!
*/
if (GLEW_ARB_texture_query_lod) {
- /* a #version 400 feature, but we use #version 150 maximum so use extension */
+ /* a #version 400 feature, but we use #version 330 maximum so use extension */
strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
}
-
- if (use_geometry_shader && GPU_geometry_shader_support_via_extension()) {
- strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
- }
-
- if (GLEW_VERSION_3_1 && !GLEW_VERSION_3_2 && GLEW_ARB_compatibility) {
- strcat(defines, "#extension GL_ARB_compatibility: enable\n");
- }
-
- if (!GLEW_VERSION_3_1) {
- if (GLEW_ARB_draw_instanced) {
- strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
- }
-
- if (!GLEW_VERSION_3_0 && GLEW_EXT_gpu_shader4) {
- strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
- /* TODO: maybe require this? shaders become so much nicer */
- }
- }
}
static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH],
- bool use_opensubdiv,
- bool use_new_shading)
+ bool use_opensubdiv)
{
/* some useful defines to detect GPU type */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
@@ -207,10 +233,6 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH],
if (GPU_bicubic_bump_support())
strcat(defines, "#define BUMP_BICUBIC\n");
- if (GLEW_VERSION_3_0) {
- strcat(defines, "#define BIT_OPERATIONS\n");
- }
-
#ifdef WITH_OPENSUBDIV
/* TODO(sergey): Check whether we actually compiling shader for
* the OpenSubdiv mesh.
@@ -232,10 +254,6 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH],
UNUSED_VARS(use_opensubdiv);
#endif
- if (use_new_shading) {
- strcat(defines, "#define USE_NEW_SHADING\n");
- }
-
return;
}
@@ -243,20 +261,64 @@ GPUShader *GPU_shader_create(const char *vertexcode,
const char *fragcode,
const char *geocode,
const char *libcode,
- const char *defines,
- int input,
- int output,
- int number)
+ const char *defines)
{
return GPU_shader_create_ex(vertexcode,
fragcode,
geocode,
libcode,
defines,
- input,
- output,
- number,
- GPU_SHADER_FLAGS_NONE);
+ GPU_SHADER_FLAGS_NONE,
+ GPU_SHADER_TFB_NONE,
+ NULL,
+ 0);
+}
+
+#define DEBUG_SHADER_NONE ""
+#define DEBUG_SHADER_VERTEX "vert"
+#define DEBUG_SHADER_FRAGMENT "frag"
+#define DEBUG_SHADER_GEOMETRY "geom"
+
+/**
+ * Dump GLSL shaders to disk
+ *
+ * This is used for profiling shader performance externally and debug if shader code is correct.
+ * If called with no code, it simply bumps the shader index, so different shaders for the same
+ * program share the same index.
+ */
+static void gpu_dump_shaders(const char **code, const int num_shaders, const char *extension)
+{
+ if ((G.debug & G_DEBUG_GPU_SHADERS) == 0) {
+ return;
+ }
+
+ /* We use the same shader index for shaders in the same program.
+ * So we call this function once before calling for the invidual shaders. */
+ static int shader_index = 0;
+ if (code == NULL) {
+ shader_index++;
+ BLI_assert(STREQ(DEBUG_SHADER_NONE, extension));
+ return;
+ }
+
+ /* Determine the full path of the new shader. */
+ char shader_path[FILE_MAX];
+
+ char file_name[512] = {'\0'};
+ sprintf(file_name, "%04d.%s", shader_index, extension);
+
+ BLI_join_dirfile(shader_path, sizeof(shader_path), BKE_tempdir_session(), file_name);
+
+ /* Write shader to disk. */
+ FILE *f = fopen(shader_path, "w");
+ if (f == NULL) {
+ printf("Error writing to file: %s\n", shader_path);
+ }
+ for (int j = 0; j < num_shaders; j++) {
+ fprintf(f, "%s", code[j]);
+ }
+ fclose(f);
+ printf("Shader file written to disk: %s\n", shader_path);
}
GPUShader *GPU_shader_create_ex(const char *vertexcode,
@@ -264,16 +326,12 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
const char *geocode,
const char *libcode,
const char *defines,
- int input,
- int output,
- int number,
- const int flags)
+ const int flags,
+ const GPUShaderTFBType tf_type,
+ const char **tf_names,
+ const int tf_count)
{
#ifdef WITH_OPENSUBDIV
- /* TODO(sergey): used to add #version 150 to the geometry shader.
- * Could safely be renamed to "use_geometry_code" since it's very
- * likely any of geometry code will want to use GLSL 1.5.
- */
bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
#else
UNUSED_VARS(flags);
@@ -286,10 +344,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
char standard_defines[MAX_DEFINE_LENGTH] = "";
char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
- if (geocode && !GPU_geometry_shader_support())
- return NULL;
-
shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
+ gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE);
if (vertexcode)
shader->vertex = glCreateShader(GL_VERTEX_SHADER);
@@ -311,9 +367,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
}
gpu_shader_standard_defines(standard_defines,
- use_opensubdiv,
- (flags & GPU_SHADER_FLAGS_NEW_SHADING) != 0);
- gpu_shader_standard_extensions(standard_extensions, geocode != NULL);
+ use_opensubdiv);
+ gpu_shader_standard_extensions(standard_extensions);
if (vertexcode) {
const char *source[5];
@@ -327,6 +382,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
if (defines) source[num_source++] = defines;
source[num_source++] = vertexcode;
+ gpu_dump_shaders(source, num_source, DEBUG_SHADER_VERTEX);
+
glAttachShader(shader->program, shader->vertex);
glShaderSource(shader->vertex, num_source, source, NULL);
@@ -366,6 +423,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
if (libcode) source[num_source++] = libcode;
source[num_source++] = fragcode;
+ gpu_dump_shaders(source, num_source, DEBUG_SHADER_FRAGMENT);
+
glAttachShader(shader->program, shader->fragment);
glShaderSource(shader->fragment, num_source, source, NULL);
@@ -392,6 +451,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
if (defines) source[num_source++] = defines;
source[num_source++] = geocode;
+ gpu_dump_shaders(source, num_source, DEBUG_SHADER_GEOMETRY);
+
glAttachShader(shader->program, shader->geometry);
glShaderSource(shader->geometry, num_source, source, NULL);
@@ -405,23 +466,22 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
GPU_shader_free(shader);
return NULL;
}
-
- if (!use_opensubdiv) {
- GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
- }
}
#ifdef WITH_OPENSUBDIV
if (use_opensubdiv) {
glBindAttribLocation(shader->program, 0, "position");
glBindAttribLocation(shader->program, 1, "normal");
- GPU_shader_geometry_stage_primitive_io(shader,
- GL_LINES_ADJACENCY_EXT,
- GL_TRIANGLE_STRIP,
- 4);
}
#endif
+ if (tf_names != NULL) {
+ glTransformFeedbackVaryings(shader->program, tf_count, tf_names, GL_INTERLEAVED_ATTRIBS);
+ /* Primitive type must be setup */
+ BLI_assert(tf_type != GPU_SHADER_TFB_NONE);
+ shader->feedback_transform_type = tf_type;
+ }
+
glLinkProgram(shader->program);
glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
if (!status) {
@@ -436,38 +496,75 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
return NULL;
}
+ shader->interface = GWN_shaderinterface_create(shader->program);
+
#ifdef WITH_OPENSUBDIV
/* TODO(sergey): Find a better place for this. */
- if (use_opensubdiv && GLEW_VERSION_4_1) {
- glProgramUniform1i(shader->program,
- glGetUniformLocation(shader->program, "FVarDataOffsetBuffer"),
- 30); /* GL_TEXTURE30 */
-
- glProgramUniform1i(shader->program,
- glGetUniformLocation(shader->program, "FVarDataBuffer"),
- 31); /* GL_TEXTURE31 */
+ if (use_opensubdiv) {
+ if (GLEW_VERSION_4_1) {
+ glProgramUniform1i(shader->program,
+ GWN_shaderinterface_uniform(shader->interface, "FVarDataOffsetBuffer")->location,
+ 30); /* GL_TEXTURE30 */
+
+ glProgramUniform1i(shader->program,
+ GWN_shaderinterface_uniform(shader->interface, "FVarDataBuffer")->location,
+ 31); /* GL_TEXTURE31 */
+ }
+ else {
+ glUseProgram(shader->program);
+ glUniform1i(GWN_shaderinterface_uniform(shader->interface, "FVarDataOffsetBuffer")->location, 30);
+ glUniform1i(GWN_shaderinterface_uniform(shader->interface, "FVarDataBuffer")->location, 31);
+ glUseProgram(0);
+ }
}
#endif
return shader;
}
+#undef DEBUG_SHADER_GEOMETRY
+#undef DEBUG_SHADER_FRAGMENT
+#undef DEBUG_SHADER_VERTEX
+#undef DEBUG_SHADER_NONE
+
void GPU_shader_bind(GPUShader *shader)
{
- GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
+ BLI_assert(shader && shader->program);
+
glUseProgram(shader->program);
- GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
+ gpuBindMatrices(shader->interface);
}
void GPU_shader_unbind(void)
{
- GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
glUseProgram(0);
- GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
+}
+
+bool GPU_shader_transform_feedback_enable(GPUShader *shader, unsigned int vbo_id)
+{
+ if (shader->feedback_transform_type == GPU_SHADER_TFB_NONE) {
+ return false;
+ }
+
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo_id);
+
+ switch (shader->feedback_transform_type) {
+ case GPU_SHADER_TFB_POINTS: glBeginTransformFeedback(GL_POINTS); return true;
+ case GPU_SHADER_TFB_LINES: glBeginTransformFeedback(GL_LINES); return true;
+ case GPU_SHADER_TFB_TRIANGLES: glBeginTransformFeedback(GL_TRIANGLES); return true;
+ default: return false;
+ }
+}
+
+void GPU_shader_transform_feedback_disable(GPUShader *UNUSED(shader))
+{
+ glEndTransformFeedback();
}
void GPU_shader_free(GPUShader *shader)
{
+ BLI_assert(shader);
+
if (shader->vertex)
glDeleteShader(shader->vertex);
if (shader->geometry)
@@ -477,25 +574,43 @@ void GPU_shader_free(GPUShader *shader)
if (shader->program)
glDeleteProgram(shader->program);
- if (shader->uniform_interface)
- MEM_freeN(shader->uniform_interface);
+ if (shader->interface)
+ GWN_shaderinterface_discard(shader->interface);
MEM_freeN(shader);
}
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
{
- return glGetUniformLocation(shader->program, name);
+ BLI_assert(shader && shader->program);
+ const Gwn_ShaderInput *uniform = GWN_shaderinterface_uniform(shader->interface, name);
+ return uniform ? uniform->location : -1;
+}
+
+int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin)
+{
+ BLI_assert(shader && shader->program);
+ const Gwn_ShaderInput *uniform = GWN_shaderinterface_uniform_builtin(shader->interface, builtin);
+ return uniform ? uniform->location : -1;
+}
+
+int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
+{
+ BLI_assert(shader && shader->program);
+
+ const Gwn_ShaderInput *ubo = GWN_shaderinterface_ubo(shader->interface, name);
+ return ubo ? ubo->location : -1;
}
void *GPU_shader_get_interface(GPUShader *shader)
{
- return shader->uniform_interface;
+ return shader->interface;
}
-void GPU_shader_set_interface(GPUShader *shader, void *interface)
+/* Clement : Temp */
+int GPU_shader_get_program(GPUShader *shader)
{
- shader->uniform_interface = interface;
+ return (int)shader->program;
}
void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
@@ -503,16 +618,12 @@ void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int leng
if (location == -1 || value == NULL)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
if (length == 1) glUniform1fv(location, arraysize, value);
else if (length == 2) glUniform2fv(location, arraysize, value);
else if (length == 3) glUniform3fv(location, arraysize, value);
else if (length == 4) glUniform4fv(location, arraysize, value);
else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value);
else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
}
void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
@@ -520,14 +631,10 @@ void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int
if (location == -1)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
-
if (length == 1) glUniform1iv(location, arraysize, value);
else if (length == 2) glUniform2iv(location, arraysize, value);
else if (length == 3) glUniform3iv(location, arraysize, value);
else if (length == 4) glUniform4iv(location, arraysize, value);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
}
void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
@@ -535,225 +642,296 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
if (location == -1)
return;
- GPU_CHECK_ERRORS_AROUND(glUniform1i(location, value));
+ glUniform1i(location, value);
}
-void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
+void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo)
{
- if (GPU_geometry_shader_support_via_extension()) {
- /* geometry shaders must provide this info themselves for #version 150 and up */
- glProgramParameteriEXT(shader->program, GL_GEOMETRY_INPUT_TYPE_EXT, input);
- glProgramParameteriEXT(shader->program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
- glProgramParameteriEXT(shader->program, GL_GEOMETRY_VERTICES_OUT_EXT, number);
+ int bindpoint = GPU_uniformbuffer_bindpoint(ubo);
+
+ if (location == -1) {
+ return;
}
+
+ glUniformBlockBinding(shader->program, location, bindpoint);
}
void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
{
- GLenum arbnumber;
int number = GPU_texture_bound_number(tex);
- int bindcode = GPU_texture_opengl_bindcode(tex);
- int target = GPU_texture_target(tex);
- if (number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
+ if (number == -1) {
+ fprintf(stderr, "Texture is not bound.\n");
+ BLI_assert(0);
return;
}
-
- if (number == -1)
- return;
if (location == -1)
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
-
- arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
-
- if (number != 0) glActiveTexture(arbnumber);
- if (bindcode != 0)
- glBindTexture(target, bindcode);
- else
- GPU_invalid_tex_bind(target);
glUniform1i(location, number);
- glEnable(target);
- if (number != 0) glActiveTexture(GL_TEXTURE0);
-
- GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
{
- int index;
-
- GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocation(shader->program, name));
-
- return index;
+ BLI_assert(shader && shader->program);
+ const Gwn_ShaderInput *attrib = GWN_shaderinterface_attr(shader->interface, name);
+ return attrib ? attrib->location : -1;
}
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
{
- GPUShader *retval = NULL;
-
- switch (shader) {
- case GPU_SHADER_VSM_STORE:
- if (!GG.shaders.vsm_store)
- GG.shaders.vsm_store = GPU_shader_create(
- datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.vsm_store;
- break;
- case GPU_SHADER_SEP_GAUSSIAN_BLUR:
- if (!GG.shaders.sep_gaussian_blur)
- GG.shaders.sep_gaussian_blur = GPU_shader_create(
- datatoc_gpu_shader_sep_gaussian_blur_vert_glsl,
- datatoc_gpu_shader_sep_gaussian_blur_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.sep_gaussian_blur;
- break;
- case GPU_SHADER_SMOKE:
- if (!GG.shaders.smoke)
- GG.shaders.smoke = GPU_shader_create(
- datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.smoke;
- break;
- case GPU_SHADER_SMOKE_FIRE:
- if (!GG.shaders.smoke_fire)
- GG.shaders.smoke_fire = GPU_shader_create(
- datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_fire_frag_glsl,
- NULL, NULL, NULL, 0, 0, 0);
- retval = GG.shaders.smoke_fire;
- break;
- case GPU_SHADER_SMOKE_COBA:
- if (!GG.shaders.smoke_coba)
- GG.shaders.smoke_coba = GPU_shader_create(
- datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl,
- NULL, NULL, "#define USE_COBA;\n", 0, 0, 0);
- retval = GG.shaders.smoke_coba;
- break;
- }
-
- if (retval == NULL)
- printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
-
- return retval;
-}
-
-#define MAX_DEFINES 100
-
-GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp)
-{
- int offset;
- char defines[MAX_DEFINES] = "";
- /* avoid shaders out of range */
- if (effect >= MAX_FX_SHADERS)
- return NULL;
-
- offset = 2 * effect;
-
- if (persp) {
- offset += 1;
- strcat(defines, "#define PERSP_MATRIX\n");
- }
-
- if (!GG.shaders.fx_shaders[offset]) {
- GPUShader *shader = NULL;
-
- switch (effect) {
- case GPU_SHADER_FX_SSAO:
- shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ BLI_assert(shader != GPU_NUM_BUILTIN_SHADERS); /* don't be a troll */
+
+ static const GPUShaderStages builtin_shader_stages[GPU_NUM_BUILTIN_SHADERS] = {
+ [GPU_SHADER_VSM_STORE] = { datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl },
+ [GPU_SHADER_SEP_GAUSSIAN_BLUR] = { datatoc_gpu_shader_sep_gaussian_blur_vert_glsl,
+ datatoc_gpu_shader_sep_gaussian_blur_frag_glsl },
+ [GPU_SHADER_SMOKE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
+ [GPU_SHADER_SMOKE_FIRE] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
+ [GPU_SHADER_SMOKE_COBA] = { datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl },
+
+ [GPU_SHADER_TEXT] = { datatoc_gpu_shader_text_vert_glsl,
+ datatoc_gpu_shader_text_frag_glsl,
+ datatoc_gpu_shader_text_geom_glsl },
+ [GPU_SHADER_TEXT_SIMPLE] = { datatoc_gpu_shader_text_simple_vert_glsl,
+ datatoc_gpu_shader_text_frag_glsl,
+ datatoc_gpu_shader_text_simple_geom_glsl },
+ [GPU_SHADER_KEYFRAME_DIAMOND] = { datatoc_gpu_shader_keyframe_diamond_vert_glsl,
+ datatoc_gpu_shader_keyframe_diamond_frag_glsl },
+ [GPU_SHADER_EDGES_FRONT_BACK_PERSP] = { datatoc_gpu_shader_edges_front_back_persp_vert_glsl,
+ /* this version is */ datatoc_gpu_shader_flat_color_frag_glsl,
+ /* magical but slooow */ datatoc_gpu_shader_edges_front_back_persp_geom_glsl },
+ [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] = { datatoc_gpu_shader_edges_front_back_ortho_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_EDGES_OVERLAY_SIMPLE] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_edges_overlay_frag_glsl,
+ datatoc_gpu_shader_edges_overlay_simple_geom_glsl },
+ [GPU_SHADER_EDGES_OVERLAY] = { datatoc_gpu_shader_edges_overlay_vert_glsl,
+ datatoc_gpu_shader_edges_overlay_frag_glsl,
+ datatoc_gpu_shader_edges_overlay_geom_glsl },
+ [GPU_SHADER_SIMPLE_LIGHTING] = { datatoc_gpu_shader_3D_normal_vert_glsl, datatoc_gpu_shader_simple_lighting_frag_glsl },
+ /* Use 'USE_FLAT_NORMAL' to make flat shader from smooth */
+ [GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR] = { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl },
+ [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl },
+ [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA] = { datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl },
+
+ [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_mask_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = { datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_modulate_alpha_frag_glsl },
+ [GPU_SHADER_3D_IMAGE_DEPTH] = { datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_depth_linear_frag_glsl },
+ [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = { datatoc_gpu_shader_3D_image_vert_glsl,
+ datatoc_gpu_shader_image_depth_copy_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_image_multisample_resolve_frag_glsl },
+
+ [GPU_SHADER_2D_IMAGE_INTERLACE] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_interlace_frag_glsl },
+ [GPU_SHADER_2D_CHECKER] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_checker_frag_glsl },
+
+ [GPU_SHADER_2D_DIAG_STRIPES] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_diag_stripes_frag_glsl },
+
+ [GPU_SHADER_2D_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_2D_FLAT_COLOR] = { datatoc_gpu_shader_2D_flat_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_2D_SMOOTH_COLOR] = { datatoc_gpu_shader_2D_smooth_color_vert_glsl,
+ datatoc_gpu_shader_2D_smooth_color_frag_glsl },
+ [GPU_SHADER_2D_SMOOTH_COLOR_DITHER] = { datatoc_gpu_shader_2D_smooth_color_vert_glsl,
+ datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_linear_frag_glsl },
+ [GPU_SHADER_2D_IMAGE] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_DESATURATE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_desaturate_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_alpha_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_shuffle_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_RECT_COLOR] = { datatoc_gpu_shader_2D_image_rect_vert_glsl,
+ datatoc_gpu_shader_image_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = { datatoc_gpu_shader_2D_image_multi_rect_vert_glsl,
+ datatoc_gpu_shader_image_varying_color_frag_glsl },
+
+ [GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_UNIFORM_COLOR_U32] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_3D_FLAT_COLOR_U32] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_3D_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl,
+ datatoc_gpu_shader_3D_smooth_color_frag_glsl },
+ [GPU_SHADER_3D_DEPTH_ONLY] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_depth_only_frag_glsl },
+ [GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl },
+
+ [GPU_SHADER_3D_GROUNDPOINT] = { datatoc_gpu_shader_3D_groundpoint_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_GROUNDLINE] = { datatoc_gpu_shader_3D_passthrough_vert_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl,
+ datatoc_gpu_shader_3D_groundline_geom_glsl },
+
+ [GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl,
+ datatoc_gpu_shader_2D_line_dashed_frag_glsl,
+ datatoc_gpu_shader_2D_line_dashed_geom_glsl },
+ [GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl,
+ datatoc_gpu_shader_2D_line_dashed_frag_glsl,
+ datatoc_gpu_shader_2D_line_dashed_geom_glsl },
+
+ [GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR] =
+ { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl,
+ datatoc_gpu_shader_simple_lighting_frag_glsl},
+ [GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+ [GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+ [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS] = { datatoc_gpu_shader_instance_screen_aligned_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+ [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED] = { datatoc_gpu_shader_instance_screen_aligned_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+
+ [GPU_SHADER_CAMERA] = { datatoc_gpu_shader_instance_camera_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+ [GPU_SHADER_DISTANCE_LINES] = { datatoc_gpu_shader_instance_distance_line_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+
+ [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] =
+ { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
+ [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] =
+ { datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl },
+ [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] =
+ { datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_aa_frag_glsl },
+ [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] =
+ { datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl },
+ [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] =
+ { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl },
+ [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = { datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl },
+ [GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_point_varying_size_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] =
+ { datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_frag_glsl },
+ [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] =
+ { datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_aa_frag_glsl },
+ [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] =
+ { datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl },
+
+ [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = { datatoc_gpu_shader_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE] =
+ { datatoc_gpu_shader_instance_variying_size_variying_id_vert_glsl,
+ datatoc_gpu_shader_flat_id_frag_glsl },
+ [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] =
+ { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE] =
+ { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = { datatoc_gpu_shader_instance_edges_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_gpu_shader_instance_edges_variying_color_geom_glsl},
+
+ [GPU_SHADER_2D_WIDGET_BASE] = { datatoc_gpu_shader_2D_widget_base_vert_glsl,
+ datatoc_gpu_shader_2D_widget_base_frag_glsl},
+ [GPU_SHADER_2D_WIDGET_BASE_INST] = { datatoc_gpu_shader_2D_widget_base_vert_glsl,
+ datatoc_gpu_shader_2D_widget_base_frag_glsl},
+ [GPU_SHADER_2D_WIDGET_SHADOW] = { datatoc_gpu_shader_2D_widget_shadow_vert_glsl,
+ datatoc_gpu_shader_2D_widget_shadow_frag_glsl },
+ [GPU_SHADER_2D_NODELINK] = { datatoc_gpu_shader_2D_nodelink_vert_glsl,
+ datatoc_gpu_shader_2D_nodelink_frag_glsl },
+ [GPU_SHADER_2D_NODELINK_INST] = { datatoc_gpu_shader_2D_nodelink_vert_glsl,
+ datatoc_gpu_shader_2D_nodelink_frag_glsl },
+ };
+
+ if (builtin_shaders[shader] == NULL) {
+ /* just a few special cases */
+ const char *defines = NULL;
+ switch (shader) {
+ case GPU_SHADER_2D_IMAGE_MULTISAMPLE_2:
+ defines = "#define SAMPLES 2\n";
break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
- strcat(defines, "#define FIRST_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ case GPU_SHADER_2D_IMAGE_MULTISAMPLE_4:
+ defines = "#define SAMPLES 4\n";
break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
- strcat(defines, "#define SECOND_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ case GPU_SHADER_2D_IMAGE_MULTISAMPLE_8:
+ defines = "#define SAMPLES 8\n";
break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
- strcat(defines, "#define THIRD_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ case GPU_SHADER_2D_IMAGE_MULTISAMPLE_16:
+ defines = "#define SAMPLES 16\n";
break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
- strcat(defines, "#define FOURTH_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ case GPU_SHADER_2D_WIDGET_BASE_INST:
+ case GPU_SHADER_2D_NODELINK_INST:
+ defines = "#define USE_INSTANCE\n";
break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
- strcat(defines, "#define FIFTH_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ case GPU_SHADER_SMOKE_COBA:
+ defines = "#define USE_COBA\n";
break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
- strcat(defines, "#define FIRST_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ case GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE:
+ case GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE:
+ defines = "#define UNIFORM_SCALE\n";
break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
- strcat(defines, "#define SECOND_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
- defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
+ case GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS:
+ defines = "#define AXIS_NAME\n";
break;
-
- case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
- strcat(defines, "#define THIRD_PASS\n");
- shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ case GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR:
+ defines = "#define USE_INSTANCE_COLOR\n";
break;
-
- 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);
+ case GPU_SHADER_3D_FLAT_COLOR_U32:
+ case GPU_SHADER_3D_UNIFORM_COLOR_U32:
+ defines = "#define USE_COLOR_U32\n";
+ break;
+ case GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR:
+ defines = "#define USE_FLAT_NORMAL\n";
+ break;
+ default:
break;
}
- GG.shaders.fx_shaders[offset] = shader;
- GPU_fx_shader_init_interface(shader, effect);
- }
-
- return GG.shaders.fx_shaders[offset];
-}
-
-
-void GPU_shader_free_builtin_shaders(void)
-{
- int i;
+ const GPUShaderStages *stages = builtin_shader_stages + shader;
- if (GG.shaders.vsm_store) {
- GPU_shader_free(GG.shaders.vsm_store);
- GG.shaders.vsm_store = NULL;
- }
+ if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP && !GLEW_VERSION_3_2) {
+ /* TODO: remove after switch to core profile (maybe) */
+ static const GPUShaderStages legacy_fancy_edges =
+ { datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl,
+ datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl };
+ stages = &legacy_fancy_edges;
+ }
- if (GG.shaders.sep_gaussian_blur) {
- GPU_shader_free(GG.shaders.sep_gaussian_blur);
- GG.shaders.sep_gaussian_blur = NULL;
- }
+ if (shader == GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR && !GLEW_VERSION_3_2) {
+ /* Dashed need geometry shader, which are not supported by legacy OpenGL, fallback to solid lines. */
+ /* TODO: remove after switch to core profile (maybe) */
+ static const GPUShaderStages legacy_dashed_lines = { datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl,
+ datatoc_gpu_shader_2D_line_dashed_frag_glsl };
+ stages = &legacy_dashed_lines;
+ }
- if (GG.shaders.smoke) {
- GPU_shader_free(GG.shaders.smoke);
- GG.shaders.smoke = NULL;
+ /* common case */
+ builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom, NULL, defines);
}
- if (GG.shaders.smoke_fire) {
- GPU_shader_free(GG.shaders.smoke_fire);
- GG.shaders.smoke_fire = NULL;
- }
+ return builtin_shaders[shader];
+}
- if (GG.shaders.smoke_coba) {
- GPU_shader_free(GG.shaders.smoke_coba);
- GG.shaders.smoke_coba = NULL;
- }
+#define MAX_DEFINES 100
- for (i = 0; i < 2 * MAX_FX_SHADERS; ++i) {
- if (GG.shaders.fx_shaders[i]) {
- GPU_shader_free(GG.shaders.fx_shaders[i]);
- GG.shaders.fx_shaders[i] = NULL;
+void GPU_shader_free_builtin_shaders(void)
+{
+ for (int i = 0; i < GPU_NUM_BUILTIN_SHADERS; ++i) {
+ if (builtin_shaders[i]) {
+ GPU_shader_free(builtin_shaders[i]);
+ builtin_shaders[i] = NULL;
}
}
}
-
-
diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h
new file mode 100644
index 00000000000..d8ec6b5d6d1
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_shader_private.h
@@ -0,0 +1,44 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_shader_private.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_SHADER_PRIVATE_H__
+#define __GPU_SHADER_PRIVATE_H__
+
+#include "GPU_glew.h"
+#include "gawain/gwn_shader_interface.h"
+
+struct GPUShader {
+ GLuint program; /* handle for full program (links shader stages below) */
+
+ GLuint vertex; /* handle for vertex shader */
+ GLuint geometry; /* handle for geometry shader */
+ GLuint fragment; /* handle for fragment shader */
+
+ Gwn_ShaderInterface *interface; /* cached uniform & attrib interface for shader */
+
+ int feedback_transform_type;
+};
+
+#endif /* __GPU_SHADER_PRIVATE_H__ */
+
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index f50465189b2..38b38736660 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -35,6 +35,7 @@
#include "BKE_global.h"
+#include "GPU_batch.h"
#include "GPU_debug.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
@@ -48,10 +49,25 @@ static struct GPUTextureGlobal {
GPUTexture *invalid_tex_3D;
} GG = {NULL, NULL, NULL};
-/* GPUTexture */
+/* Maximum number of FBOs a texture can be attached to. */
+#define GPU_TEX_MAX_FBO_ATTACHED 8
+
+typedef enum GPUTextureFormatFlag {
+ GPU_FORMAT_DEPTH = (1 << 0),
+ GPU_FORMAT_STENCIL = (1 << 1),
+ GPU_FORMAT_INTEGER = (1 << 2),
+ GPU_FORMAT_FLOAT = (1 << 3),
+
+ GPU_FORMAT_1D = (1 << 10),
+ GPU_FORMAT_2D = (1 << 11),
+ GPU_FORMAT_3D = (1 << 12),
+ GPU_FORMAT_CUBE = (1 << 13),
+ GPU_FORMAT_ARRAY = (1 << 14),
+} GPUTextureFormatFlag;
+/* GPUTexture */
struct GPUTexture {
- int w, h; /* width/height */
+ int w, h, d; /* width/height/depth */
int number; /* number for multitexture binding */
int refcount; /* reference count */
GLenum target; /* GL_TEXTURE_* */
@@ -60,45 +76,318 @@ struct GPUTexture {
GLuint bindcode; /* opengl identifier for texture */
int fromblender; /* we got the texture from Blender */
- GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
- int fb_attachment; /* slot the texture is attached to */
- int depth; /* is a depth texture? if 3D how deep? */
+ GPUTextureFormat format;
+ GPUTextureFormatFlag format_flag;
+
+ unsigned int bytesize; /* number of byte for one pixel */
+ int components; /* number of color/alpha channels */
+ int samples; /* number of samples for multisamples textures. 0 if not multisample target */
+
+ int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED];
+ GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED];
};
-static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
+/* ------ Memory Management ------- */
+/* Records every texture allocation / free
+ * to estimate the Texture Pool Memory consumption */
+static unsigned int memory_usage;
+
+static unsigned int gpu_texture_memory_footprint_compute(GPUTexture *tex)
{
- unsigned char *pixels, *p;
- const float *fp = fpixels;
- const int len = 4 * length;
+ int samp = max_ii(tex->samples, 1);
+ switch (tex->target) {
+ case GL_TEXTURE_1D:
+ return tex->bytesize * tex->w * samp;
+ case GL_TEXTURE_1D_ARRAY:
+ case GL_TEXTURE_2D:
+ return tex->bytesize * tex->w * tex->h * samp;
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_3D:
+ return tex->bytesize * tex->w * tex->h * tex->d * samp;
+ case GL_TEXTURE_CUBE_MAP:
+ return tex->bytesize * 6 * tex->w * tex->h * samp;
+ case GL_TEXTURE_CUBE_MAP_ARRAY:
+ return tex->bytesize * 6 * tex->w * tex->h * tex->d * samp;
+ default:
+ return 0;
+ }
+}
- p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
+static void gpu_texture_memory_footprint_add(GPUTexture *tex)
+{
+ memory_usage += gpu_texture_memory_footprint_compute(tex);
+}
- for (int a = 0; a < len; a++, p++, fp++)
- *p = unit_float_to_uchar_clamp((*fp));
+static void gpu_texture_memory_footprint_remove(GPUTexture *tex)
+{
+ memory_usage -= gpu_texture_memory_footprint_compute(tex);
+}
- return pixels;
+unsigned int GPU_texture_memory_usage_get(void)
+{
+ return memory_usage;
}
-static void gpu_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
+/* -------------------------------- */
+
+static GLenum gpu_texture_get_format(
+ int components, GPUTextureFormat data_type,
+ GLenum *format, GLenum *data_format, GPUTextureFormatFlag *format_flag, unsigned int *bytesize)
{
- void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
+ if (ELEM(data_type, GPU_DEPTH_COMPONENT24,
+ GPU_DEPTH_COMPONENT16,
+ GPU_DEPTH_COMPONENT32F))
+ {
+ *format_flag |= GPU_FORMAT_DEPTH;
+ *data_format = GL_FLOAT;
+ *format = GL_DEPTH_COMPONENT;
+ }
+ else if (data_type == GPU_DEPTH24_STENCIL8) {
+ *format_flag |= GPU_FORMAT_DEPTH | GPU_FORMAT_STENCIL;
+ *data_format = GL_UNSIGNED_INT_24_8;
+ *format = GL_DEPTH_STENCIL;
+ }
+ else {
+ /* Integer formats */
+ if (ELEM(data_type, GPU_RG16I, GPU_R16I, GPU_RG16UI, GPU_R16UI, GPU_R32UI)) {
+ if (ELEM(data_type, GPU_R16UI, GPU_RG16UI, GPU_R32UI)) {
+ *data_format = GL_UNSIGNED_INT;
+ }
+ else {
+ *data_format = GL_INT;
+ }
- if (target == GL_TEXTURE_1D)
- glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
- else
- glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
-
- MEM_freeN(pixels);
+ *format_flag |= GPU_FORMAT_INTEGER;
+
+ switch (components) {
+ case 1: *format = GL_RED_INTEGER; break;
+ case 2: *format = GL_RG_INTEGER; break;
+ case 3: *format = GL_RGB_INTEGER; break;
+ case 4: *format = GL_RGBA_INTEGER; break;
+ default: break;
+ }
+ }
+ else {
+ *data_format = GL_FLOAT;
+ *format_flag |= GPU_FORMAT_FLOAT;
+
+ switch (components) {
+ case 1: *format = GL_RED; break;
+ case 2: *format = GL_RG; break;
+ case 3: *format = GL_RGB; break;
+ case 4: *format = GL_RGBA; break;
+ default: break;
+ }
+ }
+ }
+
+ switch (data_type) {
+ case GPU_RGBA32F:
+ *bytesize = 32;
+ break;
+ case GPU_RG32F:
+ case GPU_RGBA16F:
+ case GPU_RGBA16:
+ *bytesize = 16;
+ break;
+ case GPU_RGB16F:
+ *bytesize = 12;
+ break;
+ case GPU_RG16F:
+ case GPU_RG16I:
+ case GPU_RG16UI:
+ case GPU_RG16:
+ case GPU_DEPTH24_STENCIL8:
+ case GPU_DEPTH_COMPONENT32F:
+ case GPU_RGBA8:
+ case GPU_R11F_G11F_B10F:
+ case GPU_R32F:
+ case GPU_R32UI:
+ *bytesize = 4;
+ break;
+ case GPU_DEPTH_COMPONENT24:
+ *bytesize = 3;
+ break;
+ case GPU_DEPTH_COMPONENT16:
+ case GPU_R16F:
+ case GPU_R16I:
+ case GPU_RG8:
+ *bytesize = 2;
+ break;
+ case GPU_R8:
+ *bytesize = 1;
+ break;
+ default:
+ *bytesize = 0;
+ break;
+ }
+
+ /* You can add any of the available type to this list
+ * For available types see GPU_texture.h */
+ switch (data_type) {
+ /* Formats texture & renderbuffer */
+ case GPU_RGBA32F: return GL_RGBA32F;
+ case GPU_RGBA16F: return GL_RGBA16F;
+ case GPU_RGBA16: return GL_RGBA16;
+ case GPU_RG32F: return GL_RG32F;
+ case GPU_RGB16F: return GL_RGB16F;
+ case GPU_RG16F: return GL_RG16F;
+ case GPU_RG16I: return GL_RG16I;
+ case GPU_RG16: return GL_RG16;
+ case GPU_RGBA8: return GL_RGBA8;
+ case GPU_R32F: return GL_R32F;
+ case GPU_R32UI: return GL_R32UI;
+ case GPU_R16F: return GL_R16F;
+ case GPU_R16I: return GL_R16I;
+ case GPU_R16UI: return GL_R16UI;
+ case GPU_RG8: return GL_RG8;
+ case GPU_RG16UI: return GL_RG16UI;
+ case GPU_R8: return GL_R8;
+ /* Special formats texture & renderbuffer */
+ case GPU_R11F_G11F_B10F: return GL_R11F_G11F_B10F;
+ case GPU_DEPTH24_STENCIL8: return GL_DEPTH24_STENCIL8;
+ /* Texture only format */
+ /* ** Add Format here **/
+ /* Special formats texture only */
+ /* ** Add Format here **/
+ /* Depth Formats */
+ case GPU_DEPTH_COMPONENT32F: return GL_DEPTH_COMPONENT32F;
+ case GPU_DEPTH_COMPONENT24: return GL_DEPTH_COMPONENT24;
+ case GPU_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT16;
+ default:
+ fprintf(stderr, "Texture format incorrect or unsupported\n");
+ return 0;
+ }
}
-static GPUTexture *GPU_texture_create_nD(
- int w, int h, int n, const float *fpixels, int depth,
- GPUHDRType hdr_type, int components, int samples,
- char err_out[256])
+static int gpu_texture_get_component_count(GPUTextureFormat format)
+{
+ switch (format) {
+ case GPU_RGBA8:
+ case GPU_RGBA16F:
+ case GPU_RGBA16:
+ case GPU_RGBA32F:
+ return 4;
+ case GPU_RGB16F:
+ case GPU_R11F_G11F_B10F:
+ return 3;
+ case GPU_RG8:
+ case GPU_RG16:
+ case GPU_RG16F:
+ case GPU_RG16I:
+ case GPU_RG16UI:
+ case GPU_RG32F:
+ return 2;
+ default:
+ return 1;
+ }
+}
+
+static float *GPU_texture_3D_rescale(GPUTexture *tex, int w, int h, int d, int channels, const float *fpixels)
{
- GLenum type, format, internalformat;
- void *pixels = NULL;
+ const unsigned int xf = w / tex->w, yf = h / tex->h, zf = d / tex->d;
+ float *nfpixels = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->d, "GPUTexture Rescaled 3Dtex");
+
+ if (nfpixels) {
+ GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
+
+ for (unsigned k = 0; k < tex->d; k++) {
+ for (unsigned j = 0; j < tex->h; j++) {
+ for (unsigned i = 0; i < tex->w; i++) {
+ /* obviously doing nearest filtering here,
+ * it's going to be slow in any case, let's not make it worse */
+ float xb = i * xf;
+ float yb = j * yf;
+ float zb = k * zf;
+ unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
+ unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
+
+ if (channels == 4) {
+ nfpixels[offset * 4] = fpixels[offset_orig * 4];
+ nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
+ nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
+ nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
+ }
+ else
+ nfpixels[offset] = fpixels[offset_orig];
+ }
+ }
+ }
+ }
+
+ return nfpixels;
+}
+
+/* This tries to allocate video memory for a given texture
+ * If alloc fails, lower the resolution until it fits. */
+static bool gpu_texture_try_alloc(
+ GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum format, GLenum data_format,
+ int channels, bool try_rescale, const float *fpixels, float **rescaled_fpixels)
+{
+ int r_width;
+
+ switch (proxy) {
+ case GL_PROXY_TEXTURE_1D:
+ glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL);
+ break;
+ case GL_PROXY_TEXTURE_1D_ARRAY:
+ case GL_PROXY_TEXTURE_2D:
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL);
+ break;
+ case GL_PROXY_TEXTURE_2D_ARRAY:
+ case GL_PROXY_TEXTURE_3D:
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, NULL);
+ break;
+ }
+
+ glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &r_width);
+
+ if (r_width == 0 && try_rescale) {
+ const int w = tex->w, h = tex->h, d = tex->d;
+
+ /* Find largest texture possible */
+ while (r_width == 0) {
+ tex->w /= 2;
+ tex->h /= 2;
+ tex->d /= 2;
+
+ /* really unlikely to happen but keep this just in case */
+ if (tex->w == 0) break;
+ if (tex->h == 0 && proxy != GL_PROXY_TEXTURE_1D) break;
+ if (tex->d == 0 && proxy == GL_PROXY_TEXTURE_3D) break;
+
+ if (proxy == GL_PROXY_TEXTURE_1D)
+ glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_2D)
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_3D)
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, NULL);
+
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+ }
+ /* Rescale */
+ if (r_width > 0) {
+ switch (proxy) {
+ case GL_PROXY_TEXTURE_1D:
+ case GL_PROXY_TEXTURE_2D:
+ /* Do nothing for now */
+ return false;
+ case GL_PROXY_TEXTURE_3D:
+ *rescaled_fpixels = GPU_texture_3D_rescale(tex, w, h, d, channels, fpixels);
+ return (bool)*rescaled_fpixels;
+ }
+ }
+ }
+
+ return (r_width > 0);
+}
+
+static GPUTexture *GPU_texture_create_nD(
+ int w, int h, int d, int n, const float *fpixels,
+ GPUTextureFormat data_type, int samples,
+ const bool can_rescale, char err_out[256])
+{
if (samples) {
CLAMP_MAX(samples, GPU_max_color_texture_samples());
}
@@ -106,280 +395,287 @@ static GPUTexture *GPU_texture_create_nD(
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->w = w;
tex->h = h;
+ tex->d = d;
+ tex->samples = samples;
tex->number = -1;
tex->refcount = 1;
- tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
- tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
- tex->depth = depth;
- tex->fb_attachment = -1;
+ tex->format = data_type;
+ tex->components = gpu_texture_get_component_count(data_type);
+ tex->format_flag = 0;
+
+ if (n == 2) {
+ if (d == 0)
+ tex->target_base = tex->target = GL_TEXTURE_2D;
+ else
+ tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY;
+ }
+ else if (n == 1) {
+ if (h == 0)
+ tex->target_base = tex->target = GL_TEXTURE_1D;
+ else
+ tex->target_base = tex->target = GL_TEXTURE_1D_ARRAY;
+ }
+ else if (n == 3) {
+ tex->target_base = tex->target = GL_TEXTURE_3D;
+ }
+ else {
+ /* should never happen */
+ MEM_freeN(tex);
+ return NULL;
+ }
+
+ if (samples && n == 2 && d == 0)
+ tex->target = GL_TEXTURE_2D_MULTISAMPLE;
+
+ GLenum format, internalformat, data_format;
+ internalformat = gpu_texture_get_format(tex->components, data_type, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
+ gpu_texture_memory_footprint_add(tex);
+
+ /* Generate Texture object */
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());
- }
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUTexture: texture create failed");
+ else
+ fprintf(stderr, "GPUTexture: texture create failed");
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);
- if (depth) {
- type = GL_UNSIGNED_BYTE;
- format = GL_DEPTH_COMPONENT;
- internalformat = GL_DEPTH_COMPONENT;
- }
- else {
- type = GL_FLOAT;
-
- if (components == 4) {
- 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;
- }
- }
- else if (components == 2) {
- /* these formats rely on ARB_texture_rg or OpenGL 3.0 */
- format = GL_RG;
- switch (hdr_type) {
- case GPU_HDR_NONE:
- internalformat = GL_RG8;
- break;
- case GPU_HDR_HALF_FLOAT:
- internalformat = GL_RG16F;
- break;
- case GPU_HDR_FULL_FLOAT:
- internalformat = GL_RG32F;
- break;
- default:
- break;
- }
- }
+ /* Check if texture fit in VRAM */
+ GLenum proxy = GL_PROXY_TEXTURE_2D;
- if (fpixels && hdr_type == GPU_HDR_NONE) {
- type = GL_UNSIGNED_BYTE;
- pixels = GPU_texture_convert_pixels(w * h, fpixels);
- }
+ if (n == 2) {
+ if (d > 0)
+ proxy = GL_PROXY_TEXTURE_2D_ARRAY;
+ }
+ else if (n == 1) {
+ if (h == 0)
+ proxy = GL_PROXY_TEXTURE_1D;
+ else
+ proxy = GL_PROXY_TEXTURE_1D_ARRAY;
+ }
+ else if (n == 3) {
+ proxy = GL_PROXY_TEXTURE_3D;
}
- if (tex->target == GL_TEXTURE_1D) {
- glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
+ float *rescaled_fpixels = NULL;
+ bool valid = gpu_texture_try_alloc(tex, proxy, internalformat, format, data_format, tex->components, can_rescale,
+ fpixels, &rescaled_fpixels);
+ if (!valid) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUTexture: texture alloc failed");
+ else
+ fprintf(stderr, "GPUTexture: texture alloc failed. Not enough Video Memory.");
+ GPU_texture_free(tex);
+ return NULL;
+ }
- if (fpixels) {
- glTexSubImage1D(tex->target, 0, 0, w, format, type,
- pixels ? pixels : fpixels);
+ /* Upload Texture */
+ const float *pix = (rescaled_fpixels) ? rescaled_fpixels : fpixels;
- if (tex->w > w) {
- gpu_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1);
- }
- }
- }
- else {
+ if (tex->target == GL_TEXTURE_2D ||
+ tex->target == GL_TEXTURE_2D_MULTISAMPLE ||
+ tex->target == GL_TEXTURE_1D_ARRAY)
+ {
if (samples) {
glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
+ if (pix)
+ glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, data_format, pix);
}
else {
- glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
- format, type, NULL);
- }
-
- if (fpixels) {
- glTexSubImage2D(tex->target, 0, 0, 0, w, h,
- format, type, pixels ? pixels : fpixels);
-
- if (tex->w > w) {
- gpu_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h);
- }
- if (tex->h > h) {
- gpu_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h);
- }
+ glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, data_format, pix);
}
}
+ else if (tex->target == GL_TEXTURE_1D) {
+ glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, data_format, pix);
+ }
+ else {
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, pix);
+ }
- if (pixels)
- MEM_freeN(pixels);
+ if (rescaled_fpixels)
+ MEM_freeN(rescaled_fpixels);
- if (depth) {
+ /* Texture Parameters */
+ if (GPU_texture_stencil(tex) || /* Does not support filtering */
+ GPU_texture_integer(tex) || /* Does not support filtering */
+ GPU_texture_depth(tex))
+ {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
else {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
- if (tex->target_base != GL_TEXTURE_1D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ if (GPU_texture_depth(tex)) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ }
+
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ if (n > 1) {
glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
- else
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ if (n > 2) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ }
+
+ glBindTexture(tex->target, 0);
return tex;
}
-
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
+static GPUTexture *GPU_texture_cube_create(
+ int w, int d,
+ const float *fpixels_px, const float *fpixels_py, const float *fpixels_pz,
+ const float *fpixels_nx, const float *fpixels_ny, const float *fpixels_nz,
+ GPUTextureFormat data_type,
+ char err_out[256])
{
- GLenum type, format, internalformat;
- void *pixels = NULL;
+ GLenum format, internalformat, data_format;
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->w = w;
- tex->h = h;
- tex->depth = depth;
+ tex->h = w;
+ tex->d = d;
+ tex->samples = 0;
tex->number = -1;
tex->refcount = 1;
- tex->target = GL_TEXTURE_3D;
- tex->target_base = GL_TEXTURE_3D;
+ tex->format = data_type;
+ tex->components = gpu_texture_get_component_count(data_type);
+ tex->format_flag = GPU_FORMAT_CUBE;
+ if (d == 0) {
+ tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
+ }
+ else {
+ BLI_assert(false && "Cubemap array Not implemented yet");
+ // tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY;
+ }
+
+ internalformat = gpu_texture_get_format(tex->components, data_type, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
+
+ gpu_texture_memory_footprint_add(tex);
+
+ /* Generate Texture object */
glGenTextures(1, &tex->bindcode);
if (!tex->bindcode) {
- fprintf(stderr, "GPUTexture: texture create failed: %d\n",
- (int)glGetError());
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUTexture: texture create failed");
+ else
+ fprintf(stderr, "GPUTexture: texture create failed");
GPU_texture_free(tex);
return NULL;
}
- tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
- GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
-
- type = GL_FLOAT;
- if (channels == 4) {
- format = GL_RGBA;
- internalformat = GL_RGBA8;
+ /* Upload Texture */
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_px);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_py);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_pz);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_nx);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_ny);
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, tex->w, tex->h, 0, format, data_format, fpixels_nz);
+
+ /* Texture Parameters */
+ if (GPU_texture_stencil(tex) || /* Does not support filtering */
+ GPU_texture_integer(tex) || /* Does not support filtering */
+ GPU_texture_depth(tex))
+ {
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
else {
- format = GL_RED;
- internalformat = GL_INTENSITY8;
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
- /* 3D textures are quite heavy, test if it's possible to create them first */
- glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
-
- bool rescale = false;
- int r_width;
-
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
-
- while (r_width == 0) {
- rescale = true;
- tex->w /= 2;
- tex->h /= 2;
- tex->depth /= 2;
- glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+ if (GPU_texture_depth(tex)) {
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
}
- /* really unlikely to happen but keep this just in case */
- tex->w = max_ii(tex->w, 1);
- tex->h = max_ii(tex->h, 1);
- tex->depth = max_ii(tex->depth, 1);
-
-#if 0
- if (fpixels)
- pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
-#endif
+ 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);
- GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
-
- /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
- * for gooseberry */
- if (rescale && fpixels) {
- /* FIXME: should these be floating point? */
- const unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
- float *tex3d = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->depth, "tex3d");
-
- GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
-
- for (unsigned k = 0; k < tex->depth; k++) {
- for (unsigned j = 0; j < tex->h; j++) {
- for (unsigned i = 0; i < tex->w; i++) {
- /* obviously doing nearest filtering here,
- * it's going to be slow in any case, let's not make it worse */
- float xb = i * xf;
- float yb = j * yf;
- float zb = k * zf;
- unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
- unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
+ glBindTexture(tex->target, 0);
- if (channels == 4) {
- tex3d[offset * 4] = fpixels[offset_orig * 4];
- tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
- tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
- tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
- }
- else
- tex3d[offset] = fpixels[offset_orig];
- }
- }
- }
-
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
+ return tex;
+}
- MEM_freeN(tex3d);
- }
- else {
- if (fpixels) {
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
- GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
- }
+/* Special buffer textures. data_type must be compatible with the buffer content. */
+static GPUTexture *GPU_texture_create_buffer(GPUTextureFormat data_type, const GLuint buffer)
+{
+ GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
+ tex->number = -1;
+ tex->refcount = 1;
+ tex->format = data_type;
+ tex->components = gpu_texture_get_component_count(data_type);
+ tex->format_flag = 0;
+ tex->target_base = tex->target = GL_TEXTURE_BUFFER;
+
+ GLenum format, internalformat, data_format;
+ internalformat = gpu_texture_get_format(tex->components, data_type, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
+
+ if (!(ELEM(data_type, GPU_R8, GPU_R16) ||
+ ELEM(data_type, GPU_R16F, GPU_R32F) ||
+ ELEM(data_type, GPU_R8I, GPU_R16I, GPU_R32I) ||
+ ELEM(data_type, GPU_R8UI, GPU_R16UI, GPU_R32UI) ||
+ ELEM(data_type, GPU_RG8, GPU_RG16) ||
+ ELEM(data_type, GPU_RG16F, GPU_RG32F) ||
+ ELEM(data_type, GPU_RG8I, GPU_RG16I, GPU_RG32I) ||
+ ELEM(data_type, GPU_RG8UI, GPU_RG16UI, GPU_RG32UI) ||
+ //ELEM(data_type, GPU_RGB32F, GPU_RGB32I, GPU_RGB32UI) || /* Not available until gl 4.0 */
+ ELEM(data_type, GPU_RGBA8, GPU_RGBA16) ||
+ ELEM(data_type, GPU_RGBA16F, GPU_RGBA32F) ||
+ ELEM(data_type, GPU_RGBA8I, GPU_RGBA16I, GPU_RGBA32I) ||
+ ELEM(data_type, GPU_RGBA8UI, GPU_RGBA16UI, GPU_RGBA32UI)))
+ {
+ fprintf(stderr, "GPUTexture: invalid format for texture buffer");
+ GPU_texture_free(tex);
+ return NULL;
}
+ /* Generate Texture object */
+ glGenTextures(1, &tex->bindcode);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- if (pixels)
- MEM_freeN(pixels);
+ if (!tex->bindcode) {
+ fprintf(stderr, "GPUTexture: texture create failed");
+ GPU_texture_free(tex);
+ BLI_assert(0 && "glGenTextures failled: Are you sure a valid OGL context is active on this thread?");
+ return NULL;
+ }
- GPU_texture_unbind(tex);
+ glBindTexture(tex->target, tex->bindcode);
+ glTexBuffer(tex->target, internalformat, buffer);
+ glBindTexture(tex->target, 0);
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, double UNUSED(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);
- GPU_update_image_time(ima, time);
+ GLint bindcode = GPU_verify_image(ima, iuser, textarget, 0, mipmap, is_data);
/* see GPUInput::textarget: it can take two values - GL_TEXTURE_2D and GL_TEXTURE_CUBE_MAP
* these values are correct for glDisable, so textarget can be safely used in
* GPU_texture_bind/GPU_texture_unbind through tex->target_base */
+ /* (is any of this obsolete now that we don't glEnable/Disable textures?) */
if (textarget == GL_TEXTURE_2D)
gputt = TEXTARGET_TEXTURE_2D;
else
@@ -398,14 +694,17 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
tex->target = textarget;
tex->target_base = textarget;
tex->fromblender = 1;
+ tex->format = -1;
+ tex->components = -1;
+ tex->samples = 0;
ima->gputexture[gputt] = tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+ GPU_print_error_debug("Blender Texture Not Loaded");
}
else {
- GLint w, h, border;
+ GLint w, h;
GLenum gettarget;
@@ -417,10 +716,8 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
glBindTexture(textarget, tex->bindcode);
glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h);
- glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_BORDER, &border);
-
- tex->w = w - border;
- tex->h = h - border;
+ tex->w = w;
+ tex->h = h;
}
glBindTexture(textarget, 0);
@@ -452,11 +749,13 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
tex->refcount = 1;
tex->target = GL_TEXTURE_2D;
tex->target_base = GL_TEXTURE_2D;
+ tex->format = -1;
+ tex->components = -1;
prv->gputexture[0] = tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
+ GPU_print_error_debug("Blender Texture Not Loaded");
}
else {
GLint w, h;
@@ -475,114 +774,165 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
}
-GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_1D(
+ int w, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, 0, 0, 1, pixels, data_type, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
+GPUTexture *GPU_texture_create_2D(
+ int w, int h, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, h, 0, 2, pixels, data_type, 0, false, err_out);
}
+
GPUTexture *GPU_texture_create_2D_multisample(
- int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
+ int w, int h, GPUTextureFormat data_type, const float *pixels, int samples, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, h, 0, 2, pixels, data_type, samples, false, err_out);
}
-GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
+GPUTexture *GPU_texture_create_2D_array(
+ int w, int h, int d, GPUTextureFormat data_type, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, h, d, 2, pixels, data_type, 0, false, err_out);
}
-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);
-
- if (tex)
- GPU_texture_unbind(tex);
- return tex;
+GPUTexture *GPU_texture_create_3D(
+ int w, int h, int d, GPUTextureFormat data_type, const float *pixels, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, d, 3, pixels, data_type, 0, true, err_out);
}
-/**
- * A shadow map for VSM needs two components (depth and depth^2)
- */
-GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
+GPUTexture *GPU_texture_create_cube(
+ int w, GPUTextureFormat data_type, const float *fpixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- GPU_texture_unbind(tex);
+ const float *fpixels_px, *fpixels_py, *fpixels_pz, *fpixels_nx, *fpixels_ny, *fpixels_nz;
+ const int channels = gpu_texture_get_component_count(data_type);
+
+ if (fpixels) {
+ fpixels_px = fpixels + 0 * w * w * channels;
+ fpixels_nx = fpixels + 1 * w * w * channels;
+ fpixels_py = fpixels + 2 * w * w * channels;
+ fpixels_ny = fpixels + 3 * w * w * channels;
+ fpixels_pz = fpixels + 4 * w * w * channels;
+ fpixels_nz = fpixels + 5 * w * w * channels;
+ }
+ else {
+ fpixels_px = fpixels_py = fpixels_pz = fpixels_nx = fpixels_ny = fpixels_nz = NULL;
}
- return tex;
+ return GPU_texture_cube_create(w, 0, fpixels_px, fpixels_py, fpixels_pz, fpixels_nx, fpixels_ny, fpixels_nz,
+ data_type, err_out);
}
-GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
+GPUTexture *GPU_texture_create_from_vertbuf(Gwn_VertBuf *vert)
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
+ Gwn_VertFormat *format = &vert->format;
+ Gwn_VertAttr *attr = &format->attribs[0];
- if (tex) {
- /* Now we tweak some of the settings */
- if (repeat) {
- 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);
+ /* Detect incompatible cases (not supported by texture buffers) */
+ BLI_assert(format->attrib_ct == 1 && vert->vbo_id != 0);
+ BLI_assert(attr->comp_ct != 3); /* Not until OGL 4.0 */
+ BLI_assert(attr->comp_type != GWN_COMP_I10);
+ BLI_assert(attr->fetch_mode != GWN_FETCH_INT_TO_FLOAT);
- GPU_texture_unbind(tex);
+ unsigned int byte_per_comp = attr->sz / attr->comp_ct;
+ bool is_uint = ELEM(attr->comp_type, GWN_COMP_U8, GWN_COMP_U16, GWN_COMP_U32);
+
+ /* Cannot fetch signed int or 32bit ints as normalized float. */
+ if (attr->fetch_mode == GWN_FETCH_INT_TO_FLOAT_UNIT) {
+ BLI_assert(is_uint || byte_per_comp <= 2);
}
- return tex;
+ GPUTextureFormat data_type;
+ switch (attr->fetch_mode) {
+ case GWN_FETCH_FLOAT:
+ switch (attr->comp_ct) {
+ case 1: data_type = GPU_R32F; break;
+ case 2: data_type = GPU_RG32F; break;
+ // case 3: data_type = GPU_RGB32F; break; /* Not supported */
+ default: data_type = GPU_RGBA32F; break;
+ }
+ break;
+ case GWN_FETCH_INT:
+ switch (attr->comp_ct) {
+ case 1:
+ switch (byte_per_comp) {
+ case 1: data_type = (is_uint) ? GPU_R8UI : GPU_R8I; break;
+ case 2: data_type = (is_uint) ? GPU_R16UI : GPU_R16I; break;
+ default: data_type = (is_uint) ? GPU_R32UI : GPU_R32I; break;
+ }
+ break;
+ case 2:
+ switch (byte_per_comp) {
+ case 1: data_type = (is_uint) ? GPU_RG8UI : GPU_RG8I; break;
+ case 2: data_type = (is_uint) ? GPU_RG16UI : GPU_RG16I; break;
+ default: data_type = (is_uint) ? GPU_RG32UI : GPU_RG32I; break;
+ }
+ break;
+ default:
+ switch (byte_per_comp) {
+ case 1: data_type = (is_uint) ? GPU_RGBA8UI : GPU_RGBA8I; break;
+ case 2: data_type = (is_uint) ? GPU_RGBA16UI : GPU_RGBA16I; break;
+ default: data_type = (is_uint) ? GPU_RGBA32UI : GPU_RGBA32I; break;
+ }
+ break;
+ }
+ break;
+ case GWN_FETCH_INT_TO_FLOAT_UNIT:
+ switch (attr->comp_ct) {
+ case 1: data_type = (byte_per_comp == 1) ? GPU_R8 : GPU_R16; break;
+ case 2: data_type = (byte_per_comp == 1) ? GPU_RG8 : GPU_RG16; break;
+ default: data_type = (byte_per_comp == 1) ? GPU_RGBA8 : GPU_RGBA16; break;
+ }
+ break;
+ default:
+ BLI_assert(0);
+ return NULL;
+ }
+
+ return GPU_texture_create_buffer(data_type, vert->vbo_id);
}
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
+void GPU_texture_update(GPUTexture *tex, const float *pixels)
{
- GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
+ BLI_assert(tex->format > -1);
+ BLI_assert(tex->components > -1);
- if (tex) {
- /* Now we tweak some of the settings */
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ GLenum format, data_format;
+ gpu_texture_get_format(tex->components, tex->format, &format, &data_format,
+ &tex->format_flag, &tex->bytesize);
- GPU_texture_unbind(tex);
+ glBindTexture(tex->target, tex->bindcode);
+
+ switch (tex->target) {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ case GL_TEXTURE_1D_ARRAY:
+ glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, data_format, pixels);
+ break;
+ case GL_TEXTURE_1D:
+ glTexSubImage1D(tex->target, 0, 0, tex->w, format, data_format, pixels);
+ break;
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->d, format, data_format, pixels);
+ break;
+ default:
+ BLI_assert(!"tex->target mode not supported");
}
- return tex;
+ glBindTexture(tex->target, 0);
}
void GPU_invalid_tex_init(void)
{
+ memory_usage = 0;
const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
- GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
- GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
- GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
+ GG.invalid_tex_1D = GPU_texture_create_1D(1, GPU_RGBA8, color, NULL);
+ GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, GPU_RGBA8, color, NULL);
+ GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, GPU_RGBA8, color, NULL);
}
void GPU_invalid_tex_bind(int mode)
@@ -610,61 +960,45 @@ void GPU_invalid_tex_free(void)
GPU_texture_free(GG.invalid_tex_3D);
}
-
void GPU_texture_bind(GPUTexture *tex, int number)
{
+ BLI_assert(number >= 0);
+
if (number >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
return;
}
if ((G.debug & G_DEBUG)) {
- if (tex->fb && GPU_framebuffer_bound(tex->fb)) {
- fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to bind "
+ "texture attached to current framebuffer!\n");
+ BLI_assert(0); /* Should never happen! */
+ break;
+ }
}
}
- if (number < 0)
- return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
+ glActiveTexture(GL_TEXTURE0 + number);
- GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + number);
- if (number != 0) glActiveTexture(arbnumber);
- if (tex->bindcode != 0) {
- glBindTexture(tex->target_base, tex->bindcode);
- }
+ if (tex->bindcode != 0)
+ glBindTexture(tex->target, tex->bindcode);
else
GPU_invalid_tex_bind(tex->target_base);
- glEnable(tex->target_base);
- if (number != 0) glActiveTexture(GL_TEXTURE0);
tex->number = number;
-
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
}
void GPU_texture_unbind(GPUTexture *tex)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
-
if (tex->number == -1)
return;
-
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
- GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
- if (tex->number != 0) glActiveTexture(arbnumber);
- glBindTexture(tex->target_base, 0);
- glDisable(tex->target_base);
- if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glBindTexture(tex->target, 0);
tex->number = -1;
-
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
}
int GPU_texture_bound_number(GPUTexture *tex)
@@ -672,39 +1006,79 @@ int GPU_texture_bound_number(GPUTexture *tex)
return tex->number;
}
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
+#define WARN_NOT_BOUND(_tex) do { \
+ if (_tex->number == -1) { \
+ fprintf(stderr, "Warning : Trying to set parameter on a texture not bound.\n"); \
+ BLI_assert(0); \
+ return; \
+ } \
+} while (0);
+
+void GPU_texture_generate_mipmap(GPUTexture *tex)
{
- if (tex->number >= GPU_max_textures()) {
- fprintf(stderr, "Not enough texture slots.\n");
- return;
- }
+ WARN_NOT_BOUND(tex);
- if (tex->number == -1)
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glGenerateMipmap(tex->target_base);
+}
+
+void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
+{
+ WARN_NOT_BOUND(tex);
+
+ /* Could become an assertion ? (fclem) */
+ if (!GPU_texture_depth(tex))
return;
- GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
+ GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
+
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode);
+}
- GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
- if (tex->number != 0) glActiveTexture(arbnumber);
+void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
+{
+ WARN_NOT_BOUND(tex);
- if (tex->depth) {
- if (compare)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
- else
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- }
+ /* Stencil and integer format does not support filtering. */
+ BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- if (use_filter) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
- else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
- if (tex->number != 0) glActiveTexture(GL_TEXTURE0);
+ GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
+
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter);
+}
+
+void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter)
+{
+ WARN_NOT_BOUND(tex);
- GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
+ /* Stencil and integer format does not support filtering. */
+ BLI_assert((!use_filter && !use_mipmap) || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
+
+ GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
+ GLenum mipmap = (use_filter)
+ ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR
+ : (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST;
+
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
+}
+
+void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat)
+{
+ WARN_NOT_BOUND(tex);
+
+ GLenum repeat = (use_repeat) ? GL_REPEAT : GL_CLAMP_TO_EDGE;
+
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat);
+ if (tex->target_base != GL_TEXTURE_1D)
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat);
+ if (tex->target_base == GL_TEXTURE_3D)
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat);
}
void GPU_texture_free(GPUTexture *tex)
@@ -715,11 +1089,17 @@ void GPU_texture_free(GPUTexture *tex)
fprintf(stderr, "GPUTexture: negative refcount\n");
if (tex->refcount == 0) {
- if (tex->fb)
- GPU_framebuffer_texture_detach(tex);
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] != NULL) {
+ GPU_framebuffer_texture_detach_slot(tex->fb[i], tex, tex->fb_attachment[i]);
+ }
+ }
+
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
+ gpu_texture_memory_footprint_remove(tex);
+
MEM_freeN(tex);
}
}
@@ -744,29 +1124,64 @@ int GPU_texture_height(const GPUTexture *tex)
return tex->h;
}
-int GPU_texture_depth(const GPUTexture *tex)
+GPUTextureFormat GPU_texture_format(const GPUTexture *tex)
{
- return tex->depth;
+ return tex->format;
}
-int GPU_texture_opengl_bindcode(const GPUTexture *tex)
+int GPU_texture_samples(const GPUTexture *tex)
{
- return tex->bindcode;
+ return tex->samples;
+}
+
+bool GPU_texture_depth(const GPUTexture *tex)
+{
+ return (tex->format_flag & GPU_FORMAT_DEPTH) != 0;
}
-GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
+bool GPU_texture_stencil(const GPUTexture *tex)
{
- return tex->fb;
+ return (tex->format_flag & GPU_FORMAT_STENCIL) != 0;
}
-int GPU_texture_framebuffer_attachment(GPUTexture *tex)
+bool GPU_texture_integer(const GPUTexture *tex)
{
- return tex->fb_attachment;
+ return (tex->format_flag & GPU_FORMAT_INTEGER) != 0;
}
-void GPU_texture_framebuffer_set(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
+bool GPU_texture_cube(const GPUTexture *tex)
{
- tex->fb = fb;
- tex->fb_attachment = attachment;
+ return (tex->format_flag & GPU_FORMAT_CUBE) != 0;
}
+int GPU_texture_opengl_bindcode(const GPUTexture *tex)
+{
+ return tex->bindcode;
+}
+
+void GPU_texture_attach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb, int attachment)
+{
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] == NULL) {
+ tex->fb[i] = fb;
+ tex->fb_attachment[i] = attachment;
+ return;
+ }
+ }
+
+ BLI_assert(!"Error: Texture: Not enough Framebuffer slots");
+}
+
+/* Return previous attachment point */
+int GPU_texture_detach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb)
+{
+ for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) {
+ if (tex->fb[i] == fb) {
+ tex->fb[i] = NULL;
+ return tex->fb_attachment[i];
+ }
+ }
+
+ BLI_assert(!"Error: Texture: Framebuffer is not attached");
+ return 0;
+}
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c
new file mode 100644
index 00000000000..afd43600d9b
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_uniformbuffer.c
@@ -0,0 +1,378 @@
+/*
+ * ***** 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_uniformbuffer.c
+ * \ingroup gpu
+ */
+
+#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "gpu_codegen.h"
+
+#include "GPU_extensions.h"
+#include "GPU_glew.h"
+#include "GPU_material.h"
+#include "GPU_uniformbuffer.h"
+
+typedef enum GPUUniformBufferFlag {
+ GPU_UBO_FLAG_INITIALIZED = (1 << 0),
+ GPU_UBO_FLAG_DIRTY = (1 << 1),
+} GPUUniformBufferFlag;
+
+typedef enum GPUUniformBufferType {
+ GPU_UBO_STATIC = 0,
+ GPU_UBO_DYNAMIC = 1,
+} GPUUniformBufferType;
+
+struct GPUUniformBuffer {
+ int size; /* in bytes */
+ GLuint bindcode; /* opengl identifier for UBO */
+ int bindpoint; /* current binding point */
+ GPUUniformBufferType type;
+};
+
+#define GPUUniformBufferStatic GPUUniformBuffer
+
+typedef struct GPUUniformBufferDynamic {
+ GPUUniformBuffer buffer;
+ ListBase items; /* GPUUniformBufferDynamicItem */
+ void *data;
+ char flag;
+} GPUUniformBufferDynamic;
+
+struct GPUUniformBufferDynamicItem {
+ struct GPUUniformBufferDynamicItem *next, *prev;
+ GPUType gputype;
+ float *data;
+ int size;
+};
+
+
+/* Prototypes */
+static GPUType get_padded_gpu_type(struct LinkData *link);
+static void gpu_uniformbuffer_inputs_sort(struct ListBase *inputs);
+
+static GPUUniformBufferDynamicItem *gpu_uniformbuffer_populate(
+ GPUUniformBufferDynamic *ubo, const GPUType gputype, float *num);
+
+/* Only support up to this type, if you want to extend it, make sure the
+ * padding logic is correct for the new types. */
+#define MAX_UBO_GPU_TYPE GPU_VEC4
+
+static void gpu_uniformbuffer_initialize(GPUUniformBuffer *ubo, const void *data)
+{
+ glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
+ glBufferData(GL_UNIFORM_BUFFER, ubo->size, data, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+}
+
+GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256])
+{
+ GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBufferStatic), "GPUUniformBufferStatic");
+ ubo->size = size;
+ ubo->bindpoint = -1;
+
+ /* Generate Buffer object */
+ glGenBuffers(1, &ubo->bindcode);
+
+ if (!ubo->bindcode) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO create failed");
+ GPU_uniformbuffer_free(ubo);
+ return NULL;
+ }
+
+ if (ubo->size > GPU_max_ubo_size()) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO too big");
+ GPU_uniformbuffer_free(ubo);
+ return NULL;
+ }
+
+ gpu_uniformbuffer_initialize(ubo, data);
+ return ubo;
+}
+
+/**
+ * Create dynamic UBO from parameters
+ * Return NULL if failed to create or if \param inputs is empty.
+ *
+ * \param inputs ListBase of BLI_genericNodeN(GPUInput)
+ */
+GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_out[256])
+{
+ /* There is no point on creating an UBO if there is no arguments. */
+ if (BLI_listbase_is_empty(inputs)) {
+ return NULL;
+ }
+
+ GPUUniformBufferDynamic *ubo = MEM_callocN(sizeof(GPUUniformBufferDynamic), "GPUUniformBufferDynamic");
+ ubo->buffer.type = GPU_UBO_DYNAMIC;
+ ubo->buffer.bindpoint = -1;
+ ubo->flag = GPU_UBO_FLAG_DIRTY;
+
+ /* Generate Buffer object. */
+ glGenBuffers(1, &ubo->buffer.bindcode);
+
+ if (!ubo->buffer.bindcode) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO create failed");
+ GPU_uniformbuffer_free(&ubo->buffer);
+ return NULL;
+ }
+
+ if (ubo->buffer.size > GPU_max_ubo_size()) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO too big");
+ GPU_uniformbuffer_free(&ubo->buffer);
+ return NULL;
+ }
+
+ /* Make sure we comply to the ubo alignment requirements. */
+ gpu_uniformbuffer_inputs_sort(inputs);
+
+ for (LinkData *link = inputs->first; link; link = link->next) {
+ GPUInput *input = link->data;
+ GPUType gputype = get_padded_gpu_type(link);
+ gpu_uniformbuffer_populate(ubo, gputype, input->dynamicvec);
+ }
+
+ ubo->data = MEM_mallocN(ubo->buffer.size, __func__);
+
+ /* Initialize buffer data. */
+ GPU_uniformbuffer_dynamic_update(&ubo->buffer);
+ return &ubo->buffer;
+}
+
+/**
+ * Free the data, and clean the items list.
+ */
+static void gpu_uniformbuffer_dynamic_reset(GPUUniformBufferDynamic *ubo)
+{
+ ubo->buffer.size = 0;
+ if (ubo->data) {
+ MEM_freeN(ubo->data);
+ }
+ BLI_freelistN(&ubo->items);
+}
+
+void GPU_uniformbuffer_free(GPUUniformBuffer *ubo)
+{
+ if (ubo->type == GPU_UBO_DYNAMIC) {
+ gpu_uniformbuffer_dynamic_reset((GPUUniformBufferDynamic *)ubo);
+ }
+
+ glDeleteBuffers(1, &ubo->bindcode);
+ MEM_freeN(ubo);
+}
+
+static void gpu_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
+{
+ glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo->size, data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+}
+
+void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
+{
+ BLI_assert(ubo->type == GPU_UBO_STATIC);
+ gpu_uniformbuffer_update(ubo, data);
+}
+
+/**
+ * We need to recalculate the internal data, and re-generate it
+ * from its populated items.
+ */
+void GPU_uniformbuffer_dynamic_update(GPUUniformBuffer *ubo_)
+{
+ BLI_assert(ubo_->type == GPU_UBO_DYNAMIC);
+ GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_;
+
+ float *offset = ubo->data;
+ for (GPUUniformBufferDynamicItem *item = ubo->items.first; item; item = item->next) {
+ memcpy(offset, item->data, item->size);
+ offset += item->gputype;
+ }
+
+ if (ubo->flag & GPU_UBO_FLAG_INITIALIZED) {
+ gpu_uniformbuffer_update(ubo_, ubo->data);
+ }
+ else {
+ ubo->flag |= GPU_UBO_FLAG_INITIALIZED;
+ gpu_uniformbuffer_initialize(ubo_, ubo->data);
+ }
+
+ ubo->flag &= ~GPU_UBO_FLAG_DIRTY;
+}
+
+/**
+ * We need to pad some data types (vec3) on the C side
+ * To match the GPU expected memory block alignment.
+ */
+static GPUType get_padded_gpu_type(LinkData *link)
+{
+ GPUInput *input = link->data;
+ GPUType gputype = input->type;
+
+ /* Unless the vec3 is followed by a float we need to treat it as a vec4. */
+ if (gputype == GPU_VEC3 &&
+ (link->next != NULL) &&
+ (((GPUInput *)link->next->data)->type != GPU_FLOAT))
+ {
+ gputype = GPU_VEC4;
+ }
+
+ return gputype;
+}
+
+/**
+ * Returns 1 if the first item shold be after second item.
+ * We make sure the vec4 uniforms come first.
+ */
+static int inputs_cmp(const void *a, const void *b)
+{
+ const LinkData *link_a = a, *link_b = b;
+ const GPUInput *input_a = link_a->data, *input_b = link_b->data;
+ return input_a->type < input_b->type ? 1 : 0;
+}
+
+/**
+ * Make sure we respect the expected alignment of UBOs.
+ * vec4, pad vec3 as vec4, then vec2, then floats.
+ */
+static void gpu_uniformbuffer_inputs_sort(ListBase *inputs)
+{
+ /* Order them as vec4, vec3, vec2, float. */
+ BLI_listbase_sort(inputs, inputs_cmp);
+
+ /* Creates a lookup table for the different types; */
+ LinkData *inputs_lookup[MAX_UBO_GPU_TYPE + 1] = {NULL};
+ GPUType cur_type = MAX_UBO_GPU_TYPE + 1;
+
+ for (LinkData *link = inputs->first; link; link = link->next) {
+ GPUInput *input = link->data;
+ if (input->type == cur_type) {
+ continue;
+ }
+ else {
+ inputs_lookup[input->type] = link;
+ cur_type = input->type;
+ }
+ }
+
+ /* If there is no GPU_VEC3 there is no need for alignment. */
+ if (inputs_lookup[GPU_VEC3] == NULL) {
+ return;
+ }
+
+ LinkData *link = inputs_lookup[GPU_VEC3];
+ while (link != NULL && ((GPUInput *)link->data)->type == GPU_VEC3) {
+ LinkData *link_next = link->next;
+
+ /* If GPU_VEC3 is followed by nothing or a GPU_FLOAT, no need for aligment. */
+ if ((link_next == NULL) ||
+ ((GPUInput *)link_next->data)->type == GPU_FLOAT)
+ {
+ break;
+ }
+
+ /* If there is a float, move it next to current vec3. */
+ if (inputs_lookup[GPU_FLOAT] != NULL) {
+ LinkData *float_input = inputs_lookup[GPU_FLOAT];
+ inputs_lookup[GPU_FLOAT] = float_input->next;
+
+ BLI_remlink(inputs, float_input);
+ BLI_insertlinkafter(inputs, link, float_input);
+ }
+
+ link = link_next;
+ }
+}
+
+/**
+ * This may now happen from the main thread, so we can't update the UBO
+ * We simply flag it as dirty
+ */
+static GPUUniformBufferDynamicItem *gpu_uniformbuffer_populate(
+ GPUUniformBufferDynamic *ubo, const GPUType gputype, float *num)
+{
+ BLI_assert(gputype <= MAX_UBO_GPU_TYPE);
+ GPUUniformBufferDynamicItem *item = MEM_callocN(sizeof(GPUUniformBufferDynamicItem), __func__);
+
+ item->gputype = gputype;
+ item->data = num;
+ item->size = gputype * sizeof(float);
+ ubo->buffer.size += item->size;
+
+ ubo->flag |= GPU_UBO_FLAG_DIRTY;
+ BLI_addtail(&ubo->items, item);
+
+ return item;
+}
+
+void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number)
+{
+ if (number >= GPU_max_ubo_binds()) {
+ fprintf(stderr, "Not enough UBO slots.\n");
+ return;
+ }
+
+ if (ubo->type == GPU_UBO_DYNAMIC) {
+ GPUUniformBufferDynamic *ubo_dynamic = (GPUUniformBufferDynamic *)ubo;
+ if (ubo_dynamic->flag & GPU_UBO_FLAG_DIRTY) {
+ GPU_uniformbuffer_dynamic_update(ubo);
+ }
+ }
+
+ if (ubo->bindcode != 0) {
+ glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode);
+ }
+
+ ubo->bindpoint = number;
+}
+
+void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo)
+{
+ ubo->bindpoint = -1;
+}
+
+int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo)
+{
+ return ubo->bindpoint;
+}
+
+void GPU_uniformbuffer_tag_dirty(GPUUniformBuffer *ubo_)
+{
+ BLI_assert(ubo_->type == GPU_UBO_DYNAMIC);
+ GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_;
+ ubo->flag |= GPU_UBO_FLAG_DIRTY;
+}
+
+#undef MAX_UBO_GPU_TYPE
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
new file mode 100644
index 00000000000..0bf215f31a8
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -0,0 +1,644 @@
+/*
+ * ***** 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):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_viewport.c
+ * \ingroup gpu
+ *
+ * System that manages viewport drawing.
+ */
+
+#include <string.h>
+
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+#include "BLI_mempool.h"
+
+#include "BIF_gl.h"
+
+#include "DNA_vec_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_global.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+#include "GPU_immediate.h"
+#include "GPU_texture.h"
+#include "GPU_viewport.h"
+#include "GPU_draw.h"
+
+#include "DRW_engine.h"
+
+#include "MEM_guardedalloc.h"
+
+static const int default_fbl_len = (sizeof(DefaultFramebufferList)) / sizeof(void *);
+static const int default_txl_len = (sizeof(DefaultTextureList)) / sizeof(void *);
+
+/* Maximum number of simultaneous engine enabled at the same time.
+ * Setting it lower than the real number will do lead to
+ * higher VRAM usage due to sub-efficient buffer reuse. */
+#define MAX_ENGINE_BUFFER_SHARING 5
+
+typedef struct ViewportTempTexture {
+ struct ViewportTempTexture *next, *prev;
+ void *user[MAX_ENGINE_BUFFER_SHARING];
+ GPUTexture *texture;
+} ViewportTempTexture;
+
+struct GPUViewport {
+ int size[2];
+ int samples;
+ int flag;
+
+ ListBase data; /* ViewportEngineData wrapped in LinkData */
+ unsigned int data_hash; /* If hash mismatch we free all ViewportEngineData in this viewport */
+
+ DefaultFramebufferList *fbl;
+ DefaultTextureList *txl;
+
+ ViewportMemoryPool vmempool; /* Used for rendering data structure. */
+ struct DRWInstanceDataList *idatalist; /* Used for rendering data structure. */
+
+ ListBase tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines */
+
+ /* Profiling data */
+ double cache_time;
+};
+
+enum {
+ DO_UPDATE = (1 << 0),
+};
+
+static void gpu_viewport_buffers_free(FramebufferList *fbl, int fbl_len, TextureList *txl, int txl_len);
+static void gpu_viewport_storage_free(StorageList *stl, int stl_len);
+static void gpu_viewport_passes_free(PassList *psl, int psl_len);
+static void gpu_viewport_texture_pool_free(GPUViewport *viewport);
+static void gpu_viewport_default_fb_create(GPUViewport *viewport);
+
+void GPU_viewport_tag_update(GPUViewport *viewport)
+{
+ viewport->flag |= DO_UPDATE;
+}
+
+bool GPU_viewport_do_update(GPUViewport *viewport)
+{
+ bool ret = (viewport->flag & DO_UPDATE);
+ viewport->flag &= ~DO_UPDATE;
+ return ret;
+}
+
+GPUViewport *GPU_viewport_create(void)
+{
+ GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport");
+ viewport->fbl = MEM_callocN(sizeof(DefaultFramebufferList), "FramebufferList");
+ viewport->txl = MEM_callocN(sizeof(DefaultTextureList), "TextureList");
+ viewport->idatalist = DRW_instance_data_list_create();
+
+ viewport->size[0] = viewport->size[1] = -1;
+
+ return viewport;
+}
+
+GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs)
+{
+ GPUViewport *viewport = GPU_viewport_create();
+ GPUTexture *color, *depth;
+ GPUFrameBuffer *fb;
+ viewport->size[0] = GPU_offscreen_width(ofs);
+ viewport->size[1] = GPU_offscreen_height(ofs);
+
+ GPU_offscreen_viewport_data_get(ofs, &fb, &color, &depth);
+
+ if (GPU_texture_samples(color)) {
+ viewport->txl->multisample_color = color;
+ viewport->txl->multisample_depth = depth;
+ viewport->fbl->multisample_fb = fb;
+ gpu_viewport_default_fb_create(viewport);
+ }
+ else {
+ viewport->fbl->default_fb = fb;
+ viewport->txl->color = color;
+ viewport->txl->depth = depth;
+ GPU_framebuffer_ensure_config(&viewport->fbl->color_only_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(viewport->txl->color)
+ });
+ GPU_framebuffer_ensure_config(&viewport->fbl->depth_only_fb, {
+ GPU_ATTACHMENT_TEXTURE(viewport->txl->depth),
+ GPU_ATTACHMENT_NONE
+ });
+ }
+
+ return viewport;
+}
+/**
+ * Clear vars assigned from offscreen, so we don't free data owned by `GPUOffScreen`.
+ */
+void GPU_viewport_clear_from_offscreen(GPUViewport *viewport)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+
+ if (dfbl->multisample_fb) {
+ /* GPUViewport expect the final result to be in default_fb but
+ * GPUOffscreen wants it in its multisample_fb, so we sync it back. */
+ GPU_framebuffer_blit(dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT);
+ dfbl->multisample_fb = NULL;
+ dtxl->multisample_color = NULL;
+ dtxl->multisample_depth = NULL;
+ }
+ else {
+ viewport->fbl->default_fb = NULL;
+ dtxl->color = NULL;
+ dtxl->depth = NULL;
+ }
+}
+
+void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
+{
+ LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData");
+ ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData");
+ int fbl_len, txl_len, psl_len, stl_len;
+
+ DRW_engine_viewport_data_size_get(engine_type, &fbl_len, &txl_len, &psl_len, &stl_len);
+
+ data->engine_type = engine_type;
+
+ data->fbl = MEM_callocN((sizeof(void *) * fbl_len) + sizeof(FramebufferList), "FramebufferList");
+ data->txl = MEM_callocN((sizeof(void *) * txl_len) + sizeof(TextureList), "TextureList");
+ data->psl = MEM_callocN((sizeof(void *) * psl_len) + sizeof(PassList), "PassList");
+ data->stl = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), "StorageList");
+
+ ld->data = data;
+ BLI_addtail(&viewport->data, ld);
+
+ return data;
+}
+
+static void gpu_viewport_engines_data_free(GPUViewport *viewport)
+{
+ int fbl_len, txl_len, psl_len, stl_len;
+
+ LinkData *next;
+ for (LinkData *link = viewport->data.first; link; link = next) {
+ next = link->next;
+ ViewportEngineData *data = link->data;
+ DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, &psl_len, &stl_len);
+
+ gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
+ gpu_viewport_passes_free(data->psl, psl_len);
+ gpu_viewport_storage_free(data->stl, stl_len);
+
+ MEM_freeN(data->fbl);
+ MEM_freeN(data->txl);
+ MEM_freeN(data->psl);
+ MEM_freeN(data->stl);
+
+ /* We could handle this in the DRW module */
+ if (data->text_draw_cache) {
+ extern void DRW_text_cache_destroy(struct DRWTextStore *dt);
+ DRW_text_cache_destroy(data->text_draw_cache);
+ data->text_draw_cache = NULL;
+ }
+
+ MEM_freeN(data);
+
+ BLI_remlink(&viewport->data, link);
+ MEM_freeN(link);
+ }
+
+ gpu_viewport_texture_pool_free(viewport);
+}
+
+void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type)
+{
+ for (LinkData *link = viewport->data.first; link; link = link->next) {
+ ViewportEngineData *vdata = link->data;
+ if (vdata->engine_type == engine_type) {
+ return vdata;
+ }
+ }
+ return NULL;
+}
+
+ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport)
+{
+ return &viewport->vmempool;
+}
+
+struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport)
+{
+ return viewport->idatalist;
+}
+
+void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport)
+{
+ return viewport->fbl;
+}
+
+void *GPU_viewport_texture_list_get(GPUViewport *viewport)
+{
+ return viewport->txl;
+}
+
+void GPU_viewport_size_get(const GPUViewport *viewport, int size[2])
+{
+ size[0] = viewport->size[0];
+ size[1] = viewport->size[1];
+}
+
+/**
+ * Special case, this is needed for when we have a viewport without a frame-buffer output
+ * (occlusion queries for eg) but still need to set the size since it may be used for other calculations.
+ */
+void GPU_viewport_size_set(GPUViewport *viewport, const int size[2])
+{
+ viewport->size[0] = size[0];
+ viewport->size[1] = size[1];
+}
+
+double *GPU_viewport_cache_time_get(GPUViewport *viewport)
+{
+ return &viewport->cache_time;
+}
+
+/**
+ * Try to find a texture coresponding to params into the texture pool.
+ * If no texture was found, create one and add it to the pool.
+ */
+GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int format)
+{
+ GPUTexture *tex;
+
+ for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
+ if ((GPU_texture_format(tmp_tex->texture) == format) &&
+ (GPU_texture_width(tmp_tex->texture) == width) &&
+ (GPU_texture_height(tmp_tex->texture) == height))
+ {
+ /* Search if the engine is not already using this texture */
+ for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) {
+ if (tmp_tex->user[i] == engine) {
+ break;
+ }
+
+ if (tmp_tex->user[i] == NULL) {
+ tmp_tex->user[i] = engine;
+ return tmp_tex->texture;
+ }
+ }
+ }
+ }
+
+ tex = GPU_texture_create_2D(width, height, format, NULL, NULL);
+ GPU_texture_bind(tex, 0);
+ /* Doing filtering for depth does not make sense when not doing shadow mapping,
+ * and enabling texture filtering on integer texture make them unreadable. */
+ bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex);
+ GPU_texture_filter_mode(tex, do_filter);
+ GPU_texture_unbind(tex);
+
+ ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture");
+ tmp_tex->texture = tex;
+ tmp_tex->user[0] = engine;
+ BLI_addtail(&viewport->tex_pool, tmp_tex);
+
+ return tex;
+}
+
+static void gpu_viewport_texture_pool_clear_users(GPUViewport *viewport)
+{
+ ViewportTempTexture *tmp_tex_next;
+
+ for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex_next) {
+ tmp_tex_next = tmp_tex->next;
+ bool no_user = true;
+ for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) {
+ if (tmp_tex->user[i] != NULL) {
+ tmp_tex->user[i] = NULL;
+ no_user = false;
+ }
+ }
+
+ if (no_user) {
+ GPU_texture_free(tmp_tex->texture);
+ BLI_freelinkN(&viewport->tex_pool, tmp_tex);
+ }
+ }
+}
+
+static void gpu_viewport_texture_pool_free(GPUViewport *viewport)
+{
+ for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) {
+ GPU_texture_free(tmp_tex->texture);
+ }
+
+ BLI_freelistN(&viewport->tex_pool);
+}
+
+bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash)
+{
+ bool dirty = false;
+
+ if (viewport->data_hash != hash) {
+ gpu_viewport_engines_data_free(viewport);
+ dirty = true;
+ }
+
+ viewport->data_hash = hash;
+
+ return dirty;
+}
+
+void GPU_viewport_cache_release(GPUViewport *viewport)
+{
+ for (LinkData *link = viewport->data.first; link; link = link->next) {
+ ViewportEngineData *data = link->data;
+ int psl_len;
+ DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL);
+ gpu_viewport_passes_free(data->psl, psl_len);
+ }
+}
+
+static void gpu_viewport_default_fb_create(GPUViewport *viewport)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+ int *size = viewport->size;
+ bool ok = true;
+
+ dtxl->color = GPU_texture_create_2D(size[0], size[1], GPU_RGBA8, NULL, NULL);
+ dtxl->depth = GPU_texture_create_2D(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL);
+
+ if (!(dtxl->depth && dtxl->color)) {
+ ok = false;
+ goto cleanup;
+ }
+
+ GPU_framebuffer_ensure_config(&dfbl->default_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_NONE
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->color_only_fb, {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(dtxl->color)
+ });
+
+ ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL);
+ ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL);
+
+cleanup:
+ if (!ok) {
+ GPU_viewport_free(viewport);
+ DRW_opengl_context_disable();
+ return;
+ }
+
+ GPU_framebuffer_restore();
+}
+
+static void gpu_viewport_default_multisample_fb_create(GPUViewport *viewport)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+ int *size = viewport->size;
+ int samples = viewport->samples;
+ bool ok = true;
+
+ dtxl->multisample_color = GPU_texture_create_2D_multisample(size[0], size[1], GPU_RGBA8, NULL, samples, NULL);
+ dtxl->multisample_depth = GPU_texture_create_2D_multisample(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, samples, NULL);
+
+ if (!(dtxl->multisample_depth && dtxl->multisample_color)) {
+ ok = false;
+ goto cleanup;
+ }
+
+ GPU_framebuffer_ensure_config(&dfbl->multisample_fb, {
+ GPU_ATTACHMENT_TEXTURE(dtxl->multisample_depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->multisample_color)
+ });
+
+ ok = ok && GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL);
+
+cleanup:
+ if (!ok) {
+ GPU_viewport_free(viewport);
+ DRW_opengl_context_disable();
+ return;
+ }
+
+ GPU_framebuffer_restore();
+}
+
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ int fbl_len, txl_len;
+
+ /* add one pixel because of scissor test */
+ int rect_w = BLI_rcti_size_x(rect) + 1;
+ int rect_h = BLI_rcti_size_y(rect) + 1;
+
+ DRW_opengl_context_enable();
+
+ if (dfbl->default_fb) {
+ if (rect_w != viewport->size[0] || rect_h != viewport->size[1] || U.ogl_multisamples != viewport->samples) {
+ gpu_viewport_buffers_free(
+ (FramebufferList *)viewport->fbl, default_fbl_len,
+ (TextureList *)viewport->txl, default_txl_len);
+
+ for (LinkData *link = viewport->data.first; link; link = link->next) {
+ ViewportEngineData *data = link->data;
+ DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL);
+ gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
+ }
+
+ gpu_viewport_texture_pool_free(viewport);
+ }
+ }
+
+ viewport->size[0] = rect_w;
+ viewport->size[1] = rect_h;
+ viewport->samples = U.ogl_multisamples;
+
+ gpu_viewport_texture_pool_clear_users(viewport);
+
+ /* Multisample Buffer */
+ if (viewport->samples > 0) {
+ if (!dfbl->default_fb) {
+ gpu_viewport_default_multisample_fb_create(viewport);
+ }
+ }
+
+ if (!dfbl->default_fb) {
+ gpu_viewport_default_fb_create(viewport);
+ }
+}
+
+void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+
+ if (dfbl->default_fb == NULL)
+ return;
+
+ DefaultTextureList *dtxl = viewport->txl;
+
+ GPUTexture *color = dtxl->color;
+
+ const float w = (float)GPU_texture_width(color);
+ const float h = (float)GPU_texture_height(color);
+
+ BLI_assert(w == BLI_rcti_size_x(rect) + 1);
+ BLI_assert(h == BLI_rcti_size_y(rect) + 1);
+
+ /* wmOrtho for the screen has this same offset */
+ const float halfx = GLA_PIXEL_OFS / w;
+ const float halfy = GLA_PIXEL_OFS / h;
+
+ float x1 = rect->xmin;
+ float x2 = rect->xmin + w;
+ float y1 = rect->ymin;
+ float y2 = rect->ymin + h;
+
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+ GPU_shader_bind(shader);
+
+ GPU_texture_bind(color, 0);
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), halfx, halfy, 1.0f + halfx, 1.0f + halfy);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x1, y1, x2, y2);
+ glUniform4f(GPU_shader_get_builtin_uniform(shader, GWN_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f);
+
+ GWN_draw_primitive(GWN_PRIM_TRI_STRIP, 4);
+
+ GPU_texture_unbind(color);
+}
+
+void GPU_viewport_unbind(GPUViewport *UNUSED(viewport))
+{
+ GPU_framebuffer_restore();
+ DRW_opengl_context_disable();
+}
+
+
+GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport)
+{
+ DefaultFramebufferList *dfbl = viewport->fbl;
+
+ if (dfbl->default_fb) {
+ DefaultTextureList *dtxl = viewport->txl;
+ return dtxl->color;
+ }
+
+ return NULL;
+}
+
+static void gpu_viewport_buffers_free(
+ FramebufferList *fbl, int fbl_len,
+ TextureList *txl, int txl_len)
+{
+ for (int i = 0; i < fbl_len; i++) {
+ GPUFrameBuffer *fb = fbl->framebuffers[i];
+ if (fb) {
+ GPU_framebuffer_free(fb);
+ fbl->framebuffers[i] = NULL;
+ }
+ }
+ for (int i = 0; i < txl_len; i++) {
+ GPUTexture *tex = txl->textures[i];
+ if (tex) {
+ GPU_texture_free(tex);
+ txl->textures[i] = NULL;
+ }
+ }
+}
+
+static void gpu_viewport_storage_free(StorageList *stl, int stl_len)
+{
+ for (int i = 0; i < stl_len; i++) {
+ void *storage = stl->storage[i];
+ if (storage) {
+ MEM_freeN(storage);
+ stl->storage[i] = NULL;
+ }
+ }
+}
+
+static void gpu_viewport_passes_free(PassList *psl, int psl_len)
+{
+ for (int i = 0; i < psl_len; i++) {
+ struct DRWPass *pass = psl->passes[i];
+ if (pass) {
+ DRW_pass_free(pass);
+ psl->passes[i] = NULL;
+ }
+ }
+}
+
+/* Must be executed inside Drawmanager Opengl Context. */
+void GPU_viewport_free(GPUViewport *viewport)
+{
+ gpu_viewport_engines_data_free(viewport);
+
+ gpu_viewport_buffers_free(
+ (FramebufferList *)viewport->fbl, default_fbl_len,
+ (TextureList *)viewport->txl, default_txl_len);
+
+ gpu_viewport_texture_pool_free(viewport);
+
+ MEM_freeN(viewport->fbl);
+ MEM_freeN(viewport->txl);
+
+ if (viewport->vmempool.calls != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.calls);
+ }
+ if (viewport->vmempool.states != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.states);
+ }
+ if (viewport->vmempool.shgroups != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.shgroups);
+ }
+ if (viewport->vmempool.uniforms != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.uniforms);
+ }
+ if (viewport->vmempool.passes != NULL) {
+ BLI_mempool_destroy(viewport->vmempool.passes);
+ }
+
+ DRW_instance_data_list_free(viewport->idatalist);
+ MEM_freeN(viewport->idatalist);
+
+ MEM_freeN(viewport);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl
new file mode 100644
index 00000000000..769e2b0e37c
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+in vec4 color;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl
new file mode 100644
index 00000000000..9fdf8ececc5
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl
@@ -0,0 +1,48 @@
+/**
+ * Simple shader that just draw multiple icons at the specified locations
+ * does not need any vertex input (producing less call to immBegin/End)
+ **/
+
+/* Same as ICON_DRAW_CACHE_SIZE */
+#define MAX_CALLS 16
+
+uniform vec4 calls_data[MAX_CALLS * 3];
+
+out vec2 texCoord_interp;
+flat out vec4 finalColor;
+
+void main()
+{
+ /* Rendering 2 triangle per icon. */
+ int i = gl_VertexID / 6;
+ int v = gl_VertexID % 6;
+
+ vec4 pos = calls_data[i*3];
+ vec4 tex = calls_data[i*3+1];
+ finalColor = calls_data[i*3+2];
+
+ /* TODO Remove this */
+ if (v == 2) v = 4;
+ else if (v == 3) v = 0;
+ else if (v == 5) v = 2;
+
+ if (v == 0) {
+ pos.xy = pos.xw;
+ tex.xy = tex.xw;
+ }
+ else if (v == 1) {
+ pos.xy = pos.xz;
+ tex.xy = tex.xz;
+ }
+ else if (v == 2) {
+ pos.xy = pos.yw;
+ tex.xy = tex.yw;
+ }
+ else {
+ pos.xy = pos.yz;
+ tex.xy = tex.yz;
+ }
+
+ gl_Position = vec4(pos.xy, 0.0f, 1.0f);
+ texCoord_interp = tex.xy;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
new file mode 100644
index 00000000000..118f4e3b187
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl
@@ -0,0 +1,35 @@
+/**
+ * Simple shader that just draw one icon at the specified location
+ * does not need any vertex input (producing less call to immBegin/End)
+ **/
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec4 rect_icon;
+uniform vec4 rect_geom;
+
+out vec2 texCoord_interp;
+
+void main()
+{
+ vec2 uv;
+ vec2 co;
+ if (gl_VertexID == 0) {
+ co = rect_geom.xw;
+ uv = rect_icon.xw;
+ }
+ else if (gl_VertexID == 1) {
+ co = rect_geom.xy;
+ uv = rect_icon.xy;
+ }
+ else if (gl_VertexID == 2) {
+ co = rect_geom.zw;
+ uv = rect_icon.zw;
+ }
+ else {
+ co = rect_geom.zy;
+ uv = rect_icon.zy;
+ }
+
+ gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f);
+ texCoord_interp = uv;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl
new file mode 100644
index 00000000000..228f3f1da19
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+/* Keep in sync with intern/opencolorio/gpu_shader_display_transform_vertex.glsl */
+in vec2 texCoord;
+in vec2 pos;
+out vec2 texCoord_interp;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos.xy, 0.0f, 1.0f);
+ texCoord_interp = texCoord;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl
new file mode 100644
index 00000000000..7caf00f58fd
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl
@@ -0,0 +1,54 @@
+
+/*
+ * Fragment Shader for dashed lines, with uniform multi-color(s), or any single-color, and any thickness.
+ *
+ * Dashed is performed in screen space.
+ */
+
+uniform float dash_width;
+
+/* Simple mode, discarding non-dash parts (so no need for blending at all). */
+uniform float dash_factor; /* if > 1.0, solid line. */
+
+/* More advanced mode, allowing for complex, multi-colored patterns. Enabled when num_colors > 0. */
+/* Note: max number of steps/colors in pattern is 32! */
+uniform int num_colors; /* Enabled if > 0, 1 for solid line. */
+uniform vec4 colors[32];
+
+noperspective in float distance_along_line;
+noperspective in vec4 color_geom;
+
+out vec4 fragColor;
+
+void main()
+{
+ /* Multi-color option. */
+ if (num_colors > 0) {
+ /* Solid line case, simple. */
+ if (num_colors == 1) {
+ fragColor = colors[0];
+ }
+ /* Actually dashed line... */
+ else {
+ float normalized_distance = fract(distance_along_line / dash_width);
+ fragColor = colors[int(normalized_distance * num_colors)];
+ }
+ }
+ /* Single color option. */
+ else {
+ /* Solid line case, simple. */
+ if (dash_factor >= 1.0f) {
+ fragColor = color_geom;
+ }
+ /* Actually dashed line... */
+ else {
+ float normalized_distance = fract(distance_along_line / dash_width);
+ if (normalized_distance <= dash_factor) {
+ fragColor = color_geom;
+ }
+ else {
+ discard;
+ }
+ }
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl
new file mode 100644
index 00000000000..db4bdf0a9f0
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl
@@ -0,0 +1,56 @@
+
+/*
+ * Geometry Shader for dashed lines, with uniform multi-color(s), or any single-color, and unary thickness.
+ *
+ * Dashed is performed in screen space.
+ */
+
+
+/* Make to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewport_size;
+
+/* Uniforms from fragment shader, used here to optimize out useless computation in case of solid line. */
+uniform float dash_factor; /* if > 1.0, solid line. */
+uniform int num_colors; /* Enabled if > 0, 1 for solid line. */
+
+layout(lines) in;
+
+in vec4 color_vert[];
+
+layout(line_strip, max_vertices = 2) out;
+noperspective out float distance_along_line;
+noperspective out vec4 color_geom;
+
+void main()
+{
+ vec4 v1 = gl_in[0].gl_Position;
+ vec4 v2 = gl_in[1].gl_Position;
+
+ gl_Position = v1;
+ color_geom = color_vert[0];
+ distance_along_line = 0.0f;
+ EmitVertex();
+
+ gl_Position = v2;
+ color_geom = color_vert[1];
+ if ((num_colors == 1) || (dash_factor >= 1.0f)) {
+ /* Solid line, optimize out distance computation! */
+ distance_along_line = 0.0f;
+ }
+ else {
+ vec2 p1 = (v1.xy / v1.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range.
+ p1 = p1 * viewport_size; // <- 'virtual' screen coordinates.
+
+ vec2 p2 = (v2.xy / v2.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range.
+ p2 = p2 * viewport_size; // <- 'virtual' screen coordinates.
+
+ distance_along_line = distance(p1, p2);
+ }
+ EmitVertex();
+
+ EndPrimitive();
+
+ /* Note: we could also use similar approach as diag_stripes_frag, but this would give us dashed 'anchored'
+ * to the screen, and not to one end of the line... */
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl
new file mode 100644
index 00000000000..f5c611586aa
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl
@@ -0,0 +1,21 @@
+
+/*
+ * Vertex Shader for dashed lines with 2D coordinates, with uniform multi-colors or uniform single-color,
+ * and unary thickness.
+ *
+ * Dashed is performed in screen space.
+ */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform vec4 color;
+
+in vec2 pos;
+
+out vec4 color_vert;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ color_vert = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl
new file mode 100644
index 00000000000..20c72f4407d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl
@@ -0,0 +1,59 @@
+
+// Draw dashed lines, perforated in screen space, with non-unary width.
+
+/* Make to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewport_size;
+
+/* Width of the generated 'line'. */
+uniform float width; /* in pixels, screen space. */
+
+/* Uniforms from fragment shader, used here to optimize out useless computation in case of solid line. */
+uniform float dash_factor; /* if > 1.0, solid line. */
+uniform int num_colors; /* Enabled if > 0, 1 for solid line. */
+
+layout(lines) in;
+
+layout(triangle_strip, max_vertices = 4) out;
+noperspective out float distance_along_line;
+
+void main()
+{
+ vec4 v1 = gl_in[0].gl_Position;
+ vec4 v2 = gl_in[1].gl_Position;
+
+ /* Width, from 2D screen space in pixels, to ModelViewProjection space of each input vertices. */
+ float w1 = (width / viewport_size) * v1.w * 2.0;
+ float w2 = (width / viewport_size) * v2.w * 2.0;
+
+ /* Normalized vector parallel to screen and orthogonal to line. */
+ vec4 wdir = normalize(vec4(v1.y - v2.y, v2.x - v1.x, 0.0, 0.0))
+
+ distance_along_line = 0.0f;
+ gl_Position = v1 + (wdir * w1);
+ EmitVertex();
+
+ gl_Position = v1 - (wdir * w1);
+ EmitVertex();
+
+ if ((num_colors == 1) || (dash_factor >= 1.0f)) {
+ /* Solid line, optimize out distance computation! */
+ distance_along_line = 0.0f;
+ }
+ else {
+ vec2 p1 = (v1.xy / v1.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range.
+ p1 = p1 * viewport_size; // <- 'virtual' screen coordinates.
+
+ vec2 p2 = (v2.xy / v2.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range.
+ p2 = p2 * viewport_size; // <- 'virtual' screen coordinates.
+
+ distance_along_line = distance(p1, p2);
+ }
+ gl_Position = v2 + (wdir * w2);
+ EmitVertex();
+
+ gl_Position = v2 - (wdir * w2);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl
new file mode 100644
index 00000000000..1497f9eeeb1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl
@@ -0,0 +1,10 @@
+
+in float colorGradient;
+in vec4 finalColor;
+
+out vec4 fragColor;
+
+void main() {
+ fragColor = finalColor;
+ fragColor.a *= smoothstep(1.0, 0.1, abs(colorGradient));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
new file mode 100644
index 00000000000..4a9f5f94321
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
@@ -0,0 +1,107 @@
+/**
+ * 2D Quadratic Bezier thick line drawing
+ **/
+
+#define MID_VERTEX 57
+
+/* u is position along the curve, defining the tangent space.
+ * v is "signed" distance (compressed to [0..1] range) from the pos in expand direction */
+in vec2 uv;
+in vec2 pos; /* verts position in the curve tangent space */
+in vec2 expand;
+
+#ifdef USE_INSTANCE
+/* Instance attrib */
+in vec2 P0;
+in vec2 P1;
+in vec2 P2;
+in vec2 P3;
+in ivec4 colid_doarrow;
+
+uniform vec4 colors[6];
+
+#define colStart colors[colid_doarrow[0]]
+#define colEnd colors[colid_doarrow[1]]
+#define colShadow colors[colid_doarrow[2]]
+#define doArrow (colid_doarrow[3] != 0)
+
+#else
+/* Single curve drawcall, use uniform. */
+uniform vec2 bezierPts[4];
+
+#define P0 bezierPts[0]
+#define P1 bezierPts[1]
+#define P2 bezierPts[2]
+#define P3 bezierPts[3]
+
+uniform vec4 colors[3];
+uniform bool doArrow;
+
+#define colShadow colors[0]
+#define colStart colors[1]
+#define colEnd colors[2]
+
+#endif
+
+uniform float expandSize;
+uniform float arrowSize;
+uniform mat4 ModelViewProjectionMatrix;
+
+out float colorGradient;
+out vec4 finalColor;
+
+void main(void)
+{
+ float t = uv.x;
+ float t2 = t * t;
+ float t2_3 = 3.0 * t2;
+ float one_minus_t = 1.0 - t;
+ float one_minus_t2 = one_minus_t * one_minus_t;
+ float one_minus_t2_3 = 3.0 * one_minus_t2;
+
+ vec2 point = (P0 * one_minus_t2 * one_minus_t +
+ P1 * one_minus_t2_3 * t +
+ P2 * t2_3 * one_minus_t +
+ P3 * t2 * t);
+
+ vec2 tangent = ((P1 - P0) * one_minus_t2_3 +
+ (P2 - P1) * 6.0 * (t - t2) +
+ (P3 - P2) * t2_3);
+
+ /* tangent space at t */
+ tangent = normalize(tangent);
+ vec2 normal = tangent.yx * vec2(-1.0, 1.0);
+
+ /* Position vertex on the curve tangent space */
+ point += (pos.x * tangent + pos.y * normal) * arrowSize;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(point, 0.0, 1.0);
+
+ vec2 exp_axis = expand.x * tangent + expand.y * normal;
+
+ /* rotate & scale the expand axis */
+ exp_axis = ModelViewProjectionMatrix[0].xy * exp_axis.xx +
+ ModelViewProjectionMatrix[1].xy * exp_axis.yy;
+
+
+ float expand_dist = (uv.y * 2.0 - 1.0);
+ colorGradient = expand_dist;
+
+ if (gl_VertexID < MID_VERTEX) {
+ /* Shadow pass */
+ finalColor = colShadow;
+ }
+ else {
+ /* Second pass */
+ finalColor = mix(colStart, colEnd, uv.x);
+ expand_dist *= 0.5;
+ }
+
+ /* Expand into a line */
+ gl_Position.xy += exp_axis * expandSize * expand_dist;
+
+ /* if arrow */
+ if (expand.y != 1.0 && !doArrow) {
+ gl_Position.xy *= 0.0;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl
new file mode 100644
index 00000000000..1f833cfb7be
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl
@@ -0,0 +1,21 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+
+in vec2 pos;
+out vec2 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl
new file mode 100644
index 00000000000..99bdeb22904
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl
@@ -0,0 +1,24 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+uniform float outlineWidth;
+
+in vec2 pos;
+out vec4 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl
new file mode 100644
index 00000000000..5fad95236df
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl
@@ -0,0 +1,27 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+uniform float outlineWidth;
+
+in vec2 pos;
+in vec4 color;
+out vec4 radii;
+out vec4 fillColor;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+ fillColor = color;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl
new file mode 100644
index 00000000000..d6aacf0cdc5
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl
@@ -0,0 +1,14 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+in float size;
+in vec4 color;
+out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ gl_PointSize = size;
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl
new file mode 100644
index 00000000000..145ed16248a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl
@@ -0,0 +1,20 @@
+
+noperspective in vec4 finalColor;
+out vec4 fragColor;
+
+/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */
+#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0))
+const vec4 dither_mat4x4[4] = vec4[4](
+ vec4( P(0.0), P(8.0), P(2.0), P(10.0)),
+ vec4(P(12.0), P(4.0), P(14.0), P(6.0)),
+ vec4( P(3.0), P(11.0), P(1.0), P(9.0)),
+ vec4(P(15.0), P(7.0), P(13.0), P(5.0))
+);
+
+void main()
+{
+ ivec2 tx1 = ivec2(gl_FragCoord.xy) % 4;
+ ivec2 tx2 = ivec2(gl_FragCoord.xy) % 2;
+ float dither_noise = dither_mat4x4[tx1.x][tx1.y];
+ fragColor = finalColor + dither_noise;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl
new file mode 100644
index 00000000000..4a4bfb6a616
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl
@@ -0,0 +1,8 @@
+
+noperspective in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl
new file mode 100644
index 00000000000..fe91f4d0902
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+in vec4 color;
+
+noperspective out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl
new file mode 100644
index 00000000000..89e3c52f9f8
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl
@@ -0,0 +1,9 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 pos;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
new file mode 100644
index 00000000000..a356014d025
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl
@@ -0,0 +1,40 @@
+uniform vec3 checkerColorAndSize;
+
+noperspective in vec4 finalColor;
+noperspective in float butCo;
+flat in float discardFac;
+
+out vec4 fragColor;
+
+vec4 do_checkerboard()
+{
+ float size = checkerColorAndSize.z;
+ vec2 phase = mod(gl_FragCoord.xy, size * 2.0);
+
+ if ((phase.x > size && phase.y < size) ||
+ (phase.x < size && phase.y > size))
+ {
+ return vec4(checkerColorAndSize.xxx, 1.0);
+ }
+ else {
+ return vec4(checkerColorAndSize.yyy, 1.0);
+ }
+}
+
+void main()
+{
+ if (min(1.0, -butCo) > discardFac) {
+ discard;
+ }
+
+ fragColor = finalColor;
+
+ if (butCo > 0.5) {
+ vec4 checker = do_checkerboard();
+ fragColor = mix(checker, fragColor, fragColor.a);
+ }
+
+ if (butCo > 0.0) {
+ fragColor.a = 1.0;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
new file mode 100644
index 00000000000..dcd23413c77
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl
@@ -0,0 +1,202 @@
+#define BIT_RANGE(x) uint((1 << x) - 1)
+
+/* 2 bits for corner */
+/* Attention! Not the same order as in UI_interface.h!
+ * Ordered by drawing order. */
+#define BOTTOM_LEFT 0u
+#define BOTTOM_RIGHT 1u
+#define TOP_RIGHT 2u
+#define TOP_LEFT 3u
+#define CNR_FLAG_RANGE BIT_RANGE(2)
+
+/* 4bits for corner id */
+#define CORNER_VEC_OFS 2u
+#define CORNER_VEC_RANGE BIT_RANGE(4)
+const vec2 cornervec[36] = vec2[36](
+ vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0),
+ vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0),
+ vec2(0.0, -1.0), vec2(-0.02, -0.805), vec2(-0.067, -0.617), vec2(-0.169, -0.45), vec2(-0.293, -0.293), vec2(-0.45, -0.169), vec2(-0.617, -0.076), vec2(-0.805, -0.02), vec2(-1.0, 0.0),
+ vec2(1.0, 0.0), vec2(0.805, -0.02), vec2(0.617, -0.067), vec2(0.45, -0.169), vec2(0.293, -0.293), vec2(0.169, -0.45), vec2(0.076, -0.617), vec2(0.02, -0.805), vec2(0.0, -1.0)
+);
+
+/* 4bits for jitter id */
+#define JIT_OFS 6u
+#define JIT_RANGE BIT_RANGE(4)
+const vec2 jit[9] = vec2[9](
+ vec2( 0.468813, -0.481430), vec2(-0.155755, -0.352820),
+ vec2( 0.219306, -0.238501), vec2(-0.393286, -0.110949),
+ vec2(-0.024699, 0.013908), vec2( 0.343805, 0.147431),
+ vec2(-0.272855, 0.269918), vec2( 0.095909, 0.388710),
+ vec2( 0.0, 0.0)
+);
+
+/* 2bits for other flags */
+#define INNER_FLAG uint(1 << 10) /* is inner vert */
+#define EMBOSS_FLAG uint(1 << 11) /* is emboss vert */
+
+/* 2bits for color */
+#define COLOR_OFS 12u
+#define COLOR_RANGE BIT_RANGE(2)
+#define COLOR_INNER 0u
+#define COLOR_EDGE 1u
+#define COLOR_EMBOSS 2u
+
+/* 2bits for trias type */
+#define TRIA_FLAG uint(1 << 14) /* is tria vert */
+#define TRIA_FIRST INNER_FLAG /* is first tria (reuse INNER_FLAG) */
+
+/* We can reuse the CORNER_* bits for tria */
+#define TRIA_VEC_RANGE BIT_RANGE(6)
+const vec2 triavec[37] = vec2[37](
+ /* ROUNDBOX_TRIA_ARROWS */
+ vec2(-0.352077, 0.532607), vec2(-0.352077, -0.549313), vec2( 0.330000, -0.008353),
+ vec2( 0.352077, 0.532607), vec2( 0.352077, -0.549313), vec2(-0.330000, -0.008353),
+ /* ROUNDBOX_TRIA_SCROLL - circle tria (triangle strip) */
+ vec2(0.000000, 1.000000),
+ vec2(0.382684, 0.923879), vec2(-0.382683, 0.923880),
+ vec2(0.707107, 0.707107), vec2(-0.707107, 0.707107),
+ vec2(0.923879, 0.382684), vec2(-0.923879, 0.382684),
+ vec2(1.000000, 0.000000), vec2(-1.000000, 0.000000),
+ vec2(0.923879, -0.382684), vec2(-0.923879, -0.382684),
+ vec2(0.707107, -0.707107), vec2(-0.707107, -0.707107),
+ vec2(0.382684, -0.923879), vec2(-0.382683, -0.923880),
+ vec2(0.000000, -1.000000),
+ /* ROUNDBOX_TRIA_MENU - menu arrows */
+ vec2(-0.33, 0.16), vec2(0.33, 0.16), vec2(0.0, 0.82),
+ vec2(0.0, -0.82), vec2(-0.33, -0.16), vec2(0.33, -0.16),
+ /* ROUNDBOX_TRIA_CHECK - check mark */
+ vec2(-0.578579, 0.253369), vec2(-0.392773, 0.412794), vec2(-0.004241, -0.328551),
+ vec2(-0.003001, 0.034320), vec2(1.055313, 0.864744), vec2(0.866408, 1.026895),
+ /* ROUNDBOX_TRIA_HOLD_ACTION_ARROW - hold action arrows */
+#define OY (-0.2 / 2)
+#define SC (0.35 * 2)
+// vec2(-0.5 + SC, 1.0 + OY), vec2( 0.5, 1.0 + OY), vec2( 0.5, 0.0 + OY + SC),
+ vec2( 0.5 - SC, 1.0 + OY), vec2(-0.5, 1.0 + OY), vec2(-0.5, 0.0 + OY + SC)
+#undef OY
+#undef SC
+);
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#define MAX_PARAM 11
+#ifdef USE_INSTANCE
+#define MAX_INSTANCE 6
+uniform vec4 parameters[MAX_PARAM * MAX_INSTANCE];
+#else
+uniform vec4 parameters[MAX_PARAM];
+#endif
+
+/* gl_InstanceID is 0 if not drawing instances. */
+#define recti parameters[gl_InstanceID * MAX_PARAM + 0]
+#define rect parameters[gl_InstanceID * MAX_PARAM + 1]
+#define radsi parameters[gl_InstanceID * MAX_PARAM + 2].x
+#define rads parameters[gl_InstanceID * MAX_PARAM + 2].y
+#define faci parameters[gl_InstanceID * MAX_PARAM + 2].zw
+#define roundCorners parameters[gl_InstanceID * MAX_PARAM + 3]
+#define colorInner1 parameters[gl_InstanceID * MAX_PARAM + 4]
+#define colorInner2 parameters[gl_InstanceID * MAX_PARAM + 5]
+#define colorEdge parameters[gl_InstanceID * MAX_PARAM + 6]
+#define colorEmboss parameters[gl_InstanceID * MAX_PARAM + 7]
+#define colorTria parameters[gl_InstanceID * MAX_PARAM + 8]
+#define tria1Center parameters[gl_InstanceID * MAX_PARAM + 9].xy
+#define tria2Center parameters[gl_InstanceID * MAX_PARAM + 9].zw
+#define tria1Size parameters[gl_InstanceID * MAX_PARAM + 10].x
+#define tria2Size parameters[gl_InstanceID * MAX_PARAM + 10].y
+#define shadeDir parameters[gl_InstanceID * MAX_PARAM + 10].z
+#define alphaDiscard parameters[gl_InstanceID * MAX_PARAM + 10].w
+
+/* We encode alpha check and discard factor together. */
+#define doAlphaCheck (alphaDiscard < 0.0)
+#define discardFactor abs(alphaDiscard)
+
+in uint vflag;
+
+noperspective out vec4 finalColor;
+noperspective out float butCo;
+flat out float discardFac;
+
+vec2 do_widget(void)
+{
+ uint cflag = vflag & CNR_FLAG_RANGE;
+ uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE;
+
+ vec2 v = cornervec[cflag * 9u + vofs];
+
+ bool is_inner = (vflag & INNER_FLAG) != 0u;
+
+ /* Scale by corner radius */
+ v *= roundCorners[cflag] * ((is_inner) ? radsi : rads);
+
+ /* Position to corner */
+ vec4 rct = (is_inner) ? recti : rect;
+ if (cflag == BOTTOM_LEFT)
+ v += rct.xz;
+ else if (cflag == BOTTOM_RIGHT)
+ v += rct.yz;
+ else if (cflag == TOP_RIGHT)
+ v += rct.yw;
+ else /* (cflag == TOP_LEFT) */
+ v += rct.xw;
+
+ vec2 uv = faci * (v - recti.xz);
+
+ /* compute uv and color gradient */
+ uint color_id = (vflag >> COLOR_OFS) & COLOR_RANGE;
+ if (color_id == COLOR_INNER) {
+ float fac = clamp((shadeDir > 0.0) ? uv.y : uv.x, 0.0, 1.0);
+
+ if (doAlphaCheck) {
+ finalColor = colorInner1;
+ butCo = uv.x;
+ }
+ else {
+ finalColor = mix(colorInner2, colorInner1, fac);
+ butCo = -abs(uv.x);
+ }
+ }
+ else if (color_id == COLOR_EDGE) {
+ finalColor = colorEdge;
+ butCo = -abs(uv.x);
+ }
+ else /* (color_id == COLOR_EMBOSS) */ {
+ finalColor = colorEmboss;
+ butCo = -abs(uv.x);
+ }
+
+ bool is_emboss = (vflag & EMBOSS_FLAG) != 0u;
+ v.y -= (is_emboss) ? 1.0f : 0.0;
+
+ return v;
+}
+
+vec2 do_tria()
+{
+ uint vofs = vflag & TRIA_VEC_RANGE;
+
+ vec2 v = triavec[vofs];
+
+ finalColor = colorTria;
+ butCo = -1.0;
+
+ bool is_tria_first = (vflag & TRIA_FIRST) != 0u;
+
+ if (is_tria_first)
+ v = v * tria1Size + tria1Center;
+ else
+ v = v * tria2Size + tria2Center;
+
+ return v;
+}
+
+void main()
+{
+ discardFac = discardFactor;
+ bool is_tria = (vflag & TRIA_FLAG) != 0u;
+
+ vec2 v = (is_tria) ? do_tria() : do_widget();
+
+ /* Antialiasing offset */
+ v += jit[(vflag >> JIT_OFS) & JIT_RANGE];
+
+ gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl
new file mode 100644
index 00000000000..fc4d055a903
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl
@@ -0,0 +1,13 @@
+
+in float shadowFalloff;
+
+out vec4 fragColor;
+
+uniform float alpha;
+
+void main()
+{
+ fragColor = vec4(0.0);
+ /* Manual curve fit of the falloff curve of previous drawing method. */
+ fragColor.a = alpha * (shadowFalloff * shadowFalloff * 0.722 + shadowFalloff * 0.277);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl
new file mode 100644
index 00000000000..f6be496ac4f
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl
@@ -0,0 +1,64 @@
+#define BIT_RANGE(x) uint((1 << x) - 1)
+
+/* 2 bits for corner */
+/* Attention! Not the same order as in UI_interface.h!
+ * Ordered by drawing order. */
+#define BOTTOM_LEFT 0u
+#define BOTTOM_RIGHT 1u
+#define TOP_RIGHT 2u
+#define TOP_LEFT 3u
+#define CNR_FLAG_RANGE BIT_RANGE(2)
+
+/* 4bits for corner id */
+#define CORNER_VEC_OFS 2u
+#define CORNER_VEC_RANGE BIT_RANGE(4)
+const vec2 cornervec[36] = vec2[36](
+ vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0),
+ vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0),
+ vec2(0.0, -1.0), vec2(-0.02, -0.805), vec2(-0.067, -0.617), vec2(-0.169, -0.45), vec2(-0.293, -0.293), vec2(-0.45, -0.169), vec2(-0.617, -0.076), vec2(-0.805, -0.02), vec2(-1.0, 0.0),
+ vec2(1.0, 0.0), vec2(0.805, -0.02), vec2(0.617, -0.067), vec2(0.45, -0.169), vec2(0.293, -0.293), vec2(0.169, -0.45), vec2(0.076, -0.617), vec2(0.02, -0.805), vec2(0.0, -1.0)
+);
+
+#define INNER_FLAG uint(1 << 10) /* is inner vert */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform vec4 parameters[4];
+/* radi and rad per corner */
+#define recti parameters[0]
+#define rect parameters[1]
+#define radsi parameters[2].x
+#define rads parameters[2].y
+#define roundCorners parameters[3]
+
+in uint vflag;
+
+out float shadowFalloff;
+
+void main()
+{
+ uint cflag = vflag & CNR_FLAG_RANGE;
+ uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE;
+
+ vec2 v = cornervec[cflag * 9u + vofs];
+
+ bool is_inner = (vflag & INNER_FLAG) != 0u;
+
+ shadowFalloff = (is_inner) ? 1.0 : 0.0;
+
+ /* Scale by corner radius */
+ v *= roundCorners[cflag] * ((is_inner) ? radsi : rads);
+
+ /* Position to corner */
+ vec4 rct = (is_inner) ? recti : rect;
+ if (cflag == BOTTOM_LEFT)
+ v += rct.xz;
+ else if (cflag == BOTTOM_RIGHT)
+ v += rct.yz;
+ else if (cflag == TOP_RIGHT)
+ v += rct.yw;
+ else /* (cflag == TOP_LEFT) */
+ v += rct.xw;
+
+ gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl
new file mode 100644
index 00000000000..84e44837264
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl
@@ -0,0 +1,12 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ModelMatrix;
+uniform vec4 ClipPlane;
+
+in vec3 pos;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_ClipDistance[0] = dot(ModelMatrix * vec4(pos, 1.0), ClipPlane);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl
new file mode 100644
index 00000000000..7db7e28d8e6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl
@@ -0,0 +1,26 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+#if defined(USE_COLOR_U32)
+in uint color;
+#else
+in vec4 color;
+#endif
+
+flat out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+#if defined(USE_COLOR_U32)
+ finalColor = vec4(
+ ((color ) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 8) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 16) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 24) ) * (1.0f / 255.0f));
+#else
+ finalColor = color;
+#endif
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl
new file mode 100644
index 00000000000..f16fa21b342
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl
@@ -0,0 +1,16 @@
+
+/* Make to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ViewProjectionMatrix;
+
+layout(points) in;
+layout(line_strip, max_vertices = 2) out;
+
+void main()
+{
+ vec3 vert = gl_in[0].gl_Position.xyz;
+ gl_Position = ViewProjectionMatrix * vec4(vert.xyz, 1.0);
+ EmitVertex();
+ gl_Position = ViewProjectionMatrix * vec4(vert.xy, 0.0, 1.0);
+ EmitVertex();
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl
new file mode 100644
index 00000000000..55f410eb25d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl
@@ -0,0 +1,11 @@
+
+/* Made to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ViewProjectionMatrix;
+
+in vec3 pos;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * vec4(pos.xy, 0.0, 1.0);
+ gl_PointSize = 2.0;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl
new file mode 100644
index 00000000000..eb877ab20b6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl
@@ -0,0 +1,12 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec2 texCoord;
+in vec3 pos;
+out vec2 texCoord_interp;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos.xyz, 1.0f);
+ texCoord_interp = texCoord;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl
new file mode 100644
index 00000000000..84fbf977846
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl
@@ -0,0 +1,26 @@
+
+/*
+ * Vertex Shader for dashed lines with 3D coordinates, with uniform multi-colors or uniform single-color,
+ * and unary thickness.
+ *
+ * Legacy version, without geometry shader support, always produce solid lines!
+ */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewport_size;
+
+uniform vec4 color;
+
+in vec3 pos;
+noperspective out float distance_along_line;
+noperspective out vec4 color_geom;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ /* Hack - prevent stupid GLSL compiler to optimize out unused viewport_size uniform, which gives crash! */
+ distance_along_line = viewport_size.x * 0.000001f - viewport_size.x * 0.0000009f;
+
+ color_geom = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl
new file mode 100644
index 00000000000..2fe08896585
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl
@@ -0,0 +1,21 @@
+
+/*
+ * Vertex Shader for dashed lines with 3D coordinates, with uniform multi-colors or uniform single-color,
+ * and unary thickness.
+ *
+ * Dashed is performed in screen space.
+ */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+uniform vec4 color;
+
+in vec3 pos;
+
+out vec4 color_vert;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ color_vert = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl
new file mode 100644
index 00000000000..e6b8fed7265
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl
@@ -0,0 +1,22 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 pos;
+in vec3 nor;
+in vec4 color;
+
+#ifdef USE_FLAT_NORMAL
+flat out vec3 normal;
+flat out vec4 finalColor;
+#else
+out vec3 normal;
+out vec4 finalColor;
+#endif
+
+void main()
+{
+ normal = normalize(NormalMatrix * nor);
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl
new file mode 100644
index 00000000000..a3f447a85f9
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 pos;
+in vec3 nor;
+out vec3 normal;
+
+void main()
+{
+ normal = normalize(NormalMatrix * nor);
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl
new file mode 100644
index 00000000000..60793bf56b6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl
@@ -0,0 +1,8 @@
+
+/* Does Nothing */
+in vec3 pos;
+
+void main()
+{
+ gl_Position = vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl
new file mode 100644
index 00000000000..2fe9c0623fa
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl
@@ -0,0 +1,12 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 color;
+out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl
new file mode 100644
index 00000000000..ebc945fcf35
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl
@@ -0,0 +1,21 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+
+in vec3 pos;
+out vec2 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl
new file mode 100644
index 00000000000..0d6b90cfba4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl
@@ -0,0 +1,24 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform float size;
+uniform float outlineWidth;
+
+in vec3 pos;
+out vec4 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * size;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - 1.0;
+ radii[2] = radius - outlineWidth;
+ radii[3] = radius - outlineWidth - 1.0;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl
new file mode 100644
index 00000000000..e14b9535c89
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl
@@ -0,0 +1,14 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in float size;
+in vec4 color;
+out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl
new file mode 100644
index 00000000000..e4f173ab617
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl
@@ -0,0 +1,11 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in float size;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl
new file mode 100644
index 00000000000..41fdefd22e8
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl
@@ -0,0 +1,8 @@
+
+in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl
new file mode 100644
index 00000000000..a1feb2f75b7
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 color;
+
+out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl
new file mode 100644
index 00000000000..059473ebb74
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl
@@ -0,0 +1,9 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
index 01a335af048..5f7455582cd 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
@@ -20,12 +20,10 @@
#define STIPPLE_HEXAGON 3
#define STIPPLE_DIAG_STRIPES 4
#define STIPPLE_DIAG_STRIPES_SWAP 5
-#define STIPPLE_S3D_INTERLACE_ROW 6
-#define STIPPLE_S3D_INTERLACE_ROW_SWAP 7
-#define STIPPLE_S3D_INTERLACE_COLUMN 8
-#define STIPPLE_S3D_INTERLACE_COLUMN_SWAP 9
-#define STIPPLE_S3D_INTERLACE_CHECKERBOARD 10
-#define STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP 11
+
+#ifndef NO_SPECULAR
+uniform mat4 ProjectionMatrix;
+#endif
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
#if defined(USE_FLAT_NORMAL)
@@ -58,7 +56,7 @@ uniform sampler2D_default texture_map;
#ifdef USE_STIPPLE
uniform int stipple_id;
#if defined(DRAW_LINE)
-varying in float t;
+varying float t;
uniform int stipple_pattern;
#endif
#endif
@@ -74,14 +72,9 @@ void main()
/* We have to use mod function and integer casting.
* This can be optimized further with the bitwise operations
* when GLSL 1.3 is supported. */
- if (stipple_id == STIPPLE_HALFTONE ||
- stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD ||
- stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP)
- {
+ if (stipple_id == STIPPLE_HALFTONE) {
int result = int(mod(gl_FragCoord.x + gl_FragCoord.y, 2));
bool dis = result == 0;
- if (stipple_id == STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP)
- dis = !dis;
if (dis)
discard;
}
@@ -116,22 +109,6 @@ void main()
if (!((16 - modx > mody && mody > 8 - modx) || mody > 24 - modx))
discard;
}
- else if (stipple_id == STIPPLE_S3D_INTERLACE_ROW || stipple_id == STIPPLE_S3D_INTERLACE_ROW_SWAP) {
- int result = int(mod(gl_FragCoord.y, 2));
- bool dis = result == 0;
- if (stipple_id == STIPPLE_S3D_INTERLACE_ROW_SWAP)
- dis = !dis;
- if (dis)
- discard;
- }
- else if (stipple_id == STIPPLE_S3D_INTERLACE_COLUMN || stipple_id == STIPPLE_S3D_INTERLACE_COLUMN_SWAP) {
- int result = int(mod(gl_FragCoord.x, 2));
- bool dis = result != 0;
- if (stipple_id == STIPPLE_S3D_INTERLACE_COLUMN_SWAP)
- dis = !dis;
- if (dis)
- discard;
- }
else if (stipple_id == STIPPLE_HEXAGON) {
int mody = int(mod(gl_FragCoord.y, 2));
int modx = int(mod(gl_FragCoord.x, 4));
@@ -190,7 +167,7 @@ void main()
#ifndef NO_SPECULAR
/* view vector computation, depends on orthographics or perspective */
- vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0);
+ vec3 V = (ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0);
#endif
for (int i = 0; i < NUM_SCENE_LIGHTS; i++) {
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl b/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
index a88681a5fd3..13f05b340bf 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
@@ -14,9 +14,9 @@ layout(line_strip, max_vertices = 10) out;
layout(triangle_strip, max_vertices = 6) out;
#endif
-varying out float t;
-varying in vec4 varying_vertex_color_line[];
-varying out vec4 varying_vertex_color;
+out float t;
+in vec4 varying_vertex_color_line[];
+out vec4 varying_vertex_color;
uniform ivec4 viewport;
uniform float line_width;
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
index 42fbdadf1d1..dbf6c267f14 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
@@ -1,4 +1,8 @@
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat3 NormalMatrix;
+
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
#if defined(USE_FLAT_NORMAL)
varying vec3 eyespace_vert_pos;
@@ -29,15 +33,15 @@ varying float gl_ClipDistance[6];
void main()
{
- vec4 co = gl_ModelViewMatrix * gl_Vertex;
+ vec4 co = ModelViewMatrix * gl_Vertex;
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
#if !defined(USE_FLAT_NORMAL)
- varying_normal = normalize(gl_NormalMatrix * gl_Normal);
+ varying_normal = normalize(NormalMatrix * gl_Normal);
#endif
#if defined(USE_FLAT_NORMAL)
/* transform vertex into eyespace */
- eyespace_vert_pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
+ eyespace_vert_pos = (ModelViewMatrix * gl_Vertex).xyz;
#endif
#ifndef USE_SOLID_LIGHTING
@@ -45,7 +49,7 @@ void main()
#endif
#endif
- gl_Position = gl_ProjectionMatrix * co;
+ gl_Position = ProjectionMatrix * co;
#ifdef CLIP_WORKAROUND
int i;
diff --git a/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl b/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl
new file mode 100644
index 00000000000..545f6d19e21
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl
@@ -0,0 +1,20 @@
+
+uniform vec4 color1;
+uniform vec4 color2;
+uniform int size;
+
+out vec4 fragColor;
+
+void main()
+{
+ vec2 phase = mod(gl_FragCoord.xy, (size*2));
+
+ if ((phase.x > size && phase.y < size) ||
+ (phase.x < size && phase.y > size))
+ {
+ fragColor = color1;
+ }
+ else {
+ fragColor = color2;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl b/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl
new file mode 100644
index 00000000000..60e71e19004
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl
@@ -0,0 +1,6 @@
+
+void main()
+{
+ // no color output, only depth (line below is implicit)
+ // gl_FragDepth = gl_FragCoord.z;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl
new file mode 100644
index 00000000000..beb71c58100
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl
@@ -0,0 +1,20 @@
+
+uniform vec4 color1;
+uniform vec4 color2;
+uniform int size1;
+uniform int size2;
+
+out vec4 fragColor;
+
+void main()
+{
+ float phase = mod((gl_FragCoord.x + gl_FragCoord.y), (size1 + size2));
+
+ if (phase < size1)
+ {
+ fragColor = color1;
+ }
+ else {
+ fragColor = color2;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl
new file mode 100644
index 00000000000..4ed7ed56c11
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl
@@ -0,0 +1,54 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+uniform bool drawFront = true;
+uniform bool drawBack = true;
+uniform bool drawSilhouette = true;
+
+uniform vec4 frontColor;
+uniform vec4 backColor;
+uniform vec4 silhouetteColor;
+
+uniform vec3 eye; // direction we are looking
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+
+// normals of faces this edge joins (object coords)
+in vec3 N1;
+in vec3 N2;
+
+flat out vec4 finalColor;
+
+// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
+
+// to discard an entire line, set both endpoints to nowhere
+// and it won't produce any fragments
+const vec4 nowhere = vec4(vec3(0.0), 1.0);
+
+void main()
+{
+ bool face_1_front = dot(N1, eye) > 0.0;
+ bool face_2_front = dot(N2, eye) > 0.0;
+
+ vec4 position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ if (face_1_front && face_2_front) {
+ // front-facing edge
+ gl_Position = drawFront ? position : nowhere;
+ finalColor = frontColor;
+ }
+ else if (face_1_front || face_2_front) {
+ // exactly one face is front-facing, silhouette edge
+ gl_Position = drawSilhouette ? position : nowhere;
+ finalColor = silhouetteColor;
+ }
+ else {
+ // back-facing edge
+ gl_Position = drawBack ? position : nowhere;
+ finalColor = backColor;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl
new file mode 100644
index 00000000000..e7632fcad15
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl
@@ -0,0 +1,60 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. This geometry shader
+// decides which edge type to use if endpoints disagree.
+
+uniform mat4 ProjectionMatrix;
+
+uniform bool drawFront = true;
+uniform bool drawBack = true;
+uniform bool drawSilhouette = true;
+
+uniform vec4 frontColor;
+uniform vec4 backColor;
+uniform vec4 silhouetteColor;
+
+layout(lines) in;
+layout(line_strip, max_vertices = 2) out;
+
+in vec4 MV_pos[];
+in float edgeClass[];
+
+flat out vec4 finalColor;
+
+void emitLine(vec4 color)
+{
+ gl_Position = ProjectionMatrix * MV_pos[0];
+ EmitVertex();
+ gl_Position = ProjectionMatrix * MV_pos[1];
+ finalColor = color;
+ EmitVertex();
+ EndPrimitive();
+}
+
+void main()
+{
+ float finalEdgeClass = max(edgeClass[0], edgeClass[1]);
+
+ if (finalEdgeClass > 0.0f) {
+ // front-facing edge
+ if (drawFront)
+ emitLine(frontColor);
+ }
+ else if (finalEdgeClass < 0.0f) {
+ // back-facing edge
+ if (drawBack)
+ emitLine(backColor);
+ }
+ else {
+ // exactly one face is front-facing, silhouette edge
+ if (drawSilhouette)
+ emitLine(silhouetteColor);
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl
new file mode 100644
index 00000000000..30b3bdb890d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl
@@ -0,0 +1,68 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// This shader is an imperfect stepping stone until all platforms are
+// ready for geometry shaders.
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. Need to use a geometry
+// shader or pass in an extra position attribute (the other endpoint)
+// to do this properly.
+
+uniform bool drawFront = true;
+uniform bool drawBack = true;
+uniform bool drawSilhouette = true;
+
+uniform vec4 frontColor;
+uniform vec4 backColor;
+uniform vec4 silhouetteColor;
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 pos;
+
+// normals of faces this edge joins (object coords)
+in vec3 N1;
+in vec3 N2;
+
+flat out vec4 finalColor;
+
+// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
+
+// to discard an entire line, set its color to invisible
+// (must have GL_BLEND enabled, or discard in fragment shader)
+const vec4 invisible = vec4(0.0);
+
+bool front(vec3 N)
+{
+ vec4 xformed = ModelViewMatrix * vec4(pos, 1.0);
+ return dot(NormalMatrix * N, normalize(-xformed.xyz)) > 0.0;
+}
+
+void main()
+{
+ bool face_1_front = front(N1);
+ bool face_2_front = front(N2);
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ if (face_1_front && face_2_front) {
+ // front-facing edge
+ finalColor = drawFront ? frontColor : invisible;
+ }
+ else if (face_1_front || face_2_front) {
+ // exactly one face is front-facing, silhouette edge
+ finalColor = drawSilhouette ? silhouetteColor : invisible;
+ }
+ else {
+ // back-facing edge
+ finalColor = drawBack ? backColor : invisible;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl
new file mode 100644
index 00000000000..e1fb78dd1a9
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl
@@ -0,0 +1,44 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. We use a geometry
+// shader to resolve this properly.
+
+uniform mat4 ModelViewMatrix;
+uniform mat3 NormalMatrix;
+
+in vec3 pos;
+in vec3 N1, N2; // normals of faces this edge joins (object coords)
+
+out vec4 MV_pos;
+out float edgeClass;
+
+// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
+
+bool front(vec3 N, vec3 eye)
+{
+ return dot(NormalMatrix * N, eye) > 0.0;
+}
+
+void main()
+{
+ MV_pos = ModelViewMatrix * vec4(pos, 1.0);
+
+ vec3 eye = normalize(-MV_pos.xyz);
+
+ bool face_1_front = front(N1, eye);
+ bool face_2_front = front(N2, eye);
+
+ if (face_1_front && face_2_front)
+ edgeClass = 1.0; // front-facing edge
+ else if (face_1_front || face_2_front)
+ edgeClass = 0.0; // exactly one face is front-facing, silhouette edge
+ else
+ edgeClass = -1.0; // back-facing edge
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl
new file mode 100644
index 00000000000..0538c037dcf
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl
@@ -0,0 +1,20 @@
+
+#define SMOOTH 1
+
+const float transitionWidth = 1.0;
+
+uniform vec4 fillColor = vec4(0);
+uniform vec4 outlineColor = vec4(0,0,0,1);
+
+noperspective in vec3 distanceToOutline;
+
+out vec4 FragColor;
+
+void main() {
+ float edgeness = min(min(distanceToOutline.x, distanceToOutline.y), distanceToOutline.z);
+#if SMOOTH
+ FragColor = mix(outlineColor, fillColor, smoothstep(0, transitionWidth, edgeness));
+#else
+ FragColor = (edgeness <= 0) ? outlineColor : fillColor;
+#endif
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl
new file mode 100644
index 00000000000..ad0dccb6c81
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl
@@ -0,0 +1,67 @@
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+
+uniform float outlineWidth = 1.0;
+uniform vec2 viewportSize;
+
+in vec4 pos_xformed[];
+in float widthModulator[];
+
+noperspective out vec3 distanceToOutline;
+
+// project to screen space
+vec2 proj(int axis) {
+ vec4 pos = pos_xformed[axis];
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+float dist(vec2 pos[3], int v) {
+ // current vertex position
+ vec2 vpos = pos[v];
+ // endpoints of opposite edge
+ vec2 e1 = pos[(v + 1) % 3];
+ vec2 e2 = pos[(v + 2) % 3];
+
+ float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify
+ return abs_det / distance(e2, e1);
+}
+
+vec3 distance[3];
+
+void clearEdge(int v) {
+ float distant = 10 * outlineWidth;
+ for (int i = 0; i < 3; ++i)
+ distance[i][v] += distant;
+}
+
+void modulateEdge(int v) {
+ float offset = min(widthModulator[v],1) * outlineWidth;
+ for (int i = 0; i < 3; ++i)
+ distance[i][v] -= offset;
+}
+
+void main() {
+ vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2));
+
+ for (int v = 0; v < 3; ++v)
+ distance[v] = vec3(0);
+
+ for (int v = 0; v < 3; ++v) {
+ if (widthModulator[v] > 0) {
+ distance[v][v] = dist(pos, v);
+ modulateEdge(v);
+ }
+ }
+
+ for (int v = 0; v < 3; ++v)
+ if (widthModulator[v] <= 0)
+ clearEdge(v);
+
+ for (int v = 0; v < 3; ++v) {
+ gl_Position = pos_xformed[v];
+ distanceToOutline = distance[v];
+ EmitVertex();
+ }
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl
new file mode 100644
index 00000000000..ec692e210c2
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl
@@ -0,0 +1,52 @@
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+
+uniform float outlineWidth = 1.0;
+uniform vec2 viewportSize;
+
+noperspective out vec3 distanceToOutline;
+
+// project to screen space
+vec2 proj(int axis) {
+ vec4 pos = gl_in[axis].gl_Position;
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+float dist(vec2 pos[3], int v) {
+ // current vertex position
+ vec2 vpos = pos[v];
+ // endpoints of opposite edge
+ vec2 e1 = pos[(v + 1) % 3];
+ vec2 e2 = pos[(v + 2) % 3];
+
+ float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify
+ return abs_det / distance(e2, e1);
+}
+
+vec3 distance[3];
+
+void modulateEdge(int v) {
+ float offset = 0.5 * outlineWidth;
+ for (int i = 0; i < 3; ++i)
+ distance[i][v] -= offset;
+}
+
+void main() {
+ vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2));
+
+ for (int v = 0; v < 3; ++v)
+ distance[v] = vec3(0);
+
+ for (int v = 0; v < 3; ++v) {
+ distance[v][v] = dist(pos, v);
+ modulateEdge(v);
+ }
+
+ for (int v = 0; v < 3; ++v) {
+ gl_Position = gl_in[v].gl_Position;
+ distanceToOutline = distance[v];
+ EmitVertex();
+ }
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl
new file mode 100644
index 00000000000..fb1d0aafe05
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in float edgeWidthModulator;
+
+out vec4 pos_xformed;
+out float widthModulator;
+
+void main() {
+ pos_xformed = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ widthModulator = edgeWidthModulator;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl
index 3819203bcd9..fc9cafb6b02 100644
--- a/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl
@@ -1,17 +1,15 @@
-varying vec3 coords;
+in vec3 coords;
+out vec4 fragColor;
uniform sampler3D flame_texture;
uniform sampler1D spectrum_texture;
void main()
{
- float flame = texture3D(flame_texture, coords).r;
- vec4 emission = texture1D(spectrum_texture, flame);
+ float flame = texture(flame_texture, coords).r;
+ vec4 emission = texture(spectrum_texture, flame);
- vec4 color;
- color.rgb = emission.a * emission.rgb;
- color.a = emission.a;
-
- gl_FragColor = color;
+ fragColor.rgb = emission.a * emission.rgb;
+ fragColor.a = emission.a;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl
new file mode 100644
index 00000000000..cefae1021d2
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl
@@ -0,0 +1,11 @@
+
+flat in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ if (finalColor.a > 0.0)
+ fragColor = finalColor;
+ else
+ discard;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
new file mode 100644
index 00000000000..d738ed5ddb2
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl
@@ -0,0 +1,8 @@
+
+flat in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_flat_id_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_id_frag.glsl
new file mode 100644
index 00000000000..aa6f30531ae
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_flat_id_frag.glsl
@@ -0,0 +1,8 @@
+
+flat in uint finalId;
+out uint fragId;
+
+void main()
+{
+ fragId = finalId;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
index e04cd7d3306..c4e7cff2b0b 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
@@ -1,9 +1,10 @@
uniform sampler2D depthbuffer;
-varying vec4 uvcoordsvar;
+
+in vec4 uvcoordsvar;
void main(void)
{
- float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+ float depth = texture(depthbuffer, uvcoordsvar.xy).r;
/* XRay background, discard */
if (depth >= 1.0) {
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
index 338ef6d51a7..15d30e75969 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
@@ -17,17 +17,18 @@ uniform vec4 dof_params;
uniform vec4 viewvecs[3];
// coordinates on framebuffer in normalized (0.0-1.0) uv space
-varying vec4 uvcoordsvar;
+in vec4 uvcoordsvar;
/* color texture coordinates, offset by a small amount */
-varying vec2 color_uv1;
-varying vec2 color_uv2;
+in vec2 color_uv1;
+in vec2 color_uv2;
-varying vec2 depth_uv1;
-varying vec2 depth_uv2;
-varying vec2 depth_uv3;
-varying vec2 depth_uv4;
+in vec2 depth_uv1;
+in vec2 depth_uv2;
+in vec2 depth_uv3;
+in vec2 depth_uv4;
+out vec4 FragColor;
float calculate_far_coc(in float zdepth)
{
@@ -63,85 +64,85 @@ void first_pass()
offset_row[2] = 3.0 * offset_row[0];
/* heavily blur the image */
- vec4 color = texture2D(colorbuffer, color_uv1);
- color += texture2D(colorbuffer, color_uv1 + offset_row[1]);
- color += texture2D(colorbuffer, color_uv2);
- color += texture2D(colorbuffer, color_uv2 + offset_row[1]);
+ vec4 color = texture(colorbuffer, color_uv1);
+ color += texture(colorbuffer, color_uv1 + offset_row[1]);
+ color += texture(colorbuffer, color_uv2);
+ color += texture(colorbuffer, color_uv2 + offset_row[1]);
color /= 4.0;
- depth.r = texture2D(depthbuffer, depth_uv1).r;
- depth.g = texture2D(depthbuffer, depth_uv2).r;
- depth.b = texture2D(depthbuffer, depth_uv3).r;
- depth.a = texture2D(depthbuffer, depth_uv4).r;
+ depth.r = texture(depthbuffer, depth_uv1).r;
+ depth.g = texture(depthbuffer, depth_uv2).r;
+ depth.b = texture(depthbuffer, depth_uv3).r;
+ depth.a = texture(depthbuffer, depth_uv4).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = calculate_near_coc(zdepth);
- depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[0]).r;
- depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[0]).r;
- depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[0]).r;
- depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[0]).r;
+ depth.r = texture(depthbuffer, depth_uv1 + offset_row[0]).r;
+ depth.g = texture(depthbuffer, depth_uv2 + offset_row[0]).r;
+ depth.b = texture(depthbuffer, depth_uv3 + offset_row[0]).r;
+ depth.a = texture(depthbuffer, depth_uv4 + offset_row[0]).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = max(calculate_near_coc(zdepth), coc);
- depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[1]).r;
- depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[1]).r;
- depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[1]).r;
- depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[1]).r;
+ depth.r = texture(depthbuffer, depth_uv1 + offset_row[1]).r;
+ depth.g = texture(depthbuffer, depth_uv2 + offset_row[1]).r;
+ depth.b = texture(depthbuffer, depth_uv3 + offset_row[1]).r;
+ depth.a = texture(depthbuffer, depth_uv4 + offset_row[1]).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = max(calculate_near_coc(zdepth), coc);
- depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[2]).r;
- depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[2]).r;
- depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[2]).r;
- depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[2]).r;
+ depth.r = texture(depthbuffer, depth_uv1 + offset_row[2]).r;
+ depth.g = texture(depthbuffer, depth_uv2 + offset_row[2]).r;
+ depth.b = texture(depthbuffer, depth_uv3 + offset_row[2]).r;
+ depth.a = texture(depthbuffer, depth_uv4 + offset_row[2]).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = max(calculate_near_coc(zdepth), coc);
final_coc = max(max(coc.x, coc.y), max(coc.z, coc.w));
- gl_FragColor = vec4(color.rgb, final_coc);
+ FragColor = vec4(color.rgb, final_coc);
}
/* second pass, gaussian blur the downsampled image */
void second_pass()
{
- vec4 depth = vec4(texture2D(depthbuffer, uvcoordsvar.xy).r);
+ vec4 depth = vec4(texture(depthbuffer, uvcoordsvar.xy).r);
/* clever sampling to sample 2 pixels at once. Of course it's not real gaussian sampling this way */
- vec4 color = texture2D(colorbuffer, uvcoordsvar.xy) * 0.3125;
- color += texture2D(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
- color += texture2D(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
- color += texture2D(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
- color += texture2D(colorbuffer, uvcoordsvar.xy - invrendertargetdim) * 0.234375;
- color += texture2D(colorbuffer, uvcoordsvar.xy - 2.5 * invrendertargetdim) * 0.09375;
- color += texture2D(colorbuffer, uvcoordsvar.xy - 4.5 * invrendertargetdim) * 0.015625;
-
- gl_FragColor = color;
+ vec4 color = texture(colorbuffer, uvcoordsvar.xy) * 0.3125;
+ color += texture(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
+ color += texture(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
+ color += texture(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
+ color += texture(colorbuffer, uvcoordsvar.xy - invrendertargetdim) * 0.234375;
+ color += texture(colorbuffer, uvcoordsvar.xy - 2.5 * invrendertargetdim) * 0.09375;
+ color += texture(colorbuffer, uvcoordsvar.xy - 4.5 * invrendertargetdim) * 0.015625;
+
+ FragColor = color;
}
/* third pass, calculate the final coc from blurred and unblurred images */
void third_pass()
{
- vec4 color = texture2D(colorbuffer, uvcoordsvar.xy);
- vec4 color_blurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
+ vec4 color = texture(colorbuffer, uvcoordsvar.xy);
+ vec4 color_blurred = texture(blurredcolorbuffer, uvcoordsvar.xy);
float coc = 2.0 * max(color_blurred.a, color.a); -color.a;
- gl_FragColor = vec4(color.rgb, coc);
+ FragColor = vec4(color.rgb, coc);
}
/* fourth pass, blur the final coc once to get rid of discontinuities */
void fourth_pass()
{
- vec4 color = texture2D(colorbuffer, uvcoordsvar.xz);
- color += texture2D(colorbuffer, uvcoordsvar.yz);
- color += texture2D(colorbuffer, uvcoordsvar.xw);
- color += texture2D(colorbuffer, uvcoordsvar.yw);
+ vec4 color = texture(colorbuffer, uvcoordsvar.xz);
+ color += texture(colorbuffer, uvcoordsvar.yz);
+ color += texture(colorbuffer, uvcoordsvar.xw);
+ color += texture(colorbuffer, uvcoordsvar.yw);
- gl_FragColor = color / 4.0;
+ FragColor = color / 4.0;
}
vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
@@ -150,10 +151,10 @@ vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
vec4 result = weight * color;
weight *= 4.0;
- result += weight * texture2D(colorbuffer, uv + color_uv1.xy);
- result += weight * texture2D(colorbuffer, uv - color_uv1.xy);
- result += weight * texture2D(colorbuffer, uv + color_uv1.yx);
- result += weight * texture2D(colorbuffer, uv - color_uv1.yx);
+ result += weight * texture(colorbuffer, uv + color_uv1.xy);
+ result += weight * texture(colorbuffer, uv - color_uv1.xy);
+ result += weight * texture(colorbuffer, uv + color_uv1.yx);
+ result += weight * texture(colorbuffer, uv - color_uv1.yx);
return result;
}
@@ -163,11 +164,11 @@ vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
void fifth_pass()
{
vec4 factors;
- vec4 color_orig = texture2D(colorbuffer, uvcoordsvar.xy);
- vec4 highblurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
- vec4 mediumblurred = texture2D(mblurredcolorbuffer, uvcoordsvar.xy);
+ vec4 color_orig = texture(colorbuffer, uvcoordsvar.xy);
+ vec4 highblurred = texture(blurredcolorbuffer, uvcoordsvar.xy);
+ vec4 mediumblurred = texture(mblurredcolorbuffer, uvcoordsvar.xy);
vec4 smallblurred = small_sample_blur(colorbuffer, uvcoordsvar.xy, color_orig);
- float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+ float depth = texture(depthbuffer, uvcoordsvar.xy).r;
float zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth)).r;
float coc_far = clamp(calculate_far_coc(zdepth), 0.0, 1.0);
@@ -188,7 +189,7 @@ void fifth_pass()
color /= dot(factors, vec4(1.0));
/* using original color is not correct, but use that for now because alpha of
* blurred buffers uses CoC instead */
- gl_FragColor = vec4(color.rgb, color_orig.a);
+ FragColor = vec4(color.rgb, color_orig.a);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
index 182113367d3..c41c1d0820b 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
@@ -14,24 +14,28 @@ uniform sampler2D depthbuffer;
uniform sampler2D cocbuffer;
-/* this includes focal distance in x and aperture size in y */
+/* this includes aperture size in x and focal distance in y */
uniform vec4 dof_params;
/* viewvectors for reconstruction of world space */
uniform vec4 viewvecs[3];
/* initial uv coordinate */
-varying vec2 uvcoord;
+in vec2 uvcoord;
/* coordinate used for calculating radius et al set in geometry shader */
-varying vec2 particlecoord;
-varying vec4 color;
+in vec2 particlecoord;
+flat in vec4 color;
/* downsampling coordinates */
-varying vec2 downsample1;
-varying vec2 downsample2;
-varying vec2 downsample3;
-varying vec2 downsample4;
+in vec2 downsample1;
+in vec2 downsample2;
+in vec2 downsample3;
+in vec2 downsample4;
+
+layout(location = 0) out vec4 fragData0;
+layout(location = 1) out vec4 fragData1;
+layout(location = 2) out vec4 fragData2;
#define M_PI 3.1415926535897932384626433832795
@@ -55,15 +59,15 @@ void downsample_pass()
float far_coc, near_coc;
/* custom downsampling. We need to be careful to sample nearest here to avoid leaks */
- vec4 color1 = texture2D(colorbuffer, downsample1);
- vec4 color2 = texture2D(colorbuffer, downsample2);
- vec4 color3 = texture2D(colorbuffer, downsample3);
- vec4 color4 = texture2D(colorbuffer, downsample4);
+ vec4 color1 = texture(colorbuffer, downsample1);
+ vec4 color2 = texture(colorbuffer, downsample2);
+ vec4 color3 = texture(colorbuffer, downsample3);
+ vec4 color4 = texture(colorbuffer, downsample4);
- depth.r = texture2D(depthbuffer, downsample1).r;
- depth.g = texture2D(depthbuffer, downsample2).r;
- depth.b = texture2D(depthbuffer, downsample3).r;
- depth.a = texture2D(depthbuffer, downsample4).r;
+ depth.r = texture(depthbuffer, downsample1).r;
+ depth.g = texture(depthbuffer, downsample2).r;
+ depth.b = texture(depthbuffer, downsample3).r;
+ depth.a = texture(depthbuffer, downsample4).r;
zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
coc = calculate_coc(zdepth);
@@ -82,16 +86,16 @@ void downsample_pass()
float norm_far = dot(far_weights, vec4(1.0));
/* now write output to weighted buffers. */
- gl_FragData[0] = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z +
+ fragData0 = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z +
color4 * near_weights.w;
- gl_FragData[1] = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z +
+ fragData1 = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z +
color4 * far_weights.w;
if (norm_near > 0.0)
- gl_FragData[0] /= norm_near;
+ fragData0 /= norm_near;
if (norm_far > 0.0)
- gl_FragData[1] /= norm_far;
- gl_FragData[2] = vec4(near_coc, far_coc, 0.0, 1.0);
+ fragData1 /= norm_far;
+ fragData2 = vec4(near_coc, far_coc, 0.0, 1.0);
}
/* accumulate color in the near/far blur buffers */
@@ -102,36 +106,36 @@ void accumulate_pass(void) {
if (dof_params.w == 0.0)
r = 1.0;
else
- r = cos(M_PI / dof_params.w) /
- (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI))));
+ r = cos(M_PI / dof_params.w) /
+ (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI))));
if (dot(particlecoord, particlecoord) > r * r)
discard;
- gl_FragData[0] = color;
+ fragData0 = color;
}
-#define MERGE_THRESHOLD 4.0
+#define MERGE_THRESHOLD 4.0
/* combine the passes, */
void final_pass(void) {
vec4 finalcolor;
float totalweight;
- float depth = texture2D(depthbuffer, uvcoord).r;
+ float depth = texture(depthbuffer, uvcoord).r;
vec4 zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth));
float coc_near = calculate_coc(zdepth).r;
float coc_far = max(-coc_near, 0.0);
coc_near = max(coc_near, 0.0);
- vec4 farcolor = texture2D(farbuffer, uvcoord);
+ vec4 farcolor = texture(farbuffer, uvcoord);
float farweight = farcolor.a;
if (farweight > 0.0)
farcolor /= farweight;
- vec4 nearcolor = texture2D(nearbuffer, uvcoord);
+ vec4 nearcolor = texture(nearbuffer, uvcoord);
- vec4 srccolor = texture2D(colorbuffer, uvcoord);
+ vec4 srccolor = texture(colorbuffer, uvcoord);
- vec4 coc = texture2D(cocbuffer, uvcoord);
+ vec4 coc = texture(cocbuffer, uvcoord);
float mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_far);
finalcolor = mix(srccolor, farcolor, mixfac);
@@ -152,7 +156,9 @@ void final_pass(void) {
finalcolor = mix(finalcolor, nearcolor, nearweight / totalweight);
}
- gl_FragData[0] = finalcolor;
+ fragData0 = finalcolor;
+ // fragData0 = vec4(nearweight, farweight, 0.0, 1.0);
+ // fragData0 = vec4(nearcolor.rgb, 1.0);
}
void main()
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
index 4c650e7695f..52d0a9be499 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
@@ -5,27 +5,14 @@ uniform vec2 layerselection;
uniform sampler2D cocbuffer;
-#if __VERSION__ >= 150
- layout(points) in;
- layout(triangle_strip, max_vertices = 4) out;
-
- #define POS gl_in[0].gl_Position
-#else
- /* use the EXT_geometry_shader4 way */
- #define POS gl_PositionIn[0]
-#endif
-
-/* initial uv coordinate */
-#if __VERSION__ < 130
- varying in vec2 uvcoord[];
- varying out vec2 particlecoord;
- varying out vec4 color;
- #define textureLod texture2DLod
-#else
- in vec2 uvcoord[];
- out vec2 particlecoord;
- out vec4 color;
-#endif
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+#define POS gl_in[0].gl_Position
+
+in vec2 uvcoord[];
+out vec2 particlecoord;
+flat out vec4 color;
#define M_PI 3.1415926535897932384626433832795
@@ -46,21 +33,23 @@ void main()
vec2 offset_far = vec2(offset_val * 0.5) / vec2(rendertargetdim.x, rendertargetdim.y);
- gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
color = colortex;
+
+ gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
particlecoord = vec2(-1.0, -1.0);
EmitVertex();
+
gl_Position = POS + vec4(-offset_far.x, offset_far.y, 0.0, 0.0);
particlecoord = vec2(-1.0, 1.0);
- color = colortex;
EmitVertex();
+
gl_Position = POS + vec4(offset_far.x, -offset_far.y, 0.0, 0.0);
particlecoord = vec2(1.0, -1.0);
- color = colortex;
EmitVertex();
+
gl_Position = POS + vec4(offset_far.x, offset_far.y, 0.0, 0.0);
particlecoord = vec2(1.0, 1.0);
- color = colortex;
EmitVertex();
+
EndPrimitive();
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
index 09a0c75facc..1dd5bf42b25 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
@@ -1,27 +1,31 @@
-uniform vec2 invrendertargetdim;
-uniform ivec2 rendertargetdim;
+
+in vec2 pos;
+in vec2 uvs;
/* initial uv coordinate */
-varying vec2 uvcoord;
+out vec2 uvcoord;
/* coordinate used for calculating radius et al set in geometry shader */
-varying vec2 particlecoord;
+out vec2 particlecoord;
/* downsampling coordinates */
-varying vec2 downsample1;
-varying vec2 downsample2;
-varying vec2 downsample3;
-varying vec2 downsample4;
+out vec2 downsample1;
+out vec2 downsample2;
+out vec2 downsample3;
+out vec2 downsample4;
+
+uniform vec2 invrendertargetdim;
+uniform ivec2 rendertargetdim;
void vert_dof_downsample()
{
/* gather pixels from neighbors. half dimensions means we offset half a pixel to
* get this right though it's possible we may lose a pixel at some point */
- downsample1 = gl_MultiTexCoord0.xy + vec2(-0.5, -0.5) * invrendertargetdim;
- downsample2 = gl_MultiTexCoord0.xy + vec2(-0.5, 0.5) * invrendertargetdim;
- downsample3 = gl_MultiTexCoord0.xy + vec2(0.5, 0.5) * invrendertargetdim;
- downsample4 = gl_MultiTexCoord0.xy + vec2(0.5, -0.5) * invrendertargetdim;
+ downsample1 = uvs.xy + vec2(-0.5, -0.5) * invrendertargetdim;
+ downsample2 = uvs.xy + vec2(-0.5, 0.5) * invrendertargetdim;
+ downsample3 = uvs.xy + vec2(0.5, 0.5) * invrendertargetdim;
+ downsample4 = uvs.xy + vec2(0.5, -0.5) * invrendertargetdim;
- gl_Position = gl_Vertex;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
/* geometry shading pass, calculate a texture coordinate based on the indexed id */
@@ -42,8 +46,8 @@ void vert_dof_coc_scatter_pass()
void vert_dof_final()
{
- uvcoord = gl_MultiTexCoord0.xy;
- gl_Position = gl_Vertex;
+ uvcoord = uvs;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void main()
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
index 63b57d5775c..0fcab6302e4 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
@@ -1,51 +1,54 @@
uniform vec2 invrendertargetdim;
-//texture coordinates for framebuffer read
-varying vec4 uvcoordsvar;
+in vec2 pos;
+in vec2 uvs;
+
+/* texture coordinates for framebuffer read */
+out vec4 uvcoordsvar;
/* color texture coordinates, offset by a small amount */
-varying vec2 color_uv1;
-varying vec2 color_uv2;
+out vec2 color_uv1;
+out vec2 color_uv2;
-varying vec2 depth_uv1;
-varying vec2 depth_uv2;
-varying vec2 depth_uv3;
-varying vec2 depth_uv4;
+out vec2 depth_uv1;
+out vec2 depth_uv2;
+out vec2 depth_uv3;
+out vec2 depth_uv4;
//very simple shader for gull screen FX, just pass values on
void vert_generic()
{
- uvcoordsvar = gl_MultiTexCoord0;
- gl_Position = gl_Vertex;
+ uvcoordsvar = vec4(uvs, 0.0, 0.0);
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void vert_dof_first_pass()
{
/* we offset the texture coordinates by 1.5 pixel,
* then we reuse that to sample the surrounding pixels */
- color_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
- color_uv2 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
+ color_uv1 = uvs.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+ color_uv2 = uvs.xy + vec2(0.5, -1.5) * invrendertargetdim;
- depth_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
- depth_uv2 = gl_MultiTexCoord0.xy + vec2(-0.5, -1.5) * invrendertargetdim;
- depth_uv3 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
- depth_uv4 = gl_MultiTexCoord0.xy + vec2(1.5, -1.5) * invrendertargetdim;
+ depth_uv1 = uvs.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+ depth_uv2 = uvs.xy + vec2(-0.5, -1.5) * invrendertargetdim;
+ depth_uv3 = uvs.xy + vec2(0.5, -1.5) * invrendertargetdim;
+ depth_uv4 = uvs.xy + vec2(1.5, -1.5) * invrendertargetdim;
- gl_Position = gl_Vertex;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void vert_dof_fourth_pass()
{
vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
- uvcoordsvar = gl_MultiTexCoord0.xxyy +
+ uvcoordsvar = uvs.xxyy +
halfpixel *
vec4(invrendertargetdim.x,
invrendertargetdim.x,
invrendertargetdim.y,
invrendertargetdim.y);
- gl_Position = gl_Vertex;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void vert_dof_fifth_pass()
@@ -53,8 +56,8 @@ void vert_dof_fifth_pass()
vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
color_uv1 = vec2(0.5, 1.5) * invrendertargetdim;
- uvcoordsvar = gl_MultiTexCoord0;
- gl_Position = gl_Vertex;
+ uvcoordsvar = vec4(uvs, 0.0, 0.0);
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void main()
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
index 1dc49b52be1..7aa6786d292 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
@@ -1,14 +1,17 @@
+uniform mat4 ProjectionMatrix;
+
/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer
* we change the factors from the article to fit the OpennGL model. */
#ifdef PERSP_MATRIX
+
/* perspective camera code */
vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
{
float d = 2.0 * depth - 1.0;
- float zview = -gl_ProjectionMatrix[3][2] / (d + gl_ProjectionMatrix[2][2]);
+ float zview = -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
return zview * (viewvec_origin + vec3(uvcoords, 0.0) * viewvec_diff);
}
@@ -18,7 +21,7 @@ vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
vec4 d = 2.0 * depth - vec4(1.0);
/* return positive value, so sign differs! */
- return vec4(gl_ProjectionMatrix[3][2]) / (d + vec4(gl_ProjectionMatrix[2][2]));
+ return vec4(ProjectionMatrix[3][2]) / (d + vec4(ProjectionMatrix[2][2]));
}
#else
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
index f19ff4ec65a..4904010c841 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
@@ -1,3 +1,4 @@
+
// color buffer
uniform sampler2D colorbuffer;
@@ -9,8 +10,10 @@ uniform sampler1D ssao_concentric_tex;
// depth buffer
uniform sampler2D depthbuffer;
+
// coordinates on framebuffer in normalized (0.0-1.0) uv space
-varying vec4 uvcoordsvar;
+in vec4 uvcoordsvar;
+out vec4 FragColor;
/* ssao_params.x : pixel scale for the ssao radious */
/* ssao_params.y : factor for the ssao darkening */
@@ -33,7 +36,7 @@ vec3 calculate_view_space_normal(in vec3 viewposition)
float calculate_ssao_factor(float depth)
{
/* take the normalized ray direction here */
- vec2 rotX = texture2D(jitter_tex, uvcoordsvar.xy * ssao_sample_params.yz).rg;
+ vec2 rotX = texture(jitter_tex, uvcoordsvar.xy * ssao_sample_params.yz).rg;
vec2 rotY = vec2(-rotX.y, rotX.x);
/* occlusion is zero in full depth */
@@ -46,9 +49,9 @@ float calculate_ssao_factor(float depth)
/* find the offset in screen space by multiplying a point
* in camera space at the depth of the point by the projection matrix. */
vec2 offset;
- float homcoord = gl_ProjectionMatrix[2][3] * position.z + gl_ProjectionMatrix[3][3];
- offset.x = gl_ProjectionMatrix[0][0] * ssao_params.x / homcoord;
- offset.y = gl_ProjectionMatrix[1][1] * ssao_params.x / homcoord;
+ float homcoord = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3];
+ offset.x = ProjectionMatrix[0][0] * ssao_params.x / homcoord;
+ offset.y = ProjectionMatrix[1][1] * ssao_params.x / homcoord;
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
@@ -57,7 +60,7 @@ float calculate_ssao_factor(float depth)
int num_samples = int(ssao_sample_params.x);
for (x = 0; x < num_samples; x++) {
- vec2 dir_sample = texture1D(ssao_concentric_tex, (float(x) + 0.5) / ssao_sample_params.x).rg;
+ vec2 dir_sample = texture(ssao_concentric_tex, (float(x) + 0.5) / ssao_sample_params.x).rg;
/* rotate with random direction to get jittered result */
vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY));
@@ -67,7 +70,7 @@ float calculate_ssao_factor(float depth)
if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0)
continue;
- float depth_new = texture2D(depthbuffer, uvcoords).r;
+ float depth_new = texture(depthbuffer, uvcoords).r;
if (depth_new != 1.0) {
vec3 pos_new = get_view_space_from_depth(uvcoords, viewvecs[0].xyz, viewvecs[1].xyz, depth_new);
vec3 dir = pos_new - position;
@@ -87,8 +90,8 @@ float calculate_ssao_factor(float depth)
void main()
{
- float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
- vec4 scene_col = texture2D(colorbuffer, uvcoordsvar.xy);
+ float depth = texture(depthbuffer, uvcoordsvar.xy).r;
+ vec4 scene_col = texture(colorbuffer, uvcoordsvar.xy);
vec3 final_color = mix(scene_col.rgb, ssao_color.rgb, calculate_ssao_factor(depth));
- gl_FragColor = vec4(final_color.rgb, scene_col.a);
+ FragColor = vec4(final_color.rgb, scene_col.a);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
deleted file mode 100644
index 5194e414520..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
+++ /dev/null
@@ -1,9 +0,0 @@
-varying vec4 uvcoordsvar;
-
-//very simple shader for full screen FX, just pass values on
-
-void main()
-{
- uvcoordsvar = gl_MultiTexCoord0;
- gl_Position = gl_Vertex;
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
index fe630dbeddb..705b79cbf56 100644
--- a/source/blender/gpu/shaders/gpu_shader_geometry.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
@@ -1,10 +1,11 @@
+
+uniform mat4 ProjectionMatrix;
+
uniform int PrimitiveIdBase;
uniform int osd_active_uv_offset;
-#if __VERSION__ >= 150
- layout(lines_adjacency) in;
- layout(triangle_strip, max_vertices = 4) out;
-#endif
+layout(lines_adjacency) in;
+layout(triangle_strip, max_vertices = 4) out;
in block {
VertexData v;
@@ -31,17 +32,12 @@ uniform int osd_fvar_count;
tessCoord.t); \
}
-#ifdef USE_NEW_SHADING
# define INTERP_FACE_VARYING_ATT_2(result, fvarOffset, tessCoord) \
{ \
vec2 tmp; \
INTERP_FACE_VARYING_2(tmp, fvarOffset, tessCoord); \
result = vec3(tmp, 0); \
}
-#else
-# define INTERP_FACE_VARYING_ATT_2(result, fvarOffset, tessCoord) \
- INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord)
-#endif
uniform samplerBuffer FVarDataBuffer;
uniform isamplerBuffer FVarDataOffsetBuffer;
@@ -69,7 +65,7 @@ void emit_flat(int index, vec3 normal)
set_mtface_vertex_attrs(st);
- gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ gl_Position = ProjectionMatrix * inpt[index].v.position;
EmitVertex();
}
@@ -90,7 +86,7 @@ void emit_smooth(int index)
set_mtface_vertex_attrs(st);
- gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ gl_Position = ProjectionMatrix * inpt[index].v.position;
EmitVertex();
}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl
new file mode 100644
index 00000000000..727c3c0a832
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform vec4 color;
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp).r * color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl
new file mode 100644
index 00000000000..ef8935cc7ba
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform vec4 color;
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp) * color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl
new file mode 100644
index 00000000000..10f4dfd5a87
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl
@@ -0,0 +1,12 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+
+void main()
+{
+ float depth = texture(image, texCoord_interp).r;
+ fragColor = vec4(depth);
+ gl_FragDepth = depth;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl
new file mode 100644
index 00000000000..bcbe1f577fd
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl
@@ -0,0 +1,16 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform float znear;
+uniform float zfar;
+uniform sampler2D image;
+
+void main()
+{
+ float depth = texture(image, texCoord_interp).r;
+
+ /* normalize */
+ fragColor.rgb = vec3((2.0f * znear) / (zfar + znear - (depth * (zfar - znear))));
+ fragColor.a = 1.0f;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_desaturate_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_desaturate_frag.glsl
new file mode 100644
index 00000000000..1ac0d68b35f
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_desaturate_frag.glsl
@@ -0,0 +1,14 @@
+
+uniform float factor;
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform vec4 color;
+uniform sampler2D image;
+
+void main()
+{
+ vec4 tex = texture(image, texCoord_interp);
+ tex.rgb = ((0.3333333 * factor) * vec3(tex.r + tex.g + tex.b)) + (tex.rgb * (1.0 - factor));
+ fragColor = tex * color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_frag.glsl
new file mode 100644
index 00000000000..6eeab8ca7e8
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_frag.glsl
@@ -0,0 +1,10 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
new file mode 100644
index 00000000000..d95645f58e5
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
@@ -0,0 +1,34 @@
+
+/* Keep these in sync with GPU_shader.h */
+#define INTERLACE_ROW 0
+#define INTERLACE_COLUMN 1
+#define INTERLACE_CHECKERBOARD 2
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform int interlace_id;
+uniform sampler2D image_a;
+uniform sampler2D image_b;
+
+bool interlace()
+{
+ if (interlace_id == INTERLACE_CHECKERBOARD) {
+ return (int(gl_FragCoord.x + gl_FragCoord.y) & 1) != 0;
+ }
+ else if (interlace_id == INTERLACE_ROW) {
+ return (int(gl_FragCoord.y) & 1) != 0;
+ }
+ else if (interlace_id == INTERLACE_COLUMN) {
+ return (int(gl_FragCoord.x) & 1) != 0;
+ }
+}
+
+void main()
+{
+ if (interlace()) {
+ fragColor = texture(image_a, texCoord_interp);
+ } else {
+ fragColor = texture(image_b, texCoord_interp);
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl
new file mode 100644
index 00000000000..97eb3afc177
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl
@@ -0,0 +1,30 @@
+
+/* Display a linear image texture into sRGB space */
+
+uniform sampler2D image;
+
+in vec2 texCoord_interp;
+
+out vec4 fragColor;
+
+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() {
+ fragColor = texture(image, texCoord_interp.st);
+
+ linearrgb_to_srgb(fragColor, fragColor);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl
new file mode 100644
index 00000000000..4a45d03175e
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl
@@ -0,0 +1,12 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+uniform vec4 color;
+
+void main()
+{
+ fragColor.a = texture(image, texCoord_interp).a * color.a;
+ fragColor.rgb = color.rgb;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl
new file mode 100644
index 00000000000..51092d56e5e
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl
@@ -0,0 +1,12 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform float alpha;
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp);
+ fragColor.a *= alpha;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl
new file mode 100644
index 00000000000..57362c88320
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl
@@ -0,0 +1,124 @@
+
+uniform sampler2DMS depthMulti;
+uniform sampler2DMS colorMulti;
+
+out vec4 fragColor;
+
+#if SAMPLES > 16
+#error "Too many samples"
+#endif
+
+// #define USE_DEPTH_WEIGHTING
+
+void main()
+{
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+
+ bvec4 b1, b2, b3, b4;
+ vec4 w1, w2, w3, w4;
+ vec4 d1, d2, d3, d4;
+ vec4 c1, c2, c3, c4, c5, c6, c7, c8;
+ vec4 c9, c10, c11, c12, c13, c14, c15, c16;
+ d1 = d2 = d3 = d4 = vec4(1.0);
+ w1 = w2 = w3 = w4 = vec4(0.0);
+ c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = vec4(0.0);
+ c9 = c10 = c11 = c12 = c13 = c14 = c15 = c16 = vec4(0.0);
+
+ /* Depth */
+
+ d1.x = texelFetch(depthMulti, texel, 0).r;
+ d1.y = texelFetch(depthMulti, texel, 1).r;
+#if SAMPLES > 2
+ d1.z = texelFetch(depthMulti, texel, 2).r;
+ d1.w = texelFetch(depthMulti, texel, 3).r;
+#endif
+#if SAMPLES > 4
+ d2.x = texelFetch(depthMulti, texel, 4).r;
+ d2.y = texelFetch(depthMulti, texel, 5).r;
+ d2.z = texelFetch(depthMulti, texel, 6).r;
+ d2.w = texelFetch(depthMulti, texel, 7).r;
+#endif
+#if SAMPLES > 8
+ d3.x = texelFetch(depthMulti, texel, 8).r;
+ d3.y = texelFetch(depthMulti, texel, 9).r;
+ d3.z = texelFetch(depthMulti, texel, 10).r;
+ d3.w = texelFetch(depthMulti, texel, 11).r;
+ d4.x = texelFetch(depthMulti, texel, 12).r;
+ d4.y = texelFetch(depthMulti, texel, 13).r;
+ d4.z = texelFetch(depthMulti, texel, 14).r;
+ d4.w = texelFetch(depthMulti, texel, 15).r;
+#endif
+
+ /* COLOR */
+ b1 = notEqual(d1, vec4(1.0));
+ if (any(b1)) {
+ c1 = texelFetch(colorMulti, texel, 0);
+ c2 = texelFetch(colorMulti, texel, 1);
+#if SAMPLES > 2
+ c3 = texelFetch(colorMulti, texel, 2);
+ c4 = texelFetch(colorMulti, texel, 3);
+#endif
+ w1 = vec4(b1);
+ }
+#if SAMPLES > 4
+ b2 = notEqual(d2, vec4(1.0));
+ if (any(b2)) {
+ c5 = texelFetch(colorMulti, texel, 4);
+ c6 = texelFetch(colorMulti, texel, 5);
+ c7 = texelFetch(colorMulti, texel, 6);
+ c8 = texelFetch(colorMulti, texel, 7);
+ w2 = vec4(b2);
+ }
+#endif
+#if SAMPLES > 8
+ b3 = notEqual(d3, vec4(1.0));
+ if (any(b3)) {
+ c9 = texelFetch(colorMulti, texel, 8);
+ c10 = texelFetch(colorMulti, texel, 9);
+ c11 = texelFetch(colorMulti, texel, 10);
+ c12 = texelFetch(colorMulti, texel, 11);
+ w3 = vec4(b3);
+ }
+ b4 = notEqual(d4, vec4(1.0));
+ if (any(b4)) {
+ c13 = texelFetch(colorMulti, texel, 12);
+ c14 = texelFetch(colorMulti, texel, 13);
+ c15 = texelFetch(colorMulti, texel, 14);
+ c16 = texelFetch(colorMulti, texel, 15);
+ w4 = vec4(b4);
+ }
+#endif
+
+#if SAMPLES > 8
+ d1 = min(d1, min(d3, d4));
+#endif
+#if SAMPLES > 4
+ d1 = min(d1, d2);
+#endif
+#if SAMPLES > 2
+ d1.xy = min(d1.xy, d1.zw);
+#endif
+ gl_FragDepth = min(d1.x, d1.y);
+
+#ifdef USE_DEPTH_WEIGHTING
+ c1 *= w1.x; c2 *= w1.y; c3 *= w1.z; c4 *= w1.w;
+ c5 *= w2.x; c6 *= w2.y; c7 *= w2.z; c8 *= w2.w;
+ c9 *= w3.x; c10 *= w3.y; c11 *= w3.z; c12 *= w3.w;
+ c13 *= w4.x; c14 *= w4.y; c15 *= w4.z; c16 *= w4.w;
+#endif
+
+ c1 = c1 + c2;
+#if SAMPLES > 2
+ c1 += c3 + c4;
+#endif
+#if SAMPLES > 4
+ c1 += c5 + c6 + c7 + c8;
+#endif
+#if SAMPLES > 8
+ c1 += c9 + c10 + c11 + c12 + c13 + c14 + c15 + c16;
+#endif
+
+ const float inv_samples = 1.0 / float(SAMPLES);
+
+ fragColor = c1 * inv_samples;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl
new file mode 100644
index 00000000000..64662247d69
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl
@@ -0,0 +1,16 @@
+
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+uniform vec4 color;
+uniform vec4 shuffle;
+
+void main()
+{
+ vec4 sample = texture(image, texCoord_interp);
+ fragColor = vec4(sample.r * shuffle.r +
+ sample.g * shuffle.g +
+ sample.b * shuffle.b +
+ sample.a * shuffle.a) * color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl
new file mode 100644
index 00000000000..37686092700
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec2 texCoord_interp;
+flat in vec4 finalColor;
+out vec4 fragColor;
+
+uniform sampler2D image;
+
+void main()
+{
+ fragColor = texture(image, texCoord_interp) * finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl
new file mode 100644
index 00000000000..aec8fd9b0a1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl
@@ -0,0 +1,50 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in float pos;
+
+/* ---- Per instance Attribs ---- */
+in vec3 color;
+in vec4 corners[2]; /* trouble fetching vec2 */
+in float depth;
+in vec4 tria;
+in mat4 InstanceModelMatrix;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ vec3 pPos;
+
+ if (pos == 1.0) {
+ pPos = vec3(corners[0].xy, depth);
+ }
+ else if (pos == 2.0) {
+ pPos = vec3(corners[0].zw, depth);
+ }
+ else if (pos == 3.0) {
+ pPos = vec3(corners[1].xy, depth);
+ }
+ else if (pos == 4.0) {
+ pPos = vec3(corners[1].zw, depth);
+ }
+ else if (pos == 5.0) {
+ pPos = vec3(tria.xy, depth);
+ }
+ else if (pos == 6.0) {
+ vec2 ofs = tria.xy - corners[0].xy;
+ ofs.x = -ofs.x;
+ pPos = vec3(corners[1].zw + ofs, depth);
+ }
+ else if (pos == 7.0) {
+ pPos = vec3(tria.zw, depth);
+ }
+ else {
+ pPos = vec3(0.0);
+ }
+
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pPos, 1.0);
+
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
new file mode 100644
index 00000000000..ced5bb7f684
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
@@ -0,0 +1,25 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+in vec3 color;
+in float start;
+in float end;
+in mat4 InstanceModelMatrix;
+
+uniform float size;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ float len = end - start;
+ vec3 sta = vec3(0.0, 0.0, -start);
+
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * -len + sta, 1.0);
+ gl_PointSize = size;
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl
new file mode 100644
index 00000000000..e26f419b8cd
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl
@@ -0,0 +1,57 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. This geometry shader
+// decides which edge type to use if endpoints disagree.
+
+uniform mat4 ProjectionMatrix;
+
+uniform bool drawFront = true;
+uniform bool drawBack = true;
+uniform bool drawSilhouette = true;
+
+layout(lines) in;
+layout(line_strip, max_vertices = 2) out;
+
+in vec4 MV_pos[];
+in float edgeClass[];
+in vec3 fCol[];
+
+flat out vec4 finalColor;
+
+void emitLine(vec4 color)
+{
+ gl_Position = ProjectionMatrix * MV_pos[0];
+ EmitVertex();
+ gl_Position = ProjectionMatrix * MV_pos[1];
+ finalColor = color;
+ EmitVertex();
+ EndPrimitive();
+}
+
+void main()
+{
+ float finalEdgeClass = max(edgeClass[0], edgeClass[1]);
+
+ if (finalEdgeClass > 0.0f) {
+ // front-facing edge
+ if (drawFront)
+ emitLine(vec4(fCol[0], 0.75));
+ }
+ else if (finalEdgeClass < 0.0f) {
+ // back-facing edge
+ if (drawBack)
+ emitLine(vec4(fCol[0], 0.5));
+ }
+ else {
+ // exactly one face is front-facing, silhouette edge
+ if (drawSilhouette)
+ emitLine(vec4(fCol[0], 1.0));
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl
new file mode 100644
index 00000000000..fa30c9fb1ed
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl
@@ -0,0 +1,63 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. We use a geometry
+// shader to resolve this properly.
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+
+in vec3 pos;
+in vec3 N1, N2; // normals of faces this edge joins (object coords)
+
+/* instance attrib */
+in vec3 color;
+in mat4 InstanceModelMatrix;
+
+out vec4 MV_pos;
+out float edgeClass;
+out vec3 fCol;
+
+// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
+
+bool front(mat3 NormalMatrix, vec3 N, vec3 eye)
+{
+ return dot(NormalMatrix * N, eye) > 0.0;
+}
+
+void main()
+{
+ vec3 eye;
+
+ mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix;
+
+ MV_pos = ModelViewMatrix * vec4(pos, 1.0);
+
+ mat3 NormalMatrix = transpose(inverse(mat3(ModelViewMatrix)));
+
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ eye = normalize(-MV_pos.xyz);
+ }
+ else {
+ eye = vec3(0.0, 0.0, 1.0);
+ }
+
+ bool face_1_front = front(NormalMatrix, N1, eye);
+ bool face_2_front = front(NormalMatrix, N2, eye);
+
+ if (face_1_front && face_2_front)
+ edgeClass = 1.0; // front-facing edge
+ else if (face_1_front || face_2_front)
+ edgeClass = 0.0; // exactly one face is front-facing, silhouette edge
+ else
+ edgeClass = -1.0; // back-facing edge
+
+ fCol = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl
new file mode 100644
index 00000000000..9876717b297
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl
@@ -0,0 +1,27 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+in vec3 nor;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+
+out vec3 normal;
+flat out vec4 finalColor;
+
+void main()
+{
+ mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * InstanceModelMatrix;
+ /* This is slow and run per vertex, but it's still faster than
+ * doing it per instance on CPU and sending it on via instance attrib */
+ mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix)));
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ normal = NormalMatrix * nor;
+
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl
new file mode 100644
index 00000000000..2ee74b3eae0
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl
@@ -0,0 +1,32 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screen_vecs[2];
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos; /* using Z as axis id */
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec3 color;
+in float size;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ vec3 offset = vec3(0.0);
+
+#ifdef AXIS_NAME
+ if (pos.z == 0.0)
+ offset = vec3(1.125, 0.0, 0.0);
+ else if (pos.z == 1.0)
+ offset = vec3(0.0, 1.125, 0.0);
+ else
+ offset = vec3(0.0, 0.0, 1.125);
+ offset *= size;
+#endif
+
+ vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y;
+ gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(offset, 1.0) + vec4(screen_pos * size, 0.0));
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl
new file mode 100644
index 00000000000..ba0ac29fb79
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screen_vecs[2];
+uniform float size;
+uniform float pixel_size;
+
+/* ---- Instanciated Attribs ---- */
+in vec2 pos;
+
+/* ---- Per instance Attribs ---- */
+in vec3 world_pos;
+in vec3 color;
+
+flat out vec4 finalColor;
+
+float mul_project_m4_v3_zfac(in vec3 co)
+{
+ return (ViewProjectionMatrix[0][3] * co.x) +
+ (ViewProjectionMatrix[1][3] * co.y) +
+ (ViewProjectionMatrix[2][3] * co.z) + ViewProjectionMatrix[3][3];
+}
+
+void main()
+{
+ float pix_size = mul_project_m4_v3_zfac(world_pos) * pixel_size;
+ vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y;
+ gl_Position = ViewProjectionMatrix * vec4(world_pos + screen_pos * size * pix_size, 1.0);
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl
new file mode 100644
index 00000000000..10a2ba61a2c
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl
@@ -0,0 +1,22 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec3 color;
+#ifdef UNIFORM_SCALE
+in float size;
+#else
+in vec3 size;
+#endif
+
+flat out vec4 finalColor;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * size, 1.0);
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl
new file mode 100644
index 00000000000..49750dddb3c
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl
@@ -0,0 +1,23 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform int baseId;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+#ifdef UNIFORM_SCALE
+in float size;
+#else
+in vec3 size;
+#endif
+in int callId;
+
+flat out uint finalId;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * size, 1.0);
+ finalId = uint(baseId + callId);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl
new file mode 100644
index 00000000000..eac167e8045
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl
@@ -0,0 +1,13 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl
new file mode 100644
index 00000000000..7f445369833
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl
@@ -0,0 +1,31 @@
+
+in vec4 radii;
+in vec4 finalColor;
+in vec4 finalOutlineColor;
+out vec4 fragColor;
+
+void main() {
+ vec2 quad = abs(gl_PointCoord - vec2(0.5));
+ float dist = quad.x + quad.y;
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure point color
+// ...
+// dist = 0 at center of point
+
+ float mid_stroke = 0.5 * (radii[1] + radii[2]);
+
+ vec4 backgroundColor = vec4(finalOutlineColor.rgb, 0.0);
+
+ if (dist > mid_stroke)
+ fragColor = mix(finalOutlineColor, backgroundColor, smoothstep(radii[1], radii[0], dist));
+ else
+ fragColor = mix(finalColor, finalOutlineColor, smoothstep(radii[3], radii[2], dist));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
new file mode 100644
index 00000000000..c49832bf9b4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
@@ -0,0 +1,34 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+const float pixel_fudge = sqrt(2.0);
+const float outline_width = 1.15 * pixel_fudge;
+
+in vec2 pos;
+in float size;
+in vec4 color;
+in vec4 outlineColor;
+out vec4 finalColor;
+out vec4 finalOutlineColor;
+out vec4 radii;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+
+ // pass through unchanged
+ gl_PointSize = size + pixel_fudge; // 0.5 pixel_fudge on either side
+ finalColor = color;
+ finalOutlineColor = outlineColor;
+
+ // calculate concentric radii in pixels
+ float radius = 0.5 * gl_PointSize;
+
+ // start at the outside and progress toward the center
+ radii[0] = radius;
+ radii[1] = radius - pixel_fudge;
+ radii[2] = radius - outline_width;
+ radii[3] = radius - outline_width - pixel_fudge;
+
+ // convert to PointCoord units
+ radii /= size;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index aace5e95169..795320df6b7 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1,12 +1,50 @@
+
+uniform mat4 ModelMatrix;
+uniform mat4 ModelViewMatrix;
+uniform mat4 ModelViewMatrixInverse;
+uniform mat3 NormalMatrix;
+
+#ifndef ATTRIB
+uniform mat4 ModelMatrixInverse;
+#endif
+
+/* Old glsl mode compat. */
+
+#ifndef CLOSURE_DEFAULT
+
+struct Closure {
+ vec3 radiance;
+ float opacity;
+};
+
+#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0)
+
+Closure closure_mix(Closure cl1, Closure cl2, float fac)
+{
+ Closure cl;
+ cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
+ cl.opacity = mix(cl1.opacity, cl2.opacity, fac);
+ return cl;
+}
+
+Closure closure_add(Closure cl1, Closure cl2)
+{
+ Closure cl;
+ cl.radiance = cl1.radiance + cl2.radiance;
+ cl.opacity = cl1.opacity + cl2.opacity;
+ return cl;
+}
+
+Closure nodetree_exec(void); /* Prototype */
+
+#endif /* CLOSURE_DEFAULT */
+
+
/* Converters */
float convert_rgba_to_float(vec4 color)
{
-#ifdef USE_NEW_SHADING
- return color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;
-#else
- return (color.r + color.g + color.b) / 3.0;
-#endif
+ return dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
}
float exp_blender(float f)
@@ -53,7 +91,7 @@ void rgb_to_hsv(vec4 rgb, out vec4 outcol)
h = 0.0;
}
else {
- c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta;
+ c = (vec3(cmax) - rgb.xyz) / cdelta;
if (rgb.x == cmax) h = c[2] - c[1];
else if (rgb.y == cmax) h = 2.0 + c[0] - c[2];
@@ -155,56 +193,15 @@ void color_to_blender_normal_new_shading(vec3 color, out vec3 normal)
normal.y = -2.0 * ((color.g) - 0.5);
normal.z = -2.0 * ((color.b) - 0.5);
}
-
+#ifndef M_PI
#define M_PI 3.14159265358979323846
-#define M_1_PI 0.31830988618379069
+#endif
+#ifndef M_1_PI
+#define M_1_PI 0.318309886183790671538
+#endif
/*********** SHADER NODES ***************/
-void vcol_attribute(vec4 attvcol, out vec4 vcol)
-{
- vcol = vec4(attvcol.x, attvcol.y, attvcol.z, 1.0);
-}
-
-void uv_attribute(vec2 attuv, out vec3 uv)
-{
- uv = vec3(attuv * 2.0 - vec2(1.0, 1.0), 0.0);
-}
-
-void geom(
- vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 attvcol,
- out vec3 global, out vec3 local, out vec3 view, out vec3 orco, out vec3 uv,
- out vec3 normal, out vec4 vcol, out float vcol_alpha, out float frontback)
-{
- local = co;
- view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0);
- global = (viewinvmat * vec4(local, 1.0)).xyz;
- orco = attorco;
- uv_attribute(attuv, uv);
- normal = -normalize(nor); /* blender render normal is negated */
- vcol_attribute(attvcol, vcol);
- srgb_to_linearrgb(vcol, vcol);
- vcol_alpha = attvcol.a;
- frontback = (gl_FrontFacing) ? 1.0 : 0.0;
-}
-
-void particle_info(
- vec4 sprops, vec4 loc, vec3 vel, vec3 avel,
- out float index, out float random, out float age,
- out float life_time, out vec3 location,
- out float size, out vec3 velocity, out vec3 angular_velocity)
-{
- index = sprops.x;
- random = loc.w;
- age = sprops.y;
- life_time = sprops.z;
- size = sprops.w;
-
- location = loc.xyz;
- velocity = vel;
- angular_velocity = avel;
-}
-
void vect_normalize(vec3 vin, out vec3 vout)
{
vout = normalize(vin);
@@ -272,17 +269,6 @@ void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
outview = normalize(co);
}
-void lamp(
- vec4 col, float energy, vec3 lv, float dist, vec3 shadow, float visifac,
- out vec4 outcol, out vec3 outlv, out float outdist, out vec4 outshadow, out float outvisifac)
-{
- outcol = col * energy;
- outlv = lv;
- outdist = dist;
- outshadow = vec4(shadow, 1.0);
- outvisifac = visifac;
-}
-
void math_add(float val1, float val2, out float outval)
{
outval = val1 + val2;
@@ -426,13 +412,13 @@ void squeeze(float val, float width, float center, out float outval)
void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
outvec = v1 + v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) / 3.0;
+ outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333;
}
void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
outvec = v1 - v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) / 3.0;
+ outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333;
}
void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
@@ -448,7 +434,7 @@ void vec_math_mix(float strength, vec3 v1, vec3 v2, out vec3 outvec)
void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
- outvec = vec3(0, 0, 0);
+ outvec = vec3(0);
outval = dot(v1, v2);
}
@@ -490,9 +476,9 @@ void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
{
- outvec.x = texture2D(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x;
- outvec.y = texture2D(curvemap, vec2((vec.y + 1.0) * 0.5, 0.0)).y;
- outvec.z = texture2D(curvemap, vec2((vec.z + 1.0) * 0.5, 0.0)).z;
+ outvec.x = texture(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x;
+ outvec.y = texture(curvemap, vec2((vec.y + 1.0) * 0.5, 0.0)).y;
+ outvec.z = texture(curvemap, vec2((vec.z + 1.0) * 0.5, 0.0)).z;
if (fac != 1.0)
outvec = (outvec * fac) + (vec * (1.0 - fac));
@@ -501,9 +487,9 @@ void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
void curves_rgb(float fac, vec4 col, sampler2D curvemap, out vec4 outcol)
{
- outcol.r = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.r, 0.0)).a, 0.0)).r;
- outcol.g = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.g, 0.0)).a, 0.0)).g;
- outcol.b = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.b, 0.0)).a, 0.0)).b;
+ outcol.r = texture(curvemap, vec2(texture(curvemap, vec2(col.r, 0.0)).a, 0.0)).r;
+ outcol.g = texture(curvemap, vec2(texture(curvemap, vec2(col.g, 0.0)).a, 0.0)).g;
+ outcol.b = texture(curvemap, vec2(texture(curvemap, vec2(col.b, 0.0)).a, 0.0)).b;
if (fac != 1.0)
outcol = (outcol * fac) + (col * (1.0 - fac));
@@ -823,22 +809,19 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha)
{
- outcol = texture2D(colormap, vec2(fac, 0.0));
+ outcol = texture(colormap, vec2(fac, 0.0));
outalpha = outcol.a;
}
void rgbtobw(vec4 color, out float outval)
{
-#ifdef USE_NEW_SHADING
- outval = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;
-#else
- outval = color.r * 0.35 + color.g * 0.45 + color.b * 0.2; /* keep these factors in sync with texture.h:RGBTOBW */
-#endif
+ vec3 factors = vec3(0.2126, 0.7152, 0.0722);
+ outval = dot(color.rgb, factors);
}
void invert(float fac, vec4 col, out vec4 outcol)
{
- outcol.xyz = mix(col.xyz, vec3(1.0, 1.0, 1.0) - col.xyz, fac);
+ outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac);
outcol.w = col.w;
}
@@ -916,56 +899,6 @@ void output_node(vec4 rgb, float alpha, out vec4 outrgb)
/*********** TEXTURES ***************/
-void texture_flip_blend(vec3 vec, out vec3 outvec)
-{
- outvec = vec.yxz;
-}
-
-void texture_blend_lin(vec3 vec, out float outval)
-{
- outval = (1.0 + vec.x) / 2.0;
-}
-
-void texture_blend_quad(vec3 vec, out float outval)
-{
- outval = max((1.0 + vec.x) / 2.0, 0.0);
- outval *= outval;
-}
-
-void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal)
-{
- float a = sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) * 20.0;
- float wi = 0.5 + 0.5 * sin(a);
-
- value = wi;
- color = vec4(wi, wi, wi, 1.0);
- normal = vec3(0.0, 0.0, 0.0);
-}
-
-void texture_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal)
-{
- color = texture2D(ima, (vec.xy + vec2(1.0, 1.0)) * 0.5);
- value = color.a;
-
- normal.x = 2.0 * (color.r - 0.5);
- normal.y = 2.0 * (0.5 - color.g);
- normal.z = 2.0 * (color.b - 0.5);
-}
-
-/************* MTEX *****************/
-
-void texco_orco(vec3 attorco, out vec3 orco)
-{
- orco = attorco;
-}
-
-void texco_uv(vec2 attuv, out vec3 uv)
-{
- /* disabled for now, works together with leaving out mtex_2d_mapping */
- // uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); */
- uv = vec3(attuv, 0.0);
-}
-
void texco_norm(vec3 normal, out vec3 outnormal)
{
/* corresponds to shi->orn, which is negated so cancels
@@ -973,436 +906,11 @@ void texco_norm(vec3 normal, out vec3 outnormal)
outnormal = normalize(normal);
}
-void texco_tangent(vec4 tangent, out vec3 outtangent)
-{
- outtangent = normalize(tangent.xyz);
-}
-
-void texco_global(mat4 viewinvmat, vec3 co, out vec3 global)
-{
- global = (viewinvmat * vec4(co, 1.0)).xyz;
-}
-
-void texco_object(mat4 viewinvmat, mat4 obinvmat, vec3 co, out vec3 object)
-{
- object = (obinvmat * (viewinvmat * vec4(co, 1.0))).xyz;
-}
-
-void texco_refl(vec3 vn, vec3 view, out vec3 ref)
-{
- ref = view - 2.0 * dot(vn, view) * vn;
-}
-
-void shade_norm(vec3 normal, out vec3 outnormal)
-{
- /* blender render normal is negated */
- outnormal = -normalize(normal);
-}
-
-void mtex_mirror(vec3 tcol, vec4 refcol, float tin, float colmirfac, out vec4 outrefcol)
-{
- outrefcol = mix(refcol, vec4(1.0, tcol), tin * colmirfac);
-}
-
-void mtex_rgb_blend(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- float facm;
-
- fact *= facg;
- facm = 1.0 - fact;
-
- incol = fact * texcol + facm * outcol;
-}
-
-void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- float facm;
-
- fact *= facg;
- facm = 1.0 - fact;
-
- incol = (facm + fact * texcol) * outcol;
-}
-
-void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- float facm;
-
- fact *= facg;
- facm = 1.0 - fact;
-
- incol = vec3(1.0) - (vec3(facm) + fact * (vec3(1.0) - texcol)) * (vec3(1.0) - outcol);
-}
-
-void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- float facm;
-
- fact *= facg;
- facm = 1.0 - fact;
-
- if (outcol.r < 0.5)
- incol.r = outcol.r * (facm + 2.0 * fact * texcol.r);
- else
- incol.r = 1.0 - (facm + 2.0 * fact * (1.0 - texcol.r)) * (1.0 - outcol.r);
-
- if (outcol.g < 0.5)
- incol.g = outcol.g * (facm + 2.0 * fact * texcol.g);
- else
- incol.g = 1.0 - (facm + 2.0 * fact * (1.0 - texcol.g)) * (1.0 - outcol.g);
-
- if (outcol.b < 0.5)
- incol.b = outcol.b * (facm + 2.0 * fact * texcol.b);
- else
- incol.b = 1.0 - (facm + 2.0 * fact * (1.0 - texcol.b)) * (1.0 - outcol.b);
-}
-
-void mtex_rgb_sub(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- incol = -fact * facg * texcol + outcol;
-}
-
-void mtex_rgb_add(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- incol = fact * facg * texcol + outcol;
-}
-
-void mtex_rgb_div(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- float facm;
-
- fact *= facg;
- facm = 1.0 - fact;
-
- if (texcol.r != 0.0) incol.r = facm * outcol.r + fact * outcol.r / texcol.r;
- if (texcol.g != 0.0) incol.g = facm * outcol.g + fact * outcol.g / texcol.g;
- if (texcol.b != 0.0) incol.b = facm * outcol.b + fact * outcol.b / texcol.b;
-}
-
-void mtex_rgb_diff(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- float facm;
-
- fact *= facg;
- facm = 1.0 - fact;
-
- incol = facm * outcol + fact * abs(texcol - outcol);
-}
-
-void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- float facm, col;
-
- fact *= facg;
- facm = 1.0 - fact;
-
- incol.r = min(outcol.r, texcol.r) * fact + outcol.r * facm;
- incol.g = min(outcol.g, texcol.g) * fact + outcol.g * facm;
- incol.b = min(outcol.b, texcol.b) * fact + outcol.b * facm;
-}
-
-void mtex_rgb_light(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- float facm, col;
-
- fact *= facg;
-
- col = fact * texcol.r;
- if (col > outcol.r) incol.r = col; else incol.r = outcol.r;
- col = fact * texcol.g;
- if (col > outcol.g) incol.g = col; else incol.g = outcol.g;
- col = fact * texcol.b;
- if (col > outcol.b) incol.b = col; else incol.b = outcol.b;
-}
-
-void mtex_rgb_hue(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- vec4 col;
-
- mix_hue(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
- incol.rgb = col.rgb;
-}
-
-void mtex_rgb_sat(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- vec4 col;
-
- mix_sat(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
- incol.rgb = col.rgb;
-}
-
-void mtex_rgb_val(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- vec4 col;
-
- mix_val(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
- incol.rgb = col.rgb;
-}
-
-void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- vec4 col;
-
- mix_color(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
- incol.rgb = col.rgb;
-}
-
-void mtex_rgb_soft(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- vec4 col;
-
- mix_soft(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
- incol.rgb = col.rgb;
-}
-
-void mtex_rgb_linear(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
-{
- fact *= facg;
-
- if (texcol.r > 0.5)
- incol.r = outcol.r + fact * (2.0 * (texcol.r - 0.5));
- else
- incol.r = outcol.r + fact * (2.0 * (texcol.r) - 1.0);
-
- if (texcol.g > 0.5)
- incol.g = outcol.g + fact * (2.0 * (texcol.g - 0.5));
- else
- incol.g = outcol.g + fact * (2.0 * (texcol.g) - 1.0);
-
- if (texcol.b > 0.5)
- incol.b = outcol.b + fact * (2.0 * (texcol.b - 0.5));
- else
- incol.b = outcol.b + fact * (2.0 * (texcol.b) - 1.0);
-}
-
-void mtex_value_vars(inout float fact, float facg, out float facm)
-{
- fact *= abs(facg);
- facm = 1.0 - fact;
-
- if (facg < 0.0) {
- float tmp = fact;
- fact = facm;
- facm = tmp;
- }
-}
-
-void mtex_value_blend(float outcol, float texcol, float fact, float facg, out float incol)
-{
- float facm;
- mtex_value_vars(fact, facg, facm);
-
- incol = fact * texcol + facm * outcol;
-}
-
-void mtex_value_mul(float outcol, float texcol, float fact, float facg, out float incol)
-{
- float facm;
- mtex_value_vars(fact, facg, facm);
-
- facm = 1.0 - facg;
- incol = (facm + fact * texcol) * outcol;
-}
-
-void mtex_value_screen(float outcol, float texcol, float fact, float facg, out float incol)
-{
- float facm;
- mtex_value_vars(fact, facg, facm);
-
- facm = 1.0 - facg;
- incol = 1.0 - (facm + fact * (1.0 - texcol)) * (1.0 - outcol);
-}
-
-void mtex_value_sub(float outcol, float texcol, float fact, float facg, out float incol)
-{
- float facm;
- mtex_value_vars(fact, facg, facm);
-
- fact = -fact;
- incol = fact * texcol + outcol;
-}
-
-void mtex_value_add(float outcol, float texcol, float fact, float facg, out float incol)
-{
- float facm;
- mtex_value_vars(fact, facg, facm);
-
- fact = fact;
- incol = fact * texcol + outcol;
-}
-
-void mtex_value_div(float outcol, float texcol, float fact, float facg, out float incol)
-{
- float facm;
- mtex_value_vars(fact, facg, facm);
-
- if (texcol != 0.0)
- incol = facm * outcol + fact * outcol / texcol;
- else
- incol = 0.0;
-}
-
-void mtex_value_diff(float outcol, float texcol, float fact, float facg, out float incol)
-{
- float facm;
- mtex_value_vars(fact, facg, facm);
-
- incol = facm * outcol + fact * abs(texcol - outcol);
-}
-
-void mtex_value_dark(float outcol, float texcol, float fact, float facg, out float incol)
-{
- float facm;
- mtex_value_vars(fact, facg, facm);
-
- incol = facm * outcol + fact * min(outcol, texcol);
-}
-
-void mtex_value_light(float outcol, float texcol, float fact, float facg, out float incol)
-{
- float facm;
- mtex_value_vars(fact, facg, facm);
-
- float col = fact * texcol;
- if (col > outcol) incol = col; else incol = outcol;
-}
-
-void mtex_value_clamp_positive(float fac, out float outfac)
-{
- outfac = max(fac, 0.0);
-}
-
-void mtex_value_clamp(float fac, out float outfac)
-{
- outfac = clamp(fac, 0.0, 1.0);
-}
-
-void mtex_har_divide(float har, out float outhar)
-{
- outhar = har / 128.0;
-}
-
-void mtex_har_multiply_clamp(float har, out float outhar)
-{
- har *= 128.0;
-
- if (har < 1.0) outhar = 1.0;
- else if (har > 511.0) outhar = 511.0;
- else outhar = har;
-}
-
-void mtex_alpha_from_col(vec4 col, out float alpha)
-{
- alpha = col.a;
-}
-
-void mtex_alpha_to_col(vec4 col, float alpha, out vec4 outcol)
-{
- outcol = vec4(col.rgb, alpha);
-}
-
-void mtex_alpha_multiply_value(vec4 col, float value, out vec4 outcol)
-{
- outcol = vec4(col.rgb, col.a * value);
-}
-
-void mtex_rgbtoint(vec4 rgb, out float intensity)
-{
- intensity = dot(vec3(0.35, 0.45, 0.2), rgb.rgb);
-}
-
-void mtex_value_invert(float invalue, out float outvalue)
-{
- outvalue = 1.0 - invalue;
-}
-
-void mtex_rgb_invert(vec4 inrgb, out vec4 outrgb)
-{
- outrgb = vec4(vec3(1.0) - inrgb.rgb, inrgb.a);
-}
-
-void mtex_value_stencil(float stencil, float intensity, out float outstencil, out float outintensity)
-{
- float fact = intensity;
- outintensity = intensity * stencil;
- outstencil = stencil * fact;
-}
-
-void mtex_rgb_stencil(float stencil, vec4 rgb, out float outstencil, out vec4 outrgb)
-{
- float fact = rgb.a;
- outrgb = vec4(rgb.rgb, rgb.a * stencil);
- outstencil = stencil * fact;
-}
-
-void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco)
-{
- outtexco = texco + ofs;
-}
-
-void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco)
-{
- outtexco = size * texco;
-}
-
-void mtex_2d_mapping(vec3 vec, out vec3 outvec)
-{
- outvec = vec3(vec.xy * 0.5 + vec2(0.5), vec.z);
-}
-
vec3 mtex_2d_mapping(vec3 vec)
{
return vec3(vec.xy * 0.5 + vec2(0.5), vec.z);
}
-void mtex_cube_map(vec3 co, samplerCube ima, out float value, out vec4 color)
-{
- color = textureCube(ima, co);
- value = 1.0;
-}
-
-void mtex_cube_map_refl_from_refldir(
- samplerCube ima, vec3 reflecteddirection, out float value, out vec4 color)
-{
- color = textureCube(ima, reflecteddirection);
- value = color.a;
-}
-
-void mtex_cube_map_refl(
- samplerCube ima, vec3 vp, vec3 vn, mat4 viewmatrixinverse, mat4 viewmatrix,
- out float value, out vec4 color)
-{
- vec3 viewdirection = vec3(viewmatrixinverse * vec4(vp, 0.0));
- vec3 normaldirection = normalize(vec3(vec4(vn, 0.0) * viewmatrix));
- vec3 reflecteddirection = reflect(viewdirection, normaldirection);
- color = textureCube(ima, reflecteddirection);
- value = 1.0;
-}
-
-void mtex_image(vec3 texco, sampler2D ima, out float value, out vec4 color)
-{
- color = texture2D(ima, texco.xy);
- value = 1.0;
-}
-
-void mtex_normal(vec3 texco, sampler2D ima, out vec3 normal)
-{
- // The invert of the red channel is to make
- // the normal map compliant with the outside world.
- // It needs to be done because in Blender
- // the normal used points inward.
- // Should this ever change this negate must be removed.
- vec4 color = texture2D(ima, texco.xy);
- normal = 2.0 * (vec3(-color.r, color.g, color.b) - vec3(-0.5, 0.5, 0.5));
-}
-
-void mtex_bump_normals_init(vec3 vN, out vec3 vNorg, out vec3 vNacc, out float fPrevMagnitude)
-{
- vNorg = vN;
- vNacc = vN;
- fPrevMagnitude = 1.0;
-}
-
/** helper method to extract the upper left 3x3 matrix from a 4x4 matrix */
mat3 to_mat3(mat4 m4)
{
@@ -1413,976 +921,6 @@ mat3 to_mat3(mat4 m4)
return m3;
}
-void mtex_bump_init_objspace(
- vec3 surf_pos, vec3 surf_norm,
- mat4 mView, mat4 mViewInv, mat4 mObj, mat4 mObjInv,
- float fPrevMagnitude_in, vec3 vNacc_in,
- out float fPrevMagnitude_out, out vec3 vNacc_out,
- out vec3 vR1, out vec3 vR2, out float fDet)
-{
- mat3 obj2view = to_mat3(gl_ModelViewMatrix);
- mat3 view2obj = to_mat3(gl_ModelViewMatrixInverse);
-
- vec3 vSigmaS = view2obj * dFdx(surf_pos);
- vec3 vSigmaT = view2obj * dFdy(surf_pos);
- vec3 vN = normalize(surf_norm * obj2view);
-
- vR1 = cross(vSigmaT, vN);
- vR2 = cross(vN, vSigmaS);
- fDet = dot(vSigmaS, vR1);
-
- /* pretransform vNacc (in mtex_bump_apply) using the inverse transposed */
- vR1 = vR1 * view2obj;
- vR2 = vR2 * view2obj;
- vN = vN * view2obj;
-
- float fMagnitude = abs(fDet) * length(vN);
- vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in);
- fPrevMagnitude_out = fMagnitude;
-}
-
-void mtex_bump_init_texturespace(
- vec3 surf_pos, vec3 surf_norm,
- float fPrevMagnitude_in, vec3 vNacc_in,
- out float fPrevMagnitude_out, out vec3 vNacc_out,
- out vec3 vR1, out vec3 vR2, out float fDet)
-{
- vec3 vSigmaS = dFdx(surf_pos);
- vec3 vSigmaT = dFdy(surf_pos);
- vec3 vN = surf_norm; /* normalized interpolated vertex normal */
-
- vR1 = normalize(cross(vSigmaT, vN));
- vR2 = normalize(cross(vN, vSigmaS));
- fDet = sign(dot(vSigmaS, vR1));
-
- float fMagnitude = abs(fDet);
- vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in);
- fPrevMagnitude_out = fMagnitude;
-}
-
-void mtex_bump_init_viewspace(
- vec3 surf_pos, vec3 surf_norm,
- float fPrevMagnitude_in, vec3 vNacc_in,
- out float fPrevMagnitude_out, out vec3 vNacc_out,
- out vec3 vR1, out vec3 vR2, out float fDet)
-{
- vec3 vSigmaS = dFdx(surf_pos);
- vec3 vSigmaT = dFdy(surf_pos);
- vec3 vN = surf_norm; /* normalized interpolated vertex normal */
-
- vR1 = cross(vSigmaT, vN);
- vR2 = cross(vN, vSigmaS);
- fDet = dot(vSigmaS, vR1);
-
- float fMagnitude = abs(fDet);
- vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in);
- fPrevMagnitude_out = fMagnitude;
-}
-
-void mtex_bump_tap3(
- vec3 texco, sampler2D ima, float hScale,
- out float dBs, out float dBt)
-{
- vec2 STll = texco.xy;
- vec2 STlr = texco.xy + dFdx(texco.xy);
- vec2 STul = texco.xy + dFdy(texco.xy);
-
- float Hll, Hlr, Hul;
- rgbtobw(texture2D(ima, STll), Hll);
- rgbtobw(texture2D(ima, STlr), Hlr);
- rgbtobw(texture2D(ima, STul), Hul);
-
- dBs = hScale * (Hlr - Hll);
- dBt = hScale * (Hul - Hll);
-}
-
-#ifdef BUMP_BICUBIC
-
-void mtex_bump_bicubic(
- vec3 texco, sampler2D ima, float hScale,
- out float dBs, out float dBt )
-{
- float Hl;
- float Hr;
- float Hd;
- float Hu;
-
- vec2 TexDx = dFdx(texco.xy);
- vec2 TexDy = dFdy(texco.xy);
-
- vec2 STl = texco.xy - 0.5 * TexDx;
- vec2 STr = texco.xy + 0.5 * TexDx;
- vec2 STd = texco.xy - 0.5 * TexDy;
- vec2 STu = texco.xy + 0.5 * TexDy;
-
- rgbtobw(texture2D(ima, STl), Hl);
- rgbtobw(texture2D(ima, STr), Hr);
- rgbtobw(texture2D(ima, STd), Hd);
- rgbtobw(texture2D(ima, STu), Hu);
-
- vec2 dHdxy = vec2(Hr - Hl, Hu - Hd);
- float fBlend = clamp(1.0 - textureQueryLOD(ima, texco.xy).x, 0.0, 1.0);
- if (fBlend != 0.0) {
- // the derivative of the bicubic sampling of level 0
- ivec2 vDim;
- vDim = textureSize(ima, 0);
-
- // taking the fract part of the texture coordinate is a hardcoded wrap mode.
- // this is acceptable as textures use wrap mode exclusively in 3D view elsewhere in blender.
- // this is done so that we can still get a valid texel with uvs outside the 0,1 range
- // by texelFetch below, as coordinates are clamped when using this function.
- vec2 fTexLoc = vDim * fract(texco.xy) - vec2(0.5, 0.5);
- ivec2 iTexLoc = ivec2(floor(fTexLoc));
- vec2 t = clamp(fTexLoc - iTexLoc, 0.0, 1.0); // sat just to be pedantic
-
-/*******************************************************************************************
- * This block will replace the one below when one channel textures are properly supported. *
- *******************************************************************************************
- vec4 vSamplesUL = textureGather(ima, (iTexLoc+ivec2(-1,-1) + vec2(0.5,0.5))/vDim);
- vec4 vSamplesUR = textureGather(ima, (iTexLoc+ivec2(1,-1) + vec2(0.5,0.5))/vDim);
- vec4 vSamplesLL = textureGather(ima, (iTexLoc+ivec2(-1,1) + vec2(0.5,0.5))/vDim);
- vec4 vSamplesLR = textureGather(ima, (iTexLoc+ivec2(1,1) + vec2(0.5,0.5))/vDim);
-
- mat4 H = mat4(vSamplesUL.w, vSamplesUL.x, vSamplesLL.w, vSamplesLL.x,
- vSamplesUL.z, vSamplesUL.y, vSamplesLL.z, vSamplesLL.y,
- vSamplesUR.w, vSamplesUR.x, vSamplesLR.w, vSamplesLR.x,
- vSamplesUR.z, vSamplesUR.y, vSamplesLR.z, vSamplesLR.y);
- */
- ivec2 iTexLocMod = iTexLoc + ivec2(-1, -1);
-
- mat4 H;
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- ivec2 iTexTmp = iTexLocMod + ivec2(i, j);
-
- // wrap texture coordinates manually for texelFetch to work on uvs oitside the 0,1 range.
- // this is guaranteed to work since we take the fractional part of the uv above.
- iTexTmp.x = (iTexTmp.x < 0) ? iTexTmp.x + vDim.x : ((iTexTmp.x >= vDim.x) ? iTexTmp.x - vDim.x : iTexTmp.x);
- iTexTmp.y = (iTexTmp.y < 0) ? iTexTmp.y + vDim.y : ((iTexTmp.y >= vDim.y) ? iTexTmp.y - vDim.y : iTexTmp.y);
-
- rgbtobw(texelFetch(ima, iTexTmp, 0), H[i][j]);
- }
- }
-
- float x = t.x, y = t.y;
- float x2 = x * x, x3 = x2 * x, y2 = y * y, y3 = y2 * y;
-
- vec4 X = vec4(-0.5 * (x3 + x) + x2, 1.5 * x3 - 2.5 * x2 + 1, -1.5 * x3 + 2 * x2 + 0.5 * x, 0.5 * (x3 - x2));
- vec4 Y = vec4(-0.5 * (y3 + y) + y2, 1.5 * y3 - 2.5 * y2 + 1, -1.5 * y3 + 2 * y2 + 0.5 * y, 0.5 * (y3 - y2));
- vec4 dX = vec4(-1.5 * x2 + 2 * x - 0.5, 4.5 * x2 - 5 * x, -4.5 * x2 + 4 * x + 0.5, 1.5 * x2 - x);
- vec4 dY = vec4(-1.5 * y2 + 2 * y - 0.5, 4.5 * y2 - 5 * y, -4.5 * y2 + 4 * y + 0.5, 1.5 * y2 - y);
-
- // complete derivative in normalized coordinates (mul by vDim)
- vec2 dHdST = vDim * vec2(dot(Y, H * dX), dot(dY, H * X));
-
- // transform derivative to screen-space
- vec2 dHdxy_bicubic = vec2(dHdST.x * TexDx.x + dHdST.y * TexDx.y,
- dHdST.x * TexDy.x + dHdST.y * TexDy.y);
-
- // blend between the two
- dHdxy = dHdxy * (1 - fBlend) + dHdxy_bicubic * fBlend;
- }
-
- dBs = hScale * dHdxy.x;
- dBt = hScale * dHdxy.y;
-}
-
-#endif
-
-void mtex_bump_tap5(
- vec3 texco, sampler2D ima, float hScale,
- out float dBs, out float dBt)
-{
- vec2 TexDx = dFdx(texco.xy);
- vec2 TexDy = dFdy(texco.xy);
-
- vec2 STc = texco.xy;
- vec2 STl = texco.xy - 0.5 * TexDx;
- vec2 STr = texco.xy + 0.5 * TexDx;
- vec2 STd = texco.xy - 0.5 * TexDy;
- vec2 STu = texco.xy + 0.5 * TexDy;
-
- float Hc, Hl, Hr, Hd, Hu;
- rgbtobw(texture2D(ima, STc), Hc);
- rgbtobw(texture2D(ima, STl), Hl);
- rgbtobw(texture2D(ima, STr), Hr);
- rgbtobw(texture2D(ima, STd), Hd);
- rgbtobw(texture2D(ima, STu), Hu);
-
- dBs = hScale * (Hr - Hl);
- dBt = hScale * (Hu - Hd);
-}
-
-void mtex_bump_deriv(
- vec3 texco, sampler2D ima, float ima_x, float ima_y, float hScale,
- out float dBs, out float dBt)
-{
- float s = 1.0; // negate this if flipped texture coordinate
- vec2 TexDx = dFdx(texco.xy);
- vec2 TexDy = dFdy(texco.xy);
-
- // this variant using a derivative map is described here
- // http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html
- vec2 dim = vec2(ima_x, ima_y);
- vec2 dBduv = hScale * dim * (2.0 * texture2D(ima, texco.xy).xy - 1.0);
-
- dBs = dBduv.x * TexDx.x + s * dBduv.y * TexDx.y;
- dBt = dBduv.x * TexDy.x + s * dBduv.y * TexDy.y;
-}
-
-void mtex_bump_apply(
- float fDet, float dBs, float dBt, vec3 vR1, vec3 vR2, vec3 vNacc_in,
- out vec3 vNacc_out, out vec3 perturbed_norm)
-{
- vec3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2);
-
- vNacc_out = vNacc_in - vSurfGrad;
- perturbed_norm = normalize(vNacc_out);
-}
-
-void mtex_bump_apply_texspace(
- float fDet, float dBs, float dBt, vec3 vR1, vec3 vR2,
- sampler2D ima, vec3 texco, float ima_x, float ima_y, vec3 vNacc_in,
- out vec3 vNacc_out, out vec3 perturbed_norm)
-{
- vec2 TexDx = dFdx(texco.xy);
- vec2 TexDy = dFdy(texco.xy);
-
- vec3 vSurfGrad = sign(fDet) * (
- dBs / length(vec2(ima_x * TexDx.x, ima_y * TexDx.y)) * vR1 +
- dBt / length(vec2(ima_x * TexDy.x, ima_y * TexDy.y)) * vR2);
-
- vNacc_out = vNacc_in - vSurfGrad;
- perturbed_norm = normalize(vNacc_out);
-}
-
-void mtex_negate_texnormal(vec3 normal, out vec3 outnormal)
-{
- outnormal = vec3(-normal.x, -normal.y, normal.z);
-}
-
-void mtex_nspace_tangent(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal)
-{
- vec3 B = tangent.w * cross(normal, tangent.xyz);
-
- outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal;
- outnormal = normalize(outnormal);
-}
-
-void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal)
-{
- outnormal = normalize((viewmat * vec4(texnormal, 0.0)).xyz);
-}
-
-void mtex_nspace_object(vec3 texnormal, out vec3 outnormal)
-{
- outnormal = normalize(gl_NormalMatrix * texnormal);
-}
-
-void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal)
-{
- outnormal = (1.0 - norfac) * normal + norfac * newnormal;
- outnormal = normalize(outnormal);
-}
-
-/******* MATERIAL *********/
-
-void lamp_visibility_sun_hemi(vec3 lampvec, out vec3 lv, out float dist, out float visifac)
-{
- lv = lampvec;
- dist = 1.0;
- visifac = 1.0;
-}
-
-void lamp_visibility_other(vec3 co, vec3 lampco, out vec3 lv, out float dist, out float visifac)
-{
- lv = co - lampco;
- dist = length(lv);
- lv = normalize(lv);
- visifac = 1.0;
-}
-
-void lamp_falloff_invlinear(float lampdist, float dist, out float visifac)
-{
- visifac = lampdist / (lampdist + dist);
-}
-
-void lamp_falloff_invsquare(float lampdist, float dist, out float visifac)
-{
- visifac = lampdist / (lampdist + dist * dist);
-}
-
-void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out float visifac)
-{
- float lampdistkw = lampdist * lampdist;
-
- visifac = lampdist / (lampdist + ld1 * dist);
- visifac *= lampdistkw / (lampdistkw + ld2 * dist * dist);
-}
-
-void lamp_falloff_invcoefficients(float coeff_const, float coeff_lin, float coeff_quad, float dist, out float visifac)
-{
- vec3 coeff = vec3(coeff_const, coeff_lin, coeff_quad);
- vec3 d_coeff = vec3(1.0, dist, dist * dist);
- float visifac_r = dot(coeff, d_coeff);
- if (visifac_r > 0.0)
- visifac = 1.0 / visifac_r;
- else
- visifac = 0.0;
-}
-
-void lamp_falloff_curve(float lampdist, sampler2D curvemap, float dist, out float visifac)
-{
- visifac = texture2D(curvemap, vec2(dist / lampdist, 0.0)).x;
-}
-
-void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac)
-{
- float t = lampdist - dist;
-
- outvisifac = visifac * max(t, 0.0) / lampdist;
-}
-
-void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr)
-{
- if (dot(lv, lampvec) > 0.0) {
- vec3 lvrot = (lampimat * vec4(lv, 0.0)).xyz;
- /* without clever non-uniform scale, we could do: */
- // float x = max(abs(lvrot.x / lvrot.z), abs(lvrot.y / lvrot.z));
- float x = max(abs((lvrot.x / scale.x) / lvrot.z), abs((lvrot.y / scale.y) / lvrot.z));
-
- inpr = 1.0 / sqrt(1.0 + x * x);
- }
- else
- inpr = 0.0;
-}
-
-void lamp_visibility_spot_circle(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr)
-{
- /* without clever non-uniform scale, we could do: */
- // inpr = dot(lv, lampvec);
- if (dot(lv, lampvec) > 0.0) {
- vec3 lvrot = (lampimat * vec4(lv, 0.0)).xyz;
- float x = abs(lvrot.x / lvrot.z);
- float y = abs(lvrot.y / lvrot.z);
-
- float ellipse = abs((x * x) / (scale.x * scale.x) + (y * y) / (scale.y * scale.y));
-
- inpr = 1.0 / sqrt(1.0 + ellipse);
- }
- else
- inpr = 0.0;
-}
-
-void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac)
-{
- float t = spotsi;
-
- if (inpr <= t) {
- outvisifac = 0.0;
- }
- else {
- t = inpr - t;
-
- /* soft area */
- if (spotbl != 0.0)
- inpr *= smoothstep(0.0, 1.0, t / spotbl);
-
- outvisifac = visifac * inpr;
- }
-}
-
-void lamp_visibility_clamp(float visifac, out float outvisifac)
-{
- outvisifac = (visifac < 0.001) ? 0.0 : visifac;
-}
-
-void world_paper_view(vec3 vec, out vec3 outvec)
-{
- vec3 nvec = normalize(vec);
- outvec = (gl_ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0);
-}
-
-void world_zen_mapping(vec3 view, float zenup, float zendown, out float zenfac)
-{
- if (view.z >= 0.0)
- zenfac = zenup;
- else
- zenfac = zendown;
-}
-
-void world_blend_paper_real(vec3 vec, out float blend)
-{
- blend = abs(vec.y);
-}
-
-void world_blend_paper(vec3 vec, out float blend)
-{
- blend = (vec.y + 1.0) * 0.5;
-}
-
-void world_blend_real(vec3 vec, out float blend)
-{
- blend = abs(normalize(vec).z);
-}
-
-void world_blend(vec3 vec, out float blend)
-{
- blend = (normalize(vec).z + 1) * 0.5;
-}
-
-void shade_view(vec3 co, out vec3 view)
-{
- /* handle perspective/orthographic */
- view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0);
-}
-
-void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn)
-{
- vec3 c = cross(lv, tang);
- vec3 vnor = cross(c, tang);
-
- vn = -normalize(vnor);
-}
-
-void shade_inp(vec3 vn, vec3 lv, out float inp)
-{
- inp = dot(vn, lv);
-}
-
-void shade_is_no_diffuse(out float is)
-{
- is = 0.0;
-}
-
-void shade_is_hemi(float inp, out float is)
-{
- is = 0.5 * inp + 0.5;
-}
-
-float area_lamp_energy(mat4 area, vec3 co, vec3 vn)
-{
- vec3 vec[4], c[4];
- float rad[4], fac;
-
- vec[0] = normalize(co - area[0].xyz);
- vec[1] = normalize(co - area[1].xyz);
- vec[2] = normalize(co - area[2].xyz);
- vec[3] = normalize(co - area[3].xyz);
-
- c[0] = normalize(cross(vec[0], vec[1]));
- c[1] = normalize(cross(vec[1], vec[2]));
- c[2] = normalize(cross(vec[2], vec[3]));
- c[3] = normalize(cross(vec[3], vec[0]));
-
- rad[0] = acos(dot(vec[0], vec[1]));
- rad[1] = acos(dot(vec[1], vec[2]));
- rad[2] = acos(dot(vec[2], vec[3]));
- rad[3] = acos(dot(vec[3], vec[0]));
-
- fac = rad[0] * dot(vn, c[0]);
- fac += rad[1] * dot(vn, c[1]);
- fac += rad[2] * dot(vn, c[2]);
- fac += rad[3] * dot(vn, c[3]);
-
- return max(fac, 0.0);
-}
-
-void shade_inp_area(
- vec3 position, vec3 lampco, vec3 lampvec, vec3 vn, mat4 area, float areasize, float k,
- out float inp)
-{
- vec3 co = position;
- vec3 vec = co - lampco;
-
- if (dot(vec, lampvec) < 0.0) {
- inp = 0.0;
- }
- else {
- float intens = area_lamp_energy(area, co, vn);
-
- inp = pow(intens * areasize, k);
- }
-}
-
-void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out float is)
-{
- vec3 h = normalize(v + l);
- float nh = max(dot(n, h), 0.0);
- float nv = max(dot(n, v), 0.0);
- float realnl = dot(n, l);
-
- if (realnl < 0.0) {
- is = 0.0;
- }
- else if (nl < 0.0) {
- is = 0.0;
- }
- else {
- float vh = max(dot(v, h), 0.0);
- float Lit_A = acos(realnl);
- float View_A = acos(nv);
-
- vec3 Lit_B = normalize(l - realnl * n);
- vec3 View_B = normalize(v - nv * n);
-
- float t = max(dot(Lit_B, View_B), 0.0);
-
- float a, b;
-
- if (Lit_A > View_A) {
- a = Lit_A;
- b = View_A;
- }
- else {
- a = View_A;
- b = Lit_A;
- }
-
- float A = 1.0 - (0.5 * ((rough * rough) / ((rough * rough) + 0.33)));
- float B = 0.45 * ((rough * rough) / ((rough * rough) + 0.09));
-
- b *= 0.95;
- is = nl * (A + (B * t * sin(a) * tan(b)));
- }
-}
-
-void shade_diffuse_toon(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float is)
-{
- float rslt = dot(n, l);
- float ang = acos(rslt);
-
- if (ang < size) is = 1.0;
- else if (ang > (size + tsmooth) || tsmooth == 0.0) is = 0.0;
- else is = 1.0 - ((ang - size) / tsmooth);
-}
-
-void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float is)
-{
- if (nl <= 0.0) {
- is = 0.0;
- }
- else {
- float nv = max(dot(n, v), 0.0);
-
- if (darkness <= 1.0)
- is = nl * pow(max(nv * nl, 0.1), darkness - 1.0);
- else
- is = nl * pow(1.0001 - nv, darkness - 1.0);
- }
-}
-
-float fresnel_fac(vec3 view, vec3 vn, float grad, float fac)
-{
- float t1, t2;
- float ffac;
-
- if (fac == 0.0) {
- ffac = 1.0;
- }
- else {
- t1 = dot(view, vn);
- if (t1 > 0.0) t2 = 1.0 + t1;
- else t2 = 1.0 - t1;
-
- t2 = grad + (1.0 - grad) * pow(t2, fac);
-
- if (t2 < 0.0) ffac = 0.0;
- else if (t2 > 1.0) ffac = 1.0;
- else ffac = t2;
- }
-
- return ffac;
-}
-
-void shade_diffuse_fresnel(vec3 vn, vec3 lv, vec3 view, float fac_i, float fac, out float is)
-{
- is = fresnel_fac(lv, vn, fac_i, fac);
-}
-
-void shade_cubic(float is, out float outis)
-{
- if (is > 0.0 && is < 1.0)
- outis = smoothstep(0.0, 1.0, is);
- else
- outis = is;
-}
-
-void shade_visifac(float i, float visifac, float refl, out float outi)
-{
- /*if (i > 0.0)*/
- outi = max(i * visifac * refl, 0.0);
- /*else
- outi = i;*/
-}
-
-void shade_tangent_v_spec(vec3 tang, out vec3 vn)
-{
- vn = tang;
-}
-
-void shade_add_to_diffuse(float i, vec3 lampcol, vec3 col, out vec3 outcol)
-{
- if (i > 0.0)
- outcol = i * lampcol * col;
- else
- outcol = vec3(0.0, 0.0, 0.0);
-}
-
-void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t)
-{
- lv += view;
- lv = normalize(lv);
-
- t = dot(vn, lv);
- t = 0.5 * t + 0.5;
-
- t = visifac * spec * pow(t, hard);
-}
-
-void shade_phong_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
-{
- vec3 h = normalize(l + v);
- float rslt = max(dot(h, n), 0.0);
-
- specfac = pow(rslt, hard);
-}
-
-void shade_cooktorr_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
-{
- vec3 h = normalize(v + l);
- float nh = dot(n, h);
-
- if (nh < 0.0) {
- specfac = 0.0;
- }
- else {
- float nv = max(dot(n, v), 0.0);
- float i = pow(nh, hard);
-
- i = i / (0.1 + nv);
- specfac = i;
- }
-}
-
-void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, out float specfac)
-{
- if (refrac < 1.0) {
- specfac = 0.0;
- }
- else if (spec_power == 0.0) {
- specfac = 0.0;
- }
- else {
- if (spec_power < 100.0)
- spec_power = sqrt(1.0 / spec_power);
- else
- spec_power = 10.0 / spec_power;
-
- vec3 h = normalize(v + l);
- float nh = dot(n, h);
- if (nh < 0.0) {
- specfac = 0.0;
- }
- else {
- float nv = max(dot(n, v), 0.01);
- float nl = dot(n, l);
- if (nl <= 0.01) {
- specfac = 0.0;
- }
- else {
- float vh = max(dot(v, h), 0.01);
-
- float a = 1.0;
- float b = (2.0 * nh * nv) / vh;
- float c = (2.0 * nh * nl) / vh;
-
- float g = 0.0;
-
- if (a < b && a < c) g = a;
- else if (b < a && b < c) g = b;
- else if (c < a && c < b) g = c;
-
- float p = sqrt(((refrac * refrac) + (vh * vh) - 1.0));
- float f = ((((p - vh) * (p - vh)) / ((p + vh) * (p + vh))) *
- (1.0 + ((((vh * (p + vh)) - 1.0) * ((vh * (p + vh)) - 1.0)) /
- (((vh * (p - vh)) + 1.0) * ((vh * (p - vh)) + 1.0)))));
- float ang = acos(nh);
-
- specfac = max(f * g * exp_blender((-(ang * ang) / (2.0 * spec_power * spec_power))), 0.0);
- }
- }
- }
-}
-
-void shade_wardiso_spec(vec3 n, vec3 l, vec3 v, float rms, out float specfac)
-{
- vec3 h = normalize(l + v);
- float nh = max(dot(n, h), 0.001);
- float nv = max(dot(n, v), 0.001);
- float nl = max(dot(n, l), 0.001);
- float angle = tan(acos(nh));
- float alpha = max(rms, 0.001);
-
- specfac = nl * (1.0 / (4.0 * M_PI * alpha * alpha)) * (exp_blender(-(angle * angle) / (alpha * alpha)) / (sqrt(nv * nl)));
-}
-
-void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float specfac)
-{
- vec3 h = normalize(l + v);
- float rslt = dot(h, n);
- float ang = acos(rslt);
-
- if (ang < size) rslt = 1.0;
- else if (ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0;
- else rslt = 1.0 - ((ang - size) / tsmooth);
-
- specfac = rslt;
-}
-
-void shade_spec_area_inp(float specfac, float inp, out float outspecfac)
-{
- outspecfac = specfac * inp;
-}
-
-void shade_spec_t(float shadfac, float spec, float visifac, float specfac, out float t)
-{
- t = shadfac * spec * visifac * specfac;
-}
-
-void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol)
-{
- outcol = t * lampcol * speccol;
-}
-
-void shade_add_mirror(vec3 mir, vec4 refcol, vec3 combined, out vec3 result)
-{
- result = mir * refcol.gba + (vec3(1.0) - mir * refcol.rrr) * combined;
-}
-
-void alpha_spec_correction(vec3 spec, float spectra, float alpha, out float outalpha)
-{
- if (spectra > 0.0) {
- float t = clamp(max(max(spec.r, spec.g), spec.b) * spectra, 0.0, 1.0);
- outalpha = (1.0 - t) * alpha + t;
- }
- else {
- outalpha = alpha;
- }
-}
-
-void shade_add(vec4 col1, vec4 col2, out vec4 outcol)
-{
- outcol = col1 + col2;
-}
-
-void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol)
-{
- outcol = col + col1 * col2;
-}
-
-void shade_add_clamped(vec4 col1, vec4 col2, out vec4 outcol)
-{
- outcol = col1 + max(col2, vec4(0.0, 0.0, 0.0, 0.0));
-}
-
-void shade_madd_clamped(vec4 col, vec4 col1, vec4 col2, out vec4 outcol)
-{
- outcol = col + max(col1 * col2, vec4(0.0, 0.0, 0.0, 0.0));
-}
-
-void env_apply(vec4 col, vec3 hor, vec3 zen, vec4 f, mat4 vm, vec3 vn, out vec4 outcol)
-{
- vec3 vv = normalize(vm[2].xyz);
- float skyfac = 0.5 * (1.0 + dot(vn, -vv));
- outcol = col + f * vec4(mix(hor, zen, skyfac), 0);
-}
-
-void shade_maddf(vec4 col, float f, vec4 col1, out vec4 outcol)
-{
- outcol = col + f * col1;
-}
-
-void shade_mul(vec4 col1, vec4 col2, out vec4 outcol)
-{
- outcol = col1 * col2;
-}
-
-void shade_mul_value(float fac, vec4 col, out vec4 outcol)
-{
- outcol = col * fac;
-}
-
-void shade_mul_value_v3(float fac, vec3 col, out vec3 outcol)
-{
- outcol = col * fac;
-}
-
-void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
-{
- outcol = vec4(col.rgb * obcol.rgb, col.a);
-}
-
-void ramp_rgbtobw(vec3 color, out float outval)
-{
- outval = color.r * 0.3 + color.g * 0.58 + color.b * 0.12;
-}
-
-void shade_only_shadow(float i, float shadfac, float energy, vec3 shadcol, out vec3 outshadrgb)
-{
- outshadrgb = i * energy * (1.0 - shadfac) * (vec3(1.0) - shadcol);
-}
-
-void shade_only_shadow_diffuse(vec3 shadrgb, vec3 rgb, vec4 diff, out vec4 outdiff)
-{
- outdiff = diff - vec4(rgb * shadrgb, 0.0);
-}
-
-void shade_only_shadow_specular(vec3 shadrgb, vec3 specrgb, vec4 spec, out vec4 outspec)
-{
- outspec = spec - vec4(specrgb * shadrgb, 0.0);
-}
-
-void shade_clamp_positive(vec4 col, out vec4 outcol)
-{
- outcol = max(col, vec4(0.0));
-}
-
-void test_shadowbuf(
- vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, float shadowbias, float inp,
- out float result)
-{
- if (inp <= 0.0) {
- result = 0.0;
- }
- else {
- vec4 co = shadowpersmat * vec4(rco, 1.0);
-
- //float bias = (1.5 - inp*inp)*shadowbias;
- co.z -= shadowbias * co.w;
-
- if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0)
- result = shadow2DProj(shadowmap, co).x;
- else
- result = 1.0;
- }
-}
-
-void test_shadowbuf_vsm(
- vec3 rco, sampler2D shadowmap, mat4 shadowpersmat, float shadowbias, float bleedbias, float inp,
- out float result)
-{
- if (inp <= 0.0) {
- result = 0.0;
- }
- else {
- vec4 co = shadowpersmat * vec4(rco, 1.0);
- if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0) {
- vec2 moments = texture2DProj(shadowmap, co).rg;
- float dist = co.z / co.w;
- float p = 0.0;
-
- if (dist <= moments.x)
- p = 1.0;
-
- float variance = moments.y - (moments.x * moments.x);
- variance = max(variance, shadowbias / 10.0);
-
- float d = moments.x - dist;
- float p_max = variance / (variance + d * d);
-
- // Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1]
- p_max = clamp((p_max - bleedbias) / (1.0 - bleedbias), 0.0, 1.0);
-
- result = max(p, p_max);
- }
- else {
- result = 1.0;
- }
- }
-}
-
-void shadows_only(
- vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat,
- float shadowbias, vec3 shadowcolor, float inp,
- out vec3 result)
-{
- result = vec3(1.0);
-
- if (inp > 0.0) {
- float shadfac;
-
- test_shadowbuf(rco, shadowmap, shadowpersmat, shadowbias, inp, shadfac);
- result -= (1.0 - shadfac) * (vec3(1.0) - shadowcolor);
- }
-}
-
-void shadows_only_vsm(
- vec3 rco, sampler2D shadowmap, mat4 shadowpersmat,
- float shadowbias, float bleedbias, vec3 shadowcolor, float inp,
- out vec3 result)
-{
- result = vec3(1.0);
-
- if (inp > 0.0) {
- float shadfac;
-
- test_shadowbuf_vsm(rco, shadowmap, shadowpersmat, shadowbias, bleedbias, inp, shadfac);
- result -= (1.0 - shadfac) * (vec3(1.0) - shadowcolor);
- }
-}
-
-void shade_light_texture(vec3 rco, sampler2D cookie, mat4 shadowpersmat, out vec4 result)
-{
-
- vec4 co = shadowpersmat * vec4(rco, 1.0);
-
- result = texture2DProj(cookie, co);
-}
-
-void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol)
-{
- outcol = linfac * (1.0 - exp(col * logfac));
-}
-
-void shade_mist_factor(
- vec3 co, float enable, float miststa, float mistdist, float misttype, float misi,
- out float outfac)
-{
- if (enable == 1.0) {
- float fac, zcor;
-
- zcor = (gl_ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2];
-
- fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0);
- if (misttype == 0.0) fac *= fac;
- else if (misttype == 1.0) ;
- else fac = sqrt(fac);
-
- outfac = 1.0 - (1.0 - fac) * (1.0 - misi);
- }
- else {
- outfac = 0.0;
- }
-}
-
-void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol)
-{
- float fac = clamp(col.a, 0.0, 1.0);
- outcol = vec4(mix(hor, col.rgb, fac), col.a);
-}
-
-void shade_alpha_opaque(vec4 col, out vec4 outcol)
-{
- outcol = vec4(col.rgb, 1.0);
-}
-
-void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
-{
- outcol = vec4(col.rgb, col.a * obcol.a);
-}
-
/*********** NEW SHADER UTILITIES **************/
float fresnel_dielectric_0(float eta)
@@ -2428,7 +966,15 @@ float hypot(float x, float y)
void generated_from_orco(vec3 orco, out vec3 generated)
{
- generated = orco * 0.5 + vec3(0.5);
+#ifdef VOLUMETRICS
+#ifdef MESH_SHADER
+ generated = volumeObjectLocalCoord;
+#else
+ generated = worldPosition;
+#endif
+#else
+ generated = orco;
+#endif
}
int floor_to_int(float x)
@@ -2441,7 +987,6 @@ int quick_floor(float x)
return int(x) - ((x < 0) ? 1 : 0);
}
-#ifdef BIT_OPERATIONS
float integer_noise(int n)
{
int nn;
@@ -2505,7 +1050,6 @@ vec3 cellnoise_color(vec3 p)
return vec3(r, g, b);
}
-#endif // BIT_OPERATIONS
float floorfrac(float x, out int i)
{
@@ -2513,316 +1057,348 @@ float floorfrac(float x, out int i)
return x - i;
}
+/* bsdfs */
-/* Principled BSDF operations */
-
-float sqr(float a)
+void convert_metallic_to_specular_tinted(
+ vec3 basecol, float metallic, float specular_fac, float specular_tint,
+ out vec3 diffuse, out vec3 f0)
{
- return a*a;
+ vec3 dielectric = vec3(0.034) * specular_fac * 2.0;
+ float lum = dot(basecol, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
+ vec3 tint = lum > 0 ? basecol / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
+ f0 = mix(dielectric * mix(vec3(1.0), tint, specular_tint), basecol, metallic);
+ diffuse = mix(basecol, vec3(0.0), metallic);
}
-float schlick_fresnel(float u)
+#ifndef VOLUMETRICS
+void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
{
- float m = clamp(1.0 - u, 0.0, 1.0);
- float m2 = m * m;
- return m2 * m2 * m; // pow(m,5)
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance);
+ result.radiance *= color.rgb;
}
-float GTR1(float NdotH, float a)
+void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result)
{
- if (a >= 1.0) {
- return M_1_PI;
- }
-
- a = max(a, 0.001);
- float a2 = a*a;
- float t = 1.0 + (a2 - 1.0) * NdotH*NdotH;
- return (a2 - 1.0) / (M_PI * log(a2) * t);
+ vec3 out_spec, ssr_spec;
+ eevee_closure_glossy(N, vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec * color.rgb;
+ result.ssr_data = vec4(ssr_spec * color.rgb, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
}
-float GTR2(float NdotH, float a)
+void node_bsdf_anisotropic(
+ vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T,
+ out Closure result)
{
- float a2 = a*a;
- float t = 1.0 + (a2 - 1.0) * NdotH*NdotH;
- return a2 / (M_PI * t*t);
+ node_bsdf_diffuse(color, 0.0, N, result);
}
-float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay)
+void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result)
{
- return 1.0 / (M_PI * ax*ay * sqr(sqr(HdotX / ax) + sqr(HdotY / ay) + NdotH*NdotH));
+ vec3 out_spec, out_refr, ssr_spec;
+ vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : color.rgb; /* Simulate 2 transmission event */
+ eevee_closure_glass(N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
+ out_refr *= refr_color;
+ out_spec *= color.rgb;
+ float fresnel = F_eta(ior, dot(N, cameraVec));
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = mix(out_refr, out_spec, fresnel);
+ result.ssr_data = vec4(ssr_spec * color.rgb * fresnel, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
}
-float smithG_GGX(float NdotV, float alphaG)
+void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result)
{
- float a = alphaG*alphaG;
- float b = NdotV*NdotV;
- return 1.0 / (NdotV + sqrt(a + b - a * b));
+ node_bsdf_diffuse(color, 0.0, N, result);
}
-vec3 rotate_vector(vec3 p, vec3 n, float theta) {
- return (
- p * cos(theta) + cross(n, p) *
- sin(theta) + n * dot(p, n) *
- (1.0 - cos(theta))
- );
-}
+void node_bsdf_principled_clearcoat(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+ float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+ float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id,
+ float sss_id, vec3 sss_scale, out Closure result)
+{
+ metallic = saturate(metallic);
+ transmission = saturate(transmission);
+ vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec;
+ convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0);
-/*********** NEW SHADER NODES ***************/
+ transmission *= 1.0 - metallic;
+ subsurface *= 1.0 - metallic;
-#define NUM_LIGHTS 3
+ clearcoat *= 0.25;
+ clearcoat *= 1.0 - transmission;
-/* bsdfs */
+#ifdef USE_SSS
+ diffuse = mix(diffuse, vec3(0.0), subsurface);
+#else
+ diffuse = mix(diffuse, subsurface_color.rgb, subsurface);
+#endif
+ f0 = mix(f0, vec3(1.0), transmission);
+
+ float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0));
+ eevee_closure_principled(N, diffuse, f0, int(ssr_id), roughness,
+ CN, clearcoat, clearcoat_roughness, 1.0, sss_scalef, ior,
+ out_diff, out_trans, out_spec, out_refr, ssr_spec);
+
+ vec3 refr_color = base_color.rgb;
+ refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission event */
+
+ float fresnel = F_eta(ior, dot(N, cameraVec));
+ vec3 refr_spec_color = base_color.rgb * fresnel;
+ /* This bit maybe innacurate. */
+ out_refr = out_refr * refr_color * (1.0 - fresnel) + out_spec * refr_spec_color;
+
+ ssr_spec = mix(ssr_spec, refr_spec_color, transmission);
+
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec + out_diff * diffuse;
+ result.radiance = mix(result.radiance, out_refr, transmission);
+ result.ssr_data = vec4(ssr_spec, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
+#ifdef USE_SSS
+ result.sss_data.a = sss_scalef;
+ result.sss_data.rgb = out_diff + out_trans;
+#ifdef USE_SSS_ALBEDO
+ result.sss_albedo.rgb = mix(vec3(0.0), subsurface_color.rgb, subsurface);
+#else
+ result.sss_data.rgb *= mix(vec3(0.0), subsurface_color.rgb, subsurface);
+#endif
+ result.sss_data.rgb *= (1.0 - transmission);
+#endif
+}
-void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result)
+void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
{
- /* ambient light */
- vec3 L = vec3(0.2);
-
- /* directional lights */
- for (int i = 0; i < NUM_LIGHTS; i++) {
- vec3 light_position = gl_LightSource[i].position.xyz;
- vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
-
- float bsdf = max(dot(N, light_position), 0.0);
- L += light_diffuse * bsdf;
- }
-
- result = vec4(L * color.rgb, 1.0);
+ node_bsdf_diffuse(color, 0.0, -N, result);
}
-void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result)
+void node_bsdf_transparent(vec4 color, out Closure result)
{
- /* ambient light */
- vec3 L = vec3(0.2);
-
- /* directional lights */
- for (int i = 0; i < NUM_LIGHTS; i++) {
- vec3 light_position = gl_LightSource[i].position.xyz;
- vec3 H = gl_LightSource[i].halfVector.xyz;
- vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
- vec3 light_specular = gl_LightSource[i].specular.rgb;
-
- /* we mix in some diffuse so low roughness still shows up */
- float r2 = roughness * roughness;
- float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / r2);
- bsdf += 0.5 * max(dot(N, light_position), 0.0);
- L += light_specular * bsdf;
- }
-
- result = vec4(L * color.rgb, 1.0);
+ /* this isn't right */
+ result = CLOSURE_DEFAULT;
+ result.radiance = vec3(0.0);
+ result.opacity = 0.0;
+ result.ssr_id = TRANSPARENT_CLOSURE_FLAG;
}
-void node_bsdf_anisotropic(
- vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T,
- out vec4 result)
+void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result)
{
node_bsdf_diffuse(color, 0.0, N, result);
}
-void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, out vec4 result)
-{
+void node_subsurface_scattering(
+ vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, float sss_id,
+ out Closure result)
+{
+#if defined(USE_SSS)
+ vec3 out_diff, out_trans;
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.ssr_data = vec4(0.0);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = -1;
+ result.sss_data.a = scale;
+ eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans);
+ result.sss_data.rgb = out_diff + out_trans;
+#ifdef USE_SSS_ALBEDO
+ /* Not perfect for texture_blur not exaclty equal to 0.0 or 1.0. */
+ result.sss_albedo.rgb = mix(color.rgb, vec3(1.0), texture_blur);
+ result.sss_data.rgb *= mix(vec3(1.0), color.rgb, texture_blur);
+#else
+ result.sss_data.rgb *= color.rgb;
+#endif
+#else
node_bsdf_diffuse(color, 0.0, N, result);
+#endif
}
-void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 result)
+void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result)
{
- node_bsdf_diffuse(color, 0.0, N, result);
+ vec3 out_refr;
+ color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */
+ eevee_closure_refraction(N, roughness, ior, out_refr);
+ vec3 vN = normalize(mat3(ViewMatrix) * N);
+ result = CLOSURE_DEFAULT;
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.radiance = out_refr * color.rgb;
+ result.ssr_id = REFRACT_CLOSURE_FLAG;
}
-void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
- float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
- float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result)
+void node_ambient_occlusion(vec4 color, vec3 vN, out Closure result)
{
- /* ambient light */
- // TODO: set ambient light to an appropriate value
- vec3 L = mix(0.1, 0.03, metallic) * mix(base_color.rgb, subsurface_color.rgb, subsurface * (1.0 - metallic));
-
- float eta = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
-
- /* set the viewing vector */
- vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? -normalize(I) : vec3(0.0, 0.0, 1.0);
-
- /* get the tangent */
- vec3 Tangent = T;
- if (T == vec3(0.0)) {
- // if no tangent is set, use a default tangent
- if(N.x != N.y || N.x != N.z) {
- Tangent = vec3(N.z-N.y, N.x-N.z, N.y-N.x); // (1,1,1) x N
- }
- else {
- Tangent = vec3(N.z-N.y, N.x+N.z, -N.y-N.x); // (-1,1,1) x N
- }
- }
-
- /* rotate tangent */
- if (anisotropic_rotation != 0.0) {
- Tangent = rotate_vector(Tangent, N, anisotropic_rotation * 2.0 * M_PI);
- }
-
- /* calculate the tangent and bitangent */
- vec3 Y = normalize(cross(N, Tangent));
- vec3 X = cross(Y, N);
-
- /* fresnel normalization parameters */
- float F0 = fresnel_dielectric_0(eta);
- float F0_norm = 1.0 / (1.0 - F0);
-
- /* directional lights */
- for (int i = 0; i < NUM_LIGHTS; i++) {
- vec3 light_position_world = gl_LightSource[i].position.xyz;
- vec3 light_position = normalize(light_position_world);
-
- vec3 H = normalize(light_position + V);
-
- vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
- vec3 light_specular = gl_LightSource[i].specular.rgb;
-
- float NdotL = dot(N, light_position);
- float NdotV = dot(N, V);
- float LdotH = dot(light_position, H);
-
- vec3 diffuse_and_specular_bsdf = vec3(0.0);
- if (NdotL >= 0.0 && NdotV >= 0.0) {
- float NdotH = dot(N, H);
-
- float Cdlum = 0.3 * base_color.r + 0.6 * base_color.g + 0.1 * base_color.b; // luminance approx.
-
- vec3 Ctint = Cdlum > 0 ? base_color.rgb / Cdlum : vec3(1.0); // normalize lum. to isolate hue+sat
- vec3 Cspec0 = mix(specular * 0.08 * mix(vec3(1.0), Ctint, specular_tint), base_color.rgb, metallic);
- vec3 Csheen = mix(vec3(1.0), Ctint, sheen_tint);
-
- // Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
- // and mix in diffuse retro-reflection based on roughness
-
- float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
- float Fd90 = 0.5 + 2.0 * LdotH*LdotH * roughness;
- float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV);
-
- // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
- // 1.25 scale is used to (roughly) preserve albedo
- // Fss90 used to "flatten" retroreflection based on roughness
- float Fss90 = LdotH*LdotH * roughness;
- float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV);
- float ss = 1.25 * (Fss * (1.0 / (NdotL + NdotV) - 0.5) + 0.5);
-
- // specular
- float aspect = sqrt(1.0 - anisotropic * 0.9);
- float a = sqr(roughness);
- float ax = max(0.001, a / aspect);
- float ay = max(0.001, a * aspect);
- float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay); //GTR2(NdotH, a);
- float FH = (fresnel_dielectric_cos(LdotH, eta) - F0) * F0_norm;
- vec3 Fs = mix(Cspec0, vec3(1.0), FH);
- float roughg = sqr(roughness * 0.5 + 0.5);
- float Gs = smithG_GGX(NdotL, roughg) * smithG_GGX(NdotV, roughg);
-
- // sheen
- vec3 Fsheen = schlick_fresnel(LdotH) * sheen * Csheen;
-
- vec3 diffuse_bsdf = (mix(Fd * base_color.rgb, ss * subsurface_color.rgb, subsurface) + Fsheen) * light_diffuse;
- vec3 specular_bsdf = Gs * Fs * Ds * light_specular;
- diffuse_and_specular_bsdf = diffuse_bsdf * (1.0 - metallic) + specular_bsdf;
- }
- diffuse_and_specular_bsdf *= max(NdotL, 0.0);
+ vec3 bent_normal;
+ vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
+ float final_ao = occlusion_compute(normalize(worldNormal), viewPosition, 1.0, rand, bent_normal);
+ result = CLOSURE_DEFAULT;
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.radiance = final_ao * color.rgb;
+}
- float CNdotL = dot(CN, light_position);
- float CNdotV = dot(CN, V);
+#endif /* VOLUMETRICS */
- vec3 clearcoat_bsdf = vec3(0.0);
- if (CNdotL >= 0.0 && CNdotV >= 0.0 && clearcoat > 0.0) {
- float CNdotH = dot(CN, H);
- //float FH = schlick_fresnel(LdotH);
+/* emission */
- // clearcoat (ior = 1.5 -> F0 = 0.04)
- float Dr = GTR1(CNdotH, sqr(clearcoat_roughness));
- float Fr = fresnel_dielectric_cos(LdotH, 1.5); //mix(0.04, 1.0, FH);
- float Gr = smithG_GGX(CNdotL, 0.25) * smithG_GGX(CNdotV, 0.25);
+void node_emission(vec4 color, float strength, vec3 vN, out Closure result)
+{
+#ifndef VOLUMETRICS
+ color *= strength;
+ result = CLOSURE_DEFAULT;
+ result.radiance = color.rgb;
+ result.opacity = color.a;
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+#else
+ result = Closure(vec3(0.0), vec3(0.0), color.rgb * strength, 0.0);
+#endif
+}
- clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25) * light_specular;
- }
- clearcoat_bsdf *= max(CNdotL, 0.0);
+/* background */
- L += diffuse_and_specular_bsdf + clearcoat_bsdf;
- }
+void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
+{
+ vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (ProjectionMatrixInverse * v);
- result = vec4(L, 1.0);
+ vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ worldvec = (ViewMatrixInverse * co).xyz;
+#else
+ worldvec = (ModelViewMatrixInverse * co).xyz;
+#endif
}
-void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result)
+void node_background(vec4 color, float strength, out Closure result)
{
- node_bsdf_diffuse(color, 0.0, N, result);
+#ifndef VOLUMETRICS
+ color *= strength;
+ result = CLOSURE_DEFAULT;
+ result.radiance = color.rgb;
+ result.opacity = color.a;
+#else
+ result = CLOSURE_DEFAULT;
+#endif
}
-void node_bsdf_transparent(vec4 color, out vec4 result)
-{
- /* this isn't right */
- result.r = color.r;
- result.g = color.g;
- result.b = color.b;
- result.a = 0.0;
-}
+/* volumes */
-void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result)
+void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result)
{
- node_bsdf_diffuse(color, 0.0, N, result);
+#ifdef VOLUMETRICS
+ result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
}
-void node_subsurface_scattering(
- vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N,
- out vec4 result)
+void node_volume_absorption(vec4 color, float density, out Closure result)
{
- node_bsdf_diffuse(color, 0.0, N, result);
+#ifdef VOLUMETRICS
+ result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
}
-void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv, vec3 tangent, out vec4 result)
+void node_blackbody(float temperature, sampler2D spectrummap, out vec4 color)
{
- result = color;
+ if(temperature >= 12000.0) {
+ color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0);
+ }
+ else if(temperature < 965.0) {
+ color = vec4(4.70366907, 0.0, 0.0, 1.0);
+ }
+ else {
+ float t = (temperature - 965.0) / (12000.0 - 965.0);
+ color = vec4(texture(spectrummap, vec2(t, 0.0)).rgb, 1.0);
+ }
}
-void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out vec4 result)
+void node_volume_principled(
+ vec4 color,
+ float density,
+ float anisotropy,
+ vec4 absorption_color,
+ float emission_strength,
+ vec4 emission_color,
+ float blackbody_intensity,
+ vec4 blackbody_tint,
+ float temperature,
+ float density_attribute,
+ vec4 color_attribute,
+ float temperature_attribute,
+ sampler2D spectrummap,
+ out Closure result)
{
- node_bsdf_diffuse(color, 0.0, N, result);
-}
+#ifdef VOLUMETRICS
+ vec3 absorption_coeff = vec3(0.0);
+ vec3 scatter_coeff = vec3(0.0);
+ vec3 emission_coeff = vec3(0.0);
-void node_ambient_occlusion(vec4 color, out vec4 result)
-{
- result = color;
-}
+ /* Compute density. */
+ density = max(density, 0.0);
-/* emission */
+ if(density > 1e-5) {
+ density = max(density * density_attribute, 0.0);
+ }
-void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
-{
- result = color * strength;
-}
+ if(density > 1e-5) {
+ /* Compute scattering and absorption coefficients. */
+ vec3 scatter_color = color.rgb * color_attribute.rgb;
-/* background */
+ scatter_coeff = scatter_color * density;
+ absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0));
+ absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * density;
+ }
-void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
-{
- vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+ /* Compute emission. */
+ emission_strength = max(emission_strength, 0.0);
- vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
- worldvec = (gl_ModelViewMatrixInverse * co).xyz;
-}
+ if(emission_strength > 1e-5) {
+ emission_coeff += emission_strength * emission_color.rgb;
+ }
-void node_background(vec4 color, float strength, vec3 N, out vec4 result)
-{
- result = color * strength;
+ if(blackbody_intensity > 1e-3) {
+ /* Add temperature from attribute. */
+ float T = max(temperature * max(temperature_attribute, 0.0), 0.0);
+
+ /* Stefan-Boltzman law. */
+ float T4 = (T * T) * (T * T);
+ float sigma = 5.670373e-8 * 1e-6 / M_PI;
+ float intensity = sigma * mix(1.0, T4, blackbody_intensity);
+
+ if(intensity > 1e-5) {
+ vec4 bb;
+ node_blackbody(T, spectrummap, bb);
+ emission_coeff += bb.rgb * blackbody_tint.rgb * intensity;
+ }
+ }
+
+ result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
}
/* closures */
-void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader)
+void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader)
{
- shader = mix(shader1, shader2, fac);
+ shader = closure_mix(shader1, shader2, fac);
}
-void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
+void node_add_shader(Closure shader1, Closure shader2, out Closure shader)
{
- shader = shader1 + shader2;
+ shader = closure_add(shader1, shader2);
}
/* fresnel */
@@ -2830,7 +1406,7 @@ void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
void node_fresnel(float ior, vec3 N, vec3 I, out float result)
{
/* handle perspective/orthographic */
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
float eta = max(ior, 0.00001);
result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta);
@@ -2842,7 +1418,7 @@ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float
{
/* fresnel */
float eta = max(1.0 - blend, 0.00001);
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta);
@@ -2872,11 +1448,67 @@ void node_gamma(vec4 col, float gamma, out vec4 outcol)
/* geometry */
+void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ outvec = texture(tex, cos).aaa;
+ outcol = vec4(outvec, 1.0);
+ outf = dot(vec3(1.0 / 3.0), outvec);
+}
+
+void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+
+ vec4 value = texture(tex, cos).rgba;
+ /* Density is premultiplied for interpolation, divide it out here. */
+ if (value.a > 1e-8)
+ value.rgb /= value.a;
+
+ outvec = value.rgb;
+ outcol = vec4(outvec, 1.0);
+ outf = dot(vec3(1.0 / 3.0), outvec);
+}
+
+void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ outf = texture(tex, cos).r;
+ outvec = vec3(outf, outf, outf);
+ outcol = vec4(outf, outf, outf, 1.0);
+}
+
+void node_attribute_volume_temperature(sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ float flame = texture(tex, cos).r;
+
+ outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x): 0.0;
+ outvec = vec3(outf, outf, outf);
+ outcol = vec4(outf, outf, outf, 1.0);
+}
+
void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf)
{
outcol = vec4(attr, 1.0);
outvec = attr;
- outf = (attr.x + attr.y + attr.z) / 3.0;
+ outf = dot(vec3(1.0 / 3.0), attr);
}
void node_uvmap(vec3 attr_uv, out vec3 outvec)
@@ -2884,19 +1516,47 @@ void node_uvmap(vec3 attr_uv, out vec3 outvec)
outvec = attr_uv;
}
+void tangent_orco_x(vec3 orco_in, out vec3 orco_out)
+{
+ orco_out = vec3(0.0, (orco_in.z - 0.5) * -0.5, (orco_in.y - 0.5) * 0.5);
+}
+
+void tangent_orco_y(vec3 orco_in, out vec3 orco_out)
+{
+ orco_out = vec3((orco_in.z - 0.5) * -0.5, 0.0, (orco_in.x - 0.5) * 0.5);
+}
+
+void tangent_orco_z(vec3 orco_in, out vec3 orco_out)
+{
+ orco_out = vec3((orco_in.y - 0.5) * -0.5, (orco_in.x - 0.5) * 0.5, 0.0);
+}
+
+void node_tangentmap(vec4 attr_tangent, mat4 toworld, out vec3 tangent)
+{
+ tangent = (toworld * vec4(attr_tangent.xyz, 0.0)).xyz;
+}
+
+void node_tangent(vec3 N, vec3 orco, mat4 objmat, mat4 toworld, out vec3 T)
+{
+ N = (toworld * vec4(N, 0.0)).xyz;
+ T = (objmat * vec4(orco, 0.0)).xyz;
+ T = cross(N, normalize(cross(T, N)));
+}
+
void node_geometry(
- vec3 I, vec3 N, mat4 toworld,
+ vec3 I, vec3 N, vec3 orco, mat4 objmat, mat4 toworld,
out vec3 position, out vec3 normal, out vec3 tangent,
out vec3 true_normal, out vec3 incoming, out vec3 parametric,
out float backfacing, out float pointiness)
{
- position = (toworld * vec4(I, 1.0)).xyz;
+ position = worldPosition;
normal = (toworld * vec4(N, 0.0)).xyz;
- tangent = vec3(0.0);
+ tangent_orco_z(orco, orco);
+ node_tangent(N, orco, objmat, toworld, tangent);
true_normal = normal;
/* handle perspective/orthographic */
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
incoming = -(toworld * vec4(I_view, 0.0)).xyz;
parametric = vec3(0.0);
@@ -2910,16 +1570,15 @@ void node_tex_coord(
out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
out vec3 camera, out vec3 window, out vec3 reflection)
{
- generated = attr_orco * 0.5 + vec3(0.5);
+ generated = attr_orco;
normal = normalize((obinvmat * (viewinvmat * vec4(N, 0.0))).xyz);
uv = attr_uv;
object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz;
camera = vec3(I.xy, -I.z);
- vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
+ vec4 projvec = ProjectionMatrix * vec4(I, 1.0);
window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
- vec3 shade_I;
- shade_view(I, shade_I);
+ vec3 shade_I = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
vec3 view_reflection = reflect(shade_I, normalize(N));
reflection = (viewinvmat * vec4(view_reflection, 0.0)).xyz;
}
@@ -2930,13 +1589,18 @@ void node_tex_coord_background(
out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
out vec3 camera, out vec3 window, out vec3 reflection)
{
- vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+ vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (ProjectionMatrixInverse * v);
vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
co = normalize(co);
- vec3 coords = (gl_ModelViewMatrixInverse * co).xyz;
+
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ vec3 coords = (ViewMatrixInverse * co).xyz;
+#else
+ vec3 coords = (ModelViewMatrixInverse * co).xyz;
+#endif
generated = coords;
normal = -coords;
@@ -2944,13 +1608,17 @@ void node_tex_coord_background(
object = coords;
camera = vec3(co.xy, -co.z);
- window = (gl_ProjectionMatrix[3][3] == 0.0) ?
+ window = (ProjectionMatrix[3][3] == 0.0) ?
vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) :
vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0);
reflection = -coords;
}
+#if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER))
+#define node_tex_coord node_tex_coord_background
+#endif
+
/* textures */
float calc_gradient(vec3 p, int gradient_type)
@@ -3020,7 +1688,6 @@ void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 c
fac = check ? 1.0 : 0.0;
}
-#ifdef BIT_OPERATIONS
vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bias,
float brick_width, float row_height,
float offset_amount, int offset_frequency,
@@ -3056,7 +1723,6 @@ vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bi
return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist));
}
}
-#endif
void node_tex_brick(vec3 co,
vec4 color1, vec4 color2,
@@ -3067,7 +1733,6 @@ void node_tex_brick(vec3 co,
float squash_amount, float squash_frequency,
out vec4 color, out float fac)
{
-#ifdef BIT_OPERATIONS
vec2 f2 = calc_brick_texture(co * scale,
mortar_size, mortar_smooth, bias,
brick_width, row_height,
@@ -3081,10 +1746,6 @@ void node_tex_brick(vec3 co,
}
color = mix(color1, mortar, f);
fac = f;
-#else
- color = vec4(1.0);
- fac = 1.0;
-#endif
}
void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac)
@@ -3099,7 +1760,15 @@ void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color
float u = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5;
float v = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5;
- color = texture2D(ima, vec2(u, v));
+ /* Fix pole bleeding */
+ float half_width = 0.5 / float(textureSize(ima, 0).x);
+ v = clamp(v, half_width, 1.0 - half_width);
+
+ /* Fix u = 0 seam */
+ /* This is caused by texture filtering, since uv don't have smooth derivatives
+ * at u = 0 or 2PI, hardware filtering is using the smallest mipmap for certain
+ * texels. So we force the highest mipmap and don't do anisotropic filtering. */
+ color = textureLod(ima, vec2(u, v), 0.0);
}
void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color)
@@ -3115,7 +1784,7 @@ void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color)
float u = 0.5 * (nco.x + 1.0);
float v = 0.5 * (nco.z + 1.0);
- color = texture2D(ima, vec2(u, v));
+ color = texture(ima, vec2(u, v));
}
void node_tex_environment_empty(vec3 co, out vec4 color)
@@ -3125,7 +1794,7 @@ void node_tex_environment_empty(vec3 co, out vec4 color)
void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
{
- color = texture2D(ima, co.xy);
+ color = texture(ima, co.xy);
alpha = color.a;
}
@@ -3199,21 +1868,21 @@ void node_tex_image_box(vec3 texco,
if(signed_N.x < 0.0) {
uv.x = 1.0 - uv.x;
}
- color += weight.x * texture2D(ima, uv);
+ color += weight.x * texture(ima, uv);
}
if (weight.y > 0.0) {
vec2 uv = texco.xz;
if(signed_N.y > 0.0) {
uv.x = 1.0 - uv.x;
}
- color += weight.y * texture2D(ima, uv);
+ color += weight.y * texture(ima, uv);
}
if (weight.z > 0.0) {
vec2 uv = texco.yx;
if(signed_N.z > 0.0) {
uv.x = 1.0 - uv.x;
}
- color += weight.z * texture2D(ima, uv);
+ color += weight.z * texture(ima, uv);
}
alpha = color.a;
@@ -3286,7 +1955,6 @@ void node_tex_magic(vec3 co, float scale, float distortion, float depth, out vec
fac = (color.x + color.y + color.z) / 3.0;
}
-#ifdef BIT_OPERATIONS
float noise_fade(float t)
{
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
@@ -3361,10 +2029,9 @@ float noise_turbulence(vec3 p, float octaves, int hard)
float fscale = 1.0;
float amp = 1.0;
float sum = 0.0;
- int i, n;
octaves = clamp(octaves, 0.0, 16.0);
- n = int(octaves);
- for (i = 0; i <= n; i++) {
+ int n = int(octaves);
+ for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
if (hard != 0) {
t = abs(2.0 * t - 1.0);
@@ -3374,7 +2041,7 @@ float noise_turbulence(vec3 p, float octaves, int hard)
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
- if (rmd != 0.0) {
+ if (rmd != 0.0) {
float t = noise(fscale * p);
if (hard != 0) {
t = abs(2.0 * t - 1.0);
@@ -3389,11 +2056,9 @@ float noise_turbulence(vec3 p, float octaves, int hard)
return sum;
}
}
-#endif // BIT_OPERATIONS
void node_tex_noise(vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac)
{
-#ifdef BIT_OPERATIONS
vec3 p = co * scale;
int hard = 0;
if (distortion != 0.0) {
@@ -3409,15 +2074,8 @@ void node_tex_noise(vec3 co, float scale, float detail, float distortion, out ve
noise_turbulence(vec3(p.y, p.x, p.z), detail, hard),
noise_turbulence(vec3(p.y, p.z, p.x), detail, hard),
1);
-#else // BIT_OPERATIONS
- color = vec4(1.0);
- fac = 1.0;
-#endif // BIT_OPERATIONS
}
-
-#ifdef BIT_OPERATIONS
-
/* Musgrave fBm
*
* H: fractal increment parameter
@@ -3433,9 +2091,8 @@ float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves)
float value = 0.0;
float pwr = 1.0;
float pwHL = pow(lacunarity, -H);
- int i;
- for (i = 0; i < int(octaves); i++) {
+ for (int i = 0; i < int(octaves); i++) {
value += snoise(p) * pwr;
pwr *= pwHL;
p *= lacunarity;
@@ -3461,9 +2118,8 @@ float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octa
float value = 1.0;
float pwr = 1.0;
float pwHL = pow(lacunarity, -H);
- int i;
- for (i = 0; i < int(octaves); i++) {
+ for (int i = 0; i < int(octaves); i++) {
value *= (pwr * snoise(p) + 1.0);
pwr *= pwHL;
p *= lacunarity;
@@ -3489,13 +2145,12 @@ float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float oct
float value, increment, rmd;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
- int i;
/* first unscaled octave of function; later octaves are scaled */
value = offset + snoise(p);
p *= lacunarity;
- for (i = 1; i < int(octaves); i++) {
+ for (int i = 1; i < int(octaves); i++) {
increment = (snoise(p) + offset) * pwr * value;
value += increment;
pwr *= pwHL;
@@ -3524,13 +2179,12 @@ float noise_musgrave_hybrid_multi_fractal(vec3 p, float H, float lacunarity, flo
float result, signal, weight, rmd;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
- int i;
result = snoise(p) + offset;
weight = gain * result;
p *= lacunarity;
- for (i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
+ for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
if (weight > 1.0)
weight = 1.0;
@@ -3561,14 +2215,13 @@ float noise_musgrave_ridged_multi_fractal(vec3 p, float H, float lacunarity, flo
float result, signal, weight;
float pwHL = pow(lacunarity, -H);
float pwr = pwHL;
- int i;
signal = offset - abs(snoise(p));
signal *= signal;
result = signal;
weight = 1.0;
- for (i = 1; i < int(octaves); i++) {
+ for (int i = 1; i < int(octaves); i++) {
p *= lacunarity;
weight = clamp(signal * gain, 0.0, 1.0);
signal = offset - abs(snoise(p));
@@ -3590,19 +2243,18 @@ float svm_musgrave(int type,
float gain,
vec3 p)
{
- if (type == 0 /*NODE_MUSGRAVE_MULTIFRACTAL*/)
+ if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */)
return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
- else if (type == 1 /*NODE_MUSGRAVE_FBM*/)
+ else if (type == 1 /* NODE_MUSGRAVE_FBM */)
return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
- else if (type == 2 /*NODE_MUSGRAVE_HYBRID_MULTIFRACTAL*/)
+ else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */)
return intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
- else if (type == 3 /*NODE_MUSGRAVE_RIDGED_MULTIFRACTAL*/)
+ else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */)
return intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
- else if (type == 4 /*NODE_MUSGRAVE_HETERO_TERRAIN*/)
+ else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */)
return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
return 0.0;
}
-#endif // #ifdef BIT_OPERATIONS
void node_tex_musgrave(vec3 co,
float scale,
@@ -3615,7 +2267,6 @@ void node_tex_musgrave(vec3 co,
out vec4 color,
out float fac)
{
-#ifdef BIT_OPERATIONS
fac = svm_musgrave(int(type),
dimension,
lacunarity,
@@ -3624,9 +2275,6 @@ void node_tex_musgrave(vec3 co,
1.0,
gain,
co * scale);
-#else
- fac = 1.0;
-#endif
color = vec4(fac, fac, fac, 1.0);
}
@@ -3638,7 +2286,6 @@ void node_tex_sky(vec3 co, out vec4 color)
void node_tex_voronoi(vec3 co, float scale, float coloring, out vec4 color, out float fac)
{
-#ifdef BIT_OPERATIONS
vec3 p = co * scale;
int xx, yy, zz, xi, yi, zi;
float da[4];
@@ -3703,13 +2350,8 @@ void node_tex_voronoi(vec3 co, float scale, float coloring, out vec4 color, out
color = vec4(cellnoise_color(pa[0]), 1);
fac = (color.x + color.y + color.z) * (1.0 / 3.0);
}
-#else // BIT_OPERATIONS
- color = vec4(1.0);
- fac = 1.0;
-#endif // BIT_OPERATIONS
}
-#ifdef BIT_OPERATIONS
float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile)
{
float n;
@@ -3731,22 +2373,16 @@ float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int
return (n < 0.0) ? n + 1.0 : n;
}
}
-#endif // BIT_OPERATIONS
void node_tex_wave(
vec3 co, float scale, float distortion, float detail, float detail_scale, float wave_type, float wave_profile,
out vec4 color, out float fac)
{
-#ifdef BIT_OPERATIONS
float f;
f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile));
color = vec4(f, f, f, 1.0);
fac = f;
-#else // BIT_OPERATIONS
- color = vec4(1.0);
- fac = 1;
-#endif // BIT_OPERATIONS
}
/* light path */
@@ -3766,13 +2402,21 @@ void node_light_path(
out float transparent_depth,
out float transmission_depth)
{
+#ifndef PROBE_CAPTURE
is_camera_ray = 1.0;
- is_shadow_ray = 0.0;
- is_diffuse_ray = 0.0;
is_glossy_ray = 0.0;
- is_singular_ray = 0.0;
+ is_diffuse_ray = 0.0;
is_reflection_ray = 0.0;
is_transmission_ray = 0.0;
+#else
+ is_camera_ray = 0.0;
+ is_glossy_ray = 1.0;
+ is_diffuse_ray = 1.0;
+ is_reflection_ray = 1.0;
+ is_transmission_ray = 1.0;
+#endif
+ is_shadow_ray = 0.0;
+ is_singular_ray = 0.0;
ray_length = 1.0;
ray_depth = 1.0;
diffuse_depth = 1.0;
@@ -3835,6 +2479,23 @@ void node_bevel(float radius, vec3 N, out vec3 result)
result = N;
}
+void node_hair_info(out float is_strand, out float intercept, out float thickness, out vec3 tangent, out float random)
+{
+#ifdef HAIR_SHADER
+ is_strand = 1.0;
+ intercept = hairTime;
+ thickness = hairThickness;
+ tangent = normalize(worldNormal); /* TODO fix naming */
+ random = 0.0;
+#else
+ is_strand = 0.0;
+ intercept = 0.0;
+ thickness = 0.0;
+ tangent = vec3(1.0);
+ random = 0.0;
+#endif
+}
+
void node_displacement_object(float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result)
{
N = (vec4(N, 0.0) * obmat).xyz;
@@ -3871,37 +2532,75 @@ void node_vector_displacement_world(vec4 vector, float midlevel, float scale, ou
/* output */
-void node_output_material(vec4 surface, vec4 volume, vec3 displacement, out vec4 result)
+void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result)
{
+#ifdef VOLUMETRICS
+ result = volume;
+#else
result = surface;
+#endif
}
-void node_output_world(vec4 surface, vec4 volume, out vec4 result)
+uniform float backgroundAlpha;
+
+void node_output_world(Closure surface, Closure volume, out Closure result)
{
- result = surface;
+#ifndef VOLUMETRICS
+ result.radiance = surface.radiance;
+ result.opacity = backgroundAlpha;
+#else
+ result = volume;
+#endif /* VOLUMETRICS */
}
-/* ********************** matcap style render ******************** */
+#ifndef VOLUMETRICS
+/* TODO : clean this ifdef mess */
+/* EEVEE output */
+void world_normals_get(out vec3 N)
+{
+ N = gl_FrontFacing ? worldNormal : -worldNormal;
+}
-void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result)
+void node_eevee_specular(
+ vec4 diffuse, vec4 specular, float roughness, vec4 emissive, float transp, vec3 normal,
+ float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal,
+ float occlusion, float ssr_id, out Closure result)
{
- vec3 normal;
- vec2 tex;
-
-#ifndef USE_OPENSUBDIV
- /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
- * between shader stages and we want the full range of the normal */
- normal = vec3(2.0, 2.0, 2.0) * vec3(N.x, N.y, N.z) - vec3(1.0, 1.0, 1.0);
- if (normal.z < 0.0) {
- normal.z = 0.0;
+ vec3 out_diff, out_spec, ssr_spec;
+ eevee_closure_default(normal, diffuse.rgb, specular.rgb, int(ssr_id), roughness, occlusion,
+ out_diff, out_spec, ssr_spec);
+
+ vec3 vN = normalize(mat3(ViewMatrix) * normal);
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb;
+ result.opacity = 1.0 - transp;
+ result.ssr_data = vec4(ssr_spec, roughness);
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.ssr_id = int(ssr_id);
+}
+
+void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha)
+{
+ vec4 spec_accum = vec4(0.0);
+ if (ssrToggle && cl.ssr_id == outputSsrId) {
+ vec3 V = cameraVec;
+ vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec);
+ vec3 N = transform_direction(ViewMatrixInverse, vN);
+ float roughness = cl.ssr_data.a;
+ float roughnessSquared = max(1e-3, roughness * roughness);
+ fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum);
}
- normal = normalize(normal);
-#else
- normal = inpt.v.normal;
- mask = vec4(1.0, 1.0, 1.0, 1.0);
-#endif
- tex.x = 0.5 + 0.49 * normal.x;
- tex.y = 0.5 + 0.49 * normal.y;
- result = texture2D(ima, tex) * mask;
+ outalpha = cl.opacity;
+ outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0);
+
+# ifdef USE_SSS
+# ifdef USE_SSS_ALBEDO
+ outcol.rgb += cl.sss_data.rgb * cl.sss_albedo;
+# else
+ outcol.rgb += cl.sss_data.rgb;
+# endif
+# endif
}
+
+#endif /* VOLUMETRICS */
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl
new file mode 100644
index 00000000000..fef81cf58fe
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl
@@ -0,0 +1,24 @@
+
+uniform vec4 color;
+
+in vec2 radii;
+out vec4 fragColor;
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure point color
+// ...
+// dist = 0 at center of point
+
+ fragColor.rgb = color.rgb;
+ fragColor.a = mix(color.a, 0.0, smoothstep(radii[1], radii[0], dist));
+
+ if (fragColor.a == 0.0) {
+ discard;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl
new file mode 100644
index 00000000000..852c76fcb26
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl
@@ -0,0 +1,17 @@
+
+uniform vec4 color;
+
+out vec4 fragColor;
+
+void main()
+{
+ vec2 centered = gl_PointCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+
+ // round point with jaggy edges
+ if (dist_squared > rad_squared)
+ discard;
+
+ fragColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl
new file mode 100644
index 00000000000..eae5ee633ae
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl
@@ -0,0 +1,36 @@
+
+uniform vec4 color;
+uniform vec4 outlineColor;
+
+in vec4 radii;
+out vec4 fragColor;
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure point color
+// ...
+// dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ fragColor.rgb = outlineColor.rgb;
+ fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else {
+ fragColor = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist));
+ }
+
+ if (fragColor.a == 0.0) {
+ discard;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl
new file mode 100644
index 00000000000..2d2724bb686
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl
@@ -0,0 +1,16 @@
+
+in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ vec2 centered = gl_PointCoord - vec2(0.5);
+ float dist_squared = dot(centered, centered);
+ const float rad_squared = 0.25;
+
+ // round point with jaggy edges
+ if (dist_squared > rad_squared)
+ discard;
+
+ fragColor = finalColor;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl
new file mode 100644
index 00000000000..9b7d4bfc6d6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl
@@ -0,0 +1,31 @@
+
+uniform vec4 outlineColor;
+
+in vec4 radii;
+in vec4 fillColor;
+out vec4 fragColor;
+
+void main() {
+ float dist = length(gl_PointCoord - vec2(0.5));
+
+// transparent outside of point
+// --- 0 ---
+// smooth transition
+// --- 1 ---
+// pure outline color
+// --- 2 ---
+// smooth transition
+// --- 3 ---
+// pure fill color
+// ...
+// dist = 0 at center of point
+
+ float midStroke = 0.5 * (radii[1] + radii[2]);
+
+ if (dist > midStroke) {
+ fragColor.rgb = outlineColor.rgb;
+ fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist));
+ }
+ else
+ fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
index b485d2cce86..78241a798a2 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
@@ -1,16 +1,19 @@
uniform vec2 ScaleU;
uniform sampler2D textureSource;
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
void main()
{
vec4 color = vec4(0.0);
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y)) * 0.015625;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y)) * 0.09375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y)) * 0.234375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y)) * 0.234375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y)) * 0.09375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y)) * 0.015625;
+ color += texture(textureSource, texCoord_interp.st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y)) * 0.015625;
+ color += texture(textureSource, texCoord_interp.st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y)) * 0.09375;
+ color += texture(textureSource, texCoord_interp.st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y)) * 0.234375;
+ color += texture(textureSource, texCoord_interp.st + vec2(0.0, 0.0)) * 0.3125;
+ color += texture(textureSource, texCoord_interp.st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y)) * 0.234375;
+ color += texture(textureSource, texCoord_interp.st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y)) * 0.09375;
+ color += texture(textureSource, texCoord_interp.st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y)) * 0.015625;
- gl_FragColor = color;
+ fragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
index 5d00108b052..fca39852c2a 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -1,6 +1,14 @@
+out vec2 texCoord_interp;
+
void main()
{
- gl_Position = ftransform();
- gl_TexCoord[0] = gl_MultiTexCoord0;
+ const vec4 vert[3] = vec4[3](
+ vec3(-1.0, -1.0, 0.0, 0.0),
+ vec3( 3.0, -1.0, 2.0, 0.0),
+ vec3(-1.0, 3.0, 0.0, 2.0)
+ );
+
+ gl_Position = vec4(vert[gl_VertexID].xy, 0.0, 1.0);
+ texCoord_interp = vert[gl_VertexID].zw;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl
new file mode 100644
index 00000000000..d65768eff4d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl
@@ -0,0 +1,18 @@
+
+#ifndef USE_INSTANCE_COLOR
+uniform vec4 color;
+#endif
+uniform vec3 light;
+
+in vec3 normal;
+#ifdef USE_INSTANCE_COLOR
+flat in vec4 finalColor;
+# define color finalColor
+#endif
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color;
+ fragColor.xyz *= clamp(dot(normalize(normal), light), 0.0, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl
new file mode 100644
index 00000000000..6b13f408c84
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl
@@ -0,0 +1,14 @@
+
+uniform vec3 light;
+uniform float alpha;
+uniform float global;
+
+in vec3 normal;
+in vec4 finalColor;
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor * (global + (1.0 - global) * max(0.0, dot(normalize(normal), light)));
+ fragColor.a = alpha;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl
new file mode 100644
index 00000000000..58c5f292647
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl
@@ -0,0 +1,16 @@
+
+uniform vec3 light;
+
+#ifdef USE_FLAT_NORMAL
+flat in vec3 normal;
+flat in vec4 finalColor;
+#else
+in vec3 normal;
+in vec4 finalColor;
+#endif
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = finalColor * max(0.0, dot(normalize(normal), light));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
index 6ded453225e..b57bd5b6a37 100644
--- a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
@@ -1,5 +1,6 @@
-varying vec3 coords;
+in vec3 coords;
+out vec4 fragColor;
uniform vec3 active_color;
uniform float step_size;
@@ -16,7 +17,7 @@ uniform sampler3D color_band_texture;
void main()
{
/* compute color and density from volume texture */
- vec4 soot = texture3D(soot_texture, coords);
+ vec4 soot = texture(soot_texture, coords);
#ifndef USE_COBA
vec3 soot_color;
@@ -24,7 +25,7 @@ void main()
soot_color = active_color * soot.rgb / soot.a;
}
else {
- soot_color = vec3(0, 0, 0);
+ soot_color = vec3(0);
}
float soot_density = density_scale * soot.a;
@@ -33,16 +34,14 @@ void main()
float soot_alpha = 1.0 - soot_transmittance;
/* shade */
- float shadow = texture3D(shadow_texture, coords).r;
+ float shadow = texture(shadow_texture, coords).r;
soot_color *= soot_transmittance * shadow;
/* premultiply alpha */
- vec4 color = vec4(soot_alpha * soot_color, soot_alpha);
+ fragColor = vec4(soot_alpha * soot_color, soot_alpha);
#else
- float color_band = texture3D(color_band_texture, coords).r;
- vec4 transfer_function = texture1D(transfer_texture, color_band);
- vec4 color = transfer_function * density_scale;
+ float color_band = texture(color_band_texture, coords).r;
+ vec4 transfer_function = texture(transfer_texture, color_band);
+ fragColor = transfer_function * density_scale;
#endif
-
- gl_FragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
index 297486ae26a..8c30e9baf9e 100644
--- a/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
@@ -1,5 +1,7 @@
-varying vec3 coords;
+uniform mat4 ModelViewProjectionMatrix;
+
+out vec3 coords;
uniform vec3 min_location;
uniform vec3 invsize;
@@ -7,6 +9,7 @@ uniform vec3 ob_sizei;
void main()
{
- gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz * ob_sizei, 1.0);
+ // TODO: swap gl_Vertex for vec3 pos, update smoke setup code
+ gl_Position = ModelViewProjectionMatrix * vec4(gl_Vertex.xyz * ob_sizei, 1.0);
coords = (gl_Vertex.xyz - min_location) * invsize;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
new file mode 100644
index 00000000000..fbfa4cfcc9d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
@@ -0,0 +1,74 @@
+
+flat in vec4 color_flat;
+flat in vec4 texCoord_rect;
+noperspective in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D glyph;
+
+const vec2 offsets4[4] = vec2[4](
+ vec2(-0.5, 0.5), vec2( 0.5, 0.5),
+ vec2(-0.5, -0.5), vec2(-0.5, -0.5)
+);
+
+const vec2 offsets16[16] = vec2[16](
+ vec2(-1.5, 1.5), vec2(-0.5, 1.5), vec2( 0.5, 1.5), vec2( 1.5, 1.5),
+ vec2(-1.5, 0.5), vec2(-0.5, 0.5), vec2( 0.5, 0.5), vec2( 1.5, 0.5),
+ vec2(-1.5, -0.5), vec2(-0.5, -0.5), vec2( 0.5, -0.5), vec2( 1.5, -0.5),
+ vec2(-1.5, -1.5), vec2(-0.5, -1.5), vec2( 0.5, -1.5), vec2( 1.5, -1.5)
+);
+
+#define sample_glyph_offset(texco, texel, ofs) texture(glyph, texco + ofs * texel).r
+
+void main()
+{
+ // input color replaces texture color
+ fragColor.rgb = color_flat.rgb;
+
+ vec2 texel = 1.0 / vec2(textureSize(glyph, 0));
+ vec2 texco = mix(abs(texCoord_rect.xy), abs(texCoord_rect.zw), texCoord_interp);
+
+ // modulate input alpha & texture alpha
+ if (texCoord_rect.x > 0) {
+ fragColor.a = texture(glyph, texco).r;
+ }
+ else {
+ fragColor.a = 0.0;
+
+ if (texCoord_rect.w > 0) {
+ /* 3x3 blur */
+ /* Manual unroll for perf. (stupid glsl compiler) */
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[0]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[1]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[2]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets4[3]);
+ fragColor.a *= (1.0 / 4.0);
+ }
+ else {
+ /* 5x5 blur */
+ /* Manual unroll for perf. (stupid glsl compiler) */
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 0]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 1]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 2]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 3]);
+
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 4]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 5]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 6]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 7]);
+
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 8]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 9]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[10]) * 2.0;
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[11]);
+
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[12]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[13]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[14]);
+ fragColor.a += sample_glyph_offset(texco, texel, offsets16[15]);
+ fragColor.a *= (1.0 / 20.0);
+ }
+ }
+
+ fragColor.a *= color_flat.a;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl
new file mode 100644
index 00000000000..0acd2106f7a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl
@@ -0,0 +1,37 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+in vec4 pos_rect[];
+in vec4 tex_rect[];
+in vec4 color[];
+
+flat out vec4 color_flat;
+flat out vec4 texCoord_rect;
+noperspective out vec2 texCoord_interp;
+
+void main()
+{
+ color_flat = color[0];
+ texCoord_rect = tex_rect[0];
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xy, 0.0, 1.0));
+ texCoord_interp = vec2(0.0, 0.0);
+ EmitVertex();
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zy, 0.0, 1.0));
+ texCoord_interp = vec2(1.0, 0.0);
+ EmitVertex();
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xw, 0.0, 1.0));
+ texCoord_interp = vec2(0.0, 1.0);
+ EmitVertex();
+
+ gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zw, 0.0, 1.0));
+ texCoord_interp = vec2(1.0, 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl
new file mode 100644
index 00000000000..8903fd1df57
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl
@@ -0,0 +1,36 @@
+
+layout(points) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+in vec4 pos_rect[];
+in vec4 tex_rect[];
+in vec4 color[];
+
+flat out vec4 color_flat;
+flat out vec4 texCoord_rect;
+noperspective out vec2 texCoord_interp;
+
+void main()
+{
+ color_flat = color[0];
+ texCoord_rect = tex_rect[0];
+ gl_Position.zw = vec2(0.0, 1.0);
+
+ gl_Position.xy = pos_rect[0].xy;
+ texCoord_interp = vec2(0.0, 0.0);
+ EmitVertex();
+
+ gl_Position.xy = pos_rect[0].zy;
+ texCoord_interp = vec2(1.0, 0.0);
+ EmitVertex();
+
+ gl_Position.xy = pos_rect[0].xw;
+ texCoord_interp = vec2(0.0, 1.0);
+ EmitVertex();
+
+ gl_Position.xy = pos_rect[0].zw;
+ texCoord_interp = vec2(1.0, 1.0);
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl
new file mode 100644
index 00000000000..4a2cde71e07
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl
@@ -0,0 +1,22 @@
+
+/* Simpler version of gpu_shader_text_vert that supports only 2D translation. */
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec4 pos; /* rect */
+in vec4 tex; /* rect */
+in vec4 col;
+
+out vec4 pos_rect;
+out vec4 tex_rect;
+out vec4 color;
+
+void main()
+{
+ /* Manual mat4*vec2 */
+ pos_rect = ModelViewProjectionMatrix[0].xyxy * pos.xxzz;
+ pos_rect += ModelViewProjectionMatrix[1].xyxy * pos.yyww;
+ pos_rect += ModelViewProjectionMatrix[3].xyxy;
+ tex_rect = tex;
+ color = col;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
new file mode 100644
index 00000000000..338156f5b68
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl
@@ -0,0 +1,17 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec4 pos; /* rect */
+in vec4 tex; /* rect */
+in vec4 col;
+
+out vec4 pos_rect;
+out vec4 tex_rect;
+out vec4 color;
+
+void main()
+{
+ pos_rect = pos;
+ tex_rect = tex;
+ color = col;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl
new file mode 100644
index 00000000000..118a661863d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl
@@ -0,0 +1,21 @@
+
+#if defined(USE_COLOR_U32)
+uniform uint color;
+#else
+uniform vec4 color;
+#endif
+
+out vec4 fragColor;
+
+void main()
+{
+#if defined(USE_COLOR_U32)
+ fragColor = vec4(
+ ((color ) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 8) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 16) & uint(0xFF)) * (1.0f / 255.0f),
+ ((color >> 24) ) * (1.0f / 255.0f));
+#else
+ fragColor = color;
+#endif
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
index db0068d2f3d..2a6c137e195 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
@@ -1,3 +1,8 @@
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat3 NormalMatrix;
+
#ifdef USE_OPENSUBDIV
in vec3 normal;
in vec4 position;
@@ -7,8 +12,8 @@ out block {
} outpt;
#endif
-varying vec3 varposition;
-varying vec3 varnormal;
+out vec3 varposition;
+out vec3 varnormal;
#ifdef CLIP_WORKAROUND
varying float gl_ClipDistance[6];
@@ -42,11 +47,7 @@ void srgb_to_linearrgb(vec4 col_from, out vec4 col_to)
bool is_srgb(int info)
{
-#ifdef USE_NEW_SHADING
return (info == 1)? true: false;
-#else
- return false;
-#endif
}
void set_var_from_attr(float attr, int info, out float var)
@@ -89,11 +90,11 @@ void main()
vec3 normal = gl_Normal;
#endif
- vec4 co = gl_ModelViewMatrix * position;
+ vec4 co = ModelViewMatrix * position;
varposition = co.xyz;
- varnormal = normalize(gl_NormalMatrix * normal);
- gl_Position = gl_ProjectionMatrix * co;
+ varnormal = normalize(NormalMatrix * normal);
+ gl_Position = ProjectionMatrix * co;
#ifdef CLIP_WORKAROUND
int i;
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
index d45a4b316a8..af2e4ba19a2 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
@@ -1,7 +1,6 @@
-varying vec3 varposition;
-varying vec3 varnormal;
-
+out vec3 varposition;
+out vec3 varnormal;
/* Color, keep in sync with: gpu_shader_vertex.glsl */
@@ -30,11 +29,7 @@ void srgb_to_linearrgb(vec4 col_from, out vec4 col_to)
bool is_srgb(int info)
{
-#ifdef USE_NEW_SHADING
return (info == 1)? true: false;
-#else
- return false;
-#endif
}
void set_var_from_attr(float attr, int info, out float var)
diff --git a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
index 3761bf350eb..6aad94bbf59 100644
--- a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
@@ -2,7 +2,8 @@
* This fragment shader was initially found at http://fabiensanglard.net/shadowmappingVSM/index.php
*/
-varying vec4 v_position;
+in vec4 v_position;
+out vec4 fragColor;
void main()
{
@@ -17,5 +18,6 @@ void main()
float dy = dFdy(depth);
moment2 += 0.25 * (dx * dx + dy * dy);
- gl_FragColor = vec4(moment1, moment2, 0.0, 0.0);
+ fragColor = vec4(moment1, moment2, 0.0, 0.0);
+ // TODO: write to a 2-component target --^
}
diff --git a/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl b/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl
index 224c3e78adc..def835156f7 100644
--- a/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl
@@ -1,7 +1,10 @@
-varying vec4 v_position;
+
+uniform mat4 ModelViewProjectionMatrix;
+
+out vec4 v_position;
void main()
{
- gl_Position = ftransform();
+ gl_Position = ModelViewProjectionMatrix * gl_Vertex;
v_position = gl_Position;
}