Revert "[automated] Updating /docs due to commit 60b1951" and "Generalize scene description for automated testing (#9627)"
This reverts commite2dd47bf42. This reverts commit60b1951f90. renderdiff test breakage
This commit is contained in:
@@ -159,50 +159,37 @@ extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nGetViewerOptions(JNIEnv* env, jclass,
|
||||
jlong nativeObject, jobject result) {
|
||||
AutomationEngine* automation = (AutomationEngine*) nativeObject;
|
||||
const auto& settings = automation->getSettings();
|
||||
const auto& options = settings.viewer;
|
||||
auto options = automation->getViewerOptions();
|
||||
|
||||
const jclass klass = env->GetObjectClass(result);
|
||||
|
||||
const jfieldID cameraAperture = env->GetFieldID(klass, "cameraAperture", "F");
|
||||
const jfieldID cameraSpeed = env->GetFieldID(klass, "cameraSpeed", "F");
|
||||
const jfieldID cameraISO = env->GetFieldID(klass, "cameraISO", "F");
|
||||
const jfieldID cameraNear = env->GetFieldID(klass, "cameraNear", "F");
|
||||
const jfieldID cameraFar = env->GetFieldID(klass, "cameraFar", "F");
|
||||
const jfieldID groundShadowStrength = env->GetFieldID(klass, "groundShadowStrength", "F");
|
||||
const jfieldID groundPlaneEnabled = env->GetFieldID(klass, "groundPlaneEnabled", "Z");
|
||||
const jfieldID skyboxEnabled = env->GetFieldID(klass, "skyboxEnabled", "Z");
|
||||
const jfieldID cameraFocalLength = env->GetFieldID(klass, "cameraFocalLength", "F");
|
||||
const jfieldID cameraFocusDistance = env->GetFieldID(klass, "cameraFocusDistance", "F");
|
||||
const jfieldID autoScaleEnabled = env->GetFieldID(klass, "autoScaleEnabled", "Z");
|
||||
const jfieldID autoInstancingEnabled = env->GetFieldID(klass, "autoInstancingEnabled", "Z");
|
||||
|
||||
env->SetFloatField(result, cameraAperture, options.cameraAperture);
|
||||
env->SetFloatField(result, cameraSpeed, options.cameraSpeed);
|
||||
env->SetFloatField(result, cameraISO, options.cameraISO);
|
||||
env->SetFloatField(result, cameraNear, options.cameraNear);
|
||||
env->SetFloatField(result, cameraFar, options.cameraFar);
|
||||
env->SetFloatField(result, groundShadowStrength, options.groundShadowStrength);
|
||||
env->SetBooleanField(result, groundPlaneEnabled, options.groundPlaneEnabled);
|
||||
env->SetBooleanField(result, skyboxEnabled, options.skyboxEnabled);
|
||||
env->SetFloatField(result, cameraFocalLength, options.cameraFocalLength);
|
||||
env->SetFloatField(result, cameraFocusDistance, options.cameraFocusDistance);
|
||||
env->SetBooleanField(result, autoScaleEnabled, options.autoScaleEnabled);
|
||||
env->SetBooleanField(result, autoInstancingEnabled, options.autoInstancingEnabled);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nGetCameraSettings(JNIEnv* env, jclass,
|
||||
jlong nativeObject, jobject result) {
|
||||
AutomationEngine* automation = (AutomationEngine*) nativeObject;
|
||||
const auto& settings = automation->getSettings();
|
||||
const auto& camera = settings.camera;
|
||||
|
||||
const jclass klass = env->GetObjectClass(result);
|
||||
|
||||
const jfieldID aperture = env->GetFieldID(klass, "aperture", "F");
|
||||
const jfieldID shutterSpeed = env->GetFieldID(klass, "shutterSpeed", "F");
|
||||
const jfieldID sensitivity = env->GetFieldID(klass, "sensitivity", "F");
|
||||
const jfieldID near = env->GetFieldID(klass, "near", "F");
|
||||
const jfieldID far = env->GetFieldID(klass, "far", "F");
|
||||
const jfieldID focalLength = env->GetFieldID(klass, "focalLength", "F");
|
||||
const jfieldID focusDistance = env->GetFieldID(klass, "focusDistance", "F");
|
||||
|
||||
env->SetFloatField(result, aperture, camera.aperture);
|
||||
env->SetFloatField(result, shutterSpeed, camera.shutterSpeed);
|
||||
env->SetFloatField(result, sensitivity, camera.sensitivity);
|
||||
env->SetFloatField(result, near, camera.near);
|
||||
env->SetFloatField(result, far, camera.far);
|
||||
env->SetFloatField(result, focalLength, camera.focalLength);
|
||||
env->SetFloatField(result, focusDistance, camera.focusDistance);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nGetColorGrading(JNIEnv*, jclass,
|
||||
jlong nativeObject, jlong nativeEngine) {
|
||||
|
||||
@@ -94,23 +94,20 @@ public class AutomationEngine {
|
||||
* Allows remote control for the viewer.
|
||||
*/
|
||||
public static class ViewerOptions {
|
||||
public float cameraAperture = 16.0f;
|
||||
public float cameraSpeed = 125.0f;
|
||||
public float cameraISO = 100.0f;
|
||||
public float cameraNear = 0.1f;
|
||||
public float cameraFar = 100.0f;
|
||||
public float groundShadowStrength = 0.75f;
|
||||
public boolean groundPlaneEnabled = false;
|
||||
public boolean skyboxEnabled = true;
|
||||
public float cameraFocalLength = 28.0f;
|
||||
public float cameraFocusDistance = 0.0f;
|
||||
public boolean autoScaleEnabled = true;
|
||||
public boolean autoInstancingEnabled = false;
|
||||
}
|
||||
|
||||
public static class CameraSettings {
|
||||
public float aperture = 16.0f;
|
||||
public float shutterSpeed = 125.0f;
|
||||
public float sensitivity = 100.0f;
|
||||
public float near = 0.1f;
|
||||
public float far = 100.0f;
|
||||
public float focalLength = 28.0f;
|
||||
public float focusDistance = 10.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an automation engine from a JSON specification.
|
||||
*
|
||||
@@ -232,13 +229,6 @@ public class AutomationEngine {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public CameraSettings getCameraSettings() {
|
||||
CameraSettings result = new CameraSettings();
|
||||
nGetCameraSettings(mNativeObject, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a color grading object that corresponds to the latest settings.
|
||||
*
|
||||
@@ -290,7 +280,6 @@ public class AutomationEngine {
|
||||
long[] materials, long ibl, int sunlight, int[] assetLights, long lightManager,
|
||||
long scene, long renderer);
|
||||
private static native void nGetViewerOptions(long nativeObject, Object result);
|
||||
private static native void nGetCameraSettings(long nativeObject, Object result);
|
||||
private static native long nGetColorGrading(long nativeObject, long nativeEngine);
|
||||
private static native void nSignalBatchMode(long nativeObject);
|
||||
private static native void nStopRunning(long nativeObject);
|
||||
|
||||
@@ -389,9 +389,9 @@ class MainActivity : Activity() {
|
||||
viewerContent.assetLights = modelViewer.asset?.lightEntities
|
||||
automation.applySettings(modelViewer.engine, json, viewerContent)
|
||||
modelViewer.view.colorGrading = automation.getColorGrading(modelViewer.engine)
|
||||
modelViewer.cameraFocalLength = automation.cameraSettings.focalLength
|
||||
modelViewer.cameraNear = automation.cameraSettings.near
|
||||
modelViewer.cameraFar = automation.cameraSettings.far
|
||||
modelViewer.cameraFocalLength = automation.viewerOptions.cameraFocalLength
|
||||
modelViewer.cameraNear = automation.viewerOptions.cameraNear
|
||||
modelViewer.cameraFar = automation.viewerOptions.cameraFar
|
||||
updateRootTransform()
|
||||
}
|
||||
|
||||
|
||||
@@ -352,7 +352,7 @@ used to create the SPIR-V is not available.</p>
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../dup/viewer.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<a rel="next prefetch" href="../dup/uberz.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
@@ -366,7 +366,7 @@ used to create the SPIR-V is not available.</p>
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../dup/viewer.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<a rel="next prefetch" href="../dup/uberz.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
@@ -236,7 +236,7 @@ mapping should be specified as an <code>optional</code> feature of the ubershade
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../dup/viewer.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../dup/matdbg.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
@@ -250,7 +250,7 @@ mapping should be specified as an <code>optional</code> feature of the ubershade
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
<a rel="prev" href="../dup/viewer.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<a rel="prev" href="../dup/matdbg.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1,333 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>viewer - Filament</title>
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<link rel="shortcut icon" href="../favicon.png">
|
||||
<link rel="stylesheet" href="../css/variables.css">
|
||||
<link rel="stylesheet" href="../css/general.css">
|
||||
<link rel="stylesheet" href="../css/chrome.css">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
||||
<link rel="stylesheet" href="../fonts/fonts.css">
|
||||
|
||||
<!-- Highlight.js Stylesheets -->
|
||||
<link rel="stylesheet" href="../highlight.css">
|
||||
<link rel="stylesheet" href="../tomorrow-night.css">
|
||||
<link rel="stylesheet" href="../ayu-highlight.css">
|
||||
|
||||
<!-- Custom theme stylesheets -->
|
||||
|
||||
<!-- MathJax -->
|
||||
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
|
||||
<!-- Provide site root to javascript -->
|
||||
<script>
|
||||
var path_to_root = "../";
|
||||
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
|
||||
</script>
|
||||
<!-- Start loading toc.js asap -->
|
||||
<script src="../toc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="body-container">
|
||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||
<script>
|
||||
try {
|
||||
var theme = localStorage.getItem('mdbook-theme');
|
||||
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||||
|
||||
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||||
}
|
||||
|
||||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||||
}
|
||||
} catch (e) { }
|
||||
</script>
|
||||
|
||||
<!-- Set the theme before any content is loaded, prevents flash -->
|
||||
<script>
|
||||
var theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
const html = document.documentElement;
|
||||
html.classList.remove('light')
|
||||
html.classList.add(theme);
|
||||
html.classList.add("js");
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
||||
|
||||
<!-- Hide / unhide sidebar before it is displayed -->
|
||||
<script>
|
||||
var sidebar = null;
|
||||
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
||||
if (document.body.clientWidth >= 1080) {
|
||||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||
sidebar = sidebar || 'visible';
|
||||
} else {
|
||||
sidebar = 'hidden';
|
||||
}
|
||||
sidebar_toggle.checked = sidebar === 'visible';
|
||||
html.classList.remove('sidebar-visible');
|
||||
html.classList.add("sidebar-" + sidebar);
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<div style="display:flex;align-items:center;justify-content:center">
|
||||
<img class="flogo" src="../images/filament_logo_small.png"></img>
|
||||
</div>
|
||||
<!-- populated by js -->
|
||||
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
|
||||
<noscript>
|
||||
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
|
||||
</noscript>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
|
||||
<div class="sidebar-resize-indicator"></div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="page-wrapper" class="page-wrapper">
|
||||
|
||||
<div class="page">
|
||||
<div id="menu-bar-hover-placeholder"></div>
|
||||
<div id="menu-bar" class="menu-bar sticky">
|
||||
<div class="left-buttons">
|
||||
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||
<i class="fa fa-bars"></i>
|
||||
</label>
|
||||
<!-- Filament: disable themes because the markdeep part does not look good for dark themes -->
|
||||
<!--
|
||||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||||
<i class="fa fa-paint-brush"></i>
|
||||
</button>
|
||||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||||
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||||
</ul>
|
||||
-->
|
||||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h1 class="menu-title">Filament</h1>
|
||||
|
||||
<div class="right-buttons">
|
||||
<a href="https://github.com/google/filament" title="Git repository" aria-label="Git repository">
|
||||
<i id="git-repository-button" class="fa fa-github"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="search-wrapper" class="hidden">
|
||||
<form id="searchbar-outer" class="searchbar-outer">
|
||||
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||||
</form>
|
||||
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||||
<div id="searchresults-header" class="searchresults-header"></div>
|
||||
<ul id="searchresults">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||||
<script>
|
||||
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||||
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||||
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="content" class="content">
|
||||
<main>
|
||||
<h1 id="viewer-library"><a class="header" href="#viewer-library">Viewer Library</a></h1>
|
||||
<p>The <strong>Viewer Library</strong> (<code>libs/viewer</code>) provides a high-level abstraction for configuring and rendering Filament scenes. It is used by tools like <code>gltf_viewer</code> to load assets, manage settings, and drive the rendering loop.</p>
|
||||
<h2 id="features"><a class="header" href="#features">Features</a></h2>
|
||||
<ul>
|
||||
<li><strong>Settings Management</strong>: Centralized configuration for View, Camera, Lights, and Materials via the <code>Settings</code> struct.</li>
|
||||
<li><strong>JSON Serialization</strong>: Full support for loading and saving settings via JSON.</li>
|
||||
<li><strong>Automation</strong>: <code>AutomationEngine</code> allows scripting the viewer with a sequence of JSON-based test cases (batch mode).</li>
|
||||
<li><strong>GUI Integration</strong>: Built-in support for <code>imgui</code> via <code>ViewerGui</code> and <code>Settings</code> binding.</li>
|
||||
</ul>
|
||||
<h2 id="json-settings-schema"><a class="header" href="#json-settings-schema">JSON Settings Schema</a></h2>
|
||||
<p>The viewer settings can be configured using a JSON object. This is used for <code>gltf_viewer --settings</code> or in automation specs.</p>
|
||||
<h3 id="root-object"><a class="header" href="#root-object">Root Object</a></h3>
|
||||
<p>The root object contains the following categories:</p>
|
||||
<div class="table-wrapper"><table><thead><tr><th style="text-align: left">Key</th><th style="text-align: left">Type</th><th style="text-align: left">Description</th></tr></thead><tbody>
|
||||
<tr><td style="text-align: left"><code>view</code></td><td style="text-align: left">Object</td><td style="text-align: left">Post-processing and rendering quality settings.</td></tr>
|
||||
<tr><td style="text-align: left"><code>camera</code></td><td style="text-align: left">Object</td><td style="text-align: left"><strong>[NEW]</strong> Explicit camera control (pose, projection, exposure).</td></tr>
|
||||
<tr><td style="text-align: left"><code>lighting</code></td><td style="text-align: left">Object</td><td style="text-align: left"><strong>[NEW]</strong> Environment and dynamic light settings.</td></tr>
|
||||
<tr><td style="text-align: left"><code>viewer</code></td><td style="text-align: left">Object</td><td style="text-align: left">Global viewer options (skybox, background, scaling).</td></tr>
|
||||
<tr><td style="text-align: left"><code>animation</code></td><td style="text-align: left">Object</td><td style="text-align: left"><strong>[NEW]</strong> Animation playback control.</td></tr>
|
||||
<tr><td style="text-align: left"><code>material</code></td><td style="text-align: left">Object</td><td style="text-align: left">Material overrides.</td></tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
<hr />
|
||||
<h3 id="camera-settings-camera"><a class="header" href="#camera-settings-camera">Camera Settings (<code>camera</code>)</a></h3>
|
||||
<p>Allows explicit control over the camera. If <code>enabled</code> is false, the viewer uses its default orbit camera logic (auto-scaling/centering).</p>
|
||||
<pre><code class="language-json">"camera": {
|
||||
"enabled": true, // Must be true to use these explicit settings
|
||||
"projection": "PERSPECTIVE", // "PERSPECTIVE" or "ORTHO"
|
||||
"center": [0, 0, 0], // World-space look-at point
|
||||
"lookAt": [0, 0, -1], // World-space eye position (confusingly named 'lookAt' in internal legacy, often 'eye')
|
||||
"up": [0, 1, 0], // Up vector
|
||||
"near": 0.1, // Near plane
|
||||
"far": 100.0, // Far plane
|
||||
"focalLength": 28.0, // Focal length in mm (Perspective only)
|
||||
"fov": 0.0, // Field of view in degrees (overrides focalLength if > 0)
|
||||
"aperture": 16.0, // f-stop
|
||||
"shutterSpeed": 125.0, // 1/seconds
|
||||
"sensitivity": 100.0, // ISO
|
||||
"focusDistance": 10.0, // Focus distance in world units
|
||||
"scaling": [1.0, 1.0], // Custom projection matrix scaling (mostly for Ortho)
|
||||
"shift": [0.0, 0.0] // Custom projection matrix shift
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="lighting-settings-lighting"><a class="header" href="#lighting-settings-lighting">Lighting Settings (<code>lighting</code>)</a></h3>
|
||||
<p>Controls the Image Based Lighting (IBL), the Sun, and additional dynamic lights.</p>
|
||||
<pre><code class="language-json">"lighting": {
|
||||
"iblIntensity": 30000.0,
|
||||
"iblRotation": 0.0, // Rotation in degrees
|
||||
"enableSunlight": true,
|
||||
"enableShadows": true,
|
||||
"sunlight": { // **[NEW]** Nested sunlight properties
|
||||
"intensity": 100000.0,
|
||||
"color": [0.98, 0.92, 0.89],
|
||||
"direction": [0.6, -1.0, -0.8],
|
||||
"sunHaloSize": 10.0,
|
||||
"sunHaloFalloff": 80.0,
|
||||
"sunAngularRadius": 1.9,
|
||||
"castShadows": true,
|
||||
"shadowOptions": { // Per-light shadow options
|
||||
"mapSize": 1024,
|
||||
"shadowCascades": 1,
|
||||
"stable": false
|
||||
}
|
||||
},
|
||||
"lights": [ // **[NEW]** Array of custom lights
|
||||
{
|
||||
"type": "POINT", // "POINT", "SPOT", "FOCUSED_SPOT", "DIRECTIONAL", "SUN"
|
||||
"position": [0, 2, 0],
|
||||
"color": [1, 0, 0],
|
||||
"intensity": 5000.0,
|
||||
"falloff": 10.0,
|
||||
"castShadows": true,
|
||||
"shadowOptions": { "mapSize": 512 }
|
||||
},
|
||||
{
|
||||
"type": "SPOT",
|
||||
"position": [2, 5, 2],
|
||||
"direction": [0, -1, 0],
|
||||
"spotInner": 0.5, // Inner cone angle (radians)
|
||||
"spotOuter": 0.8 // Outer cone angle (radians)
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="view-settings-view"><a class="header" href="#view-settings-view">View Settings (<code>view</code>)</a></h3>
|
||||
<p>Standard Filament view settings.</p>
|
||||
<pre><code class="language-json">"view": {
|
||||
"postProcessingEnabled": true,
|
||||
"antiAliasing": "FXAA", // "NONE", "FXAA"
|
||||
"msaa": {
|
||||
"enabled": true,
|
||||
"sampleCount": 4
|
||||
},
|
||||
"ssao": { "enabled": true, ... },
|
||||
"bloom": { "enabled": true, ... },
|
||||
"dof": { "enabled": false, ... },
|
||||
"vignette": { "enabled": false, ... },
|
||||
"colorGrading": {
|
||||
"toneMapping": "ACES_LEGACY", // "LINEAR", "ACES", "FILMIC", "PBR_NEUTRAL", etc.
|
||||
"exposure": 0.0,
|
||||
"gamma": [1.0, 1.0, 1.0]
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="viewer-options-viewer"><a class="header" href="#viewer-options-viewer">Viewer Options (<code>viewer</code>)</a></h3>
|
||||
<p>General app-level settings.</p>
|
||||
<pre><code class="language-json">"viewer": {
|
||||
"skyboxEnabled": true,
|
||||
"backgroundColor": [0, 0, 0], // Used if skybox is disabled
|
||||
"autoScaleEnabled": true, // Fit model to unit cube
|
||||
"groundPlaneEnabled": false
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="animation-settings-animation"><a class="header" href="#animation-settings-animation">Animation Settings (<code>animation</code>)</a></h3>
|
||||
<p>Control glTF animation playback.</p>
|
||||
<pre><code class="language-json">"animation": {
|
||||
"enabled": true,
|
||||
"speed": 1.0,
|
||||
"time": -1.0 // If >= 0, forces animation to this specific time (seconds)
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
<a rel="prev" href="../dup/matdbg.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../dup/uberz.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
<a rel="prev" href="../dup/matdbg.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
|
||||
<a rel="next prefetch" href="../dup/uberz.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
window.playground_copyable = true;
|
||||
</script>
|
||||
|
||||
|
||||
<script src="../elasticlunr.min.js"></script>
|
||||
<script src="../mark.min.js"></script>
|
||||
<script src="../searcher.js"></script>
|
||||
|
||||
<script src="../clipboard.min.js"></script>
|
||||
<script src="../highlight.js"></script>
|
||||
<script src="../book.js"></script>
|
||||
|
||||
<!-- Custom JS scripts -->
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -49,9 +49,6 @@
|
||||
"libs/fgviewer/README.md": {
|
||||
"dest": "dup/fgviewer.md"
|
||||
},
|
||||
"libs/viewer/README.md": {
|
||||
"dest": "dup/viewer.md"
|
||||
},
|
||||
"ios/CocoaPods/README.md": {
|
||||
"dest": "release/cocoapods.md"
|
||||
},
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
- [gltfio](./dup/gltfio.md)
|
||||
- [iblprefilter](./dup/iblprefilter.md)
|
||||
- [matdbg](./dup/matdbg.md)
|
||||
- [viewer](./dup/viewer.md)
|
||||
- [uberz](./dup/uberz.md)
|
||||
- [Tools](./notes/tools.md)
|
||||
- [beamsplitter](./dup/beamsplitter.md)
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -274,7 +274,7 @@ const float kToastDelayDuration = 2.0f;
|
||||
self.modelView.engine, message->buffer, message->bufferByteCount, content);
|
||||
ColorGrading* const colorGrading = _automation->getColorGrading(self.modelView.engine);
|
||||
self.modelView.view->setColorGrading(colorGrading);
|
||||
self.modelView.cameraFocalLength = _automation->getSettings().camera.focalLength;
|
||||
self.modelView.cameraFocalLength = _automation->getViewerOptions().cameraFocalLength;
|
||||
}
|
||||
|
||||
- (void)loadGlb:(viewer::ReceivedMessage const*)message {
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
# Viewer Library
|
||||
|
||||
The **Viewer Library** (`libs/viewer`) provides a high-level abstraction for configuring and rendering Filament scenes. It is used by tools like `gltf_viewer` to load assets, manage settings, and drive the rendering loop.
|
||||
|
||||
## Features
|
||||
|
||||
- **Settings Management**: Centralized configuration for View, Camera, Lights, and Materials via the `Settings` struct.
|
||||
- **JSON Serialization**: Full support for loading and saving settings via JSON.
|
||||
- **Automation**: `AutomationEngine` allows scripting the viewer with a sequence of JSON-based test cases (batch mode).
|
||||
- **GUI Integration**: Built-in support for `imgui` via `ViewerGui` and `Settings` binding.
|
||||
|
||||
## JSON Settings Schema
|
||||
|
||||
The viewer settings can be configured using a JSON object. This is used for `gltf_viewer --settings` or in automation specs.
|
||||
|
||||
### Root Object
|
||||
|
||||
The root object contains the following categories:
|
||||
|
||||
| Key | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `view` | Object | Post-processing and rendering quality settings. |
|
||||
| `camera` | Object | **[NEW]** Explicit camera control (pose, projection, exposure). |
|
||||
| `lighting` | Object | **[NEW]** Environment and dynamic light settings. |
|
||||
| `viewer` | Object | Global viewer options (skybox, background, scaling). |
|
||||
| `animation` | Object | **[NEW]** Animation playback control. |
|
||||
| `material` | Object | Material overrides. |
|
||||
|
||||
---
|
||||
|
||||
### Camera Settings (`camera`)
|
||||
|
||||
Allows explicit control over the camera. If `enabled` is false, the viewer uses its default orbit camera logic (auto-scaling/centering).
|
||||
|
||||
```json
|
||||
"camera": {
|
||||
"enabled": true, // Must be true to use these explicit settings
|
||||
"projection": "PERSPECTIVE", // "PERSPECTIVE" or "ORTHO"
|
||||
"center": [0, 0, 0], // World-space look-at point
|
||||
"lookAt": [0, 0, -1], // World-space eye position (confusingly named 'lookAt' in internal legacy, often 'eye')
|
||||
"up": [0, 1, 0], // Up vector
|
||||
"near": 0.1, // Near plane
|
||||
"far": 100.0, // Far plane
|
||||
"focalLength": 28.0, // Focal length in mm (Perspective only)
|
||||
"fov": 0.0, // Field of view in degrees (overrides focalLength if > 0)
|
||||
"aperture": 16.0, // f-stop
|
||||
"shutterSpeed": 125.0, // 1/seconds
|
||||
"sensitivity": 100.0, // ISO
|
||||
"focusDistance": 10.0, // Focus distance in world units
|
||||
"scaling": [1.0, 1.0], // Custom projection matrix scaling (mostly for Ortho)
|
||||
"shift": [0.0, 0.0] // Custom projection matrix shift
|
||||
}
|
||||
```
|
||||
|
||||
### Lighting Settings (`lighting`)
|
||||
|
||||
Controls the Image Based Lighting (IBL), the Sun, and additional dynamic lights.
|
||||
|
||||
```json
|
||||
"lighting": {
|
||||
"iblIntensity": 30000.0,
|
||||
"iblRotation": 0.0, // Rotation in degrees
|
||||
"enableSunlight": true,
|
||||
"enableShadows": true,
|
||||
"sunlight": { // **[NEW]** Nested sunlight properties
|
||||
"intensity": 100000.0,
|
||||
"color": [0.98, 0.92, 0.89],
|
||||
"direction": [0.6, -1.0, -0.8],
|
||||
"sunHaloSize": 10.0,
|
||||
"sunHaloFalloff": 80.0,
|
||||
"sunAngularRadius": 1.9,
|
||||
"castShadows": true,
|
||||
"shadowOptions": { // Per-light shadow options
|
||||
"mapSize": 1024,
|
||||
"shadowCascades": 1,
|
||||
"stable": false
|
||||
}
|
||||
},
|
||||
"lights": [ // **[NEW]** Array of custom lights
|
||||
{
|
||||
"type": "POINT", // "POINT", "SPOT", "FOCUSED_SPOT", "DIRECTIONAL", "SUN"
|
||||
"position": [0, 2, 0],
|
||||
"color": [1, 0, 0],
|
||||
"intensity": 5000.0,
|
||||
"falloff": 10.0,
|
||||
"castShadows": true,
|
||||
"shadowOptions": { "mapSize": 512 }
|
||||
},
|
||||
{
|
||||
"type": "SPOT",
|
||||
"position": [2, 5, 2],
|
||||
"direction": [0, -1, 0],
|
||||
"spotInner": 0.5, // Inner cone angle (radians)
|
||||
"spotOuter": 0.8 // Outer cone angle (radians)
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### View Settings (`view`)
|
||||
|
||||
Standard Filament view settings.
|
||||
|
||||
```json
|
||||
"view": {
|
||||
"postProcessingEnabled": true,
|
||||
"antiAliasing": "FXAA", // "NONE", "FXAA"
|
||||
"msaa": {
|
||||
"enabled": true,
|
||||
"sampleCount": 4
|
||||
},
|
||||
"ssao": { "enabled": true, ... },
|
||||
"bloom": { "enabled": true, ... },
|
||||
"dof": { "enabled": false, ... },
|
||||
"vignette": { "enabled": false, ... },
|
||||
"colorGrading": {
|
||||
"toneMapping": "ACES_LEGACY", // "LINEAR", "ACES", "FILMIC", "PBR_NEUTRAL", etc.
|
||||
"exposure": 0.0,
|
||||
"gamma": [1.0, 1.0, 1.0]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Viewer Options (`viewer`)
|
||||
|
||||
General app-level settings.
|
||||
|
||||
```json
|
||||
"viewer": {
|
||||
"skyboxEnabled": true,
|
||||
"backgroundColor": [0, 0, 0], // Used if skybox is disabled
|
||||
"autoScaleEnabled": true, // Fit model to unit cube
|
||||
"groundPlaneEnabled": false
|
||||
}
|
||||
```
|
||||
|
||||
### Animation Settings (`animation`)
|
||||
|
||||
Control glTF animation playback.
|
||||
|
||||
```json
|
||||
"animation": {
|
||||
"enabled": true,
|
||||
"speed": 1.0,
|
||||
"time": -1.0 // If >= 0, forces animation to this specific time (seconds)
|
||||
}
|
||||
```
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
Scene* scene;
|
||||
IndirectLight* indirectLight;
|
||||
utils::Entity sunlight;
|
||||
const utils::Entity* assetLights;
|
||||
utils::Entity* assetLights;
|
||||
size_t assetLightCount;
|
||||
};
|
||||
|
||||
@@ -211,11 +211,6 @@ public:
|
||||
*/
|
||||
ViewerOptions getViewerOptions() const;
|
||||
|
||||
/**
|
||||
* Gets the current full settings object.
|
||||
*/
|
||||
const Settings& getSettings() const { return *mSettings; }
|
||||
|
||||
/**
|
||||
* Signals that batch mode can begin. Call this after all meshes and textures finish loading.
|
||||
*/
|
||||
@@ -269,10 +264,6 @@ private:
|
||||
Engine* mColorGradingEngine = nullptr;
|
||||
ColorGrading* mColorGrading = nullptr;
|
||||
ColorGradingSettings mColorGradingSettings = {};
|
||||
std::vector<utils::Entity> mCustomLights;
|
||||
|
||||
void updateCustomLights(Engine* engine, const std::vector<LightDefinition>& lights,
|
||||
Scene* scene);
|
||||
|
||||
size_t mCurrentTest;
|
||||
float mElapsedTime;
|
||||
|
||||
@@ -17,13 +17,11 @@
|
||||
#ifndef VIEWER_SETTINGS_H
|
||||
#define VIEWER_SETTINGS_H
|
||||
|
||||
#include <filament/Camera.h>
|
||||
#include <filament/ColorGrading.h>
|
||||
#include <filament/ColorSpace.h>
|
||||
#include <filament/IndirectLight.h>
|
||||
#include <filament/LightManager.h>
|
||||
#include <filament/MaterialInstance.h>
|
||||
#include <filament/Renderer.h>
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/View.h>
|
||||
|
||||
@@ -46,11 +44,6 @@ class Renderer;
|
||||
|
||||
namespace viewer {
|
||||
|
||||
struct ColorGradingSettings;
|
||||
struct DynamicLightingSettings;
|
||||
struct MaterialSettings;
|
||||
struct Settings;
|
||||
struct ViewSettings;
|
||||
struct ColorGradingSettings;
|
||||
struct DynamicLightingSettings;
|
||||
struct MaterialSettings;
|
||||
@@ -59,10 +52,6 @@ struct ViewSettings;
|
||||
struct LightSettings;
|
||||
struct ViewerOptions;
|
||||
struct DebugOptions;
|
||||
struct CameraSettings;
|
||||
struct AnimationSettings;
|
||||
struct RenderSettings;
|
||||
struct LightDefinition;
|
||||
|
||||
enum class ToneMapping : uint8_t {
|
||||
LINEAR = 0,
|
||||
@@ -93,8 +82,6 @@ using VsmShadowOptions = filament::View::VsmShadowOptions;
|
||||
using GuardBandOptions = filament::View::GuardBandOptions;
|
||||
using StereoscopicOptions = filament::View::StereoscopicOptions;
|
||||
using LightManager = filament::LightManager;
|
||||
using CameraProjection = filament::Camera::Projection;
|
||||
using BlendMode = filament::BlendMode;
|
||||
|
||||
// These functions push all editable property values to their respective Filament objects.
|
||||
void applySettings(Engine* engine, const ViewSettings& settings, View* dest);
|
||||
@@ -105,8 +92,6 @@ void applySettings(Engine* engine, const ViewerOptions& settings, Camera* camera
|
||||
Renderer* renderer);
|
||||
void applySettings(Engine* engine, const DebugOptions& settings,
|
||||
Renderer* renderer);
|
||||
void applySettings(Engine* engine, const CameraSettings& settings, Camera* camera,
|
||||
double aspectRatio = 0.0);
|
||||
|
||||
// Creates a new ColorGrading object based on the given settings.
|
||||
UTILS_PUBLIC
|
||||
@@ -219,9 +204,6 @@ struct ViewSettings {
|
||||
ColorGradingSettings colorGrading;
|
||||
DynamicLightingSettings dynamicLighting;
|
||||
FogSettings fogSettings;
|
||||
BlendMode blendMode = BlendMode::OPAQUE;
|
||||
bool stencilBufferEnabled = false;
|
||||
uint8_t visibleLayers = 0x01;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -235,68 +217,35 @@ struct MaterialSettings {
|
||||
MaterialProperty<math::float4> float4[MAX_COUNT];
|
||||
};
|
||||
|
||||
struct LightDefinition {
|
||||
LightManager::Type type = LightManager::Type::POINT;
|
||||
math::float3 position = { 0.0f, 0.0f, 0.0f };
|
||||
math::float3 direction = { 0.0f, -1.0f, 0.0f };
|
||||
math::float3 color = { 1.0f, 1.0f, 1.0f };
|
||||
float intensity = 0.0f;
|
||||
float falloff = 0.0f;
|
||||
float spotInner = 0.0f;
|
||||
float spotOuter = 0.0f;
|
||||
float sunHaloSize = 10.0f;
|
||||
float sunHaloFalloff = 80.0f;
|
||||
float sunAngularRadius = 1.9f;
|
||||
bool castShadows = false;
|
||||
LightManager::ShadowOptions shadowOptions;
|
||||
};
|
||||
|
||||
struct LightSettings {
|
||||
bool enableShadows = true; // Global toggle to enabling/disabling shadows
|
||||
bool enableShadows = true;
|
||||
bool enableSunlight = true;
|
||||
LightManager::ShadowOptions shadowOptions;
|
||||
SoftShadowOptions softShadowOptions;
|
||||
float sunlightIntensity = 100000.0f;
|
||||
float sunlightHaloSize = 10.0f;
|
||||
float sunlightHaloFalloff = 80.0f;
|
||||
float sunlightAngularRadius = 1.9f;
|
||||
math::float3 sunlightDirection = {0.6, -1.0, -0.8};
|
||||
math::float3 sunlightColor = filament::Color::toLinear<filament::ACCURATE>({ 0.98, 0.92, 0.89});
|
||||
float iblIntensity = 30000.0f;
|
||||
float iblRotation = 0.0f;
|
||||
LightDefinition sunlight;
|
||||
std::vector<LightDefinition> lights;
|
||||
};
|
||||
|
||||
struct CameraSettings {
|
||||
math::float3 center = { 0.0f, 0.0f, 0.0f };
|
||||
math::float3 lookAt = { 0.0f, 0.0f, -1.0f };
|
||||
math::float3 up = { 0.0f, 1.0f, 0.0f };
|
||||
float horizontalFov = 0.0f; // degrees, if 0 use focal length
|
||||
float near = 0.1f;
|
||||
float far = 100.0f;
|
||||
float focalLength = 28.0f; // mm, if 0 use fov
|
||||
float aperture = 16.0f;
|
||||
float shutterSpeed = 125.0f;
|
||||
float sensitivity = 100.0f; // ISO
|
||||
float focusDistance = 10.0f;
|
||||
float eyeOcularDistance = 0.0f;
|
||||
float eyeToeIn = 0.0f;
|
||||
CameraProjection projection = CameraProjection::PERSPECTIVE;
|
||||
bool enabled = false;
|
||||
math::float2 scaling = { 1.0, 1.0 };
|
||||
math::float2 shift = { 0.0, 0.0 };
|
||||
};
|
||||
|
||||
struct AnimationSettings {
|
||||
bool enabled = false;
|
||||
float time = -1.0f;
|
||||
float speed = 1.0f;
|
||||
};
|
||||
|
||||
struct RenderSettings {
|
||||
Renderer::ClearOptions clearOptions = {};
|
||||
Renderer::FrameRateOptions frameRateOptions = {};
|
||||
};
|
||||
|
||||
struct ViewerOptions {
|
||||
float cameraAperture = 16.0f;
|
||||
float cameraSpeed = 125.0f;
|
||||
float cameraISO = 100.0f;
|
||||
float cameraNear = 0.1f;
|
||||
float cameraFar = 100.0f;
|
||||
float cameraEyeOcularDistance = 0.0f;
|
||||
float cameraEyeToeIn = 0.0f;
|
||||
float groundShadowStrength = 0.75f;
|
||||
bool groundPlaneEnabled = false;
|
||||
bool skyboxEnabled = true;
|
||||
sRGBColor backgroundColor = { 0.0f };
|
||||
float cameraFocalLength = 28.0f;
|
||||
float cameraFocusDistance = 10.0f;
|
||||
bool autoScaleEnabled = true;
|
||||
bool autoInstancingEnabled = false;
|
||||
};
|
||||
@@ -310,9 +259,6 @@ struct Settings {
|
||||
MaterialSettings material;
|
||||
LightSettings lighting;
|
||||
ViewerOptions viewer;
|
||||
CameraSettings camera;
|
||||
AnimationSettings animation;
|
||||
RenderSettings render;
|
||||
DebugOptions debug;
|
||||
};
|
||||
|
||||
|
||||
@@ -231,9 +231,6 @@ public:
|
||||
|
||||
int getCurrentCamera() const { return mCurrentCamera; }
|
||||
|
||||
utils::Entity getSunlight() const { return mSunlight; }
|
||||
IndirectLight* getIndirectLight() const { return mIndirectLight; }
|
||||
|
||||
private:
|
||||
using SceneMask = gltfio::NodeManager::SceneMask;
|
||||
|
||||
|
||||
14
libs/viewer/schemas/README.md
Normal file
14
libs/viewer/schemas/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
The schema in this folder can be used to enable autocomplete and help features when authoring
|
||||
automation specs in your favorite text editor. For example, for Visual Studio Code you can add the
|
||||
following to `.vscode/settings`:
|
||||
|
||||
```
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": [
|
||||
"libs/viewer/tests/basic.json"
|
||||
],
|
||||
"url": "./libs/viewer/schemas/automation.json"
|
||||
}
|
||||
]
|
||||
```
|
||||
43
libs/viewer/schemas/automation.json
Normal file
43
libs/viewer/schemas/automation.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://github.com/google/filament/automation.json",
|
||||
"title": "Spec",
|
||||
"description": "A specification that generates a set of Settings objects",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Prefix used for screenshots and exported settings"
|
||||
},
|
||||
"base": {
|
||||
"type": "object",
|
||||
"description": "The base configuration to which permutations are applied",
|
||||
"patternProperties": {
|
||||
"[A-Z0-9_\\.]+": { "type": ["number", "boolean", "string" ] }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"permute": {
|
||||
"type": "object",
|
||||
"description": "Specifies a cross-product of property values",
|
||||
"patternProperties": {
|
||||
"[A-Z0-9_\\.]+": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": true,
|
||||
"oneOf": [
|
||||
{ "items": { "type": "number" } },
|
||||
{ "items": { "type": "string" } },
|
||||
{ "items": { "type": "boolean" } }
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"minItems": 1
|
||||
}
|
||||
@@ -20,14 +20,9 @@
|
||||
|
||||
#include <filament/Camera.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/LightManager.h>
|
||||
#include <filament/Renderer.h>
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/TransformManager.h>
|
||||
#include <filament/Viewport.h>
|
||||
|
||||
#include <utils/EntityManager.h>
|
||||
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
|
||||
#include <utils/Log.h>
|
||||
@@ -203,21 +198,10 @@ void AutomationEngine::applySettings(Engine* engine, const char* json, size_t js
|
||||
}
|
||||
viewer::applySettings(engine, mSettings->lighting, content.indirectLight, content.sunlight,
|
||||
content.assetLights, content.assetLightCount, content.lightManager, content.scene, content.view);
|
||||
updateCustomLights(engine, mSettings->lighting.lights, content.scene);
|
||||
|
||||
Camera* camera = &content.view->getCamera();
|
||||
Skybox* skybox = content.scene->getSkybox();
|
||||
viewer::applySettings(engine, mSettings->viewer, camera, skybox, content.renderer);
|
||||
viewer::applySettings(engine, mSettings->debug, content.renderer);
|
||||
|
||||
// Apply CameraSettings
|
||||
double const aspect = (double) content.view->getViewport().width /
|
||||
(double) content.view->getViewport().height;
|
||||
viewer::applySettings(engine, mSettings->camera, camera, aspect);
|
||||
|
||||
// Apply RenderSettings
|
||||
content.renderer->setClearOptions(mSettings->render.clearOptions);
|
||||
content.renderer->setFrameRateOptions(mSettings->render.frameRateOptions);
|
||||
}
|
||||
|
||||
ColorGrading* AutomationEngine::getColorGrading(Engine* engine) {
|
||||
@@ -233,6 +217,14 @@ ColorGrading* AutomationEngine::getColorGrading(Engine* engine) {
|
||||
}
|
||||
|
||||
ViewerOptions AutomationEngine::getViewerOptions() const {
|
||||
ViewerOptions options = mSettings->viewer;
|
||||
const auto dofOptions = mSettings->view.dof;
|
||||
if (dofOptions.enabled) {
|
||||
options.cameraFocalLength = Camera::computeEffectiveFocalLength(
|
||||
options.cameraFocalLength / 1000.0,
|
||||
std::max(0.1f, options.cameraFocusDistance)) * 1000.0;
|
||||
|
||||
}
|
||||
return mSettings->viewer;
|
||||
}
|
||||
|
||||
@@ -245,20 +237,6 @@ void AutomationEngine::tick(Engine* engine, const ViewerContent& content, float
|
||||
for (size_t i = 0; i < content.materialCount; i++) {
|
||||
viewer::applySettings(engine, mSettings->material, content.materials[i]);
|
||||
}
|
||||
viewer::applySettings(engine, mSettings->lighting, content.indirectLight, content.sunlight,
|
||||
content.assetLights, content.assetLightCount, content.lightManager, content.scene,
|
||||
content.view);
|
||||
updateCustomLights(engine, mSettings->lighting.lights, content.scene);
|
||||
|
||||
// Apply CameraSettings
|
||||
double const aspect = (double) content.view->getViewport().width /
|
||||
(double) content.view->getViewport().height;
|
||||
viewer::applySettings(engine, mSettings->camera, &content.view->getCamera(), aspect);
|
||||
|
||||
// Apply RenderSettings
|
||||
content.renderer->setClearOptions(mSettings->render.clearOptions);
|
||||
content.renderer->setFrameRateOptions(mSettings->render.frameRateOptions);
|
||||
|
||||
if (mOptions.verbose) {
|
||||
utils::slog.i << "Running test " << mCurrentTest << utils::io::endl;
|
||||
}
|
||||
@@ -285,7 +263,7 @@ void AutomationEngine::tick(Engine* engine, const ViewerContent& content, float
|
||||
|
||||
const bool isLastTest = mCurrentTest == mSpec->size() - 1;
|
||||
|
||||
int const digits = (int) log10((double) mSpec->size()) + 1;
|
||||
const int digits = (int) log10 ((double) mSpec->size()) + 1;
|
||||
std::ostringstream stringStream;
|
||||
stringStream << mSpec->getName(mCurrentTest)
|
||||
<< std::setfill('0') << std::setw(digits) << mCurrentTest;
|
||||
@@ -318,51 +296,5 @@ const char* AutomationEngine::getStatusMessage() const {
|
||||
return gStatus.c_str();
|
||||
}
|
||||
|
||||
void AutomationEngine::updateCustomLights(Engine* engine,
|
||||
const std::vector<LightDefinition>& lights, Scene* scene) {
|
||||
auto& em = utils::EntityManager::get();
|
||||
LightManager* lm = &engine->getLightManager();
|
||||
|
||||
// Destroy old lights
|
||||
for (auto entity: mCustomLights) {
|
||||
lm->destroy(entity);
|
||||
scene->remove(entity);
|
||||
em.destroy(entity);
|
||||
}
|
||||
mCustomLights.clear();
|
||||
|
||||
if (lights.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new lights
|
||||
mCustomLights.resize(lights.size());
|
||||
em.create(mCustomLights.size(), mCustomLights.data());
|
||||
|
||||
for (size_t i = 0; i < lights.size(); ++i) {
|
||||
const auto& def = lights[i];
|
||||
LightManager::Builder builder(def.type);
|
||||
builder.color(def.color)
|
||||
.intensity(def.intensity)
|
||||
.position(def.position)
|
||||
.direction(def.direction)
|
||||
.falloff(def.falloff)
|
||||
.spotLightCone(def.spotInner, def.spotOuter)
|
||||
.castShadows(def.castShadows)
|
||||
.sunHaloSize(def.sunHaloSize)
|
||||
.sunHaloFalloff(def.sunHaloFalloff)
|
||||
.sunAngularRadius(def.sunAngularRadius)
|
||||
.build(*engine, mCustomLights[i]);
|
||||
|
||||
// Shadow options must be set on the instance after creation
|
||||
auto instance = lm->getInstance(mCustomLights[i]);
|
||||
if (instance) {
|
||||
lm->setShadowOptions(instance, def.shadowOptions);
|
||||
}
|
||||
|
||||
scene->addEntity(mCustomLights[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace viewer
|
||||
} // namespace filament
|
||||
|
||||
@@ -47,7 +47,7 @@ static const char* DEFAULT_AUTOMATION = R"TXT([
|
||||
{
|
||||
"name": "vieweropts",
|
||||
"base": {
|
||||
"camera.focusDistance": 0.1
|
||||
"viewer.cameraFocusDistance": 0.1
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -59,7 +59,7 @@ static const char* DEFAULT_AUTOMATION = R"TXT([
|
||||
"view.taa.enabled": [false, true],
|
||||
"view.antiAliasing": ["NONE", "FXAA"],
|
||||
"view.ssao.enabled": [false, true],
|
||||
"view.screenSpaceReflections.enabled": [false, true],
|
||||
"view.screenSpaceReflections.enabled": [false, true]
|
||||
"view.bloom.enabled": [false, true],
|
||||
"view.dof.enabled": [false, true],
|
||||
"view.guardBand.enabled": [false, true]
|
||||
@@ -89,20 +89,10 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, std::str
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
static int skip(jsmntok_t const* tokens, int i) {
|
||||
int size = tokens[i].size;
|
||||
i++;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
i = skip(tokens, i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int parseBaseSettings(jsmntok_t const* tokens, int i, const char* jsonChunk, Settings* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
// Current token is Key
|
||||
for (int j = 0; j < size; ++j, i += 2) {
|
||||
std::stringstream dk(STR(tokens[i], jsonChunk));
|
||||
std::string token;
|
||||
std::string prefix;
|
||||
@@ -113,8 +103,6 @@ static int parseBaseSettings(jsmntok_t const* tokens, int i, const char* jsonChu
|
||||
prefix += "{ \"" + token + "\": ";
|
||||
depth++;
|
||||
}
|
||||
|
||||
// Next token is Value
|
||||
std::string json = prefix + STR(tokens[i + 1], jsonChunk);
|
||||
for (int d = 0; d < depth; d++) { json += " } "; }
|
||||
if (VERBOSE) {
|
||||
@@ -124,11 +112,6 @@ static int parseBaseSettings(jsmntok_t const* tokens, int i, const char* jsonChu
|
||||
// Now that we have a complete JSON string, apply this property change.
|
||||
JsonSerializer serializer;
|
||||
serializer.readJson(json.c_str(), json.size(), out);
|
||||
|
||||
// Advance past Key
|
||||
i++;
|
||||
// Advance past Value (recursively)
|
||||
i = skip(tokens, i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
using namespace utils;
|
||||
|
||||
namespace filament::viewer {
|
||||
|
||||
std::string_view to_string(color::ColorSpace const& colorspace) noexcept {
|
||||
using namespace color;
|
||||
if (colorspace == Rec709-Linear-D65) {
|
||||
@@ -68,7 +67,6 @@ int parse(jsmntok_t const* tokens, int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
using CGQL = filament::ColorGrading::QualityLevel;
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, CGQL* out) {
|
||||
@@ -108,35 +106,6 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, color::C
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, CameraProjection* out) {
|
||||
if (0 == compare(tokens[i], jsonChunk, "PERSPECTIVE")) {
|
||||
*out = CameraProjection::PERSPECTIVE;
|
||||
} else if (0 == compare(tokens[i], jsonChunk, "ORTHO")) {
|
||||
*out = CameraProjection::ORTHO;
|
||||
} else {
|
||||
slog.w << "Invalid CameraProjection: '" << STR(tokens[i], jsonChunk) << "'" << io::endl;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, LightManager::Type* out) {
|
||||
if (0 == compare(tokens[i], jsonChunk, "SUN")) {
|
||||
*out = LightManager::Type::SUN;
|
||||
} else if (0 == compare(tokens[i], jsonChunk, "DIRECTIONAL")) {
|
||||
*out = LightManager::Type::DIRECTIONAL;
|
||||
} else if (0 == compare(tokens[i], jsonChunk, "POINT")) {
|
||||
*out = LightManager::Type::POINT;
|
||||
} else if (0 == compare(tokens[i], jsonChunk, "FOCUSED_SPOT")) {
|
||||
*out = LightManager::Type::FOCUSED_SPOT;
|
||||
} else if (0 == compare(tokens[i], jsonChunk, "SPOT")) {
|
||||
*out = LightManager::Type::SPOT;
|
||||
} else {
|
||||
slog.w << "Invalid Light Type: '" << STR(tokens[i], jsonChunk) << "'" << io::endl;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, GenericToneMapperSettings* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int size = tokens[i++].size;
|
||||
@@ -336,12 +305,6 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, ViewSett
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->postProcessingEnabled);
|
||||
} else if (compare(tok, jsonChunk, "stereoscopicOptions") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->stereoscopicOptions);
|
||||
} else if (compare(tok, jsonChunk, "blendMode") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->blendMode);
|
||||
} else if (compare(tok, jsonChunk, "stencilBufferEnabled") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->stencilBufferEnabled);
|
||||
} else if (compare(tok, jsonChunk, "visibleLayers") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->visibleLayers);
|
||||
} else {
|
||||
slog.w << "Invalid view setting key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
@@ -491,220 +454,9 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk,
|
||||
return i;
|
||||
}
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, LightDefinition* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "type") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->type);
|
||||
} else if (compare(tok, jsonChunk, "position") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->position);
|
||||
} else if (compare(tok, jsonChunk, "direction") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->direction);
|
||||
} else if (compare(tok, jsonChunk, "color") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->color);
|
||||
} else if (compare(tok, jsonChunk, "intensity") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->intensity);
|
||||
} else if (compare(tok, jsonChunk, "falloff") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->falloff);
|
||||
} else if (compare(tok, jsonChunk, "spotInner") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->spotInner);
|
||||
} else if (compare(tok, jsonChunk, "spotOuter") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->spotOuter);
|
||||
} else if (compare(tok, jsonChunk, "spotOuter") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->spotOuter);
|
||||
} else if (compare(tok, jsonChunk, "sunHaloSize") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunHaloSize);
|
||||
} else if (compare(tok, jsonChunk, "sunHaloFalloff") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunHaloFalloff);
|
||||
} else if (compare(tok, jsonChunk, "sunAngularRadius") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunAngularRadius);
|
||||
} else if (compare(tok, jsonChunk, "castShadows") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->castShadows);
|
||||
} else if (compare(tok, jsonChunk, "shadowOptions") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->shadowOptions);
|
||||
} else {
|
||||
slog.w << "Invalid light definition key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
}
|
||||
if (i < 0) {
|
||||
slog.e << "Invalid light definition value: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk,
|
||||
std::vector<LightDefinition>* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
|
||||
int size = tokens[i++].size;
|
||||
out->resize(size);
|
||||
for (int j = 0; j < size; ++j) {
|
||||
i = parse(tokens, i, jsonChunk, &(*out)[j]);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, CameraSettings* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "center") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->center);
|
||||
} else if (compare(tok, jsonChunk, "lookAt") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->lookAt);
|
||||
} else if (compare(tok, jsonChunk, "up") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->up);
|
||||
} else if (compare(tok, jsonChunk, "horizontalFov") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->horizontalFov);
|
||||
} else if (compare(tok, jsonChunk, "near") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->near);
|
||||
} else if (compare(tok, jsonChunk, "far") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->far);
|
||||
} else if (compare(tok, jsonChunk, "focalLength") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->focalLength);
|
||||
} else if (compare(tok, jsonChunk, "projection") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->projection);
|
||||
} else if (compare(tok, jsonChunk, "enabled") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->enabled);
|
||||
} else if (compare(tok, jsonChunk, "scaling") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->scaling);
|
||||
} else if (compare(tok, jsonChunk, "shift") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->shift);
|
||||
} else if (compare(tok, jsonChunk, "aperture") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->aperture);
|
||||
} else if (compare(tok, jsonChunk, "shutterSpeed") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->shutterSpeed);
|
||||
} else if (compare(tok, jsonChunk, "sensitivity") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sensitivity);
|
||||
} else if (compare(tok, jsonChunk, "focusDistance") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->focusDistance);
|
||||
} else if (compare(tok, jsonChunk, "eyeOcularDistance") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->eyeOcularDistance);
|
||||
} else if (compare(tok, jsonChunk, "eyeToeIn") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->eyeToeIn);
|
||||
} else {
|
||||
slog.w << "Invalid camera options key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
}
|
||||
if (i < 0) {
|
||||
slog.e << "Invalid camera options value: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, AnimationSettings* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "enabled") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->enabled);
|
||||
} else if (compare(tok, jsonChunk, "time") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->time);
|
||||
} else if (compare(tok, jsonChunk, "speed") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->speed);
|
||||
} else {
|
||||
slog.w << "Invalid animation options key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
}
|
||||
if (i < 0) {
|
||||
slog.e << "Invalid animation options value: '" << STR(tok, jsonChunk) << "'"
|
||||
<< io::endl;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk,
|
||||
Renderer::ClearOptions* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "clearColor") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->clearColor);
|
||||
} else if (compare(tok, jsonChunk, "clear") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->clear);
|
||||
} else if (compare(tok, jsonChunk, "discard") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->discard);
|
||||
} else if (compare(tok, jsonChunk, "clearStencil") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->clearStencil);
|
||||
} else {
|
||||
slog.w << "Invalid clear options key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
}
|
||||
if (i < 0) {
|
||||
slog.e << "Invalid clear options value: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk,
|
||||
Renderer::FrameRateOptions* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int const size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "headRoomRatio") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->headRoomRatio);
|
||||
} else if (compare(tok, jsonChunk, "history") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->history);
|
||||
} else if (compare(tok, jsonChunk, "scaleRate") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->scaleRate);
|
||||
} else {
|
||||
slog.w << "Invalid frame rate options key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
}
|
||||
if (i < 0) {
|
||||
slog.e << "Invalid frame rate options value: '" << STR(tok, jsonChunk) << "'"
|
||||
<< io::endl;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, RenderSettings* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int const size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "clearOptions") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->clearOptions);
|
||||
} else if (compare(tok, jsonChunk, "frameRateOptions") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->frameRateOptions);
|
||||
} else {
|
||||
slog.w << "Invalid render settings key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
}
|
||||
if (i < 0) {
|
||||
slog.e << "Invalid render settings value: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, LightSettings* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int const size = tokens[i++].size;
|
||||
int size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
@@ -712,16 +464,26 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, LightSet
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->enableShadows);
|
||||
} else if (compare(tok, jsonChunk, "enableSunlight") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->enableSunlight);
|
||||
} else if (compare(tok, jsonChunk, "shadowOptions") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->shadowOptions);
|
||||
} else if (compare(tok, jsonChunk, "softShadowOptions") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->softShadowOptions);
|
||||
} else if (compare(tok, jsonChunk, "sunlight") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunlight);
|
||||
} else if (compare(tok, jsonChunk, "sunlightIntensity") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunlightIntensity);
|
||||
} else if (compare(tok, jsonChunk, "sunlightHaloSize") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunlightHaloSize);
|
||||
} else if (compare(tok, jsonChunk, "sunlightHaloFalloff") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunlightHaloFalloff);
|
||||
} else if (compare(tok, jsonChunk, "sunlightAngularRadius") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunlightAngularRadius);
|
||||
} else if (compare(tok, jsonChunk, "sunlightDirection") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunlightDirection);
|
||||
} else if (compare(tok, jsonChunk, "sunlightColor") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->sunlightColor);
|
||||
} else if (compare(tok, jsonChunk, "iblIntensity") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->iblIntensity);
|
||||
} else if (compare(tok, jsonChunk, "iblRotation") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->iblRotation);
|
||||
} else if (compare(tok, jsonChunk, "lights") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->lights);
|
||||
} else {
|
||||
slog.w << "Invalid light setting key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
@@ -736,22 +498,40 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, LightSet
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, ViewerOptions* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int const size = tokens[i++].size;
|
||||
int size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
if (compare(tok, jsonChunk, "groundShadowStrength") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->groundShadowStrength);
|
||||
if (compare(tok, jsonChunk, "cameraAperture") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cameraAperture);
|
||||
} else if (compare(tok, jsonChunk, "cameraSpeed") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cameraSpeed);
|
||||
} else if (compare(tok, jsonChunk, "cameraISO") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cameraISO);
|
||||
} else if (compare(tok, jsonChunk, "cameraNear") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cameraNear);
|
||||
} else if (compare(tok, jsonChunk, "cameraFar") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cameraFar);
|
||||
} else if (compare(tok, jsonChunk, "cameraEyeOcularDistance") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cameraEyeOcularDistance);
|
||||
} else if (compare(tok, jsonChunk, "cameraEyeToeIn") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cameraEyeToeIn);
|
||||
} else if (compare(tok, jsonChunk, "groundShadowStrength") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->groundShadowStrength);
|
||||
} else if (compare(tok, jsonChunk, "groundPlaneEnabled") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->groundPlaneEnabled);
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->groundPlaneEnabled);
|
||||
} else if (compare(tok, jsonChunk, "skyboxEnabled") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->skyboxEnabled);
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->skyboxEnabled);
|
||||
} else if (compare(tok, jsonChunk, "backgroundColor") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->backgroundColor);
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->backgroundColor);
|
||||
} else if (compare(tok, jsonChunk, "cameraFocalLength") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cameraFocalLength);
|
||||
} else if (compare(tok, jsonChunk, "cameraFocusDistance") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->cameraFocusDistance);
|
||||
} else if (compare(tok, jsonChunk, "autoInstancingEnabled") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->autoInstancingEnabled);
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->autoInstancingEnabled);
|
||||
} else if (compare(tok, jsonChunk, "autoScaleEnabled") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->autoScaleEnabled);
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->autoScaleEnabled);
|
||||
} else {
|
||||
slog.w << "Invalid viewer options key: '" << STR(tok, jsonChunk) << "'" << io::endl;
|
||||
i = parse(tokens, i + 1);
|
||||
@@ -766,7 +546,7 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, ViewerOp
|
||||
|
||||
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DebugOptions* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int const size = tokens[i++].size;
|
||||
int size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
@@ -786,7 +566,7 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, DebugOpt
|
||||
|
||||
int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, Settings* out) {
|
||||
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int const size = tokens[i++].size;
|
||||
int size = tokens[i++].size;
|
||||
for (int j = 0; j < size; ++j) {
|
||||
const jsmntok_t tok = tokens[i];
|
||||
CHECK_KEY(tok);
|
||||
@@ -798,12 +578,6 @@ int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, Settings* out)
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->lighting);
|
||||
} else if (compare(tok, jsonChunk, "viewer") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->viewer);
|
||||
} else if (compare(tok, jsonChunk, "camera") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->camera);
|
||||
} else if (compare(tok, jsonChunk, "animation") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->animation);
|
||||
} else if (compare(tok, jsonChunk, "render") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->render);
|
||||
} else if (compare(tok, jsonChunk, "debug") == 0) {
|
||||
i = parse(tokens, i + 1, jsonChunk, &out->debug);
|
||||
} else {
|
||||
@@ -838,9 +612,6 @@ void applySettings(Engine* engine, const ViewSettings& settings, View* dest) {
|
||||
dest->setGuardBandOptions(settings.guardBand);
|
||||
dest->setStereoscopicOptions(settings.stereoscopicOptions);
|
||||
dest->setPostProcessingEnabled(settings.postProcessingEnabled);
|
||||
dest->setBlendMode(static_cast<View::BlendMode>(settings.blendMode));
|
||||
dest->setStencilBufferEnabled(settings.stencilBufferEnabled);
|
||||
dest->setVisibleLayers(settings.visibleLayers, settings.visibleLayers);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -865,14 +636,14 @@ void applySettings(Engine* engine, const LightSettings& settings, IndirectLight*
|
||||
} else {
|
||||
scene->remove(sunlight);
|
||||
}
|
||||
lm->setIntensity(light, settings.sunlight.intensity);
|
||||
lm->setSunHaloSize(light, settings.sunlight.sunHaloSize);
|
||||
lm->setSunHaloFalloff(light, settings.sunlight.sunHaloFalloff);
|
||||
lm->setSunAngularRadius(light, settings.sunlight.sunAngularRadius);
|
||||
lm->setDirection(light, normalize(settings.sunlight.direction));
|
||||
lm->setColor(light, settings.sunlight.color);
|
||||
lm->setShadowCaster(light, settings.sunlight.castShadows && settings.enableShadows);
|
||||
lm->setShadowOptions(light, settings.sunlight.shadowOptions);
|
||||
lm->setIntensity(light, settings.sunlightIntensity);
|
||||
lm->setSunHaloSize(light, settings.sunlightHaloSize);
|
||||
lm->setSunHaloFalloff(light, settings.sunlightHaloFalloff);
|
||||
lm->setSunAngularRadius(light, settings.sunlightAngularRadius);
|
||||
lm->setDirection(light, normalize(settings.sunlightDirection));
|
||||
lm->setColor(light, settings.sunlightColor);
|
||||
lm->setShadowCaster(light, settings.enableShadows);
|
||||
lm->setShadowOptions(light, settings.shadowOptions);
|
||||
}
|
||||
if (ibl) {
|
||||
ibl->setIntensity(settings.iblIntensity);
|
||||
@@ -881,13 +652,8 @@ void applySettings(Engine* engine, const LightSettings& settings, IndirectLight*
|
||||
for (size_t i = 0; i < sceneLightCount; i++) {
|
||||
auto const li = lm->getInstance(sceneLights[i]);
|
||||
if (li) {
|
||||
// Note: We don't have individual settings for these "scene lights" (IBL maps etc)
|
||||
// in the current structure unless we map them by index or name.
|
||||
// For now, we only enforce the global shadow toggle.
|
||||
lm->setShadowCaster(li, settings.enableShadows);
|
||||
// We removed the global shadowOptions. If they need defaults, they should be set elsewhere or
|
||||
// we should keep a "defaultShadowOptions" but for now assuming individual control via automation
|
||||
// or existing defaults.
|
||||
lm->setShadowOptions(li, settings.shadowOptions);
|
||||
}
|
||||
}
|
||||
view->setSoftShadowOptions(settings.softShadowOptions);
|
||||
@@ -910,57 +676,36 @@ void applySettings(Engine* engine, const ViewerOptions& settings, Camera* camera
|
||||
if (skybox) {
|
||||
skybox->setLayerMask(0xff, settings.skyboxEnabled ? 0xff : 0x00);
|
||||
}
|
||||
engine->setAutomaticInstancingEnabled(settings.autoInstancingEnabled);
|
||||
}
|
||||
if (camera) {
|
||||
camera->setExposure(
|
||||
settings.cameraAperture,
|
||||
1.0f / settings.cameraSpeed,
|
||||
settings.cameraISO);
|
||||
|
||||
void applySettings(Engine* engine, const DebugOptions& settings, Renderer* renderer) {
|
||||
if (!renderer->getFrameToSkipCount()) {
|
||||
renderer->skipNextFrames(settings.skipFrames);
|
||||
camera->setFocusDistance(settings.cameraFocusDistance);
|
||||
}
|
||||
}
|
||||
|
||||
void applySettings(Engine* engine, const CameraSettings& settings, Camera* camera,
|
||||
double aspectRatio) {
|
||||
camera->setExposure(settings.aperture, 1.0f / settings.shutterSpeed, settings.sensitivity);
|
||||
|
||||
camera->setFocusDistance(settings.focusDistance);
|
||||
engine->setAutomaticInstancingEnabled(settings.autoInstancingEnabled);
|
||||
|
||||
// Eyes are rendered from left-to-right, i.e., eye 0 is rendered to the left side of the
|
||||
// window.
|
||||
// For testing, we want to render a side-by-side layout so users can view with
|
||||
// "cross-eyed" stereo.
|
||||
// For cross-eyed stereo, Eye 0 is really the RIGHT eye, while Eye 1 is the LEFT eye.
|
||||
double const od = settings.eyeOcularDistance;
|
||||
double const toeIn = settings.eyeToeIn;
|
||||
size_t const eyeCount = engine->getConfig().stereoscopicEyeCount;
|
||||
double3 const up = double3(0.0, 1.0, 0.0);
|
||||
mat4 const rightEye = mat4::translation(double3{ od, 0.0, 0.0 }) * mat4::rotation(toeIn, up);
|
||||
mat4 const leftEye = mat4::translation(double3{ -od, 0.0, 0.0 }) * mat4::rotation(-toeIn, up);
|
||||
mat4 const modelMatrices[2] = { rightEye, leftEye };
|
||||
for (size_t i = 0; i < eyeCount; i++) {
|
||||
const auto od = settings.cameraEyeOcularDistance;
|
||||
const auto toeIn = settings.cameraEyeToeIn;
|
||||
const auto eyeCount = engine->getConfig().stereoscopicEyeCount;
|
||||
const double3 up = double3(0.0, 1.0, 0.0);
|
||||
const mat4 rightEye = mat4::translation(double3{ od, 0.0, 0.0}) * mat4::rotation( toeIn, up);
|
||||
const mat4 leftEye = mat4::translation(double3{-od, 0.0, 0.0}) * mat4::rotation(-toeIn, up);
|
||||
const mat4 modelMatrices[2] = { rightEye, leftEye };
|
||||
for (int i = 0; i < eyeCount; i++) {
|
||||
camera->setEyeModelMatrix(i, modelMatrices[i % 2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.enabled && aspectRatio > 0.0) {
|
||||
camera->lookAt(settings.center, settings.lookAt, settings.up);
|
||||
if (settings.projection == CameraProjection::PERSPECTIVE) {
|
||||
if (settings.focalLength > 0.0f) {
|
||||
camera->setLensProjection(settings.focalLength, aspectRatio, settings.near,
|
||||
settings.far);
|
||||
} else {
|
||||
camera->setProjection(settings.horizontalFov, aspectRatio, settings.near,
|
||||
settings.far, Camera::Fov::VERTICAL);
|
||||
}
|
||||
} else {
|
||||
// ORTHO
|
||||
double const left = -settings.scaling.x * aspectRatio;
|
||||
double const right = settings.scaling.x * aspectRatio;
|
||||
double const bottom = -settings.scaling.y;
|
||||
double const top = settings.scaling.y;
|
||||
camera->setProjection(Camera::Projection::ORTHO, left + settings.shift.x,
|
||||
right + settings.shift.x, bottom + settings.shift.y, top + settings.shift.y,
|
||||
settings.near, settings.far);
|
||||
}
|
||||
void applySettings(Engine* engine, const DebugOptions& settings, Renderer* renderer) {
|
||||
if (!renderer->getFrameToSkipCount()) {
|
||||
renderer->skipNextFrames(settings.skipFrames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1021,25 +766,6 @@ static std::ostream& operator<<(std::ostream& out, CGQL in) {
|
||||
return out << "\"INVALID\"";
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& out, CameraProjection in) {
|
||||
switch (in) {
|
||||
case CameraProjection::ORTHO: return out << "\"ORTHO\"";
|
||||
case CameraProjection::PERSPECTIVE: return out << "\"PERSPECTIVE\"";
|
||||
}
|
||||
return out << "\"INVALID\"";
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& out, LightManager::Type in) {
|
||||
switch (in) {
|
||||
case LightManager::Type::SUN: return out << "\"SUN\"";
|
||||
case LightManager::Type::DIRECTIONAL: return out << "\"DIRECTIONAL\"";
|
||||
case LightManager::Type::POINT: return out << "\"POINT\"";
|
||||
case LightManager::Type::FOCUSED_SPOT: return out << "\"FOCUSED_SPOT\"";
|
||||
case LightManager::Type::SPOT: return out << "\"SPOT\"";
|
||||
}
|
||||
return out << "\"INVALID\"";
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& out, ToneMapping in) {
|
||||
switch (in) {
|
||||
case ToneMapping::LINEAR: return out << "\"LINEAR\"";
|
||||
@@ -1181,74 +907,41 @@ static std::ostream& operator<<(std::ostream& out, const MaterialSettings& in) {
|
||||
return out << result;
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& out, const LightDefinition& in) {
|
||||
return out << "{\n"
|
||||
<< "\"type\": " << in.type << ",\n"
|
||||
<< "\"position\": " << in.position << ",\n"
|
||||
<< "\"direction\": " << in.direction << ",\n"
|
||||
<< "\"color\": " << in.color << ",\n"
|
||||
<< "\"intensity\": " << in.intensity << ",\n"
|
||||
<< "\"falloff\": " << in.falloff << ",\n"
|
||||
<< "\"spotInner\": " << in.spotInner << ",\n"
|
||||
<< "\"spotOuter\": " << in.spotOuter << ",\n"
|
||||
<< "\"sunHaloSize\": " << in.sunHaloSize << ",\n"
|
||||
<< "\"sunHaloFalloff\": " << in.sunHaloFalloff << ",\n"
|
||||
<< "\"sunAngularRadius\": " << in.sunAngularRadius << ",\n"
|
||||
<< "\"castShadows\": " << to_string(in.castShadows) << ",\n"
|
||||
<< "\"shadowOptions\": " << in.shadowOptions << "\n"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& out, const LightSettings& in) {
|
||||
out << "{\n"
|
||||
return out << "{\n"
|
||||
<< "\"enableShadows\": " << to_string(in.enableShadows) << ",\n"
|
||||
<< "\"enableSunlight\": " << to_string(in.enableSunlight) << ",\n"
|
||||
<< "\"shadowOptions\": " << (in.shadowOptions) << ",\n"
|
||||
<< "\"softShadowOptions\": " << (in.softShadowOptions) << ",\n"
|
||||
<< "\"sunlight\": " << (in.sunlight) << ",\n"
|
||||
<< "\"sunlightIntensity\": " << (in.sunlightIntensity) << ",\n"
|
||||
<< "\"sunlightHaloSize\": " << (in.sunlightHaloSize) << ",\n"
|
||||
<< "\"sunlightHaloFalloff\": " << (in.sunlightHaloFalloff) << ",\n"
|
||||
<< "\"sunlightAngularRadius\": " << (in.sunlightAngularRadius) << ",\n"
|
||||
<< "\"sunlightDirection\": " << (in.sunlightDirection) << ",\n"
|
||||
<< "\"sunlightColor\": " << (in.sunlightColor) << ",\n"
|
||||
<< "\"iblIntensity\": " << (in.iblIntensity) << ",\n"
|
||||
<< "\"iblRotation\": " << (in.iblRotation) << ",\n"
|
||||
<< "\"lights\": [\n";
|
||||
for (size_t i = 0; i < in.lights.size(); ++i) {
|
||||
out << in.lights[i];
|
||||
if (i < in.lights.size() - 1) {
|
||||
out << ",";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
return out << "]\n" << "}";
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& out, const CameraSettings& in) {
|
||||
return out << "{\n"
|
||||
<< "\"center\": " << in.center << ",\n"
|
||||
<< "\"lookAt\": " << in.lookAt << ",\n"
|
||||
<< "\"up\": " << in.up << ",\n"
|
||||
<< "\"horizontalFov\": " << in.horizontalFov << ",\n"
|
||||
<< "\"near\": " << in.near << ",\n"
|
||||
<< "\"far\": " << in.far << ",\n"
|
||||
<< "\"focalLength\": " << in.focalLength << ",\n"
|
||||
<< "\"aperture\": " << in.aperture << ",\n"
|
||||
<< "\"shutterSpeed\": " << in.shutterSpeed << ",\n"
|
||||
<< "\"sensitivity\": " << in.sensitivity << ",\n"
|
||||
<< "\"focusDistance\": " << in.focusDistance << ",\n"
|
||||
<< "\"eyeOcularDistance\": " << in.eyeOcularDistance << ",\n"
|
||||
<< "\"eyeToeIn\": " << in.eyeToeIn << ",\n"
|
||||
<< "\"projection\": " << in.projection << ",\n"
|
||||
<< "\"enabled\": " << to_string(in.enabled) << ",\n"
|
||||
<< "\"scaling\": " << in.scaling << ",\n"
|
||||
<< "\"shift\": " << in.shift << "\n"
|
||||
<< "}";
|
||||
<< "\"iblRotation\": " << (in.iblRotation) << "\n"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& out, const ViewerOptions& in) {
|
||||
return out << "{\n"
|
||||
<< "\"groundShadowStrength\": " << (in.groundShadowStrength) << ",\n"
|
||||
<< "\"groundPlaneEnabled\": " << to_string(in.groundPlaneEnabled) << ",\n"
|
||||
<< "\"skyboxEnabled\": " << to_string(in.skyboxEnabled) << ",\n"
|
||||
<< "\"backgroundColor\": " << (in.backgroundColor) << ",\n"
|
||||
<< "\"autoInstancingEnabled\": " << to_string(in.autoInstancingEnabled) << ",\n"
|
||||
<< "\"autoScaleEnabled\": " << to_string(in.autoScaleEnabled) << "\n"
|
||||
<< "}";
|
||||
<< "\"cameraAperture\": " << (in.cameraAperture) << ",\n"
|
||||
<< "\"cameraSpeed\": " << (in.cameraSpeed) << ",\n"
|
||||
<< "\"cameraISO\": " << (in.cameraISO) << ",\n"
|
||||
<< "\"cameraNear\": " << (in.cameraNear) << ",\n"
|
||||
<< "\"cameraFar\": " << (in.cameraFar) << ",\n"
|
||||
<< "\"cameraEyeOcularDistance\": " << (in.cameraEyeOcularDistance) << ",\n"
|
||||
<< "\"cameraEyeToeIn\": " << (in.cameraEyeToeIn) << ",\n"
|
||||
<< "\"groundShadowStrength\": " << (in.groundShadowStrength) << ",\n"
|
||||
<< "\"groundPlaneEnabled\": " << to_string(in.groundPlaneEnabled) << ",\n"
|
||||
<< "\"skyboxEnabled\": " << to_string(in.skyboxEnabled) << ",\n"
|
||||
<< "\"backgroundColor\": " << (in.backgroundColor) << ",\n"
|
||||
<< "\"cameraFocalLength\": " << (in.cameraFocalLength) << ",\n"
|
||||
<< "\"cameraFocusDistance\": " << (in.cameraFocusDistance) << ",\n"
|
||||
<< "\"autoInstancingEnabled\": " << to_string(in.autoInstancingEnabled) << ",\n"
|
||||
<< "\"autoScaleEnabled\": " << to_string(in.autoScaleEnabled) << "\n"
|
||||
<< "}";
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& out, const DebugOptions& in) {
|
||||
@@ -1290,12 +983,12 @@ static std::ostream& operator<<(std::ostream& out, const ViewSettings& in) {
|
||||
|
||||
static std::ostream& operator<<(std::ostream& out, const Settings& in) {
|
||||
return out << "{\n"
|
||||
<< "\"view\": " << (in.view) << ",\n"
|
||||
<< "\"material\": " << (in.material) << ",\n"
|
||||
<< "\"lighting\": " << (in.lighting) << ",\n"
|
||||
<< "\"viewer\": " << (in.viewer) << ",\n"
|
||||
<< "\"camera\": " << (in.camera) << ",\n"
|
||||
<< "\"debug\": " << (in.debug) << "}";
|
||||
<< "\"view\": " << (in.view) << ",\n"
|
||||
<< "\"material\": " << (in.material) << ",\n"
|
||||
<< "\"lighting\": " << (in.lighting) << ",\n"
|
||||
<< "\"viewer\": " << (in.viewer) << ",\n"
|
||||
<< "\"debug\": " << (in.debug)
|
||||
<< "}";
|
||||
}
|
||||
|
||||
bool GenericToneMapperSettings::operator==(const GenericToneMapperSettings& rhs) const {
|
||||
|
||||
@@ -429,13 +429,13 @@ ViewerGui::ViewerGui(filament::Engine* engine, filament::Scene* scene, filament:
|
||||
|
||||
using namespace filament;
|
||||
LightManager::Builder(LightManager::Type::SUN)
|
||||
.color(mSettings.lighting.sunlight.color)
|
||||
.intensity(mSettings.lighting.sunlight.intensity)
|
||||
.direction(normalize(mSettings.lighting.sunlight.direction))
|
||||
.color(mSettings.lighting.sunlightColor)
|
||||
.intensity(mSettings.lighting.sunlightIntensity)
|
||||
.direction(normalize(mSettings.lighting.sunlightDirection))
|
||||
.castShadows(true)
|
||||
.sunAngularRadius(mSettings.lighting.sunlight.sunAngularRadius)
|
||||
.sunHaloSize(mSettings.lighting.sunlight.sunHaloSize)
|
||||
.sunHaloFalloff(mSettings.lighting.sunlight.sunHaloFalloff)
|
||||
.sunAngularRadius(mSettings.lighting.sunlightAngularRadius)
|
||||
.sunHaloSize(mSettings.lighting.sunlightHaloSize)
|
||||
.sunHaloFalloff(mSettings.lighting.sunlightHaloFalloff)
|
||||
.build(*engine, mSunlight);
|
||||
if (mSettings.lighting.enableSunlight) {
|
||||
mScene->addEntity(mSunlight);
|
||||
@@ -510,9 +510,9 @@ void ViewerGui::setIndirectLight(filament::IndirectLight* ibl,
|
||||
bool const dIsValid = std::none_of(std::begin(d.v), std::end(d.v), is_not_a_number);
|
||||
bool const cIsValid = std::none_of(std::begin(c.v), std::end(c.v), is_not_a_number);
|
||||
if (dIsValid && cIsValid) {
|
||||
mSettings.lighting.sunlight.direction = d;
|
||||
mSettings.lighting.sunlight.color = c.rgb;
|
||||
mSettings.lighting.sunlight.intensity = c[3] * ibl->getIntensity();
|
||||
mSettings.lighting.sunlightDirection = d;
|
||||
mSettings.lighting.sunlightColor = c.rgb;
|
||||
mSettings.lighting.sunlightIntensity = c[3] * ibl->getIntensity();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -945,31 +945,31 @@ void ViewerGui::updateUserInterface() {
|
||||
}
|
||||
if (ImGui::CollapsingHeader("Sunlight")) {
|
||||
ImGui::Checkbox("Enable sunlight", &light.enableSunlight);
|
||||
ImGui::SliderFloat("Sun intensity", &light.sunlight.intensity, 0.0f, 150000.0f);
|
||||
ImGui::SliderFloat("Halo size", &light.sunlight.sunHaloSize, 1.01f, 40.0f);
|
||||
ImGui::SliderFloat("Halo falloff", &light.sunlight.sunHaloFalloff, 4.0f, 1024.0f);
|
||||
ImGui::SliderFloat("Sun radius", &light.sunlight.sunAngularRadius, 0.1f, 10.0f);
|
||||
ImGuiExt::DirectionWidget("Sun direction", light.sunlight.direction.v);
|
||||
ImGui::SliderFloat("Shadow Far", &light.sunlight.shadowOptions.shadowFar, 0.0f,
|
||||
mSettings.camera.far);
|
||||
ImGui::SliderFloat("Sun intensity", &light.sunlightIntensity, 0.0f, 150000.0f);
|
||||
ImGui::SliderFloat("Halo size", &light.sunlightHaloSize, 1.01f, 40.0f);
|
||||
ImGui::SliderFloat("Halo falloff", &light.sunlightHaloFalloff, 4.0f, 1024.0f);
|
||||
ImGui::SliderFloat("Sun radius", &light.sunlightAngularRadius, 0.1f, 10.0f);
|
||||
ImGuiExt::DirectionWidget("Sun direction", light.sunlightDirection.v);
|
||||
ImGui::SliderFloat("Shadow Far", &light.shadowOptions.shadowFar, 0.0f,
|
||||
mSettings.viewer.cameraFar);
|
||||
|
||||
if (ImGui::CollapsingHeader("Shadow direction")) {
|
||||
float3 shadowDirection = light.sunlight.shadowOptions.transform * light.sunlight.direction;
|
||||
float3 shadowDirection = light.shadowOptions.transform * light.sunlightDirection;
|
||||
ImGuiExt::DirectionWidget("Shadow direction", shadowDirection.v);
|
||||
light.sunlight.shadowOptions.transform = normalize(quatf{
|
||||
cross(light.sunlight.direction, shadowDirection),
|
||||
sqrt(length2(light.sunlight.direction) * length2(shadowDirection))
|
||||
+ dot(light.sunlight.direction, shadowDirection)
|
||||
light.shadowOptions.transform = normalize(quatf{
|
||||
cross(light.sunlightDirection, shadowDirection),
|
||||
sqrt(length2(light.sunlightDirection) * length2(shadowDirection))
|
||||
+ dot(light.sunlightDirection, shadowDirection)
|
||||
});
|
||||
}
|
||||
}
|
||||
if (ImGui::CollapsingHeader("Shadows")) {
|
||||
ImGui::Checkbox("Enable shadows", &light.enableShadows);
|
||||
int mapSize = light.sunlight.shadowOptions.mapSize;
|
||||
int mapSize = light.shadowOptions.mapSize;
|
||||
ImGui::SliderInt("Shadow map size", &mapSize, 32, 1024);
|
||||
light.sunlight.shadowOptions.mapSize = mapSize;
|
||||
ImGui::Checkbox("Stable Shadows", &light.sunlight.shadowOptions.stable);
|
||||
ImGui::Checkbox("Enable LiSPSM", &light.sunlight.shadowOptions.lispsm);
|
||||
light.shadowOptions.mapSize = mapSize;
|
||||
ImGui::Checkbox("Stable Shadows", &light.shadowOptions.stable);
|
||||
ImGui::Checkbox("Enable LiSPSM", &light.shadowOptions.lispsm);
|
||||
|
||||
int shadowType = (int)mSettings.view.shadowType;
|
||||
ImGui::Combo("Shadow type", &shadowType, "PCF\0VSM\0DPCF\0PCSS\0PCFd\0\0");
|
||||
@@ -977,7 +977,7 @@ void ViewerGui::updateUserInterface() {
|
||||
|
||||
if (mSettings.view.shadowType == ShadowType::VSM) {
|
||||
ImGui::Checkbox("High precision", &mSettings.view.vsmShadowOptions.highPrecision);
|
||||
ImGui::Checkbox("ELVSM", &mSettings.lighting.sunlight.shadowOptions.vsm.elvsm);
|
||||
ImGui::Checkbox("ELVSM", &mSettings.lighting.shadowOptions.vsm.elvsm);
|
||||
char label[32];
|
||||
snprintf(label, 32, "%d", 1 << mVsmMsaaSamplesLog2);
|
||||
ImGui::SliderInt("VSM MSAA samples", &mVsmMsaaSamplesLog2, 0, 3, label);
|
||||
@@ -989,7 +989,7 @@ void ViewerGui::updateUserInterface() {
|
||||
ImGui::SliderInt("VSM anisotropy", &vsmAnisotropy, 0, 3, label);
|
||||
mSettings.view.vsmShadowOptions.anisotropy = vsmAnisotropy;
|
||||
ImGui::Checkbox("VSM mipmapping", &mSettings.view.vsmShadowOptions.mipmapping);
|
||||
ImGui::SliderFloat("VSM blur", &light.sunlight.shadowOptions.vsm.blurWidth, 0.0f, 125.0f);
|
||||
ImGui::SliderFloat("VSM blur", &light.shadowOptions.vsm.blurWidth, 0.0f, 125.0f);
|
||||
|
||||
// These are not very useful in practice (defaults are good), but we keep them here for debugging
|
||||
//ImGui::SliderFloat("VSM exponent", &mSettings.view.vsmShadowOptions.exponent, 0.0, 6.0f);
|
||||
@@ -1000,15 +1000,15 @@ void ViewerGui::updateUserInterface() {
|
||||
ImGui::SliderFloat("Penumbra Ratio scale", &light.softShadowOptions.penumbraRatioScale, 1.0f, 100.0f);
|
||||
}
|
||||
|
||||
int shadowCascades = light.sunlight.shadowOptions.shadowCascades;
|
||||
int shadowCascades = light.shadowOptions.shadowCascades;
|
||||
ImGui::SliderInt("Cascades", &shadowCascades, 1, 4);
|
||||
ImGui::Checkbox("Debug cascades",
|
||||
debug.getPropertyAddress<bool>("d.shadowmap.visualize_cascades"));
|
||||
ImGui::Checkbox("Enable contact shadows", &light.sunlight.shadowOptions.screenSpaceContactShadows);
|
||||
ImGui::SliderFloat("Split pos 0", &light.sunlight.shadowOptions.cascadeSplitPositions[0], 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("Split pos 1", &light.sunlight.shadowOptions.cascadeSplitPositions[1], 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("Split pos 2", &light.sunlight.shadowOptions.cascadeSplitPositions[2], 0.0f, 1.0f);
|
||||
light.sunlight.shadowOptions.shadowCascades = shadowCascades;
|
||||
ImGui::Checkbox("Enable contact shadows", &light.shadowOptions.screenSpaceContactShadows);
|
||||
ImGui::SliderFloat("Split pos 0", &light.shadowOptions.cascadeSplitPositions[0], 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("Split pos 1", &light.shadowOptions.cascadeSplitPositions[1], 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("Split pos 2", &light.shadowOptions.cascadeSplitPositions[2], 0.0f, 1.0f);
|
||||
light.shadowOptions.shadowCascades = shadowCascades;
|
||||
}
|
||||
ImGui::Unindent();
|
||||
}
|
||||
@@ -1083,12 +1083,12 @@ void ViewerGui::updateUserInterface() {
|
||||
if (ImGui::CollapsingHeader("Camera")) {
|
||||
ImGui::Indent();
|
||||
|
||||
ImGui::SliderFloat("Focal length (mm)", &mSettings.camera.focalLength, 16.0f, 90.0f);
|
||||
ImGui::SliderFloat("Aperture", &mSettings.camera.aperture, 1.0f, 32.0f);
|
||||
ImGui::SliderFloat("Speed (1/s)", &mSettings.camera.shutterSpeed, 1000.0f, 1.0f);
|
||||
ImGui::SliderFloat("ISO", &mSettings.camera.sensitivity, 25.0f, 6400.0f);
|
||||
ImGui::SliderFloat("Near", &mSettings.camera.near, 0.001f, 1.0f);
|
||||
ImGui::SliderFloat("Far", &mSettings.camera.far, 1.0f, 10000.0f);
|
||||
ImGui::SliderFloat("Focal length (mm)", &mSettings.viewer.cameraFocalLength, 16.0f, 90.0f);
|
||||
ImGui::SliderFloat("Aperture", &mSettings.viewer.cameraAperture, 1.0f, 32.0f);
|
||||
ImGui::SliderFloat("Speed (1/s)", &mSettings.viewer.cameraSpeed, 1000.0f, 1.0f);
|
||||
ImGui::SliderFloat("ISO", &mSettings.viewer.cameraISO, 25.0f, 6400.0f);
|
||||
ImGui::SliderFloat("Near", &mSettings.viewer.cameraNear, 0.001f, 1.0f);
|
||||
ImGui::SliderFloat("Far", &mSettings.viewer.cameraFar, 1.0f, 10000.0f);
|
||||
|
||||
if (ImGui::CollapsingHeader("DoF")) {
|
||||
bool dofMedian = mSettings.view.dof.filter == View::DepthOfFieldOptions::Filter::MEDIAN;
|
||||
@@ -1097,7 +1097,7 @@ void ViewerGui::updateUserInterface() {
|
||||
if (!dofRingCount) dofRingCount = 5;
|
||||
if (!dofMaxCoC) dofMaxCoC = 32;
|
||||
ImGui::Checkbox("Enabled##dofEnabled", &mSettings.view.dof.enabled);
|
||||
ImGui::SliderFloat("Focus distance", &mSettings.camera.focusDistance, 0.0f, 30.0f);
|
||||
ImGui::SliderFloat("Focus distance", &mSettings.viewer.cameraFocusDistance, 0.0f, 30.0f);
|
||||
ImGui::SliderFloat("Blur scale", &mSettings.view.dof.cocScale, 0.1f, 10.0f);
|
||||
ImGui::SliderFloat("CoC aspect-ratio", &mSettings.view.dof.cocAspectRatio, 0.25f, 4.0f);
|
||||
ImGui::SliderInt("Ring count", &dofRingCount, 1, 17);
|
||||
@@ -1162,11 +1162,12 @@ void ViewerGui::updateUserInterface() {
|
||||
debug.getPropertyAddress<bool>("d.stereo.combine_multiview_images"));
|
||||
ImGui::Unindent();
|
||||
#endif
|
||||
ImGui::SliderFloat("Ocular distance", &mSettings.camera.eyeOcularDistance, 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("Ocular distance",
|
||||
&mSettings.viewer.cameraEyeOcularDistance, 0.0f, 1.0f);
|
||||
|
||||
float toeInDegrees = mSettings.camera.eyeToeIn / f::PI * 180.0f;
|
||||
float toeInDegrees = mSettings.viewer.cameraEyeToeIn / f::PI * 180.0f;
|
||||
ImGui::SliderFloat("Toe in", &toeInDegrees, 0.0f, 30.0, "%.3f°");
|
||||
mSettings.camera.eyeToeIn = toeInDegrees / 180.0f * f::PI;
|
||||
mSettings.viewer.cameraEyeToeIn = toeInDegrees / 180.0f * f::PI;
|
||||
|
||||
ImGui::Unindent();
|
||||
#endif
|
||||
@@ -1184,9 +1185,6 @@ void ViewerGui::updateUserInterface() {
|
||||
// At this point, all View settings have been modified,
|
||||
// so we can now push them into the Filament View.
|
||||
applySettings(mEngine, mSettings.view, mView);
|
||||
double const aspect =
|
||||
(double) mView->getViewport().width / (double) mView->getViewport().height;
|
||||
applySettings(mEngine, mSettings.camera, &mView->getCamera(), aspect);
|
||||
|
||||
auto lights = utils::FixedCapacityVector<utils::Entity>::with_capacity(mScene->getEntityCount());
|
||||
mScene->forEach([&](utils::Entity entity) {
|
||||
|
||||
@@ -221,88 +221,3 @@ int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
static const char* JSON_TEST_CAMERA = R"TXT(
|
||||
{
|
||||
"camera": {
|
||||
"aperture": 4.0,
|
||||
"shutterSpeed": 200,
|
||||
"sensitivity": 400,
|
||||
"focalLength": 50,
|
||||
"focusDistance": 5.0,
|
||||
"projection": "ORTHO",
|
||||
"near": 0.5,
|
||||
"far": 1000.0,
|
||||
"scaling": [0.5, 0.6],
|
||||
"shift": [0.1, 0.2]
|
||||
}
|
||||
}
|
||||
)TXT";
|
||||
|
||||
TEST_F(ViewSettingsTest, JsonTestCamera) {
|
||||
JsonSerializer serializer;
|
||||
Settings settings;
|
||||
ASSERT_TRUE(serializer.readJson(JSON_TEST_CAMERA, strlen(JSON_TEST_CAMERA), &settings));
|
||||
|
||||
EXPECT_FLOAT_EQ(settings.camera.aperture, 4.0f);
|
||||
EXPECT_FLOAT_EQ(settings.camera.shutterSpeed, 200.0f);
|
||||
EXPECT_FLOAT_EQ(settings.camera.sensitivity, 400.0f);
|
||||
EXPECT_FLOAT_EQ(settings.camera.focalLength, 50.0f);
|
||||
EXPECT_FLOAT_EQ(settings.camera.focusDistance, 5.0f);
|
||||
EXPECT_EQ(settings.camera.projection, CameraProjection::ORTHO);
|
||||
EXPECT_FLOAT_EQ(settings.camera.near, 0.5f);
|
||||
EXPECT_FLOAT_EQ(settings.camera.far, 1000.0f);
|
||||
EXPECT_FLOAT_EQ(settings.camera.scaling.x, 0.5f);
|
||||
EXPECT_FLOAT_EQ(settings.camera.scaling.y, 0.6f);
|
||||
EXPECT_FLOAT_EQ(settings.camera.shift.x, 0.1f);
|
||||
EXPECT_FLOAT_EQ(settings.camera.shift.y, 0.2f);
|
||||
}
|
||||
|
||||
static const char* JSON_TEST_LIGHTS = R"TXT(
|
||||
{
|
||||
"lighting": {
|
||||
"enableSunlight": false,
|
||||
"lights": [
|
||||
{
|
||||
"type": "POINT",
|
||||
"position": [1.0, 2.0, 3.0],
|
||||
"color": [1.0, 0.0, 0.0],
|
||||
"intensity": 1000.0,
|
||||
"falloff": 5.0,
|
||||
"castShadows": true
|
||||
},
|
||||
{
|
||||
"type": "SPOT",
|
||||
"direction": [0.0, -1.0, 0.0],
|
||||
"spotInner": 0.5,
|
||||
"spotOuter": 0.8
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
)TXT";
|
||||
|
||||
TEST_F(ViewSettingsTest, JsonTestLights) {
|
||||
JsonSerializer serializer;
|
||||
Settings settings;
|
||||
ASSERT_TRUE(serializer.readJson(JSON_TEST_LIGHTS, strlen(JSON_TEST_LIGHTS), &settings));
|
||||
|
||||
EXPECT_FALSE(settings.lighting.enableSunlight);
|
||||
ASSERT_EQ(settings.lighting.lights.size(), 2);
|
||||
|
||||
const auto& light0 = settings.lighting.lights[0];
|
||||
EXPECT_EQ(light0.type, LightManager::Type::POINT);
|
||||
EXPECT_FLOAT_EQ(light0.position.x, 1.0f);
|
||||
EXPECT_FLOAT_EQ(light0.position.y, 2.0f);
|
||||
EXPECT_FLOAT_EQ(light0.position.z, 3.0f);
|
||||
EXPECT_FLOAT_EQ(light0.color.r, 1.0f);
|
||||
EXPECT_FLOAT_EQ(light0.intensity, 1000.0f);
|
||||
EXPECT_FLOAT_EQ(light0.falloff, 5.0f);
|
||||
EXPECT_TRUE(light0.castShadows);
|
||||
|
||||
const auto& light1 = settings.lighting.lights[1];
|
||||
EXPECT_EQ(light1.type, LightManager::Type::SPOT);
|
||||
EXPECT_FLOAT_EQ(light1.direction.y, -1.0f);
|
||||
EXPECT_FLOAT_EQ(light1.spotInner, 0.5f);
|
||||
EXPECT_FLOAT_EQ(light1.spotOuter, 0.8f);
|
||||
}
|
||||
|
||||
@@ -781,7 +781,7 @@ int main(int argc, char** argv) {
|
||||
? AutomationEngine::Options::ExportFormat::PPM
|
||||
: AutomationEngine::Options::ExportFormat::TIFF;
|
||||
app.automationEngine->setOptions(options);
|
||||
app.viewer->getSettings().animation.enabled = false;
|
||||
app.viewer->stopAnimation();
|
||||
}
|
||||
|
||||
if (!app.settingsFile.empty()) {
|
||||
@@ -1084,16 +1084,7 @@ int main(int argc, char** argv) {
|
||||
// Gradually add renderables to the scene as their textures become ready.
|
||||
app.viewer->populateScene();
|
||||
|
||||
auto const& animSettings = app.viewer->getSettings().animation;
|
||||
if (animSettings.enabled) {
|
||||
double animTime = now;
|
||||
if (animSettings.time >= 0.0f) {
|
||||
animTime = animSettings.time;
|
||||
} else {
|
||||
animTime *= animSettings.speed;
|
||||
}
|
||||
app.viewer->applyAnimation(animTime);
|
||||
}
|
||||
app.viewer->applyAnimation(now);
|
||||
};
|
||||
|
||||
auto resize = [&app](Engine*, View* view) {
|
||||
@@ -1125,21 +1116,13 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Note that this focal length might be different from the slider value because the
|
||||
// automation engine applies Camera::computeEffectiveFocalLength when DoF is enabled.
|
||||
float focalLength = app.viewer->getSettings().camera.focalLength;
|
||||
float const focusDistance = app.viewer->getSettings().camera.focusDistance;
|
||||
if (app.viewer->getSettings().view.dof.enabled) {
|
||||
focalLength = Camera::computeEffectiveFocalLength(focalLength / 1000.0,
|
||||
std::max(0.1f, focusDistance)) *
|
||||
1000.0;
|
||||
}
|
||||
FilamentApp::get().setCameraFocalLength(focalLength);
|
||||
FilamentApp::get().setCameraNearFar(app.viewer->getSettings().camera.near,
|
||||
app.viewer->getSettings().camera.far);
|
||||
FilamentApp::get().setCameraFocalLength(viewerOptions.cameraFocalLength);
|
||||
FilamentApp::get().setCameraNearFar(viewerOptions.cameraNear, viewerOptions.cameraFar);
|
||||
|
||||
size_t const cameraCount = app.asset->getCameraEntityCount();
|
||||
const size_t cameraCount = app.asset->getCameraEntityCount();
|
||||
view->setCamera(app.mainCamera);
|
||||
|
||||
int const currentCamera = app.viewer->getCurrentCamera();
|
||||
const int currentCamera = app.viewer->getCurrentCamera();
|
||||
if (currentCamera > 0 && currentCamera <= cameraCount) {
|
||||
const utils::Entity* cameras = app.asset->getCameraEntities();
|
||||
Camera* camera = engine->getCameraComponent(cameras[currentCamera - 1]);
|
||||
@@ -1167,11 +1150,8 @@ int main(int argc, char** argv) {
|
||||
Camera& camera = view->getCamera();
|
||||
Skybox* skybox = scene->getSkybox();
|
||||
applySettings(engine, app.viewer->getSettings().viewer, &camera, skybox, renderer);
|
||||
double const aspect =
|
||||
(double) view->getViewport().width / (double) view->getViewport().height;
|
||||
applySettings(engine, app.viewer->getSettings().camera, &camera, aspect);
|
||||
|
||||
// FIXME: This applySettings() is done here instead of in AutomationEngine.cpp because
|
||||
// FIMXE: This applySettings() is done here instead of in AutomationEngine.cpp because
|
||||
// we need access to the Renderer, which AutomationEngine does not provide.
|
||||
applySettings(engine, app.viewer->getSettings().debug, renderer);
|
||||
|
||||
@@ -1203,7 +1183,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
};
|
||||
|
||||
auto postRender = [&app](Engine* engine, View* view, Scene* scene, Renderer* renderer) {
|
||||
auto postRender = [&app](Engine* engine, View* view, Scene*, Renderer* renderer) {
|
||||
if (app.screenshot) {
|
||||
std::ostringstream stringStream;
|
||||
stringStream << "screenshot" << std::setfill('0') << std::setw(2) << +app.screenshotSeq;
|
||||
@@ -1222,12 +1202,6 @@ int main(int argc, char** argv) {
|
||||
.renderer = renderer,
|
||||
.materials = app.instance->getMaterialInstances(),
|
||||
.materialCount = app.instance->getMaterialInstanceCount(),
|
||||
.lightManager = &engine->getLightManager(),
|
||||
.scene = scene,
|
||||
.indirectLight = app.viewer->getIndirectLight(),
|
||||
.sunlight = app.viewer->getSunlight(),
|
||||
.assetLights = app.asset->getLightEntities(),
|
||||
.assetLightCount = app.asset->getLightEntityCount(),
|
||||
};
|
||||
app.automationEngine->tick(engine, content, ImGui::GetIO().DeltaTime);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"name": "base",
|
||||
"models": ["Box", "BoxTextured", "FlightHelmet", "lucy"],
|
||||
"rendering": {
|
||||
"camera.focalLength": 35.0,
|
||||
"viewer.cameraFocalLength": 35.0,
|
||||
"view.postProcessingEnabled": true,
|
||||
"view.dithering": "NONE"
|
||||
},
|
||||
@@ -56,7 +56,7 @@
|
||||
"description": "transmission",
|
||||
"apply_presets": ["base", "transmission_models"],
|
||||
"rendering": {
|
||||
"camera.focalLength": 52.0
|
||||
"viewer.cameraFocalLength": 52.0
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"models": ["lucy", "DamagedHelmet"], // [optional] Base name for the gltf file used in the test. For
|
||||
// example, source files are lucy.glb and DamagedHelmet.gltf
|
||||
"rendering": { // [required] Rendering settings used in the test. The json format
|
||||
"camera.focusDistance": 0, // is taken from AutomationSpec in libs/viewer
|
||||
"viewer.cameraFocusDistance": 0, // is taken from AutomationSpec in libs/viewer
|
||||
"view.postProcessingEnabled": true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user