-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Kyle Barron
committed
Apr 19, 2020
1 parent
c5c93f3
commit 19f32c4
Showing
3 changed files
with
237 additions
and
0 deletions.
There are no files selected for viewing
68 changes: 68 additions & 0 deletions
68
modules/bands-bitmap-layer/src/bands-bitmap-layer-pan-fragment.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
export default ` | ||
#define SHADER_NAME bands-bitmap-layer-pan-fragment-shader | ||
#ifdef GL_ES | ||
precision highp float; | ||
#endif | ||
uniform sampler2D bitmapTexture_r; | ||
uniform sampler2D bitmapTexture_g; | ||
uniform sampler2D bitmapTexture_b; | ||
uniform sampler2D bitmapTexture_pan; | ||
varying vec2 vTexCoord; | ||
uniform float desaturate; | ||
uniform vec4 transparentColor; | ||
uniform vec3 tintColor; | ||
uniform float opacity; | ||
uniform float panWeight; | ||
// calculate pansharpen ratio | ||
float pansharpen_ratio(vec3 rgb, float pan, float weight) { | ||
return pan / ((rgb.r + rgb.g + rgb.b * weight) / (2. + weight)); | ||
} | ||
// Brovey Method: Each resampled, multispectral pixel is | ||
// multiplied by the ratio of the corresponding | ||
// panchromatic pixel intensity to the sum of all the | ||
// multispectral intensities. | ||
// Original code from https://github.com/mapbox/rio-pansharpen | ||
vec3 pansharpen(vec3 rgb, float pan, float weight) { | ||
float ratio = pansharpen_ratio(rgb, pan, weight); | ||
vec3 alteredRGB = ratio * rgb; | ||
return clamp(alteredRGB, 0., 1.); | ||
} | ||
// apply desaturation | ||
vec3 color_desaturate(vec3 color) { | ||
float luminance = (color.r + color.g + color.b) * 0.333333333; | ||
return mix(color, vec3(luminance), desaturate); | ||
} | ||
// apply tint | ||
vec3 color_tint(vec3 color) { | ||
return color * tintColor; | ||
} | ||
// blend with background color | ||
vec4 apply_opacity(vec3 color, float alpha) { | ||
return mix(transparentColor, vec4(color, 1.0), alpha); | ||
} | ||
void main(void) { | ||
float r_band = texture2D(bitmapTexture_r, vTexCoord).r; | ||
float g_band = texture2D(bitmapTexture_g, vTexCoord).r; | ||
float b_band = texture2D(bitmapTexture_b, vTexCoord).r; | ||
float pan_band = texture2D(bitmapTexture_pan, vTexCoord).r; | ||
vec3 image = vec3(r_band, g_band, b_band); | ||
vec3 pansharpenedImage = pansharpen(image, pan_band, panWeight); | ||
gl_FragColor = apply_opacity(color_tint(color_desaturate(pansharpenedImage)), opacity); | ||
geometry.uv = vTexCoord; | ||
DECKGL_FILTER_COLOR(gl_FragColor, geometry); | ||
} | ||
`; |
168 changes: 168 additions & 0 deletions
168
modules/bands-bitmap-layer/src/bands-bitmap-layer-pan.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
import GL from "@luma.gl/constants"; | ||
import { BitmapLayer } from "@deck.gl/layers"; | ||
import { Texture2D } from "@luma.gl/core"; | ||
|
||
import fs from "./bands-bitmap-layer-pan-fragment"; | ||
|
||
const DEFAULT_TEXTURE_PARAMETERS = { | ||
[GL.TEXTURE_MIN_FILTER]: GL.LINEAR_MIPMAP_LINEAR, | ||
[GL.TEXTURE_MAG_FILTER]: GL.LINEAR, | ||
[GL.TEXTURE_WRAP_S]: GL.CLAMP_TO_EDGE, | ||
[GL.TEXTURE_WRAP_T]: GL.CLAMP_TO_EDGE, | ||
}; | ||
|
||
const defaultProps = { | ||
image_r: { type: "object", value: null, async: true }, | ||
image_g: { type: "object", value: null, async: true }, | ||
image_b: { type: "object", value: null, async: true }, | ||
image_pan: { type: "object", value: null, async: true }, | ||
bounds: { type: "array", value: [1, 0, 0, 1], compare: true }, | ||
|
||
desaturate: { type: "number", min: 0, max: 1, value: 0 }, | ||
// Weight of blue band | ||
panWeight: { type: "number", min: 0, max: 1, value: 0.2 }, | ||
// More context: because of the blending mode we're using for ground imagery, | ||
// alpha is not effective when blending the bitmap layers with the base map. | ||
// Instead we need to manually dim/blend rgb values with a background color. | ||
transparentColor: { type: "color", value: [0, 0, 0, 0] }, | ||
tintColor: { type: "color", value: [255, 255, 255] }, | ||
}; | ||
|
||
export default class BandsBitmapLayer extends BitmapLayer { | ||
draw(opts) { | ||
const { uniforms } = opts; | ||
const { | ||
bitmapTexture_r, | ||
bitmapTexture_g, | ||
bitmapTexture_b, | ||
bitmapTexture_pan, | ||
model, | ||
} = this.state; | ||
const { desaturate, transparentColor, tintColor, panWeight } = this.props; | ||
|
||
// // TODO fix zFighting | ||
// Render the image | ||
if ( | ||
bitmapTexture_r && | ||
bitmapTexture_g && | ||
bitmapTexture_b && | ||
bitmapTexture_pan && | ||
model | ||
) { | ||
model | ||
.setUniforms( | ||
Object.assign({}, uniforms, { | ||
bitmapTexture_r, | ||
bitmapTexture_g, | ||
bitmapTexture_b, | ||
bitmapTexture_pan, | ||
panWeight, | ||
desaturate, | ||
transparentColor: transparentColor.map((x) => x / 255), | ||
tintColor: tintColor.slice(0, 3).map((x) => x / 255), | ||
}) | ||
) | ||
.draw(); | ||
} | ||
} | ||
|
||
finalizeState() { | ||
super.finalizeState(); | ||
|
||
if (this.state.bitmapTexture_r) { | ||
this.state.bitmapTexture_r.delete(); | ||
} | ||
if (this.state.bitmapTexture_g) { | ||
this.state.bitmapTexture_g.delete(); | ||
} | ||
if (this.state.bitmapTexture_b) { | ||
this.state.bitmapTexture_b.delete(); | ||
} | ||
if (this.state.bitmapTexture_pan) { | ||
this.state.bitmapTexture_pan.delete(); | ||
} | ||
} | ||
|
||
getShaders() { | ||
// use object.assign to make sure we don't overwrite existing fields like `vs`, `modules`... | ||
return Object.assign({}, super.getShaders(), { | ||
fs, | ||
}); | ||
} | ||
|
||
updateState({ props, oldProps, changeFlags }) { | ||
// setup model first | ||
if (changeFlags.extensionsChanged) { | ||
const { gl } = this.context; | ||
if (this.state.model) { | ||
this.state.model.delete(); | ||
} | ||
this.setState({ model: this._getModel(gl) }); | ||
this.getAttributeManager().invalidateAll(); | ||
} | ||
|
||
if (props.image_r !== oldProps.image_r) { | ||
const bitmapTexture_r = this.loadTexture(props.image_r); | ||
if (this.state.bitmapTexture_r) { | ||
this.state.bitmapTexture_r.delete(); | ||
} | ||
this.setState({ bitmapTexture_r }); | ||
} | ||
if (props.image_g !== oldProps.image_g) { | ||
const bitmapTexture_g = this.loadTexture(props.image_g); | ||
if (this.state.bitmapTexture_g) { | ||
this.state.bitmapTexture_g.delete(); | ||
} | ||
this.setState({ bitmapTexture_g }); | ||
} | ||
if (props.image_b !== oldProps.image_b) { | ||
const bitmapTexture_b = this.loadTexture(props.image_b); | ||
if (this.state.bitmapTexture_b) { | ||
this.state.bitmapTexture_b.delete(); | ||
} | ||
this.setState({ bitmapTexture_b }); | ||
} | ||
if (props.image_pan !== oldProps.image_pan) { | ||
const bitmapTexture_pan = this.loadTexture(props.image_pan); | ||
if (this.state.bitmapTexture_pan) { | ||
this.state.bitmapTexture_pan.delete(); | ||
} | ||
this.setState({ bitmapTexture_pan }); | ||
} | ||
|
||
const attributeManager = this.getAttributeManager(); | ||
|
||
if (props.bounds !== oldProps.bounds) { | ||
attributeManager.invalidate("positions"); | ||
} | ||
} | ||
|
||
loadTexture(image) { | ||
const { gl } = this.context; | ||
|
||
if (image instanceof Texture2D) { | ||
return image; | ||
} else if (image instanceof HTMLVideoElement) { | ||
// Initialize an empty texture while we wait for the video to load | ||
return { | ||
bitmapTexture: new Texture2D(gl, { | ||
width: 1, | ||
height: 1, | ||
parameters: DEFAULT_TEXTURE_PARAMETERS, | ||
mipmaps: false, | ||
}), | ||
}; | ||
} else if (image) { | ||
// Browser object: Image, ImageData, HTMLCanvasElement, ImageBitmap | ||
return { | ||
bitmapTexture: new Texture2D(gl, { | ||
data: image, | ||
parameters: DEFAULT_TEXTURE_PARAMETERS, | ||
}), | ||
}; | ||
} | ||
} | ||
} | ||
|
||
BandsBitmapLayer.defaultProps = defaultProps; | ||
BandsBitmapLayer.layerName = "BandsBitmapLayer"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { default as BandsBitmapLayer } from "./bands-bitmap-layer"; | ||
export { default as PanBandsBitmapLayer } from "./bands-bitmap-layer-pan"; |