-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathresource-manager.js
127 lines (108 loc) · 3.42 KB
/
resource-manager.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
class ResourceManager {
constructor(gl) {
this.gl = gl;
this.resources = new Map();
this.shaders = new Map();
this.programs = new Map();
}
async loadShader(name, type) {
try {
const response = await fetch(`shaders/${name}`);
if (!response.ok) {
throw new Error(`Failed to load shader: ${name}`);
}
const source = await response.text();
const shader = WebGLUtils.createShader(this.gl, type, source);
if (!shader) {
throw new Error(`Failed to compile shader: ${name}`);
}
this.shaders.set(name, shader);
return shader;
} catch (error) {
console.error(`Error loading shader: ${name}`, error);
throw error;
}
}
async createProgram(name, vertexShaderName, fragmentShaderName, transformFeedbackVaryings = null) {
try {
const vertexShader = await this.loadShader(`${vertexShaderName}.vert`, this.gl.VERTEX_SHADER);
const fragmentShader = await this.loadShader(`${fragmentShaderName}.frag`, this.gl.FRAGMENT_SHADER);
const program = WebGLUtils.createProgram(
this.gl,
vertexShader,
fragmentShader,
transformFeedbackVaryings
);
if (!program) {
throw new Error(`Failed to create program: ${name}`);
}
this.programs.set(name, program);
return program;
} catch (error) {
console.error(`Error creating program: ${name}`, error);
throw error;
}
}
createBuffer(data, usage = this.gl.DYNAMIC_COPY) {
const buffer = WebGLUtils.createBuffer(this.gl, data, usage);
this.resources.set(buffer, { type: 'buffer', data, usage });
return buffer;
}
createTexture(options = {}) {
const texture = WebGLUtils.createAndSetupTexture(this.gl, options);
this.resources.set(texture, { type: 'texture', ...options });
return texture;
}
createFramebuffer() {
const framebuffer = this.gl.createFramebuffer();
this.resources.set(framebuffer, { type: 'framebuffer' });
return framebuffer;
}
deleteResource(resource) {
const resourceInfo = this.resources.get(resource);
if (!resourceInfo) return;
const gl = this.gl;
switch (resourceInfo.type) {
case 'texture':
gl.deleteTexture(resource);
break;
case 'buffer':
gl.deleteBuffer(resource);
break;
case 'framebuffer':
gl.deleteFramebuffer(resource);
break;
}
this.resources.delete(resource);
}
dispose() {
const gl = this.gl;
// Delete all resources
this.resources.forEach((info, resource) => {
this.deleteResource(resource);
});
// Delete all shaders
this.shaders.forEach(shader => {
gl.deleteShader(shader);
});
this.shaders.clear();
// Delete all programs
this.programs.forEach(program => {
gl.deleteProgram(program);
});
this.programs.clear();
}
// Utility methods
getProgram(name) {
return this.programs.get(name);
}
hasProgram(name) {
return this.programs.has(name);
}
getShader(name) {
return this.shaders.get(name);
}
hasShader(name) {
return this.shaders.has(name);
}
}