Jo jeste jsem narazil na projekt jednoho manika co si hodne hraje se shadery a protoze se mi nektere efekty hodne libily, tak jsem postval AI na to aby z toho udelala singlepage html/javascript page.
<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rocaille 2 - WebGL Shader</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { overflow: hidden; background: #000; font-family: system-ui, sans-serif; color: #eee; }
canvas { display: block; width: 100vw; height: 100vh; }
#ui {
position: absolute;
top: 15px;
right: 15px;
background: rgba(15, 15, 20, 0.85);
backdrop-filter: blur(8px);
padding: 16px;
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.1);
display: grid;
grid-template-columns: 100px 120px 45px;
gap: 10px 12px;
align-items: center;
font-size: 13px;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 4px 20px rgba(0,0,0,0.5);
}
#ui label { font-weight: 500; }
#ui input[type=range] { accent-color: #007acc; cursor: pointer; }
#ui span { font-family: monospace; text-align: right; opacity: 0.8; }
</style>
</head>
<body>
<canvas id="glcanvas"></canvas>
<div id="ui"></div>
<script>
const vsSource = `#version 300 es
in vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}`;
const fsSource = `#version 300 es
precision highp float;
uniform vec2 u_resolution;
uniform float u_time;
uniform float u_brightness;
uniform float u_scale;
uniform float u_steps;
uniform float u_offset;
uniform float u_color;
uniform vec3 u_rgb;
uniform float u_turb_max;
uniform float u_turb_speed;
out vec4 fragColor;
void main() {
vec3 col = vec3(0.0);
vec2 p = (2.0 * gl_FragCoord.xy - u_resolution.xy) / u_resolution.y / u_scale;
for (float i = 0.0; i < u_steps; i += 1.0) {
vec2 wave = p;
for (float j = 1.0; j < u_turb_max; j += 1.0) {
wave += sin(wave.yx * j + u_offset * i + u_turb_speed * u_time) / j;
}
col += (cos(u_color * i + u_rgb) + 1.0) / length(wave);
}
col = 1.0 - exp(-u_brightness * col * col);
fragColor = vec4(col, 1.0);
}`;
const params = [
{ id: 'u_brightness', label: 'Brightness', val: 0.028, min: 0.001, max: 0.1, step: 0.001 },
{ id: 'u_scale', label: 'Scale', val: 0.3, min: 0.05, max: 1.0, step: 0.01 },
{ id: 'u_steps', label: 'Steps', val: 10, min: 1, max: 20, step: 1 },
{ id: 'u_offset', label: 'Offset', val: 1.0, min: 0.0, max: 2.0, step: 0.05 },
{ id: 'u_color', label: 'Color Shift', val: 1.0, min: 0.0, max: 2.0, step: 0.05 },
{ id: 'u_rgb_r', label: 'RGB Phase R', val: 0.0, min: -1.0, max: 3.0, step: 0.1 },
{ id: 'u_rgb_g', label: 'RGB Phase G', val: 1.0, min: -1.0, max: 3.0, step: 0.1 },
{ id: 'u_rgb_b', label: 'RGB Phase B', val: 2.0, min: -1.0, max: 3.0, step: 0.1 },
{ id: 'u_turb_max', label: 'Turb Max', val: 9.0, min: 4.5, max: 13.5, step: 0.5 },
{ id: 'u_turb_speed', label: 'Turb Speed', val: 1.0, min: 0.0, max: 3.0, step: 0.05 }
];
const state = {};
const uiContainer = document.getElementById('ui');
params.forEach(p => {
state[p.id] = p.val;
const label = document.createElement('label');
label.textContent = p.label;
const input = document.createElement('input');
input.type = 'range';
input.min = p.min;
input.max = p.max;
input.step = p.step;
input.value = p.val;
const valDisplay = document.createElement('span');
valDisplay.textContent = p.val;
input.addEventListener('input', (e) => {
const num = parseFloat(e.target.value);
state[p.id] = num;
valDisplay.textContent = num;
});
uiContainer.appendChild(label);
uiContainer.appendChild(input);
uiContainer.appendChild(valDisplay);
});
const canvas = document.getElementById('glcanvas');
const gl = canvas.getContext('webgl2');
if (!gl) {
alert('WebGL 2 není ve vašem prohlížeči podporován.');
}
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(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
const program = gl.createProgram();
gl.attachShader(program, createShader(gl, gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, createShader(gl, gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);
const positionLoc = gl.getAttribLocation(program, 'a_position');
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1, -1, 1, -1, -1, 1,
-1, 1, 1, -1, 1, 1,
]), gl.STATIC_DRAW);
const uniforms = {
u_resolution: gl.getUniformLocation(program, 'u_resolution'),
u_time: gl.getUniformLocation(program, 'u_time'),
u_brightness: gl.getUniformLocation(program, 'u_brightness'),
u_scale: gl.getUniformLocation(program, 'u_scale'),
u_steps: gl.getUniformLocation(program, 'u_steps'),
u_offset: gl.getUniformLocation(program, 'u_offset'),
u_color: gl.getUniformLocation(program, 'u_color'),
u_rgb: gl.getUniformLocation(program, 'u_rgb'),
u_turb_max: gl.getUniformLocation(program, 'u_turb_max'),
u_turb_speed: gl.getUniformLocation(program, 'u_turb_speed'),
};
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
gl.viewport(0, 0, canvas.width, canvas.height);
}
window.addEventListener('resize', resize);
resize();
function render(time) {
time *= 0.001;
gl.useProgram(program);
gl.enableVertexAttribArray(positionLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
gl.uniform2f(uniforms.u_resolution, canvas.width, canvas.height);
gl.uniform1f(uniforms.u_time, time);
gl.uniform1f(uniforms.u_brightness, state.u_brightness);
gl.uniform1f(uniforms.u_scale, state.u_scale);
gl.uniform1f(uniforms.u_steps, state.u_steps);
gl.uniform1f(uniforms.u_offset, state.u_offset);
gl.uniform1f(uniforms.u_color, state.u_color);
gl.uniform3f(uniforms.u_rgb, state.u_rgb_r, state.u_rgb_g, state.u_rgb_b);
gl.uniform1f(uniforms.u_turb_max, state.u_turb_max);
gl.uniform1f(uniforms.u_turb_speed, state.u_turb_speed);
gl.drawArrays(gl.TRIANGLES, 0, 6);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
</script>
</body>
</html>