Uniform переменные в шейдерах WebGL в контексте CesiumJS представляют собой механизм передачи данных из JavaScript-кода в GPU-шейдеры, которые выполняются на стороне видеокарты. Uniform остаются неизменными в пределах одного вызова отрисовки и служат основным способом управления визуальными параметрами материалов, эффектов и процедурной генерации.
В архитектуре CesiumJS uniform-данные используются на нескольких уровнях: в материалах (Material), в appearance объектов (Appearance), в кастомных шейдерах Primitive, а также в постобработке сцены. Их роль заключается в связывании логики приложения с графическим конвейером WebGL без необходимости пересоздания шейдера при каждом изменении параметров.
В WebGL uniform — это глобальные переменные шейдера, доступные только для чтения в GLSL-коде. CesiumJS абстрагирует работу с ними через JavaScript-объекты, автоматически обновляя значения при рендере сцены.
В типичном случае uniform объявляется в GLSL:
uniform float u_time;
uniform vec3 u_color;
uniform float u_intensity;
В JavaScript-слое CesiumJS этим переменным соответствует объект
uniforms, передаваемый в материал или шейдерную
конфигурацию:
material.uniforms = {
u_time: 0.0,
u_color: Cesium.Color.RED,
u_intensity: 1.0
};
Движок выполняет автоматическое преобразование типов Cesium → GLSL,
включая Color, Cartesian3, числа и
текстуры.
Материальная система CesiumJS использует uniform как основной способ параметризации процедурных материалов.
Материал определяется через Cesium.Material, где
GLSL-код описывает визуальное поведение:
const pulseMaterial = Cesium.Material.fromType("Color");
pulseMaterial.uniforms.color = Cesium.Color.YELLOW;
В кастомных материалах структура расширяется:
Cesium.Material._materialCache.addMaterial("pulseMaterial", {
fabric: {
type: "pulseMaterial",
uniforms: {
time: 0.0,
speed: 2.0,
color: Cesium.Color.WHITE
},
source: `
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
float t = sin(time * speed);
material.diffuse = color.rgb * t;
material.alpha = 1.0;
return material;
}
`
}
});
Здесь uniforms становятся частью fabric-описания
материала, а Cesium автоматически прокидывает их в шейдер.
Одним из ключевых применений uniform является динамическое изменение параметров во времени. CesiumJS предоставляет механизм обновления значений на каждом кадре через callback-функции.
const material = new Cesium.Material({
fabric: {
type: "DynamicColor",
uniforms: {
time: () => performance.now() * 0.001,
color: Cesium.Color.BLUE
},
source: `
czm_material czm_getMaterial(czm_materialInput input)
{
czm_material m = czm_getDefaultMaterial(input);
m.diffuse = color.rgb * abs(sin(time));
return m;
}
`
}
});
В данном случае uniform time вычисляется на лету, что
позволяет создавать анимационные эффекты без ручного обновления
сцены.
На уровне Primitive API uniform используются более явно, так как разработчик напрямую управляет шейдером.
const primitive = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(-100, 30, -90, 40)
})
}),
appearance: new Cesium.MaterialAppearance({
material: new Cesium.Material({
fabric: {
type: "CustomShader",
uniforms: {
brightness: 1.5,
offset: 0.2
},
source: `
czm_material czm_getMaterial(czm_materialInput input)
{
czm_material material = czm_getDefaultMaterial(input);
material.diffuse = vec3(brightness - offset);
return material;
}
`
}
})
})
});
Primitive слой требует строгого соответствия типов uniform и GLSL, поскольку отсутствует высокий уровень абстракции Entity API.
CesiumJS поддерживает несколько типов данных для uniform:
float → JavaScript Numbervec2/vec3/vec4 → Cesium.Cartesian2 / Cartesian3 /
Colormat3/mat4 → Cesium.Matrix3 / Matrix4sampler2D → Cesium.TextureПример передачи текстуры:
material.uniforms.image = Cesium.buildModuleUrl("Assets/Textures/waterNormals.jpg");
Cesium автоматически загружает и связывает текстуру с uniform sampler2D.
В шейдерах CesiumJS присутствует набор встроенных uniform и varying
переменных, начинающихся с префикса czm_. Они предоставляют
доступ к состоянию сцены:
czm_frameNumber — номер текущего кадраczm_viewerPosition — позиция камерыczm_sunDirection — направление солнцаczm_morphTime — время морфинга глобусаПример использования:
uniform float speed;
void main()
{
float t = czm_frameNumber * speed;
gl_FragColor = vec4(abs(sin(t)));
}
Эти значения не требуют ручной передачи из JavaScript, но могут комбинироваться с пользовательскими uniform.
В Entity API CesiumJS uniform-значения часто связываются с Property-объектами, позволяющими динамическое обновление на уровне данных.
entity.polygon.material = new Cesium.ColorMaterialProperty(
new Cesium.CallbackProperty(() => {
return Cesium.Color.fromRandom({ alpha: 1.0 });
}, false)
);
Внутри такие конструкции транслируются в uniform-параметры материала, обновляемые на каждом кадре.
CesiumJS минимизирует стоимость обновления uniform через внутренние механизмы кэширования:
Это критично для сцен с большим количеством объектов, где изменение одного параметра не должно приводить к дорогостоящей перекомпиляции GLSL.
При использовании Cesium.ShaderSource uniform становятся
частью единого графа шейдеров.
const shader = new Cesium.ShaderSource({
sources: [`
uniform float amplitude;
void main()
{
gl_FragColor = vec4(amplitude);
}
`]
});
Далее uniform привязывается через appearance:
appearance.uniforms = {
amplitude: 0.75
};
PostProcessStage также активно использует uniform для управления эффектами:
const stage = new Cesium.PostProcessStage({
fragmentShader: `
uniform float intensity;
void main()
{
vec4 color = texture2D(colorTexture, v_textureCoordinates);
gl_FragColor = color * intensity;
}
`,
uniforms: {
intensity: 1.2
}
});
Здесь uniform влияет на финальный цвет кадра после рендеринга сцены.
Uniform в CesiumJS имеют ряд технических ограничений WebGL:
При сложных сценах предпочтение отдается текстурам или uniform buffer objects (в расширенных конфигурациях WebGL2).
В сложных приложениях uniform структурируются как конфигурационные слои:
const uniforms = {
global: {
time: 0,
cameraHeight: 0
},
material: {
glowIntensity: 1.0,
colorShift: Cesium.Color.WHITE
}
};
Такой подход упрощает синхронизацию между различными шейдерными программами и снижает риск конфликтов имен.
Внутри render loop CesiumJS uniform обновляются на этапе подготовки команд отрисовки. Каждая primitive или entity формирует render command, содержащий:
GPU получает уже готовый пакет данных, минимизируя CPU overhead.
Uniform-подход в CesiumJS формирует базовый слой взаимодействия между JavaScript и GPU-шейдерами, обеспечивая управляемую, предсказуемую и высокопроизводительную модель изменения визуальных параметров в реальном времени.