蝙蝠岛资源网 Design By www.hbtsch.com
前提条件和预期结果
目前只有少数的浏览器支持 WebGL ,请看我的另外一篇文章:Can I use WebGL?.
下面的例子是在 Windows 下的 Chrome 16/23 以及 Android 下的 Firefox 17 进行测试。如果你使用的是非兼容浏览器访问则会弹出一个警告。
图1:包含 Hello world 文本的动画的 WebGL 立方体
在兼容 HTML5 的浏览器上,你将会看到如下图所示的带动画效果的立方体:
图2: 示例运行的屏幕截图
该代码基于 Lighting in WebGL - How to simulate lighting effects in your WebGL context - 非常感谢这篇教程。在该实例初始运行时,动画的立方体是通过一个静态的 Bitmap 图形对象渲染的。
下面的代码演示如何在程序中动态的渲染文本:
XML/HTML Code复制内容到剪贴板- // TODO #1 New method to create a texture
- function createCubeTexture(text) {
- ...
- }
在这里使用 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); 是非常重要的,用来确保写文本时不会前后颠倒。剩下的就很容易理解了:
XML/HTML Code复制内容到剪贴板- // TODO #2 Assign the created texture for display
- cubeTexture = createCubeTexture("Hello World!");
源码
// File #1: webgl-demo.htm
XML/HTML Code复制内容到剪贴板- <html>
- <head>
- <title>WebGL - Hello World!</title>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <script src="sylvester.js" type="text/javascript"></script>
- <script src="glUtils.js" type="text/javascript"></script>
- <script src="webgl-demo.js" type="text/javascript"></script>
- <!-- Fragment shader program -->
- <script id="shader-fs" type="x-shader/x-fragment">
- varying highp vec2 vTextureCoord;
- varying highp vec3 vLighting;
- uniform sampler2D uSampler;
- void main(void) {
- highp vec4 texelColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
- gl_FragColor = vec4(texelColor.rgb * vLighting, texelColor.a);
- }
- </script>
- <!-- Vertex shader program -->
- <script id="shader-vs" type="x-shader/x-vertex">
- attribute highp vec3 aVertexNormal;
- attribute highp vec3 aVertexPosition;
- attribute highp vec2 aTextureCoord;
- uniform highp mat4 uNormalMatrix;
- uniform highp mat4 uMVMatrix;
- uniform highp mat4 uPMatrix;
- varying highp vec2 vTextureCoord;
- varying highp vec3 vLighting;
- void main(void) {
- gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
- vTextureCoord = aTextureCoord;
- // Apply lighting effect
- highp vec3 ambientLight = vec3(0.6, 0.6, 0.6);
- highp vec3 directionalLightColor = vec3(0.5, 0.5, 0.75);
- highp vec3 directionalVector = vec3(0.85, 0.8, 0.75);
- highp vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0);
- highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0);
- vLighting = ambientLight + (directionalLightColor * directional);
- }
- </script>
- </head>
- <body onload="start()">
- <canvas id="glcanvas" width="640" height="480">
- Your browser doesn't appear to support the HTML5 <code><canvas></code> element.
- </canvas>
- </body>
- </html>
// File #02: webgl-demo.js
- var canvas;
- var gl;
- var cubeVerticesBuffer;
- var cubeVerticesTextureCoordBuffer;
- var cubeVerticesIndexBuffer;
- var cubeVerticesIndexBuffer;
- var cubeRotation = 0.0;
- var lastCubeUpdateTime = 0;
- var cubeImage;
- var cubeTexture;
- var mvMatrix;
- var shaderProgram;
- var vertexPositionAttribute;
- var vertexNormalAttribute;
- var textureCoordAttribute;
- var perspectiveMatrix;
- //
- // start
- //
- // Called when the canvas is created to get the ball rolling.
- //
- function start() {
- canvas = document.getElementById("glcanvas");
- initWebGL(canvas); // Initialize the GL context
- // Only continue if WebGL is available and working
- if (gl) {
- gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaque
- gl.clearDepth(1.0); // Clear everything
- gl.enable(gl.DEPTH_TEST); // Enable depth testing
- gl.depthFunc(gl.LEQUAL); // Near things obscure far things
- // Initialize the shaders; this is where all the lighting for the
- // vertices and so forth is established.
- initShaders();
- // Here's where we call the routine that builds all the objects
- // we'll be drawing.
- initBuffers();
- // Next, load and set up the textures we'll be using.
- // TODO#2 Start
- cubeTexture = createCubeTexture("Hello World!");
- // TODO#2 End
- // Set up to draw the scene periodically.
- setInterval(drawScene, 15);
- }
- }
- //
- // initWebGL
- //
- // Initialize WebGL, returning the GL context or null if
- // WebGL isn't available or could not be initialized.
- //
- function initWebGL() {
- gl = null;
- try {
- gl = canvas.getContext("experimental-webgl");
- }
- catch(e) {
- }
- // If we don't have a GL context, give up now
- if (!gl) {
- alert("Unable to initialize WebGL. Your browser may not support it.");
- }
- }
- //
- // initBuffers
- //
- // Initialize the buffers we'll need. For this demo, we just have
- // one object -- a simple two-dimensional cube.
- //
- function initBuffers() {
- // Create a buffer for the cube's vertices.
- cubeVerticesBuffer = gl.createBuffer();
- // Select the cubeVerticesBuffer as the one to apply vertex
- // operations to from here out.
- gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesBuffer);
- // Now create an array of vertices for the cube.
- var vertices = [
- // Front face
- -1.0, -1.0, 1.0,
- 1.0, -1.0, 1.0,
- 1.0, 1.0, 1.0,
- -1.0, 1.0, 1.0,
- // Back face
- -1.0, -1.0, -1.0,
- -1.0, 1.0, -1.0,
- 1.0, 1.0, -1.0,
- 1.0, -1.0, -1.0,
- // Top face
- -1.0, 1.0, -1.0,
- -1.0, 1.0, 1.0,
- 1.0, 1.0, 1.0,
- 1.0, 1.0, -1.0,
- // Bottom face
- -1.0, -1.0, -1.0,
- 1.0, -1.0, -1.0,
- 1.0, -1.0, 1.0,
- -1.0, -1.0, 1.0,
- // Right face
- 1.0, -1.0, -1.0,
- 1.0, 1.0, -1.0,
- 1.0, 1.0, 1.0,
- 1.0, -1.0, 1.0,
- // Left face
- -1.0, -1.0, -1.0,
- -1.0, -1.0, 1.0,
- -1.0, 1.0, 1.0,
- -1.0, 1.0, -1.0
- ];
- // Now pass the list of vertices into WebGL to build the shape. We
- // do this by creating a Float32Array from the JavaScript array,
- // then use it to fill the current vertex buffer.
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
- // Set up the normals for the vertices, so that we can compute lighting.
- cubeVerticesNormalBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer);
- var vertexNormals = [
- // Front
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
- 0.0, 0.0, 1.0,
- // Back
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
- 0.0, 0.0, -1.0,
- // Top
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 1.0, 0.0,
- // Bottom
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
- 0.0, -1.0, 0.0,
- // Right
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0,
- // Left
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0,
- -1.0, 0.0, 0.0
- ];
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexNormals),
- gl.STATIC_DRAW);
- // Map the texture onto the cube's faces.
- cubeVerticesTextureCoordBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesTextureCoordBuffer);
- var textureCoordinates = [
- // Front
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Back
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Top
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Bottom
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Right
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0,
- // Left
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0
- ];
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates),
- gl.STATIC_DRAW);
- // Build the element array buffer; this specifies the indices
- // into the vertex array for each face's vertices.
- cubeVerticesIndexBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
- // This array defines each face as two triangles, using the
- // indices into the vertex array to specify each triangle's
- // position.
- var cubeVertexIndices = [
- 0, 1, 2, 0, 2, 3, // front
- 4, 5, 6, 4, 6, 7, // back
- 8, 9, 10, 8, 10, 11, // top
- 12, 13, 14, 12, 14, 15, // bottom
- 16, 17, 18, 16, 18, 19, // right
- 20, 21, 22, 20, 22, 23 // left
- ]
- // Now send the element array to GL
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
- new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
- }
- //
- // initTextures
- //
- // Initialize the textures we'll be using, then initiate a load of
- // the texture images. The handleTextureLoaded() callback will finish
- // the job; it gets called each time a texture finishes loading.
- //
- // TODO#1 Start
- function createCubeTexture(text) {
- // create a hidden canvas to draw the texture
- var canvas = document.createElement('canvas');
- canvas.id = "hiddenCanvas";
- canvas.width = 512;
- canvas.height = 512;
- canvas.style.display = "none";
- var body = document.getElementsByTagName("body")[0];
- body.appendChild(canvas);
- // draw texture
- var cubeImage = document.getElementById('hiddenCanvas');
- var ctx = cubeImage.getContext('2d');
- ctx.beginPath();
- ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.fillStyle = 'white';
- ctx.fill();
- ctx.fillStyle = 'black';
- ctx.font = "65px Arial";
- ctx.textAlign = 'center';
- ctx.fillText(text, ctx.canvas.width / 2, ctx.canvas.height / 2);
- ctx.restore();
- // create new texture
- var texture = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
- handleTextureLoaded(cubeImage, texture)
- return texture;
- }
- // TODO#1 End
- function handleTextureLoaded(image, texture) {
- gl.bindTexture(gl.TEXTURE_2D, texture);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
- gl.generateMipmap(gl.TEXTURE_2D);
- gl.bindTexture(gl.TEXTURE_2D, null);
- }
- //
- // drawScene
- //
- // Draw the scene.
- //
- function drawScene() {
- // Clear the canvas before we start drawing on it.
- gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
- // Establish the perspective with which we want to view the
- // scene. Our field of view is 45 degrees, with a width/height
- // ratio of 640:480, and we only want to see objects between 0.1 units
- // and 100 units away from the camera.
- perspectiveMatrix = makePerspective(45, 640.0/480.0, 0.1, 100.0);
- // Set the drawing position to the "identity" point, which is
- // the center of the scene.
- loadIdentity();
- // Now move the drawing position a bit to where we want to start
- // drawing the cube.
- mvTranslate([0.0, 0.0, -6.0]);
- // Save the current matrix, then rotate before we draw.
- mvPushMatrix();
- mvRotate(cubeRotation, [1, 0, 1]);
- // Draw the cube by binding the array buffer to the cube's vertices
- // array, setting attributes, and pushing it to GL.
- gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesBuffer);
- gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
- // Set the texture coordinates attribute for the vertices.
- gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesTextureCoordBuffer);
- gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
- // Bind the normals buffer to the shader attribute.
- gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer);
- gl.vertexAttribPointer(vertexNormalAttribute, 3, gl.FLOAT, false, 0, 0);
- // Specify the texture to map onto the faces.
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, cubeTexture);
- gl.uniform1i(gl.getUniformLocation(shaderProgram, "uSampler"), 0);
- // Draw the cube.
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
- setMatrixUniforms();
- gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
- // Restore the original matrix
- mvPopMatrix();
- // Update the rotation for the next draw, if it's time to do so.
- var currentTime = (new Date).getTime();
- if (lastCubeUpdateTime) {
- var delta = currentTime - lastCubeUpdateTime;
- cubeRotation += (30 * delta) / 1000.0;
- }
- lastCubeUpdateTime = currentTime;
- }
- //
- // initShaders
- //
- // Initialize the shaders, so WebGL knows how to light our scene.
- //
- function initShaders() {
- var fragmentShader = getShader(gl, "shader-fs");
- var vertexShader = getShader(gl, "shader-vs");
- // Create the shader program
- shaderProgram = gl.createProgram();
- gl.attachShader(shaderProgram, vertexShader);
- gl.attachShader(shaderProgram, fragmentShader);
- gl.linkProgram(shaderProgram);
- // If creating the shader program failed, alert
- if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
- alert("Unable to initialize the shader program.");
- }
- gl.useProgram(shaderProgram);
- vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
- gl.enableVertexAttribArray(vertexPositionAttribute);
- textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
- gl.enableVertexAttribArray(textureCoordAttribute);
- vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");
- gl.enableVertexAttribArray(vertexNormalAttribute);
- }
- //
- // getShader
- //
- // Loads a shader program by scouring the current document,
- // looking for a script with the specified ID.
- //
- function getShader(gl, id) {
- var shaderScript = document.getElementById(id);
- // Didn't find an element with the specified ID; abort.
- if (!shaderScript) {
- return null;
- }
- // Walk through the source element's children, building the
- // shader source string.
- var theSource = "";
- var currentChild = shaderScript.firstChild;
- while(currentChild) {
- if (currentChild.nodeType == 3) {
- theSource += currentChild.textContent;
- }
- currentChildcurrentChild = currentChild.nextSibling;
- }
- // Now figure out what type of shader script we have,
- // based on its MIME type.
- var shader;
- if (shaderScript.type == "x-shader/x-fragment") {
- shader = gl.createShader(gl.FRAGMENT_SHADER);
- } else if (shaderScript.type == "x-shader/x-vertex") {
- shader = gl.createShader(gl.VERTEX_SHADER);
- } else {
- return null; // Unknown shader type
- }
- // Send the source to the shader object
- gl.shaderSource(shader, theSource);
- // Compile the shader program
- gl.compileShader(shader);
- // See if it compiled successfully
- if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
- alert("An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader));
- return null;
- }
- return shader;
- }
- //
- // Matrix utility functions
- //
- function loadIdentity() {
- mvMatrix = Matrix.I(4);
- }
- function multMatrix(m) {
- mvMatrixmvMatrix = mvMatrix.x(m);
- }
- function mvTranslate(v) {
- multMatrix(Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4());
- }
- function setMatrixUniforms() {
- var pUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
- gl.uniformMatrix4fv(pUniform, false, new Float32Array(perspectiveMatrix.flatten()));
- var mvUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
- gl.uniformMatrix4fv(mvUniform, false, new Float32Array(mvMatrix.flatten()));
- var normalMatrix = mvMatrix.inverse();
- normalMatrixnormalMatrix = normalMatrix.transpose();
- var nUniform = gl.getUniformLocation(shaderProgram, "uNormalMatrix");
- gl.uniformMatrix4fv(nUniform, false, new Float32Array(normalMatrix.flatten()));
- }
- var mvMatrixStack = [];
- function mvPushMatrix(m) {
- if (m) {
- mvMatrixStack.push(m.dup());
- mmvMatrix = m.dup();
- } else {
- mvMatrixStack.push(mvMatrix.dup());
- }
- }
- function mvPopMatrix() {
- if (!mvMatrixStack.length) {
- throw("Can't pop from an empty matrix stack.");
- }
- mvMatrix = mvMatrixStack.pop();
- return mvMatrix;
- }
- function mvRotate(angle, v) {
- var inRadians = angle * Math.PI / 180.0;
- var m = Matrix.Rotation(inRadians, $V([v[0], v[1], v[2]])).ensure4x4();
- multMatrix(m);
- }
标签:
浏览器,WebGL
蝙蝠岛资源网 Design By www.hbtsch.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
蝙蝠岛资源网 Design By www.hbtsch.com
暂无在支持HTML5的浏览器上运行WebGL程序的方法的评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
2024年12月24日
2024年12月24日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]