目录
Shader public APIs
Introduction
将 Shader public APIs小节单独做总结是有必要的,这部分与材质框架代码编写相关。资料依然来自于官方文档:
- https://github.com/google/filament/tree/main/docs/Materials.html
Types
- 虽然 GLSL 的变量类型可以直接使用(如vec4 或 mat4),但 Filament 建议使用以下类型别名:(大部分开C++程序员都喜欢这种方式)
名称 | GLSL 类型 |
---|---|
bool2 | bvec2 |
bool3 | bvec3 |
bool4 | bvec4 |
int2 | ivec2 |
int3 | ivec3 |
int4 | ivec4 |
uint2 | uvec2 |
uint3 | uvec3 |
uint4 | uvec4 |
float2 | float2 |
float3 | float3 |
float4 | float4 |
float4×4 | mat4 |
float3×3 | mat3 |
Math
名称 | GLSL 类型 | 描述 |
---|---|---|
PI | float | π \pi π |
HALF_PI | float | π 2 \cfrac{\pi}{2} 2π |
saturate(float x) | float | 将指定值Clamp到 0.0 和1.0 之间 |
pow5(float x) | float | x 5 x^5 x5 |
sq(float x) | float | x 2 x^2 x2 |
max3(float3 v) | float | 返回 float3 中最大的值 |
mulMat4×4Float3(float4×4 m, float3 v) | float4 | 返回 m ∗ v m * v m∗v |
mulMat3×3Float3(float4×4 m, float3 v) | float4 | 返回 m ∗ v m * v m∗v |
Matrices
名称 | 类型 | 描述 |
---|---|---|
getViewFromWorldMatrix() | float4×4 | 从世界空间转换为视图空间的矩阵 |
getWorldFromViewMatrix() | float4×4 | 从视图空间转换为世界空间的矩阵 |
getClipFromViewMatrix() | float4×4 | 从视图空间转换为裁剪空间的矩阵 |
getViewFromClipMatrix() | float4×4 | 从裁剪空间转换为视图空间的矩阵 |
getClipFromWorldMatrix() | float4×4 | 从世界转换为裁剪空间的矩阵 |
getWorldFromClipMatrix() | float4×4 | 从裁剪空间转换为世界空间的矩阵 |
Frame constants
名称 | 类型 | 描述 |
---|---|---|
getResolution() | float4 | 视图的分辨率(以像素为单位):宽度、高度、1 /宽度、1 /高度 |
getWorldCameraPosition() | float3 | camera/eye 在世界空间中的位置 |
getWorldOffset() | float3 | 获得 API 级(API-level)世界空间所需的变换 |
getTime() | float | 当前时间秒以内的部分。为介于 0 和 1 之间的值 |
getUserTime() | float4 | 当前时间(以秒为单位): time, (double)time - time, 0, 0 |
getUserTimeMode(float m) | float | 当前时间除余 m(以秒为单位) |
getExposure() | float | 相机的曝光量 |
getEV100() | float | 相机 ISO100 时的曝光量 |
- world space
- 为了获得良好的精度,Filament的着色系统中的"世界空间"不一定与API级别的世界空间相匹配。要获得 API 级像机的位置,自定义材质可以将 getWorldOffset()添加到 getWorldCameraPosition()中。
Vertex only
- 只在 vertex 块中使用的 API
名称 | 类型 | 描述 |
---|---|---|
getPosition() | float4 | 材质定义域中的顶点位置(默认:对象/模型空间) |
getCustom0() 到 getCustom7() | float4 | 自定义顶点属性 (attribute) |
getWorldFromModelMatrix() | float4×4 | 从模型(对象)空间转换为世界空间的矩阵 |
getWorldFromModelNormalMatrix() | float3×3 | 将法线从模型(对象)空间转换为世界空间的矩阵 |
getVertexIndex() | int | 当前顶点的索引 |
Fragment only
- 以下 API 只能用于 fragment block
名称 | 类型 | 描述 |
---|---|---|
getWorldTangentFrame() | float3×3 | 矩阵在每列中包含世界空间中顶点的 tangent (frame[0]),bi-tangent(frame[1])和 normal (frame[2])。如果材质不计算bump mapping 的切线空间法线,或者渲染不是各向异性的,则在此矩阵中只有法线有效。 |
getWorldPosition() | float3 | 片元在世界空间中的位置 |
getWorldViewVector() | float3 | 世界空间中从片元位置到 eye 的归一化向量 |
getWorldNormalVector() | float3 | 在 bump mapping 之后,世界空间中归一化法线(必须在prepareMaterial() 之后使用) |
getWorldGeometricNormalVector() | float3 | 在 bump mapping 之前,世界空间中归一化法线(可以在 prepareMaterial() 之前使用) |
getWorldReflectedVector() | float3 | view vector 关于法线的反射向量(必须在prepareMaterial() 之后使用) |
getNormalizedViewportCoord() | float3 | 归一化视口位置 (viewport position)(即NDC坐标归一化为[0,1],可以在 prepareMaterial() 之前使用) |
getNdotV() | float | dot(normal, view) 的结果,总是严格大于0(必须在prepareMaterial() 之后使用) |
getColor() | float4 | 片元的插值颜色(如果需要颜色属性) |
getUV0() | float2 | UV 坐标,仅当需要 uv0 属性时才可用 |
getUV1() | float2 | UV 坐标,仅当需要 uv1 属性时才可用 |
getMaskThreshold() | float | 返回 mask 阈值,仅当混合设置为 masked 时才可用 |
inverseTonemap(float3) | float3 | 将 inverse tone mapping 运算符应用于指定的线性sRGB颜色,并返回一个线性sRGB颜色。此操作可能是一种近似操作,最好与“Filmic” tone mapping 操作符配合使用 |
inverseTonemapSRGB(float3) | float3 | 将 inverse tone mapping 运算符应用于指定的非线性sRGB颜色,并返回线性sRGB颜色。此操作可能是一种近似操作,最好与“Filmic” tone mapping 操作符配合使用 |
luminance(float3) | float | 计算指定线性 sRGB 颜色的 luminance |
ycbcrToRgb(float, float2) | float3 | 将 luminance 和 CbCr 对转换为 sRGB 颜色 |
uvToRenderTargetUV(float2) | float2 | 转换 UV 坐标以允许从 RenderTarget attachment 进行采样 |
- sampling from render targets
- 对于曲面域 (surface domain) 中的材质,从 filament::RenderTarget 的一个 filament::Texture采样时,请使用uvToRenderTargetUV变换纹理坐标。这会将根据正在使用的backend 来翻转坐标 (不同backend 对uv坐标的坐标轴定义不同)。
Handling colors
Linear colors
-
如果颜色数据来自纹理,只需确保使用 sRGB 纹理即可从 sRGB 到线性的自动硬件转换中受益。
-
如果颜色数据作为参数传递给材质,则可以通过在每个颜色通道上运行以下算法,将 sRGB 转换为线性:
float sRGB_to_linear(float color) { return color <= 0.04045 ? color / 12.92 : pow((color + 0.055) / 1.055, 2.4); }
-
或者,可以使用下面两个简化、但不太准确的版本之一:
// Cheaper linearColor = pow(color, 2.2); // Cheapest linearColor = color * color;
Pre-multiplied alpha
-
如果颜色的 RGB 分量乘以 Alpha 通道,则使用Pre-multiplied alpha:
// Compute pre-multiplied color color.rgb *= color.a;
-
如果从纹理中对颜色进行采样,则只需确保提前 pre-multiplied 纹理数据即可。
- 默认情况下,在 Android 设备上,从 Bitmap 上传的任何纹理都将预先 pre-multiplied。
总结
本节主要整理一下材质框架使用的API,以便后期进行查询使用。