Initial commit
This commit is contained in:
307
Demos/Texture3/demo.js
Normal file
307
Demos/Texture3/demo.js
Normal file
@@ -0,0 +1,307 @@
|
||||
|
||||
import Shader from "../../framework/WebGpu.js"
|
||||
|
||||
import Matrix4 from "../../framework/Matrix4.js"
|
||||
|
||||
import Vector3 from "../../framework/Vector3.js"
|
||||
|
||||
import Camera from "../../framework/Camera.js";
|
||||
|
||||
import EventManager from "../../framework/eventManager.js";
|
||||
|
||||
import ShaderInpector from "../../framework/ShaderInpector.js";
|
||||
|
||||
|
||||
export class ParticleSimulation {
|
||||
|
||||
canvas;
|
||||
|
||||
device;
|
||||
|
||||
camera;
|
||||
|
||||
useLocalSort = true;
|
||||
|
||||
eventManager = new EventManager();
|
||||
|
||||
frameCount = 0;
|
||||
|
||||
setCanvas( canvas ) {
|
||||
|
||||
this.canvas = canvas;
|
||||
|
||||
this.eventManager.setCanvas( canvas );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
createTextureFromImageBitmap( device, imageBitmap ) {
|
||||
|
||||
const texture = device.createTexture( {
|
||||
|
||||
size: [ imageBitmap.width, imageBitmap.height, 1 ],
|
||||
|
||||
format: 'rgba8unorm',
|
||||
|
||||
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
|
||||
|
||||
} );
|
||||
|
||||
device.queue.copyExternalImageToTexture(
|
||||
|
||||
{ source: imageBitmap },
|
||||
|
||||
{ texture: texture },
|
||||
|
||||
[ imageBitmap.width, imageBitmap.height, 1 ]
|
||||
|
||||
);
|
||||
|
||||
return texture;
|
||||
|
||||
}
|
||||
|
||||
async loadImageBitmap(url) {
|
||||
|
||||
const response = await fetch( url );
|
||||
|
||||
const blob = await response.blob();
|
||||
|
||||
const imageBitmap = await createImageBitmap( blob );
|
||||
|
||||
return imageBitmap;
|
||||
}
|
||||
|
||||
|
||||
async loadTexture( url ) {
|
||||
|
||||
const imageBitmap = await this.loadImageBitmap( url );
|
||||
|
||||
const texture = this.createTextureFromImageBitmap( this.device, imageBitmap );
|
||||
|
||||
return texture;
|
||||
|
||||
}
|
||||
|
||||
createPlane(width, height, repeatU, repeatV) {
|
||||
|
||||
const vertices = new Float32Array( 18 ); // 6 vertices (2 triangles) * 3 coords
|
||||
const normals = new Float32Array( 18 ); // same count as vertices
|
||||
const uvs = new Float32Array( 12 ); // 6 vertices * 2 coords
|
||||
|
||||
// Positions (two triangles forming a plane on XY plane at z=0)
|
||||
// Large plane from (-width/2, -height/2) to (width/2, height/2)
|
||||
vertices.set([
|
||||
-width / 2, -height / 2, 0,
|
||||
width / 2, -height / 2, 0,
|
||||
-width / 2, height / 2, 0,
|
||||
|
||||
-width / 2, height / 2, 0,
|
||||
width / 2, -height / 2, 0,
|
||||
width / 2, height / 2, 0
|
||||
]);
|
||||
|
||||
// Normals all pointing +Z
|
||||
for (let i = 0; i < 6; i++) {
|
||||
normals[i * 3 + 0] = 0;
|
||||
normals[i * 3 + 1] = 0;
|
||||
normals[i * 3 + 2] = 1;
|
||||
}
|
||||
|
||||
// UVs scaled by repeatU, repeatV to repeat texture over the plane
|
||||
uvs.set([
|
||||
0, 0,
|
||||
repeatU, 0,
|
||||
0, repeatV,
|
||||
|
||||
0, repeatV,
|
||||
repeatU, 0,
|
||||
repeatU, repeatV
|
||||
]);
|
||||
|
||||
return { vertices, normals, uvs };
|
||||
|
||||
}
|
||||
|
||||
async setup( offscreenCanvas, width, height ) {
|
||||
|
||||
offscreenCanvas.width = width;
|
||||
|
||||
offscreenCanvas.height = height;
|
||||
|
||||
this.canvas = offscreenCanvas;
|
||||
|
||||
const context = offscreenCanvas.getContext("webgpu");
|
||||
|
||||
this.camera = new Camera( [0, 0, 1115], [0, -.3, 0], [0, 1, 0] );
|
||||
|
||||
this.eventManager.setup( offscreenCanvas, this.camera );
|
||||
|
||||
|
||||
const adapter = await self.navigator.gpu.requestAdapter();
|
||||
|
||||
if ( !adapter ) {
|
||||
|
||||
throw new Error("Failed to get GPU adapter");
|
||||
|
||||
}
|
||||
|
||||
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
||||
|
||||
this.device = await adapter.requestDevice();
|
||||
|
||||
this.renderShader = new Shader( this.device );
|
||||
|
||||
context.configure({
|
||||
device: this.device,
|
||||
format: presentationFormat,
|
||||
alphaMode: "opaque"
|
||||
});
|
||||
const instanceCount = 100;
|
||||
const instancePositions = new Float32Array(instanceCount * 4); // vec4 per instance
|
||||
|
||||
for (let i = 0; i < instanceCount; i++) {
|
||||
|
||||
const x = (i % 10) * 300.0;
|
||||
const y = Math.floor(i / 10) * 350.0;
|
||||
|
||||
instancePositions[i * 4 + 0] = x - 1000;
|
||||
instancePositions[i * 4 + 1] = 0;
|
||||
instancePositions[i * 4 + 2] = y - 1000;
|
||||
instancePositions[i * 4 + 3] = 0;
|
||||
}
|
||||
|
||||
|
||||
var model = await this.loadJSON("demo.json");
|
||||
|
||||
var mesh = model.meshes[0];
|
||||
|
||||
console.log("mesh", mesh);
|
||||
|
||||
this.renderShader.setCanvas( this.canvas );
|
||||
|
||||
this.renderShader.topology = "triangle-list";
|
||||
|
||||
await this.renderShader.setup( "../../shaders/triangle-list-texture-normal.wgsl");
|
||||
|
||||
this.renderShader.setAttribute( "position", mesh.vertices );
|
||||
|
||||
this.renderShader.setAttribute( "normal", mesh.normals );
|
||||
|
||||
this.renderShader.setAttribute( "bitangent", mesh.bitangents );
|
||||
|
||||
this.renderShader.setAttribute( "uv", mesh.texturecoords[0] );
|
||||
|
||||
var faces = mesh.faces;
|
||||
|
||||
const indexArray = new Uint32Array(faces.length * 3);
|
||||
|
||||
for (let i = 0; i < faces.length; i++) {
|
||||
|
||||
indexArray[i * 3 + 0] = faces[i][0];
|
||||
|
||||
indexArray[i * 3 + 1] = faces[i][1];
|
||||
|
||||
indexArray[i * 3 + 2] = faces[i][2];
|
||||
|
||||
}
|
||||
|
||||
this.renderShader.setIndices( indexArray );
|
||||
|
||||
this.renderShader.setCanvas( this.canvas );
|
||||
|
||||
this.renderShader.topology = "triangle-list";
|
||||
|
||||
await this.renderShader.setup( "../../shaders/triangle-list-texture-normal.wgsl");
|
||||
|
||||
/*
|
||||
const { vertices, normals, uvs } = this.createPlane( 1000, 1000, 4, 4 );
|
||||
|
||||
this.renderShader.setAttribute( "position", vertices );
|
||||
|
||||
this.renderShader.setAttribute( "normal", normals );
|
||||
|
||||
this.renderShader.setAttribute( "uv", uvs );
|
||||
|
||||
|
||||
this.vertexCount = vertices.length / 3
|
||||
|
||||
*/
|
||||
this.renderShader.setVariable( "instancePositions", instancePositions );
|
||||
|
||||
var texture = await this.loadTexture("./textures/0_floorTiles_diff.png");
|
||||
|
||||
const sampler = this.device.createSampler({
|
||||
minFilter: 'linear',
|
||||
magFilter: 'linear',
|
||||
mipmapFilter: 'linear',
|
||||
addressModeU: 'repeat',
|
||||
addressModeV: 'repeat',
|
||||
});
|
||||
|
||||
this.renderShader.setVariable( "mySampler", sampler );
|
||||
|
||||
this.renderShader.setVariable( "myTexture", texture );
|
||||
|
||||
var normalTexture = await this.loadTexture("./textures/0_floorTiles_ddn.png");
|
||||
|
||||
this.renderShader.setVariable( "normalMapTexture", normalTexture );
|
||||
|
||||
|
||||
this.render();
|
||||
|
||||
}
|
||||
|
||||
updateTimeDelta() {
|
||||
|
||||
const now = performance.now();
|
||||
|
||||
this.deltaTimeValue = ( now - this.lastFrameTime ) / 1000;
|
||||
|
||||
this.lastFrameTime = now;
|
||||
|
||||
}
|
||||
|
||||
async render() {
|
||||
|
||||
this.updateTimeDelta();
|
||||
|
||||
const viewMatrixData = this.camera.getViewMatrix();
|
||||
|
||||
const projectionMatrixData = Matrix4.createProjectionMatrix( this.camera, this.canvas )
|
||||
|
||||
const viewProjectionMatrix = Matrix4.multiply( projectionMatrixData, viewMatrixData );
|
||||
|
||||
const cameraWorldMatrix = Matrix4.invert( viewMatrixData );
|
||||
|
||||
const cameraPosition = Matrix4.getColumn( cameraWorldMatrix, 3 );
|
||||
|
||||
this.renderShader.setVariable( "viewProjectionMatrix", viewProjectionMatrix );
|
||||
|
||||
this.renderShader.setVariable( "cameraPosition", cameraPosition );
|
||||
|
||||
|
||||
this.renderShader.renderToCanvas( this.vertexCount, 74, 0 );
|
||||
|
||||
this.frameCount++;
|
||||
|
||||
requestAnimationFrame( this.render.bind( this ) );
|
||||
|
||||
}
|
||||
|
||||
async loadJSON( pathName ) {
|
||||
|
||||
const response = await fetch( pathName );
|
||||
|
||||
if ( !response.ok ){
|
||||
|
||||
throw new Error( `Failed to load shader: ${ pathName }` );
|
||||
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user