Complete end portal shader

This commit is contained in:
tryashtar
2026-04-08 00:06:19 -06:00
parent 868a56830b
commit d14e6c02ee
4 changed files with 203 additions and 138 deletions
+15 -11
View File
@@ -1,12 +1,16 @@
*
!*/
/caddy/config/
/caddy/data/
/copyparty/cache/
/copyparty/config/copyparty/
/jellyfin/cache/
/jellyfin/config/
/pigallery2/images/
/pigallery2/tmp/
/pigallery2/db/
!/.gitignore
!/docker-compose.yaml
!/caddy/Caddyfile
!/copyparty/config/copyparty.conf
!/pigallery2/config/config.json
!/http/index.html
!/http/poem.html
!/http/script.js
!/http/style.css
/http/bitf
/http/marketplace
/http/mcfont
/http/mojira
/http/reddit
/media
+88 -27
View File
@@ -6,59 +6,98 @@
<meta name="theme-color" content="#02060D"/>
<title>End Poem</title>
<script src="https://xemantic.github.io/shader-web-background/dist/shader-web-background.min.js"></script>
<script type="x-shader/x-fragment" id="image">
<script type="x-shader/x-fragment" id="end-portal">
precision highp float;
uniform vec2 iResolution;
uniform float iTime;
mat2 mat2_rotate_z(float radians) {
return mat2(
cos(radians), -sin(radians),
sin(radians), cos(radians)
);
}
uniform sampler2D Sampler0;
uniform sampler2D Sampler1;
const mat4 SCALE_TRANSLATE = mat4(
0.5, 0.0, 0.0, 0.25,
0.0, 0.5, 0.0, 0.25,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
mat4 end_portal_layer(float layer) {
mat4 translate = mat4(
1.0, 0.0, 0.0, 17.0 / layer,
0.0, 1.0, 0.0, (2.0 + layer / 1.5) * (iTime * 1.5),
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
mat2 rotate = mat2_rotate_z(radians((layer * layer * 4321.0 + layer * 9.0) * 2.0));
mat2 scale = mat2((4.5 - layer / 4.0) * 2.0);
return mat4(scale * rotate) * translate * SCALE_TRANSLATE;
}
void main() {
vec4 uv = vec4(gl_FragCoord.xy / iResolution.xy, 0.0, 1.0);
vec3 color = texture2D(Sampler0, uv.xy).rgb * vec3(0.022087, 0.098399, 0.110818);
color += texture2D(Sampler1, (uv * end_portal_layer(1.0)).xy).rgb * vec3(0.022087, 0.098399, 0.110818);
color += texture2D(Sampler1, (uv * end_portal_layer(2.0)).xy).rgb * vec3(0.011892, 0.095924, 0.089485);
color += texture2D(Sampler1, (uv * end_portal_layer(3.0)).xy).rgb * vec3(0.027636, 0.101689, 0.100326);
color += texture2D(Sampler1, (uv * end_portal_layer(4.0)).xy).rgb * vec3(0.046564, 0.109883, 0.114838);
color += texture2D(Sampler1, (uv * end_portal_layer(5.0)).xy).rgb * vec3(0.064901, 0.117696, 0.097189);
color += texture2D(Sampler1, (uv * end_portal_layer(6.0)).xy).rgb * vec3(0.063761, 0.086895, 0.123646);
color += texture2D(Sampler1, (uv * end_portal_layer(7.0)).xy).rgb * vec3(0.084817, 0.111994, 0.166380);
color += texture2D(Sampler1, (uv * end_portal_layer(8.0)).xy).rgb * vec3(0.097489, 0.154120, 0.091064);
color += texture2D(Sampler1, (uv * end_portal_layer(9.0)).xy).rgb * vec3(0.106152, 0.131144, 0.195191);
color += texture2D(Sampler1, (uv * end_portal_layer(10.0)).xy).rgb * vec3(0.097721, 0.110188, 0.187229);
color += texture2D(Sampler1, (uv * end_portal_layer(11.0)).xy).rgb * vec3(0.133516, 0.138278, 0.148582);
color += texture2D(Sampler1, (uv * end_portal_layer(12.0)).xy).rgb * vec3(0.070006, 0.243332, 0.235792);
color += texture2D(Sampler1, (uv * end_portal_layer(13.0)).xy).rgb * vec3(0.196766, 0.142899, 0.214696);
color += texture2D(Sampler1, (uv * end_portal_layer(14.0)).xy).rgb * vec3(0.047281, 0.315338, 0.321970);
color += texture2D(Sampler1, (uv * end_portal_layer(15.0)).xy).rgb * vec3(0.204675, 0.390010, 0.302066);
//color += texture2D(Sampler1, (uv * end_portal_layer(16.0)).xy).rgb * vec3(0.080955, 0.314821, 0.661491);
gl_FragColor = vec4(color, 1.0);
}
</script>
<script>
const loadImage = (src) => new Promise((resolve, reject) => {
const loadImage = (src) =>
new Promise((resolve, reject) => {
let img = new Image();
img.crossOrigin = "";
img.onload = () => resolve(img);
img.onerror = () => {
reject(new Error("Failed to load image from: " + src));
};
img.src = src;
});
const setupImage = (gl, texture, image) => {
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.bindTexture(gl.TEXTURE_2D, null);
};
shaderWebBackground.shade({
onInit: (ctx) => {
loadImage("end_portal.png")
.then(image => {
loadImage("poem/end_sky.png").then((image) => {
const gl = ctx.gl;
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.bindTexture(gl.TEXTURE_2D, null);
setupImage(gl, texture, image);
ctx.Sampler0 = texture;
});
loadImage("end_sky.png")
.then(image => {
loadImage("poem/end_portal.png").then((image) => {
const gl = ctx.gl;
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
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.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.bindTexture(gl.TEXTURE_2D, null);
ctx.Sampler0 = texture;
setupImage(gl, texture, image);
ctx.Sampler1 = texture;
});
},
shaders: {
image: {
"end-portal": {
uniforms: {
iResolution: (gl, loc, ctx) => gl.uniform2f(loc, ctx.width, ctx.height),
iTime: (gl, loc) => gl.uniform1f(loc, performance.now() / (24000 / 20 * 1000)),
Sampler0: (gl, loc, ctx) => ctx.texture(loc, ctx.Sampler0),
Sampler1: (gl, loc, ctx) => ctx.texture(loc, ctx.Sampler1),
}
}
}
@@ -68,8 +107,27 @@
body {
color: white;
background-color: #02060D;
margin: 0;
}
.vignette {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: -1;
background: radial-gradient(
ellipse,
rgba(0,0,0,0) 0%,
rgba(0,0,0,0) 50%,
rgba(0,0,0,166) 100%
);
}
.poem-box {
margin: auto;
max-width: fit-content;
z-index: 0;
}
@font-face {
font-family: MinecraftDefault;
@@ -198,6 +256,8 @@
</script>
</head>
<body>
<div class="vignette"></div>
<div class="poem-box">
<div class="poem">
<input type="text" id="playername" class="white" placeholder="player name" maxlength="64" size="16" oninput="updatePlayerName()"></input>
<p class="aqua">I see the player you mean.</p>
@@ -277,5 +337,6 @@
<p class="aqua">You are the player.</p>
<p class="green">Wake up.</p>
</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB