【问题标题】:Cesium primitives (triangles) shading铯基元(三角形)着色
【发布时间】:2018-11-26 02:15:30
【问题描述】:

我使用这段代码在 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,并且遇到了编译错误。有没有其他方法可以创建这种阴影?

谢谢!

【问题讨论】:

    标签: opengl-es glsl cesium


    【解决方案1】:

    不管你没有发布你的 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,但我想会有一些“默认”着色器可以进行基本照明。如果没有,那么像这样的简单照明的基础称为Lambertian reflectance。您的顶点着色器将输出计算为dot(N, L) 的颜色,其中 N 是顶点的法线,L 是从该顶点到光源的矢量(或者如果它是定向的,则只是光线方向的负数/环境/太阳/等光)。片段着色器只会将该颜色传回。

    【讨论】:

    • 你是对的,这是正常的问题。现在,我通过基本着色获得了良好的可视化效果。可以使用以下方法计算法线:Cesium.GeometryPipeline.computeNormal(geometry);,包括索引。
    猜你喜欢
    • 1970-01-01
    • 2018-01-05
    • 2020-07-17
    • 2021-08-02
    • 1970-01-01
    • 2015-01-06
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多