- 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
- 128
import { Redirect } from './Redirect';
import { ViewableBuffer } from '@pixi/core';
import type { DisplayObject } from '@pixi/display';
import type { TYPES } from '@pixi/constants';
export interface IAttributeRedirectOptions
{
source: string | ((db: DisplayObject) => any);
attrib: string;
type: string;
size?: number | '%notarray%';
glType: number;
glSize: number;
normalize?: boolean;
}
/**
* This redirect defines an attribute of a display-object's geometry. The attribute
* data is expected to be stored in a `PIXI.ViewableBuffer`, in an array, or (if
* just one element) as the property itself.
*
* @example
* // This attribute redirect calculates the tint used on top of a texture. Since the
* // tintMode can change anytime, it is better to use a derived source (function).
* //
* // Furthermore, the color is uploaded as four bytes (`attribute vec4 aTint`) while the
* // source returns an integer. This is done by splitting the 32-bit integer into four
* // 8-bit bytes.
* new AttributeRedirect({
* source: (tgt: ExampleDisplay) => (tgt.alpha < 1.0 && tgt.tintMode === PREMULTIPLY)
* ? premultiplyTint(tgt.rgb, tgt.alpha)
* : tgt.rgb + (tgt.alpha << 24);
* attrib: 'aTint',
* type: 'int32',
* size: '%notarray%', // optional/default
* glType: PIXI.TYPES.UNSIGNED_BYTE,
* glSize: 4,
* normalize: true // We are using [0, 255] range for RGBA here. Must normalize to [0, 1].
* });
*/
export class AttributeRedirect extends Redirect
{
/**
* The type of data stored in the source buffer. This can be any of: `int8`, `uint8`,
* `int16`, `uint16`, `int32`, `uint32`, or (by default) `float32`.
*
* @member {string}
* @see [PIXI.ViewableBuffer#view]{@link https://pixijs.download/dev/docs/PIXI.ViewableBuffer.html}
* @default 'float32'
*/
public type: string;
/**
* Number of elements to extract out of `source` with
* the given view type, for one vertex.
*
* If source isn't an array (only one element), then
* you can set this to `'%notarray%'`.
*
* @member {number | '%notarray%'}
*/
public size: number | '%notarray%';
/**
* Type of attribute, when uploading.
*
* Normally, you would use the corresponding type for
* the view on source. However, to speed up uploads
* you can aggregate attribute values in larger data
* types. For example, an RGBA vec4 (byte-sized channels)
* can be represented as one `Uint32`, while having
* a `glType` of `UNSIGNED_BYTE`.
*/
public glType: TYPES;
/**
* Size of attribute in terms of `glType`.
*
* Note that `glSize * glType <= size * type`
*
* @readonly
*/
public glSize: number;
/**
* Whether to normalize the attribute values.
*
* @readonly
*/
public normalize: boolean;
/** This is equal to `size` or 1 if size is `%notarray%`. */
public properSize: number;
/**
* @param {object} options
* @param {string | Function} options.source - redirect source
* @param {string} options.attrib - shader attribute variable
* @param {string}[options.type='float32'] - the type of data stored in the source
* @param {number | '%notarray%'}[options.size=0] - size of the source array ('%notarray' if not an array & just one element)
* @param {PIXI.TYPES}[options.glType=PIXI.TYPES.FLOAT] - data format to be uploaded in
* @param {number} options.glSize - number of elements to be uploaded as (size of source and upload must match)
* @param {boolean}[options.normalize=false] - whether to normalize the data before uploading
*/
constructor(options: IAttributeRedirectOptions)
{
super(options.source, options.attrib);
this.type = options.type;
this.size = options.size;
this.properSize = (options.size === '%notarray%' || options.size === undefined) ? 1 : options.size;
this.glType = options.glType;
this.glSize = options.glSize;
this.normalize = !!options.normalize;
}
static vertexSizeFor(attributeRedirects: Array<AttributeRedirect>): number
{
return attributeRedirects.reduce(
(acc, redirect) =>
(ViewableBuffer.sizeOf(redirect.type)
* redirect.properSize)
+ acc,
0);
}
}