Тестовый форум для дизайнов

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Тестовая тема 1

Сообщений 1 страница 19 из 19

1

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

2

2

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

3

2

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

4

2

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

5

2

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

6

--

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

7

Esymeo
Тест-тест!

0

8

https://forumupload.ru/uploads/0015/1e/ae/4/599636.gif

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

9

https://forumupload.ru/uploads/0015/1e/ae/4/599636.gif

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

10

https://forumupload.ru/uploads/0015/1e/ae/4/599636.gif

тестируем размытый текст

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

11

Пример ссылки, пример обычного текста

Пример ссылки, пример обычного текста

https://forumupload.ru/uploads/0015/1e/ae/4/599636.gif

https://forumupload.ru/uploads/0015/1e/ae/4/599636.gif

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

12

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

13

[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]

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

14

Таблица с невидимыми границами:

https://forumupload.ru/uploads/0015/1e/ae/4/599636.gif

https://forumupload.ru/uploads/0015/1e/ae/4/599636.gif

Таблица где границы видны:

https://forumupload.ru/uploads/0015/1e/ae/4/599636.gif

https://forumupload.ru/uploads/0015/1e/ae/4/599636.gif

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

15

[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]

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

16

[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]

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

17

[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]

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

18

[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]

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

19

[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]

Подпись автора

"You don't need to be protected,
Because nothing shocks you any more."
© Mesh
https://forumstatic.ru/files/0015/1e/ae/69675.gif https://forumstatic.ru/files/0018/3d/6c/77729.jpg

0

Быстрый ответ

Напишите ваше сообщение и нажмите «Отправить»