From 0bd9515b3dcffb370ffe141a1e3ca3d52b5943cb Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Wed, 7 Aug 2019 11:19:49 -0700 Subject: [PATCH] Add getWorldOffset() shader API, enhance docs. This allows advanced shader authors like myself to get coordinates in the API level world space. Fixes #1485. --- docs/Materials.md.html | 19 +++++++++++++++++-- filament/src/View.cpp | 3 +++ filament/src/details/Camera.h | 1 + .../include/private/filament/UibGenerator.h | 7 +++++-- libs/filabridge/src/UibGenerator.cpp | 5 ++++- shaders/src/common_getters.fs | 5 +++++ 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/docs/Materials.md.html b/docs/Materials.md.html index 154c54e62f..46b8d6d43e 100644 --- a/docs/Materials.md.html +++ b/docs/Materials.md.html @@ -1395,7 +1395,7 @@ struct MaterialVertexInputs { float2 uv0; // if the uv0 attribute is required float2 uv1; // if the uv1 attribute is required float3 worldNormal; // only if the shading model is not unlit - float4 worldPosition; // always available + float4 worldPosition; // always available (see note below about world-space) // variable* names are replaced with actual names float4 variable0; // if 1 or more variables is defined float4 variable1; // if 2 or more variables is defined @@ -1404,6 +1404,11 @@ struct MaterialVertexInputs { }; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! TIP: worldPosition + To achieve good precision, the `worldPosition` coordinate in the vertex shader is shifted by the + camera position. To get the true world-space position, users can add this to + `getWorldOffset()`. + !!! TIP: UV attributes By default the vertex shader of a material will flip the Y coordinate of the UV attributes of the current mesh: `material.uv0 = vec2(mesh_uv0.x, 1.0 - mesh_uv0.y)`. You can control @@ -1570,12 +1575,18 @@ type aliases: :-----------------------------------|:--------:|:------------------------------------ **getResolution()** | float4 | Resolution of the view in pixels: `width`, `height`, `1 / width`, `1 / height` **getWorldCameraPosition()** | float3 | Position of the camera/eye in world space +**getWorldOffset()** | float3 | The shift required to obtain API-level world space **getTime()** | float | Current time in seconds, may be reset regularly to avoid precision loss **getUserTime()** | float4 | Current time in seconds: `time`, `(double)time - time`, `0`, `0` **getUserTimeMode(float m)** | float | Current time modulo m in seconds **getExposure()** | float | Photometric exposure of the camera **getEV100()** | float | [Exposure value at ISO 100](https://en.wikipedia.org/wiki/Exposure_value) of the camera +!!! TIP: world space + To achieve good precision, the "world space" in Filament's shading system does not necessarily + match the API-level world space. To obtain the position of the API-level camera, custom + materials can add `getWorldOffset()` to `getWorldCameraPosition()`. + ### Vertex only The following APIs are only available from the vertex block: @@ -1594,7 +1605,7 @@ The following APIs are only available from the fragment block: Name | Type | Description :-----------------------------------|:--------:|:------------------------------------ **getWorldTangentFrame()** | float3x3 | Matrix containing in each column the `tangent` (`frame[0]`), `bi-tangent` (`frame[1]`) and `normal` (`frame[2]`) of the vertex in world space. If the material does not compute a tangent space normal for bump mapping or if the shading is not anisotropic, only the `normal` is valid in this matrix. -**getWorldPosition()** | float3 | Position of the fragment in world space +**getWorldPosition()** | float3 | Position of the fragment in world space (see note below about world-space) **getWorldViewVector()** | float3 | Normalized vector in world space from the fragment position to the eye **getWorldNormalVector()** | float3 | Normalized normal in world space, after bump mapping (must be used after `prepareMaterial()`) **getWorldGeometricNormalVector()** | float3 | Normalized normal in world space, before bump mapping (can be used before `prepareMaterial()`) @@ -1608,6 +1619,10 @@ The following APIs are only available from the fragment block: **inverseTonemapSRGB(float3)** | float3 | Applies the inverse tone mapping operator to the specified non-linear sRGB color and returns a linear sRGB color. This operation may be an approximation **luminance(float3)** | float | Computes the luminance of the specified linear sRGB color +!!! TIP: world space + To obtain API-level world space coordinates, custom materials should add `getWorldOffset()` to + `getWorldPosition()` (et al). + # Compiling materials Material packages can be compiled from material definitions using the command line tool called diff --git a/filament/src/View.cpp b/filament/src/View.cpp index bef3b3d2b2..4f7d87d617 100644 --- a/filament/src/View.cpp +++ b/filament/src/View.cpp @@ -460,6 +460,8 @@ void FView::prepare(FEngine& engine, backend::DriverApi& driver, ArenaScope& are .zf = camera->getCullingFar(), // exposure .ev100 = Exposure::ev100(*camera), + // world offset to allow users to determine the API-level camera position + .worldOffset = camera->getPosition(), // world origin transform, use only for debugging .worldOrigin = worldOriginCamera }; @@ -629,6 +631,7 @@ void FView::prepareCamera(const CameraInfo& camera, const filament::Viewport& vi u.setUniform(offsetof(PerViewUib, origin), float2{ viewport.left, viewport.bottom }); u.setUniform(offsetof(PerViewUib, cameraPosition), float3{camera.getPosition()}); + u.setUniform(offsetof(PerViewUib, worldOffset), camera.worldOffset); } void FView::prepareSSAO(Handle ssao) const noexcept { diff --git a/filament/src/details/Camera.h b/filament/src/details/Camera.h index 41bbd07359..6748f30a04 100644 --- a/filament/src/details/Camera.h +++ b/filament/src/details/Camera.h @@ -162,6 +162,7 @@ struct CameraInfo { float zn; float zf; float ev100 = 0.0f; + math::float3 worldOffset; math::float3 const& getPosition() const noexcept { return model[3].xyz; } math::float3 getForwardVector() const noexcept { return normalize(-model[2].xyz); } diff --git a/libs/filabridge/include/private/filament/UibGenerator.h b/libs/filabridge/include/private/filament/UibGenerator.h index 8b9256bd7e..30fa981a61 100644 --- a/libs/filabridge/include/private/filament/UibGenerator.h +++ b/libs/filabridge/include/private/filament/UibGenerator.h @@ -54,7 +54,7 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init) filament::math::float4 resolution; // viewport width, height, 1/width, 1/height - filament::math::float3 cameraPosition; + filament::math::float3 cameraPosition; // this is (0,0,0) when camera_at_origin is enabled float time; // time in seconds, with a 1 second period filament::math::float4 lightColorIntensity; // directional light @@ -84,8 +84,11 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init) filament::math::float2 iblMaxMipLevel; // maxlevel, float(1<