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. 最佳实践:优先使用内置属性,除非需要传递自定义计算结果
相关推荐
白兰地空瓶2 分钟前
你以为树只是画图?不——它是算法面试的“隐形主角”
前端·javascript·算法
兔老大的胡萝卜1 小时前
pm2 部署nuxt4项目
javascript·nuxt4
阿蒙Amon1 小时前
JavaScript学习笔记:17.闭包
javascript·笔记·学习
Wpa.wk1 小时前
自动化测试 - 文件上传 和 弹窗处理
开发语言·javascript·自动化测试·经验分享·爬虫·python·selenium
l1t1 小时前
利用小米mimo为精确覆盖矩形问题C程序添加打乱函数求出更大的解
c语言·开发语言·javascript·人工智能·算法
composurext1 小时前
录音切片上传
前端·javascript·css
程序员小寒1 小时前
前端高频面试题:深拷贝和浅拷贝的区别?
前端·javascript·面试
zhougl9961 小时前
Vue 中的 `render` 函数
前端·javascript·vue.js
跟着珅聪学java1 小时前
HTML中设置<select>下拉框默认值的详细教程
开发语言·前端·javascript
想睡好1 小时前
setup
前端·javascript·html