JSFiddle - React, Tailwind, and code Playground
by Sergey khorev
HTML
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Чёрная дыра с вихрем</title>
<style>
body { margin: 0; height: 200vh; }
canvas { width: 100%; height: 100vh; position: fixed; top: 0; left: 0; }
</style>
</head>
<body>
<canvas id="glCanvas"></canvas>
<script src="shader.js"></script>
</body>
</html>
JavaScript
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
// Устанавливаем размер канваса
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Вершинный шейдер (без изменений)
const vertexShaderSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
`;
// Фрагментный шейдер с вращением внутри искажения
const fragmentShaderSource = `
precision mediump float;
uniform vec2 u_resolution;
uniform float u_scroll;
uniform float u_time;
void main() {
vec2 p = (gl_FragCoord.xy * 2.0 - u_resolution) / u_resolution.y;
float radius = 0.5 + u_scroll * 0.2; // Эффект отдаления
// Вращение искажения
float angle = u_time * 2.0; // Скорость вращения
float s = sin(angle);
float c = cos(angle);
vec2 rotatedP = vec2(
p.x * c - p.y * s,
p.x * s + p.y * c
);
float distortion = 0.01 / (rotatedP.x - rotatedP.y); // Вращаем только p.x - p.y
// Оригинальная формула с вращением внутри
float o = 0.0;
o += 0.1 / abs(length(p) - radius + distortion);
// Добавляем затемнение к центру для эффекта чёрной дыры
float darkness = smoothstep(0.0, radius, length(p));
gl_FragColor = vec4(vec3(o * darkness), 1.0);
}
`;
// Функция создания шейдера (без изменений)
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 vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
const...