quaternion 3d logic
WebGL/WebGL2/WebGPU available via data uri.no drift, calculated from origin.
generate unit quaternion(1===sin**2+cos**2).
rotation order switchable(q0*q1!==q1*q0).
quaternion
quaternionRotated`p+2.*cross(q.xyz,cross(q.xyz,p)+q.w*p)`getRotated
(q0,q1,precision)=>`vec4${precision}(c(c(p,${q0}),${q1}),0.)+vec4${precision}(0.,0.,1.,2.)`vertexShaderSrc
WebGLprecision highp float;attribute vec3 p;uniform vec4 q0;uniform vec4 q1;
vec3 c(vec3 p,vec4 q){return ${quaternionRotated};}
void main(){gl_Position=${getRotated(`q0`,`q1`,``)};}WebGL2
#version 300 es\nprecision highp float;in vec3 p;layout(std140)uniform q{vec4 q0;vec4 q1;};
vec3 c(vec3 p,vec4 q){return ${quaternionRotated};}
void main(){gl_Position=${getRotated(`q0`,`q1`,``)};}WebGPU
struct Q{q0:vec4f,q1:vec4f}@binding(0)@group(0)var<uniform>q:Q;
fn c(p:vec3f,q:vec4f)->vec3f{return ${quaternionRotated};}
@vertex fn main(@location(0)p:vec3f)->@builtin(position)vec4f{return ${getRotated(`q.q0`,`q.q1`,`f`)};}3d
fragmentShaderSrc
WebGLprecision highp float;
void main(){gl_FragColor=vec4(${color.map(v=>v+`.`).join(`,`)});}WebGL2
#version 300 es\nprecision highp float;out vec4 c;
void main(){c=vec4(${color.map(v=>v+`.`).join(`,`)});}WebGPU
@fragment fn main()->@location(0)vec4f{return vec4f(${color.map(v=>v+`.`).join(`,`)});}step0: configure
WebGPU
01. request adapterawait navigator.gpu.requestAdapter()02. request device
await adapter.requestDevice()03. configure
context.configure({device:device,format:navigator.gpu.getPreferredCanvasFormat(),alphaMode:`premultiplied`})step1: bind
WebGL, WebGL2
01. create programcontext.createProgram()02. create vertexShader
context.createShader(context.VERTEX_SHADER)03. set vertexShaderSrc
context.shaderSource(vertexShader,vertexShaderSrc)04. compile vertexShader
context.compileShader(vertexShader)05. attach vertexShader
context.attachShader(program,vertexShader)06. create fragmentShader
context.createShader(context.FRAGMENT_SHADER)07. set fragmentShaderSrc
context.shaderSource(fragmentShader,fragmentShaderSrc)08. compile fragmentShader
context.compileShader(fragmentShader)09. attach fragmentShader
context.attachShader(program,fragmentShader)10. link program
context.linkProgram(program)11. clear color
context.clearColor(0,0,0,0)12. use program
context.useProgram(program)13. enable vertexAttribArray
context.enableVertexAttribArray(0)14. bind arrayBuffer
context.bindBuffer(context.ARRAY_BUFFER,context.createBuffer())15. set p
context.bufferData(context.ARRAY_BUFFER,p,context.STATIC_DRAW)16. bind elementArrayBuffer
context.bindBuffer(context.ELEMENT_ARRAY_BUFFER,context.createBuffer())17. set is
context.bufferData(context.ELEMENT_ARRAY_BUFFER,is,context.STATIC_DRAW)18. vertexAttribPointer
context.vertexAttribPointer(0,3,context.FLOAT,false,0,0)WebGL
19. get q0Locationcontext.getUniformLocation(program,`q0`)20. get q1Location
context.getUniformLocation(program,`q1`)WebGL2
19. create uniformBuffercontext.createBuffer()20. uniformBlockBinding
context.uniformBlockBinding(program,0,0)21. bind uniformBuffer
context.bindBuffer(context.UNIFORM_BUFFER,uniformBuffer)22. bind uniformBufferBase
context.bindBufferBase(context.UNIFORM_BUFFER,0,uniformBuffer)WebGPU
01. create layoutconfiguration.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{}}]})02. create pipeline
configuration.device.createRenderPipeline({
layout:configuration.device.createPipelineLayout({bindGroupLayouts:[layout]})
,primitive:{topology:topology}
,vertex:{
buffers:[{
attributes:[{format:`float32x3`,offset:0,shaderLocation:0}]
,arrayStride:12
}]
,module:configuration.device.createShaderModule({code:vertexShaderSrc})
}
,fragment:{
targets:[{format:configuration.format}]
,module:configuration.device.createShaderModule({code:fragmentShaderSrc})
}
})03. create renderBundleEncoder
configuration.device.createRenderBundleEncoder({colorFormats:[configuration.format]})04. renderBundleEncoder set pipeline
renderBundleEncoder.setPipeline(pipeline)05. create vertexBuffer
configuration.device.createBuffer({usage:GPUBufferUsage.VERTEX,size:p.byteLength,mappedAtCreation:true})06. set p
new Float32Array(vertexBuffer.getMappedRange()).set(p)07. vertexBuffer unmap
vertexBuffer.unmap()08. renderBundleEncoder set vertexBuffer
renderBundleEncoder.setVertexBuffer(0,vertexBuffer)09. create uniformBuffer
configuration.device.createBuffer({usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,size:32})10. renderBundleEncoder set bindGroup
renderBundleEncoder.setBindGroup(0,configuration.device.createBindGroup({entries:[{binding:0,resource:{buffer:uniformBuffer}}],layout:layout}))11. create indexBuffer
configuration.device.createBuffer({usage:GPUBufferUsage.INDEX,size:is.byteLength,mappedAtCreation:true})12. set is
new Uint16Array(indexBuffer.getMappedRange()).set(is)13. unmap indexBuffer
indexBuffer.unmap()14. renderBundleEncoder set indexBuffer
renderBundleEncoder.setIndexBuffer(indexBuffer,`uint16`)15. renderBundleEncoder draw indexed
renderBundleEncoder.drawIndexed(is.length)16. get bundle
renderBundleEncoder.finish()17. create descriptor
{colorAttachments:[{loadOp:`clear`,storeOp:`store`,clearValue:[0,0,0,0]}]}step2: render
WebGL
01. set q0Locationcontext.uniform4fv(q0Location,q0)02. set q1Location
context.uniform4fv(q1Location,q1)WebGL2
01. create qq0 concat q102. set q
context.bufferData(context.UNIFORM_BUFFER,q,context.STATIC_DRAW)WebGL, WebGL2
03. clearcontext.clear(context.COLOR_BUFFER_BIT|context.DEPTH_BUFFER_BIT)04. draw elements
context.drawElements(mode,is.length,context.UNSIGNED_SHORT,0)WebGPU
01. create qq0 concat q102. set q
configuration.device.queue.writeBuffer(uniformBuffer,0,q)03. descriptor set view
descriptor.colorAttachments[0].view=context.getCurrentTexture().createView()04. create commandEncoder
configuration.device.createCommandEncoder()05. get renderPass
commandEncoder.beginRenderPass(descriptor)06. renderPass execute bundles
renderPass.executeBundles([bundle])07. renderPass end
renderPass.end()08. submit
configuration.device.queue.submit([commandEncoder.finish()])