Тестовая тема 1
Сообщений 1 страница 19 из 19
Поделиться72023-02-21 21:30:42
Esymeo
Тест-тест!
Поделиться112023-03-05 13:19:13
Поделиться132023-03-05 14:02:32
[hideauthor] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed semper, turpis sit amet pulvinar suscipit, quam eros pellentesque elit, non suscipit dolor enim id magna. Cras scelerisque risus vitae urna scelerisque laoreet. Donec et congue sem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer auctor mi sit amet massa vulputate dapibus. Duis ornare lorem at libero eleifend congue. Ut pretium arcu in erat mollis, at tincidunt urna lobortis. Morbi et justo ante. Fusce pretium libero non nunc commodo dapibus. Maecenas euismod tortor et magna vulputate, rhoncus commodo justo rhoncus. Vivamus nec augue bibendum, consequat magna in, auctor ligula.
Aenean orci ipsum, tempus at magna ac, scelerisque lacinia arcu. Nullam congue nisi at neque tincidunt vehicula. Proin bibendum facilisis arcu, sit amet molestie risus suscipit a. Maecenas velit purus, interdum ac tempus vel, feugiat et ex. Praesent at lectus urna. Maecenas sit amet arcu suscipit orci pulvinar feugiat. Nunc viverra iaculis tempus. Donec facilisis tempus nibh, eu elementum nunc porttitor eget. Cras finibus, orci sed vulputate tristique, ex lorem scelerisque orci, sed commodo ante nunc eu purus. Morbi placerat orci eu nibh ultrices pharetra. Cras eu viverra massa, eu scelerisque augue.
Vestibulum gravida nec leo at tincidunt. Nunc et nisi in urna aliquet suscipit ac a orci. Aliquam a augue consectetur, tempor ante sit amet, tincidunt arcu. Phasellus ac ornare urna. Mauris elit purus, ullamcorper eu ipsum varius, pulvinar rutrum velit. Cras enim diam, dignissim ac tempor eget, sodales at velit. Nulla vitae tortor arcu. Nam sem mi, blandit vitae orci vestibulum, fermentum auctor lacus. Quisque volutpat felis eu lectus mollis sagittis. Pellentesque semper ut nisl lobortis faucibus.
Phasellus sapien massa, iaculis ut enim sed, tempus sagittis turpis. Morbi a commodo ipsum. Nullam dictum sit amet urna non sodales. Aenean a luctus magna, nec varius eros. In in nulla eu justo fermentum egestas. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec in ex metus. Nullam sit amet faucibus magna.
Integer id urna a eros faucibus suscipit. Sed mollis imperdiet justo, id rutrum mi maximus at. Fusce id ante felis. Duis magna nibh, lobortis vel interdum ut, commodo vitae urna. Quisque vel nisl posuere, accumsan nisi vel, elementum tellus. Sed nec ipsum vel quam semper sollicitudin faucibus id lectus. In posuere dapibus ornare. Cras lectus augue, hendrerit et facilisis eget, euismod vitae urna. Duis enim nibh, scelerisque quis dolor ac, semper porttitor sem. Cras sit amet nibh nec mauris cursus scelerisque. Etiam eget velit non massa consectetur hendrerit. Donec feugiat bibendum mauris, eget aliquam velit venenatis et. Nunc congue lobortis enim at maximus. Sed eleifend sit amet dui sed pretium.[/block]
- Подпись автора
Поделиться152023-06-11 12:14:04
[html]<style>
.sl-1 {width:300px;}
</style>
<!-- Автопрокрутка кликабельных картинок, © Deff, модификация от Chat GPT -->
<div class="SL"></div>
<script>
var arraySL = [
{
src: 'https://forumstatic.ru/files/0013/44/56/61036.png', //ссылка на картинку
link: 'https://example.com/image1' //ссылка на страницу
},
{
src: 'https://forumstatic.ru/files/0013/44/56/73446.png', //ссылка на картинку
link: 'https://example.com/image2' //ссылка на страницу
},
{
src: 'https://forumstatic.ru/files/0013/44/56/54143.png', //ссылка на картинку
link: 'https://example.com/image3' //ссылка на страницу
},
{
src: 'https://forumstatic.ru/files/0013/44/56/21344.png', //ссылка на картинку
link: 'https://example.com/image4' //ссылка на страницу
},
{
src: 'https://forumstatic.ru/files/0013/44/56/87837.png', //ссылка на картинку
link: 'https://example.com/image5' //ссылка на страницу
}
];
var heightSL = 'auto'; //'auto'//'386px'; //Высота в пикселах или 'auto';
var SLtime = 5; //Время в секундах;
(function() {
var arr = arraySL.slice(0);
var H = heightSL;
var t = SLtime * 1000;
var el = $('div.SL:first').removeClass('SL').addClass('sl-1').css({
'height': H,
'overflow': 'hidden'
});
var img = '<a href="#LINK"><img src="#SRC" width="100%" style="display:none"></a>';
for (var i = 0; i < arr.length; i++) {
var a = $(img.replace('#LINK', arr[i].link).replace('#SRC', arr[i].src)).appendTo(el);
if (!i) a.show();
}
var timId;
function slideImg() {
var a = el.find('img:visible:first').hide().parent().appendTo(el);
el.find('a:first img').show();
timId = setTimeout(function() {
slideImg()
}, t);
}
slideImg();
/*Видимость/невидимость Вкладки Браузера с выводом победителе!*/
// При первом входе на страницу Событие(ниже) не работает!
$(document).on('visibilitychange', function() {
clearTimeout(timId);
if (document.visibilityState == 'visible') {
slideImg();
}
});
}());
</script>
[/html]
- Подпись автора
Поделиться162023-06-11 12:14:24
[html]<!-- Автопрокрутка картинок -->
<div class="SL" style="width:300px;text-align:center"></div>
<script>
var arraySL = [ //Cписок ссылок на Изображения:
'https://forumstatic.ru/files/0013/44/56/61036.png',
'https://forumstatic.ru/files/0013/44/56/73446.png',
'https://forumstatic.ru/files/0013/44/56/54143.png',
'https://forumstatic.ru/files/0013/44/56/21344.png',
'https://forumstatic.ru/files/0013/44/56/87837.png'
]
var heightSL = 'auto'; //'auto'//'386px'; //Высота в пикселах или 'auto';
var SLtime = 5; //Время в секундах;
</script>
<script type="text/javascript" src="https://forumstatic.ru/files/0013/44/56/17756.js"></script>[/html]
- Подпись автора
Поделиться172024-02-27 14:44:19
[html]<div style="top:0px;position:fixed;z-index:-1; width:100%; left:-650px;text-align: center; font-size:50px;">
<marquee behavior="ALTERNATE" direction="up" bgcolor="#FFFF00" width="30" height="620" scrolldelay="200" onMouseOver="this.stop()" onMouseOut="this.start()" loop="infinite"><center>Код от Тони </center></marquee>
</div>[/html]
- Подпись автора
Поделиться182024-03-04 11:28:33
[html]
<style>
h5 {
opacity: 0.66;
font-weight: normal;
font-size: 1.25rem;
}
.container {
position: relative;
width: 430px;
height: 350px;
margin: 50px auto;
background: #fafafa;
display: flex;
flex-direction: column;
justify-content: space-between;
color: #fff;
}
.time {
padding: 10px;
display: flex;
justify-content: space-around;
}
.time-item {
flex: 1 1 auto;
border-radius: 5px;
margin-right: 5px;
height: 10px;
background-color: rgba(0,0,0,0.10);
position: relative;
overflow: hidden;
}
.time-item:last-child {
margin-right: 0;
}
.time-item > div {
position: absolute;
width: 0%;
height: 100%;
background-color: rgba(255,255,255,0.5);
}
.content {
position: absolute;
height: 350px;
width:430px;
background-image: linear-gradient(-180deg, rgba(255,255,255,0.00) 0%, rgba(0,0,0,0.15) 100%);
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.texts {
padding: 7%;
}
#back, #next {
position: absolute;
top: 0;
}
#back {
left: 0;
height: 100%;
width: 50%;
}
#next {
left: 50%;
height: 100%;
width: 50%;
}
</style>
<script>
const stories = [
{
title: 'Story 1',
description: 'description 1',
image: 'https://i.pinimg.com/736x/2e/be/62/2ebe623d6d27d70ea13731a01b4210e9.jpg',
time: 3500
},
{
title: 'Story 2',
description: 'description 2',
image: 'https://i.pinimg.com/736x/7c/f8/18/7cf818809ed21f9d21263b8a8417d504.jpg',
time: 4000
},{
title: 'Story 3',
description: 'description 3',
image: 'https://i.pinimg.com/736x/b7/7b/e1/b77be1a020e21187490bb65859d2832c.jpg',
time: 2500
},
{
title: 'Story 4',
description: 'description 4',
image: 'https://i.pinimg.com/736x/8d/77/5e/8d775e040b58466a44518ad6b5c2a678.jpg',
time: 7500
}
]
const container = document.querySelector('.container')
const nextButton = document.querySelector('#next')
const backButton = document.querySelector('#back')
function Storyfier(storiesArray, rootEl) {
this.stories = storiesArray
this.root = rootEl
this.times = rootEl.querySelector('#times')
this.currentTime = 0
this.currentIndex = 0
// create breakpoints for when the slides should change
this.intervals = this.stories.map((story, index) => {
// TODO change so that it just uses the previous value + current time
let sum = 0
for (let i = 0; i < index; i++){
sum += this.stories[i].time
}
return sum
})
// necessary to make sure the last slide plays to completion
this.maxTime = this.intervals[this.intervals.length - 1] + this.stories[this.stories.length - 1].time
// render progress bars
this.progressBars = this.stories.map(() => {
const el = document.createElement('div')
el.classList.add('time-item')
el.innerHTML = '<div style="width: 0%"></div>'
return el
})
this.progressBars.forEach((el) => {
this.times.appendChild(el)
})
// methods
this.render = () => {
const story = this.stories[this.currentIndex]
this.root.style.background = `url('${story.image}')`
this.root.querySelector('#title').innerHTML = story.title
this.root.querySelector('#description').innerHTML = story.description
}
this.updateProgress = () => {
this.progressBars.map((bar, index) => {
// Fill already passed bars
if (this.currentIndex > index) {
bar.querySelector('div').style.width = '100%'
return
}
if (this.currentIndex < index) {
bar.querySelector('div').style.width = '0%'
return
}
// update progress of current bar
if (this.currentIndex == index) {
const timeStart = this.intervals[this.currentIndex]
let timeEnd;
if (this.currentIndex == this.stories.length - 1){
timeEnd = this.maxTime
} else {
timeEnd = this.intervals[this.currentIndex + 1]
}
const animatable = bar.querySelector('div')
animatable.style.width = `${((this.currentTime - timeStart)/(timeEnd - timeStart))*100}%`
}
})
}
}
Storyfier.prototype.start = function(){
// Render initial state
this.render()
// START INTERVAL
const test = setInterval(() => {
this.currentTime += 10
this.updateProgress()
if (this.currentIndex >= this.stories.length - 1 && (this.currentTime > this.maxTime)){
clearInterval(test)
return
}
const lastIndex = this.currentIndex
if (this.currentTime >= this.intervals[this.currentIndex + 1]){
this.currentIndex += 1
}
if (this.currentIndex != lastIndex) {
this.render()
}
}, 10)
}
Storyfier.prototype.next = function(){
const next = this.currentIndex + 1
if (next > this.stories.length - 1){
return
}
this.currentIndex = next
this.currentTime = this.intervals[this.currentIndex]
this.render()
}
Storyfier.prototype.back = function(){
if ((this.currentTime > (this.intervals[this.currentIndex] + 350)) || this.currentIndex === 0){
this.currentTime = this.intervals[this.currentIndex]
return
}
this.currentIndex -= 1
this.currentTime = this.intervals[this.currentIndex]
this.render()
}
const setup = async () => {
const loadImages = stories.map(({ image }) => {
return new Promise((resolve, reject) => {
let img = new Image()
img.onload = () => {
resolve(image)
}
img.src = image
})
})
await Promise.all(loadImages)
const s = new Storyfier(stories, container);
s.start()
nextButton.addEventListener('click', () => {
s.next()
})
backButton.addEventListener('click', () => {
s.back()
})
}
setup()
</script>
<div class="container">
<div id="times" class="time">
</div>
<div class="content">
<div class="texts">
<h1 id="title"></h1>
<h5 id="description"></h5>
</div>
</div>
<div id="back"></div>
<div id="next"></div>
</div>
[/html]
- Подпись автора
Поделиться192024-03-04 11:30:34
[html]
<style>
#container {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 800px;
}
.a-title {
position: absolute;
color: transparent;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-image: conic-gradient(#ed0101, blue);
pointer-events: none;
mix-blend-mode: difference;
filter: drop-shadow(2px 4px 6px black);
}
.a-second-title {
position: absolute;
margin-top: 25vh;
pointer-events: none;
-webkit-text-stroke: 1.3px white;
letter-spacing: 1.125px;
font-size: -webkit-xxx-large;
font-weight: 900;
mix-blend-mode: color-dodge;
}
canvas {
width: 100%;
height: 100%;
}
</style>
<script>
'use strict';
const canvas = document.getElementsByTagName('canvas')[0];
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
let config = {
TEXTURE_DOWNSAMPLE: 1,
DENSITY_DISSIPATION: 0.98,
VELOCITY_DISSIPATION: 0.99,
PRESSURE_DISSIPATION: 0.8,
PRESSURE_ITERATIONS: 25,
CURL: 28,
SPLAT_RADIUS: 0.004 };
let pointers = [];
let splatStack = [];
const { gl, ext } = getWebGLContext(canvas);
function getWebGLContext(canvas) {
const params = { alpha: false, depth: false, stencil: false, antialias: false };
let gl = canvas.getContext('webgl2', params);
const isWebGL2 = !!gl;
if (!isWebGL2)
gl = canvas.getContext('webgl', params) || canvas.getContext('experimental-webgl', params);
let halfFloat;
let supportLinearFiltering;
if (isWebGL2) {
gl.getExtension('EXT_color_buffer_float');
supportLinearFiltering = gl.getExtension('OES_texture_float_linear');
} else {
halfFloat = gl.getExtension('OES_texture_half_float');
supportLinearFiltering = gl.getExtension('OES_texture_half_float_linear');
}
gl.clearColor(0.0, 0.0, 0.0, 1.0);
const halfFloatTexType = isWebGL2 ? gl.HALF_FLOAT : halfFloat.HALF_FLOAT_OES;
let formatRGBA;
let formatRG;
let formatR;
if (isWebGL2)
{
formatRGBA = getSupportedFormat(gl, gl.RGBA16F, gl.RGBA, halfFloatTexType);
formatRG = getSupportedFormat(gl, gl.RG16F, gl.RG, halfFloatTexType);
formatR = getSupportedFormat(gl, gl.R16F, gl.RED, halfFloatTexType);
} else
{
formatRGBA = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);
formatRG = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);
formatR = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType);
}
return {
gl,
ext: {
formatRGBA,
formatRG,
formatR,
halfFloatTexType,
supportLinearFiltering } };
}
function getSupportedFormat(gl, internalFormat, format, type)
{
if (!supportRenderTextureFormat(gl, internalFormat, format, type))
{
switch (internalFormat) {
case gl.R16F:
return getSupportedFormat(gl, gl.RG16F, gl.RG, type);
case gl.RG16F:
return getSupportedFormat(gl, gl.RGBA16F, gl.RGBA, type);
default:
return null;}
}
return {
internalFormat,
format };
}
function supportRenderTextureFormat(gl, internalFormat, format, type) {
let texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
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.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 4, 4, 0, format, type, null);
let fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
if (status != gl.FRAMEBUFFER_COMPLETE)
return false;
return true;
}
function pointerPrototype() {
this.id = -1;
this.x = 0;
this.y = 0;
this.dx = 0;
this.dy = 0;
this.down = false;
this.moved = false;
this.color = [30, 0, 300];
}
pointers.push(new pointerPrototype());
class GLProgram {
constructor(vertexShader, fragmentShader) {
this.uniforms = {};
this.program = gl.createProgram();
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
throw gl.getProgramInfoLog(this.program);
const uniformCount = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
for (let i = 0; i < uniformCount; i++) {
const uniformName = gl.getActiveUniform(this.program, i).name;
this.uniforms[uniformName] = gl.getUniformLocation(this.program, uniformName);
}
}
bind() {
gl.useProgram(this.program);
}}
function compileShader(type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
throw gl.getShaderInfoLog(shader);
return shader;
};
const baseVertexShader = compileShader(gl.VERTEX_SHADER, `
precision highp float;
precision mediump sampler2D;
attribute vec2 aPosition;
varying vec2 vUv;
varying vec2 vL;
varying vec2 vR;
varying vec2 vT;
varying vec2 vB;
uniform vec2 texelSize;
void main () {
vUv = aPosition * 0.5 + 0.5;
vL = vUv - vec2(texelSize.x, 0.0);
vR = vUv + vec2(texelSize.x, 0.0);
vT = vUv + vec2(0.0, texelSize.y);
vB = vUv - vec2(0.0, texelSize.y);
gl_Position = vec4(aPosition, 0.0, 1.0);
}
`);
const clearShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
uniform sampler2D uTexture;
uniform float value;
void main () {
gl_FragColor = value * texture2D(uTexture, vUv);
}
`);
const displayShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
uniform sampler2D uTexture;
void main () {
gl_FragColor = texture2D(uTexture, vUv);
}
`);
const splatShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
uniform sampler2D uTarget;
uniform float aspectRatio;
uniform vec3 color;
uniform vec2 point;
uniform float radius;
void main () {
vec2 p = vUv - point.xy;
p.x *= aspectRatio;
vec3 splat = exp(-dot(p, p) / radius) * color;
vec3 base = texture2D(uTarget, vUv).xyz;
gl_FragColor = vec4(base + splat, 1.0);
}
`);
const advectionManualFilteringShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
uniform sampler2D uVelocity;
uniform sampler2D uSource;
uniform vec2 texelSize;
uniform float dt;
uniform float dissipation;
vec4 bilerp (in sampler2D sam, in vec2 p) {
vec4 st;
st.xy = floor(p - 0.5) + 0.5;
st.zw = st.xy + 1.0;
vec4 uv = st * texelSize.xyxy;
vec4 a = texture2D(sam, uv.xy);
vec4 b = texture2D(sam, uv.zy);
vec4 c = texture2D(sam, uv.xw);
vec4 d = texture2D(sam, uv.zw);
vec2 f = p - st.xy;
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}
void main () {
vec2 coord = gl_FragCoord.xy - dt * texture2D(uVelocity, vUv).xy;
gl_FragColor = dissipation * bilerp(uSource, coord);
gl_FragColor.a = 1.0;
}
`);
const advectionShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
uniform sampler2D uVelocity;
uniform sampler2D uSource;
uniform vec2 texelSize;
uniform float dt;
uniform float dissipation;
void main () {
vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize;
gl_FragColor = dissipation * texture2D(uSource, coord);
gl_FragColor.a = 1.0;
}
`);
const divergenceShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
varying vec2 vL;
varying vec2 vR;
varying vec2 vT;
varying vec2 vB;
uniform sampler2D uVelocity;
vec2 sampleVelocity (in vec2 uv) {
vec2 multiplier = vec2(1.0, 1.0);
if (uv.x < 0.0) { uv.x = 0.0; multiplier.x = -1.0; }
if (uv.x > 1.0) { uv.x = 1.0; multiplier.x = -1.0; }
if (uv.y < 0.0) { uv.y = 0.0; multiplier.y = -1.0; }
if (uv.y > 1.0) { uv.y = 1.0; multiplier.y = -1.0; }
return multiplier * texture2D(uVelocity, uv).xy;
}
void main () {
float L = sampleVelocity(vL).x;
float R = sampleVelocity(vR).x;
float T = sampleVelocity(vT).y;
float B = sampleVelocity(vB).y;
float div = 0.5 * (R - L + T - B);
gl_FragColor = vec4(div, 0.0, 0.0, 1.0);
}
`);
const curlShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
varying vec2 vL;
varying vec2 vR;
varying vec2 vT;
varying vec2 vB;
uniform sampler2D uVelocity;
void main () {
float L = texture2D(uVelocity, vL).y;
float R = texture2D(uVelocity, vR).y;
float T = texture2D(uVelocity, vT).x;
float B = texture2D(uVelocity, vB).x;
float vorticity = R - L - T + B;
gl_FragColor = vec4(vorticity, 0.0, 0.0, 1.0);
}
`);
const vorticityShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
varying vec2 vT;
varying vec2 vB;
uniform sampler2D uVelocity;
uniform sampler2D uCurl;
uniform float curl;
uniform float dt;
void main () {
float T = texture2D(uCurl, vT).x;
float B = texture2D(uCurl, vB).x;
float C = texture2D(uCurl, vUv).x;
vec2 force = vec2(abs(T) - abs(B), 0.0);
force *= 1.0 / length(force + 0.00001) * curl * C;
vec2 vel = texture2D(uVelocity, vUv).xy;
gl_FragColor = vec4(vel + force * dt, 0.0, 1.0);
}
`);
const pressureShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
varying vec2 vL;
varying vec2 vR;
varying vec2 vT;
varying vec2 vB;
uniform sampler2D uPressure;
uniform sampler2D uDivergence;
vec2 boundary (in vec2 uv) {
uv = min(max(uv, 0.0), 1.0);
return uv;
}
void main () {
float L = texture2D(uPressure, boundary(vL)).x;
float R = texture2D(uPressure, boundary(vR)).x;
float T = texture2D(uPressure, boundary(vT)).x;
float B = texture2D(uPressure, boundary(vB)).x;
float C = texture2D(uPressure, vUv).x;
float divergence = texture2D(uDivergence, vUv).x;
float pressure = (L + R + B + T - divergence) * 0.25;
gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0);
}
`);
const gradientSubtractShader = compileShader(gl.FRAGMENT_SHADER, `
precision highp float;
precision mediump sampler2D;
varying vec2 vUv;
varying vec2 vL;
varying vec2 vR;
varying vec2 vT;
varying vec2 vB;
uniform sampler2D uPressure;
uniform sampler2D uVelocity;
vec2 boundary (in vec2 uv) {
uv = min(max(uv, 0.0), 1.0);
return uv;
}
void main () {
float L = texture2D(uPressure, boundary(vL)).x;
float R = texture2D(uPressure, boundary(vR)).x;
float T = texture2D(uPressure, boundary(vT)).x;
float B = texture2D(uPressure, boundary(vB)).x;
vec2 velocity = texture2D(uVelocity, vUv).xy;
velocity.xy -= vec2(R - L, T - B);
gl_FragColor = vec4(velocity, 0.0, 1.0);
}
`);
let textureWidth;
let textureHeight;
let density;
let velocity;
let divergence;
let curl;
let pressure;
initFramebuffers();
const clearProgram = new GLProgram(baseVertexShader, clearShader);
const displayProgram = new GLProgram(baseVertexShader, displayShader);
const splatProgram = new GLProgram(baseVertexShader, splatShader);
const advectionProgram = new GLProgram(baseVertexShader, ext.supportLinearFiltering ? advectionShader : advectionManualFilteringShader);
const divergenceProgram = new GLProgram(baseVertexShader, divergenceShader);
const curlProgram = new GLProgram(baseVertexShader, curlShader);
const vorticityProgram = new GLProgram(baseVertexShader, vorticityShader);
const pressureProgram = new GLProgram(baseVertexShader, pressureShader);
const gradienSubtractProgram = new GLProgram(baseVertexShader, gradientSubtractShader);
function initFramebuffers() {
textureWidth = gl.drawingBufferWidth >> config.TEXTURE_DOWNSAMPLE;
textureHeight = gl.drawingBufferHeight >> config.TEXTURE_DOWNSAMPLE;
const texType = ext.halfFloatTexType;
const rgba = ext.formatRGBA;
const rg = ext.formatRG;
const r = ext.formatR;
density = createDoubleFBO(2, textureWidth, textureHeight, rgba.internalFormat, rgba.format, texType, ext.supportLinearFiltering ? gl.LINEAR : gl.NEAREST);
velocity = createDoubleFBO(0, textureWidth, textureHeight, rg.internalFormat, rg.format, texType, ext.supportLinearFiltering ? gl.LINEAR : gl.NEAREST);
divergence = createFBO(4, textureWidth, textureHeight, r.internalFormat, r.format, texType, gl.NEAREST);
curl = createFBO(5, textureWidth, textureHeight, r.internalFormat, r.format, texType, gl.NEAREST);
pressure = createDoubleFBO(6, textureWidth, textureHeight, r.internalFormat, r.format, texType, gl.NEAREST);
}
function createFBO(texId, w, h, internalFormat, format, type, param) {
gl.activeTexture(gl.TEXTURE0 + texId);
let texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, param);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, param);
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.texImage2D(gl.TEXTURE_2D, 0, internalFormat, w, h, 0, format, type, null);
let fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
gl.viewport(0, 0, w, h);
gl.clear(gl.COLOR_BUFFER_BIT);
return [texture, fbo, texId];
}
function createDoubleFBO(texId, w, h, internalFormat, format, type, param) {
let fbo1 = createFBO(texId, w, h, internalFormat, format, type, param);
let fbo2 = createFBO(texId + 1, w, h, internalFormat, format, type, param);
return {
get read() {
return fbo1;
},
get write() {
return fbo2;
},
swap() {
let temp = fbo1;
fbo1 = fbo2;
fbo2 = temp;
} };
}
const blit = (() => {
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(0);
return destination => {
gl.bindFramebuffer(gl.FRAMEBUFFER, destination);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
};
})();
let lastTime = Date.now();
multipleSplats(parseInt(Math.random() * 20) + 5);
update();
function update() {
resizeCanvas();
const dt = Math.min((Date.now() - lastTime) / 1000, 0.016);
lastTime = Date.now();
gl.viewport(0, 0, textureWidth, textureHeight);
if (splatStack.length > 0)
multipleSplats(splatStack.pop());
advectionProgram.bind();
gl.uniform2f(advectionProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
gl.uniform1i(advectionProgram.uniforms.uVelocity, velocity.read[2]);
gl.uniform1i(advectionProgram.uniforms.uSource, velocity.read[2]);
gl.uniform1f(advectionProgram.uniforms.dt, dt);
gl.uniform1f(advectionProgram.uniforms.dissipation, config.VELOCITY_DISSIPATION);
blit(velocity.write[1]);
velocity.swap();
gl.uniform1i(advectionProgram.uniforms.uVelocity, velocity.read[2]);
gl.uniform1i(advectionProgram.uniforms.uSource, density.read[2]);
gl.uniform1f(advectionProgram.uniforms.dissipation, config.DENSITY_DISSIPATION);
blit(density.write[1]);
density.swap();
for (let i = 0; i < pointers.length; i++) {
const pointer = pointers[i];
if (pointer.moved) {
splat(pointer.x, pointer.y, pointer.dx, pointer.dy, pointer.color);
pointer.moved = false;
}
}
curlProgram.bind();
gl.uniform2f(curlProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
gl.uniform1i(curlProgram.uniforms.uVelocity, velocity.read[2]);
blit(curl[1]);
vorticityProgram.bind();
gl.uniform2f(vorticityProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
gl.uniform1i(vorticityProgram.uniforms.uVelocity, velocity.read[2]);
gl.uniform1i(vorticityProgram.uniforms.uCurl, curl[2]);
gl.uniform1f(vorticityProgram.uniforms.curl, config.CURL);
gl.uniform1f(vorticityProgram.uniforms.dt, dt);
blit(velocity.write[1]);
velocity.swap();
divergenceProgram.bind();
gl.uniform2f(divergenceProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
gl.uniform1i(divergenceProgram.uniforms.uVelocity, velocity.read[2]);
blit(divergence[1]);
clearProgram.bind();
let pressureTexId = pressure.read[2];
gl.activeTexture(gl.TEXTURE0 + pressureTexId);
gl.bindTexture(gl.TEXTURE_2D, pressure.read[0]);
gl.uniform1i(clearProgram.uniforms.uTexture, pressureTexId);
gl.uniform1f(clearProgram.uniforms.value, config.PRESSURE_DISSIPATION);
blit(pressure.write[1]);
pressure.swap();
pressureProgram.bind();
gl.uniform2f(pressureProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
gl.uniform1i(pressureProgram.uniforms.uDivergence, divergence[2]);
pressureTexId = pressure.read[2];
gl.uniform1i(pressureProgram.uniforms.uPressure, pressureTexId);
gl.activeTexture(gl.TEXTURE0 + pressureTexId);
for (let i = 0; i < config.PRESSURE_ITERATIONS; i++) {
gl.bindTexture(gl.TEXTURE_2D, pressure.read[0]);
blit(pressure.write[1]);
pressure.swap();
}
gradienSubtractProgram.bind();
gl.uniform2f(gradienSubtractProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
gl.uniform1i(gradienSubtractProgram.uniforms.uPressure, pressure.read[2]);
gl.uniform1i(gradienSubtractProgram.uniforms.uVelocity, velocity.read[2]);
blit(velocity.write[1]);
velocity.swap();
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
displayProgram.bind();
gl.uniform1i(displayProgram.uniforms.uTexture, density.read[2]);
blit(null);
requestAnimationFrame(update);
}
function splat(x, y, dx, dy, color) {
splatProgram.bind();
gl.uniform1i(splatProgram.uniforms.uTarget, velocity.read[2]);
gl.uniform1f(splatProgram.uniforms.aspectRatio, canvas.width / canvas.height);
gl.uniform2f(splatProgram.uniforms.point, x / canvas.width, 1.0 - y / canvas.height);
gl.uniform3f(splatProgram.uniforms.color, dx, -dy, 1.0);
gl.uniform1f(splatProgram.uniforms.radius, config.SPLAT_RADIUS);
blit(velocity.write[1]);
velocity.swap();
gl.uniform1i(splatProgram.uniforms.uTarget, density.read[2]);
gl.uniform3f(splatProgram.uniforms.color, color[0] * 0.3, color[1] * 0.3, color[2] * 0.3);
blit(density.write[1]);
density.swap();
}
function multipleSplats(amount) {
for (let i = 0; i < amount; i++) {
const color = [Math.random() * 10, Math.random() * 10, Math.random() * 10];
const x = canvas.width * Math.random();
const y = canvas.height * Math.random();
const dx = 1000 * (Math.random() - 0.5);
const dy = 1000 * (Math.random() - 0.5);
splat(x, y, dx, dy, color);
}
}
function resizeCanvas() {
if (canvas.width != canvas.clientWidth || canvas.height != canvas.clientHeight) {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
initFramebuffers();
}
}
canvas.addEventListener('mousemove', e => {
pointers[0].moved = pointers[0].down;
pointers[0].dx = (e.offsetX - pointers[0].x) * 10.0;
pointers[0].dy = (e.offsetY - pointers[0].y) * 10.0;
pointers[0].x = e.offsetX;
pointers[0].y = e.offsetY;
});
canvas.addEventListener('touchmove', e => {
e.preventDefault();
const touches = e.targetTouches;
for (let i = 0; i < touches.length; i++) {
let pointer = pointers[i];
pointer.moved = pointer.down;
pointer.dx = (touches[i].pageX - pointer.x) * 10.0;
pointer.dy = (touches[i].pageY - pointer.y) * 10.0;
pointer.x = touches[i].pageX;
pointer.y = touches[i].pageY;
}
}, false);
canvas.addEventListener('mousemove', () => {
pointers[0].down = true;
pointers[0].color = [Math.random() + 0.2, Math.random() + 0.2, Math.random() + 0.2];
});
canvas.addEventListener('touchstart', e => {
e.preventDefault();
const touches = e.targetTouches;
for (let i = 0; i < touches.length; i++) {
if (i >= pointers.length)
pointers.push(new pointerPrototype());
pointers[i].id = touches[i].identifier;
pointers[i].down = true;
pointers[i].x = touches[i].pageX;
pointers[i].y = touches[i].pageY;
pointers[i].color = [Math.random() + 0.2, Math.random() + 0.2, Math.random() + 0.2];
}
});
window.addEventListener('mouseleave', () => {
pointers[0].down = false;
});
window.addEventListener('touchend', e => {
const touches = e.changedTouches;
for (let i = 0; i < touches.length; i++)
for (let j = 0; j < pointers.length; j++)
if (touches[i].identifier == pointers[j].id)
pointers[j].down = false;
});
</script>
<section id='container'>
<h1 class='a-title'>Move the mouse</h1>
<h2 class='a-second-title'>See the magic</h2>
<canvas></canvas>
</section>
[/html]
- Подпись автора