diff --git a/assets/shaders/noise.frag b/assets/shaders/noise.frag
index 4dbe490..adba968 100644
--- a/assets/shaders/noise.frag
+++ b/assets/shaders/noise.frag
@@ -15,7 +15,8 @@ uniform float u_time;
void main(){
vec2 st=(gl_FragCoord.xy+u_offset)/u_resolution;
-
+
+
vec2 q=vec2(0.);
q.x=fbm(st);
q.y=fbm(st+vec2(1.));
@@ -31,4 +32,5 @@ void main(){
vec3 color=mix(u_color_start,u_color_end,f*.3);
gl_FragColor=vec4(color,1.);
+
}
\ No newline at end of file
diff --git a/assets/workers/ShaderWorker.ts b/assets/workers/ShaderWorker.ts
new file mode 100644
index 0000000..0891248
--- /dev/null
+++ b/assets/workers/ShaderWorker.ts
@@ -0,0 +1,214 @@
+import noise from "~/assets/shaders/noise.frag?raw"
+
+import resolveLygia from "~/assets/workers/resolve-lygia.esm"
+
+let interval: number
+let timeout: number
+
+const shaderOptions = { quality: 1, framerate: 1000 / 60 }
+const screen = { width: 0, height: 0, devicePixelRatio: 0 }
+
+const _colorStart = [0, 0, 0]
+const _colorEnd = [0, 0, 0]
+
+let fragmentShader = resolveLygia(noise);
+
+let canvas: OffscreenCanvas
+
+let render: (time: number) => void
+
+let must_resize = false
+
+async function main(canvas: OffscreenCanvas) {
+ const gl = canvas.getContext("webgl");
+ if (!gl) {
+ return;
+ }
+ // setup GLSL program
+ const program = gl.createProgram()
+ if (!program) { return }
+
+ const fragment = gl.createShader(gl.FRAGMENT_SHADER);
+ if (!fragment) { return }
+ gl.shaderSource(fragment, fragmentShader)
+ gl.compileShader(fragment);
+ if (!gl.getShaderParameter(fragment, gl.COMPILE_STATUS)) {
+ const lastError = gl.getShaderInfoLog(fragment);
+ console.error(lastError)
+ gl.deleteShader(fragment);
+ return
+ }
+
+ const vertex = gl.createShader(gl.VERTEX_SHADER);
+ if (!vertex) { return }
+ gl.shaderSource(vertex, `attribute vec4 a_position;void main() {gl_Position = a_position;}`)
+ gl.compileShader(vertex);
+ if (!gl.getShaderParameter(vertex, gl.COMPILE_STATUS)) {
+ const lastError = gl.getShaderInfoLog(vertex);
+ console.error(lastError)
+ gl.deleteShader(vertex);
+ return
+ }
+
+ gl.attachShader(program, fragment)
+ gl.attachShader(program, vertex)
+ gl.linkProgram(program)
+ const linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+ if (!linked) { return }
+ // const program = webglUtils.createProgramFromSources(gl, [vs, fragmentShader2]);
+
+ // look up where the vertex data needs to go.
+ const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
+
+ // look up uniform locations
+ const offset = gl.getUniformLocation(program, "u_offset");
+ const resolutionLocation = gl.getUniformLocation(program, "u_resolution");
+ const colorStart = gl.getUniformLocation(program, "u_color_start");
+ const quality = gl.getUniformLocation(program, "u_quality");
+ const colorEnd = gl.getUniformLocation(program, "u_color_end");
+ const timeLocation = gl.getUniformLocation(program, "u_time");
+
+ // Create a buffer to put three 2d clip space points in
+ const positionBuffer = gl.createBuffer();
+
+ // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+
+ // fill it with a 2 triangles that cover clipspace
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+ -1, -1, // first triangle
+ 1, -1,
+ -1, 1,
+ -1, 1, // second triangle
+ 1, -1,
+ 1, 1,
+ ]), gl.STATIC_DRAW);
+
+
+ const gl2 = gl
+ function render(time: number) {
+ if (must_resize) {
+ canvas.width = screen.width * shaderOptions.quality / 10
+ canvas.height = screen.height * shaderOptions.quality / 10
+ must_resize = false;
+ }
+
+ time *= 0.001; // convert to seconds
+ // Tell WebGL how to convert from clip space to pixels
+ gl2.viewport(0, 0, gl2.canvas.width, gl2.canvas.height);
+
+ // Tell it to use our program (pair of shaders)
+ gl2.useProgram(program);
+
+ // Turn on the attribute
+ gl2.enableVertexAttribArray(positionAttributeLocation);
+
+ // Bind the position buffer.
+ gl2.bindBuffer(gl2.ARRAY_BUFFER, positionBuffer);
+
+ // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
+ gl2.vertexAttribPointer(
+ positionAttributeLocation,
+ 2, // 2 components per iteration
+ gl2.FLOAT, // the data is 32bit floats
+ false, // don't normalize the data
+ 0, // 0 = move forward size * sizeof(type) each iteration to get the next position
+ 0, // start at the beginning of the buffer
+ );
+
+ const secondRatio = screen.width / screen.height
+
+ if (secondRatio < 1) {
+ const half = canvas.height / 2
+ gl2.uniform2f(resolutionLocation, canvas.width, canvas.height * secondRatio);
+ gl2.uniform2f(offset, 0, -half + ((half) / (1 / secondRatio)));
+ } else {
+ const half = canvas.width / 2
+ gl2.uniform2f(resolutionLocation, canvas.width / secondRatio, canvas.height);
+ gl2.uniform2f(offset, -half + ((half) / secondRatio), 0);
+ }
+ gl2.uniform1i(quality, shaderOptions.quality)
+
+ gl2.uniform3f(colorStart, _colorStart[0], _colorStart[1], _colorStart[2]);
+ gl2.uniform3f(colorEnd, _colorEnd[0], _colorEnd[1], _colorEnd[2]);
+ gl2.uniform1f(timeLocation, time);
+ gl2.drawArrays(
+ gl2.TRIANGLES,
+ 0, // offset
+ 6, // num vertices to process
+ );
+ if (timeout) {
+ self.clearTimeout(timeout)
+ timeout = self.setTimeout(() => {
+ requestAnimationFrame(render)
+ }, 1000 / shaderOptions.framerate)
+ }
+ }
+
+ requestAnimationFrame(render)
+
+ // self.clearInterval(interval)
+ // interval = self.setInterval(() => requestAnimationFrame(render), 1000 / shaderOptions.framerate)
+ self.clearTimeout(timeout)
+ if (shaderOptions.framerate == 0) {
+ return render
+ }
+ timeout = self.setTimeout(() => {
+ requestAnimationFrame(render)
+ }, 1000 / shaderOptions.framerate)
+ return render
+}
+
+self.addEventListener("message", (e) => {
+ const data = e.data
+ if (data.command == "initShader") {
+ canvas = data.canvas
+ shaderOptions.quality = data.shaderOptions.quality
+ shaderOptions.framerate = data.shaderOptions.framerate
+ if (shaderOptions.framerate == 65) {
+ shaderOptions.framerate == Infinity
+ }
+ screen.devicePixelRatio = data.screen.devicePixelRatio
+ screen.width = data.screen.width
+ screen.height = data.screen.height
+ loadShader()
+ } else if (data.command == "killShader") {
+ console.log("killShader")
+ self.clearInterval(interval)
+ self.clearTimeout(timeout)
+ }
+ else if (data.command == "resumeShader") {
+ self.clearInterval(interval)
+ self.clearTimeout(timeout)
+ shaderOptions.framerate = data.shaderOptions.framerate
+ if (shaderOptions.framerate == 65) {
+ shaderOptions.framerate == Infinity
+ }
+ timeout = self.setTimeout(() => {
+ requestAnimationFrame(render)
+ }, 1000 / shaderOptions.framerate)
+ // interval = self.setInterval(() => requestAnimationFrame(render), 1000 / shaderOptions.framerate)
+ } else if (data.command == "recolorShader") {
+ _colorStart[0] = data.colorStart[0]
+ _colorStart[1] = data.colorStart[1]
+ _colorStart[2] = data.colorStart[2]
+ _colorEnd[0] = data.colorEnd[0]
+ _colorEnd[1] = data.colorEnd[1]
+ _colorEnd[2] = data.colorEnd[2]
+ } else if (data.command == "resizeShader") {
+ shaderOptions.quality = data.shaderOptions.quality
+ screen.devicePixelRatio = data.screen.devicePixelRatio
+ screen.width = data.screen.width
+ screen.height = data.screen.height
+ must_resize = true
+ }
+})
+
+async function loadShader() {
+ if (!canvas) { return }
+ // let fragmentShader2 = fragmentShader.replace("#define FBM_OCTAVES 6", "#define FBM_OCTAVES " + shaderOptions.quality);
+ const temp = await main(canvas);
+ if (temp) {
+ render = temp
+ }
+}
\ No newline at end of file
diff --git a/assets/workers/resolve-lygia.esm.js b/assets/workers/resolve-lygia.esm.js
new file mode 100644
index 0000000..5537afc
--- /dev/null
+++ b/assets/workers/resolve-lygia.esm.js
@@ -0,0 +1,52 @@
+function getFile(url) {
+ let httpRequest = new XMLHttpRequest();
+ httpRequest.open("GET", url, false);
+ httpRequest.send();
+ if (httpRequest.status == 200)
+ return httpRequest.responseText;
+ else
+ return "";
+ }
+
+function resolveLygia(lines) {
+ if ( !Array.isArray(lines) ) {
+ lines = lines.split(/\r?\n/);
+ }
+
+ let src = "";
+ lines.forEach( (line, i) => {
+ const line_trim = line.trim();
+ if (line_trim.startsWith('#include \"lygia') ) {
+ let include_url = line_trim.substring(15);
+ include_url = "https://lygia.xyz" + include_url.replace(/\"|\;|\s/g,'');
+ src += getFile(include_url) + '\n';
+ }
+ else {
+ src += line + '\n';
+ }
+ });
+
+ return src;
+}
+
+async function resolveLygiaAsync(lines) {
+ if (!Array.isArray(lines))
+ lines = lines.split(/\r?\n/);
+
+ let src = "";
+ const response = await Promise.all(
+ lines.map(async (line, i) => {
+ const line_trim = line.trim();
+ if (line_trim.startsWith('#include "lygia')) {
+ let include_url = line_trim.substring(15);
+ include_url = "https://lygia.xyz" + include_url.replace(/\"|\;|\s/g, "");
+ return fetch(include_url).then((res) => res.text());
+ }
+ else
+ return line;
+ })
+ );
+
+ return response.join("\n");
+}
+export { resolveLygia as default };
diff --git a/components/AnimatedBackground.vue b/components/AnimatedBackground.vue
index e462b05..e29f0fc 100644
--- a/components/AnimatedBackground.vue
+++ b/components/AnimatedBackground.vue
@@ -1,151 +1,121 @@
-
+
\ No newline at end of file
diff --git a/components/MarketCards.vue b/components/MarketCards.vue
index cdcbcca..60ed6c7 100644
--- a/components/MarketCards.vue
+++ b/components/MarketCards.vue
@@ -109,7 +109,9 @@ function onEnter(el: any, done: () => unknown) {
padding-bottom: 10px;
border-radius: 10px;
filter: drop-shadow(2.5px 7.5px 1px rgba(0, 0, 0, .60));
- backdrop-filter: hue-rotate(625deg) blur(5px) brightness(80%);
+ backdrop-filter: blur(5px) brightness(80%);
+ background: rgba(155, 62, 62, 0.46);
+
}
.separator {
diff --git a/components/OptionsDialog.vue b/components/OptionsDialog.vue
index 2aa4181..78143dd 100644
--- a/components/OptionsDialog.vue
+++ b/components/OptionsDialog.vue
@@ -6,6 +6,9 @@ export interface Props {
isVisible: boolean;
}
+const _devicePixelRatio = computed(() => devicePixelRatio)
+const _window = computed(() => window)
+
const props = withDefaults(defineProps(), {
})
@@ -15,10 +18,6 @@ const close = () => {
emit('close')
}
-watch(() => settingsStore.shaderQuality, async () => {
- console.log(settingsStore.shaderQuality)
-})
-
@@ -40,27 +39,29 @@ watch(() => settingsStore.shaderQuality, async () => {
Shader Quality
-
+
-
+
+
+
+
diff --git a/components/PlayerSlot.vue b/components/PlayerSlot.vue
index da028bf..4d4c823 100644
--- a/components/PlayerSlot.vue
+++ b/components/PlayerSlot.vue
@@ -60,7 +60,6 @@ function can_buy_fire_gem(): boolean {
function checkEndTurn() {
// TODO: Add a confirmation dialog if resources are left
- console.log("Checking end turn")
if (
(!warning.value)
&& has_actions_remaining()) {
@@ -377,7 +376,7 @@ function check_for_guard(player: Player) {
border: 5px solid black;
border-radius: 10px;
filter: drop-shadow(2.5px 7.5px 1px rgba(0, 0, 0, .60));
- backdrop-filter: blur(5px) brightness(80%) hue-rotate(0deg) grayscale(80%);
+ backdrop-filter: blur(5px) brightness(80%) grayscale(80%);
}
diff --git a/nuxt.config.ts b/nuxt.config.ts
index 875119d..43369d5 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -12,13 +12,4 @@ export default defineNuxtConfig({
'@pinia/nuxt',
'@pinia-plugin-persistedstate/nuxt',
],
- app: {
- head: {
- script: [{
- src: "/webgl-utils.js"
- }, {
- src: "https://lygia.xyz/resolve.js"
- }]
- }
- },
})
diff --git a/package-lock.json b/package-lock.json
index efce2ba..4151a2e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
"hasInstallScript": true,
"dependencies": {
"@pinia/nuxt": "^0.5.1",
+ "gsap": "^3.12.5",
"nuxt": "^3.11.2",
"pinia": "^2.1.7",
"vue": "^3.4.21",
@@ -5670,6 +5671,12 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
+ "node_modules/gsap": {
+ "version": "3.12.5",
+ "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.12.5.tgz",
+ "integrity": "sha512-srBfnk4n+Oe/ZnMIOXt3gT605BX9x5+rh/prT2F1SsNJsU1XuMiP0E2aptW481OnonOGACZWBqseH5Z7csHxhQ==",
+ "license": "Standard 'no charge' license: https://gsap.com/standard-license. Club GSAP members get more: https://gsap.com/licensing/. Why GreenSock doesn't employ an MIT license: https://gsap.com/why-license/"
+ },
"node_modules/gzip-size": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-7.0.0.tgz",
diff --git a/package.json b/package.json
index 0025121..6a627ad 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
},
"dependencies": {
"@pinia/nuxt": "^0.5.1",
+ "gsap": "^3.12.5",
"nuxt": "^3.11.2",
"pinia": "^2.1.7",
"vue": "^3.4.21",
diff --git a/stores/settingsStore.ts b/stores/settingsStore.ts
index e60202a..dbd8f52 100644
--- a/stores/settingsStore.ts
+++ b/stores/settingsStore.ts
@@ -8,8 +8,9 @@ enum CardStyles {
export const useSettingsStore = defineStore("settingstore", {
state: () => ({
cardStyle: CardStyles.HERON,
- shaderQuality: 0,
- shaderFramerate: 10,
+ shaderQuality: 3,
+ shaderFramerate: 0,
+ shaderPixelated: true
}),
actions: {
switchCardStyles() {