WebGL
WebGL
Børre Stenseth
Basis > Android figuren >Forbedret

Android

Hva

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

Dette er resultatet lagt i en iframe:

Du kan også inspisere resultatet og kildekoden på en enklere side:
index-mat.html https://borres.hiof.no/wep/webgl/basis/androidbetter/index-mat.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;
// camera
var viewAspect=1.0;

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, viewAspect, 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 https://borres.hiof.no/wep/webgl/basis/androidbetter/index-mousing.html

Den andre introduserer noen scrollbarer som kontrollere:
index-matIA.html https://borres.hiof.no/wep/webgl/basis/androidbetter/index-matIA.html

Den tredje introduserer JQuery UI slidere som kontrollere:
index-matIASlide.html https://borres.hiof.no/wep/webgl/basis/androidbetter/index-matIASlide.html

En liten julehilsen
God Jul https://borres.hiof.no/wep/webgl/basis/androidbetter/doors/index.html

Eller du kan jo kikke på denne
doors.html https://borres.hiof.no/wep/js/ex/doors/doors4/doors4.html

Referanser
  1. Sylvester sylvester.jcoglan.com/ 14-05-2011
  1. OpenGL ES Software Development Kit Khronos Group www.khronos.org/opengles/sdk/docs/man/ 14-05-2011
Basis > Android figuren >Forbedret