Skip to content

Commit

Permalink
Implemented ScatterplotLayer
Browse files Browse the repository at this point in the history
  • Loading branch information
ilijapuaca committed May 2, 2020
1 parent 3287fc2 commit cbe4516
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 183 deletions.
30 changes: 28 additions & 2 deletions cpp/examples/deck.gl/flight-paths.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,40 @@ auto createLineLayer(const std::string &dataPath) -> std::shared_ptr<LineLayer::
return lineLayerProps;
}

auto createScatterplotLayer(const std::string &dataPath) -> std::shared_ptr<ScatterplotLayer::Props> {
auto scatterplotLayerProps = std::make_shared<ScatterplotLayer::Props>();
scatterplotLayerProps->id = "airports";
scatterplotLayerProps->getPosition = [](const Row &row) -> mathgl::Vector3<float> {
return row.getVector3<float>("coordinates");
};
scatterplotLayerProps->getRadius = [](const Row &row) -> float {
auto type = row.getString("type");
if (type == "major") {
return 100.0f;
} else if (type == "small") {
return 30.0f;
} else {
return 60.0f;
}
};
scatterplotLayerProps->getFillColor = [](const Row &row) -> mathgl::Vector4<float> {
return mathgl::Vector4<float>{255.0f, 144.0f, 0.0f, 255.0f};
};
scatterplotLayerProps->radiusScale = 20.0f;
scatterplotLayerProps->data = jsonLoader.loadTable(fileSystem->OpenInputStream(dataPath).ValueOrDie());

return scatterplotLayerProps;
}

int main(int argc, const char *argv[]) {
// Get data file paths relative to working directory
auto programPath = std::string{argv[0]};
auto programDirectory = programPath.erase(programPath.find_last_of("/"));
auto flightDataPath = programDirectory.append("/data/heathrow-flights.ndjson");
auto flightDataPath = programDirectory + "/data/heathrow-flights.ndjson";
auto airportDataPath = programDirectory + "/data/airports.ndjson";

auto deckProps = std::make_shared<Deck::Props>();
deckProps->layers = {createLineLayer(flightDataPath)};
deckProps->layers = {createLineLayer(flightDataPath), createScatterplotLayer(airportDataPath)};
deckProps->initialViewState = createViewState(0.0);
deckProps->views = {std::make_shared<MapView>()};
deckProps->width = 640;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ layout(std140, set = 0, binding = 1) uniform LineLayerOptions {
} layerOptions;
layout(location = 0) in vec3 positions;
layout(location = 1) in vec3 instanceSourcePositions;
layout(location = 2) in vec3 instanceTargetPositions;
layout(location = 3) in vec4 instanceColors;
Expand Down Expand Up @@ -90,7 +91,7 @@ void main(void) {
// Color
vec4 color = vec4(instanceColors.rgb, instanceColors.a * layerOptions.opacity);
// Normalize the values
// Normalize the values
vColor = clamp(color, 0, 255) / 255.0;
}
)GLSL";
Expand Down
25 changes: 4 additions & 21 deletions cpp/modules/deck.gl/layers/src/line-layer/line-layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ using namespace deckgl;
using namespace lumagl;

const std::vector<const Property*> propTypeDefs = {
// new PropertyT<std::string>{"widthUnits",
// [](const JSONObject* props) { return dynamic_cast<const LineLayer*>(props)->widthUnits; },
// [](JSONObject* props, bool value) { return dynamic_cast<LineLayer*>(props)->widthUnits = value; },
// true},
new PropertyT<std::string>{
"widthUnits", [](const JSONObject* props) { return dynamic_cast<const LineLayer::Props*>(props)->widthUnits; },
[](JSONObject* props, std::string value) { return dynamic_cast<LineLayer::Props*>(props)->widthUnits = value; },
"pixels"},
new PropertyT<float>{
"widthScale", [](const JSONObject* props) { return dynamic_cast<const LineLayer::Props*>(props)->widthScale; },
[](JSONObject* props, float value) { return dynamic_cast<LineLayer::Props*>(props)->widthScale = value; }, 1.0},
Expand Down Expand Up @@ -105,23 +105,6 @@ void LineLayer::drawState(wgpu::RenderPassEncoder pass) {
std::make_shared<garrow::Array>(this->context->device, &layerUniforms, 1, wgpu::BufferUsage::Uniform), 1);
model->draw(pass);
}

/*
const {viewport} = this->context;
const {widthUnits, widthScale, widthMinPixels, widthMaxPixels} = ;
const widthMultiplier = widthUnits === 'pixels' ? viewport.metersPerPixel :
this->state.model
.setUniforms(
Object.assign({}, uniforms, {
widthScale: widthScale * widthMultiplier,
widthMinPixels,
widthMaxPixels
})
)
.draw();
*/
}

auto LineLayer::_getModel(wgpu::Device device) -> std::shared_ptr<lumagl::Model> {
Expand Down
9 changes: 5 additions & 4 deletions cpp/modules/deck.gl/layers/src/line-layer/line-layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ class LineLayer::Props : public Layer::Props {
return new LineLayer{std::dynamic_pointer_cast<LineLayer::Props>(props)};
}

std::string widthUnits{"pixels"}; // 'pixels',
float widthScale{1}; // {type: 'number', value: 1, min: 0},
float widthMinPixels{0}; // {type: 'number', value: 0, min: 0},
float widthMaxPixels{std::numeric_limits<float>::max()}; // {type: 'number', value: Number.MAX_SAFE_INTEGER, min: 0}
std::string widthUnits{"pixels"};
float widthScale{1};
float widthMinPixels{0};
float widthMaxPixels{std::numeric_limits<float>::max()};

/// Property accessors
std::function<ArrowMapper::Vector3FloatAccessor> getSourcePosition{
Expand All @@ -82,6 +82,7 @@ class LineLayer::Props : public Layer::Props {
std::function<ArrowMapper::FloatAccessor> getWidth{[](const Row&) { return 1.0; }};
};

/// The order of fields in this structure is crucial for it to be mapped to its GLSL counterpart properly.
struct LineLayerUniforms {
float opacity;
float widthScale;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,36 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

static const char* fs = R"GLSL(
#define SHADER_NAME scatterplot-layer-fragment-shader
#ifndef DECKGL_LAYERS_SCATTERPLOT_LAYER_FRAGMENT_H
#define DECKGL_LAYERS_SCATTERPLOT_LAYER_FRAGMENT_H

precision highp float;
#include <string>

uniform bool filled;
uniform float stroked;
#include "deck.gl/core/src/shaderlib/misc/geometry.glsl.h"

varying vec4 vFillColor;
varying vec4 vLineColor;
varying vec2 unitPosition;
varying float innerUnitRadius;
varying float outerRadiusPixels;
namespace {

// NOLINTNEXTLINE(runtime/string)
static const std::string scatterplotLayerFS = R"GLSL(
layout(std140, set = 0, binding = 1) uniform ScatterplotLayerOptions {
float opacity;
float radiusScale;
float radiusMinPixels;
float radiusMaxPixels;
float lineWidthScale;
float lineWidthMinPixels;
float lineWidthMaxPixels;
float stroked;
bool filled;
} layerOptions;
layout(location = 0) in vec4 vFillColor;
layout(location = 1) in vec4 vLineColor;
layout(location = 2) in vec2 unitPosition;
layout(location = 3) in float innerUnitRadius;
layout(location = 4) in float outerRadiusPixels;
layout(location = 0) out vec4 fragColor;
void main(void) {
geometry.uv = unitPosition;
Expand All @@ -42,23 +59,29 @@ void main(void) {
discard;
}
if (stroked > 0.5) {
if (layerOptions.stroked > 0.5) {
float isLine = smoothedge(innerUnitRadius * outerRadiusPixels, distToCenter);
if (filled) {
gl_FragColor = mix(vFillColor, vLineColor, isLine);
if (layerOptions.filled) {
fragColor = mix(vFillColor, vLineColor, isLine);
} else {
if (isLine == 0.0) {
discard;
}
gl_FragColor = vec4(vLineColor.rgb, vLineColor.a * isLine);
fragColor = vec4(vLineColor.rgb, vLineColor.a * isLine);
}
} else if (filled) {
gl_FragColor = vFillColor;
} else if (layerOptions.filled) {
fragColor = vFillColor;
} else {
discard;
}
gl_FragColor.a *= inCircle;
DECKGL_FILTER_COLOR(gl_FragColor, geometry);
fragColor.a *= inCircle;
}
)GLSL";

} // anonymous namespace

// NOLINTNEXTLINE(runtime/string)
static const std::string fs = "#version 450\n" + geometryFS + "\n" + scatterplotLayerFS;

#endif // DECKGL_LAYERS_SCATTERPLOT_LAYER_FRAGMENT_H
Original file line number Diff line number Diff line change
Expand Up @@ -18,69 +18,83 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

static const char *vs = R"GLSL(
#define SHADER_NAME scatterplot-layer-vertex-shader

attribute vec3 positions;

attribute vec3 instancePositions;
attribute vec3 instancePositions64Low;
attribute float instanceRadius;
attribute float instanceLineWidths;
attribute vec4 instanceFillColors;
attribute vec4 instanceLineColors;
attribute vec3 instancePickingColors;

uniform float opacity;
uniform float radiusScale;
uniform float radiusMinPixels;
uniform float radiusMaxPixels;
uniform float lineWidthScale;
uniform float lineWidthMinPixels;
uniform float lineWidthMaxPixels;
uniform float stroked;
uniform bool filled;

varying vec4 vFillColor;
varying vec4 vLineColor;
varying vec2 unitPosition;
varying float innerUnitRadius;
varying float outerRadiusPixels;
#ifndef DECKGL_LAYERS_SCATTERPLOT_LAYER_VERTEX_H
#define DECKGL_LAYERS_SCATTERPLOT_LAYER_VERTEX_H

#include <string>

#include "deck.gl/core/src/shaderlib/project/project32.glsl.h"
#include "deck.gl/core/src/shaderlib/misc/geometry.glsl.h"

namespace {

// NOLINTNEXTLINE(runtime/string)
static const std::string scatterplotLayerVS = R"GLSL(
layout(std140, set = 0, binding = 1) uniform ScatterplotLayerOptions {
float opacity;
float radiusScale;
float radiusMinPixels;
float radiusMaxPixels;
float lineWidthScale;
float lineWidthMinPixels;
float lineWidthMaxPixels;
float stroked;
bool filled;
} layerOptions;
layout(location = 0) in vec3 positions;
layout(location = 1) in vec3 instancePositions;
layout(location = 2) in float instanceRadius;
layout(location = 3) in vec4 instanceFillColors;
layout(location = 4) in vec4 instanceLineColors;
layout(location = 5) in float instanceLineWidths;
// TODO(ilija@unfolded.ai): Revisit once double splitting is in place
vec3 instancePositions64Low = vec3(0.);
layout(location = 0) out vec4 vFillColor;
layout(location = 1) out vec4 vLineColor;
layout(location = 2) out vec2 unitPosition;
layout(location = 3) out float innerUnitRadius;
layout(location = 4) out float outerRadiusPixels;
void main(void) {
geometry.worldPosition = instancePositions;
// Multiply out radius and clamp to limits
outerRadiusPixels = clamp(
project_size_to_pixel(radiusScale * instanceRadius),
radiusMinPixels, radiusMaxPixels
project_size_to_pixel(layerOptions.radiusScale * instanceRadius),
layerOptions.radiusMinPixels, layerOptions.radiusMaxPixels
);
// Multiply out line width and clamp to limits
float lineWidthPixels = clamp(
project_size_to_pixel(lineWidthScale * instanceLineWidths),
lineWidthMinPixels, lineWidthMaxPixels
project_size_to_pixel(layerOptions.lineWidthScale * instanceLineWidths),
layerOptions.lineWidthMinPixels, layerOptions.lineWidthMaxPixels
);
// outer radius needs to offset by half stroke width
outerRadiusPixels += stroked * lineWidthPixels / 2.0;
// Outer radius needs to offset by half stroke width
outerRadiusPixels += layerOptions.stroked * lineWidthPixels / 2.0;
// position on the containing square in [-1, 1] space
// Position on the containing square in [-1, 1] space
unitPosition = positions.xy;
geometry.uv = unitPosition;
geometry.pickingColor = instancePickingColors;
innerUnitRadius = 1.0 - stroked * lineWidthPixels / outerRadiusPixels;
innerUnitRadius = 1.0 - layerOptions.stroked * lineWidthPixels / outerRadiusPixels;
vec3 offset = positions * project_pixel_size(outerRadiusPixels);
DECKGL_FILTER_SIZE(offset, geometry);
gl_Position = project_position_to_clipspace(instancePositions, instancePositions64Low, offset, geometry.position);
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
// Apply opacity to instance color, or return instance picking color
vFillColor = vec4(instanceFillColors.rgb, instanceFillColors.a * opacity);
DECKGL_FILTER_COLOR(vFillColor, geometry);
vLineColor = vec4(instanceLineColors.rgb, instanceLineColors.a * opacity);
DECKGL_FILTER_COLOR(vLineColor, geometry);
// Apply opacity to instance color, or return instance picking color, then normalize the values
vFillColor = clamp(vec4(instanceFillColors.rgb, instanceFillColors.a * layerOptions.opacity), 0, 255) / 255.0;
vLineColor = clamp(vec4(instanceLineColors.rgb, instanceLineColors.a * layerOptions.opacity), 0, 255) / 255.0;
}
)GLSL";

} // anonymous namespace

// NOLINTNEXTLINE(runtime/string)
static const std::string vs = "#version 450\n" + geometryVS + "\n" + project32VS + "\n" + scatterplotLayerVS;

#endif // DECKGL_LAYERS_SCATTERPLOT_LAYER_VERTEX_H
Loading

0 comments on commit cbe4516

Please sign in to comment.