Android
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.
Vi har laget noen funkjsoner for å sette lys og materialer
De to funksjonene initShaders() og getShader() laster inn shaderne, kompilerer dem og etablerer shaderprogrammet.
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