Add getWorldOffset() shader API, enhance docs.
This allows advanced shader authors like myself to get coordinates in the API level world space. Fixes #1485.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<HwTexture> ssao) const noexcept {
|
||||
|
||||
@@ -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); }
|
||||
|
||||
|
||||
@@ -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<<maxlevel)
|
||||
filament::math::float2 padding0;
|
||||
|
||||
filament::math::float3 worldOffset; // this is (0,0,0) when camera_at_origin is disabled
|
||||
float padding1;
|
||||
|
||||
// bring PerViewUib to 1 KiB
|
||||
filament::math::float4 padding1[16];
|
||||
filament::math::float4 padding2[15];
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -76,8 +76,11 @@ UniformInterfaceBlock const& UibGenerator::getPerViewUib() noexcept {
|
||||
// ibl max mip level
|
||||
.add("iblMaxMipLevel", 1, UniformInterfaceBlock::Type::FLOAT2)
|
||||
.add("padding0", 1, UniformInterfaceBlock::Type::FLOAT2)
|
||||
// view
|
||||
.add("worldOffset", 1, UniformInterfaceBlock::Type::FLOAT3)
|
||||
// bring size to 1 KiB
|
||||
.add("padding1", 16, UniformInterfaceBlock::Type::FLOAT4)
|
||||
.add("padding1", 1, UniformInterfaceBlock::Type::FLOAT)
|
||||
.add("padding2", 15, UniformInterfaceBlock::Type::FLOAT4)
|
||||
.build();
|
||||
return uib;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,11 @@ vec3 getWorldCameraPosition() {
|
||||
return frameUniforms.cameraPosition;
|
||||
}
|
||||
|
||||
/** @public-api */
|
||||
highp vec3 getWorldOffset() {
|
||||
return frameUniforms.worldOffset;
|
||||
}
|
||||
|
||||
/** @public-api */
|
||||
float getTime() {
|
||||
return frameUniforms.time;
|
||||
|
||||
Reference in New Issue
Block a user