Rendering a large rectangle with opacity makes fps drop in half. How to improve performance?

I have the code below that allows a user to draw a rectangle in Sandcastle by holding down SHIFT and then click and dragging. I found however when in full screen, the frame rate drops in half when the rectangle is there. Replacing the rectangle with a solid one improves the performance quite a bit, but I need transparency on mine. Are there recommended ways to draw transparent rectangles in a performant manner?

https://gist.github.com/theplatapi/0a7d789afc8028a3c20b

Is this a ground primitive on terrain? Ground primitives are currently limited by video card fill rate (meaning performance is proportional to how many pixels the polygon takes up on screen and how good your card is). Performance will improve once we also improve our terrain meta-data to include some extra min/max height information we need to reduce the size of the shadow volume; but there’s no set ETA for that change. I believe there are also WebGL2 features that will improve things further once they become available. WebGL limitations compared to desktop GL is one of the main barriers for ground primitives.

If this isn’t a ground primitive, than that’s puzzling.

I'm not using any terrain in the code linked in my previous post. It's just a plain rectangle. Even if I change the height so it's off the groups I get the same drop in performance. Does it happen for you when you try it?

I’ve not seen the problem you’re referring to. Can you create a small Sandcastle example to show the issue? http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html (or better yet point to an existing example that recreates the problem for you).

Also, can you tell us what your system specs are. OS and version, Browser and version, video card model. Finally, can you copy and paste the result of http://webglreport.com/ (you can just select all and copy the text).

Thanks

I can still reprodice it with the code for sandcastle is in this github gist here: https://gist.github.com/theplatapi/0a7d789afc8028a3c20b. To see it in the context of the full app I'm building, you can see it here: http://climatevisualize.s3-website-us-west-2.amazonaws.com/. Note that the initial load will take up to half a minute, as it's downloading a lot of weather data. For both examples use shift-click-drag to create the rectangle.

The performance drop only happens when I enter fullscreen mode and create the rectangle. When drawing a rectangle covering North America, my fps drops to around 30 and then after a few seconds climbs back up to 40fps. A regular solid rectangle displays at 50fps.

I have a Macbook Air running OS X El Capitan. I'm using Google Chrome on version 48.0.2564.109 (64-bit). My graphics card is an Intel HD Graphics 5000 1536 MB.

Here is the output from the WebGL Report:

Platform: MacIntel
Browser User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36
Context Name: webgl
GL Version: WebGL 1.0 (OpenGL ES 2.0 Chromium)
Shading Language Version: WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)
Vendor: WebKit
Renderer: WebKit WebGL
Unmasked Vendor: Intel Inc.
Unmasked Renderer: Intel HD Graphics 5000 OpenGL Engine
Antialiasing: Available
ANGLE: No
Major Performance Caveat: No

Here is the rest of the output from the WebGL report:

Vertex Shader
Max Vertex Attributes: 16
Max Vertex Uniform Vectors: 1024
Max Vertex Texture Image Units: 16
Max Varying Vectors: 15
Best float precision: [-2127, 2127] (23)

Transform Feedback
Coming in WebGL 2

Rasterizer
Aliased Line Width Range: [1, 7]
Aliased Point Size Range: [1, 255]

Fragment Shader
Max Fragment Uniform Vectors: 1024
Max Texture Image Units: 16
float/int precision: highp/highp
Best float precision: [-2127, 2127] (23)

Framebuffer
Max Color Buffers: 8
RGBA Bits: [8, 8, 8, 8]
Depth / Stencil Bits: [24, 8]
Max Render Buffer Size: 16384
Max Viewport Dimensions: [16384, 16384]

Textures
Max Texture Size: 16384
Max Cube Map Texture Size: 1024
Max Combined Texture Image Units: 16
Max Anisotropy: 16

Uniform Buffers
Coming in WebGL 2

Supported Extensions:
ANGLE_instanced_arrays
EXT_blend_minmax
EXT_frag_depth
EXT_shader_texture_lod
EXT_sRGB
EXT_texture_filter_anisotropic
WEBKIT_EXT_texture_filter_anisotropic
OES_element_index_uint
OES_standard_derivatives
OES_texture_float
OES_texture_float_linear
OES_texture_half_float
OES_texture_half_float_linear
OES_vertex_array_object
WEBGL_compressed_texture_s3tc
WEBKIT_WEBGL_compressed_texture_s3tc
WEBGL_debug_renderer_info
WEBGL_debug_shaders
WEBGL_depth_texture
WEBKIT_WEBGL_depth_texture
WEBGL_draw_buffers
WEBGL_lose_context
WEBKIT_WEBGL_lose_context

Let me know if you need any more information or a different Sandcastle example.

Hello,

The slow down is happening because you’re using a CallbackProperty for the Rectangle coordinates. This is necessary for when you’re drawing the Rectangle to avoid blinking or other artifacts, but once the Rectangle is drawn you should replace the coordinates with a static Rectangle. Otherwise the rectangle will continue to re-draw every frame, this resulting in the lag.

Best,

Hannah

That definitely helps out performance. One last question though. When I switch the callback property to a static property, the rectangle flashes. I updated the gist below that reproduces this. Is there any way to avoid this?

https://gist.github.com/theplatapi/0a7d789afc8028a3c20b

I don’t know of any way to fix that using the Entity API. What you could to is remove the rectangle entity and replace it using the primitive API to draw the static rectangle synchronously like this:

var rectangleInstance = new Cesium.GeometryInstance({
geometry : Cesium.RectangleGeometry.createGeometry(new Cesium.RectangleGeometry({
rectangle : Cesium.Rectangle.fromDegrees(-110.0, 40.0, -100.0, 45.0),
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
})),
attributes: {
color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 0.0, 0.0, 0.5))
},
});

var rectanglePrimitive = scene.primitives.add(new Cesium.Primitive({
geometryInstances : rectangleInstance,
appearance : new Cesium.PerInstanceColorAppearance({
closed : true
}),
asynchronous: false
}));

``

You can use scene.primtives.remove(rectanglePrimitive) to remove the primitive when you want to start drawing another rectangle.

Best,

Hannah