<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>HTML5 WebGL实现高温热变形动画特效</title>
<style>
body {
margin: 0;
}
img {
display: none
}
</style>
</head>
<body>
<img src="images/s1.jpg" id="scene">
<div id="containerView">
<canvas id="webglView" style="width:680px;height:500px"></canvas>
</div>
<!-- shader programs -->
<script id="vsh" type="x-shader/x-vertex">
precision mediump float;attribute vec4 position;attribute vec4 inputTextureCoordinate;
varying vec2 textureCoordinate;void main(){gl_Position = position;textureCoordinate = vec2((position.x+1.0)/2.0, 1.0-(position.y+1.0)/2.0);}
</script>
<script id="fsh_wave" type="x-shader/x-fragment">
precision mediump float;
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform float time;
void main(){
float frequency=100.0;
float amp=0.003;
float speed=0.05;
float distortion=sin(textureCoordinate.y*frequency + time*speed)*amp;
vec4 color=texture2D(inputImageTexture,vec2(textureCoordinate.x+distortion, textureCoordinate.y));
gl_FragColor = color;
}
</script>
<script src="js/requestAnimationFrame.js"></script>
<script>
var webgl = null;
var vertexShaderObject = null;
var fragmentShaderObject = null;
var programObject = null;
var v4PositionIndex = null;
var itv = {};
var time = 0.0;
function initWebGL() {
var myCanvasObject = document.getElementById("webglView");
var myDivObject = document.getElementById("containerView");
webgl = myCanvasObject.getContext("experimental-webgl");
if (webgl == null)
alert("Your browser doesn't support webgl!");
myCanvasObject.width = myDivObject.clientWidth;
myCanvasObject.height = myDivObject.clientHeight;
webgl.viewport(0, 0, myDivObject.clientWidth, myDivObject.clientHeight);
}
function initShaders(vsh, fsh) {
vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);
fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);
webgl.shaderSource(vertexShaderObject, vsh);
webgl.shaderSource(fragmentShaderObject, fsh);
webgl.compileShader(vertexShaderObject);
webgl.compileShader(fragmentShaderObject);
if (!webgl.getShaderParameter(vertexShaderObject, webgl.COMPILE_STATUS)) {
alert(webgl.getShaderInfoLog(vertexShaderObject) + "in vertex shader");
return;
}
if (!webgl.getShaderParameter(fragmentShaderObject, webgl.COMPILE_STATUS)) {
alert(webgl.getShaderInfoLog(fragmentShaderObject) + "in fragment shader");
return;
}
}
function initShaderProgram(positionName) {
programObject = webgl.createProgram();
webgl.attachShader(programObject, vertexShaderObject);
webgl.attachShader(programObject, fragmentShaderObject);
webgl.bindAttribLocation(programObject, v4PositionIndex, positionName);
webgl.linkProgram(programObject);
if (!webgl.getProgramParameter(programObject, webgl.LINK_STATUS)) {
alert(webgl.getProgramInfoLog(programObject));
return;
}
webgl.useProgram(programObject);
}
function renderWebGL(vertices, vSize, vLen, vsh, fsh, positionName) {
initWebGL();
initShaders(vsh, fsh);
initShaderProgram(positionName);
var buffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER, buffer);
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(vertices), webgl.STATIC_DRAW);
webgl.enableVertexAttribArray(v4PositionIndex);
webgl.vertexAttribPointer(v4PositionIndex, vSize, webgl.FLOAT, false, 0, 0);
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);
webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, vLen);
}
function getScriptTextByID(scriptID) {
var shaderScript = document.getElementById(scriptID);
if (shaderScript == null) return "";
if (shaderScript.textContent != null && shaderScript.textContent != "") {
return shaderScript.textContent;
}
if (shaderScript.text != null && shaderScript.text != "") {
return shaderScript.text;
}
var sourceCode = "";
var child = shaderScript.firstChild;
while (child) {
if (child.nodeType == child.TEXT_NODE) sourceCode += child.textContent;
child = child.nextSibling;
}
return sourceCode;
}
function createTextureByImgObject(imgObj) {
//设置当前激活纹理
webgl.activeTexture(webgl.TEXTURE0);
//创建纹理对象,并设置其属性
var textureObject = webgl.createTexture();
webgl.bindTexture(webgl.TEXTURE_2D, textureObject);
webgl.texImage2D(webgl.TEXTURE_2D, 0, webgl.RGBA, webgl.RGBA, webgl.UNSIGNED_BYTE, imgObj);
webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MIN_FILTER, webgl.NEAREST);
webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_MAG_FILTER, webgl.NEAREST);
webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_S, webgl.CLAMP_TO_EDGE);
webgl.texParameteri(webgl.TEXTURE_2D, webgl.TEXTURE_WRAP_T, webgl.CLAMP_TO_EDGE);
return textureObject;
}
//通过img标签的id创建一个纹理
function createTextureByImgID(imgID) {
var imgObj = document.getElementById(imgID);
if (imgObj == null) {
return null;
}
return createTextureByImgObject(imgObj);
}
var vertices = [
1.0, 1.0,
1.0, -1.0, -1.0, 1.0, -1.0, -1.0
];
function draw() {
webgl.uniform1f(itv.time, time++);
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);
webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4);
requestAnimationFrame(draw);
}
function main() {
var vsh = getScriptTextByID("vsh");
var fsh = getScriptTextByID("fsh_wave");
initWebGL();
initShaders(vsh, fsh);
initShaderProgram("position");
var buffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER, buffer);
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(vertices), webgl.STATIC_DRAW);
webgl.enableVertexAttribArray(v4PositionIndex);
webgl.vertexAttribPointer(v4PositionIndex, 2, webgl.FLOAT, false, 0, 0);
var texObj = createTextureByImgID("scene");
webgl.activeTexture(webgl.TEXTURE0);
var uniform = webgl.getUniformLocation(programObject, "inputImageTexture");
webgl.uniform1i(uniform, 0);
itv.time = webgl.getUniformLocation(programObject, "time");
draw();
}
window.addEventListener('load', main);
</script>
</body>
</html>