Демо JavaScript:
<!-- VERTEX SHADER --> <script type="shader" id="Vshader"> attribute vec2 vertexPosition; //атрибут вершин void main(){ gl_Position = vec4(vertexPosition, 0.0, 1.0); //строим вершинный шейдер } </script> <!-- FRAGMENT SHADER --> <script type="shader" id="Fshader"> precision mediump float; //устанавливаем точность для чисел с плавающей точкой uniform vec2 u_resolution; //униформы uniform float u_time; void main(){ vec2 st = gl_FragCoord.xy/u_resolution.xy; //нормализуем область st.x *= u_resolution.x/u_resolution.y; st = st * 20.-10.; //масштабируем и сдвигаем в центр float d = length( max(abs(st.xy)-.3,0.) * sin(st+u_time) * //описание фигуры sin(st-u_time)) * (sin(length(st) - u_time) + 1.); float smoother=smoothstep(.3,.4,d) * smoothstep(.6,.5,d); //сглаживаем цвет vec3 color = vec3( abs(sin(smoother*sin(st.y-u_time))), smoother*sin(st.x-u_time)*sin(st.x-u_time), smoother*abs(sin(st.x-u_time)) ); gl_FragColor = vec4(vec3(color) ,1.0); } </script> <script> function startWebGL() { //получаем исходники шейдеров var vertexShaderText = document.getElementById('Vshader').text; var fragmentShaderText = document.getElementById('Fshader').text; //получаем webgl context var canvas = document.getElementById('canvas'); var gl = canvas.getContext('webgl'); var vertexShader = gl.createShader(gl.VERTEX_SHADER); //создаем шейдеры var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(vertexShader, vertexShaderText); //передаем исходники gl.shaderSource(fragmentShader, fragmentShaderText); //компилируем. В случае неудачной компиляции выводим ошибку gl.compileShader(vertexShader); if(!gl.getShaderParameter(vertexShader,gl.COMPILE_STATUS)){ alert('ERROR COMPILING SHADER'); console.error('SHADER ERR: ',gl.getShaderInfoLog(vertexShader)); } gl.compileShader(fragmentShader); if(!gl.getShaderParameter(fragmentShader,gl.COMPILE_STATUS)){ alert('ERROR COMPILING SHADER'); console.error('SHADER ERR: ',gl.getShaderInfoLog(fragmentShader)); } var program = gl.createProgram(); //создаем программу gl.attachShader(program, vertexShader); //подключаем скомпилированные шейдеры gl.attachShader(program, fragmentShader); gl.linkProgram(program); //связываем var vertexBuffer = gl.createBuffer(); //создаем буфер вершин gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); //связываем var vertexArray = [ //массив вершин двух треугольников(из которых получена наша область работы) 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0 ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexArray), gl.STATIC_DRAW);//передаем данные нашего массива вершин в буфер вершин webgl //создаем атрибут, с помощью которого шейдер будет получать данные из буфера var positionAttribLocation = gl.getAttribLocation(program, 'vertexPosition'); gl.vertexAttribPointer( positionAttribLocation, // 2, // gl.FLOAT, // gl.FALSE, // 0, // 0 // ); gl.enableVertexAttribArray(positionAttribLocation); var timeLocation = gl.getUniformLocation(program, "u_time");//создаем униформ переменную времени function renderLoop(timeStamp) {//рекурсивная функция отрисовки var resolutionLocation = gl.getUniformLocation(program, "u_resolution"); //создаем униформ переменную разрешения gl.uniform2f(resolutionLocation, canvas.width, canvas.height); //передаем разрешение канваса в униформ переменную gl.uniform1f(timeLocation, timeStamp/1000.0); //передаем время в униформ переменную gl.drawArrays(gl.TRIANGLES, 0, 6); //отрисовываем window.requestAnimationFrame(renderLoop); //вызываем функцию для зацикливания } gl.useProgram(program); window.requestAnimationFrame(renderLoop); } startWebGL(); </script>