feat: 优化 lineLayer/arc 的 shader 代码(合并 varying、提取片元计算)

This commit is contained in:
2912401452 2021-09-16 15:26:27 +08:00
parent 957adcedf8
commit b4356b13d6
6 changed files with 48 additions and 47 deletions

View File

@ -7,9 +7,8 @@ uniform float u_opacity;
uniform float u_textureBlend; uniform float u_textureBlend;
uniform float u_blur : 0.9; uniform float u_blur : 0.9;
uniform float u_line_type: 0.0; uniform float u_line_type: 0.0;
varying vec2 v_normal; // varying vec2 v_normal;
varying vec4 v_dash_array; varying vec4 v_dash_array;
varying float v_distance_ratio;
varying vec4 v_color; varying vec4 v_color;
uniform float u_time; uniform float u_time;
@ -20,13 +19,10 @@ uniform sampler2D u_texture;
uniform vec2 u_textSize; uniform vec2 u_textSize;
uniform float segmentNumber; uniform float segmentNumber;
varying float v_segmentIndex;
varying float v_arcDistrance;
varying float v_pixelLen;
varying float v_a;
varying vec2 v_offset;
varying vec2 v_iconMapUV; varying vec2 v_iconMapUV;
varying vec4 v_dataset; // 数据集 - 用于合并单个的 varying 变量
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据 varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
uniform float u_linearColor: 0; uniform float u_linearColor: 0;
@ -38,21 +34,22 @@ uniform vec4 u_targetColor;
void main() { void main() {
float opacity = styleMappingMat[0][0]; float opacity = styleMappingMat[0][0];
float animateSpeed = 0.0; // 运动速度 float animateSpeed = 0.0; // 运动速度
float d_segmentIndex = v_dataset.r; // 当前顶点在弧线中所处的分段位置
float d_distance_ratio = v_dataset.b; // 当前顶点在弧线中所处的分段比例
// 设置弧线的底色
if(u_linearColor == 1.0) { // 使用渐变颜色 if(u_linearColor == 1.0) { // 使用渐变颜色
gl_FragColor = mix(u_sourceColor, u_targetColor, v_segmentIndex/segmentNumber); gl_FragColor = mix(u_sourceColor, u_targetColor, d_segmentIndex/segmentNumber);
} else { // 使用 color 方法传入的颜色 } else { // 使用 color 方法传入的颜色
gl_FragColor = v_color; gl_FragColor = v_color;
} }
// gl_FragColor = v_color;
// float blur = 1.- smoothstep(u_blur, 1., length(v_normal.xy)); // float blur = 1.- smoothstep(u_blur, 1., length(v_normal.xy));
// float blur = smoothstep(1.0, u_blur, length(v_normal.xy)); // float blur = smoothstep(1.0, u_blur, length(v_normal.xy));
gl_FragColor.a *= opacity; gl_FragColor.a *= opacity;
if(u_line_type == LineTypeDash) { if(u_line_type == LineTypeDash) {
float flag = 0.; float flag = 0.;
float dashLength = mod(v_distance_ratio, v_dash_array.x + v_dash_array.y + v_dash_array.z + v_dash_array.w); float dashLength = mod(d_distance_ratio, v_dash_array.x + v_dash_array.y + v_dash_array.z + v_dash_array.w);
if(dashLength < v_dash_array.x || (dashLength > (v_dash_array.x + v_dash_array.y) && dashLength < v_dash_array.x + v_dash_array.y + v_dash_array.z)) { if(dashLength < v_dash_array.x || (dashLength > (v_dash_array.x + v_dash_array.y) && dashLength < v_dash_array.x + v_dash_array.y + v_dash_array.z)) {
flag = 1.; flag = 1.;
} }
@ -61,25 +58,26 @@ void main() {
if(u_aimate.x == Animate) { if(u_aimate.x == Animate) {
animateSpeed = u_time / u_aimate.y; animateSpeed = u_time / u_aimate.y;
float alpha =1.0 - fract( mod(1.0- v_distance_ratio, u_aimate.z)* (1.0/ u_aimate.z) + u_time / u_aimate.y); float alpha =1.0 - fract( mod(1.0- d_distance_ratio, u_aimate.z)* (1.0/ u_aimate.z) + u_time / u_aimate.y);
alpha = (alpha + u_aimate.w -1.0) / u_aimate.w; alpha = (alpha + u_aimate.w -1.0) / u_aimate.w;
// alpha = smoothstep(0., 1., alpha); // alpha = smoothstep(0., 1., alpha);
alpha = clamp(alpha, 0.0, 1.0); alpha = clamp(alpha, 0.0, 1.0);
gl_FragColor.a *= alpha; gl_FragColor.a *= alpha;
} }
// 当存在贴图时在底色上贴上贴图
if(u_line_texture == LineTexture && u_line_type != LineTypeDash) { // while load texture if(u_line_texture == LineTexture && u_line_type != LineTypeDash) { // while load texture
float arcRadio = smoothstep( 0.0, 1.0, (v_segmentIndex / segmentNumber)); float arcRadio = smoothstep( 0.0, 1.0, (d_segmentIndex / segmentNumber));
// float arcRadio = smoothstep( 0.0, 1.0, v_distance_ratio); // float arcRadio = smoothstep( 0.0, 1.0, d_distance_ratio);
// float arcRadio = v_segmentIndex / (segmentNumber - 1.0);
float count = floor(v_arcDistrance/v_pixelLen);
float u = 1.0 - fract(arcRadio * count + animateSpeed); float d_texCount = v_dataset.g; // 贴图在弧线上重复的数量
float u = 1.0 - fract(arcRadio * d_texCount + animateSpeed);
if(u_aimate.x == Animate) { if(u_aimate.x == Animate) {
u = gl_FragColor.a/opacity; u = gl_FragColor.a/opacity;
} }
float v = length(v_offset)/(v_a); // 横向 float v = v_dataset.a; // 横向 v
vec2 uv= v_iconMapUV / u_textSize + vec2(u, v) / u_textSize * 64.; vec2 uv= v_iconMapUV / u_textSize + vec2(u, v) / u_textSize * 64.;
vec4 pattern = texture2D(u_texture, uv); vec4 pattern = texture2D(u_texture, uv);
@ -102,5 +100,4 @@ void main() {
gl_FragColor = filterColor(gl_FragColor); gl_FragColor = filterColor(gl_FragColor);
} }
// gl_FragColor = filterColor(gl_FragColor); // gl_FragColor = filterColor(gl_FragColor);
} }

View File

@ -12,9 +12,8 @@ uniform mat4 u_Mvp;
uniform float segmentNumber; uniform float segmentNumber;
uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ]; uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ];
varying vec4 v_color; varying vec4 v_color;
varying vec2 v_normal; // varying vec2 v_normal;
varying float v_distance_ratio;
uniform float u_line_type: 0.0; uniform float u_line_type: 0.0;
uniform vec4 u_dash_array: [10.0, 5., 0, 0]; uniform vec4 u_dash_array: [10.0, 5., 0, 0];
uniform float u_lineDir: 1.0; uniform float u_lineDir: 1.0;
@ -22,14 +21,11 @@ varying vec4 v_dash_array;
uniform float u_icon_step: 100; uniform float u_icon_step: 100;
uniform float u_line_texture: 0.0; uniform float u_line_texture: 0.0;
varying float v_segmentIndex;
varying float v_arcDistrance;
varying float v_pixelLen;
varying float v_a;
varying vec2 v_offset;
attribute vec2 a_iconMapUV; attribute vec2 a_iconMapUV;
varying vec2 v_iconMapUV; varying vec2 v_iconMapUV;
varying vec4 v_dataset; // 数据集 - 用于合并单个的 varying 变量
uniform float u_opacity: 1.0; uniform float u_opacity: 1.0;
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元 varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
@ -116,16 +112,17 @@ vec2 getNormal(vec2 line_clipspace, float offset_direction) {
void main() { void main() {
v_color = a_Color; v_color = a_Color;
vec2 source = a_Instance.rg; // 起始点
vec2 source = a_Instance.rg; vec2 target = a_Instance.ba; // 终点
vec2 target = a_Instance.ba;
float segmentIndex = a_Position.x; float segmentIndex = a_Position.x;
float segmentRatio = getSegmentRatio(segmentIndex); float segmentRatio = getSegmentRatio(segmentIndex);
float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0)); float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0));
float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir); float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir);
float d_distance_ratio;
if(u_line_type == LineTypeDash) { if(u_line_type == LineTypeDash) {
v_distance_ratio = segmentIndex / segmentNumber; d_distance_ratio = segmentIndex / segmentNumber;
vec2 s = source; vec2 s = source;
vec2 t = target; vec2 t = target;
@ -139,34 +136,44 @@ void main() {
} }
if(u_aimate.x == Animate) { if(u_aimate.x == Animate) {
v_distance_ratio = segmentIndex / segmentNumber; d_distance_ratio = segmentIndex / segmentNumber;
if(u_lineDir != 1.0) { if(u_lineDir != 1.0) {
v_distance_ratio = 1.0 - v_distance_ratio; d_distance_ratio = 1.0 - d_distance_ratio;
} }
} }
v_dataset.b = d_distance_ratio;
vec4 curr = project_position(vec4(interpolate(source, target, segmentRatio), 0.0, 1.0)); vec4 curr = project_position(vec4(interpolate(source, target, segmentRatio), 0.0, 1.0));
vec4 next = project_position(vec4(interpolate(source, target, nextSegmentRatio), 0.0, 1.0)); vec4 next = project_position(vec4(interpolate(source, target, nextSegmentRatio), 0.0, 1.0));
v_normal = getNormal((next.xy - curr.xy) * indexDir, a_Position.y); // v_normal = getNormal((next.xy - curr.xy) * indexDir, a_Position.y);
//unProjCustomCoord //unProjCustomCoord
vec2 offset = project_pixel(getExtrusionOffset((next.xy - curr.xy) * indexDir, a_Position.y)); vec2 offset = project_pixel(getExtrusionOffset((next.xy - curr.xy) * indexDir, a_Position.y));
v_segmentIndex = a_Position.x + 1.0;
float d_segmentIndex = a_Position.x + 1.0; // 当前顶点在弧线中所处的分段位置
v_dataset.r = d_segmentIndex;
if(LineTexture == u_line_texture) { // 开启贴图模式 if(LineTexture == u_line_texture) { // 开启贴图模式
v_arcDistrance = length(source - target); float arcDistrance = length(source - target); // 起始点和终点的距离
if(u_CoordinateSystem == COORDINATE_SYSTEM_P20) { // amap if(u_CoordinateSystem == COORDINATE_SYSTEM_P20) { // amap
v_arcDistrance *= 1000000.0; arcDistrance *= 1000000.0;
} }
if(u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT || u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT_OFFSET) { // mapbox if(u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT || u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT_OFFSET) { // mapbox
// v_arcDistrance *= 8.0; // arcDistrance *= 8.0;
v_arcDistrance = project_pixel_allmap(v_arcDistrance); arcDistrance = project_pixel_allmap(arcDistrance);
} }
v_iconMapUV = a_iconMapUV; v_iconMapUV = a_iconMapUV;
v_pixelLen = project_pixel(u_icon_step);
v_a = project_pixel(a_Size); float pixelLen = project_pixel(u_icon_step); // 贴图沿弧线方向的长度 - 随地图缩放改变
v_offset = offset + offset * sign(a_Position.y); float texCount = floor(arcDistrance/pixelLen); // 贴图在弧线上重复的数量
v_dataset.g = texCount;
float lineOffsetWidth = length(offset + offset * sign(a_Position.y)); // 线横向偏移的距离
float linePixelSize = project_pixel(a_Size); // 定点位置偏移
v_dataset.a = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
} }

View File

@ -19,7 +19,6 @@ uniform float u_dash_offset : 0.0;
uniform float u_dash_ratio : 0.1; uniform float u_dash_ratio : 0.1;
varying vec4 v_dash_array; varying vec4 v_dash_array;
varying float v_v;
varying vec4 v_dataset; // 数据集 - distance_ratio/distance/pixelLen/texV varying vec4 v_dataset; // 数据集 - distance_ratio/distance/pixelLen/texV
varying vec2 v_iconMapUV; varying vec2 v_iconMapUV;
@ -96,7 +95,6 @@ void main() {
// if(rV < r || rV > 1.0 - r) { // if(rV < r || rV > 1.0 - r) {
// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
// } // }
// float v = v_v;
// if(v > 0.9) { // if(v > 0.9) {
// gl_FragColor = vec4(0.17647, 0.43921568, 0.2, 1.0); // gl_FragColor = vec4(0.17647, 0.43921568, 0.2, 1.0);
// } else if(v < 0.1) { // } else if(v < 0.1) {

View File

@ -29,8 +29,7 @@ varying vec4 v_dash_array;
varying vec2 v_normal; varying vec2 v_normal;
varying vec4 v_dataset; // 数据集 - distance_ratio/distance/pixelLen/texV varying vec4 v_dataset; // 数据集 - distance_ratio/distance/pixelLen/texV
// texV 线图层 - 贴图部分的 v 坐标(线的宽度方向)
varying float v_v; // 线图层 - 贴图部分的 v 坐标(线的宽度方向)
varying vec2 v_iconMapUV; varying vec2 v_iconMapUV;
uniform float u_linearColor: 0; uniform float u_linearColor: 0;
@ -94,7 +93,6 @@ void main() {
float lineOffsetWidth = length(offset + offset * sign(a_Miter)); // 线横向偏移的距离(向两侧偏移的和) float lineOffsetWidth = length(offset + offset * sign(a_Miter)); // 线横向偏移的距离(向两侧偏移的和)
float linePixelSize = project_pixel(a_Size.x) * 2.0; // 定点位置偏移,按地图等级缩放后的距离 单侧 * 2 float linePixelSize = project_pixel(a_Size.x) * 2.0; // 定点位置偏移,按地图等级缩放后的距离 单侧 * 2
v_v = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
float texV = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值 float texV = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
// 设置数据集的参数 // 设置数据集的参数

View File

@ -47,6 +47,7 @@ export default class Amap2demo_arcLine extends React.Component {
// segmentNumber: 3, // segmentNumber: 3,
// lineType: 'dash', // lineType: 'dash',
// dashArray: [5, 5], // dashArray: [5, 5],
}); });
// .forward(false) // .forward(false)
scene.addLayer(layer); scene.addLayer(layer);

View File

@ -19,7 +19,7 @@ export default class Amap2demo_lineDash extends React.Component {
zoom: 10, zoom: 10,
rotation: 0, rotation: 0,
style: 'amap://styles/wine', style: 'amap://styles/wine',
viewMode: '2D', // viewMode: '2D',
}), }),
}); });
this.scene = scene; this.scene = scene;