@flare-engine/render 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.mts +190 -2
- package/dist/index.d.ts +190 -2
- package/dist/index.js +600 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +598 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.mjs
CHANGED
|
@@ -533,6 +533,15 @@ function fire(opts) {
|
|
|
533
533
|
intensity: opts.intensity ?? 0.8
|
|
534
534
|
};
|
|
535
535
|
}
|
|
536
|
+
function dropShadow(opts) {
|
|
537
|
+
return {
|
|
538
|
+
type: "drop-shadow",
|
|
539
|
+
color: opts.color,
|
|
540
|
+
offsetX: opts.offsetX ?? 0,
|
|
541
|
+
offsetY: opts.offsetY ?? 6,
|
|
542
|
+
blur: opts.blur ?? 4
|
|
543
|
+
};
|
|
544
|
+
}
|
|
536
545
|
function roofsCity(opts) {
|
|
537
546
|
return {
|
|
538
547
|
type: "roofs-city",
|
|
@@ -928,6 +937,593 @@ half4 main(float2 coord) {
|
|
|
928
937
|
`
|
|
929
938
|
);
|
|
930
939
|
|
|
940
|
+
// src/frame-renderer.ts
|
|
941
|
+
var BLEND_SRC_OVER = 3;
|
|
942
|
+
var BLEND_SRC_IN = 5;
|
|
943
|
+
var OUTLINE_OFFSETS = [
|
|
944
|
+
[1, 0],
|
|
945
|
+
[-1, 0],
|
|
946
|
+
[0, 1],
|
|
947
|
+
[0, -1],
|
|
948
|
+
[Math.SQRT1_2, Math.SQRT1_2],
|
|
949
|
+
[Math.SQRT1_2, -Math.SQRT1_2],
|
|
950
|
+
[-Math.SQRT1_2, Math.SQRT1_2],
|
|
951
|
+
[-Math.SQRT1_2, -Math.SQRT1_2]
|
|
952
|
+
];
|
|
953
|
+
function createFrameRenderer(Skia) {
|
|
954
|
+
const defaultPaint = Skia.Paint();
|
|
955
|
+
let tintPaint = null;
|
|
956
|
+
let flashPaint = null;
|
|
957
|
+
let grayscalePaint = null;
|
|
958
|
+
let outlinePaint = null;
|
|
959
|
+
let customPaint = null;
|
|
960
|
+
let waterPaint = null;
|
|
961
|
+
let waterRuntimeEffect = null;
|
|
962
|
+
let fogPaint = null;
|
|
963
|
+
let fogRuntimeEffect = null;
|
|
964
|
+
let firePaint = null;
|
|
965
|
+
let fireRuntimeEffect = null;
|
|
966
|
+
let dropShadowPaint = null;
|
|
967
|
+
let roofsCityPaint = null;
|
|
968
|
+
let roofsCityEffect = null;
|
|
969
|
+
let forestCanopyPaint = null;
|
|
970
|
+
let forestCanopyEffect = null;
|
|
971
|
+
let riverWavePaint = null;
|
|
972
|
+
let riverWaveEffect = null;
|
|
973
|
+
let moonCraterPaint = null;
|
|
974
|
+
let moonCraterEffect = null;
|
|
975
|
+
let caveInteriorPaint = null;
|
|
976
|
+
let caveInteriorEffect = null;
|
|
977
|
+
let mountainHillsPaint = null;
|
|
978
|
+
let mountainHillsEffect = null;
|
|
979
|
+
const roofsCityUniforms = new Array(10).fill(0);
|
|
980
|
+
const forestCanopyUniforms = new Array(10).fill(0);
|
|
981
|
+
const riverWaveUniforms = new Array(10).fill(0);
|
|
982
|
+
const moonCraterUniforms = new Array(10).fill(0);
|
|
983
|
+
const caveInteriorUniforms = new Array(10).fill(0);
|
|
984
|
+
const mountainHillsUniforms = new Array(10).fill(0);
|
|
985
|
+
const recorder = Skia.PictureRecorder();
|
|
986
|
+
const recordingBounds = Skia.XYWHRect(0, 0, 0, 0);
|
|
987
|
+
const srcRects = [];
|
|
988
|
+
const xforms = [];
|
|
989
|
+
const stretchSrcRects = [];
|
|
990
|
+
const stretchDstRects = [];
|
|
991
|
+
let stretchPaint = null;
|
|
992
|
+
const clearColor = new Float32Array(4);
|
|
993
|
+
const tintColor = new Float32Array(4);
|
|
994
|
+
const flashColor = new Float32Array(4);
|
|
995
|
+
const outlineColor = new Float32Array(4);
|
|
996
|
+
const dropShadowColor = new Float32Array(4);
|
|
997
|
+
const grayMatrix = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];
|
|
998
|
+
const customUniforms = [];
|
|
999
|
+
const waterUniforms = new Array(11).fill(0);
|
|
1000
|
+
const fogUniforms = new Array(9).fill(0);
|
|
1001
|
+
const fireUniforms = new Array(11).fill(0);
|
|
1002
|
+
let currentFrameTime = 0;
|
|
1003
|
+
let current = null;
|
|
1004
|
+
let _boundRuntime = null;
|
|
1005
|
+
let _boundChain = null;
|
|
1006
|
+
const _loggedOnce = /* @__PURE__ */ new Set();
|
|
1007
|
+
function logOnce(msg) {
|
|
1008
|
+
if (_loggedOnce.has(msg)) return;
|
|
1009
|
+
_loggedOnce.add(msg);
|
|
1010
|
+
console.warn(`[postfx] ${msg}`);
|
|
1011
|
+
}
|
|
1012
|
+
const canvas = {
|
|
1013
|
+
save: () => current?.save() ?? 0,
|
|
1014
|
+
restore: () => {
|
|
1015
|
+
current?.restore();
|
|
1016
|
+
},
|
|
1017
|
+
translate: (x, y) => {
|
|
1018
|
+
current?.translate(x, y);
|
|
1019
|
+
},
|
|
1020
|
+
scale: (sx, sy) => {
|
|
1021
|
+
current?.scale(sx, sy);
|
|
1022
|
+
},
|
|
1023
|
+
rotate: (radians, cx, cy) => {
|
|
1024
|
+
current?.rotate(radians, cx, cy);
|
|
1025
|
+
},
|
|
1026
|
+
clear: (argb) => {
|
|
1027
|
+
if (current === null) return;
|
|
1028
|
+
clearColor[0] = (argb >>> 16 & 255) / 255;
|
|
1029
|
+
clearColor[1] = (argb >>> 8 & 255) / 255;
|
|
1030
|
+
clearColor[2] = (argb & 255) / 255;
|
|
1031
|
+
clearColor[3] = (argb >>> 24 & 255) / 255;
|
|
1032
|
+
current.clear(clearColor);
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
function ensurePoolCapacity(n) {
|
|
1036
|
+
while (srcRects.length < n) {
|
|
1037
|
+
srcRects.push(Skia.XYWHRect(0, 0, 0, 0));
|
|
1038
|
+
xforms.push(Skia.RSXform(1, 0, 0, 0));
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
function ensureStretchPoolCapacity(n) {
|
|
1042
|
+
while (stretchSrcRects.length < n) {
|
|
1043
|
+
stretchSrcRects.push(Skia.XYWHRect(0, 0, 0, 0));
|
|
1044
|
+
stretchDstRects.push(Skia.XYWHRect(0, 0, 0, 0));
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
function fillSrcRects(commands, n) {
|
|
1048
|
+
for (let i = 0; i < n; i++) {
|
|
1049
|
+
const cmd = commands[i];
|
|
1050
|
+
srcRects[i]?.setXYWH(cmd.srcX, cmd.srcY, cmd.srcW, cmd.srcH);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
function fillXforms(commands, n, dx, dy) {
|
|
1054
|
+
for (let i = 0; i < n; i++) {
|
|
1055
|
+
const cmd = commands[i];
|
|
1056
|
+
const scale = cmd.srcW === 0 ? 1 : cmd.dstW / cmd.srcW;
|
|
1057
|
+
if (cmd.rotation === 0) {
|
|
1058
|
+
xforms[i]?.set(scale, 0, cmd.dstX + dx, cmd.dstY + dy);
|
|
1059
|
+
} else {
|
|
1060
|
+
const c = Math.cos(cmd.rotation);
|
|
1061
|
+
const s = Math.sin(cmd.rotation);
|
|
1062
|
+
const scos = scale * c;
|
|
1063
|
+
const ssin = scale * s;
|
|
1064
|
+
const px = cmd.dstX + cmd.anchorX * cmd.dstW + dx;
|
|
1065
|
+
const py = cmd.dstY + cmd.anchorY * cmd.dstH + dy;
|
|
1066
|
+
const axSrc = cmd.anchorX * cmd.srcW;
|
|
1067
|
+
const aySrc = cmd.anchorY * cmd.srcH;
|
|
1068
|
+
xforms[i]?.set(
|
|
1069
|
+
scos,
|
|
1070
|
+
ssin,
|
|
1071
|
+
px - scos * axSrc + ssin * aySrc,
|
|
1072
|
+
py - ssin * axSrc - scos * aySrc
|
|
1073
|
+
);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
function applyTint(effect) {
|
|
1078
|
+
if (tintPaint === null) tintPaint = Skia.Paint();
|
|
1079
|
+
writeColor(tintColor, effect.color, effect.amount);
|
|
1080
|
+
tintPaint.setColorFilter(Skia.ColorFilter.MakeBlend(tintColor, BLEND_SRC_OVER));
|
|
1081
|
+
return tintPaint;
|
|
1082
|
+
}
|
|
1083
|
+
function applyFlash(effect) {
|
|
1084
|
+
if (flashPaint === null) flashPaint = Skia.Paint();
|
|
1085
|
+
writeColor(flashColor, effect.color, flashIntensity(effect));
|
|
1086
|
+
flashPaint.setColorFilter(Skia.ColorFilter.MakeBlend(flashColor, BLEND_SRC_OVER));
|
|
1087
|
+
return flashPaint;
|
|
1088
|
+
}
|
|
1089
|
+
function applyGrayscale(effect) {
|
|
1090
|
+
if (grayscalePaint === null) grayscalePaint = Skia.Paint();
|
|
1091
|
+
writeGrayscaleMatrix(grayMatrix, effect.amount);
|
|
1092
|
+
grayscalePaint.setColorFilter(Skia.ColorFilter.MakeMatrix(grayMatrix));
|
|
1093
|
+
return grayscalePaint;
|
|
1094
|
+
}
|
|
1095
|
+
function applyOutlinePaint(effect) {
|
|
1096
|
+
if (outlinePaint === null) outlinePaint = Skia.Paint();
|
|
1097
|
+
writeColor(outlineColor, effect.color, 1);
|
|
1098
|
+
outlinePaint.setColorFilter(Skia.ColorFilter.MakeBlend(outlineColor, BLEND_SRC_IN));
|
|
1099
|
+
return outlinePaint;
|
|
1100
|
+
}
|
|
1101
|
+
function applyCustom(effect) {
|
|
1102
|
+
if (customPaint === null) customPaint = Skia.Paint();
|
|
1103
|
+
const shader = effect.shader;
|
|
1104
|
+
const floatCount = shader.getUniformFloatCount();
|
|
1105
|
+
while (customUniforms.length < floatCount) customUniforms.push(0);
|
|
1106
|
+
customUniforms.length = floatCount;
|
|
1107
|
+
fillCustomUniforms(effect, shader, customUniforms);
|
|
1108
|
+
customPaint.setShader(shader.makeShader(customUniforms));
|
|
1109
|
+
return customPaint;
|
|
1110
|
+
}
|
|
1111
|
+
function applyWater(effect, time) {
|
|
1112
|
+
if (Skia.RuntimeEffect === void 0) return defaultPaint;
|
|
1113
|
+
if (waterRuntimeEffect === null) {
|
|
1114
|
+
const compiled = Skia.RuntimeEffect.Make(WATER_SKSL);
|
|
1115
|
+
if (compiled === null) return defaultPaint;
|
|
1116
|
+
waterRuntimeEffect = compiled;
|
|
1117
|
+
}
|
|
1118
|
+
if (waterPaint === null) waterPaint = Skia.Paint();
|
|
1119
|
+
waterUniforms[0] = 0;
|
|
1120
|
+
waterUniforms[1] = 0;
|
|
1121
|
+
waterUniforms[2] = effect.color.r;
|
|
1122
|
+
waterUniforms[3] = effect.color.g;
|
|
1123
|
+
waterUniforms[4] = effect.color.b;
|
|
1124
|
+
waterUniforms[5] = effect.foamColor.r;
|
|
1125
|
+
waterUniforms[6] = effect.foamColor.g;
|
|
1126
|
+
waterUniforms[7] = effect.foamColor.b;
|
|
1127
|
+
waterUniforms[8] = effect.waveSpeed;
|
|
1128
|
+
waterUniforms[9] = effect.waveAmplitude;
|
|
1129
|
+
waterUniforms[10] = time;
|
|
1130
|
+
waterPaint.setShader(waterRuntimeEffect.makeShader(waterUniforms));
|
|
1131
|
+
return waterPaint;
|
|
1132
|
+
}
|
|
1133
|
+
function applyFog(effect, time) {
|
|
1134
|
+
if (Skia.RuntimeEffect === void 0) return defaultPaint;
|
|
1135
|
+
if (fogRuntimeEffect === null) {
|
|
1136
|
+
const compiled = Skia.RuntimeEffect.Make(FOG_SKSL);
|
|
1137
|
+
if (compiled === null) return defaultPaint;
|
|
1138
|
+
fogRuntimeEffect = compiled;
|
|
1139
|
+
}
|
|
1140
|
+
if (fogPaint === null) fogPaint = Skia.Paint();
|
|
1141
|
+
fogUniforms[0] = 0;
|
|
1142
|
+
fogUniforms[1] = 0;
|
|
1143
|
+
fogUniforms[2] = effect.color.r;
|
|
1144
|
+
fogUniforms[3] = effect.color.g;
|
|
1145
|
+
fogUniforms[4] = effect.color.b;
|
|
1146
|
+
fogUniforms[5] = effect.density;
|
|
1147
|
+
fogUniforms[6] = effect.speed;
|
|
1148
|
+
fogUniforms[7] = effect.scale;
|
|
1149
|
+
fogUniforms[8] = time;
|
|
1150
|
+
fogPaint.setShader(fogRuntimeEffect.makeShader(fogUniforms));
|
|
1151
|
+
return fogPaint;
|
|
1152
|
+
}
|
|
1153
|
+
function applyFire(effect, time) {
|
|
1154
|
+
if (Skia.RuntimeEffect === void 0) return defaultPaint;
|
|
1155
|
+
if (fireRuntimeEffect === null) {
|
|
1156
|
+
const compiled = Skia.RuntimeEffect.Make(FIRE_SKSL);
|
|
1157
|
+
if (compiled === null) return defaultPaint;
|
|
1158
|
+
fireRuntimeEffect = compiled;
|
|
1159
|
+
}
|
|
1160
|
+
if (firePaint === null) firePaint = Skia.Paint();
|
|
1161
|
+
fireUniforms[0] = 0;
|
|
1162
|
+
fireUniforms[1] = 0;
|
|
1163
|
+
fireUniforms[2] = effect.color.r;
|
|
1164
|
+
fireUniforms[3] = effect.color.g;
|
|
1165
|
+
fireUniforms[4] = effect.color.b;
|
|
1166
|
+
fireUniforms[5] = effect.tipColor.r;
|
|
1167
|
+
fireUniforms[6] = effect.tipColor.g;
|
|
1168
|
+
fireUniforms[7] = effect.tipColor.b;
|
|
1169
|
+
fireUniforms[8] = effect.speed;
|
|
1170
|
+
fireUniforms[9] = effect.intensity;
|
|
1171
|
+
fireUniforms[10] = time;
|
|
1172
|
+
firePaint.setShader(fireRuntimeEffect.makeShader(fireUniforms));
|
|
1173
|
+
return firePaint;
|
|
1174
|
+
}
|
|
1175
|
+
function applyDropShadow(effect) {
|
|
1176
|
+
if (Skia.ImageFilter === void 0) return defaultPaint;
|
|
1177
|
+
if (dropShadowPaint === null) dropShadowPaint = Skia.Paint();
|
|
1178
|
+
writeColor(dropShadowColor, effect.color, 1);
|
|
1179
|
+
dropShadowPaint.setImageFilter(
|
|
1180
|
+
Skia.ImageFilter.MakeDropShadow(
|
|
1181
|
+
effect.offsetX,
|
|
1182
|
+
effect.offsetY,
|
|
1183
|
+
effect.blur,
|
|
1184
|
+
effect.blur,
|
|
1185
|
+
dropShadowColor,
|
|
1186
|
+
null
|
|
1187
|
+
)
|
|
1188
|
+
);
|
|
1189
|
+
return dropShadowPaint;
|
|
1190
|
+
}
|
|
1191
|
+
function applyRoofsCity(effect) {
|
|
1192
|
+
if (Skia.RuntimeEffect === void 0) return defaultPaint;
|
|
1193
|
+
if (roofsCityEffect === null) {
|
|
1194
|
+
const compiled = Skia.RuntimeEffect.Make(ROOFS_CITY_SKSL);
|
|
1195
|
+
if (compiled === null) return defaultPaint;
|
|
1196
|
+
roofsCityEffect = compiled;
|
|
1197
|
+
}
|
|
1198
|
+
if (roofsCityPaint === null) roofsCityPaint = Skia.Paint();
|
|
1199
|
+
roofsCityUniforms[0] = effect.resolutionW;
|
|
1200
|
+
roofsCityUniforms[1] = effect.resolutionH;
|
|
1201
|
+
roofsCityUniforms[2] = effect.skyColor.r;
|
|
1202
|
+
roofsCityUniforms[3] = effect.skyColor.g;
|
|
1203
|
+
roofsCityUniforms[4] = effect.skyColor.b;
|
|
1204
|
+
roofsCityUniforms[5] = effect.roofColor.r;
|
|
1205
|
+
roofsCityUniforms[6] = effect.roofColor.g;
|
|
1206
|
+
roofsCityUniforms[7] = effect.roofColor.b;
|
|
1207
|
+
roofsCityUniforms[8] = effect.scrollOffsetY;
|
|
1208
|
+
roofsCityUniforms[9] = effect.density;
|
|
1209
|
+
roofsCityPaint.setShader(roofsCityEffect.makeShader(roofsCityUniforms));
|
|
1210
|
+
return roofsCityPaint;
|
|
1211
|
+
}
|
|
1212
|
+
function applyForestCanopy(effect) {
|
|
1213
|
+
if (Skia.RuntimeEffect === void 0) return defaultPaint;
|
|
1214
|
+
if (forestCanopyEffect === null) {
|
|
1215
|
+
const compiled = Skia.RuntimeEffect.Make(FOREST_CANOPY_SKSL);
|
|
1216
|
+
if (compiled === null) return defaultPaint;
|
|
1217
|
+
forestCanopyEffect = compiled;
|
|
1218
|
+
}
|
|
1219
|
+
if (forestCanopyPaint === null) forestCanopyPaint = Skia.Paint();
|
|
1220
|
+
forestCanopyUniforms[0] = effect.resolutionW;
|
|
1221
|
+
forestCanopyUniforms[1] = effect.resolutionH;
|
|
1222
|
+
forestCanopyUniforms[2] = effect.skyColor.r;
|
|
1223
|
+
forestCanopyUniforms[3] = effect.skyColor.g;
|
|
1224
|
+
forestCanopyUniforms[4] = effect.skyColor.b;
|
|
1225
|
+
forestCanopyUniforms[5] = effect.leafColor.r;
|
|
1226
|
+
forestCanopyUniforms[6] = effect.leafColor.g;
|
|
1227
|
+
forestCanopyUniforms[7] = effect.leafColor.b;
|
|
1228
|
+
forestCanopyUniforms[8] = effect.scrollOffsetY;
|
|
1229
|
+
forestCanopyUniforms[9] = effect.density;
|
|
1230
|
+
forestCanopyPaint.setShader(forestCanopyEffect.makeShader(forestCanopyUniforms));
|
|
1231
|
+
return forestCanopyPaint;
|
|
1232
|
+
}
|
|
1233
|
+
function applyRiverWave(effect) {
|
|
1234
|
+
if (Skia.RuntimeEffect === void 0) return defaultPaint;
|
|
1235
|
+
if (riverWaveEffect === null) {
|
|
1236
|
+
const compiled = Skia.RuntimeEffect.Make(RIVER_WAVE_SKSL);
|
|
1237
|
+
if (compiled === null) return defaultPaint;
|
|
1238
|
+
riverWaveEffect = compiled;
|
|
1239
|
+
}
|
|
1240
|
+
if (riverWavePaint === null) riverWavePaint = Skia.Paint();
|
|
1241
|
+
riverWaveUniforms[0] = effect.resolutionW;
|
|
1242
|
+
riverWaveUniforms[1] = effect.resolutionH;
|
|
1243
|
+
riverWaveUniforms[2] = effect.waterColor.r;
|
|
1244
|
+
riverWaveUniforms[3] = effect.waterColor.g;
|
|
1245
|
+
riverWaveUniforms[4] = effect.waterColor.b;
|
|
1246
|
+
riverWaveUniforms[5] = effect.foamColor.r;
|
|
1247
|
+
riverWaveUniforms[6] = effect.foamColor.g;
|
|
1248
|
+
riverWaveUniforms[7] = effect.foamColor.b;
|
|
1249
|
+
riverWaveUniforms[8] = effect.scrollOffsetY;
|
|
1250
|
+
riverWaveUniforms[9] = effect.waveScale;
|
|
1251
|
+
riverWavePaint.setShader(riverWaveEffect.makeShader(riverWaveUniforms));
|
|
1252
|
+
return riverWavePaint;
|
|
1253
|
+
}
|
|
1254
|
+
function applyMoonCrater(effect) {
|
|
1255
|
+
if (Skia.RuntimeEffect === void 0) return defaultPaint;
|
|
1256
|
+
if (moonCraterEffect === null) {
|
|
1257
|
+
const compiled = Skia.RuntimeEffect.Make(MOON_CRATER_SKSL);
|
|
1258
|
+
if (compiled === null) return defaultPaint;
|
|
1259
|
+
moonCraterEffect = compiled;
|
|
1260
|
+
}
|
|
1261
|
+
if (moonCraterPaint === null) moonCraterPaint = Skia.Paint();
|
|
1262
|
+
moonCraterUniforms[0] = effect.resolutionW;
|
|
1263
|
+
moonCraterUniforms[1] = effect.resolutionH;
|
|
1264
|
+
moonCraterUniforms[2] = effect.moonColor.r;
|
|
1265
|
+
moonCraterUniforms[3] = effect.moonColor.g;
|
|
1266
|
+
moonCraterUniforms[4] = effect.moonColor.b;
|
|
1267
|
+
moonCraterUniforms[5] = effect.craterColor.r;
|
|
1268
|
+
moonCraterUniforms[6] = effect.craterColor.g;
|
|
1269
|
+
moonCraterUniforms[7] = effect.craterColor.b;
|
|
1270
|
+
moonCraterUniforms[8] = effect.scrollOffsetY;
|
|
1271
|
+
moonCraterUniforms[9] = effect.craterCount;
|
|
1272
|
+
moonCraterPaint.setShader(moonCraterEffect.makeShader(moonCraterUniforms));
|
|
1273
|
+
return moonCraterPaint;
|
|
1274
|
+
}
|
|
1275
|
+
function applyCaveInterior(effect) {
|
|
1276
|
+
if (Skia.RuntimeEffect === void 0) return defaultPaint;
|
|
1277
|
+
if (caveInteriorEffect === null) {
|
|
1278
|
+
const compiled = Skia.RuntimeEffect.Make(CAVE_INTERIOR_SKSL);
|
|
1279
|
+
if (compiled === null) return defaultPaint;
|
|
1280
|
+
caveInteriorEffect = compiled;
|
|
1281
|
+
}
|
|
1282
|
+
if (caveInteriorPaint === null) caveInteriorPaint = Skia.Paint();
|
|
1283
|
+
caveInteriorUniforms[0] = effect.resolutionW;
|
|
1284
|
+
caveInteriorUniforms[1] = effect.resolutionH;
|
|
1285
|
+
caveInteriorUniforms[2] = effect.caveColor.r;
|
|
1286
|
+
caveInteriorUniforms[3] = effect.caveColor.g;
|
|
1287
|
+
caveInteriorUniforms[4] = effect.caveColor.b;
|
|
1288
|
+
caveInteriorUniforms[5] = effect.glowColor.r;
|
|
1289
|
+
caveInteriorUniforms[6] = effect.glowColor.g;
|
|
1290
|
+
caveInteriorUniforms[7] = effect.glowColor.b;
|
|
1291
|
+
caveInteriorUniforms[8] = effect.scrollOffsetY;
|
|
1292
|
+
caveInteriorUniforms[9] = effect.stalactiteCount;
|
|
1293
|
+
caveInteriorPaint.setShader(caveInteriorEffect.makeShader(caveInteriorUniforms));
|
|
1294
|
+
return caveInteriorPaint;
|
|
1295
|
+
}
|
|
1296
|
+
function applyMountainHills(effect) {
|
|
1297
|
+
if (Skia.RuntimeEffect === void 0) return defaultPaint;
|
|
1298
|
+
if (mountainHillsEffect === null) {
|
|
1299
|
+
const compiled = Skia.RuntimeEffect.Make(MOUNTAIN_HILLS_SKSL);
|
|
1300
|
+
if (compiled === null) return defaultPaint;
|
|
1301
|
+
mountainHillsEffect = compiled;
|
|
1302
|
+
}
|
|
1303
|
+
if (mountainHillsPaint === null) mountainHillsPaint = Skia.Paint();
|
|
1304
|
+
mountainHillsUniforms[0] = effect.resolutionW;
|
|
1305
|
+
mountainHillsUniforms[1] = effect.resolutionH;
|
|
1306
|
+
mountainHillsUniforms[2] = effect.skyColor.r;
|
|
1307
|
+
mountainHillsUniforms[3] = effect.skyColor.g;
|
|
1308
|
+
mountainHillsUniforms[4] = effect.skyColor.b;
|
|
1309
|
+
mountainHillsUniforms[5] = effect.hillColor.r;
|
|
1310
|
+
mountainHillsUniforms[6] = effect.hillColor.g;
|
|
1311
|
+
mountainHillsUniforms[7] = effect.hillColor.b;
|
|
1312
|
+
mountainHillsUniforms[8] = effect.scrollOffsetY;
|
|
1313
|
+
mountainHillsUniforms[9] = effect.ridgeScale;
|
|
1314
|
+
mountainHillsPaint.setShader(mountainHillsEffect.makeShader(mountainHillsUniforms));
|
|
1315
|
+
return mountainHillsPaint;
|
|
1316
|
+
}
|
|
1317
|
+
function drawOutlined(cvs, image, commands, n, effect, alpha) {
|
|
1318
|
+
const paint = applyOutlinePaint(effect);
|
|
1319
|
+
paint.setAlphaf(alpha);
|
|
1320
|
+
const srcs = srcRects.length === n ? srcRects : srcRects.slice(0, n);
|
|
1321
|
+
for (let k = 0; k < OUTLINE_OFFSETS.length; k++) {
|
|
1322
|
+
const offset = OUTLINE_OFFSETS[k];
|
|
1323
|
+
fillXforms(commands, n, offset[0] * effect.width, offset[1] * effect.width);
|
|
1324
|
+
const dsts = xforms.length === n ? xforms : xforms.slice(0, n);
|
|
1325
|
+
cvs.drawAtlas(image, srcs, dsts, paint);
|
|
1326
|
+
}
|
|
1327
|
+
paint.setAlphaf(1);
|
|
1328
|
+
defaultPaint.setAlphaf(alpha);
|
|
1329
|
+
fillXforms(commands, n, 0, 0);
|
|
1330
|
+
const mainDsts = xforms.length === n ? xforms : xforms.slice(0, n);
|
|
1331
|
+
cvs.drawAtlas(image, srcs, mainDsts, defaultPaint);
|
|
1332
|
+
defaultPaint.setAlphaf(1);
|
|
1333
|
+
}
|
|
1334
|
+
function resolveEffectPaint(effect) {
|
|
1335
|
+
switch (effect.type) {
|
|
1336
|
+
case "tint":
|
|
1337
|
+
return applyTint(effect);
|
|
1338
|
+
case "flash":
|
|
1339
|
+
return applyFlash(effect);
|
|
1340
|
+
case "grayscale":
|
|
1341
|
+
return applyGrayscale(effect);
|
|
1342
|
+
case "custom":
|
|
1343
|
+
return applyCustom(effect);
|
|
1344
|
+
case "water":
|
|
1345
|
+
return applyWater(effect, currentFrameTime);
|
|
1346
|
+
case "fog":
|
|
1347
|
+
return applyFog(effect, currentFrameTime);
|
|
1348
|
+
case "fire":
|
|
1349
|
+
return applyFire(effect, currentFrameTime);
|
|
1350
|
+
case "drop-shadow":
|
|
1351
|
+
return applyDropShadow(effect);
|
|
1352
|
+
case "outline":
|
|
1353
|
+
return applyOutlinePaint(effect);
|
|
1354
|
+
case "roofs-city":
|
|
1355
|
+
return applyRoofsCity(effect);
|
|
1356
|
+
case "forest-canopy":
|
|
1357
|
+
return applyForestCanopy(effect);
|
|
1358
|
+
case "river-wave":
|
|
1359
|
+
return applyRiverWave(effect);
|
|
1360
|
+
case "moon-crater":
|
|
1361
|
+
return applyMoonCrater(effect);
|
|
1362
|
+
case "cave-interior":
|
|
1363
|
+
return applyCaveInterior(effect);
|
|
1364
|
+
case "mountain-hills":
|
|
1365
|
+
return applyMountainHills(effect);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
return {
|
|
1369
|
+
canvas,
|
|
1370
|
+
beginFrame(viewportWidth, viewportHeight, time = 0, pixelDensity = 1) {
|
|
1371
|
+
if (viewportWidth === 0 || viewportHeight === 0) return;
|
|
1372
|
+
_boundRuntime = null;
|
|
1373
|
+
_boundChain = null;
|
|
1374
|
+
currentFrameTime = time;
|
|
1375
|
+
const pd = pixelDensity;
|
|
1376
|
+
recordingBounds.setXYWH(0, 0, viewportWidth * pd, viewportHeight * pd);
|
|
1377
|
+
current = recorder.beginRecording(recordingBounds);
|
|
1378
|
+
if (pd !== 1) current.scale(pd, pd);
|
|
1379
|
+
},
|
|
1380
|
+
drawAtlas(image, commands) {
|
|
1381
|
+
if (current === null) return;
|
|
1382
|
+
const n = commands.length;
|
|
1383
|
+
if (n === 0) return;
|
|
1384
|
+
const effect = commands[0]?.effect;
|
|
1385
|
+
const alpha = commands[0]?.alpha ?? 1;
|
|
1386
|
+
if (effect?.type === "roofs-city" || effect?.type === "forest-canopy" || effect?.type === "river-wave" || effect?.type === "moon-crater" || effect?.type === "cave-interior" || effect?.type === "mountain-hills") {
|
|
1387
|
+
const paint2 = resolveEffectPaint(effect);
|
|
1388
|
+
paint2.setAlphaf(alpha);
|
|
1389
|
+
for (let i = 0; i < n; i++) {
|
|
1390
|
+
const cmd = commands[i];
|
|
1391
|
+
const rect = Skia.XYWHRect(cmd.dstX, cmd.dstY, cmd.dstW, cmd.dstH);
|
|
1392
|
+
current.drawRect(rect, paint2);
|
|
1393
|
+
}
|
|
1394
|
+
paint2.setAlphaf(1);
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
if (commands[0]?.stretch) {
|
|
1398
|
+
if (stretchPaint === null) stretchPaint = Skia.Paint();
|
|
1399
|
+
ensureStretchPoolCapacity(n);
|
|
1400
|
+
stretchPaint.setAlphaf(alpha);
|
|
1401
|
+
for (let i = 0; i < n; i++) {
|
|
1402
|
+
const cmd = commands[i];
|
|
1403
|
+
const srcR = stretchSrcRects[i];
|
|
1404
|
+
const dstR = stretchDstRects[i];
|
|
1405
|
+
srcR.setXYWH(cmd.srcX, cmd.srcY, cmd.srcW, cmd.srcH);
|
|
1406
|
+
dstR.setXYWH(cmd.dstX, cmd.dstY, cmd.dstW, cmd.dstH);
|
|
1407
|
+
current.drawImageRect(image, srcR, dstR, stretchPaint);
|
|
1408
|
+
}
|
|
1409
|
+
stretchPaint.setAlphaf(1);
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
ensurePoolCapacity(n);
|
|
1413
|
+
fillSrcRects(commands, n);
|
|
1414
|
+
if (effect?.type === "outline") {
|
|
1415
|
+
drawOutlined(current, image, commands, n, effect, alpha);
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
fillXforms(commands, n, 0, 0);
|
|
1419
|
+
const srcs = srcRects.length === n ? srcRects : srcRects.slice(0, n);
|
|
1420
|
+
const dsts = xforms.length === n ? xforms : xforms.slice(0, n);
|
|
1421
|
+
const paint = effect === void 0 ? defaultPaint : resolveEffectPaint(effect);
|
|
1422
|
+
paint.setAlphaf(alpha);
|
|
1423
|
+
current.drawAtlas(image, srcs, dsts, paint);
|
|
1424
|
+
paint.setAlphaf(1);
|
|
1425
|
+
},
|
|
1426
|
+
setPostFxBinding(runtime, chain) {
|
|
1427
|
+
_boundRuntime = runtime;
|
|
1428
|
+
_boundChain = chain;
|
|
1429
|
+
},
|
|
1430
|
+
buildPostFxPasses(runtime, chain, width, height) {
|
|
1431
|
+
const rt = runtime ?? _boundRuntime;
|
|
1432
|
+
const ch = chain ?? _boundChain;
|
|
1433
|
+
if (rt === null || !rt.supported) return [];
|
|
1434
|
+
if (rt.buildPass === void 0) {
|
|
1435
|
+
logOnce("buildPostFxPasses: runtime.supported but buildPass absent \u2014 no passes");
|
|
1436
|
+
return [];
|
|
1437
|
+
}
|
|
1438
|
+
if (ch === null) return [];
|
|
1439
|
+
const passes = rt.buildPass(ch, width, height);
|
|
1440
|
+
if (passes.length === 0) return [];
|
|
1441
|
+
const out = [];
|
|
1442
|
+
for (const pass of passes) {
|
|
1443
|
+
const shader = pass.shader;
|
|
1444
|
+
const uniformCount = typeof shader.getUniformCount === "function" ? shader.getUniformCount() : 0;
|
|
1445
|
+
const uniforms = {};
|
|
1446
|
+
for (let i = 0; i < uniformCount; i++) {
|
|
1447
|
+
const name = typeof shader.getUniformName === "function" ? shader.getUniformName(i) : String(i);
|
|
1448
|
+
const info = typeof shader.getUniform === "function" ? shader.getUniform(i) : { columns: 1, rows: 1, slot: i };
|
|
1449
|
+
const size = info.columns * info.rows;
|
|
1450
|
+
if (size === 1) {
|
|
1451
|
+
uniforms[name] = pass.uniforms[info.slot] ?? 0;
|
|
1452
|
+
} else {
|
|
1453
|
+
const vec = [];
|
|
1454
|
+
for (let k = 0; k < size; k++) {
|
|
1455
|
+
vec.push(pass.uniforms[info.slot + k] ?? 0);
|
|
1456
|
+
}
|
|
1457
|
+
uniforms[name] = vec;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
out.push({
|
|
1461
|
+
id: pass.id,
|
|
1462
|
+
source: shader,
|
|
1463
|
+
uniforms,
|
|
1464
|
+
children: pass.children
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
return out;
|
|
1468
|
+
},
|
|
1469
|
+
endFrame() {
|
|
1470
|
+
if (current === null) return null;
|
|
1471
|
+
current = null;
|
|
1472
|
+
return recorder.finishRecordingAsPicture();
|
|
1473
|
+
}
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
function writeColor(out, color, alphaMul) {
|
|
1477
|
+
out[0] = color.r;
|
|
1478
|
+
out[1] = color.g;
|
|
1479
|
+
out[2] = color.b;
|
|
1480
|
+
out[3] = color.a * alphaMul;
|
|
1481
|
+
}
|
|
1482
|
+
function writeGrayscaleMatrix(out, amount) {
|
|
1483
|
+
const inv = 1 - amount;
|
|
1484
|
+
const lr = 0.299 * amount;
|
|
1485
|
+
const lg = 0.587 * amount;
|
|
1486
|
+
const lb = 0.114 * amount;
|
|
1487
|
+
out[0] = inv + lr;
|
|
1488
|
+
out[1] = lg;
|
|
1489
|
+
out[2] = lb;
|
|
1490
|
+
out[3] = 0;
|
|
1491
|
+
out[4] = 0;
|
|
1492
|
+
out[5] = lr;
|
|
1493
|
+
out[6] = inv + lg;
|
|
1494
|
+
out[7] = lb;
|
|
1495
|
+
out[8] = 0;
|
|
1496
|
+
out[9] = 0;
|
|
1497
|
+
out[10] = lr;
|
|
1498
|
+
out[11] = lg;
|
|
1499
|
+
out[12] = inv + lb;
|
|
1500
|
+
out[13] = 0;
|
|
1501
|
+
out[14] = 0;
|
|
1502
|
+
out[15] = 0;
|
|
1503
|
+
out[16] = 0;
|
|
1504
|
+
out[17] = 0;
|
|
1505
|
+
out[18] = 1;
|
|
1506
|
+
out[19] = 0;
|
|
1507
|
+
}
|
|
1508
|
+
function fillCustomUniforms(effect, shader, out) {
|
|
1509
|
+
const count = shader.getUniformCount();
|
|
1510
|
+
for (let i = 0; i < out.length; i++) out[i] = 0;
|
|
1511
|
+
for (let i = 0; i < count; i++) {
|
|
1512
|
+
const info = shader.getUniform(i);
|
|
1513
|
+
const name = shader.getUniformName(i);
|
|
1514
|
+
const value = effect.uniforms[name];
|
|
1515
|
+
const size = info.columns * info.rows;
|
|
1516
|
+
if (value === void 0) continue;
|
|
1517
|
+
if (typeof value === "number") {
|
|
1518
|
+
out[info.slot] = value;
|
|
1519
|
+
continue;
|
|
1520
|
+
}
|
|
1521
|
+
for (let k = 0; k < size; k++) {
|
|
1522
|
+
out[info.slot + k] = value[k] ?? 0;
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
|
|
931
1527
|
// src/sprite-font.ts
|
|
932
1528
|
function parseBMFontJSON(json) {
|
|
933
1529
|
const data = json;
|
|
@@ -1066,10 +1662,12 @@ export {
|
|
|
1066
1662
|
SpriteBatch,
|
|
1067
1663
|
WATER_SKSL,
|
|
1068
1664
|
caveInterior,
|
|
1665
|
+
createFrameRenderer,
|
|
1069
1666
|
createRenderSystem,
|
|
1070
1667
|
custom,
|
|
1071
1668
|
drawOrderCompare,
|
|
1072
1669
|
drawText,
|
|
1670
|
+
dropShadow,
|
|
1073
1671
|
fire,
|
|
1074
1672
|
flash,
|
|
1075
1673
|
flashIntensity,
|