feat: client-side rendering
This commit is contained in:
parent
61df1e725c
commit
26b393a719
7 changed files with 106 additions and 61 deletions
22
.idea/workspace.xml
generated
22
.idea/workspace.xml
generated
|
@ -7,13 +7,12 @@
|
|||
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="2d855648-9644-469a-afa2-59beb52bb1d6" name="Changes" comment="mostly functional v2 rendering">
|
||||
<change afterPath="$PROJECT_DIR$/crates/pal/src/wasm.rs" afterDir="false" />
|
||||
<list default="true" id="2d855648-9644-469a-afa2-59beb52bb1d6" name="Changes" comment="csr rendering v2">
|
||||
<change afterPath="$PROJECT_DIR$/client/src/lib/map/default_palettes.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Cargo.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.lock" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/client/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/client/package.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/client/src/lib/Map.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/lib/Map.svelte" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/crates/pal/Cargo.toml" beforeDir="false" afterPath="$PROJECT_DIR$/crates/pal/Cargo.toml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/client/src/lib/map/fragment.glsl" beforeDir="false" afterPath="$PROJECT_DIR$/client/src/lib/map/fragment.glsl" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/crates/pal/src/lib.rs" beforeDir="false" afterPath="$PROJECT_DIR$/crates/pal/src/lib.rs" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
|
@ -22,7 +21,7 @@
|
|||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="DarkyenusTimeTracker">
|
||||
<option name="totalTimeSeconds" value="11086" />
|
||||
<option name="totalTimeSeconds" value="14770" />
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
|
@ -166,7 +165,15 @@
|
|||
<option name="project" value="LOCAL" />
|
||||
<updated>1748662734805</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="4" />
|
||||
<task id="LOCAL-00004" summary="csr rendering v2">
|
||||
<option name="closed" value="true" />
|
||||
<created>1748704540785</created>
|
||||
<option name="number" value="00004" />
|
||||
<option name="presentableId" value="LOCAL-00004" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1748704540785</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="5" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
|
@ -177,6 +184,7 @@
|
|||
<MESSAGE value="feat: client work" />
|
||||
<MESSAGE value="debugging" />
|
||||
<MESSAGE value="mostly functional v2 rendering" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="mostly functional v2 rendering" />
|
||||
<MESSAGE value="csr rendering v2" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="csr rendering v2" />
|
||||
</component>
|
||||
</project>
|
|
@ -4,7 +4,7 @@
|
|||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"dev": "bun update:protobuf && bun update:wxbox-pal && vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"prepare": "svelte-kit sync || echo ''",
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
import type { DigitalRadarData, Radial } from './generated_interop/digitalRadarData';
|
||||
import {forwardGeodesic, radToDeg} from "$lib/vincenty";
|
||||
import {degToRad} from "$lib/vincenty.js";
|
||||
import init_palette_parser_wasm, {parse_palette} from "$lib/map/pal/wxbox_pal";
|
||||
import {WXBOX_STANDARD_REF} from "$lib/map/default_palettes";
|
||||
|
||||
const BELOW_THRESHOLD = -9999.0;
|
||||
const RANGE_FOLDED = -9998.0;
|
||||
|
@ -167,6 +169,8 @@
|
|||
if (container.messageType.oneofKind == 'digitalRadarData') {
|
||||
const drd: DigitalRadarData = container.messageType.digitalRadarData;
|
||||
|
||||
await init_palette_parser_wasm();
|
||||
|
||||
const dataLayer = {
|
||||
id: 'dataGl',
|
||||
type: 'custom',
|
||||
|
@ -187,14 +191,6 @@
|
|||
|
||||
this.aPos = gl.getAttribLocation(this.program, 'a_pos');
|
||||
|
||||
/*
|
||||
110.574 km = 1 deg
|
||||
deg = 1/110.574 km
|
||||
|
||||
111.320 * cos(latitude) km = 1 deg
|
||||
|
||||
*/
|
||||
|
||||
const lat = 38.976111;
|
||||
const long = -77.4875;
|
||||
|
||||
|
@ -214,7 +210,7 @@
|
|||
|
||||
if (radial.product && radial.product.data && radial.product.data.data) {
|
||||
const angle_a = radial.azimuthAngleDegrees;
|
||||
const angle_b = angle_a + radial.azimuthSpacingDegrees * 1.2;
|
||||
const angle_b = (i == drd.radials.length - 1) ? drd.radials[0].azimuthAngleDegrees : drd.radials[i+1].azimuthAngleDegrees;
|
||||
|
||||
const start_range = radial.product.data.startRange; // m
|
||||
const sample_interval = radial.product.data.sampleInterval; // m
|
||||
|
@ -294,10 +290,61 @@
|
|||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.uniform1i(gl.getUniformLocation(this.program, 'data'), 10);
|
||||
|
||||
// parse, transform, and send over the palette
|
||||
const palette = parse_palette(WXBOX_STANDARD_REF);
|
||||
gl.uniform1i(gl.getUniformLocation(this.program, 'paletteLength'), palette.length);
|
||||
const rboundsData: number[] = [];
|
||||
const rcolorData: number[] = [];
|
||||
const rcolor2Data: number[] = [];
|
||||
for (const paletteEntry of palette) {
|
||||
const [bounds, color] = paletteEntry;
|
||||
rboundsData.push(...bounds);
|
||||
rcolorData.push(...[color[0].red, color[0].green, color[0].blue, color[0].alpha]);
|
||||
rcolor2Data.push(...[color[1].red, color[1].green, color[1].blue, color[1].alpha]);
|
||||
}
|
||||
// create the bounds texture first
|
||||
const boundsData = new Float32Array(rboundsData);
|
||||
gl.activeTexture(gl.TEXTURE0 + 11);
|
||||
this.boundsTexture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.boundsTexture);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG32F, 1, palette.length, 0, gl.RG, gl.FLOAT, boundsData);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.uniform1i(gl.getUniformLocation(this.program, 'bounds'), 11);
|
||||
// then the colorData texture
|
||||
const colorData = new Uint8Array(rcolorData);
|
||||
gl.activeTexture(gl.TEXTURE0 + 12);
|
||||
this.colorDataTexture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.colorDataTexture);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, palette.length, 0, gl.RGBA, gl.UNSIGNED_BYTE, colorData);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.uniform1i(gl.getUniformLocation(this.program, 'colorData'), 12);
|
||||
// then the colorData2 texture
|
||||
const color2Data = new Uint8Array(rcolor2Data);
|
||||
gl.activeTexture(gl.TEXTURE0 + 13);
|
||||
this.color2DataTexture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.color2DataTexture);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, palette.length, 0, gl.RGBA, gl.UNSIGNED_BYTE, color2Data);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.uniform1i(gl.getUniformLocation(this.program, 'color2Data'), 13);
|
||||
},
|
||||
render(gl, args) {
|
||||
gl.activeTexture(gl.TEXTURE0 + 10);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
||||
gl.activeTexture(gl.TEXTURE0 + 11);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.boundsTexture);
|
||||
gl.activeTexture(gl.TEXTURE0 + 12);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.colorDataTexture);
|
||||
gl.activeTexture(gl.TEXTURE0 + 13);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.color2DataTexture);
|
||||
gl.useProgram(this.program);
|
||||
|
||||
gl.uniformMatrix4fv(
|
||||
|
|
8
client/src/lib/map/default_palettes.ts
Normal file
8
client/src/lib/map/default_palettes.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
export const WXBOX_STANDARD_REF = `Color4: 10 164 164 255 0 100 100 192 255
|
||||
Color4: 20 64 128 255 255 32 64 128 255
|
||||
Color4: 30 0 255 0 255 0 128 0 255
|
||||
Color4: 40 255 255 0 255 255 128 0 255
|
||||
Color4: 50 255 0 0 255 160 0 0 255
|
||||
Color4: 60 255 0 255 255 128 0 128 255
|
||||
Color4: 70 255 255 255 255 128 128 128 255
|
||||
Color4: 80 128 128 128 255`;
|
|
@ -7,12 +7,16 @@ const float PI = 3.14159265358979323846264338327950288;
|
|||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
in vec2 raw_pos;
|
||||
in vec4 vertexColor;
|
||||
flat in int azimuthNumber;
|
||||
flat in float azimuthAngle;
|
||||
|
||||
uniform sampler2D data;
|
||||
|
||||
uniform sampler2D bounds;
|
||||
uniform sampler2D colorData;
|
||||
uniform sampler2D color2Data;
|
||||
uniform int paletteLength;
|
||||
|
||||
uniform float radarLat;
|
||||
uniform float radarLng;
|
||||
|
||||
|
@ -27,18 +31,8 @@ Wgs84Coordinates rawPosToWgs84(vec2 raw_pos) {
|
|||
return Wgs84Coordinates(lat,lng);
|
||||
}
|
||||
|
||||
float haversineDistance(Wgs84Coordinates from, Wgs84Coordinates to, float radius) {
|
||||
return 2.0 * radius * asin(sqrt(pow(2.0, sin((to.lat-from.lat)/2.0)) + cos(from.lat) * cos(to.lat) * pow(2.0, sin((to.lng - from.lng)/2.0))));
|
||||
}
|
||||
|
||||
const float R = 6371000.0; // m
|
||||
|
||||
float random (vec2 st) {
|
||||
return fract(sin(dot(st.xy,
|
||||
vec2(12.9898,78.233)))*
|
||||
43758.5453123);
|
||||
}
|
||||
|
||||
void main() {
|
||||
Wgs84Coordinates thisPixelCoordinates = rawPosToWgs84(raw_pos);
|
||||
Wgs84Coordinates radarCoordinates = Wgs84Coordinates(radarLat,radarLng);
|
||||
|
@ -65,37 +59,30 @@ void main() {
|
|||
fragColor = vec4(0,0,0,0);
|
||||
return;
|
||||
}
|
||||
int selector = int(mod(float(azimuthNumber), 2.0));
|
||||
|
||||
if (selector == 0) {
|
||||
fragColor = vec4(float(azimuthAngle) / 360.0, 0, 0, 1);
|
||||
} else if (selector == 1) {
|
||||
fragColor = vec4(0,float(azimuthAngle) / 360.0, 0,1);
|
||||
} else {
|
||||
fragColor = vec4(0,0,float(azimuthAngle)/360.0,1);
|
||||
}
|
||||
|
||||
int gate_number = int(floor((distance_meters - 2125.0) / 250.0));
|
||||
|
||||
float rawValue = texelFetch(data, ivec2(gate_number, azimuthNumber), 0).r;
|
||||
|
||||
if (rawValue > 80.0) {
|
||||
fragColor = vec4(128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 1.0);
|
||||
} else if (rawValue > 70.0) {
|
||||
fragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
} else if (rawValue > 60.0) {
|
||||
fragColor = vec4(1.0, 0.0, 1.0, 1.0);
|
||||
} else if (rawValue > 50.0) {
|
||||
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
} else if (rawValue > 40.0) {
|
||||
fragColor = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
} else if (rawValue > 30.0) {
|
||||
fragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
} else if (rawValue > 20.0) {
|
||||
fragColor = vec4(64.0 / 255.0, 128.0 / 255.0, 1.0, 1.0);
|
||||
} else if (rawValue > 10.0) {
|
||||
fragColor = vec4(164.0 / 255.0, 164.0 / 255.0, 1.0, 1.0);
|
||||
} else {
|
||||
fragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
// colorize!
|
||||
for (int i = paletteLength; i > 0; i--) {
|
||||
vec2 rangeBounds = texelFetch(bounds, ivec2(0, i), 0).rg;
|
||||
float lower = rangeBounds.r;
|
||||
float higher = rangeBounds.g;
|
||||
if (rawValue >= lower && rawValue < higher) {
|
||||
float mapped_end = higher - lower;
|
||||
float mapped_point = rawValue - lower;
|
||||
float t = mapped_point / mapped_end;
|
||||
|
||||
vec4 color_start = texelFetch(colorData, ivec2(0, i), 0);
|
||||
vec4 color_end = texelFetch(color2Data, ivec2(0, i), 0);
|
||||
|
||||
|
||||
|
||||
fragColor = mix(color_start, color_end, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fragColor = vec4(0,0,0,0);
|
||||
return;
|
||||
}
|
|
@ -6,7 +6,6 @@ uniform mat4 u_matrix;
|
|||
in vec2 a_pos;
|
||||
|
||||
out vec2 raw_pos;
|
||||
out vec4 vertexColor;
|
||||
flat out int azimuthNumber;
|
||||
flat out float azimuthAngle;
|
||||
|
||||
|
@ -21,9 +20,4 @@ void main() {
|
|||
gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);
|
||||
azimuthAngle = triangleAzimuthLookup[gl_VertexID / 3];
|
||||
azimuthNumber = gl_VertexID / 3;
|
||||
|
||||
float randColor = rand(vec2(triangleAzimuthLookup[gl_VertexID/3] / 720.0,triangleAzimuthLookup[gl_VertexID/3] / 720.0));
|
||||
float randColor2 = rand(vec2(randColor, randColor));
|
||||
float randColor3 = rand(vec2(randColor, randColor));
|
||||
vertexColor = vec4(randColor,randColor2,randColor3,1.0);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
pub mod default_palettes;
|
||||
pub mod parser;
|
||||
#[cfg(feature = "wasm")]
|
||||
mod wasm;
|
||||
|
||||
pub use ordered_float::OrderedFloat;
|
||||
|
|
Loading…
Add table
Reference in a new issue