您现在的位置是:首页 >其他 >Cesium-CustomShader给3dtiles加贴图网站首页其他
Cesium-CustomShader给3dtiles加贴图
简介Cesium-CustomShader给3dtiles加贴图
一、需求
Cesium加载3dtiles是非常高频的使用需求,但是对于用户自己处理过的3dtiles文件可能需要一些特效,这种时候仅仅依赖Cesium原生的渲染就无法达到因此必须拓展。
二、为什么是CustomShader
为什么要做这个工作,可以看这个大佬的文章:https://www.cnblogs.com/HelsingWang/p/13531172.html
这里解释得很清楚虽然在Cesium中3dties是通过primitive的方式添加的:
var tileset = scene.primitives.add(new Cesium.Cesium3DTileset({
url : 'http://localhost:8002/tilesets/Seattle/tileset.json',
skipLevelOfDetail : true,
baseScreenSpaceError : 1024,
skipScreenSpaceErrorFactor : 16,
skipLevels : 1,
immediatelyLoadDesiredLevelOfDetail : false,
loadSiblings : false,
cullWithChildrenBounds : true
});
但是这种添加不是同于一般primitive添加方式:可以直接在appearance属性中添加材质对象
scene.primitives.add(new Cesium.Primitive({
geometryInstances : instance,
appearance : new Cesium.EllipsoidSurfaceAppearance({
material : Cesium.Material.fromType('Checkerboard')
})
});
这种材质对象是广义的,除了上述这种预定义的材质,还可以使用Fabric来定义材质:
material: new Cesium.Material({
fabric: {
uniforms: {
image: url
},
source: ms
}
})
甚至可以使用source写shader。但是很遗憾,3dtiles不支持这样做。那么在Cesium 1.87之后提供了CustomShader方式来为3dtiles加shader;
三、怎么做
看一个customshader的例子:https://blog.csdn.net/weixin_45174000/article/details/129240933
这个大佬呢给出了我感觉流程最全的一个示例:
var customShader = new Cesium.CustomShader({
// lightingModel: Cesium.LightingModel.UNLIT,
// lightingModel: Cesium.LightingModel.PBR,
//设置变量,由顶点着色器传递给片元着色器
varyings: {
v_normalMC: Cesium.VaryingType.VEC3,
v_st: Cesium.VaryingType.VEC3
},
//外部传给顶点着色器或者片元着色器
uniforms: {
u_texture: {
value: new Cesium.TextureUniform({
url: '/Assets/Images/buildWall.jpg'
}),
type: Cesium.UniformType.SAMPLER_2D
},
u_texture1: {
value: new Cesium.TextureUniform({
url: '/Assets/Images/buildWall1.jpg'
}),
type: Cesium.UniformType.SAMPLER_2D
}
},
//贴纹理
//顶点着色器
//将法向量从顶点着色器设置变量传给片元着色器
vertexShaderText: `
void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
v_normalMC = vsInput.attributes.normalMC;
v_st=vsInput.attributes.positionMC ;
}`,
//片元着色器
fragmentShaderText: `
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
vec3 positionMC = fsInput.attributes.positionMC;
//这里是设置要贴图的图片的尺寸,设置小了会重复
float width = 37.0;
float height = 40.0;
vec3 rgb;
//这是是设置了屋顶的颜色,当和法向量平行时,就是屋顶,这里设置0.95,相当于垂直,建筑物四周开始贴图
if (dot(vec3(0.0, 1.0, 0.0), v_normalMC) > 0.95) {
material.diffuse = vec3(1.0, 0.0, 0.0);
} else {
float textureX = 0.0;
float dotYAxis = dot(vec3(0.0, 0.0, 1.0), v_normalMC);
// cos(45deg) 约等于 0.71,这里是建筑物四周的向量与法向量会大于四十五度夹角
if (dotYAxis > 0.71 || dotYAxis < -0.71) {
//x代表的是前后面
textureX = mod(positionMC.x, width) / width;
} else {
//z代表的是左右面
textureX = mod(positionMC.z, width) / width;
}
float textureY = mod(positionMC.y, height) / height;
//我这里是根据建筑物高度贴了两张不同的图片
if (positionMC.y > 30.0) {
rgb = texture2D(u_texture1, vec2(textureX, textureY)).rgb;
} else {
rgb = texture2D(u_texture, vec2(textureX, textureY)).rgb;
}
material.diffuse = rgb;
}
}`
})
tilesets.customShader = customShader
然后如果想要了解其中的原理可以看看:Cesium3Dtilesets 使用customShader的解读以及泛光效果示例_3d_liuqing0.0-DevPress官方社区 (csdn.net)
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。