片元阶段
gsplatModifyPS 在片元阶段定制最终颜色,每覆盖像素一次,允许效果在单元覆盖范围内平滑变化,逐单元顶点阶段无法做到这一点。
查看实时示例:每个单元绘制为自身颜色的圆环,并带高亮波。
查看实时示例
可覆盖函数
只覆盖一个函数:
- GLSL
- WGSL
void modifySplatColor(vec2 gaussianUV, inout vec4 color);
fn modifySplatColor(gaussianUV: vec2f, color: ptr<function, vec4f>);
它在前向通道、高斯衰减和不透明度抖动之后,预乘颜色与输出之前调用:
- gaussianUV:片元在覆盖范围内的位置,中心为 (0,0),裁剪边缘长度为 1。
dot(gaussianUV, gaussianUV)是衰减使用的归一化半径平方。 - color:rgb 为单元颜色,a 为最终片元 alpha。均可修改,alpha 影响混合权重,可自定义衰减或逐像素淡出。
可用输入
代码块还可访问:
- gl_FragCoord(GLSL)或 pcPosition(WGSL):片元在帧缓冲区中的像素位置。
- screen_size:引擎提供的 vec4/vec4f,xy 为画布绘制缓冲区像素尺寸,zw 为倒数。与 viewport_size 的区别见内置 uniform。
- 自行声明并通过材质参数驱动的 uniform 与纹理。
示例
示例将每个单元绘制为自身颜色的圆环。gaussianUV 给出内部位置,fwidth 将要求的像素环宽转为覆盖范围单位,让任意缩放下屏幕宽度恒定:
- GLSL
- WGSL
uniform float uRingWidth;
uniform float uRingAlpha;
void modifySplatColor(vec2 gaussianUV, inout vec4 color) {
// distance from the splat center: 0 at center, 1 at the clipping edge
float radius = length(gaussianUV);
// ring of constant screen-space width at the splat edge - fwidth gives the
// change of radius per screen pixel, converting pixels to radius units
float radiusPerPixel = fwidth(radius);
float innerEdge = 1.0 - uRingWidth * radiusPerPixel;
float ring = smoothstep(innerEdge - radiusPerPixel, innerEdge, radius);
color.a = ring * uRingAlpha;
}
uniform uRingWidth: f32;
uniform uRingAlpha: f32;
fn modifySplatColor(gaussianUV: vec2f, color: ptr<function, vec4f>) {
// distance from the splat center: 0 at center, 1 at the clipping edge
let radius = length(gaussianUV);
// ring of constant screen-space width at the splat edge - fwidth gives the
// change of radius per screen pixel, converting pixels to radius units
let radiusPerPixel = fwidth(radius);
let innerEdge = 1.0 - uniform.uRingWidth * radiusPerPixel;
let ring = smoothstep(innerEdge - radiusPerPixel, innerEdge, radius);
*color = vec4f((*color).rgb, ring * uniform.uRingAlpha);
}
与顶点代码块相同,用 gsplatModifyPS 键应用,再通过材质参数驱动:
const sceneMat = app.scene.gsplat.material;
sceneMat.getShaderChunks('glsl').set('gsplatModifyPS', glslFragShader);
sceneMat.getShaderChunks('wgsl').set('gsplatModifyPS', wgslFragShader);
sceneMat.setParameter('uRingWidth', 1);
sceneMat.setParameter('uRingAlpha', 0.25);
sceneMat.update();
按每片元屏幕位置采样对齐纹理的效果,参见重新光照,它利用离屏代理网格光照调制单元。
另请参见
- 顶点阶段:移动、缩放和染色。
- Varying 数据流:读取顶点写入的逐单元值。
- 重新光照:基于本钩子的代理网格照明。