summaryrefslogtreecommitdiff
path: root/editor/plugins
diff options
context:
space:
mode:
authorjfons <joan.fonssanchez@gmail.com>2021-01-29 16:12:50 +0100
committerjfons <joan.fonssanchez@gmail.com>2021-02-01 22:19:54 +0100
commit73e62dffb909fcf47be23d4fa056e9039b7e561f (patch)
tree018eef6473d004aac5cff523431da21a9046db7f /editor/plugins
parent46de553473b4bea49176fb4316176a5662931160 (diff)
3D editor grid improvements
This commit adds a view-dependant fade to the 3D viewport grid. It fades out at steep view angles to hide the solid regions that appear far from the camera. I also included a fade to hide the grid borders. I added some improvements to the dynamic grid when the camera is in orthogonal mode. It properly handles zoom now, and the grid center is now set to the intersection point between the grid plane and the camera forward ray, keeping the grid always visible.
Diffstat (limited to 'editor/plugins')
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp192
-rw-r--r--editor/plugins/node_3d_editor_plugin.h2
2 files changed, 130 insertions, 64 deletions
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index dcf38e0617..68f5fbd53f 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -5259,6 +5259,42 @@ void Node3DEditor::_init_indicators() {
origin_points.push_back(axis * -1048576);
}
+ Ref<Shader> grid_shader = memnew(Shader);
+ grid_shader->set_code(
+ "\n"
+ "shader_type spatial; \n"
+ "render_mode unshaded; \n"
+ "uniform bool orthogonal; \n"
+ "uniform float grid_size; \n"
+ "\n"
+ "void vertex() { \n"
+ " // From FLAG_SRGB_VERTEX_COLOR \n"
+ " if (!OUTPUT_IS_SRGB) { \n"
+ " COLOR.rgb = mix(pow((COLOR.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), COLOR.rgb * (1.0 / 12.92), lessThan(COLOR.rgb, vec3(0.04045))); \n"
+ " } \n"
+ "} \n"
+ "\n"
+ "void fragment() { \n"
+ " ALBEDO = COLOR.rgb; \n"
+ " vec3 dir = orthogonal ? -vec3(0, 0, 1) : VIEW; \n"
+ " float angle_fade = abs(dot(dir, NORMAL)); \n"
+ " angle_fade = smoothstep(0.05, 0.2, angle_fade); \n"
+ " \n"
+ " vec3 world_pos = (CAMERA_MATRIX * vec4(VERTEX, 1.0)).xyz; \n"
+ " vec3 world_normal = (CAMERA_MATRIX * vec4(NORMAL, 0.0)).xyz; \n"
+ " vec3 camera_world_pos = CAMERA_MATRIX[3].xyz; \n"
+ " vec3 camera_world_pos_on_plane = camera_world_pos * (1.0 - world_normal); \n"
+ " float dist_fade = 1.0 - (distance(world_pos, camera_world_pos_on_plane) / grid_size); \n"
+ " dist_fade = smoothstep(0.02, 0.3, dist_fade); \n"
+ " \n"
+ " ALPHA = COLOR.a * dist_fade * angle_fade; \n"
+ "}");
+
+ for (int i = 0; i < 3; i++) {
+ grid_mat[i].instance();
+ grid_mat[i]->set_shader(grid_shader);
+ }
+
grid_enable[0] = EditorSettings::get_singleton()->get("editors/3d/grid_xy_plane");
grid_enable[1] = EditorSettings::get_singleton()->get("editors/3d/grid_yz_plane");
grid_enable[2] = EditorSettings::get_singleton()->get("editors/3d/grid_xz_plane");
@@ -5461,32 +5497,33 @@ void Node3DEditor::_init_indicators() {
Ref<Shader> rotate_shader = memnew(Shader);
- rotate_shader->set_code("\n"
- "shader_type spatial; \n"
- "render_mode unshaded, depth_test_disabled; \n"
- "uniform vec4 albedo; \n"
- "\n"
- "mat3 orthonormalize(mat3 m) { \n"
- " vec3 x = normalize(m[0]); \n"
- " vec3 y = normalize(m[1] - x * dot(x, m[1])); \n"
- " vec3 z = m[2] - x * dot(x, m[2]); \n"
- " z = normalize(z - y * (dot(y,m[2]))); \n"
- " return mat3(x,y,z); \n"
- "} \n"
- "\n"
- "void vertex() { \n"
- " mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX)); \n"
- " vec3 n = mv * VERTEX; \n"
- " float orientation = dot(vec3(0,0,-1),n); \n"
- " if (orientation <= 0.005) { \n"
- " VERTEX += NORMAL*0.02; \n"
- " } \n"
- "} \n"
- "\n"
- "void fragment() { \n"
- " ALBEDO = albedo.rgb; \n"
- " ALPHA = albedo.a; \n"
- "}");
+ rotate_shader->set_code(
+ "\n"
+ "shader_type spatial; \n"
+ "render_mode unshaded, depth_test_disabled; \n"
+ "uniform vec4 albedo; \n"
+ "\n"
+ "mat3 orthonormalize(mat3 m) { \n"
+ " vec3 x = normalize(m[0]); \n"
+ " vec3 y = normalize(m[1] - x * dot(x, m[1])); \n"
+ " vec3 z = m[2] - x * dot(x, m[2]); \n"
+ " z = normalize(z - y * (dot(y,m[2]))); \n"
+ " return mat3(x,y,z); \n"
+ "} \n"
+ "\n"
+ "void vertex() { \n"
+ " mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX)); \n"
+ " vec3 n = mv * VERTEX; \n"
+ " float orientation = dot(vec3(0,0,-1),n); \n"
+ " if (orientation <= 0.005) { \n"
+ " VERTEX += NORMAL*0.02; \n"
+ " } \n"
+ "} \n"
+ "\n"
+ "void fragment() { \n"
+ " ALBEDO = albedo.rgb; \n"
+ " ALPHA = albedo.a; \n"
+ "}");
Ref<ShaderMaterial> rotate_mat = memnew(ShaderMaterial);
rotate_mat->set_render_priority(Material::RENDER_PRIORITY_MAX);
@@ -5506,33 +5543,34 @@ void Node3DEditor::_init_indicators() {
Ref<ShaderMaterial> border_mat = rotate_mat->duplicate();
Ref<Shader> border_shader = memnew(Shader);
- border_shader->set_code("\n"
- "shader_type spatial; \n"
- "render_mode unshaded, depth_test_disabled; \n"
- "uniform vec4 albedo; \n"
- "\n"
- "mat3 orthonormalize(mat3 m) { \n"
- " vec3 x = normalize(m[0]); \n"
- " vec3 y = normalize(m[1] - x * dot(x, m[1])); \n"
- " vec3 z = m[2] - x * dot(x, m[2]); \n"
- " z = normalize(z - y * (dot(y,m[2]))); \n"
- " return mat3(x,y,z); \n"
- "} \n"
- "\n"
- "void vertex() { \n"
- " mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX)); \n"
- " mv = inverse(mv); \n"
- " VERTEX += NORMAL*0.008; \n"
- " vec3 camera_dir_local = mv * vec3(0,0,1); \n"
- " vec3 camera_up_local = mv * vec3(0,1,0); \n"
- " mat3 rotation_matrix = mat3(cross(camera_dir_local, camera_up_local), camera_up_local, camera_dir_local); \n"
- " VERTEX = rotation_matrix * VERTEX; \n"
- "} \n"
- "\n"
- "void fragment() { \n"
- " ALBEDO = albedo.rgb; \n"
- " ALPHA = albedo.a; \n"
- "}");
+ border_shader->set_code(
+ "\n"
+ "shader_type spatial; \n"
+ "render_mode unshaded, depth_test_disabled; \n"
+ "uniform vec4 albedo; \n"
+ "\n"
+ "mat3 orthonormalize(mat3 m) { \n"
+ " vec3 x = normalize(m[0]); \n"
+ " vec3 y = normalize(m[1] - x * dot(x, m[1])); \n"
+ " vec3 z = m[2] - x * dot(x, m[2]); \n"
+ " z = normalize(z - y * (dot(y,m[2]))); \n"
+ " return mat3(x,y,z); \n"
+ "} \n"
+ "\n"
+ "void vertex() { \n"
+ " mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX)); \n"
+ " mv = inverse(mv); \n"
+ " VERTEX += NORMAL*0.008; \n"
+ " vec3 camera_dir_local = mv * vec3(0,0,1); \n"
+ " vec3 camera_up_local = mv * vec3(0,1,0); \n"
+ " mat3 rotation_matrix = mat3(cross(camera_dir_local, camera_up_local), camera_up_local, camera_dir_local); \n"
+ " VERTEX = rotation_matrix * VERTEX; \n"
+ "} \n"
+ "\n"
+ "void fragment() { \n"
+ " ALBEDO = albedo.rgb; \n"
+ " ALPHA = albedo.a; \n"
+ "}");
border_mat->set_shader(border_shader);
border_mat->set_shader_param("albedo", Color(0.75, 0.75, 0.75, col.a / 3.0));
@@ -5694,8 +5732,11 @@ void Node3DEditor::_init_grid() {
return; // Camera3D is invalid, don't draw the grid.
}
+ bool orthogonal = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL;
+
Vector<Color> grid_colors[3];
Vector<Vector3> grid_points[3];
+ Vector<Vector3> grid_normals[3];
Color primary_grid_color = EditorSettings::get_singleton()->get("editors/3d/primary_grid_color");
Color secondary_grid_color = EditorSettings::get_singleton()->get("editors/3d/secondary_grid_color");
@@ -5731,10 +5772,26 @@ void Node3DEditor::_init_grid() {
int b = (a + 1) % 3;
int c = (a + 2) % 3;
- real_t division_level = Math::log(Math::abs(camera_position[c])) / Math::log((double)primary_grid_steps) + division_level_bias;
- division_level = CLAMP(division_level, division_level_min, division_level_max);
- real_t division_level_floored = Math::floor(division_level);
- real_t division_level_decimals = division_level - division_level_floored;
+ Vector3 normal;
+ normal[c] = 1.0;
+
+ real_t camera_distance = Math::abs(camera_position[c]);
+
+ if (orthogonal) {
+ camera_distance = camera->get_size() / 2.0;
+ Vector3 camera_direction = -camera->get_global_transform().get_basis().get_axis(2);
+ Plane grid_plane = Plane(Vector3(), normal);
+ Vector3 intersection;
+ if (grid_plane.intersects_ray(camera_position, camera_direction, &intersection)) {
+ camera_position = intersection;
+ }
+ }
+
+ real_t division_level = Math::log(Math::abs(camera_distance)) / Math::log((double)primary_grid_steps) + division_level_bias;
+
+ real_t clamped_division_level = CLAMP(division_level, division_level_min, division_level_max);
+ real_t division_level_floored = Math::floor(clamped_division_level);
+ real_t division_level_decimals = clamped_division_level - division_level_floored;
real_t small_step_size = Math::pow(primary_grid_steps, division_level_floored);
real_t large_step_size = small_step_size * primary_grid_steps;
@@ -5746,6 +5803,15 @@ void Node3DEditor::_init_grid() {
real_t bgn_b = center_b - grid_size * small_step_size;
real_t end_b = center_b + grid_size * small_step_size;
+ real_t fade_size = Math::pow(primary_grid_steps, division_level - 1.0);
+ real_t min_fade_size = Math::pow(primary_grid_steps, float(division_level_min));
+ real_t max_fade_size = Math::pow(primary_grid_steps, float(division_level_max));
+ fade_size = CLAMP(fade_size, min_fade_size, max_fade_size);
+
+ real_t grid_fade_size = (grid_size - primary_grid_steps) * fade_size;
+ grid_mat[c]->set_shader_param("grid_size", grid_fade_size);
+ grid_mat[c]->set_shader_param("orthogonal", orthogonal);
+
// In each iteration of this loop, draw one line in each direction (so two lines per loop, in each if statement).
for (int i = -grid_size; i <= grid_size; i++) {
Color line_color;
@@ -5756,11 +5822,6 @@ void Node3DEditor::_init_grid() {
line_color = secondary_grid_color;
line_color.a = line_color.a * (1 - division_level_decimals);
}
- // Makes lines farther from the center fade out.
- // Due to limitations of lines, any that come near the camera have full opacity always.
- // This should eventually be replaced by some kind of "distance fade" system, outside of this function.
- // But the effect is still somewhat convincing...
- line_color.a *= 1 - (1 - division_level_decimals * 0.9) * (Math::abs(i / (float)grid_size));
real_t position_a = center_a + i * small_step_size;
real_t position_b = center_b + i * small_step_size;
@@ -5777,6 +5838,8 @@ void Node3DEditor::_init_grid() {
grid_points[c].push_back(line_end);
grid_colors[c].push_back(line_color);
grid_colors[c].push_back(line_color);
+ grid_normals[c].push_back(normal);
+ grid_normals[c].push_back(normal);
}
if (!(origin_enabled && Math::is_zero_approx(position_b))) {
@@ -5790,6 +5853,8 @@ void Node3DEditor::_init_grid() {
grid_points[c].push_back(line_end);
grid_colors[c].push_back(line_color);
grid_colors[c].push_back(line_color);
+ grid_normals[c].push_back(normal);
+ grid_normals[c].push_back(normal);
}
}
@@ -5799,8 +5864,9 @@ void Node3DEditor::_init_grid() {
d.resize(RS::ARRAY_MAX);
d[RenderingServer::ARRAY_VERTEX] = grid_points[c];
d[RenderingServer::ARRAY_COLOR] = grid_colors[c];
+ d[RenderingServer::ARRAY_NORMAL] = grid_normals[c];
RenderingServer::get_singleton()->mesh_add_surface_from_arrays(grid[c], RenderingServer::PRIMITIVE_LINES, d);
- RenderingServer::get_singleton()->mesh_surface_set_material(grid[c], 0, indicator_mat->get_rid());
+ RenderingServer::get_singleton()->mesh_surface_set_material(grid[c], 0, grid_mat[c]->get_rid());
grid_instance[c] = RenderingServer::get_singleton()->instance_create2(grid[c], get_tree()->get_root()->get_world_3d()->get_scenario());
// Yes, the end of this line is supposed to be a.
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index d7a47fa4fa..9fb7488a0f 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -590,7 +590,6 @@ private:
/////
ToolMode tool_mode;
- bool orthogonal;
RenderingServer::ScenarioDebugMode scenario_debug;
@@ -623,6 +622,7 @@ private:
RID cursor_mesh;
RID cursor_instance;
Ref<StandardMaterial3D> indicator_mat;
+ Ref<ShaderMaterial> grid_mat[3];
Ref<StandardMaterial3D> cursor_material;
// Scene drag and drop support