Camera Yaw Control
Rotating around the y-axis to look around....
Single triangle provides a point of references for our camera - as we move around we see the triangle moving.
Functions Used: setVertexBuffer(), setIndexBuffer(), drawIndexed(), createBuffer(), getMappedRange(), getContext(), requestAdapter(), getPreferredCanvasFormat(), createCommandEncoder(), beginRenderPass(), setPipeline(), draw(), end(), submit(), getCurrentTexture(), createView(), createShaderModule()
Add event key for `A/D` which adjusts the facing direction of the camera. The yaw direction is calculated using simple sin/cos trig functions.
// ----------------------------------------------------------------------------- let counter = 0.0 ; let frameNumber = 0 ; let fpsTime = performance . now (); let cameraAt = [ 0 , 0 , 0 ]; let cameraDir = [ 0 , 0 , 1 ]; let yaw = 0.0 ; let cameraEye = [ cameraAt [ 0 ]- cameraDir [ 0 ], cameraAt [ 1 ]- cameraDir [ 1 ], cameraAt [ 2 ]- cameraDir [ 2 ] ]; function frame () { var startTime = performance . now (); // setup a transform for triangle const t = { p :{ x : 0 , y : 0 , z : 0 }, r :{ x : 0 , y : 0.0 , z : 0.0 }, s :{ x : 1.0 , y : 1.0 , z : 1.0 } }; let modelMatrix = buildMatrix ( t . p , t . r , t . s ); // update the local matrix for each triangle draw differently device . queue . writeBuffer ( mvpUniformBuffer , 0 , modelMatrix ); // Rotate the camera around the origin in the circle mat4 . lookAt ( viewMatrix , cameraEye , cameraAt , [ 0 , 1 , 0 ]); device . queue . writeBuffer ( mvpUniformBuffer , 64 , viewMatrix ); // simple counter counter += 0.001 ; const k = 0 ; const renderPassDescription = { colorAttachments : [{ view : context . getCurrentTexture (). createView (), loadOp : ( k == 0 ? "clear" : "load" ), clearValue : [ 0 , 0.5 , 0.5 , 1 ], // clear screen to color storeOp : 'store' }], depthStencilAttachment : { view : depthTexture . createView (), depthLoadOp : ( k == 0 ? "clear" : "load" ), depthClearValue : 1 , depthStoreOp : "store" , } }; renderPassDescription . colorAttachments [ 0 ]. view = context . getCurrentTexture (). createView (); const commandEncoder = device . createCommandEncoder (); const renderPass = commandEncoder . beginRenderPass ( renderPassDescription ); renderPass . setBindGroup ( 0 , uniformBindGroup ); renderPass . setPipeline ( pipeline ); renderPass . setVertexBuffer ( 0 , positionBuffer ); renderPass . setVertexBuffer ( 1 , colorBuffer ); renderPass . setIndexBuffer ( indexBuffer , 'uint16' ); renderPass . drawIndexed ( 3 , 1 ); renderPass . end (); device . queue . submit ([ commandEncoder . finish ()]); // animate - keep updating requestAnimationFrame ( frame ); // --------- Timing Information ------------------------- frameNumber ++; var endTime = performance . now (); var updateFPS = 1000.0 / ( endTime - fpsTime ); var maxFPS = 1000.0 / ( endTime - startTime ); fpsTime = endTime ; divInfo . innerHTML = ` Cursor Keys 'A/D' Yaw - Rotation<br> Frame Number: ${ frameNumber } <br> Current FPS: ${ updateFPS . toFixed ( 1 )} ,<br> Max FPS: ${ maxFPS . toFixed ( 2 )} `; } onkeydown = function( e ) { let dt = 0.2 ; switch ( event . key ) { case 'a' : { yaw -= dt * 0.1 ; } break; case 'd' : { yaw += dt * 0.1 ; } break; case "ArrowLeft" : { cameraAt [ 0 ] += dt ; } break; case "ArrowRight" : { cameraAt [ 0 ] -= dt ; } break; case "ArrowUp" : { cameraAt [ 2 ] += dt ; } break; case "ArrowDown" : { cameraAt [ 2 ] -= dt ; } break; } // end switch(..) cameraDir = [ Math . sin ( yaw ), 0 , Math . cos ( yaw ) ]; cameraEye = [ cameraAt [ 0 ]- cameraDir [ 0 ], cameraAt [ 1 ]- cameraDir [ 1 ], cameraAt [ 2 ]- cameraDir [ 2 ] ]; } // end onkeydown(..) frame ();
Resources and Links
• WebGPU Example Link [LINK ]