texture loading, vertex snapping shader

This commit is contained in:
41666 2023-10-15 00:24:19 -04:00
parent 94c5165877
commit 905a5b6038
27 changed files with 365 additions and 114 deletions

2
.gitignore vendored
View file

@ -173,3 +173,5 @@ dist
# Finder (MacOS) folder config
.DS_Store
*.blend?

View file

@ -1,5 +1,6 @@
import chalk from "chalk";
import { globSync } from "glob";
import { relative, resolve, dirname } from "node:path";
const w = 1;
@ -49,8 +50,13 @@ type Triangle = {
// ...vertToArray(t.c),
// ];
const meshAbsolutePath = resolve("./src/renderer/mesh.ts");
const getMeshImportPath = (thisFile: string) =>
relative(dirname(thisFile), meshAbsolutePath).replace(/\.ts$/g, "");
export const convertMeshes = async () => {
const meshes = globSync("src/meshes/*.ply");
const meshes = globSync("src/meshes/**/*.ply");
for (const file of meshes) {
const ply = await Bun.file(file).text();
@ -222,7 +228,7 @@ export const convertMeshes = async () => {
facesMaxValue <= 0xff ? 8 : facesMaxValue <= 0xffff ? 16 : 32;
const outFile = file.replace(".ply", ".ts");
const outString = `import { Mesh } from "../renderer/mesh";
const outString = `import { Mesh } from "${getMeshImportPath(outFile)}";
// prettier-ignore
export default new Mesh({

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

5
index.d.ts vendored
View file

@ -30,3 +30,8 @@ declare module "*.md" {
const content: string;
export default content;
}
declare module "*.png" {
const path: string;
export default path;
}

View file

@ -29,7 +29,7 @@
"ignore": [
"html/",
"README.md",
"src/meshes/*.ts"
"src/meshes/**/*.ts"
],
"delay": 1000,
"exec": "bun run . --"

View file

@ -3,9 +3,12 @@ import { WebGLApp } from "../renderer/webgl";
import { Renderable } from "../renderer/renderable";
import { Transform, etoq, v3 } from "../renderer/transform";
import { quat } from "gl-matrix";
import trianglething from "../meshes/trianglething";
import { trianglething, texture0, texture1 } from "../meshes/trianglething";
import teapot from "../meshes/teapot";
import { basic } from "../common-shaders/basic";
import { Texture } from "../renderer/texture";
import { errorShader } from "../common-shaders/error";
import { basicVertexRounding } from "../common-shaders/basic-vertex-rounding";
const app = new WebGLApp({ fov: 45 });
@ -13,21 +16,42 @@ const camera = new Transform([3, 3, 5], etoq([-15, 40, 0]));
const light = new Transform([1, 1, 0]);
const transform = new Transform(v3(0), etoq([0, 0, 0]));
const transform2 = new Transform([-2, 0, 1], etoq([0, 90 + 62, 0]));
const transform2 = new Transform([-3, 0, 1], etoq([0, 0, 0]));
const trithingTexture = new Texture(app, texture0);
const trithingTextureNormals = new Texture(app, texture1);
app.onUpdate(() => {
quat.rotateY(transform.rotation, transform.rotation, 0.001);
quat.rotateY(transform2.rotation, transform2.rotation, 0.001);
});
new Renderable(
app,
transform2,
new MeshRenderer(app, trianglething, basic(app), camera, light).configure({})
transform,
new MeshRenderer(
app,
trianglething,
basicVertexRounding(app)
.addTexture("texture0", trithingTexture)
.addTexture("texture1", trithingTextureNormals),
camera,
light
).configure({})
);
new Renderable(
app,
transform,
new MeshRenderer(app, teapot, basic(app), camera, light).configure({})
transform2,
new MeshRenderer(
app,
trianglething,
basic(app)
.addTexture("texture0", trithingTexture)
.addTexture("texture1", trithingTextureNormals),
camera,
light
).configure({})
);
app.start();

View file

@ -0,0 +1,29 @@
import { Shader, ShaderConfig } from "../renderer/shader";
import { WebGLApp } from "../renderer/webgl";
import frag from "./basic.frag";
import vert from "./basic-vertex-rounding.vert";
export const basicShaderConfig: ShaderConfig = {
attributes: {
vertex: "a_vertex",
uv0: "a_uv0",
normal: "a_normal",
vertexColor: "a_vertex_color",
},
uniforms: {
view: "u_view",
projection: "u_projection",
objectToWorld: "u_object_to_world",
objectToWorldInv: "u_object_to_world_inv",
light0: "u_light_0",
light0Color: "u_light_0_color",
time: "u_time",
albedo: "u_albedo",
texture0: "u_texture_0",
texture1: "u_texture_1",
},
};
export const basicVertexRounding = (app: WebGLApp) =>
new Shader(basicShaderConfig).vertex(vert).fragment(frag).app(app);

View file

@ -0,0 +1,35 @@
#version 300 es
uniform mat4 u_view;
uniform mat4 u_projection;
uniform mat4 u_object_to_world;
uniform mat4 u_object_to_world_inv;
uniform vec3 u_light_0;
// uniform vec4 u_light_0_color;
// uniform float u_time;
// uniform vec4 u_albedo;
in vec4 a_vertex;
in vec2 a_uv0;
in vec3 a_normal;
in vec4 a_vertex_color;
out vec2 uv0;
out vec3 normal;
out vec4 vertex_color;
out vec3 light_pos;
#define ROUNDING_FACTOR 230.0f
void main() {
mat4 worldInv = inverse(u_view);
mat4 MVW = u_projection * u_view * u_object_to_world;
vec4 realPosition = MVW * a_vertex;
realPosition.xyz = round(vec3(realPosition.xyz * ROUNDING_FACTOR)) / ROUNDING_FACTOR;
gl_Position = realPosition;
uv0 = a_uv0;
normal = normalize(mat3(worldInv) * a_normal);
vertex_color = a_vertex_color;
light_pos = normalize(mat3(u_object_to_world_inv) * u_light_0);
}

View file

@ -10,19 +10,23 @@ precision highp float;
// uniform float u_time;
// uniform vec4 u_albedo;
uniform sampler2D u_texture_0;
uniform sampler2D u_texture_1;
in vec2 uv0;
in vec3 normal;
in vec3 light_pos;
out vec4 fragColor;
void main() {
vec3 normal = normalize(normal);
vec4 normalTex = texture(u_texture_1, uv0);
vec3 normal = normalize(normal * normalTex.xyz);
float light = dot(normal, light_pos);
fragColor = vec4(1.0);
fragColor.rgb = texture(u_texture_0, uv0).rgb;
fragColor.rgb *= max(light, 0.1);
fragColor.a = 1.0;
}

View file

@ -1,76 +0,0 @@
ply
format ascii 1.0
comment Created in Blender version 3.6.4
element vertex 31
property float x
property float y
property float z
property float nx
property float ny
property float nz
property uchar red
property uchar green
property uchar blue
property uchar alpha
property float s
property float t
element face 26
property list uchar uint vertex_indices
end_header
0 2.609 0 0 -1 8.3803394e-07 0 1 255 255 0.00013659838 0.8180941
-0.368004 2.9959495 0.50652 -0.5257306 -0.44721383 0.723607 0 1 255 255 0.15755458 0.7272099
-0.595448 2.9959495 -0.19346951 -0.8506533 -0.44721213 -0.2763879 0 1 255 255 0.1575546 0.9089782
0 2.609 0 0 -1 8.3803394e-07 0 1 255 255 0.00013659043 0.6363257
0.368004 2.9959495 0.50652 0.5257306 -0.4472139 0.723607 0 1 255 255 0.15755458 0.54544157
0 2.609 0 0 -1 8.3803394e-07 0 1 255 255 0.0001365666 0.09102075
-0.595448 2.9959495 -0.19346951 -0.8506533 -0.44721213 -0.2763879 0 1 255 255 0.15755455 0.00013656964
0 2.9959495 -0.6260975 0 -0.44721153 -0.89442825 0 1 255 255 0.15755457 0.18190491
0 2.609 0 0 -1 8.3803394e-07 0 1 255 255 0.00013657454 0.2727891
0.595448 2.9959495 -0.19346951 0.8506533 -0.4472122 -0.27638793 0 1 255 255 0.15755457 0.36367324
0 2.609 0 0 -1 8.3803394e-07 0 1 255 255 0.00013658249 0.45455742
0 3.6220505 0.6260975 0 0.44721153 0.89442825 0 1 255 255 0.31497157 0.6363257
-0.595448 3.6220505 0.19346951 -0.8506533 0.44721216 0.27638793 0 1 255 255 0.31497157 0.8180941
-0.368004 3.6220505 -0.50652 -0.5257306 0.4472139 -0.72360694 0 1 255 255 0.31497154 0.09102073
0.368004 3.6220505 -0.50652 0.5257306 0.4472139 -0.72360694 0 1 255 255 0.31497154 0.27278906
0.595448 3.6220505 0.19346951 0.85065323 0.4472122 0.2763879 0 1 255 255 0.31497154 0.45455742
-0.368004 3.6220505 -0.50652 -0.5257306 0.4472139 -0.72360694 0 1 255 255 0.31497157 0.9998634
0 4.0090003 0 0 1 -8.165459e-07 0 1 255 255 0.47238955 0.72720987
0 4.0090003 0 0 1 -8.165459e-07 0 1 255 255 0.47238958 0.9089782
0 4.0090003 0 0 1 -8.165459e-07 0 1 255 255 0.47238955 0.1819049
0 4.0090003 0 0 1 -8.165459e-07 0 1 255 255 0.47238955 0.36367324
0 4.0090003 0 0 1 -8.165459e-07 0 1 255 255 0.47238955 0.54544157
1 0 0 0.8999471 -0.43599886 2.4163015e-07 0 1 255 255 0.8119813 0.33945516
0 2.5 0 -5.150958e-08 1 0 0 1 255 255 0.642322 0.16979587
-4.3711392e-08 0 1 -3.0203772e-08 -0.4359989 0.8999472 0 1 255 255 0.8119813 0.00013659486
-1 0 -8.7422784e-08 -0.8999471 -0.4359989 -2.4291313e-07 0 1 255 255 0.47266275 0.00013660162
-4.3711392e-08 0 1 -3.0203772e-08 -0.4359989 0.8999472 0 1 255 255 0.81198126 0.6790469
1.19248815e-08 0 -1 0 -0.43599886 -0.8999471 0 1 255 255 0.47266275 0.33972836
1 0 0 0.8999471 -0.43599886 2.4163015e-07 0 1 255 255 0.47266272 0.6790469
1.19248815e-08 0 -1 0 -0.43599886 -0.8999471 0 1 255 255 0.47266275 0.33945513
-1 0 -8.7422784e-08 -0.8999471 -0.4359989 -2.4291313e-07 0 1 255 255 0.81198126 0.3397284
3 0 1 2
3 1 3 4
3 5 6 7
3 8 7 9
3 10 9 4
3 1 4 11
3 2 1 12
3 7 6 13
3 9 7 14
3 4 9 15
3 1 11 12
3 2 12 16
3 7 13 14
3 9 14 15
3 4 15 11
3 12 11 17
3 16 12 18
3 14 13 19
3 15 14 20
3 11 15 21
3 22 23 24
3 24 23 25
3 26 27 28
3 25 23 29
3 29 23 22
3 26 30 27

View file

@ -1,12 +0,0 @@
import { Mesh } from "../renderer/mesh";
// prettier-ignore
export default new Mesh({
colors: new Uint8Array([0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255,0,1,255,255]),
faces: new Uint8Array([0,1,2,1,3,4,5,6,7,8,7,9,10,9,4,1,4,11,2,1,12,7,6,13,9,7,14,4,9,15,1,11,12,2,12,16,7,13,14,9,14,15,4,15,11,12,11,17,16,12,18,14,13,19,15,14,20,11,15,21,22,23,24,24,23,25,26,27,28,25,23,29,29,23,22,26,30,27]),
name: "src/meshes/trianglething.ply",
normals: new Float32Array([0,-1,8.3803394e-7,-0.5257306,-0.44721383,0.723607,-0.8506533,-0.44721213,-0.2763879,0,-1,8.3803394e-7,0.5257306,-0.4472139,0.723607,0,-1,8.3803394e-7,-0.8506533,-0.44721213,-0.2763879,0,-0.44721153,-0.89442825,0,-1,8.3803394e-7,0.8506533,-0.4472122,-0.27638793,0,-1,8.3803394e-7,0,0.44721153,0.89442825,-0.8506533,0.44721216,0.27638793,-0.5257306,0.4472139,-0.72360694,0.5257306,0.4472139,-0.72360694,0.85065323,0.4472122,0.2763879,-0.5257306,0.4472139,-0.72360694,0,1,-8.165459e-7,0,1,-8.165459e-7,0,1,-8.165459e-7,0,1,-8.165459e-7,0,1,-8.165459e-7,0.8999471,-0.43599886,2.4163015e-7,-5.150958e-8,1,0,-3.0203772e-8,-0.4359989,0.8999472,-0.8999471,-0.4359989,-2.4291313e-7,-3.0203772e-8,-0.4359989,0.8999472,0,-0.43599886,-0.8999471,0.8999471,-0.43599886,2.4163015e-7,0,-0.43599886,-0.8999471,-0.8999471,-0.4359989,-2.4291313e-7]),
positions: new Float32Array([0,2.609,0,-0.368004,2.9959495,0.50652,-0.595448,2.9959495,-0.19346951,0,2.609,0,0.368004,2.9959495,0.50652,0,2.609,0,-0.595448,2.9959495,-0.19346951,0,2.9959495,-0.6260975,0,2.609,0,0.595448,2.9959495,-0.19346951,0,2.609,0,0,3.6220505,0.6260975,-0.595448,3.6220505,0.19346951,-0.368004,3.6220505,-0.50652,0.368004,3.6220505,-0.50652,0.595448,3.6220505,0.19346951,-0.368004,3.6220505,-0.50652,0,4.0090003,0,0,4.0090003,0,0,4.0090003,0,0,4.0090003,0,0,4.0090003,0,1,0,0,0,2.5,0,-4.3711392e-8,0,1,-1,0,-8.7422784e-8,-4.3711392e-8,0,1,1.19248815e-8,0,-1,1,0,0,1.19248815e-8,0,-1,-1,0,-8.7422784e-8]),
uvs: new Float32Array([0.00013659838,0.8180941,0.15755458,0.7272099,0.1575546,0.9089782,0.00013659043,0.6363257,0.15755458,0.54544157,0.0001365666,0.09102075,0.15755455,0.00013656964,0.15755457,0.18190491,0.00013657454,0.2727891,0.15755457,0.36367324,0.00013658249,0.45455742,0.31497157,0.6363257,0.31497157,0.8180941,0.31497154,0.09102073,0.31497154,0.27278906,0.31497154,0.45455742,0.31497157,0.9998634,0.47238955,0.72720987,0.47238958,0.9089782,0.47238955,0.1819049,0.47238955,0.36367324,0.47238955,0.54544157,0.8119813,0.33945516,0.642322,0.16979587,0.8119813,0.00013659486,0.47266275,0.00013660162,0.81198126,0.6790469,0.47266275,0.33972836,0.47266272,0.6790469,0.47266275,0.33945513,0.81198126,0.3397284]),
vertexCount: 31
});

View file

@ -0,0 +1,5 @@
import trianglething from "./trianglething";
import texture0 from "./textures/texture0.png";
import texture1 from "./textures/texture1.png";
export { trianglething, texture0, texture1 };

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,67 @@
ply
format ascii 1.0
comment Created in Blender version 3.6.4
element vertex 26
property float x
property float y
property float z
property float nx
property float ny
property float nz
property float s
property float t
element face 26
property list uchar uint vertex_indices
end_header
0 2.6090002 0 0 -1 8.3803394e-07 0.7660872 0.5526656
-0.36800402 2.9959497 0.50652003 -0.5257306 -0.44721383 0.723607 0.6449925 0.52286637
-0.5954481 2.9959497 -0.19346952 -0.8506533 -0.44721213 -0.2763879 0.8418907 0.33128682
0.36800402 2.9959497 0.50652003 0.5257306 -0.4472139 0.723607 0.60803074 0.79587877
0 2.9959497 -0.62609756 0 -0.44721153 -0.89442825 0.96344936 0.40123126
0.5954481 2.9959497 -0.19346952 0.8506533 -0.4472122 -0.27638793 0.8416727 0.64077806
0 3.6220508 0.62609756 0 0.44721153 0.89442825 0.50600564 0.49428308
-0.5954481 3.6220508 0.19346952 -0.8506533 0.44721216 0.27638793 0.704352 0.31297976
-0.36800402 3.6220508 -0.50652003 -0.5257306 0.4472139 -0.72360694 0.79145527 0.046412975
0.5954481 2.9959497 -0.19346952 0.8506533 -0.4472122 -0.27638793 0.35179207 0.26814616
0 2.9959497 -0.62609756 0 -0.44721153 -0.89442825 0.47356877 0.028599411
0.36800402 3.6220508 -0.50652003 0.5257306 0.4472139 -0.72360694 0.5382167 0.15491244
0.36800402 2.9959497 0.50652003 0.5257306 -0.4472139 0.723607 0.118150145 0.42324704
0.5954481 3.6220508 0.19346952 0.85065323 0.4472122 0.2763879 0.40614995 0.39580685
0 4.0090003 0 0 1 -8.165459e-07 0.5992601 0.26365823
1.0000001 0 0 0.8999471 -0.43599886 2.4163015e-07 0.4984935 0.5027367
0 2.5000002 0 -5.150958e-08 1 0 0.24900003 0.7522302
-4.3711395e-08 0 1.0000001 -3.0203772e-08 -0.4359989 0.8999472 -0.00049349666 0.50273675
-1.0000001 0 -8.742279e-08 -0.8999471 -0.4359989 -2.4291313e-07 -0.00049346685 1.0017238
-4.3711395e-08 0 1.0000001 -3.0203772e-08 -0.4359989 0.8999472 0.7633698 0.99398905
1.1924882e-08 0 -1.0000001 0 -0.43599886 -0.8999471 0.99752307 0.7598357
1.0000001 0 0 0.8999471 -0.43599886 2.4163015e-07 0.9975231 0.99398893
1.1924882e-08 0 -1.0000001 0 -0.43599886 -0.8999471 0.49849355 1.0017238
-4.3711395e-08 0 1.0000001 -3.0203772e-08 -0.4359989 0.8999472 0.99646366 0.7612665
-1.0000001 0 -8.742279e-08 -0.8999471 -0.4359989 -2.4291313e-07 0.99646366 0.9954198
1.1924882e-08 0 -1.0000001 0 -0.43599886 -0.8999471 0.7623104 0.9954198
3 0 1 2
3 1 0 3
3 0 2 4
3 0 4 5
3 0 5 3
3 1 3 6
3 2 1 7
3 4 2 8
3 9 10 11
3 12 9 13
3 1 6 7
3 2 7 8
3 10 8 11
3 9 11 13
3 12 13 6
3 7 6 14
3 8 7 14
3 11 8 14
3 13 11 14
3 6 13 14
3 15 16 17
3 17 16 18
3 19 20 21
3 18 16 22
3 22 16 15
3 23 24 25

View file

@ -0,0 +1,12 @@
import { Mesh } from "../../renderer/mesh";
// prettier-ignore
export default new Mesh({
colors: null,
faces: new Uint8Array([0,1,2,1,0,3,0,2,4,0,4,5,0,5,3,1,3,6,2,1,7,4,2,8,9,10,11,12,9,13,1,6,7,2,7,8,10,8,11,9,11,13,12,13,6,7,6,14,8,7,14,11,8,14,13,11,14,6,13,14,15,16,17,17,16,18,19,20,21,18,16,22,22,16,15,23,24,25]),
name: "src/meshes/trianglething/trianglething.ply",
normals: new Float32Array([0,-1,8.3803394e-7,-0.5257306,-0.44721383,0.723607,-0.8506533,-0.44721213,-0.2763879,0.5257306,-0.4472139,0.723607,0,-0.44721153,-0.89442825,0.8506533,-0.4472122,-0.27638793,0,0.44721153,0.89442825,-0.8506533,0.44721216,0.27638793,-0.5257306,0.4472139,-0.72360694,0.8506533,-0.4472122,-0.27638793,0,-0.44721153,-0.89442825,0.5257306,0.4472139,-0.72360694,0.5257306,-0.4472139,0.723607,0.85065323,0.4472122,0.2763879,0,1,-8.165459e-7,0.8999471,-0.43599886,2.4163015e-7,-5.150958e-8,1,0,-3.0203772e-8,-0.4359989,0.8999472,-0.8999471,-0.4359989,-2.4291313e-7,-3.0203772e-8,-0.4359989,0.8999472,0,-0.43599886,-0.8999471,0.8999471,-0.43599886,2.4163015e-7,0,-0.43599886,-0.8999471,-3.0203772e-8,-0.4359989,0.8999472,-0.8999471,-0.4359989,-2.4291313e-7,0,-0.43599886,-0.8999471]),
positions: new Float32Array([0,2.6090002,0,-0.36800402,2.9959497,0.50652003,-0.5954481,2.9959497,-0.19346952,0.36800402,2.9959497,0.50652003,0,2.9959497,-0.62609756,0.5954481,2.9959497,-0.19346952,0,3.6220508,0.62609756,-0.5954481,3.6220508,0.19346952,-0.36800402,3.6220508,-0.50652003,0.5954481,2.9959497,-0.19346952,0,2.9959497,-0.62609756,0.36800402,3.6220508,-0.50652003,0.36800402,2.9959497,0.50652003,0.5954481,3.6220508,0.19346952,0,4.0090003,0,1.0000001,0,0,0,2.5000002,0,-4.3711395e-8,0,1.0000001,-1.0000001,0,-8.742279e-8,-4.3711395e-8,0,1.0000001,1.1924882e-8,0,-1.0000001,1.0000001,0,0,1.1924882e-8,0,-1.0000001,-4.3711395e-8,0,1.0000001,-1.0000001,0,-8.742279e-8,1.1924882e-8,0,-1.0000001]),
uvs: new Float32Array([0.7660872,0.5526656,0.6449925,0.52286637,0.8418907,0.33128682,0.60803074,0.79587877,0.96344936,0.40123126,0.8416727,0.64077806,0.50600564,0.49428308,0.704352,0.31297976,0.79145527,0.046412975,0.35179207,0.26814616,0.47356877,0.028599411,0.5382167,0.15491244,0.118150145,0.42324704,0.40614995,0.39580685,0.5992601,0.26365823,0.4984935,0.5027367,0.24900003,0.7522302,-0.00049349666,0.50273675,-0.00049346685,1.0017238,0.7633698,0.99398905,0.99752307,0.7598357,0.9975231,0.99398893,0.49849355,1.0017238,0.99646366,0.7612665,0.99646366,0.9954198,0.7623104,0.9954198]),
vertexCount: 26
});

View file

@ -20,7 +20,8 @@ export class MeshRenderer extends Behavior {
normal?: WebGLBuffer;
color?: WebGLBuffer;
faces?: WebGLBuffer;
} = {};
textures: Record<string, WebGLTexture>;
} = { textures: {} };
faceDataType: number;
colorDataType: number | null;
@ -130,6 +131,72 @@ export class MeshRenderer extends Behavior {
this.app.gl.bindVertexArray(null);
}
async initializeTextures() {
const { gl } = this.app;
for (const [name, textureObject] of Object.entries(this.shader.textures)) {
await textureObject.loadImage();
const glTex = gl.createTexture();
if (!glTex) {
throw new Error("failed to allocate texture");
}
const tex = textureObject.texture as ImageBitmap;
gl.bindTexture(gl.TEXTURE_2D, glTex);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
textureObject.width,
textureObject.height,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
tex
);
// gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
this.buffers.textures[name] = glTex;
}
}
bindTextures() {
const { gl } = this.app;
const intStart = this.app.gl.TEXTURE0;
const textures = Object.entries(this.buffers.textures);
const destructors: (() => void)[] = [];
textures.forEach(([key, tex], index) => {
const uniform = (this.shader.mappings.uniforms as any)[key];
if (!uniform) {
console.warn("had no uniform to set for", {
textures,
key,
tex,
uniform,
index,
});
return false;
}
gl.activeTexture(intStart + index);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.uniform1i(uniform, index);
destructors.push(() => {
gl.activeTexture(intStart + index);
gl.bindTexture(gl.TEXTURE_2D, null);
});
});
return destructors;
}
bindAttrib(
buffer: WebGLBuffer,
attribute: string | number,
@ -178,7 +245,7 @@ export class MeshRenderer extends Behavior {
);
}
onStart(_: never, app: WebGLApp) {
async onStart(_: never, app: WebGLApp) {
app.loading("baking vectors");
app.telemetry?.addRenderers(1);
app.telemetry?.addTriangles(this.mesh.config.faces.length);
@ -196,6 +263,8 @@ export class MeshRenderer extends Behavior {
this.shader.link();
this.initializeBuffers();
this.shader.link();
await this.initializeTextures();
}
onRenderableUpdate(time: number, transform: Transform) {
@ -206,7 +275,7 @@ export class MeshRenderer extends Behavior {
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers.position || null);
this.initializeShader(time, transform);
const textureDestructors = this.bindTextures();
gl.drawElements(
this.config.drawMode ?? gl.TRIANGLES,
this.mesh.config.faces.length,
@ -225,5 +294,11 @@ export class MeshRenderer extends Behavior {
gl.bindVertexArray(null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
textureDestructors.forEach((i) => i());
}
}
const isPowerOfTwo = (x: number) => {
return (x & (x - 1)) === 0;
};

View file

@ -1,3 +1,4 @@
import { Texture } from "./texture";
import { WebGLApp } from "./webgl";
/**
@ -47,6 +48,7 @@ export class Shader {
private _app?: WebGLApp;
public program: WebGLProgram | null = null;
public mappings: InternalMapping = {} as any;
public textures: Record<string, Texture> = {};
get gl() {
const gl = this._app?.gl;
@ -118,6 +120,12 @@ export class Shader {
gl.attachShader(this.program as WebGLProgram, shader);
}
/// Slot must be the name of the relevant uniform pointer, e.g. texture0
addTexture(slot: string, texture: Texture) {
this.textures[slot] = texture;
return this;
}
compile() {
const gl = this.gl;
this.attach(gl.FRAGMENT_SHADER, this.fragmentCode);

View file

@ -9,6 +9,7 @@ export class Telemetry extends Behavior {
public activeTriangles: number = 0;
public activeVertexes: number = 0;
public activeRenderers: number = 0;
public activeTextures: number = 0;
constructor(
public app: WebGLApp,
@ -55,7 +56,9 @@ export class Telemetry extends Behavior {
this.app.registry.onAfterUpdate.length
} | d: ${this.app.registry.onDraw.length}<br />render :: mr: ${
this.activeRenderers
} | v: ${this.activeVertexes} | t: ${this.activeTriangles}`;
} | v: ${this.activeVertexes} | t: ${
this.activeTriangles
}<br />others :: tex: ${this.activeTextures}`;
}
onAfterUpdate(time: number) {
@ -75,4 +78,8 @@ export class Telemetry extends Behavior {
addRenderers(n: number) {
this.activeRenderers += n;
}
addTextures(n: number) {
this.activeTextures += n;
}
}

View file

@ -1,17 +1,73 @@
import { Behavior } from "./behavior";
import { WebGLApp } from "./webgl";
export class Texture extends Behavior {
public texture: Uint8Array | null = null;
export class Texture {
public texture: ImageBitmap | Uint8Array | null = null;
public width: number = 0;
public height: number = 0;
constructor(
public app: WebGLApp,
public url: string
) {
super(app);
) {}
setImage(data: Uint8Array, width: number, height: number) {
this.texture = data;
this.width = width;
this.height = height;
return this;
}
async onStart(_: never, app: WebGLApp) {
app.loading("Fetching textures...");
async loadImage() {
this.app.telemetry?.addTextures(-1);
this.app.loading("Fetching textures...");
if (this.url === "manual") {
if (this.texture === null) {
throw new Error("manual specified, but texture was not ready...");
}
return;
}
const image = new Image();
return new Promise((resolve, reject) => {
image.onload = async () => {
this.texture = await createImageBitmap(image, {
imageOrientation: "flipY",
});
this.width = this.texture.width;
this.height = this.texture.height;
this.app.telemetry?.addTextures(2);
resolve(void 0);
};
image.onerror = (e) => {
this.app.telemetry?.addTextures(1);
reject(
new Error(`texture load of ${this.url} failed: ${e.toString()}`)
);
};
image.src = this.url;
});
}
}
export const White = (app: WebGLApp) =>
new Texture(app, "manual").setImage(
new Uint8Array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
2,
2
);
export const Black = (app: WebGLApp) =>
new Texture(app, "manual").setImage(
new Uint8Array([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]),
2,
2
);
export const WhyBroke = (app: WebGLApp) =>
new Texture(app, "manual").setImage(
new Uint8Array([1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1]),
2,
2
);

View file

@ -46,6 +46,7 @@ export class WebGLApp {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
// this.gl.getExtension("OES_element_index_uint"); // default
this.gl.getExtension("EXT_texture_filter_anisotropic");
if (location.search.includes("telemetry")) {
this.telemetry = new Telemetry(this);