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. 最佳实践:优先使用内置属性,除非需要传递自定义计算结果
相关推荐
Mr Xu_23 分钟前
Vue 3 中计算属性的最佳实践:提升可读性、可维护性与性能
前端·javascript
子兮曰38 分钟前
深入理解滑块验证码:那些你不知道的防破解机制
前端·javascript·canvas
Highcharts.js41 分钟前
【Highcharts】如何用命令行渲染导出图片?
javascript·导出·开发文档·highcharts·命令行渲染·命令行功能
陈振wx:zchen20082 小时前
JavaScript
javascript·js
我是伪码农2 小时前
Vue 智慧商城项目
前端·javascript·vue.js
不认输的西瓜2 小时前
fetch-event-source源码解读
前端·javascript
天下代码客3 小时前
使用electronc框架调用dll动态链接库流程和避坑
前端·javascript·vue.js·electron·node.js
冰暮流星4 小时前
javascript之数组
java·前端·javascript
xkxnq5 小时前
第五阶段:Vue3核心深度深挖(第74天)(Vue3计算属性进阶)
前端·javascript·vue.js
三小河5 小时前
Agent Skill与Rules的区别——以Cursor为例
前端·javascript·后端