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) 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"; shaderName = "imageShader";
let shaderTex = PIXI.Texture.from(this._tex, { let shaderTex = new PIXI.Texture(new PIXI.BaseTexture(this._tex, {
wrapMode: PIXI.WRAP_MODES.REPEAT, wrapMode: PIXI.WRAP_MODES.REPEAT,
scaleMode: this._interpolate ? PIXI.SCALE_MODES.LINEAR : PIXI.SCALE_MODES.NEAREST scaleMode: this._interpolate ? PIXI.SCALE_MODES.LINEAR : PIXI.SCALE_MODES.NEAREST
}); }));
shaderUniforms = { shaderUniforms = {
uTex: shaderTex, uTex: shaderTex,
uFreq: this._SF, uFreq: this._SF,
@ -725,7 +729,8 @@ export class GratingStim extends VisualStim
{ {
if (this._mask instanceof HTMLImageElement) 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.width = this._size_px[0];
this._pixi.mask.height = this._size_px[1]; this._pixi.mask.height = this._size_px[1];
this._pixi.addChild(this._pixi.mask); this._pixi.addChild(this._pixi.mask);

View File

@ -78,8 +78,7 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin)
this._addAttribute( this._addAttribute(
"interpolate", "interpolate",
interpolate, interpolate,
false, false
this._onChange(true, false),
); );
this._addAttribute( this._addAttribute(
"flipHoriz", "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. * Estimate the bounding box.
* *
@ -281,13 +296,24 @@ export class ImageStim extends util.mix(VisualStim).with(ColorMixin)
// deal with both static images and videos: // deal with both static images and videos:
if (this._image instanceof HTMLImageElement) if (this._image instanceof HTMLImageElement)
{ {
this._texture = PIXI.Texture.from(this._image); // Not using PIXI.Texture.from() on purpose, as it caches both PIXI.Texture and PIXI.BaseTexture.
// const baseTexture = new PIXI.BaseTexture(this._image); // As a result of that we can have multiple ImageStim instances using same PIXI.BaseTexture,
// this._texture = new PIXI.Texture(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) 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); 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: // add a mask if need be:
if (typeof this._mask !== "undefined") 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 // a 0.5, 0.5 anchor is required for the mask to be aligned with the image
this._pixi.mask.anchor.x = 0.5; this._pixi.mask.anchor.x = 0.5;