Skip to content

Commit f84772d

Browse files
authored
added nodeCoordinates to shaders (#658)
We already use this same concept on v3. We need nodeCoordinates so can accurately calculated the edges of nodes, we are currently doing these with textureCoords, but in case of sprites or images with textureOptions texturecoords can be different from what the shader expects them to be. resolves known issue(s): #357
2 parents 5cc4830 + c903884 commit f84772d

20 files changed

+141
-148
lines changed

src/core/lib/WebGlContextWrapper.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,53 @@ export class WebGlContextWrapper {
703703
gl.vertexAttribPointer(index, size, type, normalized, stride, offset);
704704
}
705705

706+
/**
707+
* Returns object with Attribute names as key and numbers as location values
708+
*
709+
* @param program
710+
* @returns object with numbers
711+
*/
712+
getUniformLocations(
713+
program: WebGLProgram,
714+
): Record<string, WebGLUniformLocation> {
715+
const gl = this.gl;
716+
const length = gl.getProgramParameter(
717+
program,
718+
gl.ACTIVE_UNIFORMS,
719+
) as number;
720+
const result = {} as Record<string, WebGLUniformLocation>;
721+
for (let i = 0; i < length; i++) {
722+
const info = gl.getActiveUniform(program, i) as WebGLActiveInfo;
723+
//remove bracket + value from uniform name;
724+
let name = info.name.replace(/\[.*?\]/g, '');
725+
result[name] = gl.getUniformLocation(
726+
program,
727+
name,
728+
) as WebGLUniformLocation;
729+
}
730+
return result;
731+
}
732+
733+
/**
734+
* Returns object with Attribute names as key and numbers as location values
735+
* @param program
736+
* @returns object with numbers
737+
*/
738+
getAttributeLocations(program: WebGLProgram): string[] {
739+
const gl = this.gl;
740+
const length = gl.getProgramParameter(
741+
program,
742+
gl.ACTIVE_ATTRIBUTES,
743+
) as number;
744+
745+
const result: string[] = [];
746+
for (let i = 0; i < length; i++) {
747+
const { name } = gl.getActiveAttrib(program, i) as WebGLActiveInfo;
748+
result[gl.getAttribLocation(program, name)] = name;
749+
}
750+
return result;
751+
}
752+
706753
/**
707754
* ```
708755
* gl.useProgram(program);

src/core/renderers/webgl/WebGlCoreRenderOp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export class WebGlCoreRenderOp extends CoreRenderOp {
8888
shader.bindRenderOp(this, shaderProps);
8989

9090
// TODO: Reduce calculations required
91-
const quadIdx = (this.bufferIdx / 24) * 6 * 2;
91+
const quadIdx = (this.bufferIdx / 32) * 6 * 2;
9292

9393
// Clipping
9494
if (this.clippingRect.valid) {

src/core/renderers/webgl/WebGlCoreRenderer.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
136136
this.defaultShader = this.defShaderCtrl.shader as WebGlCoreShader;
137137
const quadBuffer = glw.createBuffer();
138138
assertTruthy(quadBuffer);
139-
const stride = 6 * Float32Array.BYTES_PER_ELEMENT;
139+
const stride = 8 * Float32Array.BYTES_PER_ELEMENT;
140140
this.quadBufferCollection = new BufferCollection([
141141
{
142142
buffer: quadBuffer,
@@ -173,6 +173,14 @@ export class WebGlCoreRenderer extends CoreRenderer {
173173
stride,
174174
offset: 5 * Float32Array.BYTES_PER_ELEMENT,
175175
},
176+
a_nodeCoordinate: {
177+
name: 'a_nodeCoordinate',
178+
size: 2,
179+
type: glw.FLOAT,
180+
normalized: false,
181+
stride,
182+
offset: 6 * Float32Array.BYTES_PER_ELEMENT,
183+
},
176184
},
177185
},
178186
]);
@@ -346,6 +354,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
346354
fQuadBuffer[bufferIdx++] = texCoordY1; // texCoordY
347355
uiQuadBuffer[bufferIdx++] = params.colorTl; // color
348356
fQuadBuffer[bufferIdx++] = textureIdx; // texIndex
357+
fQuadBuffer[bufferIdx++] = 0;
358+
fQuadBuffer[bufferIdx++] = 0;
349359

350360
// Upper-Right
351361
fQuadBuffer[bufferIdx++] = params.renderCoords.x2;
@@ -354,6 +364,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
354364
fQuadBuffer[bufferIdx++] = texCoordY1;
355365
uiQuadBuffer[bufferIdx++] = params.colorTr;
356366
fQuadBuffer[bufferIdx++] = textureIdx;
367+
fQuadBuffer[bufferIdx++] = 1;
368+
fQuadBuffer[bufferIdx++] = 0;
357369

358370
// Lower-Left
359371
fQuadBuffer[bufferIdx++] = params.renderCoords.x4;
@@ -362,6 +374,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
362374
fQuadBuffer[bufferIdx++] = texCoordY2;
363375
uiQuadBuffer[bufferIdx++] = params.colorBl;
364376
fQuadBuffer[bufferIdx++] = textureIdx;
377+
fQuadBuffer[bufferIdx++] = 0;
378+
fQuadBuffer[bufferIdx++] = 1;
365379

366380
// Lower-Right
367381
fQuadBuffer[bufferIdx++] = params.renderCoords.x3;
@@ -370,6 +384,9 @@ export class WebGlCoreRenderer extends CoreRenderer {
370384
fQuadBuffer[bufferIdx++] = texCoordY2;
371385
uiQuadBuffer[bufferIdx++] = params.colorBr;
372386
fQuadBuffer[bufferIdx++] = textureIdx;
387+
388+
fQuadBuffer[bufferIdx++] = 1;
389+
fQuadBuffer[bufferIdx++] = 1;
373390
} else if (params.tb !== 0 || params.tc !== 0) {
374391
// Upper-Left
375392
fQuadBuffer[bufferIdx++] = params.tx; // vertexX
@@ -378,6 +395,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
378395
fQuadBuffer[bufferIdx++] = texCoordY1; // texCoordY
379396
uiQuadBuffer[bufferIdx++] = params.colorTl; // color
380397
fQuadBuffer[bufferIdx++] = textureIdx; // texIndex
398+
fQuadBuffer[bufferIdx++] = 0;
399+
fQuadBuffer[bufferIdx++] = 0;
381400

382401
// Upper-Right
383402
fQuadBuffer[bufferIdx++] = params.tx + params.width * params.ta;
@@ -386,6 +405,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
386405
fQuadBuffer[bufferIdx++] = texCoordY1;
387406
uiQuadBuffer[bufferIdx++] = params.colorTr;
388407
fQuadBuffer[bufferIdx++] = textureIdx;
408+
fQuadBuffer[bufferIdx++] = 1;
409+
fQuadBuffer[bufferIdx++] = 0;
389410

390411
// Lower-Left
391412
fQuadBuffer[bufferIdx++] = params.tx + params.height * params.tb;
@@ -394,6 +415,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
394415
fQuadBuffer[bufferIdx++] = texCoordY2;
395416
uiQuadBuffer[bufferIdx++] = params.colorBl;
396417
fQuadBuffer[bufferIdx++] = textureIdx;
418+
fQuadBuffer[bufferIdx++] = 0;
419+
fQuadBuffer[bufferIdx++] = 1;
397420

398421
// Lower-Right
399422
fQuadBuffer[bufferIdx++] =
@@ -404,6 +427,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
404427
fQuadBuffer[bufferIdx++] = texCoordY2;
405428
uiQuadBuffer[bufferIdx++] = params.colorBr;
406429
fQuadBuffer[bufferIdx++] = textureIdx;
430+
fQuadBuffer[bufferIdx++] = 1;
431+
fQuadBuffer[bufferIdx++] = 1;
407432
} else {
408433
// Calculate the right corner of the quad
409434
// multiplied by the scale
@@ -417,6 +442,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
417442
fQuadBuffer[bufferIdx++] = texCoordY1; // texCoordY
418443
uiQuadBuffer[bufferIdx++] = params.colorTl; // color
419444
fQuadBuffer[bufferIdx++] = textureIdx; // texIndex
445+
fQuadBuffer[bufferIdx++] = 0;
446+
fQuadBuffer[bufferIdx++] = 0;
420447

421448
// Upper-Right
422449
fQuadBuffer[bufferIdx++] = rightCornerX;
@@ -425,6 +452,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
425452
fQuadBuffer[bufferIdx++] = texCoordY1;
426453
uiQuadBuffer[bufferIdx++] = params.colorTr;
427454
fQuadBuffer[bufferIdx++] = textureIdx;
455+
fQuadBuffer[bufferIdx++] = 1;
456+
fQuadBuffer[bufferIdx++] = 0;
428457

429458
// Lower-Left
430459
fQuadBuffer[bufferIdx++] = params.tx;
@@ -433,6 +462,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
433462
fQuadBuffer[bufferIdx++] = texCoordY2;
434463
uiQuadBuffer[bufferIdx++] = params.colorBl;
435464
fQuadBuffer[bufferIdx++] = textureIdx;
465+
fQuadBuffer[bufferIdx++] = 0;
466+
fQuadBuffer[bufferIdx++] = 1;
436467

437468
// Lower-Right
438469
fQuadBuffer[bufferIdx++] = rightCornerX;
@@ -441,9 +472,10 @@ export class WebGlCoreRenderer extends CoreRenderer {
441472
fQuadBuffer[bufferIdx++] = texCoordY2;
442473
uiQuadBuffer[bufferIdx++] = params.colorBr;
443474
fQuadBuffer[bufferIdx++] = textureIdx;
475+
fQuadBuffer[bufferIdx++] = 1;
476+
fQuadBuffer[bufferIdx++] = 1;
444477
}
445478
// Update the length of the current render op
446-
this.curRenderOp.length += WORDS_PER_QUAD;
447479
this.curRenderOp.numQuads++;
448480
this.curBufferIdx = bufferIdx;
449481
}
@@ -595,7 +627,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
595627
this.quadBufferUsage = this.curBufferIdx * arr.BYTES_PER_ELEMENT;
596628

597629
// Calculate the size of each quad in bytes (4 vertices per quad) times the size of each vertex in bytes
598-
const QUAD_SIZE_IN_BYTES = 4 * (6 * arr.BYTES_PER_ELEMENT); // 6 attributes per vertex
630+
const QUAD_SIZE_IN_BYTES = 4 * (8 * arr.BYTES_PER_ELEMENT); // 8 attributes per vertex
599631
this.numQuadsRendered = this.quadBufferUsage / QUAD_SIZE_IN_BYTES;
600632
}
601633

src/core/renderers/webgl/WebGlCoreShader.ts

Lines changed: 27 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ export interface AlphaShaderProp {
6565
}
6666

6767
export abstract class WebGlCoreShader extends CoreShader {
68-
protected boundBufferCollection: BufferCollection | null = null;
6968
protected buffersBound = false;
7069
protected program: WebGLProgram;
7170
/**
@@ -77,11 +76,8 @@ export abstract class WebGlCoreShader extends CoreShader {
7776
protected vao: WebGLVertexArrayObject | undefined;
7877
protected renderer: WebGlCoreRenderer;
7978
protected glw: WebGlContextWrapper;
80-
protected attributeBuffers: Record<string, WebGLBuffer>;
81-
protected attributeLocations: Record<string, number>;
82-
protected attributeNames: string[];
79+
protected attributeLocations: string[];
8380
protected uniformLocations: Record<string, WebGLUniformLocation>;
84-
protected uniformTypes: Record<string, keyof UniformMethodMap>;
8581
readonly supportsIndexedTextures: boolean;
8682

8783
constructor(options: ShaderOptions) {
@@ -160,72 +156,20 @@ export abstract class WebGlCoreShader extends CoreShader {
160156
}
161157
this.program = program;
162158

163-
this.attributeLocations = {} as Record<string, number>;
164-
this.attributeBuffers = {} as Record<string, number>;
165-
this.attributeNames = [];
166-
167-
[...options.attributes].forEach((attributeName) => {
168-
const location = glw.getAttribLocation(this.program, attributeName);
169-
if (location < 0) {
170-
throw new Error(
171-
`${this.constructor.name}: Vertex shader must have an attribute "${attributeName}"!`,
172-
);
173-
}
174-
const buffer = glw.createBuffer();
175-
if (!buffer) {
176-
throw new Error(
177-
`${this.constructor.name}: Could not create buffer for attribute "${attributeName}"`,
178-
);
179-
}
180-
181-
this.attributeLocations[attributeName] = location;
182-
this.attributeBuffers[attributeName] = buffer;
183-
this.attributeNames.push(attributeName);
184-
});
185-
186-
this.uniformLocations = {} as Record<string, WebGLRenderingContext>;
187-
this.uniformTypes = {} as Record<string, keyof UniformMethodMap>;
188-
options.uniforms.forEach((uniform: UniformInfo) => {
189-
const location = glw.getUniformLocation(this.program, uniform.name);
190-
this.uniformTypes[uniform.name] = uniform.uniform;
191-
if (!location) {
192-
console.warn(
193-
`Shader "${this.constructor.name}" could not get uniform location for "${uniform.name}"`,
194-
);
195-
return;
196-
}
197-
this.uniformLocations[uniform.name] = location;
198-
});
199-
}
200-
201-
private bindBufferAttribute(
202-
location: number,
203-
buffer: WebGLBuffer,
204-
attribute: AttributeInfo,
205-
) {
206-
const { glw } = this;
207-
glw.enableVertexAttribArray(location);
208-
209-
glw.vertexAttribPointer(
210-
buffer,
211-
location,
212-
attribute.size,
213-
attribute.type,
214-
attribute.normalized,
215-
attribute.stride,
216-
attribute.offset,
217-
);
159+
this.attributeLocations = glw.getAttributeLocations(this.program);
160+
this.uniformLocations = glw.getUniformLocations(this.program);
218161
}
219162

220163
disableAttribute(location: number) {
221164
this.glw.disableVertexAttribArray(location);
222165
}
223166

224167
disableAttributes() {
225-
for (const loc in this.attributeLocations) {
226-
this.disableAttribute(this.attributeLocations[loc] as number);
168+
const glw = this.glw;
169+
const attribLen = this.attributeLocations.length;
170+
for (let i = 0; i < attribLen; i++) {
171+
glw.disableVertexAttribArray(i);
227172
}
228-
this.boundBufferCollection = null;
229173
}
230174

231175
/**
@@ -325,21 +269,29 @@ export abstract class WebGlCoreShader extends CoreShader {
325269
}
326270

327271
bindBufferCollection(buffer: BufferCollection) {
328-
if (this.boundBufferCollection === buffer) {
329-
return;
330-
}
331-
for (const attributeName in this.attributeLocations) {
332-
const resolvedBuffer = buffer.getBuffer(attributeName);
333-
const resolvedInfo = buffer.getAttributeInfo(attributeName);
334-
assertTruthy(resolvedBuffer, `Buffer for "${attributeName}" not found`);
335-
assertTruthy(resolvedInfo);
336-
this.bindBufferAttribute(
337-
this.attributeLocations[attributeName]!,
272+
const { glw } = this;
273+
const attribs = this.attributeLocations;
274+
const attribLen = attribs.length;
275+
276+
for (let i = 0; i < attribLen; i++) {
277+
const name = attribs[i]!;
278+
279+
const resolvedBuffer = buffer.getBuffer(name);
280+
const resolvedInfo = buffer.getAttributeInfo(name);
281+
if (resolvedBuffer === undefined || resolvedInfo === undefined) {
282+
continue;
283+
}
284+
glw.enableVertexAttribArray(i);
285+
glw.vertexAttribPointer(
338286
resolvedBuffer,
339-
resolvedInfo,
287+
i,
288+
resolvedInfo.size,
289+
resolvedInfo.type,
290+
resolvedInfo.normalized,
291+
resolvedInfo.stride,
292+
resolvedInfo.offset,
340293
);
341294
}
342-
this.boundBufferCollection = buffer;
343295
}
344296

345297
protected override bindProps(props: Record<string, unknown>) {

src/core/renderers/webgl/internal/ShaderUtils.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ export interface UniformInfo {
3737

3838
export interface ShaderOptions {
3939
renderer: WebGlCoreRenderer;
40-
attributes: string[];
41-
uniforms: UniformInfo[];
4240
shaderSources?: ShaderProgramSources;
4341
supportsIndexedTextures?: boolean;
4442
webgl1Extensions?: string[];

src/core/renderers/webgl/shaders/DefaultShader.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@ export class DefaultShader extends WebGlCoreShader {
2626
constructor(renderer: WebGlCoreRenderer) {
2727
super({
2828
renderer,
29-
attributes: ['a_position', 'a_textureCoordinate', 'a_color'],
30-
uniforms: [
31-
{ name: 'u_resolution', uniform: 'uniform2fv' },
32-
{ name: 'u_pixelRatio', uniform: 'uniform1f' },
33-
{ name: 'u_texture', uniform: 'uniform2fv' },
34-
],
3529
});
3630
}
3731

@@ -51,6 +45,7 @@ export class DefaultShader extends WebGlCoreShader {
5145
5246
attribute vec2 a_position;
5347
attribute vec2 a_textureCoordinate;
48+
attribute vec2 a_nodeCoordinate;
5449
attribute vec4 a_color;
5550
5651
uniform vec2 u_resolution;
@@ -59,13 +54,15 @@ export class DefaultShader extends WebGlCoreShader {
5954
6055
varying vec4 v_color;
6156
varying vec2 v_textureCoordinate;
57+
varying vec2 v_nodeCoordinate;
6258
6359
void main() {
6460
vec2 normalized = a_position * u_pixelRatio;
6561
vec2 screenSpace = vec2(2.0 / u_resolution.x, -2.0 / u_resolution.y);
6662
6763
v_color = a_color;
6864
v_textureCoordinate = a_textureCoordinate;
65+
v_nodeCoordinate = a_nodeCoordinate;
6966
7067
gl_Position = vec4(normalized.x * screenSpace.x - 1.0, normalized.y * -abs(screenSpace.y) + 1.0, 0.0, 1.0);
7168
gl_Position.y = -sign(screenSpace.y) * gl_Position.y;

0 commit comments

Comments
 (0)