1
1

Compare commits

...

90 Commits

Author SHA1 Message Date
a35c635edb Merge branch 'master' into tmp-overlay-engine
# Conflicts:
#	source/blender/draw/modes/paint_texture_mode.c
2019-12-02 01:40:58 +01:00
7164e63fef Overlay Engine: Change Antialiasing implementation to a novel method! 2019-12-02 01:31:05 +01:00
915e54ee9d Overlay Engine: Fix Sculpt Mask overlay 2019-12-01 12:30:17 +01:00
4926e7413d Overlay Engine: Add SMAA to replace FXAA
This gets rid of the TAA which needs to be added back
2019-11-29 15:51:02 +01:00
2c5cd812f7 Overlay Engine: Fix loose wire showing after edit mode and not showing in..
Material mode.
2019-11-28 19:23:35 +01:00
2367fd9e1f Overlay Engine: Fix issue with facing overlay
Render using the default view instead of the jittered view.
2019-11-28 12:10:33 +01:00
4e298108a3 Overlay Engine: Fix/Improve Temporal AntiAliasing
We now render 5 samples using some kind of quicunx sample position with
the first sample in the center and the 4 others being a rotated square.

Also remove a bug where the last sample would never be rendered.
2019-11-27 16:51:14 +01:00
1a44c77bb4 Merge branch 'master' into tmp-overlay-engine 2019-11-27 15:55:16 +01:00
120a7e1b44 Overlay Engine: Fix crash when enabling pose bone selection overlay 2019-11-27 15:54:50 +01:00
626e291d1c Overlay Engine: Wireframe: Fix wireframe overlay on top of infront objects 2019-11-27 15:24:24 +01:00
4b7cdfe6f9 Cleanup: Code readability/simplicity 2019-11-27 15:19:52 +01:00
d33477d1a4 Overlay Engine: Fix armature shape always transparent 2019-11-27 15:19:31 +01:00
5daca04d4e Overlay Engine: Fix Paint overlays disapearing because of TAA 2019-11-27 14:22:30 +01:00
8b48b5a11d Merge branch 'master' into tmp-overlay-engine 2019-11-27 11:11:01 +01:00
da13ddb65a Overlay Engine: Fix Armature bone toggle 2019-11-27 11:10:02 +01:00
c980f9e652 Overlay Engine: Make overlay parameters reset TAA 2019-11-27 11:09:40 +01:00
443effa45f Overlay Engine: Update overlays on ID update 2019-11-26 18:56:45 +01:00
4baf738540 Edit Armature: Tag armature after any operator to invalidate viewport
This is needed for smart AA (avoid anoying flickering of the overlays).
2019-11-26 18:56:14 +01:00
dfad332740 Fix Wireframe issue with infront objects
We were testing against the stencil buffer but the actual stencil was not
the one expected. But with current implementation it is not even required
so we just bypass it.
2019-11-26 16:36:05 +01:00
ded3fc0725 Fix infront selectability of solid objects 2019-11-26 15:39:15 +01:00
7330b347d7 Fix In Front object selectability
We use the same trick as before but we now isolate it to a drawmanager
state to avoid loosing track of the state.
2019-11-26 15:14:55 +01:00
d4420d7070 Fix FXAA alpha issue.
We just take the full RGBA color instead of packing the luma in alpha.
2019-11-26 13:37:12 +01:00
41dbaa4aee Fix crash caused by copy pasting! 2019-11-26 13:34:10 +01:00
9a207356ca Cleanup: Naming conventions, code clarity mentionned in review 2019-11-26 13:15:39 +01:00
1b32f27b13 Cleanup: Fix copyright year 2019-11-26 11:40:18 +01:00
6183d49ad8 Merge branch 'master' into tmp-overlay-engine 2019-11-24 01:40:29 +01:00
bd09bd2ffa Overlay Engine: Fix overlay toggle not working 2019-11-24 01:39:01 +01:00
03cc35013c Overlay Engine: Only alloc extra depth texture if really needed
However this is a bit hacky as both workbench deferred and overlay engine
are responsible to ensure the texture is correctly allocated and framebuffers
are settuped.
2019-11-24 01:09:40 +01:00
c7a13de09a Overlay Engine: Add Temporal Anti Aliasing
This add a very simple form of TAA for the overlay engine (in a similar
way as workbench does).
For now it only supports 4 samples but this can easily improved.

The update is not working all the time (i.e: armature edit/pose).
2019-11-24 00:31:42 +01:00
98360afb33 Overlay Engine: Add FXAA as base Antialiasing
This will be enhanced by TAA or other technique.
2019-11-23 14:14:15 +01:00
2723032ca7 Overlay Engine: Fix selection outline antialiasing 2019-11-23 14:09:09 +01:00
1552dd3f16 Overlay Mode: Fix infront depth sorting
This is an improvement to 2.81. In front objects and extras are correctly
depth sorted.

The approach is to share an in-front depth buffer between all engines
so that workbench fill it with the infront objects depth. Then the overlay
engine can use it again to draw in front objects overlays correctly
occluded by the other "in front" objects surfaces.
2019-11-22 17:39:59 +01:00
7c17e76e0e Overlay Engine: Improve In Front pass ordering
This does not fix all the issues. For instance extra's are always drawn
occluded.
2019-11-22 16:26:27 +01:00
d027db16e3 Cleanup: Fix debug Compilation warning 2019-11-22 01:32:40 +01:00
cfcbb1daee Overlay Engine: Wireframe: Put color evaluation in the shader
There are no more subgroups per color. Thus wireframes leveraging the
batching capabilities of DRWmanager.

The color mixing is also now done per vertex and interpolated instead of
per pixel. This might change the rendering a little bit.

This also fixes the xray rendering for wireframes and osx workaround shader.
2019-11-22 01:30:26 +01:00
fa009ca0bd Cleanup: DRW: Remove unused GPUBatches from Shape cache 2019-11-21 17:27:37 +01:00
06bbcb8ffa Cleanup: DRW: Remove Hack of skinroot rendering 2019-11-21 17:27:05 +01:00
e0a0f1cbe0 DRW: Fix an issue with instanced rendering and base_instance
Batches that are meant to be drawn with instancing cannot use ModelMatrix
indexing and must rely on the uniform (legacy) way.

Using the BaseInstance indexing would shift the instance attributes
received by the vertex shader which is not what we want in this case.
2019-11-21 17:25:34 +01:00
79beba2005 Merge branch 'master' into tmp-overlay-engine 2019-11-20 20:52:09 +01:00
3cd95fc46f Overlay Engine: Armature: Bone selection overlay
I forgot to implement this back
2019-11-20 20:51:07 +01:00
0a9ff3d25a BLF: Remove use of geometry shader 2019-11-20 20:51:07 +01:00
ed12703bd1 Cleanup: Remove more unused files 2019-11-20 20:51:07 +01:00
4bf0c9793a GPU: Remove The use of geom shader for dashed lines
Use the same trick used in overlay engine.

Also fixed some undefined behavior with missing viewport uniform in some
calls.
2019-11-20 20:51:07 +01:00
b695343c6c Cleanup: GPU: Remove unused shaders 2019-11-20 20:51:06 +01:00
ae3687ac48 Cleanup: DRW: Remove old unused code 2019-11-20 20:51:06 +01:00
00ba7b314e Cleanup: Remove older draw engine from draw module 2019-11-20 20:51:06 +01:00
a527a3e159 Cleanup: Make empty image use quad batch instead of specific batch 2019-11-20 20:51:06 +01:00
f21f35b68d Overlay Engine: Edit Mode: Change Normal overlays
This gets rid of the geometry shader for normal display.
(note: happens to be twice as fast)
This also remove the unecessary shader variations.

Another goal was to get the do_zbufclip behavior back.
We occlude the base vertex which can occasion some flickers bu
2019-11-20 20:51:06 +01:00
52e69ce747 GPU: Batch: Add second instance buffer
This is needed in one corner case. In an attempt to get rid of geometry
shader, we need to use instancing using pos and lnor vbos for edit mesh
normals overlay.

This is a bit hacky and quickly made. This should be do more thoroughly.
2019-11-20 20:51:06 +01:00
b5d3d4e41f Overlay Engine: Edit Mesh: Port Occlusion detection to shader
This moves the occluded wire fading at the edit cage drawing, thus removing
the need for a fullscreen compositing pass.
2019-11-19 19:03:17 +01:00
872cbbf84f Cleanup: Port back the custom shape ghash to revert perf regression
Using the DRW instancing is much slower because the modelmat ubo is too
small to contain many obmat of the same GPUBatch type.
2019-11-19 00:44:35 +01:00
75c39c8d23 Cleanup: Remove stipple start position duplication
Removes 3 floats per stipple vert. Using the same technique we could
remove the need for geom shader for GPU internal shader shader.
2019-11-19 00:41:04 +01:00
a9c8eab4b6 Overlay Engine: Loose Edges/Verts 2019-11-18 23:05:39 +01:00
122b04aec5 Merge branch 'master' into tmp-overlay-engine 2019-11-18 20:13:00 +01:00
d78bd78c14 Overlay Engine: Fix background image and sort empty images by Z depth 2019-11-18 20:12:21 +01:00
5ea8bed6f2 Overlay Engine: Sculpt Mask 2019-11-18 17:46:47 +01:00
0417033bf3 Overlay Engine: Particles 2019-11-18 17:20:09 +01:00
e06882633a Overlay Engine: Paint Modes 2019-11-17 02:27:39 +01:00
89b3a9c147 Overlay Engine: Lattice
Cleanup: Port lattice wireframe coloring to shader
2019-11-16 21:44:36 +01:00
7282ecc672 Overlay Engine: MetaBall
Note: This also improve handles positioning using the armature point shader
2019-11-16 17:26:31 +01:00
380a702172 Overlay Engine: Edit Text 2019-11-16 00:29:23 +01:00
0a12d49392 Overlay Engine: Edit Curve / Surface 2019-11-16 00:28:08 +01:00
53bce31c95 Overlay Engine: Fix warnings 2019-11-15 20:24:28 +01:00
995a96e630 Overlay Engine: Motion Path
- Now working with Alt+B clipping
- Now scalling with DPI setting
2019-11-15 18:00:57 +01:00
2a02329cb2 Fix Assert from missing UBO bind 2019-11-15 17:47:50 +01:00
99fcb0a2ca Fix compilation
Commited this cleanup by mistake
2019-11-15 01:43:22 +01:00
864ec2cb54 Merge branch 'master' into tmp-overlay-engine 2019-11-15 01:33:55 +01:00
5cae096d13 Overlay Engine: Camera Background Images 2019-11-15 01:31:08 +01:00
73162d80c2 Overlay Engine: Image Empties 2019-11-15 01:30:35 +01:00
9364ae3984 Fix groundline not being clipped by Alt+B box clipping 2019-11-14 01:58:57 +01:00
0389895f25 Cleanup: Use DRW_shgroup_uniform_vec4_copy 2019-11-13 16:28:04 +01:00
632b00aead Overlay Engine: Armatures 2019-11-12 02:36:24 +01:00
1bf797be98 Cleanup: Port screenVecs, pixelSize (pixelFac) and sizeViewport to UBO 2019-11-10 02:11:11 +01:00
ecd57e8184 Overlay Engine: Volume Velocity 2019-11-10 00:53:01 +01:00
5e9dd6d2b4 Overlay Engine: Origin transform axes 2019-11-10 00:51:39 +01:00
551c10f8ce Overlay Engine: Forcefield 2019-11-09 21:57:12 +01:00
08466bebdf Overlay Engine: Lightprobes & Speakers 2019-11-09 01:31:35 +01:00
d16c0501bd Overlay Engine: More Extra overlays
- Stippled Relationship Lines (without geometry shader)
- Object centers
- Objects Names
- Bounds
- A bit of code reorganisation
2019-11-08 22:50:39 +01:00
8e49022d93 Overlay Engine: Camera Reconstruction & Tracking 2019-11-08 17:18:43 +01:00
32fb5f7a6b Fix camera triangle appearing in camera view 2019-11-08 17:16:58 +01:00
38ef4c02e1 Overlay Engine: Empties 2019-11-08 02:51:58 +01:00
d2a1d222c0 Overlay Engine: Add Camera & Stereo Camera
This change a few thing:
- This fixes the toe-in convergence plane drawing issue.
- The volume wires are drawn without depth write to avoid Z-fighting.
2019-11-07 17:44:50 +01:00
fb7d446e37 Overlay Engine: Fix light distance display scalling with object size 2019-11-06 14:46:52 +01:00
3f651fb979 Overlay Engine: Separate GroundLine/Point to a separate buffer 2019-11-06 14:10:05 +01:00
6f260d96a4 Fix compilation error 2019-11-06 13:27:10 +01:00
8ccff665fc Overlay Engine: Add Lamps 2019-11-06 02:53:48 +01:00
bca4edeb14 Overlay Engine: Add Edit Mesh 2019-11-04 16:35:10 +01:00
0c28626de6 Overlay Engine: Add Outline 2019-11-02 01:39:59 +01:00
029587583b Overlay Engine: Add Grid 2019-11-01 15:41:19 +01:00
f3a6fe1c73 Overlay Engine: Initial Commit
This merges all overlay draw engines into one unique engine.

The goal here is to have more flexibility on how to draw overlays and
overcome some of the current design limitation.
2019-11-01 15:40:55 +01:00
216 changed files with 29235 additions and 16147 deletions

View File

@@ -168,6 +168,7 @@ class DATA_PT_lightprobe_display(DataButtonsPanel, Panel):
if probe.type == 'PLANAR':
col.prop(ob, "empty_display_size", text="Arrow Size")
col.prop(probe, "show_influence")
col.prop(probe, "show_data")
if probe.type in {'GRID', 'CUBEMAP'}:

View File

@@ -96,7 +96,13 @@ static void blf_batch_draw_init(void)
GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
g_batch.glyph_len = 0;
g_batch.batch = GPU_batch_create_ex(GPU_PRIM_POINTS, g_batch.verts, NULL, GPU_BATCH_OWNS_VBO);
/* A dummy vbo containing 4 points, attribs are not used. */
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
GPU_vertbuf_data_alloc(vbo, 4);
/* We render a quad as a triangle strip and instance it for each glyph. */
g_batch.batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO);
GPU_batch_instbuf_set(g_batch.batch, g_batch.verts, true);
}
static void blf_batch_draw_exit(void)
@@ -188,8 +194,7 @@ void blf_batch_draw(void)
GPU_vertbuf_data_len_set(g_batch.verts, g_batch.glyph_len);
GPU_vertbuf_use(g_batch.verts); /* send data */
eGPUBuiltinShader shader = (g_batch.simple_shader) ? GPU_SHADER_TEXT_SIMPLE : GPU_SHADER_TEXT;
GPU_batch_program_set_builtin(g_batch.batch, shader);
GPU_batch_program_set_builtin(g_batch.batch, GPU_SHADER_TEXT);
GPU_batch_uniform_1i(g_batch.batch, "glyph", 0);
GPU_batch_draw(g_batch.batch);

View File

@@ -21,7 +21,6 @@
set(INC
.
intern
modes
../blenfont
../blenkernel
@@ -49,8 +48,6 @@ set(INC_SYS
)
set(SRC
intern/draw_anim_viz.c
intern/draw_armature.c
intern/draw_cache.c
intern/draw_cache_extract_mesh.c
intern/draw_cache_impl_curve.c
@@ -72,20 +69,6 @@ set(SRC
intern/draw_manager_texture.c
intern/draw_select_buffer.c
intern/draw_view.c
modes/edit_armature_mode.c
modes/edit_curve_mode.c
modes/edit_lattice_mode.c
modes/edit_mesh_mode.c
modes/edit_mesh_mode_text.c
modes/edit_metaball_mode.c
modes/edit_text_mode.c
modes/object_mode.c
modes/overlay_mode.c
modes/paint_texture_mode.c
modes/paint_vertex_mode.c
modes/particle_mode.c
modes/pose_mode.c
modes/sculpt_mode.c
engines/basic/basic_engine.c
engines/eevee/eevee_bloom.c
engines/eevee/eevee_data.c
@@ -136,6 +119,25 @@ set(SRC
engines/gpencil/gpencil_shader_fx.c
engines/select/select_draw_utils.c
engines/select/select_engine.c
engines/overlay/overlay_antialiasing.c
engines/overlay/overlay_armature.c
engines/overlay/overlay_engine.c
engines/overlay/overlay_edit_curve.c
engines/overlay/overlay_edit_text.c
engines/overlay/overlay_edit_mesh.c
engines/overlay/overlay_extra.c
engines/overlay/overlay_facing.c
engines/overlay/overlay_grid.c
engines/overlay/overlay_image.c
engines/overlay/overlay_lattice.c
engines/overlay/overlay_metaball.c
engines/overlay/overlay_motion_path.c
engines/overlay/overlay_outline.c
engines/overlay/overlay_paint.c
engines/overlay/overlay_particle.c
engines/overlay/overlay_shader.c
engines/overlay/overlay_sculpt.c
engines/overlay/overlay_wireframe.c
DRW_engine.h
DRW_select_buffer.h
@@ -152,8 +154,7 @@ set(SRC
intern/draw_manager_profiling.h
intern/draw_manager_text.h
intern/draw_view.h
modes/draw_mode_engines.h
modes/edit_mesh_mode_intern.h
intern/smaa_textures.h
engines/basic/basic_engine.h
engines/eevee/eevee_engine.h
engines/eevee/eevee_lightcache.h
@@ -164,6 +165,8 @@ set(SRC
engines/workbench/workbench_private.h
engines/select/select_engine.h
engines/select/select_private.h
engines/overlay/overlay_engine.h
engines/overlay/overlay_private.h
)
set(LIB
@@ -261,90 +264,14 @@ data_to_c_simple(engines/workbench/shaders/workbench_volume_vert.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_volume_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_world_light_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_colormanagement_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_hair_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_hair_refine_vert.glsl SRC)
data_to_c_simple(modes/shaders/common_view_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_fxaa_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_fullscreen_vert.glsl SRC)
data_to_c_simple(modes/shaders/animviz_mpath_lines_vert.glsl SRC)
data_to_c_simple(modes/shaders/animviz_mpath_lines_geom.glsl SRC)
data_to_c_simple(modes/shaders/animviz_mpath_points_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_axes_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_sphere_solid_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_sphere_solid_frag.glsl SRC)
data_to_c_simple(modes/shaders/armature_sphere_outline_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_envelope_solid_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_envelope_solid_frag.glsl SRC)
data_to_c_simple(modes/shaders/armature_envelope_outline_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_envelope_distance_frag.glsl SRC)
data_to_c_simple(modes/shaders/armature_shape_solid_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_shape_solid_frag.glsl SRC)
data_to_c_simple(modes/shaders/armature_shape_outline_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_shape_outline_geom.glsl SRC)
data_to_c_simple(modes/shaders/armature_stick_vert.glsl SRC)
data_to_c_simple(modes/shaders/armature_stick_frag.glsl SRC)
data_to_c_simple(modes/shaders/armature_dof_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_common_lib.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_geom.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_mesh_analysis_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_skin_root_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_handle_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_handle_geom.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_loosevert_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_normals_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_lattice_overlay_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_lattice_overlay_loosevert_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_normals_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_normals_geom.glsl SRC)
data_to_c_simple(modes/shaders/overlay_face_orientation_frag.glsl SRC)
data_to_c_simple(modes/shaders/overlay_face_orientation_vert.glsl SRC)
data_to_c_simple(modes/shaders/overlay_face_wireframe_vert.glsl SRC)
data_to_c_simple(modes/shaders/overlay_face_wireframe_geom.glsl SRC)
data_to_c_simple(modes/shaders/overlay_face_wireframe_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_camera_image_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_camera_image_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_color_axes_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_empty_axes_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_empty_image_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_outline_resolve_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_outline_expand_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_outline_detect_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_outline_prepass_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_outline_prepass_geom.glsl SRC)
data_to_c_simple(modes/shaders/object_outline_prepass_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_grid_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_grid_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_lightprobe_grid_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_mball_handles_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_prim_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_dot_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_dot_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_loose_points_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_texture_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_texture_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_vertex_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_vertex_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_weight_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_weight_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_face_selection_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_face_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_wire_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_wire_vert.glsl SRC)
data_to_c_simple(modes/shaders/paint_vert_frag.glsl SRC)
data_to_c_simple(modes/shaders/particle_strand_frag.glsl SRC)
data_to_c_simple(modes/shaders/particle_strand_vert.glsl SRC)
data_to_c_simple(modes/shaders/pose_selection_vert.glsl SRC)
data_to_c_simple(modes/shaders/sculpt_mask_vert.glsl SRC)
data_to_c_simple(modes/shaders/volume_velocity_vert.glsl SRC)
data_to_c_simple(intern/shaders/common_colormanagement_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_globals_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_hair_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_hair_refine_vert.glsl SRC)
data_to_c_simple(intern/shaders/common_view_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_fxaa_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_smaa_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_fullscreen_vert.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_fill_vert.glsl SRC)
data_to_c_simple(engines/gpencil/shaders/gpencil_fill_frag.glsl SRC)
@@ -380,6 +307,81 @@ data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl SRC)
data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC)
data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/antialiasing_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/antialiasing_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_dof_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_envelope_outline_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_envelope_solid_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_envelope_solid_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_shape_outline_geom.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_shape_outline_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_shape_solid_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_shape_solid_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_sphere_outline_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_sphere_solid_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_sphere_solid_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_stick_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_stick_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_wire_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/depth_only_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_curve_handle_geom.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_curve_handle_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_curve_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_curve_wire_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_lattice_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_lattice_wire_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_common_lib.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_facefill_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_facefill_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_geom.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_normal_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_analysis_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_analysis_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_skin_root_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_mesh_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_particle_strand_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/edit_particle_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/extra_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/extra_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/extra_groundline_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/extra_loose_point_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/extra_loose_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/extra_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/extra_wire_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/extra_wire_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/facing_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/facing_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/grid_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/grid_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/image_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/image_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/motion_path_line_geom.glsl SRC)
data_to_c_simple(engines/overlay/shaders/motion_path_line_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/motion_path_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_detect_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_expand_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_prepass_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_prepass_geom.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_prepass_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_lightprobe_grid_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_resolve_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_face_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_texture_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_texture_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_vertcol_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_vertcol_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_weight_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_weight_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_wire_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/particle_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/particle_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/sculpt_mask_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/volume_velocity_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/wireframe_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/wireframe_geom.glsl SRC)
data_to_c_simple(engines/overlay/shaders/wireframe_frag.glsl SRC)
list(APPEND INC
)

View File

@@ -52,6 +52,7 @@ struct rcti;
/* Buffer and textures used by the viewport by default */
typedef struct DefaultFramebufferList {
struct GPUFrameBuffer *default_fb;
struct GPUFrameBuffer *in_front_fb;
struct GPUFrameBuffer *color_only_fb;
struct GPUFrameBuffer *depth_only_fb;
struct GPUFrameBuffer *multisample_fb;
@@ -60,6 +61,7 @@ typedef struct DefaultFramebufferList {
typedef struct DefaultTextureList {
struct GPUTexture *color;
struct GPUTexture *depth;
struct GPUTexture *depth_in_front;
struct GPUTexture *multisample_color;
struct GPUTexture *multisample_depth;
} DefaultTextureList;

View File

@@ -46,8 +46,8 @@ typedef struct BASIC_StorageList {
} BASIC_StorageList;
typedef struct BASIC_PassList {
struct DRWPass *depth_pass;
struct DRWPass *depth_pass_cull;
struct DRWPass *depth_pass[2];
struct DRWPass *depth_pass_cull[2];
} BASIC_PassList;
typedef struct BASIC_Data {
@@ -70,8 +70,8 @@ static struct {
} e_data = {{{NULL}}}; /* Engine data */
typedef struct BASIC_PrivateData {
DRWShadingGroup *depth_shgrp;
DRWShadingGroup *depth_shgrp_cull;
DRWShadingGroup *depth_shgrp[2];
DRWShadingGroup *depth_shgrp_cull[2];
} BASIC_PrivateData; /* Transient data */
/* Functions */
@@ -97,24 +97,21 @@ static void basic_cache_init(void *vedata)
if (!stl->g_data) {
/* Alloc transient pointers */
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
{
psl->depth_pass = DRW_pass_create("Depth Pass",
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
stl->g_data->depth_shgrp = DRW_shgroup_create(sh_data->depth, psl->depth_pass);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_state_enable(stl->g_data->depth_shgrp, DRW_STATE_CLIP_PLANES);
}
/* Twice for normal and infront objects. */
for (int i = 0; i < 2; i++) {
DRWState clip_state = (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? DRW_STATE_CLIP_PLANES : 0;
DRWState infront_state = (DRW_state_is_select() && (i == 1)) ? DRW_STATE_IN_FRONT_SELECT : 0;
DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull",
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
DRW_STATE_CULL_BACK);
stl->g_data->depth_shgrp_cull = DRW_shgroup_create(sh_data->depth, psl->depth_pass_cull);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_state_enable(stl->g_data->depth_shgrp_cull, DRW_STATE_CLIP_PLANES);
}
DRW_PASS_CREATE(psl->depth_pass[i], state | clip_state | infront_state);
stl->g_data->depth_shgrp[i] = DRW_shgroup_create(sh_data->depth, psl->depth_pass[i]);
state |= DRW_STATE_CULL_BACK;
DRW_PASS_CREATE(psl->depth_pass_cull[i], state | clip_state | infront_state);
stl->g_data->depth_shgrp_cull[i] = DRW_shgroup_create(sh_data->depth, psl->depth_pass_cull[i]);
}
}
@@ -128,6 +125,8 @@ static void basic_cache_populate(void *vedata, Object *ob)
return;
}
bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0;
const DRWContextState *draw_ctx = DRW_context_state_get();
if (ob != draw_ctx->object_edit) {
for (ParticleSystem *psys = ob->particlesystem.first; psys != NULL; psys = psys->next) {
@@ -138,7 +137,7 @@ static void basic_cache_populate(void *vedata, Object *ob)
const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
if (draw_as == PART_DRAW_PATH) {
struct GPUBatch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL);
DRW_shgroup_call(stl->g_data->depth_shgrp, hairs, NULL);
DRW_shgroup_call(stl->g_data->depth_shgrp[do_in_front], hairs, NULL);
}
}
}
@@ -155,7 +154,7 @@ static void basic_cache_populate(void *vedata, Object *ob)
/* Avoid losing flat objects when in ortho views (see T56549) */
struct GPUBatch *geom = DRW_cache_object_all_edges_get(ob);
if (geom) {
DRW_shgroup_call(stl->g_data->depth_shgrp, geom, ob);
DRW_shgroup_call(stl->g_data->depth_shgrp[do_in_front], geom, ob);
}
return;
}
@@ -165,7 +164,8 @@ static void basic_cache_populate(void *vedata, Object *ob)
!DRW_state_is_image_render();
const bool do_cull = (draw_ctx->v3d &&
(draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING));
DRWShadingGroup *shgrp = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
DRWShadingGroup *shgrp = (do_cull) ? stl->g_data->depth_shgrp_cull[do_in_front] :
stl->g_data->depth_shgrp[do_in_front];
if (use_sculpt_pbvh) {
DRW_shgroup_call_sculpt(shgrp, ob, false, false, false);
@@ -189,8 +189,10 @@ static void basic_draw_scene(void *vedata)
{
BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
DRW_draw_pass(psl->depth_pass);
DRW_draw_pass(psl->depth_pass_cull);
DRW_draw_pass(psl->depth_pass[0]);
DRW_draw_pass(psl->depth_pass_cull[0]);
DRW_draw_pass(psl->depth_pass[1]);
DRW_draw_pass(psl->depth_pass_cull[1]);
}
static void basic_engine_free(void)

View File

@@ -33,8 +33,6 @@
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
#include "draw_mode_engines.h"
#include "GPU_texture.h"
#include "gpencil_engine.h"

View File

@@ -25,6 +25,8 @@
#include "GPU_batch.h"
extern DrawEngineType draw_engine_gpencil_type;
struct GPENCIL_Data;
struct GPENCIL_StorageList;
struct MaterialGPencilStyle;

View File

@@ -29,8 +29,6 @@
#include "DEG_depsgraph_query.h"
#include "draw_mode_engines.h"
#include "RE_pipeline.h"
#include "gpencil_engine.h"

View File

@@ -0,0 +1,184 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*
* Overlay antialiasing:
*
* Most of the overlays are wires which causes a lot of flickering in motions
* due to aliasing problems.
*
* Our goal is to have a technique that works with single sample per pixel
* to avoid extra cost of managing MSAA or additional texture buffers and jitters.
*
* To solve this we use a simple and effective post-process AA. The technique
* goes like this:
*
* - During wireframe rendering, we output the line color, the line direction
* and the distance from the line for the pixel center.
*
* - Then, in a post process pass, for each pixels we gather all lines in a search area
* that could cover (even partially) the center pixel.
* We compute the coverage of each line and do a sorted alpha compositing of them.
*
* This technique has one major shortcoming compared to MSAA:
* - It handles (initial) partial visibility poorly (because of single sample). This makes
* overlaping / crossing wires a bit too thin at their intersection.
* Wireframe meshes overlaid over solid meshes can have half of the edge missing due to
* z-fighting (this has workaround).
* Another manifestation of this, is fickering of really dense wireframe if using small
* line thickness (also has workaround).
*
* The pros of this approach are many:
* - Works without geometry shader.
* - Can inflate line thickness.
* - Coverage is very close to perfect and can even be filtered (Blackman-Harris, gaussian).
* - Wires can "bleed" / overlap non-line objects since the filter is in screenspace.
* - Only uses one additional lightweight fullscreen buffer (compared to MSAA/SMAA).
* - No convergence time (compared to TAA).
*/
#include "DRW_render.h"
#include "ED_screen.h"
#include "overlay_private.h"
void OVERLAY_antialiasing_reset(OVERLAY_Data *vedata)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
pd->antialiasing.sample = 0;
}
void OVERLAY_antialiasing_init(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
OVERLAY_TextureList *txl = vedata->txl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
if (!DRW_state_is_fbo()) {
/* Use default view */
pd->view_default = (DRWView *)DRW_view_default_get();
pd->antialiasing.enabled = false;
return;
}
/* TODO Get real userpref option and remove MSAA buffer. */
pd->antialiasing.enabled = dtxl->multisample_color != NULL;
/* Use default view */
pd->view_default = (DRWView *)DRW_view_default_get();
if (pd->antialiasing.enabled) {
DRW_texture_ensure_fullscreen_2d(&txl->overlay_color_tx, GPU_RGBA8, DRW_TEX_FILTER);
DRW_texture_ensure_fullscreen_2d(&txl->overlay_line_tx, GPU_RGBA8, 0);
GPU_framebuffer_ensure_config(
&fbl->overlay_color_only_fb,
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->overlay_color_tx)});
GPU_framebuffer_ensure_config(
&fbl->overlay_default_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(txl->overlay_color_tx)});
GPU_framebuffer_ensure_config(&fbl->overlay_line_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth),
GPU_ATTACHMENT_TEXTURE(txl->overlay_color_tx),
GPU_ATTACHMENT_TEXTURE(txl->overlay_line_tx)});
}
else {
/* Just a copy of the defaults framebuffers. */
GPU_framebuffer_ensure_config(&fbl->overlay_color_only_fb,
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(dtxl->color)});
GPU_framebuffer_ensure_config(
&fbl->overlay_default_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
GPU_framebuffer_ensure_config(
&fbl->overlay_line_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
}
}
void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_TextureList *txl = vedata->txl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
OVERLAY_PassList *psl = vedata->psl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
struct GPUShader *sh;
DRWShadingGroup *grp;
if (pd->antialiasing.enabled) {
DRW_PASS_CREATE(psl->antialiasing_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL);
sh = OVERLAY_shader_antialiasing();
grp = DRW_shgroup_create(sh, psl->antialiasing_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", &dtxl->depth);
DRW_shgroup_uniform_texture_ref(grp, "colorTex", &txl->overlay_color_tx);
DRW_shgroup_uniform_texture_ref(grp, "lineTex", &txl->overlay_line_tx);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
}
void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
OVERLAY_TextureList *txl = vedata->txl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
if (pd->antialiasing.enabled) {
GPU_framebuffer_ensure_config(&fbl->overlay_in_front_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth_in_front),
GPU_ATTACHMENT_TEXTURE(txl->overlay_color_tx)});
}
else {
GPU_framebuffer_ensure_config(
&fbl->overlay_in_front_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth_in_front), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
}
}
void OVERLAY_antialiasing_start(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
if (pd->antialiasing.enabled) {
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPU_framebuffer_bind(fbl->overlay_line_fb);
GPU_framebuffer_clear_color(fbl->overlay_line_fb, clear_col);
GPU_framebuffer_bind(fbl->overlay_default_fb);
}
}
void OVERLAY_antialiasing_end(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
if (pd->antialiasing.enabled) {
GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_draw_pass(psl->antialiasing_ps);
GPU_framebuffer_bind(dfbl->default_fb);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,127 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "DNA_curve_types.h"
#include "overlay_private.h"
void OVERLAY_edit_curve_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
DRWShadingGroup *grp;
GPUShader *sh;
DRWState state;
pd->edit_curve.show_handles = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0;
pd->shdata.edit_curve_normal_length = v3d->overlay.normals_length;
/* Run Twice for in-front passes. */
for (int i = 0; i < 2; i++) {
state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH;
state |= ((i == 0) ? DRW_STATE_DEPTH_LESS_EQUAL : DRW_STATE_DEPTH_ALWAYS);
DRW_PASS_CREATE(psl->edit_curve_wire_ps[i], state | pd->clipping_state);
sh = OVERLAY_shader_edit_curve_wire();
pd->edit_curve_normal_grp[i] = grp = DRW_shgroup_create(sh, psl->edit_curve_wire_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "normalSize", pd->shdata.edit_curve_normal_length);
pd->edit_curve_wire_grp[i] = grp = DRW_shgroup_create(sh, psl->edit_curve_wire_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "normalSize", 0.0f);
}
{
state = DRW_STATE_WRITE_COLOR;
DRW_PASS_CREATE(psl->edit_curve_handle_ps, state | pd->clipping_state);
sh = OVERLAY_shader_edit_curve_handle();
pd->edit_curve_handle_grp = grp = DRW_shgroup_create(sh, psl->edit_curve_handle_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "showCurveHandles", pd->edit_curve.show_handles);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
sh = OVERLAY_shader_edit_curve_point();
pd->edit_curve_points_grp = grp = DRW_shgroup_create(sh, psl->edit_curve_handle_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
}
void OVERLAY_edit_curve_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
bool draw_normals = (pd->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_NORMALS) != 0;
bool do_xray = (ob->dtx & OB_DRAWXRAY) != 0;
Curve *cu = ob->data;
struct GPUBatch *geom;
geom = DRW_cache_curve_edge_wire_get(ob);
if (geom) {
DRW_shgroup_call_no_cull(pd->edit_curve_wire_grp[do_xray], geom, ob);
}
if ((cu->flag & CU_3D) && draw_normals) {
geom = DRW_cache_curve_edge_normal_get(ob);
DRW_shgroup_call_instances(pd->edit_curve_normal_grp[do_xray], ob, geom, 3);
}
geom = DRW_cache_curve_edge_overlay_get(ob);
if (geom) {
DRW_shgroup_call_no_cull(pd->edit_curve_handle_grp, geom, ob);
}
geom = DRW_cache_curve_vert_overlay_get(ob, pd->edit_curve.show_handles);
if (geom) {
DRW_shgroup_call_no_cull(pd->edit_curve_points_grp, geom, ob);
}
}
void OVERLAY_edit_surf_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUBatch *geom;
geom = DRW_cache_curve_edge_overlay_get(ob);
if (geom) {
DRW_shgroup_call_no_cull(pd->edit_curve_handle_grp, geom, ob);
}
geom = DRW_cache_curve_vert_overlay_get(ob, false);
if (geom) {
DRW_shgroup_call_no_cull(pd->edit_curve_points_grp, geom, ob);
}
}
void OVERLAY_edit_curve_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->edit_curve_wire_ps[0]);
DRW_draw_pass(psl->edit_curve_wire_ps[1]);
DRW_draw_pass(psl->edit_curve_handle_ps);
}

View File

@@ -0,0 +1,419 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "ED_view3d.h"
#include "DNA_mesh_types.h"
#include "BKE_editmesh.h"
#include "draw_cache_impl.h"
#include "draw_manager_text.h"
#include "overlay_private.h"
#define OVERLAY_EDIT_TEXT \
(V3D_OVERLAY_EDIT_EDGE_LEN | V3D_OVERLAY_EDIT_FACE_AREA | V3D_OVERLAY_EDIT_FACE_ANG | \
V3D_OVERLAY_EDIT_EDGE_ANG | V3D_OVERLAY_EDIT_INDICES)
void OVERLAY_edit_mesh_init(OVERLAY_Data *vedata)
{
OVERLAY_TextureList *txl = vedata->txl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
pd->edit_mesh.do_zbufclip = XRAY_FLAG_ENABLED(draw_ctx->v3d);
if (!pd->edit_mesh.do_zbufclip) {
/* Small texture which will have very small impact on rendertime. */
DRW_texture_ensure_2d(&txl->dummy_depth_tx, 1, 1, GPU_DEPTH_COMPONENT24, 0);
}
/* Create view with depth offset */
DRWView *default_view = (DRWView *)DRW_view_default_get();
/* Don't use AA view (pd->view_default) because edit mode already has anti-aliasing. */
pd->view_edit_faces = default_view;
pd->view_edit_faces_cage = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 0.5f);
pd->view_edit_edges = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 1.0f);
pd->view_edit_verts = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 1.5f);
}
void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_TextureList *txl = vedata->txl;
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
OVERLAY_ShadingData *shdata = &pd->shdata;
DRWShadingGroup *grp = NULL;
GPUShader *sh = NULL;
DRWState state = 0;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
ToolSettings *tsettings = draw_ctx->scene->toolsettings;
View3D *v3d = draw_ctx->v3d;
bool select_vert = pd->edit_mesh.select_vert = (tsettings->selectmode & SCE_SELECT_VERTEX) != 0;
bool select_face = pd->edit_mesh.select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0;
bool select_edge = pd->edit_mesh.select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0;
bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0;
bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0 ||
pd->edit_mesh.do_zbufclip;
pd->edit_mesh.ghost_ob = 0;
pd->edit_mesh.edit_ob = 0;
pd->edit_mesh.do_faces = true;
pd->edit_mesh.do_edges = true;
int *mask = shdata->data_mask;
mask[0] = 0xFF; /* Face Flag */
mask[1] = 0xFF; /* Edge Flag */
const int flag = pd->edit_mesh.flag = v3d->overlay.edit_flag;
SET_FLAG_FROM_TEST(mask[0], flag & V3D_OVERLAY_EDIT_FACES, VFLAG_FACE_SELECTED);
SET_FLAG_FROM_TEST(mask[0], flag & V3D_OVERLAY_EDIT_FREESTYLE_FACE, VFLAG_FACE_FREESTYLE);
SET_FLAG_FROM_TEST(mask[1], flag & V3D_OVERLAY_EDIT_FREESTYLE_EDGE, VFLAG_EDGE_FREESTYLE);
SET_FLAG_FROM_TEST(mask[1], flag & V3D_OVERLAY_EDIT_SEAMS, VFLAG_EDGE_SEAM);
SET_FLAG_FROM_TEST(mask[1], flag & V3D_OVERLAY_EDIT_SHARP, VFLAG_EDGE_SHARP);
SET_FLAG_FROM_TEST(mask[2], flag & V3D_OVERLAY_EDIT_CREASES, 0xFF);
SET_FLAG_FROM_TEST(mask[3], flag & V3D_OVERLAY_EDIT_BWEIGHTS, 0xFF);
if ((flag & V3D_OVERLAY_EDIT_FACES) == 0) {
pd->edit_mesh.do_faces = false;
pd->edit_mesh.do_zbufclip = false;
}
if ((flag & V3D_OVERLAY_EDIT_EDGES) == 0) {
if ((tsettings->selectmode & SCE_SELECT_EDGE) == 0) {
if ((v3d->shading.type < OB_SOLID) || (v3d->shading.flag & V3D_SHADING_XRAY)) {
/* Special case, when drawing wire, draw edges, see: T67637. */
}
else {
pd->edit_mesh.do_edges = false;
}
}
}
float backwire_opacity = (pd->edit_mesh.do_zbufclip) ? v3d->overlay.backwire_opacity : 1.0f;
float face_alpha = (do_occlude_wire || !pd->edit_mesh.do_faces) ? 0.0f : 1.0f;
GPUTexture **depth_tex = (pd->edit_mesh.do_zbufclip) ? &dtxl->depth : &txl->dummy_depth_tx;
if (select_face && !pd->edit_mesh.do_faces && pd->edit_mesh.do_edges) {
/* Force display of face centers in this case because that's
* the only way to see if a face is selected. */
show_face_dots = true;
}
{
/* TODO(fclem) Shouldn't this be going into the paint overlay? */
state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRW_PASS_CREATE(psl->edit_mesh_weight_ps, state | pd->clipping_state);
sh = OVERLAY_shader_paint_weight();
pd->edit_mesh_weight_grp = grp = DRW_shgroup_create(sh, psl->edit_mesh_weight_ps);
DRW_shgroup_uniform_float_copy(grp, "opacity", 1.0);
DRW_shgroup_uniform_bool_copy(grp, "drawContours", false);
DRW_shgroup_uniform_texture(grp, "colorramp", G_draw.weight_ramp);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
/* Run Twice for in-front passes. */
for (int i = 0; i < 2; i++) {
/* Complementary Depth Pass */
state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
DRW_PASS_CREATE(psl->edit_mesh_depth_ps[i], state | pd->clipping_state);
sh = OVERLAY_shader_depth_only();
pd->edit_mesh_depth_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_depth_ps[i]);
}
{
/* Normals */
state = DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
(pd->edit_mesh.do_zbufclip ? DRW_STATE_BLEND_ALPHA : 0);
DRW_PASS_CREATE(psl->edit_mesh_normals_ps, state | pd->clipping_state);
sh = OVERLAY_shader_edit_mesh_normal();
pd->edit_mesh_normals_grp = grp = DRW_shgroup_create(sh, psl->edit_mesh_normals_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length);
DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
}
{
/* Mesh Analysis Pass */
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->edit_mesh_analysis_ps, state | pd->clipping_state);
sh = OVERLAY_shader_edit_mesh_analysis();
pd->edit_mesh_analysis_grp = grp = DRW_shgroup_create(sh, psl->edit_mesh_analysis_ps);
DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
}
/* Run Twice for in-front passes. */
for (int i = 0; i < 2; i++) {
GPUShader *edge_sh = OVERLAY_shader_edit_mesh_edge(!select_vert);
GPUShader *face_sh = OVERLAY_shader_edit_mesh_face();
const bool do_zbufclip = (i == 0 && pd->edit_mesh.do_zbufclip);
DRWState state_common = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
DRW_STATE_BLEND_ALPHA;
/* Faces */
/* Cage geom needs to be offsetted to avoid Z-fighting. */
for (int j = 0; j < 2; j++) {
DRWPass **edit_face_ps = (j == 0) ? &psl->edit_mesh_faces_ps[i] :
&psl->edit_mesh_faces_cage_ps[i];
DRWShadingGroup **shgrp = (j == 0) ? &pd->edit_mesh_faces_grp[i] :
&pd->edit_mesh_faces_cage_grp[i];
state = state_common;
DRW_PASS_CREATE(*edit_face_ps, state | pd->clipping_state);
grp = *shgrp = DRW_shgroup_create(face_sh, *edit_face_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_ivec4(grp, "dataMask", mask, 1);
DRW_shgroup_uniform_float_copy(grp, "alpha", face_alpha);
DRW_shgroup_uniform_bool_copy(grp, "selectFaces", select_face);
}
if (do_zbufclip) {
state_common |= DRW_STATE_WRITE_DEPTH;
// state_common &= ~DRW_STATE_BLEND_ALPHA;
}
/* Edges */
/* Change first vertex convention to match blender loop structure. */
state = state_common | DRW_STATE_FIRST_VERTEX_CONVENTION;
DRW_PASS_CREATE(psl->edit_mesh_edges_ps[i], state | pd->clipping_state);
grp = pd->edit_mesh_edges_grp[i] = DRW_shgroup_create(edge_sh, psl->edit_mesh_edges_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_ivec4(grp, "dataMask", mask, 1);
DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
DRW_shgroup_uniform_bool_copy(grp, "selectEdges", pd->edit_mesh.do_edges || select_edge);
/* Verts */
DRW_PASS_CREATE(psl->edit_mesh_verts_ps[i], state | pd->clipping_state);
if (select_vert) {
sh = OVERLAY_shader_edit_mesh_vert();
grp = pd->edit_mesh_verts_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
sh = OVERLAY_shader_edit_mesh_skin_root();
grp = pd->edit_mesh_skin_roots_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
/* Facedots */
if (select_face && show_face_dots) {
sh = OVERLAY_shader_edit_mesh_facedot();
grp = pd->edit_mesh_facedots_grp[i] = DRW_shgroup_create(sh, psl->edit_mesh_verts_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex);
DRW_shgroup_state_enable(grp, DRW_STATE_WRITE_DEPTH);
}
else {
pd->edit_mesh_facedots_grp[i] = NULL;
}
}
}
static void overlay_edit_mesh_add_ob_to_pass(OVERLAY_PrivateData *pd, Object *ob, bool in_front)
{
struct GPUBatch *geom_tris, *geom_verts, *geom_edges, *geom_fcenter, *skin_roots, *circle;
DRWShadingGroup *vert_shgrp, *edge_shgrp, *fdot_shgrp, *face_shgrp, *skin_roots_shgrp;
bool has_edit_mesh_cage = false;
bool has_skin_roots = false;
/* TODO: Should be its own function. */
Mesh *me = (Mesh *)ob->data;
BMEditMesh *embm = me->edit_mesh;
if (embm) {
has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final);
has_skin_roots = CustomData_get_offset(&embm->bm->vdata, CD_MVERT_SKIN) != -1;
}
vert_shgrp = pd->edit_mesh_verts_grp[in_front];
edge_shgrp = pd->edit_mesh_edges_grp[in_front];
fdot_shgrp = pd->edit_mesh_facedots_grp[in_front];
face_shgrp = (has_edit_mesh_cage) ? pd->edit_mesh_faces_cage_grp[in_front] :
pd->edit_mesh_faces_grp[in_front];
skin_roots_shgrp = pd->edit_mesh_skin_roots_grp[in_front];
geom_edges = DRW_mesh_batch_cache_get_edit_edges(ob->data);
geom_tris = DRW_mesh_batch_cache_get_edit_triangles(ob->data);
DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob);
DRW_shgroup_call_no_cull(face_shgrp, geom_tris, ob);
if (pd->edit_mesh.select_vert) {
geom_verts = DRW_mesh_batch_cache_get_edit_vertices(ob->data);
DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob);
if (has_skin_roots) {
circle = DRW_cache_circle_get();
skin_roots = DRW_mesh_batch_cache_get_edit_skin_roots(ob->data);
DRW_shgroup_call_instances_with_attribs(skin_roots_shgrp, ob, circle, skin_roots);
}
}
if (fdot_shgrp) {
geom_fcenter = DRW_mesh_batch_cache_get_edit_facedots(ob->data);
DRW_shgroup_call_no_cull(fdot_shgrp, geom_fcenter, ob);
}
}
void OVERLAY_edit_mesh_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUBatch *geom = NULL;
bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0;
bool do_occlude_wire = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0;
bool do_show_weight = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_WEIGHT) != 0;
bool do_show_mesh_analysis = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_STATVIS) != 0;
bool fnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_FACE_NORMALS) != 0;
bool vnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0;
bool lnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0;
if (do_show_weight) {
geom = DRW_cache_mesh_surface_weights_get(ob);
DRW_shgroup_call_no_cull(pd->edit_mesh_weight_grp, geom, ob);
}
else if (do_show_mesh_analysis && !pd->xray_enabled) {
geom = DRW_cache_mesh_surface_mesh_analysis_get(ob);
if (geom) {
DRW_shgroup_call_no_cull(pd->edit_mesh_analysis_grp, geom, ob);
}
}
if (do_occlude_wire || do_in_front) {
geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call_no_cull(pd->edit_mesh_depth_grp[do_in_front], geom, ob);
}
if (vnormals_do || lnormals_do || fnormals_do) {
struct GPUBatch *normal_geom = DRW_cache_normal_arrow_get();
if (vnormals_do) {
geom = DRW_mesh_batch_cache_get_edit_vnors(ob->data);
DRW_shgroup_call_instances_with_attribs(pd->edit_mesh_normals_grp, ob, normal_geom, geom);
}
if (lnormals_do) {
geom = DRW_mesh_batch_cache_get_edit_lnors(ob->data);
DRW_shgroup_call_instances_with_attribs(pd->edit_mesh_normals_grp, ob, normal_geom, geom);
}
if (fnormals_do) {
geom = DRW_mesh_batch_cache_get_edit_facedots(ob->data);
DRW_shgroup_call_instances_with_attribs(pd->edit_mesh_normals_grp, ob, normal_geom, geom);
}
}
if (pd->edit_mesh.do_zbufclip) {
overlay_edit_mesh_add_ob_to_pass(pd, ob, false);
}
else {
overlay_edit_mesh_add_ob_to_pass(pd, ob, do_in_front);
}
pd->edit_mesh.ghost_ob += (ob->dtx & OB_DRAWXRAY) ? 1 : 0;
pd->edit_mesh.edit_ob += 1;
if (DRW_state_show_text() && (pd->edit_mesh.flag & OVERLAY_EDIT_TEXT)) {
const DRWContextState *draw_ctx = DRW_context_state_get();
DRW_text_edit_mesh_measure_stats(draw_ctx->ar, draw_ctx->v3d, ob, &draw_ctx->scene->unit);
}
}
static void overlay_edit_mesh_draw_components(OVERLAY_PassList *psl,
OVERLAY_PrivateData *pd,
bool in_front)
{
DRW_view_set_active(pd->view_edit_faces);
DRW_draw_pass(psl->edit_mesh_faces_ps[in_front]);
DRW_view_set_active(pd->view_edit_faces_cage);
DRW_draw_pass(psl->edit_mesh_faces_cage_ps[in_front]);
DRW_view_set_active(pd->view_edit_edges);
DRW_draw_pass(psl->edit_mesh_edges_ps[in_front]);
DRW_view_set_active(pd->view_edit_verts);
DRW_draw_pass(psl->edit_mesh_verts_ps[in_front]);
DRW_view_set_active(pd->view_default);
}
void OVERLAY_edit_mesh_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
OVERLAY_FramebufferList *fbl = vedata->fbl;
DRW_draw_pass(psl->edit_mesh_weight_ps);
DRW_draw_pass(psl->edit_mesh_analysis_ps);
DRW_draw_pass(psl->edit_mesh_depth_ps[NOT_IN_FRONT]);
if (pd->edit_mesh.do_zbufclip) {
DRW_draw_pass(psl->edit_mesh_depth_ps[IN_FRONT]);
/* render facefill */
DRW_view_set_active(pd->view_edit_faces);
DRW_draw_pass(psl->edit_mesh_faces_ps[NOT_IN_FRONT]);
DRW_view_set_active(pd->view_edit_faces_cage);
DRW_draw_pass(psl->edit_mesh_faces_cage_ps[NOT_IN_FRONT]);
DRW_view_set_active(pd->view_default);
GPU_framebuffer_bind(fbl->overlay_in_front_fb);
GPU_framebuffer_clear_depth(fbl->overlay_in_front_fb, 1.0f);
DRW_draw_pass(psl->edit_mesh_normals_ps);
DRW_view_set_active(pd->view_edit_edges);
DRW_draw_pass(psl->edit_mesh_edges_ps[NOT_IN_FRONT]);
DRW_view_set_active(pd->view_edit_verts);
DRW_draw_pass(psl->edit_mesh_verts_ps[NOT_IN_FRONT]);
GPU_framebuffer_bind(fbl->overlay_default_fb);
}
else {
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
DRW_draw_pass(psl->edit_mesh_normals_ps);
overlay_edit_mesh_draw_components(psl, pd, false);
if (v3d->shading.type == OB_SOLID && pd->edit_mesh.ghost_ob == 1 &&
pd->edit_mesh.edit_ob == 1) {
/* In the case of single ghost object edit (common case for retopology):
* we clear the depth buffer so that only the depth of the retopo mesh
* is occluding the edit cage. */
GPU_framebuffer_clear_depth(fbl->overlay_default_fb, 1.0f);
}
DRW_draw_pass(psl->edit_mesh_depth_ps[IN_FRONT]);
overlay_edit_mesh_draw_components(psl, pd, true);
}
}

View File

@@ -0,0 +1,201 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "BKE_font.h"
#include "DNA_curve_types.h"
#include "overlay_private.h"
void OVERLAY_edit_text_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
DRWShadingGroup *grp;
GPUShader *sh;
DRWState state;
pd->edit_curve.show_handles = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) != 0;
pd->shdata.edit_curve_normal_length = v3d->overlay.normals_length;
/* Run Twice for in-front passes. */
for (int i = 0; i < 2; i++) {
state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH;
state |= ((i == 0) ? DRW_STATE_DEPTH_LESS_EQUAL : DRW_STATE_DEPTH_ALWAYS);
DRW_PASS_CREATE(psl->edit_text_wire_ps[i], state | pd->clipping_state);
sh = OVERLAY_shader_uniform_color();
pd->edit_text_wire_grp[i] = grp = DRW_shgroup_create(sh, psl->edit_text_wire_ps[i]);
DRW_shgroup_uniform_vec4_copy(grp, "color", G_draw.block.colorWire);
}
{
state = DRW_STATE_WRITE_COLOR | DRW_STATE_LOGIC_INVERT;
DRW_PASS_CREATE(psl->edit_text_overlay_ps, state | pd->clipping_state);
sh = OVERLAY_shader_uniform_color();
pd->edit_text_overlay_grp = DRW_shgroup_create(sh, psl->edit_text_overlay_ps);
}
}
/* Use 2D quad corners to create a matrix that set
* a [-1..1] quad at the right position. */
static void v2_quad_corners_to_mat4(float corners[4][2], float r_mat[4][4])
{
unit_m4(r_mat);
sub_v2_v2v2(r_mat[0], corners[1], corners[0]);
sub_v2_v2v2(r_mat[1], corners[3], corners[0]);
mul_v2_fl(r_mat[0], 0.5f);
mul_v2_fl(r_mat[1], 0.5f);
copy_v2_v2(r_mat[3], corners[0]);
add_v2_v2(r_mat[3], r_mat[0]);
add_v2_v2(r_mat[3], r_mat[1]);
}
static void edit_text_cache_populate_select(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
const Curve *cu = ob->data;
EditFont *ef = cu->editfont;
float final_mat[4][4], box[4][2];
struct GPUBatch *geom = DRW_cache_quad_get();
for (int i = 0; i < ef->selboxes_len; i++) {
EditFontSelBox *sb = &ef->selboxes[i];
float selboxw;
if (i + 1 != ef->selboxes_len) {
if (ef->selboxes[i + 1].y == sb->y) {
selboxw = ef->selboxes[i + 1].x - sb->x;
}
else {
selboxw = sb->w;
}
}
else {
selboxw = sb->w;
}
/* NOTE: v2_quad_corners_to_mat4 don't need the 3rd corner. */
if (sb->rot == 0.0f) {
copy_v2_fl2(box[0], sb->x, sb->y);
copy_v2_fl2(box[1], sb->x + selboxw, sb->y);
copy_v2_fl2(box[3], sb->x, sb->y + sb->h);
}
else {
float mat[2][2];
angle_to_mat2(mat, sb->rot);
copy_v2_fl2(box[0], sb->x, sb->y);
mul_v2_v2fl(box[1], mat[0], selboxw);
add_v2_v2(box[1], &sb->x);
mul_v2_v2fl(box[3], mat[1], sb->h);
add_v2_v2(box[3], &sb->x);
}
v2_quad_corners_to_mat4(box, final_mat);
mul_m4_m4m4(final_mat, ob->obmat, final_mat);
DRW_shgroup_call_obmat(pd->edit_text_overlay_grp, geom, final_mat);
}
}
static void edit_text_cache_populate_cursor(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
const Curve *cu = ob->data;
EditFont *edit_font = cu->editfont;
float(*cursor)[2] = edit_font->textcurs;
float mat[4][4];
v2_quad_corners_to_mat4(cursor, mat);
mul_m4_m4m4(mat, ob->obmat, mat);
struct GPUBatch *geom = DRW_cache_quad_get();
DRW_shgroup_call_obmat(pd->edit_text_overlay_grp, geom, mat);
}
static void edit_text_cache_populate_boxes(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob);
const Curve *cu = ob->data;
for (int i = 0; i < cu->totbox; i++) {
TextBox *tb = &cu->tb[i];
const bool is_active = (i == (cu->actbox - 1));
float *color = is_active ? G_draw.block.colorActive : G_draw.block.colorWire;
if ((tb->w != 0.0f) || (tb->h != 0.0f)) {
float vecs[4][3];
vecs[0][0] = vecs[1][0] = vecs[2][0] = vecs[3][0] = cu->xof + tb->x;
vecs[0][1] = vecs[1][1] = vecs[2][1] = vecs[3][1] = cu->yof + tb->y + cu->fsize_realtime;
vecs[0][2] = vecs[1][2] = vecs[2][2] = vecs[3][2] = 0.001;
vecs[1][0] += tb->w;
vecs[2][0] += tb->w;
vecs[2][1] -= tb->h;
vecs[3][1] -= tb->h;
for (int j = 0; j < 4; j++) {
mul_v3_m4v3(vecs[j], ob->obmat, vecs[j]);
}
for (int j = 0; j < 4; j++) {
OVERLAY_extra_line_dashed(cb, vecs[j], vecs[(j + 1) % 4], color);
}
}
}
}
void OVERLAY_edit_text_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
Curve *cu = ob->data;
struct GPUBatch *geom;
bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0;
bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f;
if ((cu->flag & CU_FAST) || !has_surface) {
geom = DRW_cache_text_edge_wire_get(ob);
if (geom) {
DRW_shgroup_call(pd->edit_text_wire_grp[do_in_front], geom, ob);
}
}
else {
/* object mode draws */
}
edit_text_cache_populate_select(vedata, ob);
edit_text_cache_populate_cursor(vedata, ob);
edit_text_cache_populate_boxes(vedata, ob);
}
void OVERLAY_edit_text_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_view_set_active(NULL);
DRW_draw_pass(psl->edit_text_wire_ps[0]);
DRW_draw_pass(psl->edit_text_wire_ps[1]);
DRW_draw_pass(psl->edit_text_overlay_ps);
}

View File

@@ -0,0 +1,491 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*
* Engine for drawing a selection map where the pixels indicate the selection indices.
*/
#include "DRW_engine.h"
#include "DRW_render.h"
#include "ED_view3d.h"
#include "BKE_object.h"
#include "overlay_engine.h"
#include "overlay_private.h"
/* -------------------------------------------------------------------- */
/** \name Engine Callbacks
* \{ */
static void OVERLAY_engine_init(void *vedata)
{
OVERLAY_Data *data = vedata;
OVERLAY_StorageList *stl = data->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
const RegionView3D *rv3d = draw_ctx->rv3d;
const View3D *v3d = draw_ctx->v3d;
if (!stl->pd) {
/* Alloc transient pointers */
stl->pd = MEM_callocN(sizeof(*stl->pd), __func__);
}
OVERLAY_PrivateData *pd = stl->pd;
View3DOverlay overlay;
short v3d_flag, v3d_gridflag;
pd->hide_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) != 0;
pd->ctx_mode = CTX_data_mode_enum_ex(
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
if (!pd->hide_overlays) {
overlay = v3d->overlay;
v3d_flag = v3d->flag;
v3d_gridflag = v3d->gridflag;
}
else {
memset(&overlay, 0, sizeof(overlay));
v3d_flag = 0;
v3d_gridflag = 0;
overlay.flag = V3D_OVERLAY_HIDE_TEXT | V3D_OVERLAY_HIDE_MOTION_PATHS | V3D_OVERLAY_HIDE_BONES |
V3D_OVERLAY_HIDE_OBJECT_XTRAS | V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
}
if (v3d->shading.type == OB_WIRE) {
overlay.flag |= V3D_OVERLAY_WIREFRAMES;
}
/* Check if anything changed, and if so, reset AA. */
if (v3d_flag != pd->v3d_flag || pd->v3d_gridflag != v3d_gridflag ||
memcmp(&pd->overlay, &overlay, sizeof(overlay))) {
pd->overlay = overlay;
pd->v3d_flag = v3d_flag;
pd->v3d_gridflag = v3d_gridflag;
OVERLAY_antialiasing_reset(vedata);
}
pd->wireframe_mode = (v3d->shading.type == OB_WIRE);
pd->clipping_state = (rv3d->rflag & RV3D_CLIPPING) ? DRW_STATE_CLIP_PLANES : 0;
pd->xray_enabled = XRAY_ACTIVE(v3d);
pd->xray_enabled_and_not_wire = pd->xray_enabled && v3d->shading.type > OB_WIRE;
pd->clear_in_front = (v3d->shading.type != OB_SOLID);
OVERLAY_antialiasing_init(vedata);
switch (stl->pd->ctx_mode) {
case CTX_MODE_EDIT_MESH:
OVERLAY_edit_mesh_init(vedata);
break;
default:
/* Nothing to do. */
break;
}
OVERLAY_facing_init(vedata);
OVERLAY_grid_init(vedata);
OVERLAY_image_init(vedata);
OVERLAY_outline_init(vedata);
OVERLAY_wireframe_init(vedata);
}
static void OVERLAY_cache_init(void *vedata)
{
OVERLAY_Data *data = vedata;
OVERLAY_StorageList *stl = data->stl;
OVERLAY_PrivateData *pd = stl->pd;
switch (pd->ctx_mode) {
case CTX_MODE_EDIT_MESH:
OVERLAY_edit_mesh_cache_init(vedata);
break;
case CTX_MODE_EDIT_SURFACE:
case CTX_MODE_EDIT_CURVE:
OVERLAY_edit_curve_cache_init(vedata);
break;
case CTX_MODE_EDIT_TEXT:
OVERLAY_edit_text_cache_init(vedata);
break;
case CTX_MODE_EDIT_ARMATURE:
break;
case CTX_MODE_EDIT_METABALL:
break;
case CTX_MODE_EDIT_LATTICE:
OVERLAY_edit_lattice_cache_init(vedata);
break;
case CTX_MODE_PARTICLE:
OVERLAY_edit_particle_cache_init(vedata);
break;
case CTX_MODE_POSE:
case CTX_MODE_PAINT_WEIGHT:
case CTX_MODE_PAINT_VERTEX:
case CTX_MODE_PAINT_TEXTURE:
OVERLAY_paint_cache_init(vedata);
break;
case CTX_MODE_SCULPT:
OVERLAY_sculpt_cache_init(vedata);
break;
case CTX_MODE_OBJECT:
case CTX_MODE_PAINT_GPENCIL:
case CTX_MODE_EDIT_GPENCIL:
case CTX_MODE_SCULPT_GPENCIL:
case CTX_MODE_WEIGHT_GPENCIL:
break;
default:
BLI_assert(!"Draw mode invalid");
break;
}
OVERLAY_antialiasing_cache_init(vedata);
OVERLAY_armature_cache_init(vedata);
OVERLAY_extra_cache_init(vedata);
OVERLAY_facing_cache_init(vedata);
OVERLAY_grid_cache_init(vedata);
OVERLAY_image_cache_init(vedata);
OVERLAY_metaball_cache_init(vedata);
OVERLAY_motion_path_cache_init(vedata);
OVERLAY_outline_cache_init(vedata);
OVERLAY_particle_cache_init(vedata);
OVERLAY_wireframe_cache_init(vedata);
}
BLI_INLINE OVERLAY_DupliData *OVERLAY_duplidata_get(Object *ob, void *vedata, bool *do_init)
{
OVERLAY_DupliData **dupli_data = (OVERLAY_DupliData **)DRW_duplidata_get(vedata);
*do_init = false;
if (!ELEM(ob->type, OB_MESH, OB_SURF, OB_LATTICE, OB_CURVE, OB_FONT)) {
return NULL;
}
if (dupli_data) {
if (*dupli_data == NULL) {
*dupli_data = MEM_callocN(sizeof(OVERLAY_DupliData), __func__);
*do_init = true;
}
else if ((*dupli_data)->base_flag != ob->base_flag) {
/* Select state might have change, reinit. */
*do_init = true;
}
return *dupli_data;
}
return NULL;
}
static void OVERLAY_cache_populate(void *vedata, Object *ob)
{
OVERLAY_Data *data = vedata;
OVERLAY_PrivateData *pd = data->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool is_select = DRW_state_is_select();
const bool renderable = DRW_object_is_renderable(ob);
const bool in_pose_mode = ob->type == OB_ARMATURE && OVERLAY_armature_is_pose_mode(ob, draw_ctx);
const bool in_edit_mode = BKE_object_is_in_editmode(ob);
const bool in_particle_edit_mode = ob->mode == OB_MODE_PARTICLE_EDIT;
const bool in_paint_mode = (ob == draw_ctx->obact) &&
(draw_ctx->object_mode & OB_MODE_ALL_PAINT);
const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != NULL);
const bool has_surface = ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL, OB_FONT);
const bool draw_surface = !((ob->dt < OB_WIRE) || (!renderable && (ob->dt != OB_WIRE)));
const bool draw_facing = draw_surface && (pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION);
const bool draw_bones = (pd->overlay.flag & V3D_OVERLAY_HIDE_BONES) == 0;
const bool draw_wires = draw_surface && has_surface &&
(pd->wireframe_mode || !pd->hide_overlays);
const bool draw_outlines = !in_edit_mode && !in_paint_mode && renderable &&
(pd->v3d_flag & V3D_SELECT_OUTLINE) &&
((ob->base_flag & BASE_SELECTED) ||
(is_select && ob->type == OB_LIGHTPROBE));
const bool draw_bone_selection = (ob->type == OB_MESH) && pd->armature.do_pose_fade_geom &&
!is_select;
const bool draw_extras =
((pd->overlay.flag & V3D_OVERLAY_HIDE_OBJECT_XTRAS) == 0) ||
/* Show if this is the camera we're looking through since it's useful for selecting. */
((draw_ctx->rv3d->persp == RV3D_CAMOB) && ((ID *)draw_ctx->v3d->camera == ob->id.orig_id));
const bool draw_motion_paths = (pd->overlay.flag & V3D_OVERLAY_HIDE_MOTION_PATHS) == 0;
bool do_init;
OVERLAY_DupliData *dupli = OVERLAY_duplidata_get(ob, vedata, &do_init);
if (draw_facing) {
OVERLAY_facing_cache_populate(vedata, ob);
}
if (draw_wires) {
OVERLAY_wireframe_cache_populate(vedata, ob, dupli, do_init);
}
if (draw_outlines) {
OVERLAY_outline_cache_populate(vedata, ob, dupli, do_init);
}
if (draw_bone_selection) {
OVERLAY_pose_cache_populate(vedata, ob);
}
if (in_edit_mode) {
switch (ob->type) {
case OB_MESH:
OVERLAY_edit_mesh_cache_populate(vedata, ob);
break;
case OB_ARMATURE:
if (draw_bones) {
OVERLAY_edit_armature_cache_populate(vedata, ob);
}
break;
case OB_CURVE:
OVERLAY_edit_curve_cache_populate(vedata, ob);
break;
case OB_SURF:
OVERLAY_edit_surf_cache_populate(vedata, ob);
break;
case OB_LATTICE:
OVERLAY_edit_lattice_cache_populate(vedata, ob);
break;
case OB_MBALL:
OVERLAY_edit_metaball_cache_populate(vedata, ob);
break;
case OB_FONT:
OVERLAY_edit_text_cache_populate(vedata, ob);
break;
}
}
else if (in_pose_mode && draw_bones) {
OVERLAY_pose_armature_cache_populate(vedata, ob);
}
else if (in_paint_mode) {
switch (draw_ctx->object_mode) {
case OB_MODE_VERTEX_PAINT:
OVERLAY_paint_vertex_cache_populate(vedata, ob);
break;
case OB_MODE_WEIGHT_PAINT:
OVERLAY_paint_weight_cache_populate(vedata, ob);
break;
case OB_MODE_TEXTURE_PAINT:
OVERLAY_paint_texture_cache_populate(vedata, ob);
break;
default:
break;
}
}
else if (in_particle_edit_mode) {
OVERLAY_edit_particle_cache_populate(vedata, ob);
}
if (in_sculpt_mode) {
OVERLAY_sculpt_cache_populate(vedata, ob);
}
if (draw_motion_paths) {
OVERLAY_motion_path_cache_populate(vedata, ob);
}
switch (ob->type) {
case OB_ARMATURE:
if (draw_bones && (is_select || (!in_edit_mode && !in_pose_mode))) {
OVERLAY_armature_cache_populate(vedata, ob);
}
break;
case OB_MBALL:
if (!in_edit_mode) {
OVERLAY_metaball_cache_populate(vedata, ob);
}
break;
case OB_GPENCIL:
OVERLAY_gpencil_cache_populate(vedata, ob);
break;
}
/* Non-Meshes */
if (draw_extras) {
switch (ob->type) {
case OB_EMPTY:
OVERLAY_empty_cache_populate(vedata, ob);
break;
case OB_LAMP:
OVERLAY_light_cache_populate(vedata, ob);
break;
case OB_CAMERA:
OVERLAY_camera_cache_populate(vedata, ob);
break;
case OB_SPEAKER:
OVERLAY_speaker_cache_populate(vedata, ob);
break;
case OB_LIGHTPROBE:
OVERLAY_lightprobe_cache_populate(vedata, ob);
break;
case OB_LATTICE:
OVERLAY_lattice_cache_populate(vedata, ob);
break;
}
}
if (!BLI_listbase_is_empty(&ob->particlesystem)) {
OVERLAY_particle_cache_populate(vedata, ob);
}
/* Relationship, object center, bounbox ... */
OVERLAY_extra_cache_populate(vedata, ob);
if (dupli) {
dupli->base_flag = ob->base_flag;
}
}
static void OVERLAY_cache_finish(void *vedata)
{
/* TODO(fclem) Only do this when really needed. */
{
/* HACK we allocate the infront depth here to avoid the overhead when if is not needed. */
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRW_texture_ensure_fullscreen_2d(&dtxl->depth_in_front, GPU_DEPTH24_STENCIL8, 0);
GPU_framebuffer_ensure_config(
&dfbl->default_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
GPU_framebuffer_ensure_config(
&dfbl->in_front_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth_in_front), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
}
OVERLAY_antialiasing_cache_finish(vedata);
OVERLAY_armature_cache_finish(vedata);
OVERLAY_image_cache_finish(vedata);
}
static void OVERLAY_draw_scene(void *vedata)
{
OVERLAY_Data *data = vedata;
OVERLAY_PrivateData *pd = data->stl->pd;
OVERLAY_FramebufferList *fbl = data->fbl;
OVERLAY_antialiasing_start(vedata);
DRW_view_set_active(pd->view_default);
OVERLAY_image_draw(vedata);
OVERLAY_facing_draw(vedata);
OVERLAY_wireframe_draw(vedata);
OVERLAY_armature_draw(vedata);
OVERLAY_particle_draw(vedata);
OVERLAY_metaball_draw(vedata);
OVERLAY_extra_draw(vedata);
DRW_view_set_active(NULL);
OVERLAY_grid_draw(vedata);
OVERLAY_outline_draw(vedata);
DRW_view_set_active(pd->view_default);
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(fbl->overlay_in_front_fb);
/* If we are not in solid shading mode, we clear the depth. */
if (pd->clear_in_front) {
/* TODO(fclem) This clear should be done in a global place. */
GPU_framebuffer_clear_depth(fbl->overlay_in_front_fb, 1.0f);
}
}
OVERLAY_wireframe_in_front_draw(vedata);
OVERLAY_armature_in_front_draw(vedata);
OVERLAY_extra_in_front_draw(vedata);
OVERLAY_metaball_in_front_draw(vedata);
OVERLAY_image_in_front_draw(vedata);
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(fbl->overlay_default_fb);
}
OVERLAY_motion_path_draw(vedata);
OVERLAY_extra_centers_draw(vedata);
switch (pd->ctx_mode) {
case CTX_MODE_EDIT_MESH:
OVERLAY_edit_mesh_draw(vedata);
break;
case CTX_MODE_EDIT_SURFACE:
case CTX_MODE_EDIT_CURVE:
OVERLAY_edit_curve_draw(vedata);
break;
case CTX_MODE_EDIT_TEXT:
/* Text overlay need final color for color inversion. */
OVERLAY_antialiasing_end(vedata);
OVERLAY_edit_text_draw(vedata);
return; /* WATCH! dont do AA twice. */
case CTX_MODE_EDIT_LATTICE:
OVERLAY_edit_lattice_draw(vedata);
break;
case CTX_MODE_POSE:
/* Pain overlay needs final color because of multiply blend mode. */
OVERLAY_antialiasing_end(vedata);
OVERLAY_paint_draw(vedata);
OVERLAY_pose_draw(vedata);
return; /* WATCH! dont do AA twice. */
case CTX_MODE_PAINT_WEIGHT:
case CTX_MODE_PAINT_VERTEX:
case CTX_MODE_PAINT_TEXTURE:
/* Pain overlay need final color because of multiply blend mode. */
OVERLAY_antialiasing_end(vedata);
OVERLAY_paint_draw(vedata);
return; /* WATCH! dont do AA twice. */
case CTX_MODE_PARTICLE:
OVERLAY_edit_particle_draw(vedata);
break;
case CTX_MODE_SCULPT:
OVERLAY_sculpt_draw(vedata);
break;
default:
break;
}
OVERLAY_antialiasing_end(vedata);
}
static void OVERLAY_engine_free(void)
{
OVERLAY_shader_free();
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Engine Type
* \{ */
static const DrawEngineDataSize overlay_data_size = DRW_VIEWPORT_DATA_SIZE(OVERLAY_Data);
DrawEngineType draw_engine_overlay_type = {
NULL,
NULL,
N_("Overlay"),
&overlay_data_size,
&OVERLAY_engine_init,
&OVERLAY_engine_free,
&OVERLAY_cache_init,
&OVERLAY_cache_populate,
&OVERLAY_cache_finish,
NULL,
&OVERLAY_draw_scene,
NULL,
NULL,
NULL,
};
/** \} */
#undef SELECT_ENGINE

View File

@@ -12,24 +12,17 @@
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw
* \ingroup draw_engine
*/
#ifndef __EDIT_MESH_MODE_INTERN_H__
#define __EDIT_MESH_MODE_INTERN_H__
#ifndef __OVERLAY_ENGINE_H__
#define __OVERLAY_ENGINE_H__
struct ARegion;
struct Object;
struct UnitSettings;
struct View3D;
extern DrawEngineType draw_engine_overlay_type;
/* edit_mesh_mode_text.c */
void DRW_edit_mesh_mode_text_measure_stats(struct ARegion *ar,
struct View3D *v3d,
struct Object *ob,
const UnitSettings *unit);
#endif /* __EDIT_MESH_MODE_INTERN_H__ */
#endif /* __OVERLAY_ENGINE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "overlay_private.h"
void OVERLAY_facing_init(OVERLAY_Data *UNUSED(vedata))
{
}
void OVERLAY_facing_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->facing_ps, state | pd->clipping_state);
GPUShader *sh = OVERLAY_shader_facing();
pd->facing_grp = DRW_shgroup_create(sh, psl->facing_ps);
}
void OVERLAY_facing_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
DRW_shgroup_call(pd->facing_grp, geom, ob);
}
}
void OVERLAY_facing_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
/* We need to match underlying geometry pass, at the cost of bypassing TAA. */
DRW_view_set_active(NULL);
DRW_draw_pass(psl->facing_ps);
DRW_view_set_active(pd->view_default);
}

View File

@@ -0,0 +1,220 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "DNA_camera_types.h"
#include "DEG_depsgraph_query.h"
#include "ED_view3d.h"
#include "overlay_private.h"
enum {
SHOW_AXIS_X = (1 << 0),
SHOW_AXIS_Y = (1 << 1),
SHOW_AXIS_Z = (1 << 2),
SHOW_GRID = (1 << 3),
PLANE_XY = (1 << 4),
PLANE_XZ = (1 << 5),
PLANE_YZ = (1 << 6),
CLIP_ZPOS = (1 << 7),
CLIP_ZNEG = (1 << 8),
GRID_BACK = (1 << 9),
};
void OVERLAY_grid_init(OVERLAY_Data *vedata)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
OVERLAY_ShadingData *shd = &pd->shdata;
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
RegionView3D *rv3d = draw_ctx->rv3d;
const bool show_axis_x = (pd->v3d_gridflag & V3D_SHOW_X) != 0;
const bool show_axis_y = (pd->v3d_gridflag & V3D_SHOW_Y) != 0;
const bool show_axis_z = (pd->v3d_gridflag & V3D_SHOW_Z) != 0;
const bool show_floor = (pd->v3d_gridflag & V3D_SHOW_FLOOR) != 0;
const bool show_ortho_grid = (pd->v3d_gridflag & V3D_SHOW_ORTHO_GRID) != 0;
shd->grid_flag = 0;
if (pd->hide_overlays || !(show_axis_y || show_axis_z || show_floor || show_ortho_grid)) {
return;
}
float viewinv[4][4], wininv[4][4];
float viewmat[4][4], winmat[4][4];
DRW_view_winmat_get(NULL, winmat, false);
DRW_view_winmat_get(NULL, wininv, true);
DRW_view_viewmat_get(NULL, viewmat, false);
DRW_view_viewmat_get(NULL, viewinv, true);
/* if perps */
if (winmat[3][3] == 0.0f || rv3d->view == RV3D_VIEW_USER) {
if (show_axis_x) {
shd->grid_flag |= PLANE_XY | SHOW_AXIS_X;
}
if (show_axis_y) {
shd->grid_flag |= PLANE_XY | SHOW_AXIS_Y;
}
if (show_floor) {
shd->grid_flag |= PLANE_XY | SHOW_GRID;
}
}
else {
if (show_ortho_grid && ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) {
shd->grid_flag = PLANE_YZ | SHOW_AXIS_Y | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK;
}
else if (show_ortho_grid && ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
shd->grid_flag = PLANE_XY | SHOW_AXIS_X | SHOW_AXIS_Y | SHOW_GRID | GRID_BACK;
}
else if (show_ortho_grid && ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
shd->grid_flag = PLANE_XZ | SHOW_AXIS_X | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK;
}
}
shd->grid_axes[0] = (float)((shd->grid_flag & (PLANE_XZ | PLANE_XY)) != 0);
shd->grid_axes[1] = (float)((shd->grid_flag & (PLANE_YZ | PLANE_XY)) != 0);
shd->grid_axes[2] = (float)((shd->grid_flag & (PLANE_YZ | PLANE_XZ)) != 0);
/* Z axis if needed */
if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) {
shd->zpos_flag = SHOW_AXIS_Z;
float zvec[3], campos[3];
negate_v3_v3(zvec, viewinv[2]);
copy_v3_v3(campos, viewinv[3]);
/* z axis : chose the most facing plane */
if (fabsf(zvec[0]) < fabsf(zvec[1])) {
shd->zpos_flag |= PLANE_XZ;
}
else {
shd->zpos_flag |= PLANE_YZ;
}
shd->zneg_flag = shd->zpos_flag;
/* Persp : If camera is below floor plane, we switch clipping
* Ortho : If eye vector is looking up, we switch clipping */
if (((winmat[3][3] == 0.0f) && (campos[2] > 0.0f)) ||
((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f))) {
shd->zpos_flag |= CLIP_ZPOS;
shd->zneg_flag |= CLIP_ZNEG;
}
else {
shd->zpos_flag |= CLIP_ZNEG;
shd->zneg_flag |= CLIP_ZPOS;
}
shd->zplane_axes[0] = (float)((shd->zpos_flag & (PLANE_XZ | PLANE_XY)) != 0);
shd->zplane_axes[1] = (float)((shd->zpos_flag & (PLANE_YZ | PLANE_XY)) != 0);
shd->zplane_axes[2] = (float)((shd->zpos_flag & (PLANE_YZ | PLANE_XZ)) != 0);
}
else {
shd->zneg_flag = shd->zpos_flag = CLIP_ZNEG | CLIP_ZPOS;
}
float dist;
if (rv3d->persp == RV3D_CAMOB && v3d->camera && v3d->camera->type == OB_CAMERA) {
Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
dist = ((Camera *)(camera_object->data))->clip_end;
}
else {
dist = v3d->clip_end;
}
if (winmat[3][3] == 0.0f) {
shd->grid_mesh_size = dist;
}
else {
float viewdist = 1.0f / min_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
shd->grid_mesh_size = viewdist * dist;
}
shd->grid_distance = dist / 2.0f;
shd->grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f;
ED_view3d_grid_steps(scene, v3d, rv3d, shd->grid_steps);
}
void OVERLAY_grid_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_ShadingData *shd = &vedata->stl->pd->shdata;
OVERLAY_PassList *psl = vedata->psl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
psl->grid_ps = NULL;
if (shd->grid_flag == 0 || !DRW_state_is_fbo()) {
return;
}
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->grid_ps, state);
GPUShader *sh = OVERLAY_shader_grid();
struct GPUBatch *geom = DRW_cache_grid_get();
/* Create 3 quads to render ordered transparency Z axis */
DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->grid_ps);
DRW_shgroup_uniform_int(grp, "gridFlag", &shd->zneg_flag, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", shd->zplane_axes, 1);
DRW_shgroup_uniform_float(grp, "gridDistance", &shd->grid_distance, 1);
DRW_shgroup_uniform_float_copy(grp, "lineKernel", shd->grid_line_size);
DRW_shgroup_uniform_float_copy(grp, "meshSize", shd->grid_mesh_size);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_call(grp, geom, NULL);
grp = DRW_shgroup_create(sh, psl->grid_ps);
DRW_shgroup_uniform_int(grp, "gridFlag", &shd->grid_flag, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", shd->grid_axes, 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_float(grp, "gridSteps", shd->grid_steps, ARRAY_SIZE(shd->grid_steps));
DRW_shgroup_call(grp, geom, NULL);
grp = DRW_shgroup_create(sh, psl->grid_ps);
DRW_shgroup_uniform_int(grp, "gridFlag", &shd->zpos_flag, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", shd->zplane_axes, 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_call(grp, geom, NULL);
}
void OVERLAY_grid_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_FramebufferList *fbl = vedata->fbl;
if (psl->grid_ps) {
GPU_framebuffer_bind(fbl->overlay_color_only_fb);
DRW_draw_pass(psl->grid_ps);
GPU_framebuffer_bind(fbl->overlay_default_fb);
}
}

View File

@@ -0,0 +1,470 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "BKE_camera.h"
#include "BKE_image.h"
#include "BKE_movieclip.h"
#include "BKE_object.h"
#include "DNA_camera_types.h"
#include "DNA_screen_types.h"
#include "DEG_depsgraph_query.h"
#include "ED_view3d.h"
#include "IMB_imbuf_types.h"
#include "overlay_private.h"
void OVERLAY_image_init(OVERLAY_Data *vedata)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
OVERLAY_PrivateData *pd = vedata->stl->pd;
pd->view_reference_images = DRW_view_create_with_zoffset(
pd->view_default, draw_ctx->rv3d, -1.0f);
}
void OVERLAY_image_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DRWState state;
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER | DRW_STATE_BLEND_ALPHA_UNDER_PREMUL;
DRW_PASS_CREATE(psl->image_background_under_ps, state);
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->image_background_over_ps, state);
state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
DRW_PASS_CREATE(psl->image_empties_ps, state | pd->clipping_state);
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->image_empties_back_ps, state | pd->clipping_state);
DRW_PASS_CREATE(psl->image_empties_blend_ps, state | pd->clipping_state);
state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->image_empties_front_ps, state);
DRW_PASS_CREATE(psl->image_foreground_ps, state);
}
static void overlay_image_calc_aspect(Image *ima, const int size[2], float r_image_aspect[2])
{
float ima_x, ima_y;
if (ima) {
ima_x = size[0];
ima_y = size[1];
}
else {
/* if no image, make it a 1x1 empty square, honor scale & offset */
ima_x = ima_y = 1.0f;
}
/* Get the image aspect even if the buffer is invalid */
float sca_x = 1.0f, sca_y = 1.0f;
if (ima) {
if (ima->aspx > ima->aspy) {
sca_y = ima->aspy / ima->aspx;
}
else if (ima->aspx < ima->aspy) {
sca_x = ima->aspx / ima->aspy;
}
}
const float scale_x_inv = ima_x * sca_x;
const float scale_y_inv = ima_y * sca_y;
if (scale_x_inv > scale_y_inv) {
r_image_aspect[0] = 1.0f;
r_image_aspect[1] = scale_y_inv / scale_x_inv;
}
else {
r_image_aspect[0] = scale_x_inv / scale_y_inv;
r_image_aspect[1] = 1.0f;
}
}
static void camera_background_images_stereo_setup(Scene *scene,
View3D *v3d,
Image *ima,
ImageUser *iuser)
{
if (BKE_image_is_stereo(ima)) {
iuser->flag |= IMA_SHOW_STEREO;
if ((scene->r.scemode & R_MULTIVIEW) == 0) {
iuser->multiview_eye = STEREO_LEFT_ID;
}
else if (v3d->stereo3d_camera != STEREO_3D_ID) {
/* show only left or right camera */
iuser->multiview_eye = v3d->stereo3d_camera;
}
BKE_image_multiview_index(ima, iuser);
}
else {
iuser->flag &= ~IMA_SHOW_STEREO;
}
}
static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgpic,
const DRWContextState *draw_ctx,
OVERLAY_PrivateData *pd,
float *r_aspect,
bool *r_use_alpha_premult)
{
Image *image = bgpic->ima;
ImageUser *iuser = &bgpic->iuser;
MovieClip *clip = NULL;
GPUTexture *tex = NULL;
Scene *scene = draw_ctx->scene;
float aspect_x, aspect_y;
int width, height;
int ctime = (int)DEG_get_ctime(draw_ctx->depsgraph);
*r_use_alpha_premult = false;
switch (bgpic->source) {
case CAM_BGIMG_SOURCE_IMAGE:
if (image == NULL) {
return NULL;
}
*r_use_alpha_premult = (image->alpha_mode == IMA_ALPHA_PREMUL);
BKE_image_user_frame_calc(image, iuser, ctime);
if (image->source == IMA_SRC_SEQUENCE && !(iuser->flag & IMA_USER_FRAME_IN_RANGE)) {
/* Frame is out of range, dont show. */
return NULL;
}
else {
camera_background_images_stereo_setup(scene, draw_ctx->v3d, image, iuser);
}
ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, NULL);
if (ibuf == NULL) {
return NULL;
}
tex = GPU_texture_from_blender(image, iuser, GL_TEXTURE_2D);
if (tex == NULL) {
return NULL;
}
aspect_x = bgpic->ima->aspx;
aspect_y = bgpic->ima->aspy;
width = ibuf->x;
height = ibuf->y;
BKE_image_release_ibuf(image, ibuf, NULL);
break;
case CAM_BGIMG_SOURCE_MOVIE:
if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) {
if (scene->camera) {
clip = BKE_object_movieclip_get(scene, scene->camera, true);
}
}
else {
clip = bgpic->clip;
}
if (clip == NULL) {
return NULL;
}
BKE_movieclip_user_set_frame(&bgpic->cuser, ctime);
tex = GPU_texture_from_movieclip(clip, &bgpic->cuser, GL_TEXTURE_2D);
if (tex == NULL) {
return NULL;
}
aspect_x = clip->aspx;
aspect_y = clip->aspy;
BKE_movieclip_get_size(clip, &bgpic->cuser, &width, &height);
/* Save for freeing. */
BLI_addtail(&pd->bg_movie_clips, BLI_genericNodeN(clip));
break;
default:
/* Unsupported type. */
return NULL;
}
*r_aspect = (width * aspect_x) / (height * aspect_y);
return tex;
}
static void OVERLAY_image_free_movieclips_textures(OVERLAY_Data *data)
{
/* Free Movie clip textures after rendering */
LinkData *link;
while ((link = BLI_pophead(&data->stl->pd->bg_movie_clips))) {
MovieClip *clip = (MovieClip *)link->data;
GPU_free_texture_movieclip(clip);
MEM_freeN(link);
}
}
static void image_camera_background_matrix_get(const Camera *cam,
const CameraBGImage *bgpic,
const DRWContextState *draw_ctx,
const float image_aspect,
float rmat[4][4])
{
float rotate[4][4], scale[4][4], translate[4][4];
axis_angle_to_mat4_single(rotate, 'Z', -bgpic->rotation);
unit_m4(scale);
unit_m4(translate);
/* Normalized Object space camera frame corners. */
float cam_corners[4][3];
BKE_camera_view_frame(draw_ctx->scene, cam, cam_corners);
float cam_width = fabsf(cam_corners[0][0] - cam_corners[3][0]);
float cam_height = fabsf(cam_corners[0][1] - cam_corners[1][1]);
float cam_aspect = cam_width / cam_height;
if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) {
/* Crop. */
if (image_aspect > cam_aspect) {
scale[0][0] *= cam_height * image_aspect;
scale[1][1] *= cam_height;
}
else {
scale[0][0] *= cam_width;
scale[1][1] *= cam_width / image_aspect;
}
}
else if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) {
/* Fit. */
if (image_aspect > cam_aspect) {
scale[0][0] *= cam_width;
scale[1][1] *= cam_width / image_aspect;
}
else {
scale[0][0] *= cam_height * image_aspect;
scale[1][1] *= cam_height;
}
}
else {
/* Stretch. */
scale[0][0] *= cam_width;
scale[1][1] *= cam_height;
}
translate[3][0] = bgpic->offset[0];
translate[3][1] = bgpic->offset[1];
translate[3][2] = cam_corners[0][2];
/* These lines are for keeping 2.80 behavior and could be removed to keep 2.79 behavior. */
translate[3][0] *= min_ff(1.0f, cam_aspect);
translate[3][1] /= max_ff(1.0f, cam_aspect) * (image_aspect / cam_aspect);
/* quad is -1..1 so divide by 2. */
scale[0][0] *= 0.5f * bgpic->scale * ((bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) ? -1.0 : 1.0);
scale[1][1] *= 0.5f * bgpic->scale * ((bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) ? -1.0 : 1.0);
/* Camera shift. (middle of cam_corners) */
translate[3][0] += (cam_corners[0][0] + cam_corners[2][0]) * 0.5f;
translate[3][1] += (cam_corners[0][1] + cam_corners[2][1]) * 0.5f;
mul_m4_series(rmat, translate, rotate, scale);
}
void OVERLAY_image_camera_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
OVERLAY_PassList *psl = vedata->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Camera *cam = ob->data;
const bool show_frame = BKE_object_empty_image_frame_is_visible_in_view3d(ob, draw_ctx->rv3d);
if (!show_frame || DRW_state_is_select()) {
return;
}
float norm_obmat[4][4];
normalize_m4_m4(norm_obmat, ob->obmat);
for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
if (bgpic->flag & CAM_BGIMG_FLAG_DISABLED) {
continue;
}
float aspect = 1.0;
bool use_alpha_premult;
float mat[4][4];
/* retrieve the image we want to show, continue to next when no image could be found */
GPUTexture *tex = image_camera_background_texture_get(
bgpic, draw_ctx, pd, &aspect, &use_alpha_premult);
if (tex) {
image_camera_background_matrix_get(cam, bgpic, draw_ctx, aspect, mat);
mul_m4_m4m4(mat, norm_obmat, mat);
const bool is_foreground = (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != 0;
/* When drawing background we do 2 passes.
* - One alpha over, which works where background is visible.
* - One alpha under, works under partially visible objects. (only in cycles)
* This approach is not ideal and should be revisited.
**/
for (int i = 0; i < (is_foreground ? 1 : 2); i++) {
DRWPass *pass = is_foreground ? psl->image_foreground_ps :
((i == 0) ? psl->image_background_under_ps :
psl->image_background_over_ps);
GPUShader *sh = OVERLAY_shader_image();
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
float color[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha};
DRW_shgroup_uniform_texture(grp, "imgTexture", tex);
DRW_shgroup_uniform_bool_copy(grp, "imgPremultiplied", use_alpha_premult);
DRW_shgroup_uniform_bool_copy(grp, "imgAlphaBlend", true);
DRW_shgroup_uniform_bool_copy(grp, "imgLinear", !DRW_state_do_color_management());
DRW_shgroup_uniform_bool_copy(grp, "depthSet", true);
DRW_shgroup_uniform_vec4_copy(grp, "color", color);
DRW_shgroup_call_obmat(grp, DRW_cache_quad_get(), mat);
}
}
}
}
void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PassList *psl = vedata->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
const RegionView3D *rv3d = draw_ctx->rv3d;
GPUTexture *tex = NULL;
Image *ima = ob->data;
float mat[4][4];
const bool show_frame = BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d);
const bool show_image = show_frame && BKE_object_empty_image_data_is_visible_in_view3d(ob, rv3d);
const bool use_alpha_blend = (ob->empty_image_flag & OB_EMPTY_IMAGE_USE_ALPHA_BLEND) != 0;
const bool use_alpha_premult = ima && (ima->alpha_mode == IMA_ALPHA_PREMUL);
if (!show_frame) {
return;
}
{
/* Calling 'BKE_image_get_size' may free the texture. Get the size from 'tex' instead,
* see: T59347 */
int size[2] = {0};
if (ima != NULL) {
tex = GPU_texture_from_blender(ima, ob->iuser, GL_TEXTURE_2D);
if (tex) {
size[0] = GPU_texture_orig_width(tex);
size[1] = GPU_texture_orig_height(tex);
}
}
CLAMP_MIN(size[0], 1);
CLAMP_MIN(size[1], 1);
float image_aspect[2];
overlay_image_calc_aspect(ob->data, size, image_aspect);
copy_m4_m4(mat, ob->obmat);
mul_v3_fl(mat[0], image_aspect[0] * 0.5f * ob->empty_drawsize);
mul_v3_fl(mat[1], image_aspect[1] * 0.5f * ob->empty_drawsize);
madd_v3_v3fl(mat[3], mat[0], ob->ima_ofs[0] * 2.0f + 1.0f);
madd_v3_v3fl(mat[3], mat[1], ob->ima_ofs[1] * 2.0f + 1.0f);
}
/* Use the actual depth if we are doing depth tests to determine the distance to the object */
char depth_mode = DRW_state_is_depth() ? OB_EMPTY_IMAGE_DEPTH_DEFAULT : ob->empty_image_depth;
DRWPass *pass = NULL;
switch (depth_mode) {
case OB_EMPTY_IMAGE_DEPTH_DEFAULT:
pass = (use_alpha_blend) ? psl->image_empties_blend_ps : psl->image_empties_ps;
break;
case OB_EMPTY_IMAGE_DEPTH_BACK:
pass = psl->image_empties_back_ps;
break;
case OB_EMPTY_IMAGE_DEPTH_FRONT:
pass = psl->image_empties_front_ps;
break;
}
if (show_frame) {
OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob);
float *color;
DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
OVERLAY_empty_shape(cb, mat, 1.0f, OB_EMPTY_IMAGE, color);
}
if (show_image && tex && ((ob->color[3] > 0.0f) || !use_alpha_blend)) {
GPUShader *sh = OVERLAY_shader_image();
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_texture(grp, "imgTexture", tex);
DRW_shgroup_uniform_bool_copy(grp, "imgPremultiplied", use_alpha_premult);
DRW_shgroup_uniform_bool_copy(grp, "imgAlphaBlend", use_alpha_blend);
DRW_shgroup_uniform_bool_copy(grp, "imgLinear", false);
DRW_shgroup_uniform_bool_copy(grp, "depthSet", depth_mode != OB_EMPTY_IMAGE_DEPTH_DEFAULT);
DRW_shgroup_uniform_vec4_copy(grp, "color", ob->color);
DRW_shgroup_call_obmat(grp, DRW_cache_quad_get(), mat);
}
}
void OVERLAY_image_cache_finish(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_pass_sort_shgroup_reverse(psl->image_background_under_ps);
DRW_pass_sort_shgroup_z(psl->image_empties_blend_ps);
DRW_pass_sort_shgroup_z(psl->image_empties_front_ps);
DRW_pass_sort_shgroup_z(psl->image_empties_back_ps);
}
void OVERLAY_image_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DRW_view_set_active(pd->view_reference_images);
DRW_draw_pass(psl->image_background_over_ps);
DRW_draw_pass(psl->image_background_under_ps);
DRW_draw_pass(psl->image_empties_back_ps);
DRW_draw_pass(psl->image_empties_ps);
DRW_draw_pass(psl->image_empties_blend_ps);
DRW_view_set_active(pd->view_default);
}
void OVERLAY_image_in_front_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DRW_view_set_active(pd->view_reference_images);
DRW_draw_pass(psl->image_empties_front_ps);
DRW_draw_pass(psl->image_foreground_ps);
DRW_view_set_active(pd->view_default);
OVERLAY_image_free_movieclips_textures(vedata);
}

View File

@@ -0,0 +1,78 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "overlay_private.h"
void OVERLAY_edit_lattice_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUShader *sh;
DRWShadingGroup *grp;
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRW_PASS_CREATE(psl->edit_lattice_ps, state | pd->clipping_state);
sh = OVERLAY_shader_edit_lattice_wire();
pd->edit_lattice_wires_grp = grp = DRW_shgroup_create(sh, psl->edit_lattice_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
sh = OVERLAY_shader_edit_lattice_point();
pd->edit_lattice_points_grp = grp = DRW_shgroup_create(sh, psl->edit_lattice_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
}
void OVERLAY_edit_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUBatch *geom;
geom = DRW_cache_lattice_wire_get(ob, true);
DRW_shgroup_call(pd->edit_lattice_wires_grp, geom, ob);
geom = DRW_cache_lattice_vert_overlay_get(ob);
DRW_shgroup_call(pd->edit_lattice_points_grp, geom, ob);
}
void OVERLAY_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob);
const DRWContextState *draw_ctx = DRW_context_state_get();
float *color;
DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
struct GPUBatch *geom = DRW_cache_lattice_wire_get(ob, false);
OVERLAY_extra_wire(cb, geom, ob->obmat, color);
}
void OVERLAY_edit_lattice_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->edit_lattice_ps);
}

View File

@@ -0,0 +1,143 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "DNA_meta_types.h"
#include "BKE_object.h"
#include "DEG_depsgraph_query.h"
#include "ED_mball.h"
#include "overlay_private.h"
void OVERLAY_metaball_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
OVERLAY_InstanceFormats *formats = OVERLAY_shader_instance_formats_get();
#define BUF_INSTANCE DRW_shgroup_call_buffer_instance
for (int i = 0; i < 2; i++) {
DRWState infront_state = (DRW_state_is_select() && (i == 1)) ? DRW_STATE_IN_FRONT_SELECT : 0;
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRW_PASS_CREATE(psl->metaball_ps[i], state | pd->clipping_state | infront_state);
/* Reuse armature shader as it's perfect to outline ellipsoids. */
struct GPUVertFormat *format = formats->instance_bone;
struct GPUShader *sh = OVERLAY_shader_armature_sphere(true);
DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->metaball_ps[i]);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
pd->mball.handle[i] = BUF_INSTANCE(grp, format, DRW_cache_bone_point_wire_outline_get());
}
}
static void metaball_instance_data_set(
BoneInstanceData *data, Object *ob, const float *pos, const float radius, const float color[4])
{
/* Bone point radius is 0.05. Compensate for that. */
mul_v3_v3fl(data->mat[0], ob->obmat[0], radius / 0.05f);
mul_v3_v3fl(data->mat[1], ob->obmat[1], radius / 0.05f);
mul_v3_v3fl(data->mat[2], ob->obmat[2], radius / 0.05f);
mul_v3_m4v3(data->mat[3], ob->obmat, pos);
/* WATCH: Reminder, alpha is wiresize. */
OVERLAY_bone_instance_data_set_color(data, color);
}
void OVERLAY_edit_metaball_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
const bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0;
const bool is_select = DRW_state_is_select();
OVERLAY_PrivateData *pd = vedata->stl->pd;
MetaBall *mb = ob->data;
const float *color;
const float col_radius[4] = {0.63f, 0.19f, 0.19f, 1.0f}; /* 0x3030A0 */
const float col_radius_select[4] = {0.94f, 0.63f, 0.63f, 1.0f}; /* 0xA0A0F0 */
const float col_stiffness[4] = {0.19f, 0.63f, 0.19f, 1.0f}; /* 0x30A030 */
const float col_stiffness_select[4] = {0.63f, 0.94f, 0.63f, 1.0f}; /* 0xA0F0A0 */
int select_id = 0;
if (is_select) {
const Object *orig_object = DEG_get_original_object(ob);
select_id = orig_object->runtime.select_id;
}
LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
const bool is_selected = (ml->flag & SELECT) != 0;
const bool is_scale_radius = (ml->flag & MB_SCALE_RAD) != 0;
float stiffness_radius = ml->rad * atanf(ml->s) / (float)M_PI_2;
BoneInstanceData instdata;
if (is_select) {
DRW_select_load_id(select_id | MBALLSEL_RADIUS);
}
color = (is_selected && is_scale_radius) ? col_radius_select : col_radius;
metaball_instance_data_set(&instdata, ob, &ml->x, ml->rad, color);
DRW_buffer_add_entry_struct(pd->mball.handle[do_in_front], &instdata);
if (is_select) {
DRW_select_load_id(select_id | MBALLSEL_STIFF);
}
color = (is_selected && !is_scale_radius) ? col_stiffness_select : col_stiffness;
metaball_instance_data_set(&instdata, ob, &ml->x, stiffness_radius, color);
DRW_buffer_add_entry_struct(pd->mball.handle[do_in_front], &instdata);
select_id += 0x10000;
}
}
void OVERLAY_metaball_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
const bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0;
OVERLAY_PrivateData *pd = vedata->stl->pd;
MetaBall *mb = ob->data;
const DRWContextState *draw_ctx = DRW_context_state_get();
float *color;
DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
/* Draw radius only. */
BoneInstanceData instdata;
metaball_instance_data_set(&instdata, ob, &ml->x, ml->rad, color);
DRW_buffer_add_entry_struct(pd->mball.handle[do_in_front], &instdata);
}
}
void OVERLAY_metaball_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->metaball_ps[0]);
}
void OVERLAY_metaball_in_front_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->metaball_ps[1]);
}

View File

@@ -0,0 +1,231 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "BLI_string.h"
#include "DNA_armature_types.h"
#include "DEG_depsgraph_query.h"
#include "GPU_batch.h"
#include "UI_resources.h"
#include "draw_manager_text.h"
#include "overlay_private.h"
void OVERLAY_motion_path_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DRWShadingGroup *grp;
GPUShader *sh;
DRWState state = DRW_STATE_WRITE_COLOR;
DRW_PASS_CREATE(psl->motion_paths_ps, state | pd->clipping_state);
sh = OVERLAY_shader_motion_path_line();
pd->motion_path_lines_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
sh = OVERLAY_shader_motion_path_vert();
pd->motion_path_points_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
}
/* Just convert the CPU cache to GPU cache. */
/* T0D0(fclem) This should go into a draw_cache_impl_motionpath. */
static GPUVertBuf *mpath_vbo_get(bMotionPath *mpath)
{
if (!mpath->points_vbo) {
GPUVertFormat format = {0};
/* Match structure of bMotionPathVert. */
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
GPU_vertformat_attr_add(&format, "flag", GPU_COMP_I32, 1, GPU_FETCH_INT);
mpath->points_vbo = GPU_vertbuf_create_with_format(&format);
GPU_vertbuf_data_alloc(mpath->points_vbo, mpath->length);
/* meh... a useless memcpy. */
memcpy(mpath->points_vbo->data, mpath->points, sizeof(bMotionPathVert) * mpath->length);
}
return mpath->points_vbo;
}
static GPUBatch *mpath_batch_line_get(bMotionPath *mpath)
{
if (!mpath->batch_line) {
mpath->batch_line = GPU_batch_create(GPU_PRIM_LINE_STRIP, mpath_vbo_get(mpath), NULL);
}
return mpath->batch_line;
}
static GPUBatch *mpath_batch_points_get(bMotionPath *mpath)
{
if (!mpath->batch_points) {
mpath->batch_points = GPU_batch_create(GPU_PRIM_POINTS, mpath_vbo_get(mpath), NULL);
}
return mpath->batch_points;
}
static void motion_path_get_frame_range_to_draw(bAnimVizSettings *avs,
bMotionPath *mpath,
int current_frame,
int *r_start,
int *r_end,
int *r_step)
{
int start, end;
if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
start = current_frame - avs->path_bc;
end = current_frame + avs->path_ac + 1;
}
else {
start = avs->path_sf;
end = avs->path_ef;
}
if (start > end) {
SWAP(int, start, end);
}
CLAMP(start, mpath->start_frame, mpath->end_frame);
CLAMP(end, mpath->start_frame, mpath->end_frame);
*r_start = start;
*r_end = end;
*r_step = max_ii(avs->path_step, 1);
}
static void motion_path_cache(OVERLAY_Data *vedata,
Object *ob,
bPoseChannel *pchan,
bAnimVizSettings *avs,
bMotionPath *mpath)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
struct DRWTextStore *dt = DRW_text_cache_ensure();
int txt_flag = DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_ASCII;
int cfra = (int)DEG_get_ctime(draw_ctx->depsgraph);
bool selected = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->base_flag & BASE_SELECTED);
bool show_keyframes = (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) != 0;
bool show_keyframes_no = (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) != 0;
bool show_frame_no = (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) != 0;
bool show_lines = (mpath->flag & MOTIONPATH_FLAG_LINES) != 0;
float no_custom_col[3] = {-1.0f, -1.0f, -1.0f};
float *color = (mpath->flag & MOTIONPATH_FLAG_CUSTOM) ? mpath->color : no_custom_col;
int sfra, efra, stepsize;
motion_path_get_frame_range_to_draw(avs, mpath, cfra, &sfra, &efra, &stepsize);
int len = efra - sfra;
if (len == 0) {
return;
}
int start_index = sfra - mpath->start_frame;
/* Draw curve-line of path. */
if (show_lines) {
int motion_path_settings[4] = {cfra, sfra, efra, mpath->start_frame};
DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->motion_path_lines_grp);
DRW_shgroup_uniform_ivec4_copy(grp, "mpathLineSettings", motion_path_settings);
DRW_shgroup_uniform_int_copy(grp, "lineThickness", mpath->line_thickness);
DRW_shgroup_uniform_bool_copy(grp, "selected", selected);
DRW_shgroup_uniform_vec3_copy(grp, "customColor", color);
/* Only draw the required range. */
DRW_shgroup_call_range(grp, mpath_batch_line_get(mpath), start_index, len);
}
/* Draw points. */
{
int pt_size = max_ii(mpath->line_thickness - 1, 1);
int motion_path_settings[4] = {pt_size, cfra, mpath->start_frame, stepsize};
DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->motion_path_points_grp);
DRW_shgroup_uniform_ivec4_copy(grp, "mpathPointSettings", motion_path_settings);
DRW_shgroup_uniform_bool_copy(grp, "showKeyFrames", show_keyframes);
DRW_shgroup_uniform_vec3_copy(grp, "customColor", color);
/* Only draw the required range. */
DRW_shgroup_call_range(grp, mpath_batch_points_get(mpath), start_index, len);
}
/* Draw frame numbers at each framestep value */
if (show_frame_no || (show_keyframes_no && show_keyframes)) {
int i;
uchar col[4], col_kf[4];
UI_GetThemeColor3ubv(TH_TEXT_HI, col);
UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col_kf);
col[3] = col_kf[3] = 255;
bMotionPathVert *mpv = mpath->points + start_index;
for (i = 0; i < len; i += stepsize, mpv += stepsize) {
int frame = sfra + i;
char numstr[32];
size_t numstr_len;
bool is_keyframe = (mpv->flag & MOTIONPATH_VERT_KEY) != 0;
if ((show_keyframes && show_keyframes_no && is_keyframe) || (show_frame_no && (i == 0))) {
numstr_len = BLI_snprintf(numstr, sizeof(numstr), " %d", frame);
DRW_text_cache_add(
dt, mpv->co, numstr, numstr_len, 0, 0, txt_flag, (is_keyframe) ? col_kf : col);
}
else if (show_frame_no) {
bMotionPathVert *mpvP = (mpv - stepsize);
bMotionPathVert *mpvN = (mpv + stepsize);
/* Only draw framenum if several consecutive highlighted points don't occur on same point.
*/
if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
numstr_len = BLI_snprintf(numstr, sizeof(numstr), " %d", frame);
DRW_text_cache_add(dt, mpv->co, numstr, numstr_len, 0, 0, txt_flag, col);
}
}
}
}
}
void OVERLAY_motion_path_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
if (ob->type == OB_ARMATURE) {
if (OVERLAY_armature_is_pose_mode(ob, draw_ctx)) {
for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if (pchan->mpath) {
motion_path_cache(vedata, ob, pchan, &ob->pose->avs, pchan->mpath);
}
}
}
}
if (ob->mpath) {
motion_path_cache(vedata, ob, NULL, &ob->avs, ob->mpath);
}
}
void OVERLAY_motion_path_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->motion_paths_ps);
}

View File

@@ -0,0 +1,353 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "DNA_lightprobe_types.h"
#include "UI_resources.h"
#include "overlay_private.h"
void OVERLAY_outline_init(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
OVERLAY_TextureList *txl = vedata->txl;
if (DRW_state_is_fbo()) {
/* TODO only alloc if needed. */
/* XXX TODO GPU_R16UI can overflow, it would cause no harm
* (only bad colored or missing outlines) but we should
* use 32bits only if the scene have that many objects */
DRW_texture_ensure_fullscreen_2d(&txl->temp_depth_tx, GPU_DEPTH24_STENCIL8, 0);
DRW_texture_ensure_fullscreen_2d(&txl->outlines_id_tx, GPU_R16UI, 0);
GPU_framebuffer_ensure_config(
&fbl->outlines_prepass_fb,
{GPU_ATTACHMENT_TEXTURE(txl->temp_depth_tx), GPU_ATTACHMENT_TEXTURE(txl->outlines_id_tx)});
for (int i = 0; i < 2; i++) {
DRW_texture_ensure_fullscreen_2d(&txl->outlines_color_tx[i], GPU_RGBA8, DRW_TEX_FILTER);
GPU_framebuffer_ensure_config(
&fbl->outlines_process_fb[i],
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->outlines_color_tx[i])});
}
}
}
static int shgroup_theme_id_to_outline_id(int theme_id, const int base_flag)
{
if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) {
switch (theme_id) {
case TH_ACTIVE:
case TH_SELECT:
return 2;
case TH_TRANSFORM:
return 0;
default:
return -1;
}
}
switch (theme_id) {
case TH_ACTIVE:
return 3;
case TH_SELECT:
return 1;
case TH_TRANSFORM:
return 0;
default:
return -1;
}
}
static DRWShadingGroup *shgroup_theme_id_to_outline_or_null(OVERLAY_PrivateData *pd,
int theme_id,
const int base_flag)
{
int outline_id = shgroup_theme_id_to_outline_id(theme_id, base_flag);
switch (outline_id) {
case 3: /* TH_ACTIVE */
return pd->outlines_active_grp;
case 2: /* Duplis */
return pd->outlines_select_dupli_grp;
case 1: /* TH_SELECT */
return pd->outlines_select_grp;
case 0: /* TH_TRANSFORM */
return pd->outlines_transform_grp;
default:
return NULL;
}
}
static DRWShadingGroup *shgroup_theme_id_to_probe_outline_or_null(OVERLAY_PrivateData *pd,
int theme_id,
const int base_flag)
{
int outline_id = shgroup_theme_id_to_outline_id(theme_id, base_flag);
switch (outline_id) {
case 3: /* TH_ACTIVE */
return pd->outlines_probe_active_grp;
case 2: /* Duplis */
return pd->outlines_probe_select_dupli_grp;
case 1: /* TH_SELECT */
return pd->outlines_probe_select_grp;
case 0: /* TH_TRANSFORM */
return pd->outlines_probe_transform_grp;
default:
return NULL;
}
}
static DRWShadingGroup *outline_shgroup(DRWPass *pass, int outline_id, GPUShader *sh)
{
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_int_copy(grp, "outlineId", outline_id);
return grp;
}
void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_TextureList *txl = vedata->txl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRWShadingGroup *grp = NULL;
const float outline_width = UI_GetThemeValuef(TH_OUTLINE_WIDTH);
const bool do_outline_expand = (U.pixelsize > 1.0) || (outline_width > 2.0f);
const bool do_large_expand = ((U.pixelsize > 1.0) && (outline_width > 2.0f)) ||
(outline_width > 4.0f);
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRW_PASS_CREATE(psl->outlines_prepass_ps, state | pd->clipping_state);
GPUShader *sh_grid = OVERLAY_shader_outline_prepass_grid();
GPUShader *sh_geom = OVERLAY_shader_outline_prepass(pd->xray_enabled_and_not_wire);
GPUShader *sh = OVERLAY_shader_outline_prepass(false);
pd->outlines_transform_grp = outline_shgroup(psl->outlines_prepass_ps, 0, sh_geom);
pd->outlines_select_grp = outline_shgroup(psl->outlines_prepass_ps, 1, sh_geom);
pd->outlines_select_dupli_grp = outline_shgroup(psl->outlines_prepass_ps, 2, sh_geom);
pd->outlines_active_grp = outline_shgroup(psl->outlines_prepass_ps, 3, sh_geom);
pd->outlines_probe_transform_grp = outline_shgroup(psl->outlines_prepass_ps, 0, sh);
pd->outlines_probe_select_grp = outline_shgroup(psl->outlines_prepass_ps, 1, sh);
pd->outlines_probe_select_dupli_grp = outline_shgroup(psl->outlines_prepass_ps, 2, sh);
pd->outlines_probe_active_grp = outline_shgroup(psl->outlines_prepass_ps, 3, sh);
pd->outlines_probe_grid_grp = grp = DRW_shgroup_create(sh_grid, psl->outlines_prepass_ps);
DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
}
/* outlines_prepass_ps is still needed for selection of probes. */
if (!(pd->v3d_flag & V3D_SELECT_OUTLINE)) {
return;
}
{
DRW_PASS_CREATE(psl->outlines_detect_ps, DRW_STATE_WRITE_COLOR);
DRW_PASS_CREATE(psl->outlines_expand_ps, DRW_STATE_WRITE_COLOR);
DRW_PASS_CREATE(psl->outlines_bleed_ps, DRW_STATE_WRITE_COLOR);
DRW_PASS_CREATE(psl->outlines_resolve_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
GPUShader *sh = OVERLAY_shader_outline_detect(pd->xray_enabled_and_not_wire);
grp = DRW_shgroup_create(sh, psl->outlines_detect_ps);
/* Don't occlude the "outline" detection pass if in xray mode (too much flickering). */
DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", (pd->xray_enabled) ? 1.0f : 0.35f);
DRW_shgroup_uniform_texture_ref(grp, "outlineId", &txl->outlines_id_tx);
DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &txl->temp_depth_tx);
DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
if (do_outline_expand) {
sh = OVERLAY_shader_outline_expand(do_large_expand);
grp = DRW_shgroup_create(sh, psl->outlines_expand_ps);
DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &txl->outlines_color_tx[0]);
DRW_shgroup_uniform_bool_copy(grp, "doExpand", true);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
sh = OVERLAY_shader_outline_expand(false);
grp = DRW_shgroup_create(sh, psl->outlines_bleed_ps);
DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &txl->outlines_color_tx[1]);
DRW_shgroup_uniform_bool_copy(grp, "doExpand", false);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
else {
sh = OVERLAY_shader_outline_expand(false);
grp = DRW_shgroup_create(sh, psl->outlines_expand_ps);
DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &txl->outlines_color_tx[0]);
DRW_shgroup_uniform_bool_copy(grp, "doExpand", false);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
GPUTexture **outline_tx = &txl->outlines_color_tx[do_outline_expand ? 0 : 1];
sh = OVERLAY_shader_outline_resolve();
grp = DRW_shgroup_create(sh, psl->outlines_resolve_ps);
DRW_shgroup_uniform_texture_ref(grp, "outlineBluredColor", outline_tx);
DRW_shgroup_uniform_vec2_copy(grp, "rcpDimensions", DRW_viewport_invert_size_get());
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
}
static void outline_lightprobe(OVERLAY_PrivateData *pd, Object *ob, ViewLayer *view_layer)
{
DRWShadingGroup *grp;
LightProbe *prb = (LightProbe *)ob->data;
int theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
if (prb->type == LIGHTPROBE_TYPE_GRID) {
float corner[3];
float increment[3][3];
/* Update transforms */
float cell_dim[3], half_cell_dim[3];
cell_dim[0] = 2.0f / (float)(prb->grid_resolution_x);
cell_dim[1] = 2.0f / (float)(prb->grid_resolution_y);
cell_dim[2] = 2.0f / (float)(prb->grid_resolution_z);
mul_v3_v3fl(half_cell_dim, cell_dim, 0.5f);
/* First cell. */
copy_v3_fl(corner, -1.0f);
add_v3_v3(corner, half_cell_dim);
mul_m4_v3(ob->obmat, corner);
/* Opposite neighbor cell. */
copy_v3_fl3(increment[0], cell_dim[0], 0.0f, 0.0f);
copy_v3_fl3(increment[1], 0.0f, cell_dim[1], 0.0f);
copy_v3_fl3(increment[2], 0.0f, 0.0f, cell_dim[2]);
for (int i = 0; i < 3; i++) {
add_v3_v3(increment[i], half_cell_dim);
add_v3_fl(increment[i], -1.0f);
mul_m4_v3(ob->obmat, increment[i]);
sub_v3_v3(increment[i], corner);
}
int outline_id = shgroup_theme_id_to_outline_id(theme_id, ob->base_flag);
uint cell_count = prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z;
grp = DRW_shgroup_create_sub(pd->outlines_probe_grid_grp);
DRW_shgroup_uniform_int_copy(grp, "outlineId", outline_id);
DRW_shgroup_uniform_vec3_copy(grp, "corner", corner);
DRW_shgroup_uniform_vec3_copy(grp, "increment_x", increment[0]);
DRW_shgroup_uniform_vec3_copy(grp, "increment_y", increment[1]);
DRW_shgroup_uniform_vec3_copy(grp, "increment_z", increment[2]);
DRW_shgroup_uniform_ivec3_copy(grp, "grid_resolution", &prb->grid_resolution_x);
DRW_shgroup_call_procedural_points(grp, NULL, cell_count);
}
else if (prb->type == LIGHTPROBE_TYPE_PLANAR && (prb->flag & LIGHTPROBE_FLAG_SHOW_DATA)) {
grp = shgroup_theme_id_to_probe_outline_or_null(pd, theme_id, ob->base_flag);
DRW_shgroup_call_no_cull(grp, DRW_cache_quad_get(), ob);
}
}
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
Object *ob,
OVERLAY_DupliData *dupli,
bool init_dupli)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
struct GPUBatch *geom;
DRWShadingGroup *shgroup = NULL;
if (ob->type == OB_LIGHTPROBE) {
outline_lightprobe(pd, ob, draw_ctx->view_layer);
return;
}
if (dupli && !init_dupli) {
geom = dupli->outline_geom;
shgroup = dupli->outline_shgrp;
}
else {
/* This fixes only the biggest case which is a plane in ortho view. */
int flat_axis = 0;
bool is_flat_object_viewed_from_side = ((draw_ctx->rv3d->persp == RV3D_ORTHO) &&
DRW_object_is_flat(ob, &flat_axis) &&
DRW_object_axis_orthogonal_to_view(ob, flat_axis));
if (pd->xray_enabled_and_not_wire || is_flat_object_viewed_from_side) {
geom = DRW_cache_object_edge_detection_get(ob, NULL);
}
else {
geom = DRW_cache_object_surface_get(ob);
}
if (geom) {
int theme_id = DRW_object_wire_theme_get(ob, draw_ctx->view_layer, NULL);
shgroup = shgroup_theme_id_to_outline_or_null(pd, theme_id, ob->base_flag);
}
}
if (shgroup && geom) {
DRW_shgroup_call(shgroup, geom, ob);
}
if (init_dupli) {
dupli->outline_shgrp = shgroup;
dupli->outline_geom = geom;
}
}
void OVERLAY_outline_draw(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
OVERLAY_PassList *psl = vedata->psl;
float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
bool do_outlines = psl->outlines_prepass_ps != NULL &&
!DRW_pass_is_empty(psl->outlines_prepass_ps);
if (DRW_state_is_fbo() && do_outlines) {
DRW_stats_group_start("Outlines");
/* Render filled polygon on a separate framebuffer */
GPU_framebuffer_bind(fbl->outlines_prepass_fb);
GPU_framebuffer_clear_color_depth(fbl->outlines_prepass_fb, clearcol, 1.0f);
DRW_draw_pass(psl->outlines_prepass_ps);
/* Search outline pixels */
GPU_framebuffer_bind(fbl->outlines_process_fb[0]);
DRW_draw_pass(psl->outlines_detect_ps);
/* Expand outline to form a 3px wide line */
GPU_framebuffer_bind(fbl->outlines_process_fb[1]);
DRW_draw_pass(psl->outlines_expand_ps);
/* Bleed color so the AA can do it's stuff */
GPU_framebuffer_bind(fbl->outlines_process_fb[0]);
DRW_draw_pass(psl->outlines_bleed_ps);
/* restore main framebuffer */
GPU_framebuffer_bind(fbl->overlay_default_fb);
DRW_draw_pass(psl->outlines_resolve_ps);
DRW_stats_group_end();
}
else if (DRW_state_is_select()) {
/* Render probes spheres/planes so we can select them. */
DRW_draw_pass(psl->outlines_prepass_ps);
}
}

View File

@@ -0,0 +1,211 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "DNA_mesh_types.h"
#include "DEG_depsgraph_query.h"
#include "overlay_private.h"
void OVERLAY_paint_cache_init(OVERLAY_Data *vedata)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUShader *sh;
DRWShadingGroup *grp;
DRWState state;
const bool use_alpha_blending = (draw_ctx->v3d->shading.type == OB_WIRE);
const bool draw_contours = (pd->overlay.wpaint_flag & V3D_OVERLAY_WPAINT_CONTOURS) != 0;
float opacity = 0.0f;
switch (pd->ctx_mode) {
case CTX_MODE_POSE:
case CTX_MODE_PAINT_WEIGHT: {
opacity = pd->overlay.weight_paint_mode_opacity;
if (opacity > 0.0f) {
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
state |= use_alpha_blending ? DRW_STATE_BLEND_ALPHA : DRW_STATE_BLEND_MUL;
DRW_PASS_CREATE(psl->paint_color_ps, state | pd->clipping_state);
sh = OVERLAY_shader_paint_weight();
pd->paint_surf_grp = grp = DRW_shgroup_create(sh, psl->paint_color_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "drawContours", draw_contours);
DRW_shgroup_uniform_bool_copy(grp, "useAlphaBlend", use_alpha_blending);
DRW_shgroup_uniform_float_copy(grp, "opacity", opacity);
DRW_shgroup_uniform_texture(grp, "colorramp", G_draw.weight_ramp);
}
break;
}
case CTX_MODE_PAINT_VERTEX: {
opacity = pd->overlay.vertex_paint_mode_opacity;
if (opacity > 0.0f) {
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
state |= use_alpha_blending ? DRW_STATE_BLEND_ALPHA : DRW_STATE_BLEND_MUL;
DRW_PASS_CREATE(psl->paint_color_ps, state | pd->clipping_state);
sh = OVERLAY_shader_paint_vertcol();
pd->paint_surf_grp = grp = DRW_shgroup_create(sh, psl->paint_color_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "useAlphaBlend", use_alpha_blending);
DRW_shgroup_uniform_float_copy(grp, "opacity", opacity);
}
break;
}
case CTX_MODE_PAINT_TEXTURE: {
const ImagePaintSettings *imapaint = &draw_ctx->scene->toolsettings->imapaint;
const bool mask_enabled = imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL &&
imapaint->stencil != NULL;
opacity = mask_enabled ? pd->overlay.texture_paint_mode_opacity : 0.0f;
if (opacity > 0.0f) {
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->paint_color_ps, state | pd->clipping_state);
GPUTexture *tex = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D);
const bool mask_premult = (imapaint->stencil->alpha_mode == IMA_ALPHA_PREMUL);
const bool mask_inverted = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0;
sh = OVERLAY_shader_paint_texture();
pd->paint_surf_grp = grp = DRW_shgroup_create(sh, psl->paint_color_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "opacity", opacity);
DRW_shgroup_uniform_bool_copy(grp, "maskPremult", mask_premult);
DRW_shgroup_uniform_vec3_copy(grp, "maskColor", imapaint->stencil_col);
DRW_shgroup_uniform_bool_copy(grp, "maskInvertStencil", mask_inverted);
DRW_shgroup_uniform_texture(grp, "maskImage", tex);
}
break;
}
default:
BLI_assert(0);
break;
}
if (opacity <= 0.0f) {
psl->paint_color_ps = NULL;
pd->paint_surf_grp = NULL;
}
{
state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRW_PASS_CREATE(psl->paint_overlay_ps, state | pd->clipping_state);
sh = OVERLAY_shader_paint_face();
pd->paint_face_grp = grp = DRW_shgroup_create(sh, psl->paint_overlay_ps);
DRW_shgroup_uniform_vec4_copy(grp, "color", (float[4]){1.0f, 1.0f, 1.0f, 0.2f});
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
sh = OVERLAY_shader_paint_wire();
pd->paint_wire_selected_grp = grp = DRW_shgroup_create(sh, psl->paint_overlay_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "useSelect", true);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
pd->paint_wire_grp = grp = DRW_shgroup_create(sh, psl->paint_overlay_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "useSelect", false);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
sh = OVERLAY_shader_paint_point();
pd->paint_point_grp = grp = DRW_shgroup_create(sh, psl->paint_overlay_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
}
void OVERLAY_paint_texture_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUBatch *geom = NULL;
const Mesh *me_orig = DEG_get_original_object(ob)->data;
const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
if (pd->paint_surf_grp) {
geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
DRW_shgroup_call(pd->paint_surf_grp, geom, ob);
}
if (use_face_sel) {
geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call(pd->paint_face_grp, geom, ob);
}
}
void OVERLAY_paint_vertex_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
struct GPUBatch *geom = NULL;
const Mesh *me = ob->data;
const Mesh *me_orig = DEG_get_original_object(ob)->data;
const bool use_wire = (pd->overlay.paint_flag & V3D_OVERLAY_PAINT_WIRE) != 0;
const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
const bool use_vert_sel = (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
if (pd->paint_surf_grp) {
if (ob->mode == OB_MODE_VERTEX_PAINT) {
if (me->mloopcol == NULL) {
return;
}
geom = DRW_cache_mesh_surface_vertpaint_get(ob);
}
else {
geom = DRW_cache_mesh_surface_weights_get(ob);
}
DRW_shgroup_call(pd->paint_surf_grp, geom, ob);
}
if (use_face_sel || use_wire) {
geom = DRW_cache_mesh_surface_edges_get(ob);
DRW_shgroup_call(use_face_sel ? pd->paint_wire_selected_grp : pd->paint_wire_grp, geom, ob);
}
if (use_face_sel) {
geom = DRW_cache_mesh_surface_get(ob);
DRW_shgroup_call(pd->paint_face_grp, geom, ob);
}
if (use_vert_sel) {
geom = DRW_cache_mesh_all_verts_get(ob);
DRW_shgroup_call(pd->paint_point_grp, geom, ob);
}
}
void OVERLAY_paint_weight_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_paint_vertex_cache_populate(vedata, ob);
}
void OVERLAY_paint_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
if (psl->paint_color_ps) {
DRW_view_set_active(NULL);
DRW_draw_pass(psl->paint_color_ps);
}
DRW_draw_pass(psl->paint_overlay_ps);
}

View File

@@ -0,0 +1,217 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "DEG_depsgraph_query.h"
#include "DNA_particle_types.h"
#include "BKE_pointcache.h"
#include "ED_particle.h"
#include "overlay_private.h"
/* -------------------------------------------------------------------- */
/** \name Edit Particles
* \{ */
void OVERLAY_edit_particle_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
ParticleEditSettings *pset = PE_settings(draw_ctx->scene);
GPUShader *sh;
DRWShadingGroup *grp;
pd->edit_particle.use_weight = (pset->brushtype == PE_BRUSH_WEIGHT);
pd->edit_particle.select_mode = pset->selectmode;
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRW_PASS_CREATE(psl->edit_particle_ps, state | pd->clipping_state);
sh = OVERLAY_shader_edit_particle_strand();
pd->edit_particle_strand_grp = grp = DRW_shgroup_create(sh, psl->edit_particle_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "useWeight", pd->edit_particle.use_weight);
DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
sh = OVERLAY_shader_edit_particle_point();
pd->edit_particle_point_grp = grp = DRW_shgroup_create(sh, psl->edit_particle_ps);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
void OVERLAY_edit_particle_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id);
/* Usually the edit structure is created by Particle Edit Mode Toggle
* operator, but sometimes it's invoked after tagging hair as outdated
* (for example, when toggling edit mode). That makes it impossible to
* create edit structure for until after next dependency graph evaluation.
*
* Ideally, the edit structure will be created here already via some
* dependency graph callback or so, but currently trying to make it nicer
* only causes bad level calls and breaks design from the past.
*/
Object *ob_orig = DEG_get_original_object(ob);
PTCacheEdit *edit = PE_create_current(draw_ctx->depsgraph, scene_orig, ob_orig);
if (edit == NULL) {
/* Happens when trying to edit particles in EMITTER mode without
* having them cached.
*/
return;
}
/* NOTE: We need to pass evaluated particle system, which we need
* to find first.
*/
ParticleSystem *psys = ob->particlesystem.first;
LISTBASE_FOREACH (ParticleSystem *, psys_orig, &ob_orig->particlesystem) {
if (PE_get_current_from_psys(psys_orig) == edit) {
break;
}
psys = psys->next;
}
if (psys == NULL) {
printf("Error getting evaluated particle system for edit.\n");
return;
}
struct GPUBatch *geom;
{
geom = DRW_cache_particles_get_edit_strands(ob, psys, edit, pd->edit_particle.use_weight);
DRW_shgroup_call(pd->edit_particle_strand_grp, geom, NULL);
}
if (pd->edit_particle.select_mode == SCE_SELECT_POINT) {
geom = DRW_cache_particles_get_edit_inner_points(ob, psys, edit);
DRW_shgroup_call(pd->edit_particle_point_grp, geom, NULL);
}
if (ELEM(pd->edit_particle.select_mode, SCE_SELECT_POINT, SCE_SELECT_END)) {
geom = DRW_cache_particles_get_edit_tip_points(ob, psys, edit);
DRW_shgroup_call(pd->edit_particle_point_grp, geom, NULL);
}
}
void OVERLAY_edit_particle_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->edit_particle_ps);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Particles
* \{ */
void OVERLAY_particle_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
ParticleEditSettings *pset = PE_settings(draw_ctx->scene);
GPUShader *sh;
DRWShadingGroup *grp;
pd->edit_particle.use_weight = (pset->brushtype == PE_BRUSH_WEIGHT);
pd->edit_particle.select_mode = pset->selectmode;
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRW_PASS_CREATE(psl->particle_ps, state | pd->clipping_state);
sh = OVERLAY_shader_particle_dot();
pd->particle_dots_grp = grp = DRW_shgroup_create(sh, psl->particle_ps);
DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp);
sh = OVERLAY_shader_particle_shape();
pd->particle_shapes_grp = grp = DRW_shgroup_create(sh, psl->particle_ps);
DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp);
}
void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) {
continue;
}
ParticleSettings *part = psys->part;
int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
if (part->type == PART_HAIR) {
/* Hairs should have been rendered by the render engine.*/
continue;
}
if (!ELEM(draw_as, PART_DRAW_NOT, PART_DRAW_OB, PART_DRAW_GR)) {
struct GPUBatch *geom = DRW_cache_particles_get_dots(ob, psys);
struct GPUBatch *shape = NULL;
DRWShadingGroup *grp;
/* TODO(fclem) Here would be a good place for preemptive culling. */
/* fclem: Is color even usefull in our modern context? */
Material *ma = give_current_material(ob, part->omat);
float color[4] = {0.6f, 0.6f, 0.6f, part->draw_size};
if (ma != NULL) {
copy_v3_v3(color, &ma->r);
}
switch (draw_as) {
default:
case PART_DRAW_DOT:
grp = DRW_shgroup_create_sub(pd->particle_dots_grp);
DRW_shgroup_uniform_vec4_copy(grp, "color", color);
DRW_shgroup_call(grp, geom, NULL);
break;
case PART_DRAW_AXIS:
case PART_DRAW_CIRC:
case PART_DRAW_CROSS:
grp = DRW_shgroup_create_sub(pd->particle_shapes_grp);
DRW_shgroup_uniform_vec4_copy(grp, "color", color);
shape = DRW_cache_particles_get_prim(draw_as);
DRW_shgroup_call_instances_with_attribs(grp, NULL, shape, geom);
break;
}
}
}
}
void OVERLAY_particle_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->particle_ps);
}
/** \} */

View File

@@ -0,0 +1,585 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup DNA
*/
#ifndef __OVERLAY_PRIVATE_H__
#define __OVERLAY_PRIVATE_H__
#ifdef __APPLE__
# define USE_GEOM_SHADER_WORKAROUND 1
#else
# define USE_GEOM_SHADER_WORKAROUND 0
#endif
typedef struct OVERLAY_FramebufferList {
struct GPUFrameBuffer *overlay_default_fb;
struct GPUFrameBuffer *overlay_line_fb;
struct GPUFrameBuffer *overlay_color_only_fb;
struct GPUFrameBuffer *overlay_in_front_fb;
struct GPUFrameBuffer *outlines_prepass_fb;
struct GPUFrameBuffer *outlines_process_fb[2];
} OVERLAY_FramebufferList;
typedef struct OVERLAY_TextureList {
struct GPUTexture *temp_depth_tx;
struct GPUTexture *dummy_depth_tx;
struct GPUTexture *outlines_id_tx;
struct GPUTexture *outlines_color_tx[2];
struct GPUTexture *overlay_color_tx;
struct GPUTexture *overlay_color_history_tx;
struct GPUTexture *overlay_line_tx;
struct GPUTexture *edit_mesh_occlude_wire_tx;
} OVERLAY_TextureList;
#define NOT_IN_FRONT 0
#define IN_FRONT 1
typedef struct OVERLAY_PassList {
DRWPass *antialiasing_ps;
DRWPass *armature_ps[2];
DRWPass *armature_bone_select_ps;
DRWPass *armature_transp_ps;
DRWPass *edit_curve_wire_ps[2];
DRWPass *edit_curve_handle_ps;
DRWPass *edit_lattice_ps;
DRWPass *edit_mesh_depth_ps[2];
DRWPass *edit_mesh_verts_ps[2];
DRWPass *edit_mesh_edges_ps[2];
DRWPass *edit_mesh_faces_ps[2];
DRWPass *edit_mesh_faces_cage_ps[2];
DRWPass *edit_mesh_analysis_ps;
DRWPass *edit_mesh_normals_ps;
DRWPass *edit_mesh_weight_ps;
DRWPass *edit_particle_ps;
DRWPass *edit_text_overlay_ps;
DRWPass *edit_text_wire_ps[2];
DRWPass *extra_ps[2];
DRWPass *extra_blend_ps;
DRWPass *extra_centers_ps;
DRWPass *facing_ps;
DRWPass *grid_ps;
DRWPass *image_background_under_ps;
DRWPass *image_background_over_ps;
DRWPass *image_empties_ps;
DRWPass *image_empties_back_ps;
DRWPass *image_empties_blend_ps;
DRWPass *image_empties_front_ps;
DRWPass *image_foreground_ps;
DRWPass *metaball_ps[2];
DRWPass *motion_paths_ps;
DRWPass *outlines_prepass_ps;
DRWPass *outlines_detect_ps;
DRWPass *outlines_expand_ps;
DRWPass *outlines_bleed_ps;
DRWPass *outlines_resolve_ps;
DRWPass *paint_color_ps;
DRWPass *paint_overlay_ps;
DRWPass *particle_ps;
DRWPass *sculpt_mask_ps;
DRWPass *wireframe_ps;
DRWPass *wireframe_xray_ps;
} OVERLAY_PassList;
/* Data used by GLSL shader. To be used as UBO. */
typedef struct OVERLAY_ShadingData {
/** Grid */
float grid_axes[3], grid_distance;
float zplane_axes[3], grid_mesh_size;
float grid_steps[8];
float inv_viewport_size[2];
float grid_line_size;
int grid_flag;
int zpos_flag;
int zneg_flag;
/** Wireframe */
float wire_step_param;
/** Edit Curve */
float edit_curve_normal_length;
/** Edit Mesh */
int data_mask[4];
} OVERLAY_ShadingData;
typedef struct OVERLAY_ExtraCallBuffers {
DRWCallBuffer *camera_frame;
DRWCallBuffer *camera_tria[2];
DRWCallBuffer *camera_distances;
DRWCallBuffer *camera_volume;
DRWCallBuffer *camera_volume_frame;
DRWCallBuffer *center_active;
DRWCallBuffer *center_selected;
DRWCallBuffer *center_deselected;
DRWCallBuffer *center_selected_lib;
DRWCallBuffer *center_deselected_lib;
DRWCallBuffer *empty_axes;
DRWCallBuffer *empty_capsule_body;
DRWCallBuffer *empty_capsule_cap;
DRWCallBuffer *empty_circle;
DRWCallBuffer *empty_cone;
DRWCallBuffer *empty_cube;
DRWCallBuffer *empty_cylinder;
DRWCallBuffer *empty_image_frame;
DRWCallBuffer *empty_plain_axes;
DRWCallBuffer *empty_single_arrow;
DRWCallBuffer *empty_sphere;
DRWCallBuffer *empty_sphere_solid;
DRWCallBuffer *extra_dashed_lines;
DRWCallBuffer *extra_lines;
DRWCallBuffer *field_curve;
DRWCallBuffer *field_force;
DRWCallBuffer *field_vortex;
DRWCallBuffer *field_wind;
DRWCallBuffer *field_cone_limit;
DRWCallBuffer *field_sphere_limit;
DRWCallBuffer *field_tube_limit;
DRWCallBuffer *groundline;
DRWCallBuffer *light_point;
DRWCallBuffer *light_sun;
DRWCallBuffer *light_spot;
DRWCallBuffer *light_spot_cone_back;
DRWCallBuffer *light_spot_cone_front;
DRWCallBuffer *light_area[2];
DRWCallBuffer *origin_xform;
DRWCallBuffer *probe_planar;
DRWCallBuffer *probe_cube;
DRWCallBuffer *probe_grid;
DRWCallBuffer *speaker;
DRWShadingGroup *extra_wire;
DRWShadingGroup *extra_loose_points;
} OVERLAY_ExtraCallBuffers;
typedef struct OVERLAY_ArmatureCallBuffers {
DRWCallBuffer *box_outline;
DRWCallBuffer *box_solid;
DRWCallBuffer *dof_lines;
DRWCallBuffer *dof_sphere;
DRWCallBuffer *envelope_distance;
DRWCallBuffer *envelope_outline;
DRWCallBuffer *envelope_solid;
DRWCallBuffer *octa_outline;
DRWCallBuffer *octa_solid;
DRWCallBuffer *point_outline;
DRWCallBuffer *point_solid;
DRWCallBuffer *stick;
DRWCallBuffer *wire;
DRWShadingGroup *custom_solid;
DRWShadingGroup *custom_outline;
GHash *custom_shapes_ghash;
} OVERLAY_ArmatureCallBuffers;
typedef struct OVERLAY_PrivateData {
DRWShadingGroup *armature_bone_select_act_grp;
DRWShadingGroup *armature_bone_select_grp;
DRWShadingGroup *edit_curve_normal_grp[2];
DRWShadingGroup *edit_curve_wire_grp[2];
DRWShadingGroup *edit_curve_handle_grp;
DRWShadingGroup *edit_curve_points_grp;
DRWShadingGroup *edit_lattice_points_grp;
DRWShadingGroup *edit_lattice_wires_grp;
DRWShadingGroup *edit_mesh_depth_grp[2];
DRWShadingGroup *edit_mesh_faces_grp[2];
DRWShadingGroup *edit_mesh_faces_cage_grp[2];
DRWShadingGroup *edit_mesh_verts_grp[2];
DRWShadingGroup *edit_mesh_edges_grp[2];
DRWShadingGroup *edit_mesh_facedots_grp[2];
DRWShadingGroup *edit_mesh_skin_roots_grp[2];
DRWShadingGroup *edit_mesh_normals_grp;
DRWShadingGroup *edit_mesh_analysis_grp;
DRWShadingGroup *edit_mesh_weight_grp;
DRWShadingGroup *edit_particle_strand_grp;
DRWShadingGroup *edit_particle_point_grp;
DRWShadingGroup *edit_text_overlay_grp;
DRWShadingGroup *edit_text_wire_grp[2];
DRWShadingGroup *facing_grp;
DRWShadingGroup *motion_path_lines_grp;
DRWShadingGroup *motion_path_points_grp;
DRWShadingGroup *outlines_active_grp;
DRWShadingGroup *outlines_select_grp;
DRWShadingGroup *outlines_select_dupli_grp;
DRWShadingGroup *outlines_transform_grp;
DRWShadingGroup *outlines_probe_transform_grp;
DRWShadingGroup *outlines_probe_select_grp;
DRWShadingGroup *outlines_probe_select_dupli_grp;
DRWShadingGroup *outlines_probe_active_grp;
DRWShadingGroup *outlines_probe_grid_grp;
DRWShadingGroup *paint_surf_grp;
DRWShadingGroup *paint_wire_grp;
DRWShadingGroup *paint_wire_selected_grp;
DRWShadingGroup *paint_point_grp;
DRWShadingGroup *paint_face_grp;
DRWShadingGroup *particle_dots_grp;
DRWShadingGroup *particle_shapes_grp;
DRWShadingGroup *sculpt_mask_grp;
DRWShadingGroup *wires_grp[2][2]; /* With and without coloring. */
DRWShadingGroup *wires_all_grp[2][2]; /* With and without coloring. */
DRWShadingGroup *wires_sculpt_grp[2];
DRWView *view_default;
DRWView *view_wires;
DRWView *view_edit_faces;
DRWView *view_edit_faces_cage;
DRWView *view_edit_edges;
DRWView *view_edit_verts;
DRWView *view_reference_images;
/** TODO get rid of this. */
ListBase smoke_domains;
ListBase bg_movie_clips;
/** Two instances for in_front option and without. */
OVERLAY_ExtraCallBuffers extra_call_buffers[2];
OVERLAY_ArmatureCallBuffers armature_call_buffers[2];
View3DOverlay overlay;
enum eContextObjectMode ctx_mode;
bool clear_in_front;
bool wireframe_mode;
bool hide_overlays;
bool xray_enabled;
bool xray_enabled_and_not_wire;
short v3d_flag; /* TODO move to View3DOverlay */
short v3d_gridflag; /* TODO move to View3DOverlay */
DRWState clipping_state;
OVERLAY_ShadingData shdata;
struct {
short sample;
short target_sample;
float prev_persmat[4][4];
bool enabled;
} antialiasing;
struct {
bool show_handles;
} edit_curve;
struct {
int ghost_ob;
int edit_ob;
bool do_zbufclip;
bool do_faces;
bool do_edges;
bool select_vert;
bool select_face;
bool select_edge;
int flag; /** Copy of v3d->overlay.edit_flag. */
} edit_mesh;
struct {
bool use_weight;
int select_mode;
} edit_particle;
struct {
bool transparent;
bool show_relations;
bool do_pose_fade_geom;
} armature;
struct {
DRWCallBuffer *handle[2];
} mball;
} OVERLAY_PrivateData; /* Transient data */
typedef struct OVERLAY_StorageList {
struct OVERLAY_PrivateData *pd;
} OVERLAY_StorageList;
typedef struct OVERLAY_Data {
void *engine_type;
OVERLAY_FramebufferList *fbl;
OVERLAY_TextureList *txl;
OVERLAY_PassList *psl;
OVERLAY_StorageList *stl;
} OVERLAY_Data;
typedef struct OVERLAY_DupliData {
DRWShadingGroup *wire_shgrp;
DRWShadingGroup *outline_shgrp;
DRWShadingGroup *extra_shgrp;
struct GPUBatch *wire_geom;
struct GPUBatch *outline_geom;
struct GPUBatch *extra_geom;
short base_flag;
} OVERLAY_DupliData;
typedef struct BoneInstanceData {
/* Keep sync with bone instance vertex format (OVERLAY_InstanceFormats) */
union {
float mat[4][4];
struct {
float _pad0[3], color_hint_a;
float _pad1[3], color_hint_b;
float _pad2[3], color_a;
float _pad3[3], color_b;
};
struct {
float _pad00[3], amin_a;
float _pad01[3], amin_b;
float _pad02[3], amax_a;
float _pad03[3], amax_b;
};
};
} BoneInstanceData;
typedef struct OVERLAY_InstanceFormats {
struct GPUVertFormat *instance_pos;
struct GPUVertFormat *instance_extra;
struct GPUVertFormat *instance_bone;
struct GPUVertFormat *instance_bone_outline;
struct GPUVertFormat *instance_bone_envelope;
struct GPUVertFormat *instance_bone_envelope_distance;
struct GPUVertFormat *instance_bone_envelope_outline;
struct GPUVertFormat *instance_bone_stick;
struct GPUVertFormat *pos;
struct GPUVertFormat *pos_color;
struct GPUVertFormat *wire_extra;
} OVERLAY_InstanceFormats;
/* Pack data into the last row of the 4x4 matrix. It will be decoded by the vertex shader. */
BLI_INLINE void pack_data_in_mat4(
float rmat[4][4], const float mat[4][4], float a, float b, float c, float d)
{
copy_m4_m4(rmat, mat);
rmat[0][3] = a;
rmat[1][3] = b;
rmat[2][3] = c;
rmat[3][3] = d;
}
BLI_INLINE void pack_v4_in_mat4(float rmat[4][4], const float mat[4][4], const float v[4])
{
pack_data_in_mat4(rmat, mat, v[0], v[1], v[2], v[3]);
}
BLI_INLINE void pack_fl_in_mat4(float rmat[4][4], const float mat[4][4], float a)
{
copy_m4_m4(rmat, mat);
rmat[3][3] = a;
}
void OVERLAY_antialiasing_reset(OVERLAY_Data *vedata);
void OVERLAY_antialiasing_init(OVERLAY_Data *vedata);
void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata);
void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata);
void OVERLAY_antialiasing_start(OVERLAY_Data *vedata);
void OVERLAY_antialiasing_end(OVERLAY_Data *vedata);
bool OVERLAY_armature_is_pose_mode(Object *ob, const struct DRWContextState *draw_ctx);
void OVERLAY_armature_cache_init(OVERLAY_Data *vedata);
void OVERLAY_armature_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_armature_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_pose_armature_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_armature_cache_finish(OVERLAY_Data *vedata);
void OVERLAY_armature_draw(OVERLAY_Data *vedata);
void OVERLAY_armature_in_front_draw(OVERLAY_Data *vedata);
void OVERLAY_pose_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_pose_draw(OVERLAY_Data *vedata);
void OVERLAY_bone_instance_data_set_color_hint(BoneInstanceData *data, const float hint_color[4]);
void OVERLAY_bone_instance_data_set_color(BoneInstanceData *data, const float bone_color[4]);
void OVERLAY_edit_curve_init(OVERLAY_Data *vedata);
void OVERLAY_edit_curve_cache_init(OVERLAY_Data *vedata);
void OVERLAY_edit_curve_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_surf_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_curve_draw(OVERLAY_Data *vedata);
void OVERLAY_edit_lattice_cache_init(OVERLAY_Data *vedata);
void OVERLAY_edit_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_lattice_draw(OVERLAY_Data *vedata);
void OVERLAY_edit_text_cache_init(OVERLAY_Data *vedata);
void OVERLAY_edit_text_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_text_draw(OVERLAY_Data *vedata);
void OVERLAY_edit_mesh_init(OVERLAY_Data *vedata);
void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata);
void OVERLAY_edit_mesh_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_mesh_draw(OVERLAY_Data *vedata);
void OVERLAY_edit_particle_cache_init(OVERLAY_Data *vedata);
void OVERLAY_edit_particle_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_edit_particle_draw(OVERLAY_Data *vedata);
void OVERLAY_extra_cache_init(OVERLAY_Data *vedata);
void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_extra_draw(OVERLAY_Data *vedata);
void OVERLAY_extra_in_front_draw(OVERLAY_Data *vedata);
void OVERLAY_extra_centers_draw(OVERLAY_Data *vedata);
void OVERLAY_camera_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_empty_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_light_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_speaker_cache_populate(OVERLAY_Data *vedata, Object *ob);
OVERLAY_ExtraCallBuffers *OVERLAY_extra_call_buffer_get(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_extra_line_dashed(OVERLAY_ExtraCallBuffers *cb,
const float start[3],
const float end[3],
const float color[4]);
void OVERLAY_extra_line(OVERLAY_ExtraCallBuffers *cb,
const float start[3],
const float end[3],
const int color_id);
void OVERLAY_empty_shape(OVERLAY_ExtraCallBuffers *cb,
const float mat[4][4],
const float draw_size,
const char draw_type,
const float color[4]);
void OVERLAY_extra_loose_points(OVERLAY_ExtraCallBuffers *cb,
struct GPUBatch *geom,
const float mat[4][4],
const float color[4]);
void OVERLAY_extra_wire(OVERLAY_ExtraCallBuffers *cb,
struct GPUBatch *geom,
const float mat[4][4],
const float color[4]);
void OVERLAY_facing_init(OVERLAY_Data *vedata);
void OVERLAY_facing_cache_init(OVERLAY_Data *vedata);
void OVERLAY_facing_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_facing_draw(OVERLAY_Data *vedata);
void OVERLAY_grid_init(OVERLAY_Data *vedata);
void OVERLAY_grid_cache_init(OVERLAY_Data *vedata);
void OVERLAY_grid_draw(OVERLAY_Data *vedata);
void OVERLAY_image_init(OVERLAY_Data *vedata);
void OVERLAY_image_cache_init(OVERLAY_Data *vedata);
void OVERLAY_image_camera_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_image_cache_finish(OVERLAY_Data *vedata);
void OVERLAY_image_draw(OVERLAY_Data *vedata);
void OVERLAY_image_in_front_draw(OVERLAY_Data *vedata);
void OVERLAY_metaball_cache_init(OVERLAY_Data *vedata);
void OVERLAY_edit_metaball_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_metaball_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_metaball_draw(OVERLAY_Data *vedata);
void OVERLAY_metaball_in_front_draw(OVERLAY_Data *vedata);
void OVERLAY_motion_path_cache_init(OVERLAY_Data *vedata);
void OVERLAY_motion_path_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_motion_path_draw(OVERLAY_Data *vedata);
void OVERLAY_outline_init(OVERLAY_Data *vedata);
void OVERLAY_outline_cache_init(OVERLAY_Data *vedata);
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
Object *ob,
OVERLAY_DupliData *dupli,
bool init_dupli);
void OVERLAY_outline_draw(OVERLAY_Data *vedata);
void OVERLAY_paint_cache_init(OVERLAY_Data *vedata);
void OVERLAY_paint_texture_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_paint_vertex_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_paint_weight_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_paint_draw(OVERLAY_Data *vedata);
void OVERLAY_particle_cache_init(OVERLAY_Data *vedata);
void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_particle_draw(OVERLAY_Data *vedata);
void OVERLAY_sculpt_cache_init(OVERLAY_Data *vedata);
void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob);
void OVERLAY_sculpt_draw(OVERLAY_Data *vedata);
void OVERLAY_wireframe_init(OVERLAY_Data *vedata);
void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata);
void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
Object *ob,
OVERLAY_DupliData *dupli,
bool init_dupli);
void OVERLAY_wireframe_draw(OVERLAY_Data *vedata);
void OVERLAY_wireframe_in_front_draw(OVERLAY_Data *vedata);
GPUShader *OVERLAY_shader_antialiasing(void);
GPUShader *OVERLAY_shader_armature_degrees_of_freedom(void);
GPUShader *OVERLAY_shader_armature_envelope(bool use_outline);
GPUShader *OVERLAY_shader_armature_shape(bool use_outline);
GPUShader *OVERLAY_shader_armature_sphere(bool use_outline);
GPUShader *OVERLAY_shader_armature_stick(void);
GPUShader *OVERLAY_shader_armature_wire(void);
GPUShader *OVERLAY_shader_depth_only(void);
GPUShader *OVERLAY_shader_edit_curve_handle(void);
GPUShader *OVERLAY_shader_edit_curve_point(void);
GPUShader *OVERLAY_shader_edit_curve_wire(void);
GPUShader *OVERLAY_shader_edit_lattice_point(void);
GPUShader *OVERLAY_shader_edit_lattice_wire(void);
GPUShader *OVERLAY_shader_edit_mesh_analysis(void);
GPUShader *OVERLAY_shader_edit_mesh_edge(bool use_flat_interp);
GPUShader *OVERLAY_shader_edit_mesh_face(void);
GPUShader *OVERLAY_shader_edit_mesh_facedot(void);
GPUShader *OVERLAY_shader_edit_mesh_normal(void);
GPUShader *OVERLAY_shader_edit_mesh_skin_root(void);
GPUShader *OVERLAY_shader_edit_mesh_vert(void);
GPUShader *OVERLAY_shader_edit_particle_strand(void);
GPUShader *OVERLAY_shader_edit_particle_point(void);
GPUShader *OVERLAY_shader_extra(void);
GPUShader *OVERLAY_shader_extra_groundline(void);
GPUShader *OVERLAY_shader_extra_wire(bool use_object);
GPUShader *OVERLAY_shader_extra_loose_point(void);
GPUShader *OVERLAY_shader_extra_point(void);
GPUShader *OVERLAY_shader_facing(void);
GPUShader *OVERLAY_shader_grid(void);
GPUShader *OVERLAY_shader_image(void);
GPUShader *OVERLAY_shader_motion_path_line(void);
GPUShader *OVERLAY_shader_motion_path_vert(void);
GPUShader *OVERLAY_shader_uniform_color(void);
GPUShader *OVERLAY_shader_outline_prepass(bool use_wire);
GPUShader *OVERLAY_shader_outline_prepass_grid(void);
GPUShader *OVERLAY_shader_outline_resolve(void);
GPUShader *OVERLAY_shader_outline_expand(bool high_dpi);
GPUShader *OVERLAY_shader_outline_detect(bool use_wire);
GPUShader *OVERLAY_shader_paint_face(void);
GPUShader *OVERLAY_shader_paint_point(void);
GPUShader *OVERLAY_shader_paint_texture(void);
GPUShader *OVERLAY_shader_paint_vertcol(void);
GPUShader *OVERLAY_shader_paint_weight(void);
GPUShader *OVERLAY_shader_paint_wire(void);
GPUShader *OVERLAY_shader_particle_dot(void);
GPUShader *OVERLAY_shader_particle_shape(void);
GPUShader *OVERLAY_shader_sculpt_mask(void);
GPUShader *OVERLAY_shader_volume_velocity(bool use_needle);
GPUShader *OVERLAY_shader_wireframe(void);
GPUShader *OVERLAY_shader_wireframe_select(void);
OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void);
void OVERLAY_shader_free(void);
#endif /* __OVERLAY_PRIVATE_H__ */

View File

@@ -0,0 +1,65 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include "overlay_private.h"
#include "BKE_pbvh.h"
#include "BKE_paint.h"
#include "BKE_subdiv_ccg.h"
void OVERLAY_sculpt_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
DRWShadingGroup *grp;
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->sculpt_mask_ps, state | pd->clipping_state);
GPUShader *sh = OVERLAY_shader_sculpt_mask();
pd->sculpt_mask_grp = grp = DRW_shgroup_create(sh, psl->sculpt_mask_ps);
DRW_shgroup_uniform_float_copy(grp, "maskOpacity", pd->overlay.sculpt_mode_mask_opacity);
}
void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
PBVH *pbvh = ob->sculpt->pbvh;
const bool use_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
if (use_pbvh || !ob->sculpt->deform_modifiers_active || ob->sculpt->shapekey_active) {
if (pbvh_has_mask(pbvh)) {
DRW_shgroup_call_sculpt(pd->sculpt_mask_grp, ob, false, true, false);
}
}
}
void OVERLAY_sculpt_draw(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
DRW_draw_pass(psl->sculpt_mask_ps);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,231 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*/
#include "DNA_mesh_types.h"
#include "DNA_view3d_types.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BLI_hash.h"
#include "GPU_shader.h"
#include "DRW_render.h"
#include "ED_view3d.h"
#include "overlay_private.h"
void OVERLAY_wireframe_init(OVERLAY_Data *vedata)
{
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
pd->view_wires = DRW_view_create_with_zoffset(pd->view_default, draw_ctx->rv3d, 0.5f);
}
void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
{
OVERLAY_PassList *psl = vedata->psl;
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
DRWShadingGroup *grp = NULL;
View3DShading *shading = &draw_ctx->v3d->shading;
pd->shdata.wire_step_param = pd->overlay.wireframe_threshold - 254.0f / 255.0f;
bool is_wire_shmode = (shading->type == OB_WIRE);
bool is_material_shmode = (shading->type > OB_SOLID);
bool is_object_color = is_wire_shmode && (shading->wire_color_type == V3D_SHADING_OBJECT_COLOR);
bool is_random_color = is_wire_shmode && (shading->wire_color_type == V3D_SHADING_RANDOM_COLOR);
const bool use_select = (DRW_state_is_select() || DRW_state_is_depth());
GPUShader *wires_sh = use_select ? OVERLAY_shader_wireframe_select() :
OVERLAY_shader_wireframe();
for (int xray = 0; xray < 2; xray++) {
/* Only do stencil test if stencil buffer is written by the render engine. */
DRWState stencil_state = is_material_shmode ? 0 : DRW_STATE_STENCIL_EQUAL;
DRWState state = DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_WRITE_COLOR |
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRWPass *pass;
uint stencil_mask;
if (xray == 0) {
DRW_PASS_CREATE(psl->wireframe_ps, state | stencil_state | pd->clipping_state);
pass = psl->wireframe_ps;
stencil_mask = 0xFF;
}
else {
DRW_PASS_CREATE(psl->wireframe_xray_ps, state | pd->clipping_state);
pass = psl->wireframe_xray_ps;
stencil_mask = 0x00;
}
for (int use_coloring = 0; use_coloring < 2; use_coloring++) {
pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param);
DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring);
DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
DRW_shgroup_uniform_bool_copy(grp, "isObjectColor", is_object_color);
DRW_shgroup_uniform_bool_copy(grp, "isRandomColor", is_random_color);
DRW_shgroup_stencil_mask(grp, stencil_mask);
pd->wires_all_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 1.0f);
DRW_shgroup_stencil_mask(grp, stencil_mask);
}
pd->wires_sculpt_grp[xray] = grp = DRW_shgroup_create(wires_sh, pass);
DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f);
DRW_shgroup_uniform_bool_copy(grp, "useColoring", false);
DRW_shgroup_stencil_mask(grp, stencil_mask);
}
}
void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
Object *ob,
OVERLAY_DupliData *dupli,
bool init_dupli)
{
OVERLAY_Data *data = vedata;
OVERLAY_PrivateData *pd = data->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES) != 0;
const bool is_xray = (ob->dtx & OB_DRAWXRAY) != 0;
const bool is_mesh = ob->type == OB_MESH;
const bool use_wire = (pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) || (ob->dtx & OB_DRAWWIRE) ||
(ob->dt == OB_WIRE);
/* Fast path for duplis. */
if (dupli && !init_dupli) {
if (dupli->wire_shgrp && dupli->wire_geom) {
if (dupli->base_flag == ob->base_flag) {
DRW_shgroup_call(dupli->wire_shgrp, dupli->wire_geom, ob);
return;
}
}
else {
/* Nothing to draw for this dupli. */
return;
}
}
const bool is_edit_mode = BKE_object_is_in_editmode(ob);
bool has_edit_mesh_cage = false;
if (is_mesh && is_edit_mode) {
/* TODO: Should be its own function. */
Mesh *me = (Mesh *)ob->data;
BMEditMesh *embm = me->edit_mesh;
if (embm) {
has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final);
}
}
/* Don't do that in edit Mesh mode, unless there is a modifier preview. */
if (use_wire && (!is_mesh || (!is_edit_mode || has_edit_mesh_cage))) {
const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
!DRW_state_is_image_render();
const bool use_coloring = (use_wire && !is_edit_mode && !use_sculpt_pbvh &&
!has_edit_mesh_cage);
DRWShadingGroup *shgrp = NULL;
struct GPUBatch *geom = DRW_cache_object_face_wireframe_get(ob);
if (geom || use_sculpt_pbvh) {
if (use_sculpt_pbvh) {
shgrp = pd->wires_sculpt_grp[is_xray];
}
else if (all_wires) {
shgrp = pd->wires_all_grp[is_xray][use_coloring];
}
else {
shgrp = pd->wires_grp[is_xray][use_coloring];
}
if (use_sculpt_pbvh) {
DRW_shgroup_call_sculpt(shgrp, ob, true, false, false);
}
else {
DRW_shgroup_call(shgrp, geom, ob);
}
}
if (dupli) {
dupli->wire_shgrp = shgrp;
dupli->wire_geom = geom;
}
}
else if (is_mesh && (!is_edit_mode || has_edit_mesh_cage)) {
OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob);
Mesh *me = ob->data;
float *color;
DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
/* Draw loose geometry. */
if ((me->totpoly == 0 && me->totedge > 0) || has_edit_mesh_cage) {
struct GPUBatch *geom = DRW_cache_mesh_loose_edges_get(ob);
if (geom) {
OVERLAY_extra_wire(cb, geom, ob->obmat, color);
}
}
else if (me->totedge == 0 && me->totvert > 0) {
struct GPUBatch *geom = DRW_cache_mesh_all_verts_get(ob);
if (geom) {
OVERLAY_extra_loose_points(cb, geom, ob->obmat, color);
}
}
}
}
void OVERLAY_wireframe_draw(OVERLAY_Data *data)
{
OVERLAY_FramebufferList *fbl = data->fbl;
OVERLAY_PassList *psl = data->psl;
OVERLAY_PrivateData *pd = data->stl->pd;
if (pd->antialiasing.enabled) {
GPU_framebuffer_bind(fbl->overlay_line_fb);
}
DRW_view_set_active(pd->view_wires);
DRW_draw_pass(psl->wireframe_ps);
DRW_view_set_active(pd->view_default);
if (pd->antialiasing.enabled) {
GPU_framebuffer_bind(fbl->overlay_default_fb);
}
}
void OVERLAY_wireframe_in_front_draw(OVERLAY_Data *data)
{
OVERLAY_PassList *psl = data->psl;
OVERLAY_PrivateData *pd = data->stl->pd;
DRW_view_set_active(pd->view_wires);
DRW_draw_pass(psl->wireframe_xray_ps);
DRW_view_set_active(pd->view_default);
}

View File

@@ -0,0 +1,135 @@
uniform sampler2D colorTex;
uniform sampler2D depthTex;
uniform sampler2D lineTex;
in vec2 uvs;
out vec4 fragColor;
#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */
/**
* We want to know how much a pixel is covered by a line.
* We replace the square pixel with acircle of the same area and try to find the intersection area.
* The area we search is the circular segment. https://en.wikipedia.org/wiki/Circular_segment
* The formula for the area uses inverse trig function and is quite complexe. Instead,
* we approximate it by using the smoothstep function and a 1.05 factor to the disc radius.
*/
#define DISC_RADIUS (M_1_SQRTPI * 1.05)
#define LINE_SMOOTH_START (0.5 - DISC_RADIUS)
#define LINE_SMOOTH_END (0.5 + DISC_RADIUS)
/**
* Returns coverage of a line onto a sample that is distance_to_line (in pixels) far from the line.
* line_kernel_size is the inner size of the line with 100% coverage.
*/
float line_coverage(float distance_to_line, float line_kernel_size)
{
return smoothstep(LINE_SMOOTH_END, LINE_SMOOTH_START, abs(distance_to_line) - line_kernel_size);
}
vec4 line_coverage(vec4 distance_to_line, float line_kernel_size)
{
return smoothstep(LINE_SMOOTH_END, LINE_SMOOTH_START, abs(distance_to_line) - line_kernel_size);
}
vec2 decode_line_dir(vec2 dir)
{
return dir * 2.0 - 1.0;
}
float decode_line_dist(float dist)
{
return (dist - 0.1) * 4.0 - 2.0;
}
float neighbor_dist(vec3 line_dir_and_dist, vec2 ofs)
{
float dist = decode_line_dist(line_dir_and_dist.z);
vec2 dir = decode_line_dir(line_dir_and_dist.xy);
bool is_line = line_dir_and_dist.z != 0.0;
bool dir_horiz = abs(dir.x) > abs(dir.y);
bool ofs_horiz = (ofs.x != 0);
if (!is_line || (ofs_horiz != dir_horiz)) {
dist += 1e10; /* No line. */
}
else {
dist += dot(ofs, -dir);
}
return dist;
}
void neighbor_blend(
float line_coverage, float line_depth, vec4 line_color, inout float frag_depth, inout vec4 col)
{
line_color *= line_coverage;
if (line_coverage > 0.0 && line_depth < frag_depth) {
/* Alpha over. */
col = col * (1.0 - line_color.a) + line_color;
frag_depth = line_depth;
}
else {
/* Alpha under. */
col = col + line_color * (1.0 - col.a);
}
}
void main()
{
ivec2 center_texel = ivec2(gl_FragCoord.xy);
const float line_kernel = 0.0;
fragColor = texelFetch(colorTex, center_texel, 0);
float depth = texelFetch(depthTex, center_texel, 0).r;
float dist_raw = texelFetch(lineTex, center_texel, 0).b;
float dist = decode_line_dist(dist_raw);
/* TODO Opti: use textureGather */
vec4 neightbor_col0 = texelFetchOffset(colorTex, center_texel, 0, ivec2(1, 0));
vec4 neightbor_col1 = texelFetchOffset(colorTex, center_texel, 0, ivec2(-1, 0));
vec4 neightbor_col2 = texelFetchOffset(colorTex, center_texel, 0, ivec2(0, 1));
vec4 neightbor_col3 = texelFetchOffset(colorTex, center_texel, 0, ivec2(0, -1));
vec3 neightbor_line0 = texelFetchOffset(lineTex, center_texel, 0, ivec2(1, 0)).rgb;
vec3 neightbor_line1 = texelFetchOffset(lineTex, center_texel, 0, ivec2(-1, 0)).rgb;
vec3 neightbor_line2 = texelFetchOffset(lineTex, center_texel, 0, ivec2(0, 1)).rgb;
vec3 neightbor_line3 = texelFetchOffset(lineTex, center_texel, 0, ivec2(0, -1)).rgb;
vec4 depths;
depths.x = texelFetchOffset(depthTex, center_texel, 0, ivec2(1, 0)).r;
depths.y = texelFetchOffset(depthTex, center_texel, 0, ivec2(-1, 0)).r;
depths.z = texelFetchOffset(depthTex, center_texel, 0, ivec2(0, 1)).r;
depths.w = texelFetchOffset(depthTex, center_texel, 0, ivec2(0, -1)).r;
vec4 line_dists;
line_dists.x = neighbor_dist(neightbor_line0, vec2(1, 0));
line_dists.y = neighbor_dist(neightbor_line1, vec2(-1, 0));
line_dists.z = neighbor_dist(neightbor_line2, vec2(0, 1));
line_dists.w = neighbor_dist(neightbor_line3, vec2(0, -1));
vec4 coverage = line_coverage(line_dists, line_kernel);
if (dist_raw > 0.0) {
fragColor *= line_coverage(dist, line_kernel);
}
/* We dont order fragments but use alpha over/alpha under based on current minimum frag depth. */
neighbor_blend(coverage.x, depths.x, neightbor_col0, depth, fragColor);
neighbor_blend(coverage.y, depths.y, neightbor_col1, depth, fragColor);
neighbor_blend(coverage.z, depths.z, neightbor_col2, depth, fragColor);
neighbor_blend(coverage.w, depths.w, neightbor_col3, depth, fragColor);
#if 1
/* Fix aliasing issue with really dense meshes and 1 pixel sized lines. */
if (dist_raw > 0.0 && line_kernel < 0.45) {
vec4 lines = vec4(neightbor_line0.z, neightbor_line1.z, neightbor_line2.z, neightbor_line3.z);
/* Count number of line neighbors. */
float blend = dot(vec4(0.25), step(0.001, lines));
fragColor = mix(fragColor, fragColor / fragColor.a, blend);
}
#endif
}

View File

@@ -0,0 +1,11 @@
out vec2 uvs;
void main()
{
int v = gl_VertexID % 3;
float x = float((v & 1) << 2);
float y = float((v & 2) << 1);
gl_Position = vec4(x - 1.0, y - 1.0, 1.0, 1.0);
uvs = vec2(x, y) * 0.5;
}

View File

@@ -1,15 +1,11 @@
uniform mat4 ViewProjectionMatrix;
/* ---- Instantiated Attrs ---- */
in vec2 pos;
/* ---- Per instance Attrs ---- */
/* Assumed to be in world coordinate already. */
in mat4 InstanceModelMatrix;
in vec4 color;
in vec2 amin;
in vec2 amax;
in mat4 inst_obmat;
flat out vec4 finalColor;
@@ -23,8 +19,15 @@ vec3 sphere_project(float ax, float az)
void main()
{
mat4 model_mat = inst_obmat;
model_mat[0][3] = model_mat[1][3] = model_mat[2][3] = 0.0;
model_mat[3][3] = 1.0;
vec2 amin = vec2(inst_obmat[0][3], inst_obmat[1][3]);
vec2 amax = vec2(inst_obmat[2][3], inst_obmat[3][3]);
vec3 final_pos = sphere_project(pos.x * abs((pos.x > 0.0) ? amax.x : amin.x),
pos.y * abs((pos.y > 0.0) ? amax.y : amin.y));
gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(final_pos, 1.0));
gl_Position = ViewProjectionMatrix * (model_mat * vec4(final_pos, 1.0));
finalColor = color;
}

View File

@@ -1,12 +1,4 @@
uniform mat4 ViewMatrix;
uniform mat4 ViewMatrixInverse;
uniform mat4 ViewProjectionMatrix;
uniform mat4 ProjectionMatrix;
uniform vec2 viewportSize;
uniform float lineThickness = 2.0;
/* ---- Instantiated Attrs ---- */
in vec2 pos0;
in vec2 pos1;
@@ -24,7 +16,7 @@ flat out vec4 finalColor;
/* project to screen space */
vec2 proj(vec4 pos)
{
return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
return (0.5 * (pos.xy / pos.w) + 0.5) * sizeViewport.xy;
}
vec2 compute_dir(vec2 v0, vec2 v1, vec2 v2)
@@ -159,8 +151,9 @@ void main()
vec2 ss2 = proj(p2);
vec2 edge_dir = compute_dir(ss0, ss1, ss2);
float line_thickness = 2.0 * sizePixel;
bool outer = ((gl_VertexID & 1) == 1);
vec2 t = outlineColorSize.w * (lineThickness / viewportSize);
vec2 t = outlineColorSize.w * line_thickness * sizeViewportInv.xy;
t *= pres_fac;
t = (outer) ? t : vec2(0.0);

View File

@@ -0,0 +1,25 @@
uniform float alpha = 0.6;
uniform bool isDistance;
flat in vec3 finalStateColor;
flat in vec3 finalBoneColor;
in vec3 normalView;
out vec4 fragColor;
void main()
{
float n = normalize(normalView).z;
if (isDistance) {
n = 1.0 - clamp(-n, 0.0, 1.0);
fragColor = vec4(1.0, 1.0, 1.0, 0.2) * n;
}
else {
/* Smooth lighting factor. */
const float s = 0.2; /* [0.0-0.5] range */
float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0);
fragColor.rgb = mix(finalStateColor, finalBoneColor, fac);
fragColor.a = alpha;
}
}

View File

@@ -1,8 +1,4 @@
uniform mat4 ViewMatrix;
uniform mat4 ViewMatrixInverse;
uniform mat4 ViewProjectionMatrix;
/* ---- Instantiated Attrs ---- */
in vec3 pos;

View File

@@ -9,8 +9,6 @@ in vec2 ssNor[];
in vec4 vColSize[];
flat out vec4 finalColor;
uniform vec2 viewportSize;
uniform float lineThickness = 2.0;
vec2 compute_dir(vec2 v0, vec2 v1)
{
@@ -93,7 +91,8 @@ void main(void)
return;
}
vec2 thick = vColSize[0].w * (lineThickness / viewportSize);
float line_thickness = 2.0 * sizePixel;
vec2 thick = vColSize[0].w * (line_thickness * sizeViewportInv.xy);
vec2 edge_dir = compute_dir(ssPos[1], ssPos[2]);
vec2 hidden_point;

View File

@@ -1,13 +1,11 @@
uniform vec2 viewportSize;
/* ---- Instantiated Attrs ---- */
in vec3 pos;
in vec3 snor;
/* ---- Per instance Attrs ---- */
in mat4 InstanceModelMatrix;
in vec4 outlineColorSize;
in vec4 color;
in mat4 inst_obmat;
out vec4 pPos;
out vec3 vPos;
@@ -18,12 +16,15 @@ out vec4 vColSize;
/* project to screen space */
vec2 proj(vec4 pos)
{
return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
return (0.5 * (pos.xy / pos.w) + 0.5) * sizeViewport.xy;
}
void main()
{
vec4 worldPosition = InstanceModelMatrix * vec4(pos, 1.0);
vec4 bone_color, state_color;
mat4 model_mat = extract_matrix_packed_data(inst_obmat, state_color, bone_color);
vec4 worldPosition = model_mat * vec4(pos, 1.0);
vec4 viewpos = ViewMatrix * worldPosition;
vPos = viewpos.xyz;
@@ -31,7 +32,7 @@ void main()
/* This is slow and run per vertex, but it's still faster than
* doing it per instance on CPU and sending it on via instance attribute. */
mat3 normal_mat = transpose(inverse(mat3(InstanceModelMatrix)));
mat3 normal_mat = transpose(inverse(mat3(model_mat)));
/* TODO FIX: there is still a problem with this vector
* when the bone is scaled or in persp mode. But it's
* barelly visible at the outline corners. */
@@ -39,7 +40,7 @@ void main()
ssPos = proj(pPos);
vColSize = outlineColorSize;
vColSize = bone_color;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(worldPosition.xyz);

View File

@@ -4,17 +4,18 @@ in vec3 pos;
in vec3 nor;
/* ---- Per instance Attrs ---- */
in mat4 InstanceModelMatrix;
in vec3 boneColor;
in vec3 stateColor;
in mat4 inst_obmat;
out vec4 finalColor;
void main()
{
vec4 bone_color, state_color;
mat4 model_mat = extract_matrix_packed_data(inst_obmat, state_color, bone_color);
/* 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 attribute. */
mat3 normal_mat = transpose(inverse(mat3(InstanceModelMatrix)));
mat3 normal_mat = transpose(inverse(mat3(model_mat)));
vec3 normal = normalize(normal_world_to_view(normal_mat * nor));
/* Do lighting at an angle to avoid flat shading on front facing bone. */
@@ -24,10 +25,10 @@ void main()
/* Smooth lighting factor. */
const float s = 0.2; /* [0.0-0.5] range */
float fac = clamp((n * (1.0 - s)) + s, 0.0, 1.0);
finalColor.rgb = mix(stateColor, boneColor, fac);
finalColor.rgb = mix(state_color.rgb, bone_color.rgb, fac);
finalColor.a = 1.0;
vec4 worldPosition = InstanceModelMatrix * vec4(pos, 1.0);
vec4 worldPosition = model_mat * vec4(pos, 1.0);
gl_Position = ViewProjectionMatrix * worldPosition;
#ifdef USE_WORLD_CLIP_PLANES

View File

@@ -1,23 +1,17 @@
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
uniform vec2 viewportSize;
uniform float lineThickness = 2.0;
/* ---- Instantiated Attrs ---- */
in vec2 pos0;
in vec2 pos1;
/* ---- Per instance Attrs ---- */
in mat4 InstanceModelMatrix;
in vec4 outlineColorSize;
in mat4 inst_obmat;
flat out vec4 finalColor;
/* project to screen space */
vec2 proj(vec4 pos)
{
return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
return (0.5 * (pos.xy / pos.w) + 0.5) * sizeViewport.xy;
}
vec2 compute_dir(vec2 v0, vec2 v1, vec2 c)
@@ -34,7 +28,10 @@ vec2 compute_dir(vec2 v0, vec2 v1, vec2 c)
void main()
{
mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix;
vec4 bone_color, state_color;
mat4 model_mat = extract_matrix_packed_data(inst_obmat, state_color, bone_color);
mat4 model_view_matrix = ViewMatrix * model_mat;
mat4 sphereMatrix = inverse(model_view_matrix);
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
@@ -91,17 +88,17 @@ void main()
bool outer = ((gl_VertexID & 1) == 1);
vec2 t = outlineColorSize.w * (lineThickness / viewportSize);
vec2 t = bone_color.w * (2.0 * sizeViewportInv.xy);
t *= (is_persp) ? abs(V.z) : 1.0;
t = (outer) ? t : vec2(0.0);
gl_Position = p0;
gl_Position.xy += t * edge_dir;
finalColor = vec4(outlineColorSize.rgb, 1.0);
finalColor = vec4(bone_color.rgb, 1.0);
#ifdef USE_WORLD_CLIP_PLANES
vec4 worldPosition = InstanceModelMatrix * vec4(cam_pos0, 1.0);
vec4 worldPosition = model_mat * vec4(cam_pos0, 1.0);
world_clip_planes_calc_clip_distance(worldPosition.xyz);
#endif
}

View File

@@ -1,8 +1,4 @@
#extension GL_ARB_conservative_depth : enable
uniform mat4 ViewMatrixInverse;
uniform mat4 ProjectionMatrix;
uniform float alpha = 0.4;
flat in vec3 finalStateColor;

View File

@@ -1,14 +1,10 @@
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
/* ---- Instantiated Attrs ---- */
in vec2 pos;
/* ---- Per instance Attrs ---- */
in mat4 InstanceModelMatrix;
in vec3 stateColor;
in vec3 boneColor;
in vec4 color;
in mat4 inst_obmat;
flat out vec3 finalStateColor;
flat out vec3 finalBoneColor;
@@ -20,7 +16,10 @@ const float rad = 0.05;
void main()
{
mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix;
vec4 bone_color, state_color;
mat4 model_mat = extract_matrix_packed_data(inst_obmat, state_color, bone_color);
mat4 model_view_matrix = ViewMatrix * model_mat;
sphereMatrix = inverse(model_view_matrix);
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
@@ -78,11 +77,11 @@ void main()
gl_Position = ProjectionMatrix * V;
viewPosition = V.xyz;
finalStateColor = stateColor;
finalBoneColor = boneColor;
finalStateColor = state_color.xyz;
finalBoneColor = bone_color.xyz;
#ifdef USE_WORLD_CLIP_PLANES
vec4 worldPosition = InstanceModelMatrix * pos_4d;
vec4 worldPosition = model_mat * pos_4d;
world_clip_planes_calc_clip_distance(worldPosition.xyz);
#endif
}

View File

@@ -1,10 +1,4 @@
uniform mat4 ProjectionMatrix;
uniform mat4 ViewProjectionMatrix;
uniform mat4 ViewMatrix;
uniform vec2 viewportSize;
/* ---- Instantiated Attrs ---- */
in vec2 pos; /* bone aligned screen space */
in uint flag;
@@ -34,12 +28,10 @@ noperspective out float colorFac;
flat out vec4 finalWireColor;
flat out vec4 finalInnerColor;
uniform float stickSize = 5.0; /* might be dependent on DPI setting in the future. */
/* project to screen space */
vec2 proj(vec4 pos)
{
return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
return (0.5 * (pos.xy / pos.w) + 0.5) * sizeViewport.xy;
}
void main()
@@ -83,8 +75,9 @@ void main()
vpos *= (do_wire) ? 1.0 : 0.5;
if (finalInnerColor.a > 0.0) {
float stick_size = sizePixel * 5.0;
gl_Position = (is_head) ? p0 : p1;
gl_Position.xy += stickSize * (vpos / viewportSize);
gl_Position.xy += stick_size * (vpos * sizeViewportInv.xy);
gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */
#ifdef USE_WORLD_CLIP_PLANES

View File

@@ -0,0 +1,18 @@
in vec3 color;
in vec3 pos;
flat out vec4 finalColor;
void main()
{
finalColor.rgb = color;
finalColor.a = 1.0;
vec3 worldPosition = point_object_to_world(pos);
gl_Position = point_world_to_ndc(worldPosition);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(worldPosition);
#endif
}

View File

@@ -3,6 +3,8 @@ in vec3 pos;
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);

View File

@@ -6,7 +6,6 @@
layout(lines) in;
layout(triangle_strip, max_vertices = 10) out;
uniform vec2 viewportSize;
uniform bool showCurveHandles;
flat in int vertFlag[];
@@ -82,9 +81,9 @@ void main()
vec4(inner_color.rgb, 0.0);
vec2 v1_2 = (v2.xy / v2.w - v1.xy / v1.w);
vec2 offset = sizeEdge * 4.0 / viewportSize; /* 4.0 is eyeballed */
vec2 offset = sizeEdge * 4.0 * sizeViewportInv.xy; /* 4.0 is eyeballed */
if (abs(v1_2.x * viewportSize.x) < abs(v1_2.y * viewportSize.y)) {
if (abs(v1_2.x * sizeViewport.x) < abs(v1_2.y * sizeViewport.y)) {
offset.y = 0.0;
}
else {

View File

@@ -1,6 +1,3 @@
/* Draw Curve Vertices */
uniform vec2 viewportSize;
in vec3 pos;
in int data;

View File

@@ -1,4 +1,3 @@
/* Draw Curve Normals */
uniform float normalSize;
@@ -7,6 +6,8 @@ in vec3 nor;
in vec3 tan;
in float rad;
flat out vec4 finalColor;
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
@@ -22,6 +23,8 @@ void main()
vec3 world_pos = point_object_to_world(final_pos);
gl_Position = point_world_to_ndc(world_pos);
finalColor = colorWireEdit;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif

View File

@@ -0,0 +1,32 @@
in vec3 pos;
in int data;
out vec4 finalColor;
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
if ((data & VERT_SELECTED) != 0) {
finalColor = colorVertexSelect;
}
else if ((data & VERT_ACTIVE) != 0) {
finalColor = colorEditMeshActive;
}
else {
finalColor = colorVertex;
}
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
/* Small offset in Z */
gl_Position.z -= 3e-4;
gl_PointSize = sizeVertex * 2.0;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -0,0 +1,38 @@
uniform sampler1D weightTex;
in vec3 pos;
in float weight;
out vec4 finalColor;
#define no_active_weight 666.0
vec3 weight_to_rgb(float t)
{
if (t == no_active_weight) {
/* No weight. */
return colorWire.rgb;
}
if (t > 1.0 || t < 0.0) {
/* Error color */
return vec3(1.0, 0.0, 1.0);
}
else {
return texture(weightTex, t).rgb;
}
}
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
finalColor = vec4(weight_to_rgb(weight), 1.0);
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -12,12 +12,20 @@
#define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS)
#define GRID_LINE_SMOOTH_END (0.5 + DISC_RADIUS)
uniform sampler2D depthTex;
uniform float alpha = 1.0;
flat in vec4 finalColorOuter_f;
in vec4 finalColor_f;
noperspective in float edgeCoord_f;
out vec4 FragColor;
bool test_occlusion()
{
return gl_FragCoord.z > texelFetch(depthTex, ivec2(gl_FragCoord.xy), 0).r;
}
void main()
{
float dist = abs(edgeCoord_f) - max(sizeEdge - 0.5, 0.0);
@@ -33,4 +41,6 @@ void main()
FragColor = mix(finalColorOuter_f, finalColor_f, 1.0 - mix_w * finalColorOuter_f.a);
/* Line edges shape. */
FragColor.a *= 1.0 - (finalColorOuter_f.a > 0.0 ? mix_w_outer : mix_w);
FragColor.a *= test_occlusion() ? alpha : 1.0;
}

View File

@@ -2,9 +2,6 @@
layout(lines) in;
layout(triangle_strip, max_vertices = 4) out;
uniform vec2 viewportSize;
uniform vec2 viewportSizeInv;
in vec4 finalColor[2];
in vec4 finalColorOuter[2];
in int selectOveride[2];
@@ -55,7 +52,7 @@ void main()
ss_pos[1] = pos1.xy / pos1.w;
vec2 line = ss_pos[0] - ss_pos[1];
line = abs(line) * viewportSize;
line = abs(line) * sizeViewport.xy;
finalColorOuter_f = finalColorOuter[0];
float half_size = sizeEdge;
@@ -67,7 +64,7 @@ void main()
half_size += 0.5;
#endif
vec3 edge_ofs = half_size * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0);
vec3 edge_ofs = vec3(half_size * sizeViewportInv.xy, 0.0);
bool horizontal = line.x > line.y;
edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz;

View File

@@ -0,0 +1,53 @@
uniform float normalSize;
uniform sampler2D depthTex;
uniform float alpha = 1.0;
in vec3 pos;
in vec3 lnor;
in vec3 vnor;
in vec4 norAndFlag;
flat out vec4 finalColor;
bool test_occlusion()
{
vec3 ndc = (gl_Position.xyz / gl_Position.w) * 0.5 + 0.5;
return (ndc.z - 0.00035) > texture(depthTex, ndc.xy).r;
}
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
vec3 nor;
/* Select the right normal by cheking if the generic attrib is used. */
if (!all(equal(lnor, vec3(0)))) {
nor = lnor;
finalColor = colorLNormal;
}
else if (!all(equal(vnor, vec3(0)))) {
nor = vnor;
finalColor = colorVNormal;
}
else {
nor = norAndFlag.xyz;
finalColor = colorNormal;
}
vec3 n = normalize(normal_object_to_world(nor));
vec3 world_pos = point_object_to_world(pos);
if (gl_VertexID == 0) {
world_pos += n * normalSize;
}
gl_Position = point_world_to_ndc(world_pos);
finalColor.a *= (test_occlusion()) ? alpha : 1.0;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -0,0 +1,25 @@
/* ---- Instantiated Attrs ---- */
in vec3 pos;
/* ---- Per instance Attrs ---- */
in float size;
in vec3 local_pos;
flat out vec4 finalColor;
void main()
{
mat3 imat = mat3(ModelMatrixInverse);
vec3 right = normalize(imat * screenVecs[0].xyz);
vec3 up = normalize(imat * screenVecs[1].xyz);
vec3 screen_pos = (right * pos.x + up * pos.z) * size;
vec4 pos_4d = ModelMatrix * vec4(local_pos + screen_pos, 1.0);
gl_Position = ViewProjectionMatrix * pos_4d;
/* Manual stipple: one segment out of 2 is transparent. */
finalColor = ((gl_VertexID & 1) == 0) ? colorSkinRoot : vec4(0.0);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(pos_4d.xyz);
#endif
}

View File

@@ -1,5 +1,6 @@
uniform float faceAlphaMod;
uniform sampler2D depthTex;
uniform float alpha = 1.0;
uniform ivec4 dataMask = ivec4(0xFF);
in ivec4 data;
@@ -12,11 +13,19 @@ in vec4 norAndFlag;
#endif
out vec4 finalColor;
#ifdef EDGE
out vec4 finalColorOuter;
#endif
#ifdef USE_GEOM_SHADER
out int selectOveride;
#endif
bool test_occlusion()
{
vec3 ndc = (gl_Position.xyz / gl_Position.w) * 0.5 + 0.5;
return ndc.z > texture(depthTex, ndc.xy).r;
}
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
@@ -37,6 +46,8 @@ void main()
gl_Position.z -= 1e-7;
}
bool occluded = test_occlusion();
#elif defined(EDGE)
# ifdef FLAT
finalColor = EDIT_MESH_edge_color_inner(m_data.y);
@@ -50,18 +61,25 @@ void main()
float bweight = float(m_data.w) / 255.0;
finalColorOuter = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, crease, bweight);
bool occluded = false; /* Done in fragment shader */
#elif defined(FACE)
finalColor = EDIT_MESH_face_color(m_data.x);
finalColor.a *= faceAlphaMod;
bool occluded = true;
#elif defined(FACEDOT)
finalColor = EDIT_MESH_facedot_color(norAndFlag.w);
/* Bias Facedot Z position in clipspace. */
gl_Position.z -= 0.00035;
gl_PointSize = sizeFaceDot;
bool occluded = test_occlusion();
#endif
finalColor.a *= (occluded) ? alpha : 1.0;
#if !defined(FACE)
/* Facing based color blend */
vec3 vpos = point_world_to_view(world_pos);

View File

@@ -1,10 +1,18 @@
in vec3 pos;
in float color;
out vec4 finalColor;
void main()
{
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
finalColor = mix(colorWire, colorEdgeSelect, color);
gl_PointSize = sizeVertex * 2.0;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif

View File

@@ -0,0 +1,42 @@
uniform sampler1D weightTex;
uniform bool useWeight;
in vec3 pos;
in float color;
out vec4 finalColor;
#define no_active_weight 666.0
vec3 weight_to_rgb(float t)
{
if (t == no_active_weight) {
/* No weight. */
return colorWire.rgb;
}
if (t > 1.0 || t < 0.0) {
/* Error color */
return vec3(1.0, 0.0, 1.0);
}
else {
return texture(weightTex, t).rgb;
}
}
void main()
{
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
if (useWeight) {
finalColor = vec4(weight_to_rgb(color), 1.0);
}
else {
finalColor = mix(colorWire, colorEdgeSelect, color);
}
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -0,0 +1,13 @@
noperspective in vec2 edgePos;
flat in vec2 edgeStart;
flat in vec4 finalColor;
layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec4 lineOutput;
void main()
{
fragColor = finalColor;
lineOutput = pack_line_data(gl_FragCoord.xy, edgeStart, edgePos);
}

View File

@@ -0,0 +1,30 @@
in vec3 pos;
/* Instance */
in vec3 inst_pos;
flat out vec4 finalColor;
flat out vec2 edgeStart;
noperspective out vec2 edgePos;
void main()
{
finalColor = colorLight;
/* Relative to DPI scalling. Have constant screen size. */
vec3 screen_pos = screenVecs[0].xyz * pos.x + screenVecs[1].xyz * pos.y;
vec3 p = inst_pos;
p.z *= (pos.z == 0.0) ? 0.0 : 1.0;
float screen_size = mul_project_m4_v3_zfac(p) * sizePixel;
vec3 world_pos = p + screen_pos * screen_size;
gl_Position = point_world_to_ndc(world_pos);
/* Convert to screen position [0..sizeVp]. */
edgePos = edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -1,6 +1,5 @@
uniform vec4 color;
uniform vec4 innerColor;
in vec4 finalColor;
out vec4 fragColor;
@@ -10,10 +9,10 @@ void main()
float dist = max(centered.x, centered.y);
float fac = dist * dist * 4.0;
fragColor = mix(innerColor, color, 0.45 + fac * 0.65);
fragColor = mix(colorEditMeshMiddle, finalColor, 0.45 + fac * 0.65);
/* Make the effect more like a fresnel by offsetting
* the depth and creating mini-spheres.
* Disabled as it has performance impact. */
// gl_FragDepth = gl_FragCoord.z + 1e-6 * fac;
}
}

View File

@@ -0,0 +1,20 @@
in vec3 pos;
out vec4 finalColor;
void main()
{
/* Extract data packed inside the unused mat4 members. */
mat4 obmat = ModelMatrix;
finalColor = vec4(obmat[0][3], obmat[1][3], obmat[2][3], obmat[3][3]);
vec3 world_pos = (ModelMatrix * vec4(pos, 1.0)).xyz;
gl_Position = point_world_to_ndc(world_pos);
gl_PointSize = sizeVertex * 2.0;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -0,0 +1,30 @@
uniform vec4 color;
in vec3 pos;
out vec4 radii;
out vec4 fillColor;
out vec4 outlineColor;
void main()
{
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
gl_PointSize = sizeObjectCenter;
float radius = 0.5 * sizeObjectCenter;
float outline_width = sizePixel;
radii[0] = radius;
radii[1] = radius - 1.0;
radii[2] = radius - outline_width;
radii[3] = radius - outline_width - 1.0;
radii /= sizeObjectCenter;
fillColor = color;
outlineColor = colorOutline;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -0,0 +1,227 @@
in vec3 pos;
in int vclass;
/* Instance */
in mat4 inst_obmat;
in vec4 color;
#define lamp_area_size inst_data.xy
#define lamp_clip_sta inst_data.z
#define lamp_clip_end inst_data.w
#define lamp_spot_cosine inst_data.x
#define lamp_spot_blend inst_data.y
#define camera_corner inst_data.xy
#define camera_center inst_data.zw
#define camera_dist inst_color_data
#define camera_dist_sta inst_data.z
#define camera_dist_end inst_data.w
#define camera_distance_color inst_data.x
#define empty_size inst_data.xyz
#define empty_scale inst_data.w
#define VCLASS_LIGHT_AREA_SHAPE (1 << 0)
#define VCLASS_LIGHT_SPOT_SHAPE (1 << 1)
#define VCLASS_LIGHT_SPOT_BLEND (1 << 2)
#define VCLASS_LIGHT_SPOT_CONE (1 << 3)
#define VCLASS_LIGHT_DIST (1 << 4)
#define VCLASS_CAMERA_FRAME (1 << 5)
#define VCLASS_CAMERA_DIST (1 << 6)
#define VCLASS_CAMERA_VOLUME (1 << 7)
#define VCLASS_SCREENSPACE (1 << 8)
#define VCLASS_SCREENALIGNED (1 << 9)
#define VCLASS_EMPTY_SCALED (1 << 10)
#define VCLASS_EMPTY_AXES (1 << 11)
#define VCLASS_EMPTY_AXES_NAME (1 << 12)
#define VCLASS_EMPTY_AXES_SHADOW (1 << 13)
#define VCLASS_EMPTY_SIZE (1 << 14)
flat out vec4 finalColor;
flat out vec2 edgeStart;
noperspective out vec2 edgePos;
void main()
{
/* Extract data packed inside the unused mat4 members. */
vec4 inst_data = vec4(inst_obmat[0][3], inst_obmat[1][3], inst_obmat[2][3], inst_obmat[3][3]);
float inst_color_data = color.a;
mat4 obmat = inst_obmat;
obmat[0][3] = obmat[1][3] = obmat[2][3] = 0.0;
obmat[3][3] = 1.0;
finalColor = color;
if (color.a < 0.0) {
finalColor.a = 1.0;
}
float lamp_spot_sine;
vec3 vpos = pos;
vec3 vofs = vec3(0.0);
/* Lights */
if ((vclass & VCLASS_LIGHT_AREA_SHAPE) != 0) {
/* HACK: use alpha color for spots to pass the area_size. */
if (inst_color_data < 0.0) {
lamp_area_size.xy = vec2(-inst_color_data);
}
vpos.xy *= lamp_area_size.xy;
}
else if ((vclass & VCLASS_LIGHT_SPOT_SHAPE) != 0) {
lamp_spot_sine = sqrt(1.0 - lamp_spot_cosine * lamp_spot_cosine);
lamp_spot_sine *= ((vclass & VCLASS_LIGHT_SPOT_BLEND) != 0) ? lamp_spot_blend : 1.0;
vpos = vec3(pos.xy * lamp_spot_sine, -lamp_spot_cosine);
}
else if ((vclass & VCLASS_LIGHT_DIST) != 0) {
/* Meh nasty mess. Select one of the 6 axes to display on. (see light_distance_z_get()) */
int dist_axis = int(pos.z);
float dist = pos.z - floor(pos.z) - 0.5;
float inv = sign(dist);
dist = (abs(dist) > 0.15) ? lamp_clip_end : lamp_clip_sta;
vofs[dist_axis] = inv * dist / length(obmat[dist_axis].xyz);
vpos.z = 0.0;
if (lamp_clip_end < 0.0) {
vpos = vofs = vec3(0.0);
}
}
/* Camera */
else if ((vclass & VCLASS_CAMERA_FRAME) != 0) {
if ((vclass & VCLASS_CAMERA_VOLUME) != 0) {
vpos.z = mix(color.b, color.a, pos.z);
}
else if (camera_dist > 0.0) {
vpos.z = -abs(camera_dist);
}
else {
vpos.z *= -abs(camera_dist);
}
vpos.xy = (camera_center + camera_corner * vpos.xy) * abs(vpos.z);
}
else if ((vclass & VCLASS_CAMERA_DIST) != 0) {
vofs.xy = vec2(0.0);
vofs.z = -mix(camera_dist_sta, camera_dist_end, pos.z);
vpos.z = 0.0;
/* Distance line endpoints color */
if (any(notEqual(pos.xy, vec2(0.0)))) {
/* Override color. */
switch (int(camera_distance_color)) {
case 0: /* Mist */
finalColor = vec4(0.5, 0.5, 0.5, 1.0);
break;
case 1: /* Mist Active */
finalColor = vec4(1.0, 1.0, 1.0, 1.0);
break;
case 2: /* Clip */
finalColor = vec4(0.5, 0.5, 0.25, 1.0);
break;
case 3: /* Clip Active */
finalColor = vec4(1.0, 1.0, 0.5, 1.0);
break;
}
}
/* Focus cross */
if (pos.z == 2.0) {
vofs.z = 0.0;
if (camera_dist < 0.0) {
vpos.z = -abs(camera_dist);
}
else {
/* Disabled */
vpos = vec3(0.0);
}
}
}
/* Empties */
else if ((vclass & VCLASS_EMPTY_SCALED) != 0) {
/* This is a bit silly but we avoid scalling the object matrix on CPU (saving a mat4 mul) */
vpos *= empty_scale;
}
else if ((vclass & VCLASS_EMPTY_SIZE) != 0) {
/* This is a bit silly but we avoid scalling the object matrix on CPU (saving a mat4 mul) */
vpos *= empty_size;
}
else if ((vclass & VCLASS_EMPTY_AXES) != 0) {
float axis = vpos.z;
vofs[int(axis)] = (1.0 + fract(axis)) * empty_scale;
/* Scale uniformly by axis length */
vpos *= length(obmat[int(axis)].xyz) * empty_scale;
vec3 axis_color = vec3(0.0);
axis_color[int(axis)] = 1.0;
finalColor.rgb = mix(axis_color + fract(axis), color.rgb, color.a);
finalColor.a = 1.0;
}
/* Not exclusive with previous flags. */
if ((vclass & VCLASS_CAMERA_VOLUME) != 0) {
/* Unpack final color. */
int color_class = int(floor(color.r));
float color_intensity = fract(color.r);
switch (color_class) {
case 0: /* No eye (convergence plane) */
finalColor = vec4(1.0, 1.0, 1.0, 1.0);
break;
case 1: /* Left eye */
finalColor = vec4(0.0, 1.0, 1.0, 1.0);
break;
case 2: /* Right eye */
finalColor = vec4(1.0, 0.0, 0.0, 1.0);
break;
}
finalColor *= vec4(vec3(color_intensity), color.g);
}
vec3 world_pos;
if ((vclass & VCLASS_SCREENSPACE) != 0) {
/* Relative to DPI scalling. Have constant screen size. */
vec3 screen_pos = screenVecs[0].xyz * vpos.x + screenVecs[1].xyz * vpos.y;
vec3 p = (obmat * vec4(vofs, 1.0)).xyz;
float screen_size = mul_project_m4_v3_zfac(p) * sizePixel;
world_pos = p + screen_pos * screen_size;
}
else if ((vclass & VCLASS_SCREENALIGNED) != 0) {
/* World sized, camera facing geometry. */
vec3 screen_pos = screenVecs[0].xyz * vpos.x + screenVecs[1].xyz * vpos.y;
world_pos = (obmat * vec4(vofs, 1.0)).xyz + screen_pos;
}
else {
world_pos = (obmat * vec4(vofs + vpos, 1.0)).xyz;
}
if ((vclass & VCLASS_LIGHT_SPOT_CONE) != 0) {
/* Compute point on the cone before and after this one. */
vec2 perp = vec2(pos.y, -pos.x);
const float incr_angle = 2.0 * 3.1415 / 32.0;
const vec2 slope = vec2(cos(incr_angle), sin(incr_angle));
vec3 p0 = vec3((pos.xy * slope.x + perp * slope.y) * lamp_spot_sine, -lamp_spot_cosine);
vec3 p1 = vec3((pos.xy * slope.x - perp * slope.y) * lamp_spot_sine, -lamp_spot_cosine);
p0 = (obmat * vec4(p0, 1.0)).xyz;
p1 = (obmat * vec4(p1, 1.0)).xyz;
/* Compute normals of each side. */
vec3 edge = obmat[3].xyz - world_pos;
vec3 n0 = normalize(cross(edge, p0 - world_pos));
vec3 n1 = normalize(cross(edge, world_pos - p1));
bool persp = (ProjectionMatrix[3][3] == 0.0);
vec3 V = (persp) ? normalize(ViewMatrixInverse[3].xyz - world_pos) : ViewMatrixInverse[2].xyz;
/* Discard non-silhouete edges. */
bool facing0 = dot(n0, V) > 0.0;
bool facing1 = dot(n1, V) > 0.0;
if (facing0 == facing1) {
/* Hide line by making it cover 0 pixels. */
world_pos = obmat[3].xyz;
}
}
gl_Position = point_world_to_ndc(world_pos);
/* Convert to screen position [0..sizeVp]. */
edgePos = edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -0,0 +1,31 @@
noperspective in vec2 stipple_coord;
flat in vec2 stipple_start;
flat in vec4 finalColor;
layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec4 lineOutput;
void main()
{
fragColor = finalColor;
/* Stipple */
const float dash_width = 6.0;
const float dash_factor = 0.5;
lineOutput = pack_line_data(gl_FragCoord.xy, stipple_start, stipple_coord);
float dist = distance(stipple_start, stipple_coord);
if (fragColor.a == 0.0) {
/* Disable stippling. */
dist = 0.0;
}
fragColor.a = 1.0;
if (fract(dist / dash_width) > dash_factor) {
discard;
}
}

View File

@@ -0,0 +1,40 @@
in vec3 pos;
in vec4 color;
in int colorid; /* if equal 0 (i.e: Not specified) use color attrib and stippling. */
noperspective out vec2 stipple_coord;
flat out vec2 stipple_start;
flat out vec4 finalColor;
vec2 screen_position(vec4 p)
{
return ((p.xy / p.w) * 0.5 + 0.5) * sizeViewport.xy;
}
void main()
{
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
stipple_coord = stipple_start = screen_position(gl_Position);
#ifdef OBJECT_WIRE
/* Extract data packed inside the unused mat4 members. */
finalColor = vec4(ModelMatrix[0][3], ModelMatrix[1][3], ModelMatrix[2][3], ModelMatrix[3][3]);
#else
if (colorid == TH_CAMERA_PATH) {
finalColor = colorCameraPath;
finalColor.a = 0.0; /* No Stipple */
}
else {
finalColor = color;
finalColor.a = 1.0; /* Stipple */
}
#endif
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -9,7 +9,6 @@ in vec3 local_pos;
out vec4 FragColor;
uniform vec3 planeAxes;
uniform vec3 screenVecs[2];
uniform float gridDistance;
uniform float meshSize;
uniform float lineKernel = 0.0;
@@ -120,7 +119,7 @@ void main()
if ((gridFlag & GRID) != 0) {
/* Using `max(dot(dFdxPos, screenVecs[0]), dot(dFdyPos, screenVecs[1]))`
* would be more accurate, but not really necessary. */
float grid_res = dot(dFdxPos, screenVecs[0]);
float grid_res = dot(dFdxPos, screenVecs[0].xyz);
/* The gride begins to appear when it comprises 4 pixels */
grid_res *= 4;

View File

@@ -0,0 +1,34 @@
uniform sampler2D imgTexture;
uniform bool imgPremultiplied;
uniform bool imgAlphaBlend;
uniform bool imgLinear;
uniform vec4 color;
in vec2 uvs;
out vec4 fragColor;
void main()
{
vec2 uvs_clamped = clamp(uvs, 0.0, 1.0);
vec4 tex_color;
if (imgLinear) {
tex_color = texture_read_as_linearrgb(imgTexture, imgPremultiplied, uvs_clamped);
}
else {
tex_color = texture_read_as_srgb(imgTexture, imgPremultiplied, uvs_clamped);
}
fragColor = tex_color * color;
if (!imgAlphaBlend) {
/* Arbitrary discard anything below 5% opacity.
* Note that this could be exposed to the User. */
if (tex_color.a < 0.05) {
discard;
}
else {
fragColor.a = 1.0;
}
}
}

View File

@@ -0,0 +1,21 @@
uniform bool depthSet;
in vec3 pos;
out vec2 uvs;
void main()
{
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
if (depthSet) {
/* Result in a position at 1.0 (far plane). Small epsilon to avoid precision issue.
* This mimics the effect of infinite projection matrix
* (see http://www.terathon.com/gdc07_lengyel.pdf). */
gl_Position.z = gl_Position.w - 2.4e-7;
}
uvs = pos.xy * 0.5 + 0.5;
}

View File

@@ -2,8 +2,6 @@
layout(lines) in;
layout(triangle_strip, max_vertices = 4) out;
uniform mat4 ProjectionMatrix;
uniform vec2 viewportSize;
uniform int lineThickness = 2;
in vec4 finalColor_geom[];
@@ -21,19 +19,26 @@ vec2 compute_dir(vec2 v0, vec2 v1)
void main(void)
{
vec2 t;
vec2 edge_dir = compute_dir(ssPos[0], ssPos[1]) / viewportSize;
vec2 edge_dir = compute_dir(ssPos[0], ssPos[1]) * sizeViewportInv.xy;
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
float line_size = float(lineThickness) * sizePixel;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance);
#endif
finalColor = finalColor_geom[0];
t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[0].gl_Position.w : 1.0));
t = edge_dir * (line_size * (is_persp ? gl_in[0].gl_Position.w : 1.0));
gl_Position = gl_in[0].gl_Position + vec4(t, 0.0, 0.0);
EmitVertex();
gl_Position = gl_in[0].gl_Position - vec4(t, 0.0, 0.0);
EmitVertex();
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance);
#endif
finalColor = finalColor_geom[1];
t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[1].gl_Position.w : 1.0));
t = edge_dir * (line_size * (is_persp ? gl_in[1].gl_Position.w : 1.0));
gl_Position = gl_in[1].gl_Position + vec4(t, 0.0, 0.0);
EmitVertex();
gl_Position = gl_in[1].gl_Position - vec4(t, 0.0, 0.0);

View File

@@ -1,16 +1,13 @@
uniform mat4 ViewMatrix;
uniform mat4 ViewProjectionMatrix;
uniform vec2 viewportSize;
uniform int frameCurrent;
uniform int frameStart;
uniform int frameEnd;
uniform int cacheStart;
uniform ivec4 mpathLineSettings;
uniform bool selected;
uniform bool useCustomColor;
uniform vec3 customColor;
#define frameCurrent mpathLineSettings.x
#define frameStart mpathLineSettings.y
#define frameEnd mpathLineSettings.z
#define cacheStart mpathLineSettings.w
in vec3 pos;
out vec2 ssPos;
@@ -19,7 +16,7 @@ out vec4 finalColor_geom;
/* project to screen space */
vec2 proj(vec4 pos)
{
return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
return (0.5 * (pos.xy / pos.w) + 0.5) * sizeViewport.xy;
}
#define SET_INTENSITY(A, B, C, min, max) \
@@ -38,10 +35,10 @@ void main()
vec3 blend_base = (abs(frame - frameCurrent) == 1) ?
colorCurrentFrame.rgb :
colorBackground.rgb; /* "bleed" cframe color to ease color blending */
bool use_custom_color = customColor.x >= 0.0;
/* TODO: We might want something more consistent with custom color and standard colors. */
if (frame < frameCurrent) {
if (useCustomColor) {
if (use_custom_color) {
/* Custom color: previous frames color is darker than current frame */
finalColor_geom.rgb = customColor * 0.25;
}
@@ -57,7 +54,7 @@ void main()
}
}
else if (frame > frameCurrent) {
if (useCustomColor) {
if (use_custom_color) {
/* Custom color: next frames color is equal to user selected color */
finalColor_geom.rgb = customColor;
}
@@ -74,7 +71,7 @@ void main()
}
}
else {
if (useCustomColor) {
if (use_custom_color) {
/* Custom color: current frame color is slightly darker than user selected color */
finalColor_geom.rgb = customColor * 0.5;
}
@@ -92,4 +89,8 @@ void main()
}
finalColor_geom.a = 1.0;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(pos);
#endif
}

View File

@@ -1,13 +1,12 @@
uniform mat4 ViewProjectionMatrix;
uniform int pointSize = 2;
uniform int frameCurrent;
uniform int cacheStart;
uniform ivec4 mpathPointSettings;
uniform bool showKeyFrames = true;
uniform bool useCustomColor;
uniform vec3 customColor;
uniform int stepSize;
#define pointSize mpathPointSettings.x
#define frameCurrent mpathPointSettings.y
#define cacheStart mpathPointSettings.z
#define stepSize mpathPointSettings.w
in vec3 pos;
in int flag;
@@ -23,7 +22,8 @@ void main()
gl_PointSize = float(pointSize + 2);
int frame = gl_VertexID + cacheStart;
finalColor = (useCustomColor) ? vec4(customColor, 1.0) : vec4(1.0);
bool use_custom_color = customColor.x >= 0.0;
finalColor = (use_custom_color) ? vec4(customColor, 1.0) : vec4(1.0);
/* Bias to reduce z fighting with the path */
gl_Position.z -= 1e-4;
@@ -49,4 +49,10 @@ void main()
gl_Position.z -= 1e-4;
}
}
gl_PointSize *= sizePixel;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(pos);
#endif
}

View File

@@ -8,7 +8,6 @@ uniform sampler2D outlineDepth;
uniform sampler2D sceneDepth;
uniform float alphaOcclu;
uniform vec2 viewportSize;
void main()
{

View File

@@ -4,12 +4,17 @@ in vec4 nor; /* select flag on the 4th component */
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
bool is_select = (nor.w > 0.0);
bool is_hidden = (nor.w < 0.0);
/* Don't draw faces that are selected. */
if (nor.w > 0.0) {
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
if (is_hidden || is_select) {
gl_Position = vec4(-2.0, -2.0, -2.0, 1.0);
}
else {
#ifdef USE_WORLD_CLIP_PLANES

View File

@@ -0,0 +1,32 @@
in vec3 pos;
in vec4 nor; /* select flag on the 4th component */
out vec4 finalColor;
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
bool is_select = (nor.w > 0.0);
bool is_hidden = (nor.w < 0.0);
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
/* Add offset in Z to avoid zfighting and render selected wires on top. */
/* TODO scale this bias using znear and zfar range. */
gl_Position.z -= (is_select ? 2e-4 : 1e-4);
if (is_hidden) {
gl_Position = vec4(-2.0, -2.0, -2.0, 1.0);
}
finalColor = (is_select) ? vec4(1.0) : colorWire;
finalColor.a = nor.w;
gl_PointSize = sizeVertex * 2.0;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -0,0 +1,23 @@
in vec2 uv_interp;
out vec4 fragColor;
uniform float opacity = 1.0;
uniform sampler2D maskImage;
uniform bool maskImagePremultiplied;
uniform vec3 maskColor;
uniform bool maskInvertStencil;
void main()
{
vec4 mask = vec4(texture_read_as_srgb(maskImage, maskImagePremultiplied, uv_interp).rgb, 1.0);
if (maskInvertStencil) {
mask.rgb = 1.0 - mask.rgb;
}
float mask_step = smoothstep(0, 3.0, mask.r + mask.g + mask.b);
mask.rgb *= maskColor;
mask.a = mask_step * opacity;
fragColor = mask;
}

View File

@@ -2,14 +2,16 @@
in vec3 pos;
in vec2 mu; /* masking uv map */
out vec2 masking_uv_interp;
out vec2 uv_interp;
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
masking_uv_interp = mu;
uv_interp = mu;
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);

View File

@@ -2,7 +2,9 @@
in vec3 finalColor;
out vec4 fragColor;
uniform float opacity = 1.0;
uniform bool useAlphaBlend = false;
vec3 linear_to_srgb_attr(vec3 c)
{
@@ -15,10 +17,12 @@ vec3 linear_to_srgb_attr(vec3 c)
void main()
{
vec3 color = linear_to_srgb_attr(finalColor);
#ifdef DRW_STATE_BLEND_ALPHA
fragColor = vec4(color, opacity);
#else
fragColor.rgb = mix(vec3(1.0), color, opacity);
fragColor.a = 1.0;
#endif
if (useAlphaBlend) {
fragColor = vec4(color, opacity);
}
else {
/* mix with 1.0 -> is like opacity when using multiply blend mode */
fragColor = vec4(mix(vec3(1.0), color, opacity), 1.0);
}
}

View File

@@ -14,6 +14,8 @@ vec3 srgb_to_linear_attr(vec3 c)
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);

View File

@@ -6,6 +6,7 @@ out vec4 fragColor;
uniform float opacity = 1.0;
uniform sampler1D colorramp;
uniform bool useAlphaBlend = false;
uniform bool drawContours = false;
float contours(float value, float steps, float width_px, float max_rel_width, float gradient)
@@ -95,11 +96,11 @@ void main()
color = mix(weight_color, colorVertexUnreferenced, alert * alert);
}
#ifdef DRW_STATE_BLEND_ALPHA
/* alpha blending mix */
fragColor = vec4(color.rgb, opacity);
#else
/* mix with 1.0 -> is like opacity when using multiply blend mode */
fragColor = vec4(mix(vec3(1.0), color.rgb, opacity), 1.0);
#endif
if (useAlphaBlend) {
fragColor = vec4(color.rgb, opacity);
}
else {
/* mix with 1.0 -> is like opacity when using multiply blend mode */
fragColor = vec4(mix(vec3(1.0), color.rgb, opacity), 1.0);
}
}

View File

@@ -6,6 +6,8 @@ out vec2 weight_interp; /* (weight, alert) */
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);

View File

@@ -1,4 +1,6 @@
uniform bool useSelect;
in vec3 pos;
in vec4 nor; /* flag stored in w */
@@ -6,13 +8,11 @@ flat out vec4 finalColor;
void main()
{
#ifdef USE_SELECT
bool is_select = (nor.w > 0.0);
bool is_hidden = (nor.w < 0.0);
#else
bool is_select = false;
bool is_hidden = false;
#endif
GPU_INTEL_VERTEX_SHADER_WORKAROUND
bool is_select = (nor.w > 0.0) && useSelect;
bool is_hidden = (nor.w < 0.0) && useSelect;
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
/* Add offset in Z to avoid zfighting and render selected wires on top. */
@@ -23,30 +23,14 @@ void main()
gl_Position = vec4(-2.0, -2.0, -2.0, 1.0);
}
#ifdef VERTEX_MODE
vec4 colSel = colorEdgeSelect;
colSel.rgb = clamp(colSel.rgb - 0.2, 0.0, 1.0);
#else
const vec4 colSel = vec4(1.0, 1.0, 1.0, 1.0);
#endif
const vec4 colSel = vec4(1.0);
#ifdef USE_SELECT
finalColor = (is_select) ? colSel : colorWire;
finalColor.a = nor.w;
#else
# ifdef VERTEX_MODE
finalColor.xyz = colorWire.xyz;
finalColor.a = 1.0;
# else
/* Weight paint needs a light color to contrasts with dark weights. */
finalColor = vec4(1, 1, 1, 0.2);
# endif
#endif
/* Needed for Radeon (TM) RX 480 Graphics. */
#if defined(GPU_ATI)
gl_PointSize = sizeVertex * 2.0;
#endif
/* Weight paint needs a light color to contrasts with dark weights. */
if (!useSelect) {
finalColor = vec4(1.0, 1.0, 1.0, 0.3);
}
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);

View File

@@ -0,0 +1,16 @@
in vec4 finalColor;
out vec4 fragColor;
void main()
{
float dist = length(gl_PointCoord - vec2(0.5));
if (dist > 0.5) {
discard;
}
/* Nice sphere falloff. */
float intensity = sqrt(1.0 - dist * 2.0) * 0.5 + 0.5;
fragColor = finalColor * vec4(intensity, intensity, intensity, 1.0);
}

View File

@@ -0,0 +1,68 @@
uniform sampler1D weightTex;
uniform vec4 color; /* Drawsize packed in alpha */
/* ---- Instantiated Attrs ---- */
in vec3 pos;
in int vclass;
/* ---- Per instance Attrs ---- */
in vec3 part_pos;
in vec4 part_rot;
in float part_val;
#ifdef USE_DOTS
out vec4 finalColor;
#else
flat out vec4 finalColor;
#endif
#define VCLASS_SCREENALIGNED (1 << 9)
#define VCLASS_EMPTY_AXES (1 << 11)
vec3 rotate(vec3 vec, vec4 quat)
{
/* The quaternion representation here stores the w component in the first index */
return vec + 2.0 * cross(quat.yzw, cross(quat.yzw, vec) + quat.x * vec);
}
void main()
{
float draw_size = color.a;
vec3 world_pos = part_pos;
#ifdef USE_DOTS
gl_Position = point_world_to_ndc(world_pos);
/* World sized points. */
gl_PointSize = sizePixel * draw_size * ProjectionMatrix[1][1] * sizeViewport.y / gl_Position.w;
#else
if ((vclass & VCLASS_SCREENALIGNED) != 0) {
/* World sized, camera facing geometry. */
world_pos += (screenVecs[0].xyz * pos.x + screenVecs[1].xyz * pos.y) * draw_size;
}
else {
world_pos += rotate(pos, part_rot) * draw_size;
}
gl_Position = point_world_to_ndc(world_pos);
#endif
/* Coloring */
if ((vclass & VCLASS_EMPTY_AXES) != 0) {
/* see VBO construction for explanation. */
finalColor = vec4(clamp(pos * 10000.0, 0.0, 1.0), 1.0);
}
else if (part_val < 0.0) {
finalColor = vec4(color.rgb, 1.0);
}
else {
finalColor = vec4(texture(weightTex, part_val).rgb, 1.0);
}
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

View File

@@ -12,5 +12,9 @@ void main()
gl_Position = point_world_to_ndc(world_pos);
float mask = 1.0 - (msk * maskOpacity);
finalColor = vec4(mask, mask, mask, 1.0);
finalColor = vec4(0.0, 0.0, 0.0, mask);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
#endif
}

Some files were not shown because too many files have changed in this diff Show More