Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to run WebGL programs on HTML5 browsers

2025-04-12 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article focuses on "how to run WebGL programs on HTML5 browsers". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to run WebGL programs on HTML5 browsers.

Preconditions and expected results

At present, only a few browsers support WebGL, please see my other article: Can I use WebGL?.

The following example is tested on Chrome 16 under Windows and Firefox 17 under Android. If you are using an incompatible browser, a warning will pop up.

Figure 1: animated WebGL cube containing Hello world text

On HTML5-compatible browsers, you will see the drawing cube shown in the following figure:

Figure 2: screenshot of the sample run

This code is based on Lighting in WebGL-How to simulate lighting effects in your WebGL context-Thank you very much for this tutorial. When the instance is initially run, the cube of the animation is rendered through a static Bitmap graphics object.

The following code demonstrates how to render text dynamically in a program:

XML/HTML Code copies content to the clipboard

/ / TODO # 1 New method to create a texture

Function createCubeTexture (text) {

...

}

The use of gl.pixelStorei (gl.UNPACK_FLIP_Y_WEBGL, true) here is very important to ensure that the text is not written backwards. The rest is easy to understand:

XML/HTML Code copies content to the clipboard

/ / TODO # 2 Assign the created texture for display

CubeTexture = createCubeTexture ("Hello World!")

Source code

/ / File # 1: webgl-demo.htm

XML/HTML Code copies content to the clipboard

WebGL-Hello World!

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)

}

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)

}

Your browser doesn't appear to support the HTML5 element.

/ / File # 02: webgl-demo.js

XML/HTML Code copies content to the clipboard

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.

/ / 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.

/ / Right face

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 (45640.0max 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 ($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)

}

At this point, I believe you have a deeper understanding of "how to run WebGL programs on HTML5 browsers". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 210

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report