DRW: Split ViewProjectionMatrix in order to increase precision
This also removes the need to compute the persmat and saves some memory from the `ViewInfos` struct. This is needed to allow multiview support. Initial testing found no major performance regression during vertex heavy workload. Test file: {F13610017} Results: | Platform | Master | Split Matrix| | Linux + Mesa + AMD W6600 | 48 fps | 47 fps | | Macbook Pro M1 | 50 fps | 51 fps | | Linux + NVidia 1080Ti | 51 fps | 52 fps | | Linux + Radeon Vega 64 | 25.6 fps | 26.7 fps | Increased precision when far from origin: {F13610024} {F13610025} Reviewed By: jbakker Differential Revision: https://developer.blender.org/D16125
This commit is contained in:
parent
74ff0aeea0
commit
6306d747b7
@ -1 +1 @@
|
||||
Subproject commit 726d08c9036b939f46b59bceb72a61e3102600cc
|
||||
Subproject commit 67f1fbca1482d9d9362a4001332e785c3fd5d230
|
@ -39,6 +39,6 @@ void main()
|
||||
vec3 screen_pos = screen_vecs[0] * quadCoord.x + screen_vecs[1] * quadCoord.y;
|
||||
ws_location += screen_pos * sphere_size;
|
||||
|
||||
gl_Position = ViewProjectionMatrix * vec4(ws_location, 1.0);
|
||||
gl_Position = ProjectionMatrix * (ViewMatrix * vec4(ws_location, 1.0));
|
||||
gl_Position.z += 0.0001; /* Small bias to let the icon draw without zfighting */
|
||||
}
|
||||
|
@ -42,6 +42,6 @@ void main()
|
||||
vec3 screen_pos = screen_vecs[0] * quadCoord.x + screen_vecs[1] * quadCoord.y;
|
||||
ws_cell_location += screen_pos * sphere_size;
|
||||
|
||||
gl_Position = ViewProjectionMatrix * vec4(ws_cell_location, 1.0);
|
||||
gl_Position = ProjectionMatrix * (ViewMatrix * vec4(ws_cell_location, 1.0));
|
||||
gl_Position.z += 0.0001; /* Small bias to let the icon draw without zfighting */
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ vec3 probe_evaluate_planar(int id, PlanarData pd, vec3 P, vec3 N, vec3 V, float
|
||||
vec3 ref_pos = point_on_plane + proj_ref;
|
||||
|
||||
/* Reproject to find texture coords. */
|
||||
vec4 refco = ViewProjectionMatrix * vec4(ref_pos, 1.0);
|
||||
vec4 refco = ProjectionMatrix * (ViewMatrix * vec4(ref_pos, 1.0));
|
||||
refco.xy /= refco.w;
|
||||
|
||||
/* TODO: If we support non-ssr planar reflection, we should blur them with gaussian
|
||||
|
@ -10,7 +10,7 @@ out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 refco = ViewProjectionMatrix * vec4(worldPosition, 1.0);
|
||||
vec4 refco = ProjectionMatrix * (ViewMatrix * vec4(worldPosition, 1.0));
|
||||
refco.xy /= refco.w;
|
||||
FragColor = vec4(
|
||||
textureLod(probePlanars, vec3(refco.xy * vec2(-0.5, 0.5) + 0.5, float(probeIdx)), 0.0).rgb,
|
||||
|
@ -12,6 +12,6 @@ flat out int probeIdx;
|
||||
void main()
|
||||
{
|
||||
worldPosition = (probe_mat * vec4(-pos.x, pos.y, 0.0, 1.0)).xyz;
|
||||
gl_Position = ViewProjectionMatrix * vec4(worldPosition, 1.0);
|
||||
gl_Position = ProjectionMatrix * (ViewMatrix * vec4(worldPosition, 1.0));
|
||||
probeIdx = probe_id;
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ void main()
|
||||
/* Use jittered projmatrix to be able to match exact sample depth (depth equal test).
|
||||
* Note that currModelMatrix needs to also be equal to ModelMatrix for the samples to match. */
|
||||
#ifndef HAIR
|
||||
gl_Position = ViewProjectionMatrix * vec4(currWorldPos, 1.0);
|
||||
gl_Position = ProjectionMatrix * (ViewMatrix * vec4(currWorldPos, 1.0));
|
||||
#else
|
||||
gl_Position = ViewProjectionMatrix * vec4(wpos, 1.0);
|
||||
gl_Position = ProjectionMatrix * (ViewMatrix * vec4(wpos, 1.0));
|
||||
#endif
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ vec3 coordinate_screen(vec3 P)
|
||||
window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
|
||||
|
||||
#else /* MESH */
|
||||
window.xy = project_point(ViewProjectionMatrix, P).xy * 0.5 + 0.5;
|
||||
window.xy = project_point(ProjectionMatrix, transform_point(ViewMatrix, P)).xy * 0.5 + 0.5;
|
||||
window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
|
||||
#endif
|
||||
return window;
|
||||
|
@ -52,7 +52,7 @@ vec3 coordinate_camera(vec3 P)
|
||||
vec3 coordinate_screen(vec3 P)
|
||||
{
|
||||
vec3 window = vec3(0.0);
|
||||
window.xy = project_point(ViewProjectionMatrix, P).xy * 0.5 + 0.5;
|
||||
window.xy = project_point(ProjectionMatrix, transform_point(ViewMatrix, P)).xy * 0.5 + 0.5;
|
||||
window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
|
||||
return window;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ vec3 light_volume_light_vector(LightData ld, vec3 P)
|
||||
vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction)
|
||||
{
|
||||
/* Waiting for proper volume shadowmaps and out of frustum shadow map. */
|
||||
vec3 ndc = project_point(ViewProjectionMatrix, wpos);
|
||||
vec3 ndc = project_point(ProjectionMatrix, transform_point(ViewMatrix, wpos));
|
||||
vec3 volume_co = ndc_to_volume(ndc * 0.5 + 0.5);
|
||||
|
||||
/* Let the texture be clamped to edge. This reduce visual glitches. */
|
||||
@ -147,12 +147,15 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D v
|
||||
|
||||
if (ld.l_type == SUN) {
|
||||
/* For sun light we scan the whole frustum. So we need to get the correct endpoints. */
|
||||
vec3 ndcP = project_point(ViewProjectionMatrix, ray_wpos);
|
||||
vec3 ndcL = project_point(ViewProjectionMatrix, ray_wpos + l_vector.xyz) - ndcP;
|
||||
vec3 ndcP = project_point(ProjectionMatrix, transform_point(ViewMatrix, ray_wpos));
|
||||
vec3 ndcL = project_point(ProjectionMatrix,
|
||||
transform_point(ViewMatrix, ray_wpos + l_vector.xyz)) -
|
||||
ndcP;
|
||||
|
||||
vec3 frustum_isect = ndcP + ndcL * line_unit_box_intersect_dist_safe(ndcP, ndcL);
|
||||
|
||||
L = project_point(ViewProjectionMatrixInverse, frustum_isect) - ray_wpos;
|
||||
vec4 L_hom = ViewMatrixInverse * (ProjectionMatrixInverse * vec4(frustum_isect, 1.0));
|
||||
L = (L_hom.xyz / L_hom.w) - ray_wpos;
|
||||
L /= volShadowSteps;
|
||||
dd = length(L);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ void main()
|
||||
|
||||
gl_Position = vec4(pos, 1.0, 1.0);
|
||||
viewPosition = project_point(ProjectionMatrixInverse, vec3(pos, 0.0));
|
||||
worldPosition = project_point(ViewProjectionMatrixInverse, vec3(pos, 0.0));
|
||||
worldPosition = transform_point(ViewMatrixInverse, viewPosition);
|
||||
/* Not usable. */
|
||||
viewNormal = vec3(0.0);
|
||||
worldNormal = vec3(0.0);
|
||||
|
@ -344,7 +344,7 @@ vec3 coordinate_screen(vec3 P)
|
||||
}
|
||||
else {
|
||||
/* TODO(fclem): Actual camera transform. */
|
||||
window.xy = project_point(ViewProjectionMatrix, P).xy * 0.5 + 0.5;
|
||||
window.xy = project_point(ProjectionMatrix, transform_point(ViewMatrix, P)).xy * 0.5 + 0.5;
|
||||
window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
|
||||
}
|
||||
return window;
|
||||
|
@ -5,5 +5,5 @@ void main()
|
||||
int v = gl_VertexID % 3;
|
||||
float x = -1.0 + float((v & 1) << 2);
|
||||
float y = -1.0 + float((v & 2) << 1);
|
||||
gl_Position = drw_view.persmat * (model_matrix * vec4(x, y, 0.0, 1.0));
|
||||
gl_Position = drw_view.winmat * (drw_view.viewmat * (model_matrix * vec4(x, y, 0.0, 1.0)));
|
||||
}
|
||||
|
@ -38,5 +38,5 @@ void main()
|
||||
view_clipping_distances(sp);
|
||||
|
||||
vec4 pos_4d = vec4(sp, 1.0);
|
||||
gl_Position = drw_view.persmat * pos_4d;
|
||||
gl_Position = drw_view.winmat * (drw_view.viewmat * pos_4d);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ void main()
|
||||
finalColor.a = 1.0;
|
||||
|
||||
vec4 world_pos = model_mat * vec4(pos, 1.0);
|
||||
gl_Position = drw_view.persmat * world_pos;
|
||||
gl_Position = drw_view.winmat * (drw_view.viewmat * world_pos);
|
||||
|
||||
view_clipping_distances(world_pos.xyz);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ void main()
|
||||
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 = drw_view.persmat * pos_4d;
|
||||
gl_Position = drw_view.winmat * (drw_view.viewmat * pos_4d);
|
||||
/* Manual stipple: one segment out of 2 is transparent. */
|
||||
finalColor = ((gl_VertexID & 1) == 0) ? colorSkinRoot : vec4(0.0);
|
||||
|
||||
|
@ -39,5 +39,5 @@ void main()
|
||||
local_pos.z = clamp(local_pos.z, -1.0, 0.0);
|
||||
}
|
||||
|
||||
gl_Position = drw_view.persmat * vec4(real_pos, 1.0);
|
||||
gl_Position = drw_view.winmat * (drw_view.viewmat * vec4(real_pos, 1.0));
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ vec2 proj(vec4 pos)
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = drw_view.persmat * vec4(pos, 1.0);
|
||||
gl_Position = drw_view.winmat * (drw_view.viewmat * vec4(pos, 1.0));
|
||||
|
||||
interp.ss_pos = proj(gl_Position);
|
||||
|
||||
|
@ -108,8 +108,8 @@ void main()
|
||||
vec3 in_pos0 = vertex_fetch_attribute(base_vertex_id, pos, vec3);
|
||||
vec3 in_pos1 = vertex_fetch_attribute(base_vertex_id + 1, pos, vec3);
|
||||
|
||||
vec4 out_pos0 = ViewProjectionMatrix * vec4(in_pos0, 1.0);
|
||||
vec4 out_pos1 = ViewProjectionMatrix * vec4(in_pos1, 1.0);
|
||||
vec4 out_pos0 = ProjectionMatrix * (ViewMatrix * vec4(in_pos0, 1.0));
|
||||
vec4 out_pos1 = ProjectionMatrix * (ViewMatrix * vec4(in_pos1, 1.0));
|
||||
|
||||
/* Final calculations required for Geometry Shader alternative.
|
||||
* We need to calculate values for each vertex position to correctly determine the final output
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = drw_view.persmat * vec4(pos, 1.0);
|
||||
gl_Position = drw_view.winmat * (drw_view.viewmat * vec4(pos, 1.0));
|
||||
gl_PointSize = float(pointSize + 2);
|
||||
|
||||
int frame = gl_VertexID + cacheStart;
|
||||
|
@ -25,7 +25,7 @@ void main()
|
||||
bool is_persp = drw_view.winmat[3][3] == 0.0;
|
||||
vec2 uvs = vec2(gl_FragCoord.xy) * drw_view.viewport_size_inverse;
|
||||
vec3 pos_ndc = vec3(uvs, gl_FragCoord.z) * 2.0 - 1.0;
|
||||
vec4 pos_world = drw_view.persinv * vec4(pos_ndc, 1.0);
|
||||
vec4 pos_world = drw_view.viewinv * (drw_view.wininv * vec4(pos_ndc, 1.0));
|
||||
vec3 pos = pos_world.xyz / pos_world.w;
|
||||
|
||||
vec3 ray_ori = pos;
|
||||
|
@ -442,6 +442,9 @@ struct DRWView {
|
||||
struct DRWView *parent;
|
||||
|
||||
ViewInfos storage;
|
||||
|
||||
float4x4 persmat;
|
||||
float4x4 persinv;
|
||||
/** Number of active clip planes. */
|
||||
int clip_planes_len;
|
||||
/** Does culling result needs to be updated. */
|
||||
|
@ -695,7 +695,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
|
||||
drw_call_calc_orco(ob, ob_infos->orcotexfac);
|
||||
/* Random float value. */
|
||||
uint random = (DST.dupli_source) ?
|
||||
DST.dupli_source->random_id :
|
||||
DST.dupli_source->random_id :
|
||||
/* TODO(fclem): this is rather costly to do at runtime. Maybe we can
|
||||
* put it in ob->runtime and make depsgraph ensure it is up to date. */
|
||||
BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0);
|
||||
@ -2133,18 +2133,20 @@ static void draw_frustum_bound_sphere_calc(const BoundBox *bbox,
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_view_matrix_state_update(ViewInfos *storage,
|
||||
static void draw_view_matrix_state_update(DRWView *view,
|
||||
const float viewmat[4][4],
|
||||
const float winmat[4][4])
|
||||
{
|
||||
ViewInfos *storage = &view->storage;
|
||||
|
||||
copy_m4_m4(storage->viewmat.values, viewmat);
|
||||
invert_m4_m4(storage->viewinv.values, storage->viewmat.values);
|
||||
|
||||
copy_m4_m4(storage->winmat.values, winmat);
|
||||
invert_m4_m4(storage->wininv.values, storage->winmat.values);
|
||||
|
||||
mul_m4_m4m4(storage->persmat.values, winmat, viewmat);
|
||||
invert_m4_m4(storage->persinv.values, storage->persmat.values);
|
||||
mul_m4_m4m4(view->persmat.values, winmat, viewmat);
|
||||
invert_m4_m4(view->persinv.values, view->persmat.values);
|
||||
|
||||
const bool is_persp = (winmat[3][3] == 0.0f);
|
||||
|
||||
@ -2260,7 +2262,7 @@ void DRW_view_update_sub(DRWView *view, const float viewmat[4][4], const float w
|
||||
view->is_dirty = true;
|
||||
view->is_inverted = (is_negative_m4(viewmat) == is_negative_m4(winmat));
|
||||
|
||||
draw_view_matrix_state_update(&view->storage, viewmat, winmat);
|
||||
draw_view_matrix_state_update(view, viewmat, winmat);
|
||||
}
|
||||
|
||||
void DRW_view_update(DRWView *view,
|
||||
@ -2277,7 +2279,7 @@ void DRW_view_update(DRWView *view,
|
||||
view->is_dirty = true;
|
||||
view->is_inverted = (is_negative_m4(viewmat) == is_negative_m4(winmat));
|
||||
|
||||
draw_view_matrix_state_update(&view->storage, viewmat, winmat);
|
||||
draw_view_matrix_state_update(view, viewmat, winmat);
|
||||
|
||||
/* Prepare frustum culling. */
|
||||
|
||||
@ -2318,7 +2320,7 @@ void DRW_view_update(DRWView *view,
|
||||
}
|
||||
|
||||
draw_frustum_boundbox_calc(viewinv, winmat, &view->frustum_corners);
|
||||
draw_frustum_culling_planes_calc(view->storage.persmat.values, view->frustum_planes);
|
||||
draw_frustum_culling_planes_calc(view->persmat.values, view->frustum_planes);
|
||||
draw_frustum_bound_sphere_calc(
|
||||
&view->frustum_corners, viewinv, winmat, wininv, &view->frustum_bsphere);
|
||||
|
||||
@ -2433,8 +2435,7 @@ void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse)
|
||||
void DRW_view_persmat_get(const DRWView *view, float mat[4][4], bool inverse)
|
||||
{
|
||||
view = (view) ? view : DST.view_default;
|
||||
const ViewInfos *storage = &view->storage;
|
||||
copy_m4_m4(mat, (inverse) ? storage->persinv.values : storage->persmat.values);
|
||||
copy_m4_m4(mat, (inverse) ? view->persinv.values : view->persmat.values);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -52,8 +52,6 @@ typedef enum eObjectInfoFlag eObjectInfoFlag;
|
||||
|
||||
struct ViewInfos {
|
||||
/* View matrices */
|
||||
float4x4 persmat;
|
||||
float4x4 persinv;
|
||||
float4x4 viewmat;
|
||||
float4x4 viewinv;
|
||||
float4x4 winmat;
|
||||
@ -86,8 +84,6 @@ BLI_STATIC_ASSERT_ALIGN(ViewInfos, 16)
|
||||
/* Do not override old definitions if the shader uses this header but not shader info. */
|
||||
#ifdef USE_GPU_SHADER_CREATE_INFO
|
||||
/* TODO(@fclem): Mass rename. */
|
||||
# define ViewProjectionMatrix drw_view.persmat
|
||||
# define ViewProjectionMatrixInverse drw_view.persinv
|
||||
# define ViewMatrix drw_view.viewmat
|
||||
# define ViewMatrixInverse drw_view.viewinv
|
||||
# define ProjectionMatrix drw_view.winmat
|
||||
|
@ -21,8 +21,6 @@ void View::sync(const float4x4 &view_mat, const float4x4 &win_mat)
|
||||
data_.viewinv = view_mat.inverted();
|
||||
data_.winmat = win_mat;
|
||||
data_.wininv = win_mat.inverted();
|
||||
data_.persmat = data_.winmat * data_.viewmat;
|
||||
data_.persinv = data_.persmat.inverted();
|
||||
/* Should not be used anymore. */
|
||||
data_.viewcamtexcofac = float4(1.0f, 1.0f, 0.0f, 0.0f);
|
||||
|
||||
@ -83,7 +81,8 @@ void View::frustum_boundbox_calc(BoundBox &bbox)
|
||||
|
||||
void View::frustum_culling_planes_calc()
|
||||
{
|
||||
planes_from_projmat(data_.persmat.ptr(),
|
||||
float4x4 persmat = data_.winmat * data_.viewmat;
|
||||
planes_from_projmat(persmat.ptr(),
|
||||
data_.frustum_planes[0],
|
||||
data_.frustum_planes[5],
|
||||
data_.frustum_planes[1],
|
||||
@ -298,7 +297,8 @@ void View::compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool d
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (debug_freeze) {
|
||||
drw_debug_matrix_as_bbox(data_freeze_.persinv, float4(0, 1, 0, 1));
|
||||
float4x4 persmat = data_freeze_.winmat * data_freeze_.viewmat;
|
||||
drw_debug_matrix_as_bbox(persmat.inverted(), float4(0, 1, 0, 1));
|
||||
}
|
||||
#endif
|
||||
frozen_ = debug_freeze;
|
||||
|
@ -11,9 +11,6 @@
|
||||
/* 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;
|
||||
@ -61,8 +58,9 @@ vec3 cameraVec(vec3 P)
|
||||
/* TODO move to overlay engine. */
|
||||
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]);
|
||||
vec3 vP = (ViewMatrix * vec4(co, 1.0)).xyz;
|
||||
return pixelFac * ((ProjectionMatrix[0][3] * vP.x) + (ProjectionMatrix[1][3] * vP.y) +
|
||||
(ProjectionMatrix[2][3] * vP.z) + ProjectionMatrix[3][3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -267,13 +265,14 @@ uniform mat4 ModelMatrixInverse;
|
||||
#define normal_world_to_view(n) (mat3(ViewMatrix) * n)
|
||||
#define normal_view_to_world(n) (mat3(ViewMatrixInverse) * n)
|
||||
|
||||
#define point_object_to_ndc(p) (ViewProjectionMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0))
|
||||
#define point_object_to_ndc(p) \
|
||||
(ProjectionMatrix * (ViewMatrix * 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_ndc(p) (ProjectionMatrix * (ViewMatrix * 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)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user