Rendering custom primitive gives same color.

Hello, I’m have a custom primitive, I create a bunch of them, each one with a different location and color:

private createVertexArray(context: any) {

   this._dirty = false;

   let vertexBuffer = Cesium.Buffer.createVertexBuffer({
      context: context,
      typedArray: new Float32Array(this._points.outerPositions),
      usage: Cesium.BufferUsage.STATIC_DRAW
   });

   let attributes = [
      {
         index: 0,
         enabled: true,
         vertexBuffer: vertexBuffer,
         componentsPerAttribute: 3,
         componentDatatype: Cesium.ComponentDatatype.FLOAT,
         normalize: false,
         offsetInBytes: 0,
         strideInBytes: 0
      },
      {
         index: 1,
         enabled: true,
         value: this._color,
         componentsPerAttribute: 4,
         componentDatatype: Cesium.ComponentDatatype.FLOAT,
         normalize: false,
         offsetInBytes: 0,
         strideInBytes: 0
      }
   ];

I do get a different position for each one but I get the same color for all for some reason, I debugged cesium and saw that the color is indeed different for each drawcommand, I’m clueless of what could cause this, my code is attached, I’d love some help or guess of what could cause this.

Is this._color a single color or a typed array? If it’s a typed array you should set vertexBuffer instead of value. Setting value will result in the same color for every vertex.

I think you misunderstood me, The problem is not that I get the same color for every vertex, the problem is that I get the same color for every primitive instance.
I draw 10 primitives, they are all in different positions as they have different positions.

They all have a different color but they all use the color of the last created primitive.

for example, If I create 3 primitives, blue, red, green, I will see them transition from blue red green and stay green, I do not understand how they share this color as its instance specific.

Oh ok. Do you have a larger code example? Is it possible that all instances that are sharing the same color are using the same Color object somehow?

Hii, yes I’ve attached the code to this post, and no. when I debug cesium itself I can see that each instance of the drawcommand had a different color.

export class EllipsePrimitive {
   private _center: any;
   private _semiMajor: number;
   private _semiMinor: number;
   private _rotation: number;
   private _show: boolean;
   private _material: any;
   private _modelMatrix: any;
   private _renderState;
   private _drawCommand;
   private _points;
   private _indexBufferArray;
   private _indicesArray;
   private _dirty = true;
   private _lastMode;
   private _color;
   private vertexArray;
   private _shaderProgram;

   constructor(options: {center: any, semiMajorAxis: number, semiMinorAxis: number, rotation?: number, show?: boolean, color?:number[]}) {
      this._center = Cesium.Cartesian3.clone(options.center);
      this._semiMajor = options.semiMajorAxis;
      this._semiMinor = options.semiMinorAxis;
      this._rotation = options.rotation || 0;
      this._show = options.show || true;
      this._material = Cesium.Material.fromType(Cesium.Material.ColorType);
      this._modelMatrix = Cesium.Matrix4.clone(Cesium.Matrix4.IDENTITY);
      this._drawCommand = new Cesium.DrawCommand({owner: this});
      this._color = options.color || [0.0, 0.0, 0.0, 1.0];

      this.calculatePoints();
   }

   get center(): any {
      return this._center;
   }

   set center(value: any) {
      if (this._center !== value) {
         this._center = value;
         this._dirty = true;
      }
   }

   private set points(value) {
      if (!this._indexBufferArray || (this._points && this._points.outerPositions && this._points.outerPositions.length !== value.outerPositions.length)) {
         this._indicesArray = EllipsePrimitive.createIndicesArray(value.outerPositions.length);
      }

      this._points = value;
   }

   updateLocationData(data: {center?, semiMajorAxis?: number, semiMinorAxis?: number, rotation?: number}) {
      this.center = data.center || this._center;

      this.calculatePoints();
   }

   update(frameState) {
      if (!this._show) {
         return;
      }

      let context = frameState.context;

      this.vertexArray = (this._dirty || !this.vertexArray) ? this.createVertexArray(context) : this.vertexArray;
      this.setupShaderProgram(context);
      this.setupRenderState();
      this.setupDrawCommand();

      frameState.commandList.push(this._drawCommand);
   }

   private sceneModeChanged(mode: number) {
      return this._lastMode !== mode;
   }

   private createVertexArray(context: any) {

      this._dirty = false;

      let vertexBuffer = Cesium.Buffer.createVertexBuffer({
         context: context,
         typedArray: new Float32Array(this._points.outerPositions),
         usage: Cesium.BufferUsage.STATIC_DRAW
      });

      let attributes = [
         {
            index: 0,
            enabled: true,
            vertexBuffer: vertexBuffer,
            componentsPerAttribute: 3,
            componentDatatype: Cesium.ComponentDatatype.FLOAT,
            normalize: false,
            offsetInBytes: 0,
            strideInBytes: 0
         },
         {
            index: 1,
            enabled: true,
            value: this._color,
            componentsPerAttribute: 4,
            componentDatatype: Cesium.ComponentDatatype.FLOAT,
            normalize: false,
            offsetInBytes: 0,
            strideInBytes: 0
         }
      ];

      return new Cesium.VertexArray({
         context: context,
         attributes: attributes,
         indexBuffer: this.createIndexBuffer(context)
      });
   }

   private setupShaderProgram(context: any) {
      this._shaderProgram = this._shaderProgram || Cesium.ShaderProgram.replaceCache({
            context: context,
            shaderProgram: this._shaderProgram,
            vertexShaderSource: `
                attribute vec3 position;
                attribute vec4 color;
                varying vec4 v_color;

            void main() {
                gl_Position = czm_modelViewProjection * vec4(position, 1.0);
                v_color = color;
            }`,
            fragmentShaderSource: `
            varying vec4 v_color;
            void main()
            {
                gl_FragColor = v_color;
            }`
         });
   }

   private setupRenderState() {
      this._renderState = Cesium.RenderState.fromCache({
         cull: {
            enabled: true,
            face: Cesium.CullFace.FRONT
         },
         depthTest: {
            enabled: false
         },
         depthMask: true,
         blending: undefined
      });
   }

   private setupDrawCommand() {
      this._drawCommand.modelMatrix = this._modelMatrix;
      this._drawCommand.renderState = this._renderState;
      this._drawCommand.primitiveType = Cesium.PrimitiveType.LINE_LOOP;
      this._drawCommand.shaderProgram = this._shaderProgram;
      this._drawCommand.vertexArray = this.vertexArray;
      this._drawCommand.pass = Cesium.Pass.OPAQUE;
      this._drawCommand.boundingVolume = this.createBoundingVolume();
      this._drawCommand.debugShowBoundingVolume = false;
   }

   private calculatePoints() {
      this.points = Cesium.EllipseGeometryLibrary.computeEllipsePositions({
         center: this._center,
         rotation: this._rotation,
         semiMajorAxis: this._semiMajor,
         semiMinorAxis: this._semiMinor,
         granularity: 0.03
      }, false, true);
   }

   private createIndexBuffer(context) {
      this._indexBufferArray = Cesium.Buffer.createIndexBuffer({
         context: context,
         typedArray: this._indicesArray,
         usage: Cesium.BufferUsage.STATIC_DRAW,
         indexDatatype: Cesium.IndexDatatype.UNSIGNED_SHORT
      });
   }

   private static createIndicesArray(size: number) {
      let indicesArray = [];

      for (let i = 0; i < size / 3; i++) {
         indicesArray.push(i);
      }

      return new Uint16Array(indicesArray);
   }

   private createBoundingVolume() {
      return new Cesium.BoundingSphere(this._center, this._semiMajor);
   }

   private createInnerIndexBuffer(context: any) {
      let indicesArray = [];

      for (let i = 1; i < this._points.positions.length / 3; i++) {
         indicesArray.push(i - 1);
         indicesArray.push(i);
         indicesArray.push(i + 1);
      }

      return Cesium.Buffer.createIndexBuffer({
         context: context,
         typedArray: new Uint16Array(indicesArray),
         usage: Cesium.BufferUsage.STATIC_DRAW,
         indexDatatype: Cesium.IndexDatatype.UNSIGNED_SHORT
      });
   }
}

After some investigation there was a bug in the rendering engine. Here’s the PR with more details: https://github.com/AnalyticalGraphicsInc/cesium/pull/4995

David,

The vertex array issue was fixed in #4995.

Thanks,

Patrick

Thank you I saw :), when will you release the next version to npm ?

We publish to npm the same time we publish the Cesium release to the website- the first week day of every month. The next release will be available March 1st.

-Hannah