mirror of
https://github.com/psychopy/psychojs.git
synced 2025-05-10 10:40:54 +00:00
Merge pull request #493 from lightest/1yn08hm_gamma_and_grating_improvements
Further GratingStim development.
This commit is contained in:
commit
49e645f280
@ -101,7 +101,7 @@ export class MinimalStim extends PsychObject
|
||||
}
|
||||
else
|
||||
{
|
||||
this.win._rootContainer.addChild(this._pixi);
|
||||
this._win.addPixiObject(this._pixi);
|
||||
this.win._drawList.push(this);
|
||||
}
|
||||
}
|
||||
@ -111,9 +111,9 @@ export class MinimalStim extends PsychObject
|
||||
// from the window container, update it, then put it back:
|
||||
if (this._needUpdate && typeof this._pixi !== "undefined")
|
||||
{
|
||||
this.win._rootContainer.removeChild(this._pixi);
|
||||
this._win.removePixiObject(this._pixi);
|
||||
this._updateIfNeeded();
|
||||
this.win._rootContainer.addChild(this._pixi);
|
||||
this._win.addPixiObject(this._pixi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -140,7 +140,7 @@ export class MinimalStim extends PsychObject
|
||||
// if the stimulus has a pixi representation, remove it from the root container:
|
||||
if (typeof this._pixi !== "undefined")
|
||||
{
|
||||
this._win._rootContainer.removeChild(this._pixi);
|
||||
this._win.removePixiObject(this._pixi);
|
||||
}
|
||||
}
|
||||
this.status = PsychoJS.Status.STOPPED;
|
||||
|
@ -26,7 +26,8 @@ import { Logger } from "./Logger.js";
|
||||
* @param {string} [options.name] the name of the window
|
||||
* @param {boolean} [options.fullscr= false] whether or not to go fullscreen
|
||||
* @param {Color} [options.color= Color('black')] the background color of the window
|
||||
* @param {number} [options.gamma= 1] sets the delimiter for gamma correction. In other words gamma correction is calculated as pow(rgb, 1/gamma)
|
||||
* @param {number} [options.gamma= 1] sets the divisor for gamma correction. In other words gamma correction is calculated as pow(rgb, 1/gamma)
|
||||
* @param {number} [options.contrast= 1] sets the contrast value
|
||||
* @param {string} [options.units= 'pix'] the units of the window
|
||||
* @param {boolean} [options.waitBlanking= false] whether or not to wait for all rendering operations to be done
|
||||
* before flipping
|
||||
@ -52,6 +53,7 @@ export class Window extends PsychObject
|
||||
fullscr = false,
|
||||
color = new Color("black"),
|
||||
gamma = 1,
|
||||
contrast = 1,
|
||||
units = "pix",
|
||||
waitBlanking = false,
|
||||
autoLog = true,
|
||||
@ -64,17 +66,25 @@ export class Window extends PsychObject
|
||||
|
||||
// storing AdjustmentFilter instance to access later;
|
||||
this._adjustmentFilter = new AdjustmentFilter({
|
||||
gamma
|
||||
gamma,
|
||||
contrast
|
||||
});
|
||||
|
||||
// list of all elements, in the order they are currently drawn:
|
||||
this._drawList = [];
|
||||
|
||||
this._addAttribute("fullscr", fullscr);
|
||||
this._addAttribute("color", color);
|
||||
this._addAttribute("color", color, new Color("black"), () => {
|
||||
if (this._backgroundSprite) {
|
||||
this._backgroundSprite.tint = color.int;
|
||||
}
|
||||
});
|
||||
this._addAttribute("gamma", gamma, 1, () => {
|
||||
this._adjustmentFilter.gamma = this._gamma;
|
||||
});
|
||||
this._addAttribute("contrast", contrast, 1, () => {
|
||||
this._adjustmentFilter.contrast = this._contrast;
|
||||
});
|
||||
this._addAttribute("units", units);
|
||||
this._addAttribute("waitBlanking", waitBlanking);
|
||||
this._addAttribute("autoLog", autoLog);
|
||||
@ -295,6 +305,28 @@ export class Window extends PsychObject
|
||||
this._flipCallbacks.push({ function: flipCallback, arguments: flipCallbackArgs });
|
||||
}
|
||||
|
||||
/**
|
||||
* Add PIXI.DisplayObject to the container displayed on the scene (window)
|
||||
*
|
||||
* @name module:core.Window#addPixiObject
|
||||
* @function
|
||||
* @public
|
||||
*/
|
||||
addPixiObject (pixiObject) {
|
||||
this._stimsContainer.addChild(pixiObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove PIXI.DisplayObject from the container displayed on the scene (window)
|
||||
*
|
||||
* @name module:core.Window#removePixiObject
|
||||
* @function
|
||||
* @public
|
||||
*/
|
||||
removePixiObject (pixiObject) {
|
||||
this._stimsContainer.removeChild(pixiObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the stimuli onto the canvas.
|
||||
*
|
||||
@ -382,9 +414,9 @@ export class Window extends PsychObject
|
||||
{
|
||||
if (stimulus._needUpdate && typeof stimulus._pixi !== "undefined")
|
||||
{
|
||||
this._rootContainer.removeChild(stimulus._pixi);
|
||||
this._stimsContainer.removeChild(stimulus._pixi);
|
||||
stimulus._updateIfNeeded();
|
||||
this._rootContainer.addChild(stimulus._pixi);
|
||||
this._stimsContainer.addChild(stimulus._pixi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -429,6 +461,7 @@ export class Window extends PsychObject
|
||||
width: this._size[0],
|
||||
height: this._size[1],
|
||||
backgroundColor: this.color.int,
|
||||
powerPreference: "high-performance",
|
||||
resolution: window.devicePixelRatio,
|
||||
});
|
||||
this._renderer.view.style.transform = "translatez(0)";
|
||||
@ -438,11 +471,30 @@ export class Window extends PsychObject
|
||||
// we also change the background color of the body since the dialog popup may be longer than the window's height:
|
||||
document.body.style.backgroundColor = this._color.hex;
|
||||
|
||||
// filters in PIXI work in a slightly unexpected fashion:
|
||||
// when setting this._rootContainer.filters, filtering itself
|
||||
// ignores backgroundColor of this._renderer and in addition to that
|
||||
// all child elements of this._rootContainer ignore backgroundColor when blending.
|
||||
// To circumvent that creating a separate PIXI.Sprite that serves as background color.
|
||||
// Then placing all Stims to a separate this._stimsContainer which hovers on top of
|
||||
// background sprite so that if we need to move all stims at once, the background sprite
|
||||
// won't get affected.
|
||||
this._backgroundSprite = new PIXI.Sprite(PIXI.Texture.WHITE);
|
||||
this._backgroundSprite.tint = this.color.int;
|
||||
this._backgroundSprite.width = this._size[0];
|
||||
this._backgroundSprite.height = this._size[1];
|
||||
this._backgroundSprite.anchor.set(.5);
|
||||
this._stimsContainer = new PIXI.Container();
|
||||
this._stimsContainer.sortableChildren = true;
|
||||
|
||||
// create a top-level PIXI container:
|
||||
this._rootContainer = new PIXI.Container();
|
||||
this._rootContainer.addChild(this._backgroundSprite, this._stimsContainer);
|
||||
|
||||
// sorts children according to their zIndex value. Higher zIndex means it will be moved towards the end of the array,
|
||||
// and thus rendered on top of previous one.
|
||||
this._rootContainer.sortableChildren = true;
|
||||
|
||||
this._rootContainer.interactive = true;
|
||||
this._rootContainer.filters = [this._adjustmentFilter];
|
||||
|
||||
|
@ -127,6 +127,8 @@ export class Color
|
||||
{
|
||||
this._rgb = obj._rgb.slice();
|
||||
}
|
||||
|
||||
this._rgbFull = this._rgb.map(c => c * 2 - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,6 +144,19 @@ export class Color
|
||||
return this._rgb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the [-1,1] RGB triplet equivalent of this Color.
|
||||
*
|
||||
* @name module:util.Color.rgbFull
|
||||
* @function
|
||||
* @public
|
||||
* @return {Array.<number>} the [-1,1] RGB triplet equivalent
|
||||
*/
|
||||
get rgbFull()
|
||||
{
|
||||
return this._rgbFull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the [0,255] RGB triplet equivalent of this Color.
|
||||
*
|
||||
|
@ -1009,8 +1009,8 @@ export class Form extends util.mix(VisualStim).with(ColorMixin)
|
||||
this._stimuliClipMask.clear();
|
||||
this._stimuliClipMask.beginFill(0xFFFFFF);
|
||||
this._stimuliClipMask.drawRect(
|
||||
this._win._rootContainer.position.x + this._leftEdge_px + 2,
|
||||
this._win._rootContainer.position.y + this._bottomEdge_px + 2,
|
||||
this._win._stimsContainer.position.x + this._leftEdge_px + 2,
|
||||
this._win._stimsContainer.position.y + this._bottomEdge_px + 2,
|
||||
this._size_px[0] - 4,
|
||||
this._size_px[1] - 6,
|
||||
);
|
||||
|
@ -8,8 +8,8 @@
|
||||
*/
|
||||
|
||||
import * as PIXI from "pixi.js-legacy";
|
||||
import {AdjustmentFilter} from "@pixi/filter-adjustment";
|
||||
import { Color } from "../util/Color.js";
|
||||
import { ColorMixin } from "../util/ColorMixin.js";
|
||||
import { to_pixiPoint } from "../util/Pixi.js";
|
||||
import * as util from "../util/Util.js";
|
||||
import { VisualStim } from "./VisualStim.js";
|
||||
@ -32,7 +32,6 @@ import raisedCosShader from "./shaders/raisedCosShader.frag";
|
||||
* @name module:visual.GratingStim
|
||||
* @class
|
||||
* @extends VisualStim
|
||||
* @mixes ColorMixin
|
||||
* @param {Object} options
|
||||
* @param {String} options.name - the name used when logging messages from this stimulus
|
||||
* @param {Window} options.win - the associated Window
|
||||
@ -40,21 +39,21 @@ import raisedCosShader from "./shaders/raisedCosShader.frag";
|
||||
* @param {String | HTMLImageElement} [options.mask] - the name of the mask resource or HTMLImageElement corresponding to the mask
|
||||
* @param {String} [options.units= "norm"] - the units of the stimulus (e.g. for size, position, vertices)
|
||||
* @param {number} [options.sf=1.0] - spatial frequency of the function used in grating stimulus
|
||||
* @param {number} [options.phase=1.0] - phase of the function used in grating stimulus
|
||||
* @param {number} [options.phase=0.0] - phase of the function used in grating stimulus, multiples of period of that function
|
||||
* @param {Array.<number>} [options.pos= [0, 0]] - the position of the center of the stimulus
|
||||
* @param {number} [options.ori= 0.0] - the orientation (in degrees)
|
||||
* @param {number} [options.size] - the size of the rendered image (DEFAULT_STIM_SIZE_PX will be used if size is not specified)
|
||||
* @param {Color} [options.color= "white"] the background color
|
||||
* @param {number} [options.opacity= 1.0] - the opacity
|
||||
* @param {number} [options.contrast= 1.0] - the contrast
|
||||
* @param {Color} [options.color= "white"] - Foreground color of the stimulus. Can be String like "red" or "#ff0000" or Number like 0xff0000.
|
||||
* @param {number} [options.opacity= 1.0] - Set the opacity of the stimulus. Determines how visible the stimulus is relative to background.
|
||||
* @param {number} [options.contrast= 1.0] - Set the contrast of the stimulus, i.e. scales how far the stimulus deviates from the middle grey. Ranges [-1, 1].
|
||||
* @param {number} [options.depth= 0] - the depth (i.e. the z order)
|
||||
* @param {boolean} [options.interpolate= false] - whether or not the image is interpolated. NOT IMPLEMENTED YET.
|
||||
* @param {String} [options.blendmode= 'avg'] - blend mode of the stimulus, determines how the stimulus is blended with the background. NOT IMPLEMENTED YET.
|
||||
* @param {boolean} [options.interpolate= false] - Whether to interpolate (linearly) the texture in the stimulus. Currently supports only image based gratings.
|
||||
* @param {String} [options.blendmode= "avg"] - blend mode of the stimulus, determines how the stimulus is blended with the background. Supported values: "avg", "add", "mul", "screen".
|
||||
* @param {boolean} [options.autoDraw= false] - whether or not the stimulus should be automatically drawn on every frame flip
|
||||
* @param {boolean} [options.autoLog= false] - whether or not to log
|
||||
*/
|
||||
|
||||
export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
export class GratingStim extends VisualStim
|
||||
{
|
||||
/**
|
||||
* An object that keeps shaders source code and default uniform values for them.
|
||||
@ -142,21 +141,24 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
shader: sinShader,
|
||||
uniforms: {
|
||||
uFreq: 1.0,
|
||||
uPhase: 0.0
|
||||
uPhase: 0.0,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
sqr: {
|
||||
shader: sqrShader,
|
||||
uniforms: {
|
||||
uFreq: 1.0,
|
||||
uPhase: 0.0
|
||||
uPhase: 0.0,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
saw: {
|
||||
shader: sawShader,
|
||||
uniforms: {
|
||||
uFreq: 1.0,
|
||||
uPhase: 0.0
|
||||
uPhase: 0.0,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
tri: {
|
||||
@ -164,27 +166,31 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
uniforms: {
|
||||
uFreq: 1.0,
|
||||
uPhase: 0.0,
|
||||
uPeriod: 1.0
|
||||
uPeriod: 1.0,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
sinXsin: {
|
||||
shader: sinXsinShader,
|
||||
uniforms: {
|
||||
uFreq: 1.0,
|
||||
uPhase: 0.0
|
||||
uPhase: 0.0,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
sqrXsqr: {
|
||||
shader: sqrXsqrShader,
|
||||
uniforms: {
|
||||
uFreq: 1.0,
|
||||
uPhase: 0.0
|
||||
uPhase: 0.0,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
circle: {
|
||||
shader: circleShader,
|
||||
uniforms: {
|
||||
uRadius: 1.0
|
||||
uRadius: 1.0,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
gauss: {
|
||||
@ -192,26 +198,30 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
uniforms: {
|
||||
uA: 1.0,
|
||||
uB: 0.0,
|
||||
uC: 0.16
|
||||
uC: 0.16,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
cross: {
|
||||
shader: crossShader,
|
||||
uniforms: {
|
||||
uThickness: 0.2
|
||||
uThickness: 0.2,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
radRamp: {
|
||||
shader: radRampShader,
|
||||
uniforms: {
|
||||
uSqueeze: 1.0
|
||||
uSqueeze: 1.0,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
},
|
||||
raisedCos: {
|
||||
shader: raisedCosShader,
|
||||
uniforms: {
|
||||
uBeta: 0.25,
|
||||
uPeriod: 0.625
|
||||
uPeriod: 0.625,
|
||||
uColor: [1., 1., 1.]
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -224,6 +234,13 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
*/
|
||||
static #DEFAULT_STIM_SIZE_PX = [256, 256]; // in pixels
|
||||
|
||||
static #BLEND_MODES_MAP = {
|
||||
avg: PIXI.BLEND_MODES.NORMAL,
|
||||
add: PIXI.BLEND_MODES.ADD,
|
||||
mul: PIXI.BLEND_MODES.MULTIPLY,
|
||||
screen: PIXI.BLEND_MODES.SCREEN
|
||||
};
|
||||
|
||||
constructor({
|
||||
name,
|
||||
tex = "sin",
|
||||
@ -238,7 +255,7 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
color,
|
||||
colorSpace,
|
||||
opacity,
|
||||
contrast,
|
||||
contrast = 1,
|
||||
depth,
|
||||
interpolate,
|
||||
blendmode,
|
||||
@ -249,42 +266,20 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
{
|
||||
super({ name, win, units, ori, opacity, depth, pos, size, autoDraw, autoLog });
|
||||
|
||||
this._addAttribute(
|
||||
"tex",
|
||||
tex,
|
||||
);
|
||||
this._addAttribute(
|
||||
"mask",
|
||||
mask,
|
||||
);
|
||||
this._addAttribute(
|
||||
"SF",
|
||||
sf,
|
||||
GratingStim.#SHADERS[tex] ? GratingStim.#SHADERS[tex].uniforms.uFreq || 1.0 : 1.0
|
||||
);
|
||||
this._addAttribute(
|
||||
"phase",
|
||||
phase,
|
||||
GratingStim.#SHADERS[tex] ? GratingStim.#SHADERS[tex].uniforms.uPhase || 0.0 : 0.0
|
||||
);
|
||||
this._addAttribute(
|
||||
"color",
|
||||
color,
|
||||
"white",
|
||||
this._onChange(true, false),
|
||||
);
|
||||
this._addAttribute(
|
||||
"contrast",
|
||||
contrast,
|
||||
1.0,
|
||||
this._onChange(true, false),
|
||||
);
|
||||
this._addAttribute(
|
||||
"interpolate",
|
||||
interpolate,
|
||||
false,
|
||||
this._onChange(true, false),
|
||||
);
|
||||
this._adjustmentFilter = new AdjustmentFilter({
|
||||
contrast
|
||||
});
|
||||
this._addAttribute("tex", tex);
|
||||
this._addAttribute("mask", mask);
|
||||
this._addAttribute("SF", sf, GratingStim.#SHADERS[tex] ? GratingStim.#SHADERS[tex].uniforms.uFreq || 1.0 : 1.0);
|
||||
this._addAttribute("phase", phase, GratingStim.#SHADERS[tex] ? GratingStim.#SHADERS[tex].uniforms.uPhase || 0.0 : 0.0);
|
||||
this._addAttribute("color", color, "white");
|
||||
this._addAttribute("colorSpace", colorSpace, "RGB");
|
||||
this._addAttribute("contrast", contrast, 1.0, () => {
|
||||
this._adjustmentFilter.contrast = this._contrast;
|
||||
});
|
||||
this._addAttribute("blendmode", blendmode, "avg");
|
||||
this._addAttribute("interpolate", interpolate, false);
|
||||
|
||||
// estimate the bounding box:
|
||||
this._estimateBoundingBox();
|
||||
@ -520,6 +515,43 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color space value for the grating stimulus.
|
||||
*
|
||||
* @name module:visual.GratingStim#setColorSpace
|
||||
* @public
|
||||
* @param {String} colorSpaceVal - color space value
|
||||
* @param {boolean} [log= false] - whether of not to log
|
||||
*/
|
||||
setColorSpace (colorSpaceVal = "RGB", log = false) {
|
||||
let colorSpaceValU = colorSpaceVal.toUpperCase();
|
||||
if (Color.COLOR_SPACE[colorSpaceValU] === undefined) {
|
||||
colorSpaceValU = "RGB";
|
||||
}
|
||||
const hasChanged = this._setAttribute("colorSpace", colorSpaceValU, log);
|
||||
if (hasChanged) {
|
||||
this.setColor(this._color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set foreground color value for the grating stimulus.
|
||||
*
|
||||
* @name module:visual.GratingStim#setColor
|
||||
* @public
|
||||
* @param {Color} colorVal - color value, can be String like "red" or "#ff0000" or Number like 0xff0000.
|
||||
* @param {boolean} [log= false] - whether of not to log
|
||||
*/
|
||||
setColor (colorVal = "white", log = false) {
|
||||
const colorObj = (colorVal instanceof Color) ? colorVal : new Color(colorVal, Color.COLOR_SPACE[this._colorSpace])
|
||||
this._setAttribute("color", colorObj, log);
|
||||
if (this._pixi instanceof PIXI.Mesh) {
|
||||
this._pixi.shader.uniforms.uColor = colorObj.rgbFull;
|
||||
} else if (this._pixi instanceof PIXI.TilingSprite) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set spatial frequency value for the function.
|
||||
*
|
||||
@ -542,6 +574,47 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set blend mode of the grating stimulus.
|
||||
*
|
||||
* @name module:visual.GratingStim#setBlendmode
|
||||
* @public
|
||||
* @param {String} blendMode - blend mode, can be one of the following: ["avg", "add", "mul", "screen"].
|
||||
* @param {boolean} [log=false] - whether or not to log
|
||||
*/
|
||||
setBlendmode (blendMode = "avg", log = false) {
|
||||
this._setAttribute("blendmode", blendMode, log);
|
||||
if (this._pixi !== undefined) {
|
||||
let pixiBlendMode = GratingStim.#BLEND_MODES_MAP[blendMode];
|
||||
if (pixiBlendMode === undefined) {
|
||||
pixiBlendMode = PIXI.BLEND_MODES.NORMAL;
|
||||
}
|
||||
if (this._pixi.filters) {
|
||||
this._pixi.filters[this._pixi.filters.length - 1].blendMode = pixiBlendMode;
|
||||
} else {
|
||||
this._pixi.blendMode = pixiBlendMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to interpolate (linearly) the texture in the stimulus.
|
||||
*
|
||||
* @name module:visual.GratingStim#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.Mesh) {
|
||||
|
||||
} else if (this._pixi instanceof PIXI.TilingSprite) {
|
||||
this._pixi.texture.baseTexture.scaleMode = interpolate ? PIXI.SCALE_MODES.LINEAR : PIXI.SCALE_MODES.NEAREST;
|
||||
this._pixi.texture.baseTexture.update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the stimulus, if necessary.
|
||||
*
|
||||
@ -560,8 +633,12 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
if (this._needPixiUpdate)
|
||||
{
|
||||
this._needPixiUpdate = false;
|
||||
let currentUniforms = {};
|
||||
if (typeof this._pixi !== "undefined")
|
||||
{
|
||||
if (this._pixi instanceof PIXI.Mesh) {
|
||||
Object.assign(currentUniforms, this._pixi.shader.uniforms);
|
||||
}
|
||||
this._pixi.destroy(true);
|
||||
}
|
||||
this._pixi = undefined;
|
||||
@ -575,6 +652,7 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
if (this._tex instanceof HTMLImageElement)
|
||||
{
|
||||
this._pixi = PIXI.TilingSprite.from(this._tex, {
|
||||
scaleMode: this._interpolate ? PIXI.SCALE_MODES.LINEAR : PIXI.SCALE_MODES.NEAREST,
|
||||
width: this._size_px[0],
|
||||
height: this._size_px[1]
|
||||
});
|
||||
@ -583,12 +661,17 @@ export class GratingStim extends util.mix(VisualStim).with(ColorMixin)
|
||||
}
|
||||
else
|
||||
{
|
||||
this._pixi = this._getPixiMeshFromPredefinedShaders(this._tex, {
|
||||
uFreq: this._SF,
|
||||
uPhase: this._phase
|
||||
});
|
||||
this._pixi = this._getPixiMeshFromPredefinedShaders(
|
||||
this._tex,
|
||||
Object.assign({
|
||||
uFreq: this._SF,
|
||||
uPhase: this._phase,
|
||||
uColor: this._color.rgbFull
|
||||
}, currentUniforms)
|
||||
);
|
||||
}
|
||||
this._pixi.pivot.set(this._pixi.width * 0.5, this._pixi.width * 0.5);
|
||||
this._pixi.filters = [this._adjustmentFilter];
|
||||
|
||||
// add a mask if need be:
|
||||
if (typeof this._mask !== "undefined")
|
||||
|
@ -16,9 +16,12 @@ out vec4 shaderOut;
|
||||
|
||||
#define M_PI 3.14159265358979
|
||||
uniform float uRadius;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
float s = 1. - step(uRadius, length(uv * 2. - 1.));
|
||||
shaderOut = vec4(vec3(s), 1.0);
|
||||
// converting first to [-1, 1] space to get the proper color functionality
|
||||
// then back to [0, 1]
|
||||
float s = (1. - step(uRadius, length(uv * 2. - 1.))) * 2. - 1.;
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
@ -16,11 +16,14 @@ out vec4 shaderOut;
|
||||
|
||||
#define M_PI 3.14159265358979
|
||||
uniform float uThickness;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
float sx = step(uThickness, length(uv.x * 2. - 1.));
|
||||
float sy = step(uThickness, length(uv.y * 2. - 1.));
|
||||
float s = 1. - sx * sy;
|
||||
shaderOut = vec4(vec3(s), 1.0);
|
||||
// converting first to [-1, 1] space to get the proper color functionality
|
||||
// then back to [0, 1]
|
||||
float s = (1. - sx * sy) * 2. - 1.;
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ out vec4 shaderOut;
|
||||
uniform float uA;
|
||||
uniform float uB;
|
||||
uniform float uC;
|
||||
uniform vec3 uColor;
|
||||
|
||||
#define M_PI 3.14159265358979
|
||||
|
||||
@ -25,6 +26,8 @@ void main() {
|
||||
vec2 uv = vUvs;
|
||||
float c2 = uC * uC;
|
||||
float x = length(uv - .5);
|
||||
float g = uA * exp(-pow(x - uB, 2.) / c2 * .5);
|
||||
shaderOut = vec4(vec3(g), 1.);
|
||||
// converting first to [-1, 1] space to get the proper color functionality
|
||||
// then back to [0, 1]
|
||||
float g = uA * exp(-pow(x - uB, 2.) / c2 * .5) * 2. - 1.;
|
||||
shaderOut = vec4(vec3(g) * uColor * .5 + .5, 1.);
|
||||
}
|
||||
|
@ -14,11 +14,14 @@ precision mediump float;
|
||||
in vec2 vUvs;
|
||||
out vec4 shaderOut;
|
||||
uniform float uSqueeze;
|
||||
uniform vec3 uColor;
|
||||
|
||||
#define M_PI 3.14159265358979
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
float s = 1. - length(uv * 2. - 1.) * uSqueeze;
|
||||
shaderOut = vec4(vec3(s), 1.0);
|
||||
// converting first to [-1, 1] space to get the proper color functionality
|
||||
// then back to [0, 1]
|
||||
float s = (1. - length(uv * 2. - 1.) * uSqueeze) * 2. - 1.;
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ out vec4 shaderOut;
|
||||
#define M_PI 3.14159265358979
|
||||
uniform float uBeta;
|
||||
uniform float uPeriod;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
@ -31,5 +32,8 @@ void main() {
|
||||
} else if (absX > edgeArgument2) {
|
||||
s = 0.;
|
||||
}
|
||||
shaderOut = vec4(vec3(s), 1.0);
|
||||
// converting first to [-1, 1] space to get the proper color functionality
|
||||
// then back to [0, 1]
|
||||
s = s * 2. - 1.;
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
@ -18,10 +18,13 @@ out vec4 shaderOut;
|
||||
#define M_PI 3.14159265358979
|
||||
uniform float uFreq;
|
||||
uniform float uPhase;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
float s = uFreq * uv.x + uPhase;
|
||||
s = mod(s, 1.);
|
||||
shaderOut = vec4(vec3(s), 1.0);
|
||||
// converting first to [-1, 1] space to get the proper color functionality
|
||||
// then back to [0, 1]
|
||||
s = mod(s, 1.) * 2. - 1.;
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
@ -18,9 +18,11 @@ out vec4 shaderOut;
|
||||
#define M_PI 3.14159265358979
|
||||
uniform float uFreq;
|
||||
uniform float uPhase;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
float s = sin(uFreq * uv.x * 2. * M_PI + uPhase);
|
||||
shaderOut = vec4(.5 + .5 * vec3(s), 1.0);
|
||||
float s = sin((uFreq * uv.x + uPhase) * 2. * M_PI);
|
||||
// it's important to convert to [0, 1] while multiplication to uColor, not before, to preserve desired coloring functionality
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
@ -16,13 +16,16 @@ in vec2 vUvs;
|
||||
out vec4 shaderOut;
|
||||
|
||||
#define M_PI 3.14159265358979
|
||||
#define PI2 2.* M_PI
|
||||
uniform float uFreq;
|
||||
uniform float uPhase;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
float sx = sin(uFreq * uv.x * 2. * M_PI + uPhase);
|
||||
float sy = sin(uFreq * uv.y * 2. * M_PI + uPhase);
|
||||
float s = sx * sy * .5 + .5;
|
||||
shaderOut = vec4(vec3(s), 1.0);
|
||||
float sx = sin((uFreq * uv.x + uPhase) * PI2);
|
||||
float sy = sin((uFreq * uv.y + uPhase) * PI2);
|
||||
float s = sx * sy;
|
||||
// it's important to convert to [0, 1] while multiplication to uColor, not before, to preserve desired coloring functionality
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
@ -18,9 +18,11 @@ out vec4 shaderOut;
|
||||
#define M_PI 3.14159265358979
|
||||
uniform float uFreq;
|
||||
uniform float uPhase;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
float s = sign(sin(uFreq * uv.x * 2. * M_PI + uPhase));
|
||||
shaderOut = vec4(.5 + .5 * vec3(s), 1.0);
|
||||
float s = sign(sin((uFreq * uv.x + uPhase) * 2. * M_PI));
|
||||
// it's important to convert to [0, 1] while multiplication to uColor, not before, to preserve desired coloring functionality
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
@ -16,13 +16,16 @@ in vec2 vUvs;
|
||||
out vec4 shaderOut;
|
||||
|
||||
#define M_PI 3.14159265358979
|
||||
#define PI2 2.* M_PI
|
||||
uniform float uFreq;
|
||||
uniform float uPhase;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
float sx = sign(sin(uFreq * uv.x * 2. * M_PI + uPhase));
|
||||
float sy = sign(sin(uFreq * uv.y * 2. * M_PI + uPhase));
|
||||
float s = sx * sy * .5 + .5;
|
||||
shaderOut = vec4(vec3(s), 1.0);
|
||||
float sx = sign(sin((uFreq * uv.x + uPhase) * PI2));
|
||||
float sy = sign(sin((uFreq * uv.y + uPhase) * PI2));
|
||||
float s = sx * sy;
|
||||
// it's important to convert to [0, 1] while multiplication to uColor, not before, to preserve desired coloring functionality
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
@ -19,10 +19,13 @@ out vec4 shaderOut;
|
||||
uniform float uFreq;
|
||||
uniform float uPhase;
|
||||
uniform float uPeriod;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUvs;
|
||||
float s = uFreq * uv.x + uPhase;
|
||||
s = 2. * abs(s / uPeriod - floor(s / uPeriod + .5));
|
||||
shaderOut = vec4(vec3(s), 1.0);
|
||||
// converting first to [-1, 1] space to get the proper color functionality
|
||||
// then back to [0, 1]
|
||||
s = (2. * abs(s / uPeriod - floor(s / uPeriod + .5))) * 2. - 1.;
|
||||
shaderOut = vec4(vec3(s) * uColor * .5 + .5, 1.0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user