1
0
mirror of https://github.com/psychopy/psychojs.git synced 2025-05-10 18:50:54 +00:00

Merge pull request #513 from lightest/imagestim_interpolation_support

Interpolation support for ImageStim and solution for shared resources
This commit is contained in:
Alain Pitiot 2022-06-28 08:11:26 +02:00 committed by GitHub
commit fa731254bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 10 deletions

View File

@ -695,11 +695,15 @@ export class GratingStim extends VisualStim
if (this._tex instanceof HTMLImageElement)
{
// Not using PIXI.Texture.from() on purpose, as it caches both PIXI.Texture and PIXI.BaseTexture.
// As a result of that we can have multiple GratingStim instances using same PIXI.BaseTexture,
// thus changing texture related properties like interpolation, or calling _pixi.destroy(true)
// will affect all GratingStims who happen to share that BaseTexture.
shaderName = "imageShader";
let shaderTex = PIXI.Texture.from(this._tex, {
let shaderTex = new PIXI.Texture(new PIXI.BaseTexture(this._tex, {
wrapMode: PIXI.WRAP_MODES.REPEAT,
scaleMode: this._interpolate ? PIXI.SCALE_MODES.LINEAR : PIXI.SCALE_MODES.NEAREST
});
}));
shaderUniforms = {
uTex: shaderTex,
uFreq: this._SF,
@ -725,7 +729,8 @@ export class GratingStim extends VisualStim
{
if (this._mask instanceof HTMLImageElement)
{
this._pixi.mask = PIXI.Sprite.from(this._mask);
// Building new PIXI.BaseTexture each time we create a mask. See notes on shader texture creation above.
this._pixi.mask = PIXI.Sprite.from(new PIXI.Texture(new PIXI.BaseTexture(this._mask)));
this._pixi.mask.width = this._size_px[0];
this._pixi.mask.height = this._size_px[1];
this._pixi.addChild(this._pixi.mask);

View File

@ -78,8 +78,7 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin)
this._addAttribute(
"interpolate",
interpolate,
false,
this._onChange(true, false),
false
);
this._addAttribute(
"flipHoriz",
@ -223,6 +222,22 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin)
}
}
/**
* Whether to interpolate (linearly) the texture in the stimulus.
*
* @name module:visual.ImageStim#setInterpolate
* @public
* @param {boolean} interpolate - interpolate or not.
* @param {boolean} [log=false] - whether or not to log
*/
setInterpolate (interpolate = false, log = false) {
this._setAttribute("interpolate", interpolate, log);
if (this._pixi instanceof PIXI.Sprite) {
this._pixi.texture.baseTexture.scaleMode = interpolate ? PIXI.SCALE_MODES.LINEAR : PIXI.SCALE_MODES.NEAREST;
this._pixi.texture.baseTexture.update();
}
}
/**
* Estimate the bounding box.
*
@ -281,13 +296,24 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin)
// deal with both static images and videos:
if (this._image instanceof HTMLImageElement)
{
this._texture = PIXI.Texture.from(this._image);
// const baseTexture = new PIXI.BaseTexture(this._image);
// this._texture = new PIXI.Texture(baseTexture);
// Not using PIXI.Texture.from() on purpose, as it caches both PIXI.Texture and PIXI.BaseTexture.
// As a result of that we can have multiple ImageStim instances using same PIXI.BaseTexture,
// thus changing texture related properties like interpolation, or calling _pixi.destroy(true)
// will affect all ImageStims who happen to share that BaseTexture.
const texOpts =
{
scaleMode: this._interpolate ? PIXI.SCALE_MODES.LINEAR : PIXI.SCALE_MODES.NEAREST
};
this._texture = new PIXI.Texture(new PIXI.BaseTexture(this._image, texOpts));
}
else if (this._image instanceof HTMLVideoElement)
{
this._texture = PIXI.Texture.from(this._image, { resourceOptions: { autoPlay: true } });
const texOpts =
{
resourceOptions: { autoPlay: true },
scaleMode: this._interpolate ? PIXI.SCALE_MODES.LINEAR : PIXI.SCALE_MODES.NEAREST
};
this._texture = new PIXI.Texture(new PIXI.BaseTexture(this._image, texOpts));
}
this._pixi = PIXI.Sprite.from(this._texture);
@ -295,7 +321,8 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin)
// add a mask if need be:
if (typeof this._mask !== "undefined")
{
this._pixi.mask = PIXI.Sprite.from(this._mask);
// Building new PIXI.BaseTexture each time we create a mask. See notes on this._texture creation above.
this._pixi.mask = PIXI.Sprite.from(new PIXI.Texture(new PIXI.BaseTexture(this._mask)));
// a 0.5, 0.5 anchor is required for the mask to be aligned with the image
this._pixi.mask.anchor.x = 0.5;