Cesium自定义着色器-片元着色器数据来源

书接上文,前面说修改白膜渐变需要知道模型位置PositionMC,那这个是片元着色器内部属性,可以直接访问,还有一种是需要手动传递的,所以下面介绍片元着色器的数据来源:

片元着色器中数据的两种来源

1. 通过 Varying 从顶点着色器传递(需要手动设置)

ini 复制代码
let customShader = new Cesium.CustomShader({
    varyings: {
        v_customPosition: Cesium.VaryingType.VEC3,  // 自定义传递变量
        v_customNormal: Cesium.VaryingType.VEC3
    },
    
    vertexShaderText: `
        void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
            // 手动传递数据到片元着色器
            v_customPosition = vsInput.attributes.positionMC * 2.0; // 自定义计算
            v_customNormal = normalize(vsInput.attributes.normalMC);
        }`,
        
    fragmentShaderText: `
        void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
            // 使用通过varying传递的数据
            vec3 customPos = v_customPosition;
            vec3 customNorm = v_customNormal;
            
            material.diffuse = customNorm * 0.5 + 0.5; // 法线可视化
        }`
});

2. 直接通过 fsInput.attributes 访问(内置可用,无需传递)

ini 复制代码
let customShader = new Cesium.CustomShader({
    // 注意:这里没有定义varyings!
    
    vertexShaderText: `
        void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
            // 顶点着色器可以为空,或者处理其他逻辑
        }`,
        
    fragmentShaderText: `
        void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
            // 直接访问内置属性,无需通过varying传递
            vec3 positionMC = fsInput.attributes.positionMC;
            vec3 normalEC = fsInput.attributes.normalEC;
            vec2 texCoord = fsInput.attributes.texCoord_0;
            
            material.diffuse = vec3(texCoord, 0.0); // UV坐标可视化
        }`
});

内置可用的 fsInput.attributes

Cesium 自动提供以下内置属性:

几何属性:

arduino 复制代码
// 位置相关
vec3 positionMC;      // 模型坐标系位置
vec3 positionEC;      // 眼坐标系位置  
vec3 positionWC;      // 世界坐标系位置

// 法线相关
vec3 normalMC;        // 模型坐标系法线
vec3 normalEC;        // 眼坐标系法线

// 纹理坐标
vec2 texCoord_0;      // 第一套UV坐标
vec2 texCoord_1;      // 第二套UV坐标

其他属性:

arduino 复制代码
// 切线空间
vec3 tangentMC;       // 模型坐标系切线
vec3 bitangentMC;     // 模型坐标系副切线

// 颜色
vec3 color_0;         // 顶点颜色

什么时候需要用 Varying?

需要手动传递的情况:

1. 自定义计算的结果

arduino 复制代码
// 顶点着色器
v_customHeight = positionMC.y * 10.0;  // 自定义高度计算

// 片元着色器  
float height = v_customHeight;         // 使用自定义计算值

2. 修改后的数据

ini 复制代码
// 顶点着色器
v_modifiedNormal = normalMC * 2.0;     // 修改法线

// 片元着色器
vec3 normal = v_modifiedNormal;         // 使用修改后的法线

3. 复杂数据结构

scss 复制代码
// 需要传递多个相关数据时
v_customData = vec4(positionMC, normalMC.x); // 打包数据

实际示例对比

方案A:使用内置属性(推荐,简单)

ini 复制代码
// 直接使用内置的positionMC,不需要varying
fragmentShaderText: `
    void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
        vec3 positionMC = fsInput.attributes.positionMC;
        material.diffuse = vec3(0.0, 1.0 - positionMC.z * 0.005, 1.0);
    }`

方案B:使用Varying传递(复杂,不必要)

ini 复制代码
varyings: {
    v_positionMC: Cesium.VaryingType.VEC3
},

vertexShaderText: `
    void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
        v_positionMC = vsInput.attributes.positionMC; // 只是简单传递
    }`,

fragmentShaderText: `
    void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
        vec3 positionMC = v_positionMC; // 通过varying获取
        material.diffuse = vec3(0.0, 1.0 - positionMC.z * 0.005, 1.0);
    }`

总结

  1. 内置属性 :直接使用 fsInput.attributes.xxx,无需varying
  2. 自定义数据:需要通过varying手动传递
  3. 最佳实践:优先使用内置属性,除非需要传递自定义计算结果
相关推荐
UIUV3 小时前
var、let 与 const:JavaScript 变量声明的演进与最佳实践
javascript
阿珊和她的猫4 小时前
深入剖析 Vue Router History 路由刷新页面 404 问题:原因与解决之道
前端·javascript·vue.js
web打印社区13 小时前
使用React如何静默打印页面:完整的前端打印解决方案
前端·javascript·vue.js·react.js·pdf·1024程序员节
YiHanXii15 小时前
this 输出题
前端·javascript·1024程序员节
维他命Coco15 小时前
js常见开发学习
javascript
!win !16 小时前
分享二个实用正则
javascript·正则表达式
xw516 小时前
分享二个实用正则
javascript·正则表达式
刘新明198916 小时前
算法还原案例4-OLLVM_MD5
开发语言·前端·javascript·1024程序员节
诚实可靠王大锤16 小时前
react-native实现多列表左右滑动+滚动TabBar悬停
javascript·react native·react.js·1024程序员节