UNPKG

5.15 kBJavaScriptView Raw
1import './index.mjs';
2import { uniformParsers } from './uniformParsers.mjs';
3import { mapSize } from './mapSize.mjs';
4
5function uboUpdate(_ud, _uv, _renderer, _syncData, buffer) {
6 _renderer.buffer.update(buffer);
7}
8const UBO_TO_SINGLE_SETTERS = {
9 float: `
10 data[offset] = v;
11 `,
12 vec2: `
13 data[offset] = v[0];
14 data[offset+1] = v[1];
15 `,
16 vec3: `
17 data[offset] = v[0];
18 data[offset+1] = v[1];
19 data[offset+2] = v[2];
20
21 `,
22 vec4: `
23 data[offset] = v[0];
24 data[offset+1] = v[1];
25 data[offset+2] = v[2];
26 data[offset+3] = v[3];
27 `,
28 mat2: `
29 data[offset] = v[0];
30 data[offset+1] = v[1];
31
32 data[offset+4] = v[2];
33 data[offset+5] = v[3];
34 `,
35 mat3: `
36 data[offset] = v[0];
37 data[offset+1] = v[1];
38 data[offset+2] = v[2];
39
40 data[offset + 4] = v[3];
41 data[offset + 5] = v[4];
42 data[offset + 6] = v[5];
43
44 data[offset + 8] = v[6];
45 data[offset + 9] = v[7];
46 data[offset + 10] = v[8];
47 `,
48 mat4: `
49 for(var i = 0; i < 16; i++)
50 {
51 data[offset + i] = v[i];
52 }
53 `
54};
55const GLSL_TO_STD40_SIZE = {
56 float: 4,
57 vec2: 8,
58 vec3: 12,
59 vec4: 16,
60 int: 4,
61 ivec2: 8,
62 ivec3: 12,
63 ivec4: 16,
64 uint: 4,
65 uvec2: 8,
66 uvec3: 12,
67 uvec4: 16,
68 bool: 4,
69 bvec2: 8,
70 bvec3: 12,
71 bvec4: 16,
72 mat2: 16 * 2,
73 mat3: 16 * 3,
74 mat4: 16 * 4
75};
76function createUBOElements(uniformData) {
77 const uboElements = uniformData.map((data) => ({
78 data,
79 offset: 0,
80 dataLen: 0,
81 dirty: 0
82 }));
83 let size = 0;
84 let chunkSize = 0;
85 let offset = 0;
86 for (let i = 0; i < uboElements.length; i++) {
87 const uboElement = uboElements[i];
88 size = GLSL_TO_STD40_SIZE[uboElement.data.type];
89 if (uboElement.data.size > 1) {
90 size = Math.max(size, 16) * uboElement.data.size;
91 }
92 uboElement.dataLen = size;
93 if (chunkSize % size !== 0 && chunkSize < 16) {
94 const lineUpValue = chunkSize % size % 16;
95 chunkSize += lineUpValue;
96 offset += lineUpValue;
97 }
98 if (chunkSize + size > 16) {
99 offset = Math.ceil(offset / 16) * 16;
100 uboElement.offset = offset;
101 offset += size;
102 chunkSize = size;
103 } else {
104 uboElement.offset = offset;
105 chunkSize += size;
106 offset += size;
107 }
108 }
109 offset = Math.ceil(offset / 16) * 16;
110 return { uboElements, size: offset };
111}
112function getUBOData(uniforms, uniformData) {
113 const usedUniformDatas = [];
114 for (const i in uniforms) {
115 if (uniformData[i]) {
116 usedUniformDatas.push(uniformData[i]);
117 }
118 }
119 usedUniformDatas.sort((a, b) => a.index - b.index);
120 return usedUniformDatas;
121}
122function generateUniformBufferSync(group, uniformData) {
123 if (!group.autoManage) {
124 return { size: 0, syncFunc: uboUpdate };
125 }
126 const usedUniformDatas = getUBOData(group.uniforms, uniformData);
127 const { uboElements, size } = createUBOElements(usedUniformDatas);
128 const funcFragments = [`
129 var v = null;
130 var v2 = null;
131 var cv = null;
132 var t = 0;
133 var gl = renderer.gl
134 var index = 0;
135 var data = buffer.data;
136 `];
137 for (let i = 0; i < uboElements.length; i++) {
138 const uboElement = uboElements[i];
139 const uniform = group.uniforms[uboElement.data.name];
140 const name = uboElement.data.name;
141 let parsed = false;
142 for (let j = 0; j < uniformParsers.length; j++) {
143 const uniformParser = uniformParsers[j];
144 if (uniformParser.codeUbo && uniformParser.test(uboElement.data, uniform)) {
145 funcFragments.push(`offset = ${uboElement.offset / 4};`, uniformParsers[j].codeUbo(uboElement.data.name, uniform));
146 parsed = true;
147 break;
148 }
149 }
150 if (!parsed) {
151 if (uboElement.data.size > 1) {
152 const size2 = mapSize(uboElement.data.type);
153 const rowSize = Math.max(GLSL_TO_STD40_SIZE[uboElement.data.type] / 16, 1);
154 const elementSize = size2 / rowSize;
155 const remainder = (4 - elementSize % 4) % 4;
156 funcFragments.push(`
157 cv = ud.${name}.value;
158 v = uv.${name};
159 offset = ${uboElement.offset / 4};
160
161 t = 0;
162
163 for(var i=0; i < ${uboElement.data.size * rowSize}; i++)
164 {
165 for(var j = 0; j < ${elementSize}; j++)
166 {
167 data[offset++] = v[t++];
168 }
169 offset += ${remainder};
170 }
171
172 `);
173 } else {
174 const template = UBO_TO_SINGLE_SETTERS[uboElement.data.type];
175 funcFragments.push(`
176 cv = ud.${name}.value;
177 v = uv.${name};
178 offset = ${uboElement.offset / 4};
179 ${template};
180 `);
181 }
182 }
183 }
184 funcFragments.push(`
185 renderer.buffer.update(buffer);
186 `);
187 return {
188 size,
189 syncFunc: new Function("ud", "uv", "renderer", "syncData", "buffer", funcFragments.join("\n"))
190 };
191}
192
193export { createUBOElements, generateUniformBufferSync, getUBOData };
194//# sourceMappingURL=generateUniformBufferSync.mjs.map
195
\No newline at end of file