!

Dette materialet blir ikke lenger vedlikeholdt. Du vil finne oppdatert materiale på siden: http://borres.hiof.no/wep/

WebGL
Børre Stenseth
? Browser Support ?
WebGL > Android figuren >Forbedret

Android

Hva
Android figuren forbedret med øyne og materialer

I modulen Android figuren laget vi en enkel variant med vekt på basisgeometrien. Her skikker vi litt mer på detaljene.

Det kan være lurt å kikke på OpenGL Shading Language (GLSL) Reference Pages [1] for å få en forklaring av de enkelte metodene i shading-eksemplene og OpenGL ES 2.0 Reference Pages [2] for å få en forklaring av de enkelte metodene i javascriptet.

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

Du kan også inspisere resultatet og kildekoden på en enklere side:
index-mat.html http://www.it.hiof.no/~borres/dw/wgl/android/index-mat.html

Eller du kan se på en lett modifiswert versjon, med lyd:
godjul.html http://www.it.hiof.no/~borres/dw/wgl/doors/index.html

Geometri

Vi har lagt til øyne (halvkuler) og følehorn (sylindere)

Javascript

Javascriptet som handterer vår tegning er inkludert som egen fil. De viktigste delene av denne koden er kommentert funksjon for funksjon nedenfor. Hele fila ser slik ut: androidscript-mat.js

Det kan være lurt å kikke på OpenGL ES 2.0 Reference Pages [2] for å få en forklaring av de enkelte metodene.

Følgende globale variable er definert.

var canvas;
var gl;
var mvMatrix;
var perspectiveMatrix;
var shaderProgram;
// sizes
var bodyLength=3.0;
var bodyRadius=1.5;
var limbLength=1.7;
var limbRadius=0.4;
var hornRadius=0.1;
var hornLength=0.6;
// drawing precision
var Precision=30;
//shapes
var aCylinder;
var aDisk;
var aHat; //half sphere
// animation
var sceneRotation = 0.0;
var lastUpdateTime = 0;
var armswing=0.0;
var deltaArmswing=1.5;
var maxArmswing=50.0;
var talkSwing=0.0;
var talkCount=0;
var deltaTalkCount=1;

I funksjonen initBuffers() setter vi opp de punktene som beskriver modellen vår og som etterhvert skal sendes til vertex-shaderen.

function initBuffers() {
    // set up all shapes
    aCylinder=new Cylinder(1.0,1.0,Precision);
    aDisk=new Disk(1.0,Precision);
    aHat=new Hat(1.0,Precision);
}

Funksjonen drawScene() er lite endret

function drawScene() {
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);  
    perspectiveMatrix = makePerspective(45, canvas.width / canvas.height, 0.1, 100.0);
    loadIdentity();
    
    setLight();
    setGreenMaterial();
    // Move the drawing a bit from default eye-pos (0,0,0)
    mvTranslate([-0.0, 0.0, -16.0]);
    // overall rotation
    mvRotate(sceneRotation, [1, 0, 1]);
    mvPushMatrix();
        // Draw the main body.
        //---------------
        mvPushMatrix();
            mvScale([bodyRadius,bodyRadius,bodyLength]);        
            setMatrixUniforms();
            aCylinder.draw();
            mvPushMatrix();
                mvRotate(180.0,[1.0, 0.0, 0.0]);
                setMatrixUniforms();
                aDisk.draw(); 
            mvPopMatrix();
        mvPopMatrix();
        mvPushMatrix();
            mvTranslate([0.0, 0.0, bodyLength]);
            mvScale([bodyRadius,bodyRadius,bodyLength]);
            setMatrixUniforms();
            aDisk.draw(); 
        mvPopMatrix();
        mvPushMatrix();
            // draw head top 
            // talk
            mvTranslate([0.0, 0.0, bodyLength]);
            mvRotate(talkSwing,[1.0, 0.0, 0.0]);
            mvTranslate([0.0, 0.0, 0.07+0.05*talkSwing]);
            mvScale([bodyRadius,bodyRadius,bodyRadius]);    
            setMatrixUniforms();
            aDisk.draw();
            aHat.draw();
            // draw eyes
            setBlackMaterial();
            drawEyes();
            setGreenMaterial();        
            // draw horn
            drawHorn();
        mvPopMatrix();
        mvPushMatrix();
            // Draw arms
            mvTranslate([bodyRadius+limbRadius+0.1,0.0,bodyLength-limbRadius]);
            drawLimb(-armswing)
        mvPopMatrix();
        mvPushMatrix();
            mvTranslate([-(bodyRadius+limbRadius+0.1),0.0,bodyLength-limbRadius]);
            drawLimb(armswing);
        mvPopMatrix();
        mvPushMatrix();
            // Draw legs
            mvTranslate([(bodyRadius-limbRadius*2),0.0,0.2]);
            drawLimb(armswing);
        mvPopMatrix();
        mvPushMatrix();
            mvTranslate([-(bodyRadius-limbRadius*2),0.0,0.2]);
            drawLimb(-armswing);
        popMatrix(); 
    mvPopMatrix();
    // Update the rotation for the next draw
    var currentTime = (new Date).getTime();
    if (lastUpdateTime) {
        var delta = currentTime - lastUpdateTime;    
        sceneRotation += (30 * delta) / 1000.0;
    }  
    lastUpdateTime = currentTime;
    armswing=armswing+deltaArmswing;
    if ((armswing > maxArmswing)||(armswing < -maxArmswing))
    deltaArmswing=-deltaArmswing;
    talkCount=talkCount+deltaTalkCount;
    talkSwing=0.2*talkCount;
    if(talkCount > 40)
    deltaTalkCount=-1;
    else if(talkCount <1)
    deltaTalkCount=1;
}

Hjelpefunksjonene som tegner følehorn, øyne og hjelpefunksjonen drawLimb er definert slik:

function drawHorn()
{
    pushMatrix();
        mvRotate(10.0,[1.0, 0.0, 0.0]);
        mvRotate(30.0,[0.0, 1.0, 1.0]);
        mvTranslate([0.0, 0.0, bodyRadius-hornLength]);
        mvScale([hornRadius,hornRadius,hornLength]);
        setMatrixUniforms();
        aCylinder.draw();
    popMatrix();    
    pushMatrix();
        mvRotate(10.0,[1.0, 0.0, 0.0]);
        mvRotate(-30.0,[0.0, 1.0, 1.0]);
        mvTranslate([0.0, 0.0, bodyRadius-hornLength]);
        mvScale([hornRadius,hornRadius,hornLength]);
        setMatrixUniforms();
        aCylinder.draw();
    popMatrix();
}
function drawEyes()
{
    pushMatrix();
        mvRotate(-20.0,[1.0, 0.0, 0.0]);
        mvRotate(70.0,[0.0, 1.0, 1.0]);
        mvTranslate([0.0, 0.0, bodyRadius-2.2*limbRadius]);
        mvScale([limbRadius,limbRadius,limbRadius]);
        setMatrixUniforms();
        aHat.draw();
    popMatrix();    
    pushMatrix();
        mvRotate(-20.0,[1.0, 0.0, 0.0]);
        mvRotate(-70.0,[0.0, 1.0, 1.0]);
        mvTranslate([0.0, 0.0, bodyRadius-2.2*limbRadius]);
        mvScale([limbRadius,limbRadius,limbRadius]);
        setMatrixUniforms();
        aHat.draw();
    popMatrix();
}
function drawLimb(swing)
{
    // arm or a leg
    pushMatrix();
        mvRotate(swing,[1.0,0.0,0.0]);
        mvScale([limbRadius,limbRadius,limbRadius]);
        setMatrixUniforms();
        aHat.draw();
    popMatrix();
    pushMatrix();
        mvRotate(180.0+swing,[1.0,0.0,0.0]); 
        mvScale([limbRadius,limbRadius,limbLength]);    
        setMatrixUniforms();
        aCylinder.draw();
    popMatrix();
    pushMatrix();
        mvRotate(180.0+swing,[1.0,0.0,0.0]);
        mvTranslate([0.0,0.0,limbLength]);
        mvScale([limbRadius,limbRadius,limbRadius]);
        setMatrixUniforms();
        aHat.draw();
    popMatrix();
}

Funksjonen setMatrixUniforms() setter status på transformasjonsmatriser til shaderen.

_setMatrixUniforms

Vi har laget noen funkjsoner for å sette lys og materialer

_LightAndColor

De to funksjonene initShaders() og getShader() laster inn shaderne, kompilerer dem og etablerer shaderprogrammet.

_initShaders
_getShader

Fragment shader

Fragment shaderen arbeider med en farge og en lysretning. Begge er satt fra vertex shader. Merk at de har kvalifiseringen varying.

#ifdef GL_ES
precision mediump float;
#endif
varying vec3 vTransformedNormal;
varying vec4 vPosition;
uniform vec3 uMaterialAmbientColor;
uniform vec3 uMaterialDiffuseColor;
uniform vec3 uMaterialSpecularColor;
uniform float uMaterialShininess;
uniform vec3 uMaterialEmissiveColor;
uniform vec3 uAmbientLightingColor;
uniform vec3 uPointLightingDiffuseColor;
uniform vec3 uPointLightingSpecularColor;
uniform vec3 uPointLightingLocation;
void main(void) {
    vec3 ambientLightWeighting = uAmbientLightingColor;
    vec3 lightDirection = normalize(uPointLightingLocation - vPosition.xyz);
    vec3 normal = normalize(vTransformedNormal);
    vec3 specularLightWeighting = vec3(0.0, 0.0, 0.0);
    vec3 eyeDirection = normalize(-vPosition.xyz);
    vec3 reflectionDirection = reflect(-lightDirection, normal);
    float specularLightBrightness = 
        pow(max(dot(reflectionDirection, eyeDirection), 0.0), uMaterialShininess);
    specularLightWeighting = uPointLightingSpecularColor * specularLightBrightness;
    float diffuseLightBrightness = max(dot(normal, lightDirection), 0.0);
    vec3 diffuseLightWeighting = uPointLightingDiffuseColor * diffuseLightBrightness;
    vec3 materialAmbientColor = uMaterialAmbientColor;
    vec3 materialDiffuseColor = uMaterialDiffuseColor;
    vec3 materialSpecularColor = uMaterialSpecularColor;
    vec3 materialEmissiveColor = uMaterialEmissiveColor;
    float alpha = 1.0;
    gl_FragColor = vec4(
        materialAmbientColor * ambientLightWeighting
        + materialDiffuseColor * diffuseLightWeighting
        + materialSpecularColor * specularLightWeighting
        + materialEmissiveColor,
        alpha
    );
}

Vertex shader

De tre variablene: uMVMatrix, uPMatrix og uNormalMatrix blir satt fra Javascriptkoden. aVertexPosition representerer det aktuelle punktet, slik det er ordnet i en buffer fra Javascriptet og aVertexNormal er normalen i punktet.

Merk at hele lyssettingen etableres i shaderen.

attribute mediump vec3 aVertexNormal; // or in
attribute mediump vec3 aVertexPosition;
uniform mediump mat4 uNormalMatrix;
uniform mediump mat4 uMVMatrix;
uniform mediump mat4 uPMatrix;
varying vec3 vTransformedNormal;
varying vec4 vPosition;
varying lowp vec4 vColor;
varying mediump vec3 vLighting;
void main(void) {
    vPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
    gl_Position = uPMatrix * vPosition;
    vTransformedNormal=(uNormalMatrix * vec4(aVertexNormal, 1.0)).xyz;
}

Interaktiv

Det er laget tre enkle interaktive versjoner.

Den ene versjonen bruker musebevegelser:
index-mousing.html http://www.it.hiof.no/~borres/dw/wgl/android/index-mousing.html

Den andre introduserer noen scrollbarer som kontrollere:
index-matIA.html http://www.it.hiof.no/~borres/dw/wgl/android/index-matIA.html

Den tredje introduserer JQuery UI slidere som kontrollere:
index-matIASlide.html http://www.it.hiof.no/~borres/dw/wgl/android/index-matIASlide.html

Referanser
  1. OpenGL Shading Language (GLSL) Reference Pages Opengl.org www.opengl.org/sdk/docs/manglsl/ 14-05-2011
  1. OpenGL ES Software Development Kit Khronos Group www.khronos.org/opengles/sdk/docs/man/ 14-05-2011
  1. Sylvester sylvester.jcoglan.com/ 14-05-2011
Vedlikehold
Børre Stenseth, juni 2011
( Velkommen ) WebGL > Android figuren >Forbedret ( Ikke en pipe )