Update deps, texture demo, fix textures and normals in shader

This commit is contained in:
Szymon Nowakowski 2024-03-17 20:20:56 +01:00
parent 78683f6115
commit d28d7896de
9 changed files with 88 additions and 46 deletions

1
.gitattributes vendored
View File

@ -1 +1,2 @@
*.webm filter=lfs diff=lfs merge=lfs -text *.webm filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text

BIN
bun.lockb

Binary file not shown.

View File

@ -1,4 +1,6 @@
import { Color, DirectionalLight, Mesh, Node, PerspectiveCamera, PointLight, Quaternion, Scene, Submesh, Vector3 } from "../src/data/index"; /// <reference types="../node_modules/@webgpu/types" />
import { Color, Mesh, Node, PerspectiveCamera, PointLight, Quaternion, Scene, Submesh, Vector3 } from "../src/data/index";
import { Renderer, degToRad } from "../src/oktaeder"; import { Renderer, degToRad } from "../src/oktaeder";
import "./style.css"; import "./style.css";
@ -16,38 +18,74 @@ const camera = new PerspectiveCamera({
farPlane: Infinity, farPlane: Infinity,
}); });
const vertexBuffer = renderer.createVertexBuffer({ vertexCount: 6 }); const vertexBuffer = renderer.createVertexBuffer({ vertexCount: 12, texCoord: true });
vertexBuffer.writeTypedArray(0, { vertexBuffer.writeTypedArray(0, {
position: new Float32Array([ position: new Float32Array([
0, 0, 1,
1, 0, 0,
0, 1, 0,
-1, 0, 0, -1, 0, 0,
0, 0, -1,
0, 0, -1,
0, 0, -1,
1, 0, 0, 1, 0, 0,
0, -1, 0, 0, -1, 0,
0, 1, 0, -1, 0, 0,
0, 0, -1, 0, 0, -1,
0, 0, 1, 0, 0, 1,
]), ]),
texCoord: new Float32Array([
0.5, 0.7113,
0.333333, 1,
0.166666, 0.7113,
0.333333, 0.4226,
0, 0.4226,
0, 1,
1, 1,
0.666666, 1,
0.833333, 0.7113,
0.666666, 0.4226,
1, 0.4226,
0.5, 0.7113,
]),
}); });
const indexBuffer = renderer.createIndexBuffer({ indexCount: 24, indexFormat: "uint16" }); const indexBuffer = renderer.createIndexBuffer({ indexCount: 24, indexFormat: "uint16" });
indexBuffer.writeArray(0, [ indexBuffer.writeArray(0, [
0, 4, 3, 0, 2, 1,
4, 1, 3, 3, 4, 2,
1, 5, 3,
5, 0, 3,
4, 0, 2,
1, 4, 2,
5, 1, 2, 5, 1, 2,
0, 5, 2, 2, 0, 3,
6, 8, 7,
9, 8, 10,
7, 8, 11,
11, 8, 9,
]); ]);
const submesh: Submesh = { start: 0, length: 24 }; const submesh: Submesh = { start: 0, length: 24 };
const mesh = new Mesh({ vertexBuffer, indexBuffer, submeshes: [submesh] }); const mesh = new Mesh({ vertexBuffer, indexBuffer, submeshes: [submesh] });
const imageBitmap = await loadImageBitmap("/uvmap.png");
const texture = renderer.createTexture({
format: "srgb",
width: imageBitmap.width,
height: imageBitmap.height,
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
});
renderer._device.queue.copyExternalImageToTexture(
{ source: imageBitmap, flipY: false },
{ texture: texture._texture },
{ width: imageBitmap.width, height: imageBitmap.height },
);
const material = renderer.createMaterial({ const material = renderer.createMaterial({
baseColor: Color.white(), baseColor: Color.white(),
baseColorPartialCoverageTexture: texture,
roughness: 0.5, roughness: 0.5,
metallic: 1, metallic: 0,
}); });
const node = new Node({ mesh, materials: [material] }); const node = new Node({ mesh, materials: [material] });
@ -55,25 +93,13 @@ const node = new Node({ mesh, materials: [material] });
const scene = new Scene({ const scene = new Scene({
nodes: [ nodes: [
node, node,
new Node({
translation: new Vector3(-1, 1, 0),
light: new PointLight({ color: new Color(1, 0, 0) }),
}),
new Node({ new Node({
translation: new Vector3(0, 1, -1), translation: new Vector3(0, 1, -1),
light: new PointLight({ color: new Color(0, 1, 0) }), light: new PointLight({ color: new Color(1, 1, 1) }),
}), }),
new Node({ new Node({
translation: new Vector3(1, 1, 0), translation: new Vector3(0, -1, -1),
light: new PointLight({ color: new Color(0, 0, 1) }), light: new PointLight({ color: new Color(1, 1, 1) }),
}),
new Node({
translation: new Vector3(0, 1, 1),
light: new PointLight({ color: new Color(1, 1, 0) }),
}),
new Node({
rotation: Quaternion.fromRotationYZ(degToRad(-90)),
light: new DirectionalLight({ color: new Color(0.5, 0.5, 0.5) }),
}), }),
new Node({ new Node({
translation: new Vector3(0, 0.8, -3), translation: new Vector3(0, 0.8, -3),
@ -91,6 +117,14 @@ function onResize(this: Window) {
const _quaternion = Quaternion.identity(); const _quaternion = Quaternion.identity();
async function loadImageBitmap(url: string) {
const res = await fetch(url);
const blob = await res.blob();
const imageBitmap = await createImageBitmap(blob, { colorSpaceConversion: "none" });
return imageBitmap;
}
function draw(timeMs: number) { function draw(timeMs: number) {
const time = 0.001 * timeMs; const time = 0.001 * timeMs;
node.setRotation(_quaternion.setRotationZX(-0.5 * time)); node.setRotation(_quaternion.setRotationZX(-0.5 * time));

BIN
example/uvmap.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -22,12 +22,12 @@
"build": "tsc --build" "build": "tsc --build"
}, },
"dependencies": { "dependencies": {
"tslib": "^2.6.1" "tslib": "^2.6.2"
}, },
"devDependencies": { "devDependencies": {
"@webgpu/types": "^0.1.34", "@webgpu/types": "^0.1.40",
"esbuild": "^0.19.2", "esbuild": "^0.20.2",
"typescript": "5.1.6" "typescript": "^5.4.2"
}, },
"exports": { "exports": {
".": { ".": {

View File

@ -5,6 +5,7 @@
*/ */
import * as data from "./data"; import * as data from "./data";
import * as resources from "./resources";
/* INITIAL SUPPORT PLAN /* INITIAL SUPPORT PLAN
* *
@ -94,7 +95,7 @@ import * as data from "./data";
export interface ParseResult { export interface ParseResult {
readonly cameras: readonly data.Camera[]; readonly cameras: readonly data.Camera[];
readonly materials: readonly data.Material[]; readonly materials: readonly resources.Material[];
readonly lights: readonly data.Light[]; readonly lights: readonly data.Light[];
readonly scenes: readonly data.Scene[]; readonly scenes: readonly data.Scene[];
readonly scene: data.Scene | null; readonly scene: data.Scene | null;
@ -181,7 +182,7 @@ export async function parse(gltf: ArrayBufferView, {
}: ParseOptions = {}): Promise<ParseResult> { }: ParseOptions = {}): Promise<ParseResult> {
const cameras: data.Camera[] = []; const cameras: data.Camera[] = [];
const materials: data.Material[] = []; const materials: resources.Material[] = [];
const lights: data.Light[] = []; const lights: data.Light[] = [];
const scenes: data.Scene[] = []; const scenes: data.Scene[] = [];
const scene: data.Scene | null = null; const scene: data.Scene | null = null;
@ -267,6 +268,10 @@ export async function parse(gltf: ArrayBufferView, {
// --- JSON CHUNK ---------------------------------------------------------- // --- JSON CHUNK ----------------------------------------------------------
void(stopOnFirstError);
void(treatWarningsAsErrors);
void(rest);
throw new Error("TODO"); throw new Error("TODO");
// --- BIN CHUNK ----------------------------------------------------------- // --- BIN CHUNK -----------------------------------------------------------

View File

@ -49,7 +49,7 @@ export class Renderer {
_textureWhite: Texture2D; _textureWhite: Texture2D;
/** 1×1 rgba8unorm texture of [0, 0, 0, 255] */ /** 1×1 rgba8unorm texture of [0, 0, 0, 255] */
_textureBlack: Texture2D; _textureBlack: Texture2D;
/** 1×1 rgba8unorm texture of [128, 128, 128, 255] */ /** 1×1 rgba8unorm texture of [128, 128, 255, 255] */
_textureNormal: Texture2D; _textureNormal: Texture2D;
_depthBuffer: Texture2D; _depthBuffer: Texture2D;
@ -110,7 +110,7 @@ export class Renderer {
height: 1, height: 1,
format: "linear", format: "linear",
}); });
this._textureNormal.writeFull(new Uint8Array([128, 128, 128, 255])); this._textureNormal.writeFull(new Uint8Array([128, 128, 255, 255]));
const framebufferTexture = this._context.getCurrentTexture(); const framebufferTexture = this._context.getCurrentTexture();
this._depthBuffer = new Texture2D(this, { this._depthBuffer = new Texture2D(this, {

View File

@ -46,10 +46,10 @@ export function _createPipeline(renderer: Renderer, {
const shaderModule = renderer._device.createShaderModule({ const shaderModule = renderer._device.createShaderModule({
code: shaderCode, code: shaderCode,
hints: { compilationHints: [
"vert": { layout: renderer._pipelineLayout }, { entryPoint: "vert", layout: renderer._pipelineLayout },
"frag": { layout: renderer._pipelineLayout }, { entryPoint: "frag", layout: renderer._pipelineLayout },
}, ],
}); });
let vertexLocation = 0; let vertexLocation = 0;
@ -318,17 +318,17 @@ fn frag(fragment: Varyings) -> @location(0) vec4<f32> {
var emissive = _Material.emissive; var emissive = _Material.emissive;
var ior = _Material.ior; var ior = _Material.ior;
${texCoord ? ` ${texCoord ? `
let baseColorPartialCoverageTexel = texture(_BaseColorPartialCoverageTexture, _Sampler, fragment.texCoord); let baseColorPartialCoverageTexel = textureSample(_BaseColorPartialCoverageTexture, _Sampler, fragment.texCoord);
baseColor *= baseColorPartialCoverageTexel.rgb; baseColor *= baseColorPartialCoverageTexel.rgb;
partialCoverage *= baseColorPartialCoverageTexel.a; partialCoverage *= baseColorPartialCoverageTexel.a;
let roughnessMetallicTexel = texture(_RoughnessMetallicTexture, _Sampler, fragment.texCoord); let roughnessMetallicTexel = textureSample(_RoughnessMetallicTexture, _Sampler, fragment.texCoord);
roughness *= roughnessMetallicTexel.g; roughness *= roughnessMetallicTexel.g;
metallic *= roughnessMetallicTexel.b; metallic *= roughnessMetallicTexel.b;
let emissiveTexel = texture(_EmissiveTexture, _Sampler, fragment.texCoord); let emissiveTexel = textureSample(_EmissiveTexture, _Sampler, fragment.texCoord);
emissive *= emissiveTexel.rgb; emissive *= emissiveTexel.rgb;
` : ""} ` : ""}
${lightTexCoord ? ` ${lightTexCoord ? `
let occlusionTexel = texture(_OcclusionTexture, _Sampler, fragment.lightTexCoord); let occlusionTexel = textureSample(_OcclusionTexture, _Sampler, fragment.lightTexCoord);
occlusion += _Material.occlusionTextureStrength * (occlusionTexel.r - 1.0); occlusion += _Material.occlusionTextureStrength * (occlusionTexel.r - 1.0);
` : ""} ` : ""}
@ -348,10 +348,10 @@ fn frag(fragment: Varyings) -> @location(0) vec4<f32> {
` : ` ` : `
let matrixTStoVS = screenSpaceMatrixTStoVS(positionVS, geometricNormalVS, fragment.texCoord); let matrixTStoVS = screenSpaceMatrixTStoVS(positionVS, geometricNormalVS, fragment.texCoord);
`} `}
let normalTextureTexel = texture(_NormalTexture, _Sampler, fragment.texCoord); let normalTextureTexel = textureSample(_NormalTexture, _Sampler, fragment.texCoord);
var normalTS = normalTextureTexel.xyz * 2.0 - 1.0; var normalTS = normalTextureTexel.xyz * 2.0 - 1.0;
normalTS.xy *= _Material.normalScale; normalTS = vec3(normalTS.xy * _Material.normalScale, normalTS.z);
let actualNormalVS = normalize(matrixTStoVS * geometricNormalVS); let actualNormalVS = normalize(matrixTStoVS * normalTS);
` : ` ` : `
let actualNormalVS = geometricNormalVS; let actualNormalVS = geometricNormalVS;
`} `}

File diff suppressed because one or more lines are too long