'Add Texture to sphere

I need help figuring out how to add textures to my basketball.

What should i add to my vertex and fragment shaders.

Fragment shader

#ifdef GL_FRAGMENT_PRECISION_HIGH
       precision highp float;
    #else
       precision mediump float;
    #endif
    struct MaterialProperties {
        vec4 diffuseColor;      
        vec3 specularColor;
        vec3 emissiveColor;
        float specularExponent;
    };
    struct LightProperties {
        bool enabled;
        vec4 position;
        vec3 color;       
    };
    uniform MaterialProperties material; // do two-sided lighting, but assume front and back materials are the same
    uniform LightProperties lights[4];
    uniform mat3 normalMatrix;    
    varying vec3 v_normal;
    varying vec3 v_eyeCoords;
    
    vec3 lightingEquation( LightProperties light, MaterialProperties material, 
                                vec3 eyeCoords, vec3 N, vec3 V ) {
           // N is normal vector, V is direction to viewer.
        vec3 L, R; // Light direction and reflected light direction.      
        if ( light.position.w == 0.0 ) {
            L = normalize( light.position.xyz );
        }
        else {
            L = normalize( light.position.xyz/light.position.w - v_eyeCoords );            
        }
        if (dot(L,N) <= 0.0) {
            return vec3(0.0);
        }
        vec3 reflection = dot(L,N) * light.color * material.diffuseColor.rgb;
        R = -reflect(L,N);
        if (dot(R,V) > 0.0) {
            float factor = pow(dot(R,V),material.specularExponent);
            reflection += factor * material.specularColor * light.color;
        }
         return reflection;   
        
    }
    void main() {
        vec3 normal = normalize( normalMatrix*v_normal );
        vec3 viewDirection = normalize( -v_eyeCoords);  // (Assumes a perspective projection.)
        vec3 color = material.emissiveColor;
        
        for (int i = 0; i < 4; i++) {
            if (lights[i].enabled) { 
                if (gl_FrontFacing) {
                    color += lightingEquation( lights[i], material, v_eyeCoords,
                                                    normal, viewDirection);
                }
                else {
                    color += lightingEquation( lights[i], material, v_eyeCoords,
                                                    -normal, viewDirection);
                }
            }
        }               
       
        gl_FragColor = vec4(color,material.diffuseColor.a);        
    }

The function "world()" is being draw in my "Draw ()" function. The world consist of a scene, but for the sake of readability i will just like the ball i want to add texture to.

function world() {
    // Ground
        pushMatrix();
    mat4.translate(modelview,modelview,[-1,-3,0]);
        mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[9,9,0.5]);
    currentColor = [0.0,0.7,0.0,1];
    cube.render();
        popMatrix();

//Basketball
        pushMatrix();  
        mat4.translate(modelview,modelview,[xval,yval,3]);// 
        mat4.scale(modelview,modelview,[0.15,0.15,0.15]);
        currentColor = [1,0.3,0,1];
        sphere.render();
        popMatrix();
        
}

I have a createModel function that holds all my buffers.

I have a createProgram function that creates a program using the vertex and fragment shaders.

I have a initGL function that initializes the webgl context and gets attributes and uniform locations.

I have a init function that is called when the page is loaded.

Complete version of my code:


<!DOCTYPE html>
<meta charset="UTF-8">
<html>
<!--
   A demo of lighting and hierarchical modeling using WebGL.  
   
   Emissive color is used to make the lights seem to glow yellow when
   they are turned on.
   
   Derived from code available from Diskworld-2.html 
   
   The Shaders are still complex but have been simplified slightly.
   
      
-->
<head>
<title>Project 4 - Shooting basketball</title>
<style>
    body {
        background-color: #EEEEEE;
    }
    label {
        white-space: pre;
        margin-left: 25px;
    }
</style>

<!-- This shader is exactly as provided -->

<script type="x-shader/x-vertex" id="vshader-source">
    attribute vec3 a_coords;
    attribute vec3 a_normal;   
    uniform mat4 modelview;
    uniform mat4 projection;   
    varying vec3 v_normal;
    varying vec3 v_eyeCoords;  
    void main() {
        vec4 coords = vec4(a_coords,1.0);
        vec4 eyeCoords = modelview * coords;
        gl_Position = projection * eyeCoords;
        v_normal = normalize(a_normal);
        v_eyeCoords = eyeCoords.xyz/eyeCoords.w;         
    }
</script>

<!-- This shader has simplified lighting model and equation
Notice the light only has 3 properties now -->
<script type="x-shader/x-fragment" id="fshader-source">
    #ifdef GL_FRAGMENT_PRECISION_HIGH
       precision highp float;
    #else
       precision mediump float;
    #endif
    struct MaterialProperties {
        vec4 diffuseColor;      
        vec3 specularColor;
        vec3 emissiveColor;
        float specularExponent;
    };
    struct LightProperties {
        bool enabled;
        vec4 position;
        vec3 color;       
    };
    uniform MaterialProperties material; // do two-sided lighting, but assume front and back materials are the same
    uniform LightProperties lights[4];
    uniform mat3 normalMatrix;    
    varying vec3 v_normal;
    varying vec3 v_eyeCoords;
    
    vec3 lightingEquation( LightProperties light, MaterialProperties material, 
                                vec3 eyeCoords, vec3 N, vec3 V ) {
           // N is normal vector, V is direction to viewer.
        vec3 L, R; // Light direction and reflected light direction.      
        if ( light.position.w == 0.0 ) {
            L = normalize( light.position.xyz );
        }
        else {
            L = normalize( light.position.xyz/light.position.w - v_eyeCoords );            
        }
        if (dot(L,N) <= 0.0) {
            return vec3(0.0);
        }
        vec3 reflection = dot(L,N) * light.color * material.diffuseColor.rgb;
        R = -reflect(L,N);
        if (dot(R,V) > 0.0) {
            float factor = pow(dot(R,V),material.specularExponent);
            reflection += factor * material.specularColor * light.color;
        }
         return reflection;   
        
    }
    void main() {
        vec3 normal = normalize( normalMatrix*v_normal );
        vec3 viewDirection = normalize( -v_eyeCoords);  // (Assumes a perspective projection.)
        vec3 color = material.emissiveColor;
        
        for (int i = 0; i < 4; i++) {
            if (lights[i].enabled) { 
                if (gl_FrontFacing) {
                    color += lightingEquation( lights[i], material, v_eyeCoords,
                                                    normal, viewDirection);
                }
                else {
                    color += lightingEquation( lights[i], material, v_eyeCoords,
                                                    -normal, viewDirection);
                }
            }
        }               
       
        gl_FragColor = vec4(color,material.diffuseColor.a);        
    }
</script>


<script src="gl-matrix-min.js"></script>
<script src="trackball-rotator.js"></script>
<script src="basic-object-models-IFS.js"></script>
<script>

"use strict";


var gl;   // The webgl context.


var xval= 1.3;
var yval= -1.8;
var kval = 0; // Kick leg start

var a_coords_loc;         // Location of the a_coords attribute variable in the shader program.
var a_normal_loc;         // Location of a_normal attribute 
var a_texCoords_loc; 
// var texture;

var u_modelview;       // Locations for uniform matrices
var u_projection;
var u_normalMatrix;

var u_material;     // An object tolds uniform locations for the material.
var u_lights;       // An array of objects that holds uniform locations for light properties.

var projection = mat4.create();    // projection matrix
var modelview;                     // modelview matrix; value comes from rotator
var normalMatrix = mat3.create();  // matrix, derived from modelview matrix, for transforming normal vectors

var rotator;  // A TrackballRotator to implement rotation by mouse.

var frameNumber = 0;  // frame number during animation (actually only goes up by 0.5 per frame)

var torus, sphere, cone, cylinder, disk, ring, cube;  // basic objects, created using function createModel

var matrixStack = [];           // A stack of matrices for implementing hierarchical graphics.

var currentColor = [1,1,1,1];   // The current diffuseColor; render() functions in the basic objects set
                                // the diffuse color to currentColor when it is called before drawing the object.
                                // Other color properties, which don't change often are handled elsewhere.

var textureURLs = [
        "textures/basketball.jpg" // array to hold textures
        
];

/**
 * Draws the image, which consists of either the "world" or a closeup of the "car".
 */
function draw() {
    gl.clearColor(0,0,0,1);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    
    
    
    mat4.perspective(projection, Math.PI/4, 1, 1, 50);
    gl.uniformMatrix4fv(u_projection, false, projection );

    modelview = rotator.getViewMatrix();
    
    lights();
    
    world();
    
    
}

function setLightPosition( u_position_loc, modelview, lightPosition ) {
    var transformedPosition = new Float32Array(4);
    vec4.transformMat4(transformedPosition, lightPosition, modelview);
    gl.uniform4fv(u_position_loc, transformedPosition);
}

function lights() {   
     
  
    
    gl.uniform1i( u_lights[0].enabled, 1 );   
    gl.uniform4f( u_lights[0].position, 0,0,1,0 ); 
    gl.uniform3f( u_lights[0].color, 0.15,0.15,0.15 );  
    
    // Sun light 
    gl.uniform1i( u_lights[1].enabled, 1 );  
    gl.uniform3f( u_lights[1].color, 1,0.3,0.0 );  
    
    //Lamp at night
    gl.uniform1i( u_lights[2].enabled, 1 );  
    gl.uniform3f( u_lights[2].color, 0.35, 0.35, 0.1 ); // light 1 is the lamp at night
    gl.uniform1f( u_lights[2].attenuation, 2 ); 
    
    gl.uniform1i( u_lights[3].enabled, 1 );  
    gl.uniform3f( u_lights[3].color, 0.35, 0.35, 0.1 ); // light 1 is the lamp at night
    gl.uniform1f( u_lights[3].attenuation, 2 ); 
     
    
    
    currentColor = [ 0.3, 0.3, 0.3, 1 ];
   
    //SunSetlight
    pushMatrix();  
    mat4.translate(modelview,modelview,[7,-3,-10]);// 
    mat4.scale(modelview,modelview,[0.8,0.8,0.8]);
    setLightPosition(u_lights[1].position, modelview, [1,0,0,0]);
    gl.uniform3f( u_material.emissiveColor, 1.5,0.4, 0 );
    sphere.render();
    gl.uniform3f( u_material.emissiveColor, 0, 0, 0 );
    popMatrix();  
    
    // lamp for night
    pushMatrix();  
    mat4.translate(modelview,modelview,[-1,-0.8,3]);
    mat4.scale(modelview,modelview,[0.4,0.1,0.1]);
    setLightPosition(u_lights[2].position, modelview, [0,0,0,1]);
    gl.uniform3f( u_material.emissiveColor, 1, 1, 0 );
    cube.render();
    gl.uniform3f( u_material.emissiveColor, 0, 0, 0 );
    popMatrix();
    
    pushMatrix();  
    mat4.translate(modelview,modelview,[-1,-0.8,-3]);
    mat4.scale(modelview,modelview,[0.4,0.1,0.1]);
    setLightPosition(u_lights[3].position, modelview, [0,0,0,1]);
    gl.uniform3f( u_material.emissiveColor, 1, 1, 0 );
    cube.render();
    gl.uniform3f( u_material.emissiveColor, 0, 0, 0 );
    popMatrix();
  
   
}

/**
 * Draws a boxman figure using transformation from cubes and cylinders.
 * Note for every push their should be a pop. This resets the transformations
 */
function world() {
    // Ground
        pushMatrix();
    mat4.translate(modelview,modelview,[-1,-3,0]);
        mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[9,9,0.5]);
    currentColor = [0.0,0.7,0.0,1];
    cube.render();
        popMatrix();
        
        
        // Street lamp
        pushMatrix();
        mat4.translate(modelview,modelview,[-0.8,-4.7,3]);
        mat4.scale(modelview,modelview,[0.5,0.5,0.5]);
        streetLight();
        popMatrix();
        
         // Street lamp
        pushMatrix();
        mat4.translate(modelview,modelview,[-0.8,-4.7,-3]);
        mat4.scale(modelview,modelview,[0.5,0.5,0.5]);
        streetLight();
        popMatrix();
        
        // Basketball court
        pushMatrix();
    mat4.translate(modelview,modelview,[2,-2.75,3]);
        mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[3,3,0.1]);
    currentColor = [0.2,0.2,0.2,1];
    cube.render();
        popMatrix();
        
        //Road
        pushMatrix();
    mat4.translate(modelview,modelview,[-2,-2.75,0]);
        mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[2,9,0.1]);
    currentColor = [0.2,0.2,0.2,1];
    cube.render();
        popMatrix();
        
         //Road
        pushMatrix();
    mat4.translate(modelview,modelview,[-2,-2.72,0]);
        mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[0.2,9,0.1]);
    currentColor = [1,1,1,1];
    cube.render();
        popMatrix();
       
        //Basketball
        pushMatrix();  
        mat4.translate(modelview,modelview,[xval,yval,3]);// 
        mat4.scale(modelview,modelview,[0.15,0.15,0.15]);
        currentColor = [1,0.3,0,1];
        sphere.render();
        popMatrix();
        
             // BasketBall Player
             // Player 1
        pushMatrix();
        mat4.translate(modelview,modelview,[1,-2.2,3]);
    mat4.scale(modelview,modelview,[0.15,0.15,0.15]);
        mat4.rotate(modelview,modelview,(90)/180*Math.PI,[0,1,0]);
        // Arms
    pushMatrix();
    mat4.translate(modelview,modelview,[0,-0.5,-2]);
    mat4.rotate(modelview,modelview,(-45)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[0.5,0.5,3]);
    currentColor = [0.7,0.4,0.1,1];
    cylinder.render();
    popMatrix();    
    
    pushMatrix();
    mat4.translate(modelview,modelview,[-2,-0.5,-2]);
    mat4.rotate(modelview,modelview,(-45)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[0.5,0.5,3]);
    currentColor = [0.7,0.4,0.1,1];
    cylinder.render();
    popMatrix();    
        player();
        popMatrix();
        
        // PLayer 2
         pushMatrix();
        pushMatrix();
        mat4.translate(modelview,modelview,[2.4,-2.2,3.2]);
    mat4.scale(modelview,modelview,[0.2,0.2,0.2]);
        mat4.rotate(modelview,modelview,(-90)/180*Math.PI,[0,1,0]);
        // Arms
    pushMatrix();
    mat4.translate(modelview,modelview,[0,1.2,-3]);
    mat4.rotate(modelview,modelview,(kval)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[0.5,0.5,3]);
    currentColor = [0.7,0.4,0.1,1];
    cylinder.render();
    popMatrix();    
    
    pushMatrix();
    mat4.translate(modelview,modelview,[-2,1.2,-3]);
    mat4.rotate(modelview,modelview,(kval)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[0.5,0.5,3]);
    currentColor = [0.7,0.4,0.1,1];
    cylinder.render();
    popMatrix();    
        player();
        popMatrix();
        
        //baskethoop
        pushMatrix();
        mat4.translate(modelview,modelview,[3,-4.3,3]);
    mat4.scale(modelview,modelview,[0.5,0.5,0.5]);
        basketballhoop();
        popMatrix();
        
      
        
        //Houses 
        pushMatrix();
    mat4.translate(modelview,modelview,[-4,-2,2]);
    mat4.scale(modelview,modelview,[0.6,0.6,0.6]);
    house();
    popMatrix();
        
        pushMatrix();
    mat4.translate(modelview,modelview,[-4,-2,-2.3]);
    mat4.scale(modelview,modelview,[0.6,0.6,0.6]);
    house();
    popMatrix(); 
             
}

function streetLight(){
    pushMatrix();
    mat4.translate(modelview,modelview,[0,0,0]);
    mat4.rotate(modelview,modelview,(90)/180*Math.PI,[-1,0,0]);
    mat4.scale(modelview,modelview,[0.2,0.2,4]);
    cylinder.render();
    popMatrix();
}


function house(){
    pushMatrix();
    currentColor = [0.5,0.4,0.2,1];
    mat4.scale(modelview,modelview,[2,2,2]);
    cube.render();
    popMatrix();
    pushMatrix();
    currentColor = [0.5,0.4,0.2,1];
    mat4.translate(modelview,modelview,[0,-0.5,1.6]);
    mat4.scale(modelview,modelview,[1.3,1.3,1.3]);
    cube.render();
    popMatrix();
    
    
    pushMatrix();
    currentColor = [0.2,0.2,0.2,1];
    mat4.translate(modelview,modelview,[0,1,0.0]);
    mat4.scale(modelview,modelview,[4,1.5,4]);
    mat4.rotate(modelview,modelview,(90)/180*Math.PI,[-1,0,0]);
    cone.render();
    popMatrix();
}

function basketballhoop(){
    pushMatrix();
    currentColor = [0.1,0.1,0.1,1];
    mat4.translate(modelview,modelview,[0,0,0]);
    mat4.scale(modelview,modelview,[0.2,3,0.2]);
    mat4.rotate(modelview,modelview,(90)/180*Math.PI,[-1,0,0]);
    cylinder.render();
    popMatrix();
    
    pushMatrix();
    currentColor = [0.5,0.5,0.5,1];
    mat4.scale(modelview,modelview,[0.15,0.15,0.15]);
    mat4.rotate(modelview,modelview,(90)/180*Math.PI,[-1,0,0]);
    mat4.translate(modelview,modelview,[-4.5,0,43]);
    ring.render();
    popMatrix();
    
    pushMatrix();
    currentColor = [0,0,0.5,1];
    mat4.scale(modelview,modelview,[0.1,1.5,2]);
    mat4.translate(modelview,modelview,[0,4.4,0]);
    cube.render();
    popMatrix();
}

function player(){
    
    pushMatrix();
        //Head
    mat4.translate(modelview,modelview,[-1,3,0]);
    mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
        mat4.scale(modelview,modelview,[0.5,0.4,0.8]);
    currentColor = [0.7,0.4,0.1,1];
    sphere.render();
    popMatrix();
    // Neck
    pushMatrix();
    mat4.translate(modelview,modelview,[-1,2.5,0]);
    mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[0.3,0.4,0.3]);
    currentColor = [0.7,0.4,0.1,1];
    cylinder.render();
    popMatrix();
    // Body
    pushMatrix();
    mat4.translate(modelview,modelview,[-1,1.0,0]);
    mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[1.3,1,2]);
    currentColor = [0.0,0.0,0.9,1];
    cube.render();
    popMatrix();    
    // Legs
    pushMatrix();
    mat4.translate(modelview,modelview,[-1.3,3.1,0]);
    mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[0.6,0.6,3.0]);
    currentColor = [0.0,0.0,1,1];
    cylinder.render();
    popMatrix();
        
        pushMatrix();
    mat4.translate(modelview,modelview,[-0.7,3.1,0]);
    mat4.rotate(modelview,modelview,(90)/180*Math.PI,[1,0,0]);
    mat4.scale(modelview,modelview,[0.6,0.6,3.0]);
    currentColor = [0.0,0.0,1,1];
    cylinder.render();
    popMatrix();
      
    
}







/**
 *  Push a copy of the current modelview matrix onto the matrix stack.
 */
function pushMatrix() {
    matrixStack.push( mat4.clone(modelview) );
}


/**
 *  Restore the modelview matrix to a value popped from the matrix stack.
 */
function popMatrix() {
    modelview = matrixStack.pop();
}

<!-- As is no changes -->
/**
 *  Create one of the basic objects.  The modelData holds the data for
 *  an IFS using the structure from basic-objects-IFS.js.  This function
 *  creates VBOs to hold the coordinates, normal vectors, and indices
 *  from the IFS, and it loads the data into those buffers.  The function
 *  creates a new object whose properties are the identifies of the
 *  VBOs.  The new object also has a function, render(), that can be called to
 *  render the object, using all the data from the buffers.  That object
 *  is returned as the value of the function.  (The second parameter,
 *  xtraTranslate, is there because this program was ported from a Java
 *  version where cylinders were created in a different position, with
 *  the base on the xy-plane instead of with their center at the origin.
 *  The xtraTranslate parameter is a 3-vector that is applied as a
 *  translation to the rendered object.  It is used to move the cylinders
 *  into the position expected by the code that was ported from Java.)
 */
function createModel(modelData, xtraTranslate) {
    var model = {};
    model.coordsBuffer = gl.createBuffer();
    model.normalBuffer = gl.createBuffer();
    model.indexBuffer = gl.createBuffer();
    model.count = modelData.indices.length;
    if (xtraTranslate)
        model.xtraTranslate = xtraTranslate;
    else
        model.xtraTranslate = null;
    gl.bindBuffer(gl.ARRAY_BUFFER, model.coordsBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, modelData.vertexPositions, gl.STATIC_DRAW);
    gl.bindBuffer(gl.ARRAY_BUFFER, model.normalBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, modelData.vertexNormals, gl.STATIC_DRAW);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, modelData.indices, gl.STATIC_DRAW);
    model.render = function() {  // This function will render the object.
           // Since the buffer from which we are taking the coordinates and normals
           // change each time an object is drawn, we have to use gl.vertexAttribPointer
           // to specify the location of the data. And to do that, we must first
           // bind the buffer that contains the data.  Similarly, we have to
           // bind this object's index buffer before calling gl.drawElements.
        gl.bindBuffer(gl.ARRAY_BUFFER, this.coordsBuffer);
        gl.vertexAttribPointer(a_coords_loc, 3, gl.FLOAT, false, 0, 0);
        gl.bindBuffer(gl.ARRAY_BUFFER, this.normalBuffer);
        gl.vertexAttribPointer(a_normal_loc, 3, gl.FLOAT, false, 0, 0);
        gl.uniform4fv(u_material.diffuseColor, currentColor);
        if (this.xtraTranslate) {
            pushMatrix();
            mat4.translate(modelview,modelview,this.xtraTranslate);
        }
        gl.uniformMatrix4fv(u_modelview, false, modelview );
        mat3.normalFromMat4(normalMatrix, modelview);
        gl.uniformMatrix3fv(u_normalMatrix, false, normalMatrix);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
        gl.drawElements(gl.TRIANGLES, this.count, gl.UNSIGNED_SHORT, 0);
        if (this.xtraTranslate) {
            popMatrix();
        }
    }
    return model;
}


/* Creates a program for use in the WebGL context gl, and returns the
 * identifier for that program.  If an error occurs while compiling or
 * linking the program, an exception of type String is thrown.  The error
 * string contains the compilation or linking error.  If no error occurs,
 * the program identifier is the return value of the function.
 *    The second and third parameters are the id attributes for <script>
 * elementst that contain the source code for the vertex and fragment
 * shaders.
 */
function createProgram(gl, vertexShaderID, fragmentShaderID) {
    function getTextContent( elementID ) {
            // This nested function retrieves the text content of an
            // element on the web page.  It is used here to get the shader
            // source code from the script elements that contain it.
        var element = document.getElementById(elementID);
        var node = element.firstChild;
        var str = "";
        while (node) {
            if (node.nodeType == 3) // this is a text node
                str += node.textContent;
            node = node.nextSibling;
        }
        return str;
    }
    try {
        var vertexShaderSource = getTextContent( vertexShaderID );
        var fragmentShaderSource = getTextContent( fragmentShaderID );
    }
    catch (e) {
        throw "Error: Could not get shader source code from script elements.";
    }
    var vsh = gl.createShader( gl.VERTEX_SHADER );
    gl.shaderSource(vsh,vertexShaderSource);
    gl.compileShader(vsh);
    if ( ! gl.getShaderParameter(vsh, gl.COMPILE_STATUS) ) {
        throw "Error in vertex shader:  " + gl.getShaderInfoLog(vsh);
     }
    var fsh = gl.createShader( gl.FRAGMENT_SHADER );
    gl.shaderSource(fsh, fragmentShaderSource);
    gl.compileShader(fsh);
    if ( ! gl.getShaderParameter(fsh, gl.COMPILE_STATUS) ) {
       throw "Error in fragment shader:  " + gl.getShaderInfoLog(fsh);
    }
    var prog = gl.createProgram();
    gl.attachShader(prog,vsh);
    gl.attachShader(prog, fsh);
    gl.linkProgram(prog);
    if ( ! gl.getProgramParameter( prog, gl.LINK_STATUS) ) {
       throw "Link error in program:  " + gl.getProgramInfoLog(prog);
    }
    return prog;
}


/* Initialize the WebGL context.  Called from init() */
function initGL() {
    var prog = createProgram(gl,"vshader-source","fshader-source");
    gl.useProgram(prog);
    gl.enable(gl.DEPTH_TEST);
    
    /* Get attribute and uniform locations */
    
    a_coords_loc =  gl.getAttribLocation(prog, "a_coords");
    a_normal_loc =  gl.getAttribLocation(prog, "a_normal");
    gl.enableVertexAttribArray(a_coords_loc);
    gl.enableVertexAttribArray(a_normal_loc);
    
    u_modelview = gl.getUniformLocation(prog, "modelview");
    u_projection = gl.getUniformLocation(prog, "projection");
    u_normalMatrix =  gl.getUniformLocation(prog, "normalMatrix");
    u_material = {
        diffuseColor: gl.getUniformLocation(prog, "material.diffuseColor"),
        specularColor: gl.getUniformLocation(prog, "material.specularColor"),
        emissiveColor: gl.getUniformLocation(prog, "material.emissiveColor"),
        specularExponent: gl.getUniformLocation(prog, "material.specularExponent")
    };
    u_lights = new Array(4);
    for (var i = 0; i < 4; i++) {
        u_lights[i] = {
            enabled: gl.getUniformLocation(prog, "lights[" + i + "].enabled"),
            position: gl.getUniformLocation(prog, "lights[" + i + "].position"),
            color: gl.getUniformLocation(prog, "lights[" + i + "].color")            
        };
    }
            
    gl.uniform3f( u_material.specularColor, 0.1, 0.1, 0.1 );  // specular properties don't change
    gl.uniform1f( u_material.specularExponent, 16 );
    gl.uniform3f( u_material.emissiveColor, 0, 0, 0);  // default, will be changed temporarily for some objects
    

    for (var i = 1; i < 4; i++) { // set defaults for lights
        gl.uniform1i( u_lights[i].enabled, 0 ); 
        gl.uniform4f( u_lights[i].position, 0, 0, 1, 0 );        
        gl.uniform3f( u_lights[i].color, 1,1,1 ); 
    }
    
  // Lights are set on in the draw() method
    
  
    
} // end initGL()



//--------------------------------- animation framework ------------------------------

    
var animating = false;

/*
This is where you control the animation by changing positions,
and rotations values as needed.
Trial and error works on the numbers. Graph paper design is more efficient. 
*/

function frame() {
    if (animating) {
        frameNumber += 1;
        // Positions of the soccer ball       
        xval += 0.05;
        yval += 0.05;
        // Rotation of kick leg
        // Not perfect by anymeans but Okay for at least one viewing angle.
        kval -= 1.5;
        if (xval > 8.5 || yval < -8.5) {
           xval= 1.3;
           yval= -1.8;
           kval = 0;
        }  
        if (kval < -90) {
            kval = -90; // Don't overextend the soccer all
        }
        draw();
        requestAnimationFrame(frame);
    }
}

function setAnimating(run) {
    if (run != animating) {
        animating = run;
        if (animating)
            requestAnimationFrame(frame);
    }
}

//-------------------------------------------------------------------------


/**
 * initialization function that will be called when the page has loaded
 */
function init() {
    try {
        var canvas = document.getElementById("webglcanvas");
        gl = canvas.getContext("webgl") || 
                         canvas.getContext("experimental-webgl");
        if ( ! gl ) {
            throw "Browser does not support WebGL";
        }
    }
    catch (e) {
        document.getElementById("message").innerHTML =
            "<p>Sorry, could not get a WebGL graphics context.</p>";
        return;
    }
    try {
        initGL();  // initialize the WebGL graphics context
    }
    catch (e) {
        document.getElementById("message").innerHTML =
            "<p>Sorry, could not initialize the WebGL graphics context:" + e + "</p>";
        return;
    }
    document.getElementById("animCheck").checked = false;
    document.getElementById("reset").onclick = function() {
       rotator.setView(17,[0,1,2]);
       frameNumber = 0;
       // Initialize soccer ball positions      
       xval = 1.5; 
       yval = -1.5;      
       animating = false;
       document.getElementById("animCheck").checked = false;
       draw();
    }
    
    // Not really using all of these
    // As you create your scene use these or create from primitives
    torus = createModel(uvTorus(0.5,1,16,8));   // Create all the basic objects.
    sphere = createModel(uvSphere(1));
    cone = createModel(uvCone(),[0,0,.5]);
    cylinder = createModel(uvCylinder(),[0,0,1.5]);
    disk = createModel(uvCylinder(5.5,0.5,64),[0,0,.25]);
    ring = createModel(ring(3.3,4.8,40));
    cube = createModel(cube());
 
 // This controls the zoom and initial placement
    rotator = new TrackballRotator(canvas,function() {
        if (!animating)
           draw();
    },17,[0,1,2]); 
    draw();
}

</script>
</head>






Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source