diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2019-12-02 03:40:58 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2019-12-02 15:15:52 +0300 |
commit | 9516921c05bd9fee5c94942eb8e38f47ba7e4351 (patch) | |
tree | da007fc17bc6a02f849dae2e8f76f5ab304fe4dc /source/blender/draw/intern/shaders/common_view_lib.glsl | |
parent | 1f6c3699a836d485ed37f443cd0fcd19e978dbb6 (diff) |
Overlay Engine: Refactor & Cleanup
This is the unification of all overlays into one overlay engine as described in T65347.
I went over all the code making it more future proof with less hacks and removing old / not relevent parts.
Goals / Acheivements:
- Remove internal shader usage (only drw shaders)
- Remove viewportSize and viewportSizeInv and put them in gloabl ubo
- Fixed some drawing issues: Missing probe option and Missing Alt+B clipping of some shader
- Remove old (legacy) shaders dependancy (not using view UBO).
- Less shader variation (less compilation time at first load and less patching needed for vulkan)
- removed some geom shaders when I could
- Remove static e_data (except shaders storage where it is OK)
- Clear the way to fix some anoying limitations (dithered transparency, background image compositing etc...)
- Wireframe drawing now uses the same batching capabilities as workbench & eevee (indirect drawing).
- Reduced complexity, removed ~3000 Lines of code in draw (also removed a lot of unused shader in GPU).
- Post AA to avoid complexity and cost of MSAA.
Remaining issues:
- ~~Armature edits, overlay toggles, (... others?) are not refreshing viewport after AA is complete~~
- FXAA is not the best for wires, maybe investigate SMAA
- Maybe do something more temporally stable for AA.
- ~~Paint overlays are not working with AA.~~
- ~~infront objects are difficult to select.~~
- ~~the infront wires sometimes goes through they solid counterpart (missing clear maybe?) (toggle overlays on-off when using infront+wireframe overlay in solid shading)~~
Note: I made some decision to change slightly the appearance of some objects to simplify their drawing. Namely the empty arrows end (which is now hollow/wire) and distance points of the cameras/spots being done by lines.
Reviewed By: jbakker
Differential Revision: https://developer.blender.org/D6296
Diffstat (limited to 'source/blender/draw/intern/shaders/common_view_lib.glsl')
-rw-r--r-- | source/blender/draw/intern/shaders/common_view_lib.glsl | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl new file mode 100644 index 00000000000..1a28a307163 --- /dev/null +++ b/source/blender/draw/intern/shaders/common_view_lib.glsl @@ -0,0 +1,187 @@ +#define COMMON_VIEW_LIB +#define DRW_RESOURCE_CHUNK_LEN 512 + +/* keep in sync with DRWManager.view_data */ +layout(std140) uniform viewBlock +{ + /* Same order as DRWViewportMatrixType */ + mat4 ViewProjectionMatrix; + mat4 ViewProjectionMatrixInverse; + mat4 ViewMatrix; + mat4 ViewMatrixInverse; + mat4 ProjectionMatrix; + mat4 ProjectionMatrixInverse; + + vec4 clipPlanes[6]; + + /* TODO move it elsewhere. */ + vec4 CameraTexCoFactors; +}; + +#ifdef world_clip_planes_calc_clip_distance +# undef world_clip_planes_calc_clip_distance +# define world_clip_planes_calc_clip_distance(p) \ + _world_clip_planes_calc_clip_distance(p, clipPlanes) +#endif + +#ifdef COMMON_GLOBALS_LIB +float mul_project_m4_v3_zfac(in vec3 co) +{ + return pixelFac * ((ViewProjectionMatrix[0][3] * co.x) + (ViewProjectionMatrix[1][3] * co.y) + + (ViewProjectionMatrix[2][3] * co.z) + ViewProjectionMatrix[3][3]); +} +#endif + +/* Not the right place but need to be common to all overlay's. + * TODO Split to an overlay lib. */ +mat4 extract_matrix_packed_data(mat4 mat, out vec4 dataA, out vec4 dataB) +{ + const float div = 1.0 / 255.0; + int a = int(mat[0][3]); + int b = int(mat[1][3]); + int c = int(mat[2][3]); + int d = int(mat[3][3]); + dataA = vec4(a & 0xFF, a >> 8, b & 0xFF, b >> 8) * div; + dataB = vec4(c & 0xFF, c >> 8, d & 0xFF, d >> 8) * div; + mat[0][3] = mat[1][3] = mat[2][3] = 0.0; + mat[3][3] = 1.0; + return mat; +} + +/* Same here, Not the right place but need to be common to all overlay's. + * TODO Split to an overlay lib. */ +/* edge_start and edge_pos needs to be in the range [0..sizeViewport]. */ +vec4 pack_line_data(vec2 frag_co, vec2 edge_start, vec2 edge_pos) +{ + vec2 edge = edge_start - edge_pos; + float len = length(edge); + if (len > 0.0) { + edge /= len; + vec2 perp = vec2(-edge.y, edge.x); + float dist = dot(perp, frag_co - edge_start); + /* Add 0.1 to diffenrentiate with cleared pixels. */ + return vec4(perp * 0.5 + 0.5, dist * 0.25 + 0.5 + 0.1, 0.0); + } + else { + /* Default line if the origin is perfectly aligned with a pixel. */ + return vec4(1.0, 0.0, 0.5 + 0.1, 0.0); + } +} + +uniform int resourceChunk; + +#ifdef GPU_VERTEX_SHADER +# ifdef GL_ARB_shader_draw_parameters +# define baseInstance gl_BaseInstanceARB +# else /* no ARB_shader_draw_parameters */ +uniform int baseInstance; +# endif + +# if defined(IN_PLACE_INSTANCES) || defined(INSTANCED_ATTRIB) +/* When drawing instances of an object at the same position. */ +# define instanceId 0 +# elif defined(GPU_DEPRECATED_AMD_DRIVER) +/* A driver bug make it so that when using an attribute with GL_INT_2_10_10_10_REV as format, + * the gl_InstanceID is incremented by the 2 bit component of the attrib. + * Ignore gl_InstanceID then. */ +# define instanceId 0 +# else +# define instanceId gl_InstanceID +# endif + +# define resource_id (baseInstance + instanceId) + +/* Use this to declare and pass the value if + * the fragment shader uses the resource_id. */ +# define RESOURCE_ID_VARYING flat out int resourceIDFrag; +# define RESOURCE_ID_VARYING_GEOM flat out int resourceIDGeom; +# define PASS_RESOURCE_ID resourceIDFrag = resource_id; +# define PASS_RESOURCE_ID_GEOM resourceIDGeom = resource_id; +#endif + +/* If used in a fragment / geometry shader, we pass + * resource_id as varying. */ +#ifdef GPU_GEOMETRY_SHADER +# define RESOURCE_ID_VARYING \ + flat out int resourceIDFrag; \ + flat in int resourceIDGeom[]; + +# define resource_id resourceIDGeom +# define PASS_RESOURCE_ID(i) resourceIDFrag = resource_id[i]; +#endif + +#ifdef GPU_FRAGMENT_SHADER +flat in int resourceIDFrag; +# define resource_id resourceIDFrag +#endif + +#if !defined(GPU_INTEL) && !defined(GPU_DEPRECATED_AMD_DRIVER) && !defined(OS_MAC) && \ + !defined(INSTANCED_ATTRIB) +struct ObjectMatrices { + mat4 drw_modelMatrix; + mat4 drw_modelMatrixInverse; +}; + +layout(std140) uniform modelBlock +{ + ObjectMatrices drw_matrices[DRW_RESOURCE_CHUNK_LEN]; +}; + +# define ModelMatrix (drw_matrices[resource_id].drw_modelMatrix) +# define ModelMatrixInverse (drw_matrices[resource_id].drw_modelMatrixInverse) + +#else /* GPU_INTEL */ +/* Intel GPU seems to suffer performance impact when the model matrix is in UBO storage. + * So for now we just force using the legacy path. */ +/* Note that this is also a workaround of a problem on osx (amd or nvidia) + * and older amd driver on windows. */ +uniform mat4 ModelMatrix; +uniform mat4 ModelMatrixInverse; +#endif + +#define resource_handle (resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id) + +/** Transform shortcuts. */ +/* Rule of thumb: Try to reuse world positions and normals because converting though viewspace + * will always be decomposed in at least 2 matrix operation. */ + +/** + * Some clarification: + * Usually Normal matrix is transpose(inverse(ViewMatrix * ModelMatrix)) + * + * But since it is slow to multiply matrices we decompose it. Decomposing + * inversion and transposition both invert the product order leaving us with + * the same original order: + * transpose(ViewMatrixInverse) * transpose(ModelMatrixInverse) + * + * Knowing that the view matrix is orthogonal, the transpose is also the inverse. + * Note: This is only valid because we are only using the mat3 of the ViewMatrixInverse. + * ViewMatrix * transpose(ModelMatrixInverse) + **/ +#define normal_object_to_view(n) (mat3(ViewMatrix) * (transpose(mat3(ModelMatrixInverse)) * n)) +#define normal_object_to_world(n) (transpose(mat3(ModelMatrixInverse)) * n) +#define normal_world_to_object(n) (transpose(mat3(ModelMatrix)) * n) +#define normal_world_to_view(n) (mat3(ViewMatrix) * n) + +#define point_object_to_ndc(p) (ViewProjectionMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)) +#define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz) +#define point_object_to_world(p) ((ModelMatrix * vec4(p, 1.0)).xyz) +#define point_view_to_ndc(p) (ProjectionMatrix * vec4(p, 1.0)) +#define point_view_to_object(p) ((ModelMatrixInverse * (ViewMatrixInverse * vec4(p, 1.0))).xyz) +#define point_view_to_world(p) ((ViewMatrixInverse * vec4(p, 1.0)).xyz) +#define point_world_to_ndc(p) (ViewProjectionMatrix * vec4(p, 1.0)) +#define point_world_to_object(p) ((ModelMatrixInverse * vec4(p, 1.0)).xyz) +#define point_world_to_view(p) ((ViewMatrix * vec4(p, 1.0)).xyz) + +/* Due to some shader compiler bug, we somewhat need to access gl_VertexID + * to make vertex shaders work. even if it's actually dead code. */ +#ifdef GPU_INTEL +# define GPU_INTEL_VERTEX_SHADER_WORKAROUND gl_Position.x = float(gl_VertexID); +#else +# define GPU_INTEL_VERTEX_SHADER_WORKAROUND +#endif + +#define DRW_BASE_SELECTED (1 << 1) +#define DRW_BASE_FROM_DUPLI (1 << 2) +#define DRW_BASE_FROM_SET (1 << 3) +#define DRW_BASE_ACTIVE (1 << 4) |