PHPIndex

This page lists files in the current directory. You can view content, get download/execute commands for Wget, Curl, or PowerShell, or filter the list using wildcards (e.g., `*.sh`).

index.html
wget 'https://sme10.lists2.roe3.org/mdrone/cozyfire/index.html'
View Content
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <title>Cozy Winter Fire</title>
    <link rel="stylesheet" href="./style.css">

  </head>
    
  <body>
  <canvas id="glCanvas"></canvas>

<div class="container">
  <h1>Wood Burning Fireplace</h1>
  Have Yourself A Merry Little Christmas.
  <p><button id="fullscreenBtn">⤢ Toggle Fullscreen</button>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
    <script  src="./script.js"></script>

  </body>
  
</html>
script.js
wget 'https://sme10.lists2.roe3.org/mdrone/cozyfire/script.js'
View Content
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl2');
if (!gl) {
    console.error('WebGL 2 not supported');
    document.body.innerHTML = 'WebGL 2 is not supported in your browser.';
}

const vertexShaderSource = `#version 300 es
in vec4 aPosition;
void main() {
    gl_Position = aPosition;
}`;

const fragmentShaderSource = `#version 300 es
precision highp float;

uniform vec3 iResolution;
uniform float iTime;
uniform vec4 iMouse;
out vec4 fragColor;

/*--- BEGIN OF SHADERTOY ---*/

#define FLAME_HEIGHT 2.0
#define FLAME_ITERATIONS 5
#define FLAME_INTENSITY 2.0
#define SPARK_COUNT 50.0
#define SMOKE_OPACITY 0.8
#define TIME_SCALE 0.7
#define FLAME_WIDTH 1.2
#define NOISE_OCTAVES 3
#define DISPLACEMENT_OCTAVES 3

#define float2   vec2
#define float3   vec3
#define float4   vec4
#define lerp     mix
#define atan2    atan
#define frac     fract
#define fmod     mod
#define float2x2 mat2     
#define mul(a, b) a*b 
#define texSampl 1.
#define Texture2DSample(iChannel0, texSampl, uv) texture(iChannel0, uv)
#define ddx dFdx
#define ddy dFdy
#define saturate(oo) clamp(oo, 0.0, 1.0)

float3 fmod289(float3 x){return x-floor(x*(1./289.))*289.;}
float4 fmod289(float4 x){return x-floor(x*(1./289.))*289.;}
float4 permute(float4 x){return fmod289(((x*34.)+1.)*x);}
float4 taylorInvSqrt(float4 r){return 1.79284291400159-0.85373472095314*r;}

float snoise(float3 v){
    const float2 C = float2(1./6.,1./3.); const float4 D = float4(0.,.5,1.,2.);
    float3 i = floor(v + dot(v, C.yyy)); float3 x0 = v - i + dot(i, C.xxx);
    float3 g = step(x0.yzx, x0.xyz); float3 l = 1.0 - g;
    float3 i1 = min(g.xyz, l.zxy); float3 i2 = max(g.xyz, l.zxy);
    float3 x1 = x0 - i1 + C.xxx; float3 x2 = x0 - i2 + C.yyy;
    float3 x3 = x0 - D.yyy; i = fmod289(i);
    float4 p = permute(permute(permute(i.z + float4(0.0, i1.z, i2.z, 1.0))
        + i.y + float4(0.0, i1.y, i2.y, 1.0))+ i.x + float4(0.0, i1.x, i2.x, 1.0));
    float n_ = 0.142857142857; float3 ns = n_ * D.wyz - D.xzx;
    float4 j = p - 49.0 * floor(p * ns.z * ns.z);
    float4 x_ = floor(j * ns.z); float4 y_ = floor(j - 7.0 * x_);
    float4 x = x_ * ns.x + ns.yyyy; float4 y = y_ * ns.x + ns.yyyy;
    float4 h = 1.0 - abs(x) - abs(y);
    float4 b0 = float4(x.xy, y.xy); float4 b1 = float4(x.zw, y.zw);
    float4 s0 = floor(b0) * 2.0 + 1.0;float4 s1 = floor(b1) * 2.0 + 1.0;
    float4 sh = -step(h, float4(0.,0.,0.,0.));
    float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; float4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
    float3 p0 = float3(a0.xy, h.x); float3 p1 = float3(a0.zw, h.y);
    float3 p2 = float3(a1.xy, h.z); float3 p3 = float3(a1.zw, h.w);
    float4 norm = 1./sqrt(float4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
    p0 *= norm.x;p1 *= norm.y;p2 *= norm.z; p3 *= norm.w;
    float4 m = max(.6-float4(dot(x0,x0),dot(x1,x1),dot(x2,x2),dot(x3,x3)),0.); m=m*m;
    return 42.0 * dot(m * m, float4(dot(p0, x0), dot(p1, x1),
        dot(p2, x2), dot(p3, x3)));
}

float prng(in float2 seed) {
    seed = frac(seed * float2(5.3983, 5.4427));
    seed += dot(seed.yx, seed.xy + float2(21.5351, 14.3137));
    return frac(seed.x * seed.y * 95.4337);
}

float noiseStack(float3 pos, int octaves, float falloff) {
    float noise = snoise(float3(pos)); float off = 1.0;
    if (octaves > 1) {pos *= 2.0;off *= falloff;
       noise = (1.0 - off) * noise + off * snoise(float3(pos));}
    if (octaves > 2) {pos *= 2.0;off *= falloff;
        noise = (1.0 - off) * noise + off * snoise(float3(pos));
    }if (octaves > 3) {pos *= 2.0; off *= falloff;
        noise = (1.0 - off) * noise + off * snoise(float3(pos)); }
    if (octaves > 4) {pos *= 2.0; off *= falloff;
        noise = (1.0 - off) * noise + off * snoise(float3(pos)); }
    return (1.+noise)/2.;
}

float2 noiseStackUV(float3 pos, int octaves, float falloff, float diff) {
    float displaceA = noiseStack(pos, octaves, falloff);
    float displaceB = noiseStack(pos + float3(3984.293, 423.21, 5235.19), octaves, falloff);
    return float2(displaceA, displaceB);
}

float2 res(float2 uv, float time) {
    float PI = 3.1415926535897932384626433832795;
    float ypartClip = uv.y * FLAME_HEIGHT;
    float ypartClippedFalloff = clamp(FLAME_HEIGHT - ypartClip, 0.0, 1.0);
    float ypartClipped = min(ypartClip, 1.0);
    float ypartClippedn = 1.-ypartClipped;
    float xfuel = FLAME_WIDTH * (1.-abs(2.*uv.x-1.));
    float realTime = TIME_SCALE * time; float2 coordScaled = 6.*uv-.2;
    float3 position = float3(coordScaled,0.)+float3(1223.,6434.,8425.);
    float3 flow = float3(4.1*(.5-uv.x)*pow(ypartClippedn,4.),-2.*xfuel*pow(ypartClippedn,64.),0.);
    float3 timing = realTime * float3(0.0, -1.7, 1.1) + flow;
    float3 displacePos = float3(1.,.5,1.)*2.4*position+realTime*float3(.01,-.7,1.3);
    float3 displace3 = float3(noiseStackUV(displacePos, DISPLACEMENT_OCTAVES, 0.4, 0.1), 0.0);
    float3 noiseCoord = (float3(2.,1.,1.)*position+timing+.4*displace3);
    float noise = noiseStack(noiseCoord, NOISE_OCTAVES, 0.4);
    float flames = pow(ypartClipped,.3*xfuel)*pow(noise,.3*xfuel);
    float f = ypartClippedFalloff*pow(1.-flames*flames*flames,8.);
    float fire = FLAME_INTENSITY*(pow(f,3.)+f);
    float smokeNoise = .5+snoise(.4*(position+float3(0.,1.,0.))+timing*float3(1.,.8,-.5))/2.;
    float smoke = SMOKE_OPACITY*pow(xfuel,3.)*pow(uv.y,2.)*(smokeNoise+.4*(1.-noise));
    float sparkGridSize = SPARK_COUNT;
    float2 sparkCoord = uv*300.-float2(.0,190.*realTime);
    sparkCoord -= 30.*noiseStackUV(.01*float3(sparkCoord,30.*time),1,.4,.1);
    sparkCoord += 100.*flow.xy;
    if (fmod(sparkCoord.y/sparkGridSize,2.)<1.) sparkCoord.x +=.5*sparkGridSize;
    float2 sparkGridIndex = float2(floor(sparkCoord/sparkGridSize));
    float sparkRandom = prng(sparkGridIndex);
    float sparkLife=min(10.*(1.-min((sparkGridIndex.y+(190.*realTime/sparkGridSize))/(24.-20.*sparkRandom),1.)),1.);
    float sparks = 0.;
    if (sparkLife > 0.) {
        float sparkSize = xfuel*xfuel*sparkRandom*.04;
        float sparkRadians = 999.*sparkRandom*2.*PI+2.*time;
        float2 sparkCircular = float2(sin(sparkRadians), cos(sparkRadians));
        float2 sparkOffset = (.5-sparkSize)*sparkGridSize*sparkCircular;
        float2 sparkfmodulus = fmod(sparkCoord+sparkOffset,sparkGridSize)-float2(.5,.5)* sparkGridSize;
        float sparksGray = max(0.0, 1.0 - length(sparkfmodulus) / (sparkSize * sparkGridSize));
        sparks = sparkLife * sparksGray;
    }
    return float2(max(fire, sparks), smoke);
}

void mainImage(out float4 fragColor, in float2 fragCoord) {
    float2 uv = fragCoord.xy/iResolution.xy;
    float2 o = res(uv, iTime);
    fragColor = o.x*vec4(1.,.5,.0,1.)+vec4(.9,.8,.7,1.)*o.y;
}

/*--- END OF SHADERTOY ---*/

void main() {
    mainImage(fragColor, gl_FragCoord.xy);
}
`;

function createShader(gl, type, source) {
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('Shader compile error:', gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}

function createProgram(gl, vertexShader, fragmentShader) {
    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.error('Program link error:', gl.getProgramInfoLog(program));
        gl.deleteProgram(program);
        return null;
    }
    return program;
}

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
const program = createProgram(gl, vertexShader, fragmentShader);

const positionAttributeLocation = gl.getAttribLocation(program, 'aPosition');
const resolutionUniformLocation = gl.getUniformLocation(program, 'iResolution');
const timeUniformLocation = gl.getUniformLocation(program, 'iTime');
const mouseUniformLocation = gl.getUniformLocation(program, 'iMouse');

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);

gl.useProgram(program);

gl.enableVertexAttribArray(positionAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

let mouseX = 0, mouseY = 0;
canvas.addEventListener('mousemove', (e) => {
    mouseX = e.clientX;
    mouseY = canvas.height - e.clientY;  // Flip Y coordinate
});

function resizeCanvas() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    gl.viewport(0, 0, canvas.width, canvas.height);
}

window.addEventListener('resize', resizeCanvas);
resizeCanvas();  // Call once to set initial size

function render(time) {
    gl.uniform3f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height, 1.0);
    gl.uniform1f(timeUniformLocation, time * 0.001);
    gl.uniform4f(mouseUniformLocation, mouseX, mouseY, 0.0, 0.0);
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    requestAnimationFrame(render);
}

requestAnimationFrame(render);

// Fullscreen toggle functionality
const fullscreenBtn = document.getElementById('fullscreenBtn');
fullscreenBtn.addEventListener('click', toggleFullScreen);

function toggleFullScreen() {
  if (!document.fullscreenElement) {
    document.documentElement.requestFullscreen();
  } else {
    if (document.exitFullscreen) {
      document.exitFullscreen();
    }
  }
}
style.css
wget 'https://sme10.lists2.roe3.org/mdrone/cozyfire/style.css'
View Content
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");

body, html {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #001;
}
canvas {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

#controls {
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 100;
  display: flex;
  align-items: center;
  z-index: 1;
}
button {
  background-color: #4CAF50;
  border: none;
  color: white;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  border-radius: 10px;
  font-size: 16px;
  margin: 4px 2px;
  cursor: pointer;
  transition: background-color 0.3s;
  &:hover {
    background-color: #25902950;
  }
  &:active {
    background-color: #00FFFFCC;
  }
}
.btn {
  background-color: rgba(0, 0, 0, 0.4);
  border: none;
  color: rgba(255, 255, 255, 0.4);
  padding: 10px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 2px 2px;
  cursor: pointer;
  border-radius: 5px;
  transition: background-color 0.3s;
}
.btn:hover {
  background-color: rgba(255, 255, 255, 0.2);
  color: rgba(255, 255, 0, 1);
}
#fullscreenBtn {
  font-size: 20px;
}

.container {
  margin: 0 auto;
  padding: 2rem;
  position: absolute;
  width: 100%;
  font-family: "Roboto", sans-serif;
  text-shadow: 0 0 5px #000, 0 0 10px #000;
  color: #fff;
  filter: drop-shadow(0 0 10px rgba(0, 0, 50, 0.7))
		drop-shadow(0 0 15px rgba(0, 0, 0, 0.5))
		drop-shadow(0 0 20px rgba(0, 0, 0, 0.3));
  z-index: 2;
}


/* Phone User */
@media (max-width: 768px) {
  h1 {
    font-size: 1.25rem;
  }
  .container {
    font-size: 0.8rem;
  }
  .btn {
    font-size: 0.8rem;
  }
  #fullscreenBtn {
    font-size: 0.8rem;
    padding: 8px 15px;
  }
}