铯基元(三角形)着色
Cesium primitives (triangles) shading
我使用这段代码在 Cesium 中绘制三角形:
var mypositions = Cesium.Cartesian3.fromDegreesArrayHeights(triangles);
// unroll 'mypositions' into a flat array here
var numPositions = mypositions.length;
var pos = new Float64Array(numPositions * 3);
var normals = new Float32Array(numPositions * 3);
for (var i = 0; i < numPositions; ++i) {
pos[i * 3] = mypositions[i].x;
pos[i * 3 + 1] = mypositions[i].y;
pos[i * 3 + 2] = mypositions[i].z;
normals[i * 3] = 0.0;
normals[i * 3 + 1] = 0;
normals[i * 3 + 2] = 1.0;
}
console.log(normals)
var geometry = new Cesium.Geometry({
vertexFormat : Cesium.VertexFormat.ALL,
attributes: {
position: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.DOUBLE, // not FLOAT
componentsPerAttribute: 3,
values: pos
}),
normal: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 3,
values: normals
})
},
// Don't need the following line if no vertices are shared.
// indices: new Uint32Array([0, 1, 2, 3, 4, 5]),
primitiveType: Cesium.PrimitiveType.TRIANGLES,
boundingSphere: Cesium.BoundingSphere.fromVertices(pos)
});
var myInstance = new Cesium.GeometryInstance({
geometry: geometry,
attributes: {
color: new Cesium.ColorGeometryInstanceAttribute(0.0039215697906911,
0.7333329916000366,
0,
1)
},
show: new Cesium.ShowGeometryInstanceAttribute(true)
});
var TIN = viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: [myInstance],
asynchronous: false,
appearance: new Cesium.PerInstanceColorAppearance({
closed: true,
translucent: false,
flat: false
//,
//vertexShaderSource: "",
//fragmentShaderSource: ""
})
}));
这是我得到的:
我想启用阴影,所以结果应该类似于下图:
我尝试编写顶点和片段 GLSL 着色器但没有成功。我不熟悉 GLSL,我遇到了编译错误。还有其他方法可以创建这种阴影吗?
谢谢!
不管您还没有发布您的 GLSL 着色器或让它工作,您的问题(一旦您最终弄清楚了 GLSL 的东西)是您将所有法线设置为指向 + Z 方向而不是实际上垂直于每个三角形,就像你的第二个屏幕截图显示的那样。
var normals = new Float32Array(numPositions * 3);
for (var i = 0; i < numPositions; ++i) {
pos[i * 3] = mypositions[i].x;
pos[i * 3 + 1] = mypositions[i].y;
pos[i * 3 + 2] = mypositions[i].z;
normals[i * 3] = 0.0;
normals[i * 3 + 1] = 0;
normals[i * 3 + 2] = 1.0;
}
您需要做的是设置位置,然后对于法线,对 3 个顶点(三角形)而不是单个顶点进行操作。这样你就可以实际计算出表面法线。这是如何做到这一点的众多解释之一:
https://math.stackexchange.com/questions/305642/how-to-find-surface-normal-of-a-triangle
我不熟悉 Cesium,但我想会有一些 "default" 着色器可以进行基本照明。如果没有,那么像这样简单照明的基础就叫Lambertian reflectance。您的顶点着色器将输出一种计算为 dot(N, L)
的颜色,其中 N 是您的顶点的法线,L 是从该顶点到您的光源的矢量(或者如果它是directional/environment/sun/etc 光)。片段着色器将简单地传递回该颜色。
我使用这段代码在 Cesium 中绘制三角形:
var mypositions = Cesium.Cartesian3.fromDegreesArrayHeights(triangles);
// unroll 'mypositions' into a flat array here
var numPositions = mypositions.length;
var pos = new Float64Array(numPositions * 3);
var normals = new Float32Array(numPositions * 3);
for (var i = 0; i < numPositions; ++i) {
pos[i * 3] = mypositions[i].x;
pos[i * 3 + 1] = mypositions[i].y;
pos[i * 3 + 2] = mypositions[i].z;
normals[i * 3] = 0.0;
normals[i * 3 + 1] = 0;
normals[i * 3 + 2] = 1.0;
}
console.log(normals)
var geometry = new Cesium.Geometry({
vertexFormat : Cesium.VertexFormat.ALL,
attributes: {
position: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.DOUBLE, // not FLOAT
componentsPerAttribute: 3,
values: pos
}),
normal: new Cesium.GeometryAttribute({
componentDatatype: Cesium.ComponentDatatype.FLOAT,
componentsPerAttribute: 3,
values: normals
})
},
// Don't need the following line if no vertices are shared.
// indices: new Uint32Array([0, 1, 2, 3, 4, 5]),
primitiveType: Cesium.PrimitiveType.TRIANGLES,
boundingSphere: Cesium.BoundingSphere.fromVertices(pos)
});
var myInstance = new Cesium.GeometryInstance({
geometry: geometry,
attributes: {
color: new Cesium.ColorGeometryInstanceAttribute(0.0039215697906911,
0.7333329916000366,
0,
1)
},
show: new Cesium.ShowGeometryInstanceAttribute(true)
});
var TIN = viewer.scene.primitives.add(new Cesium.Primitive({
geometryInstances: [myInstance],
asynchronous: false,
appearance: new Cesium.PerInstanceColorAppearance({
closed: true,
translucent: false,
flat: false
//,
//vertexShaderSource: "",
//fragmentShaderSource: ""
})
}));
这是我得到的:
我想启用阴影,所以结果应该类似于下图:
我尝试编写顶点和片段 GLSL 着色器但没有成功。我不熟悉 GLSL,我遇到了编译错误。还有其他方法可以创建这种阴影吗?
谢谢!
不管您还没有发布您的 GLSL 着色器或让它工作,您的问题(一旦您最终弄清楚了 GLSL 的东西)是您将所有法线设置为指向 + Z 方向而不是实际上垂直于每个三角形,就像你的第二个屏幕截图显示的那样。
var normals = new Float32Array(numPositions * 3);
for (var i = 0; i < numPositions; ++i) {
pos[i * 3] = mypositions[i].x;
pos[i * 3 + 1] = mypositions[i].y;
pos[i * 3 + 2] = mypositions[i].z;
normals[i * 3] = 0.0;
normals[i * 3 + 1] = 0;
normals[i * 3 + 2] = 1.0;
}
您需要做的是设置位置,然后对于法线,对 3 个顶点(三角形)而不是单个顶点进行操作。这样你就可以实际计算出表面法线。这是如何做到这一点的众多解释之一:
https://math.stackexchange.com/questions/305642/how-to-find-surface-normal-of-a-triangle
我不熟悉 Cesium,但我想会有一些 "default" 着色器可以进行基本照明。如果没有,那么像这样简单照明的基础就叫Lambertian reflectance。您的顶点着色器将输出一种计算为 dot(N, L)
的颜色,其中 N 是您的顶点的法线,L 是从该顶点到您的光源的矢量(或者如果它是directional/environment/sun/etc 光)。片段着色器将简单地传递回该颜色。