QmlDesigner: Make 3D view grid fade away at distance

Fixes: QDS-10622
Change-Id: I39179e3927bfef5b0e9d99cbbd2ff16886b6dc38
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2023-09-12 15:32:34 +03:00
parent 1327a2c7ce
commit fb20ecff57
9 changed files with 127 additions and 77 deletions

View File

@@ -522,7 +522,7 @@ void Edit3DView::createResetColorAction(QAction *syncBackgroundColorAction)
Edit3DViewConfig::setColors(this, edit3dBgColorProperty, bgColors); Edit3DViewConfig::setColors(this, edit3dBgColorProperty, bgColors);
Edit3DViewConfig::saveColors(DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR, bgColors); Edit3DViewConfig::saveColors(DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR, bgColors);
QColor gridColor{0xaaaaaa}; QColor gridColor{0xcccccc};
Edit3DViewConfig::setColors(this, edit3dGridColorProperty, {gridColor}); Edit3DViewConfig::setColors(this, edit3dGridColorProperty, {gridColor});
Edit3DViewConfig::saveColors(DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, {gridColor}); Edit3DViewConfig::saveColors(DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, {gridColor});

View File

@@ -82,7 +82,7 @@ void DesignerSettings::fromSettings(QSettings *settings)
restoreValue(settings, DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET, true); restoreValue(settings, DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET, true);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR, restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_BACKGROUND_COLOR,
QStringList{"#222222", "#999999"}); QStringList{"#222222", "#999999"});
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, "#aaaaaa"); restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_GRID_COLOR, "#cccccc");
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ABSOLUTE, true); restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ABSOLUTE, true);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ENABLED, false); restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_ENABLED, false);
restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION, true); restoreValue(settings, DesignerSettingsKey::EDIT3DVIEW_SNAP_POSITION, true);

View File

@@ -54,5 +54,8 @@
<file>mockfiles/qt6/SceneView3D.qml</file> <file>mockfiles/qt6/SceneView3D.qml</file>
<file>mockfiles/qt6/SelectionBox.qml</file> <file>mockfiles/qt6/SelectionBox.qml</file>
<file>mockfiles/qt6/SpotLightHandle.qml</file> <file>mockfiles/qt6/SpotLightHandle.qml</file>
<file>mockfiles/qt6/GridMaterial.qml</file>
<file>mockfiles/shaders/gridmaterial.frag</file>
<file>mockfiles/shaders/gridmaterial.vert</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -26,7 +26,7 @@ Item {
property alias contentItem: contentItem property alias contentItem: contentItem
property color backgroundGradientColorStart: "#222222" property color backgroundGradientColorStart: "#222222"
property color backgroundGradientColorEnd: "#999999" property color backgroundGradientColorEnd: "#999999"
property color gridColor: "#aaaaaa" property color gridColor: "#cccccc"
property bool syncBackgroundColor: false property bool syncBackgroundColor: false
enum SelectionMode { Item, Group } enum SelectionMode { Item, Group }

View File

@@ -0,0 +1,22 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick3D
CustomMaterial {
property real alphaStartDepth: 500
property real alphaEndDepth: 40000
property real generalAlpha: 1
property color color: "#000000"
property real density: 50
property bool orthoMode: false
vertexShader: Qt.resolvedUrl("../shaders/gridmaterial.vert")
fragmentShader: Qt.resolvedUrl("../shaders/gridmaterial.frag")
sourceBlend: CustomMaterial.NoBlend
destinationBlend: CustomMaterial.NoBlend
shadingMode: CustomMaterial.Unshaded
depthDrawMode: Material.AlwaysDepthDraw
cullMode: Material.NoCulling
}

View File

@@ -8,38 +8,76 @@ import GridGeometry 1.0
Node { Node {
id: grid id: grid
property alias lines: gridGeometry.lines property alias gridColor: mainGridMaterial.color
property alias step: gridGeometry.step property double density: 2500 / (gridGeometry.step + gridGeometry.step * (1.0 - subGridMaterial.generalAlpha))
property alias subdivAlpha: subGridMaterial.opacity property bool orthoMode: false
property alias gridColor: mainGridMaterial.diffuseColor property double distance: 500
readonly property int minGridStep: 50
readonly property int maxGridStep: 32 * minGridStep
readonly property int gridArea: minGridStep * 512
// Step of the main lines of the grid, between those is always one subdiv line
property int gridStep: 100
// Minimum grid spacing in radians when viewed perpendicularly and lookAt is on origin.
// If spacing would go smaller, gridStep is doubled and line count halved.
// Note that spacing can stay smaller than this after maxGridStep has been reached.
readonly property double minGridRad: 0.1
eulerRotation.x: 90 eulerRotation.x: 90
function calcRad(step)
{
return Math.atan(step / distance)
}
onDistanceChanged: {
if (distance === 0)
return
// Calculate new grid step
let newStep = gridStep
let gridRad = calcRad(newStep)
while (gridRad < minGridRad && newStep < maxGridStep) {
newStep *= 2
if (newStep > maxGridStep)
newStep = maxGridStep
gridRad = calcRad(newStep)
}
while (gridRad > minGridRad * 2 && newStep > minGridStep) {
newStep /= 2
if (newStep < minGridStep)
newStep = minGridStep
gridRad = calcRad(newStep)
}
gridStep = newStep
subGridMaterial.generalAlpha = Math.min(1, 2 * (1 - (minGridRad / gridRad)))
}
// Note: Only one instance of HelperGrid is supported, as the geometry names are fixed // Note: Only one instance of HelperGrid is supported, as the geometry names are fixed
Model { // Main grid lines Model { // Main grid lines
readonly property bool _edit3dLocked: true // Make this non-pickable readonly property bool _edit3dLocked: true // Make this non-pickable
castsShadows: false
receivesShadows: false
geometry: GridGeometry { geometry: GridGeometry {
id: gridGeometry id: gridGeometry
lines: grid.gridArea / grid.gridStep
step: grid.gridStep
name: "3D Edit View Helper Grid" name: "3D Edit View Helper Grid"
} }
materials: [ materials: [
DefaultMaterial { GridMaterial {
id: mainGridMaterial id: mainGridMaterial
diffuseColor: "#aaaaaa" color: "#cccccc"
lighting: DefaultMaterial.NoLighting density: grid.density
cullMode: Material.NoCulling orthoMode: grid.orthoMode
} }
] ]
} }
Model { // Subdivision lines Model { // Subdivision lines
readonly property bool _edit3dLocked: true // Make this non-pickable readonly property bool _edit3dLocked: true // Make this non-pickable
castsShadows: false
receivesShadows: false
geometry: GridGeometry { geometry: GridGeometry {
lines: gridGeometry.lines lines: gridGeometry.lines
step: gridGeometry.step step: gridGeometry.step
@@ -48,19 +86,17 @@ Node {
} }
materials: [ materials: [
DefaultMaterial { GridMaterial {
id: subGridMaterial id: subGridMaterial
diffuseColor: mainGridMaterial.diffuseColor color: mainGridMaterial.color
lighting: DefaultMaterial.NoLighting density: grid.density
cullMode: Material.NoCulling orthoMode: grid.orthoMode
} }
] ]
} }
Model { // Z Axis Model { // Z Axis
readonly property bool _edit3dLocked: true // Make this non-pickable readonly property bool _edit3dLocked: true // Make this non-pickable
castsShadows: false
receivesShadows: false
geometry: GridGeometry { geometry: GridGeometry {
lines: gridGeometry.lines lines: gridGeometry.lines
step: gridGeometry.step step: gridGeometry.step
@@ -68,18 +104,16 @@ Node {
name: "3D Edit View Helper Grid Z Axis" name: "3D Edit View Helper Grid Z Axis"
} }
materials: [ materials: [
DefaultMaterial { GridMaterial {
id: vCenterLineMaterial id: vCenterLineMaterial
diffuseColor: "#00a1d2" color: "#00a1d2"
lighting: DefaultMaterial.NoLighting density: grid.density
cullMode: Material.NoCulling orthoMode: grid.orthoMode
} }
] ]
} }
Model { // X Axis Model { // X Axis
readonly property bool _edit3dLocked: true // Make this non-pickable readonly property bool _edit3dLocked: true // Make this non-pickable
castsShadows: false
receivesShadows: false
eulerRotation.z: 90 eulerRotation.z: 90
geometry: GridGeometry { geometry: GridGeometry {
lines: gridGeometry.lines lines: gridGeometry.lines
@@ -88,11 +122,11 @@ Node {
name: "3D Edit View Helper Grid X Axis" name: "3D Edit View Helper Grid X Axis"
} }
materials: [ materials: [
DefaultMaterial { GridMaterial {
id: hCenterLineMaterial id: hCenterLineMaterial
diffuseColor: "#cb211a" color: "#cb211a"
lighting: DefaultMaterial.NoLighting density: grid.density
cullMode: Material.NoCulling orthoMode: grid.orthoMode
} }
] ]
} }

View File

@@ -17,19 +17,6 @@ View3D {
property alias orthoCamera: sceneOrthoCamera property alias orthoCamera: sceneOrthoCamera
property vector3d cameraLookAt property vector3d cameraLookAt
// This is step of the main line of the grid, between those is always one subdiv line
property int gridStep: 100
property int minGridStep: 50
readonly property int maxGridStep: 32 * minGridStep
readonly property int gridArea: minGridStep * 128
// Minimum grid spacing in radians when viewed perpendicularly and lookAt is on origin.
// If spacing would go smaller, gridStep is doubled and line count halved.
// Note that spacing can stay smaller than this after maxGridStep has been reached.
readonly property double minGridRad: 0.1
// Measuring the distance from camera to lookAt plus the distance of lookAt from grid plane // Measuring the distance from camera to lookAt plus the distance of lookAt from grid plane
// gives a reasonable grid spacing in most cases while keeping spacing constant when // gives a reasonable grid spacing in most cases while keeping spacing constant when
// orbiting the camera. // orbiting the camera.
@@ -45,34 +32,6 @@ View3D {
camera: usePerspective ? scenePerspectiveCamera : sceneOrthoCamera camera: usePerspective ? scenePerspectiveCamera : sceneOrthoCamera
function calcRad()
{
return Math.atan(gridStep / cameraDistance)
}
onCameraDistanceChanged: {
if (cameraDistance === 0)
return
// Calculate new grid step
let gridRad = calcRad()
while (gridRad < minGridRad && gridStep < maxGridStep) {
gridStep *= 2
if (gridStep > maxGridStep)
gridStep = maxGridStep
gridRad = calcRad()
}
while (gridRad > minGridRad * 2 && gridStep > minGridStep) {
gridStep /= 2
if (gridStep < minGridStep)
gridStep = minGridStep
gridRad = calcRad()
}
// Calculate alpha for subgrid. Smaller the perceived spacing, more transparent subgrid is.
helperGrid.subdivAlpha = 2 * (1 - (minGridRad / gridRad))
}
environment: sceneEnv environment: sceneEnv
SceneEnvironment { SceneEnvironment {
id: sceneEnv id: sceneEnv
@@ -85,14 +44,14 @@ View3D {
HelperGrid { HelperGrid {
id: helperGrid id: helperGrid
lines: gridArea / gridStep orthoMode: !sceneView.usePerspective
step: gridStep distance: sceneView.cameraDistance
} }
PointLight { PointLight {
id: sceneLight id: sceneLight
position: usePerspective ? scenePerspectiveCamera.position position: sceneView.usePerspective ? scenePerspectiveCamera.position
: sceneOrthoCamera.position : sceneOrthoCamera.position
quadraticFade: 0 quadraticFade: 0
linearFade: 0 linearFade: 0
} }
@@ -115,7 +74,7 @@ View3D {
y: 600 y: 600
eulerRotation.x: -45 eulerRotation.x: -45
clipFar: 100000 clipFar: 100000
clipNear: -10000 clipNear: -100000
} }
} }
} }

View File

@@ -0,0 +1,22 @@
VARYING vec3 pos;
VARYING float worldPos;
void MAIN()
{
if (orthoMode) {
// No fadeout in orthographic mode
FRAGCOLOR = vec4(color.xyz, 1);
} else {
vec3 camDir = CAMERA_POSITION - worldPos;
vec3 camLevel = vec3(camDir.x, 0, camDir.z);
float depth;
depth = length(camDir);
float cosAngle = dot(normalize(camDir), normalize(camLevel));
float angleDepth = density * pow(cosAngle, 8);
float alpha = generalAlpha * clamp((1.0 - ((angleDepth * depth - alphaStartDepth) / (alphaEndDepth - alphaStartDepth))), 0, 1);
if (alpha > 0.01)
FRAGCOLOR = vec4(color.x * alpha, color.y * alpha, color.z * alpha, alpha);
else
discard;
}
}

View File

@@ -0,0 +1,10 @@
VARYING vec3 pos;
VARYING vec3 worldPos;
void MAIN()
{
pos = VERTEX;
vec4 pos4 = vec4(pos, 1.0);
POSITION = MODELVIEWPROJECTION_MATRIX * pos4;
worldPos = (MODEL_MATRIX * pos4).xyz;
}