Update deps, texture demo, fix textures and normals in shader
This commit is contained in:
parent
78683f6115
commit
d28d7896de
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||||
|
@ -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
BIN
example/uvmap.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -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": {
|
||||||
".": {
|
".": {
|
||||||
|
@ -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 -----------------------------------------------------------
|
||||||
|
@ -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, {
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user