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

added proper support for grating stim coloring; utils/Color extended with rgbFull(), which provides [-1, 1] rgb color space;

This commit is contained in:
lgtst 2022-05-07 22:16:56 +03:00
parent a1effe6969
commit 908f52e941
13 changed files with 89 additions and 33 deletions

View File

@ -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.
*

View File

@ -47,7 +47,7 @@ import raisedCosShader from "./shaders/raisedCosShader.frag";
* @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 {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
@ -279,12 +279,7 @@ export class GratingStim extends VisualStim
this._adjustmentFilter.contrast = this._contrast;
});
this._addAttribute("blendmode", blendmode, "avg");
this._addAttribute(
"interpolate",
interpolate,
false,
this._onChange(true, false),
);
this._addAttribute("interpolate", interpolate, false);
// estimate the bounding box:
this._estimateBoundingBox();
@ -551,7 +546,7 @@ export class GratingStim extends VisualStim
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.rgb;
this._pixi.shader.uniforms.uColor = colorObj.rgbFull;
} else if (this._pixi instanceof PIXI.TilingSprite) {
}
@ -602,6 +597,24 @@ export class GratingStim extends VisualStim
}
}
/**
* 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.
*
@ -620,8 +633,12 @@ export class GratingStim extends VisualStim
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;
@ -635,6 +652,7 @@ export class GratingStim extends VisualStim
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]
});
@ -643,10 +661,14 @@ export class GratingStim extends VisualStim
}
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];

View File

@ -20,6 +20,8 @@ uniform vec3 uColor;
void main() {
vec2 uv = vUvs;
float s = 1. - step(uRadius, length(uv * 2. - 1.));
shaderOut = vec4(vec3(s) * uColor, 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);
}

View File

@ -22,6 +22,8 @@ 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) * uColor, 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);
}

View File

@ -26,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) * uColor, 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.);
}

View File

@ -20,6 +20,8 @@ uniform vec3 uColor;
void main() {
vec2 uv = vUvs;
float s = 1. - length(uv * 2. - 1.) * uSqueeze;
shaderOut = vec4(vec3(s) * uColor, 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);
}

View File

@ -32,5 +32,8 @@ void main() {
} else if (absX > edgeArgument2) {
s = 0.;
}
shaderOut = vec4(vec3(s) * uColor, 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);
}

View File

@ -23,6 +23,8 @@ uniform vec3 uColor;
void main() {
vec2 uv = vUvs;
float s = uFreq * uv.x + uPhase;
s = mod(s, 1.);
shaderOut = vec4(vec3(s) * uColor, 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);
}

View File

@ -22,6 +22,7 @@ uniform vec3 uColor;
void main() {
vec2 uv = vUvs;
float s = sin((uFreq * uv.x + uPhase) * 2. * M_PI) * .5 + .5;
shaderOut = vec4(vec3(s) * uColor, 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);
}

View File

@ -25,6 +25,7 @@ void main() {
vec2 uv = vUvs;
float sx = sin((uFreq * uv.x + uPhase) * PI2);
float sy = sin((uFreq * uv.y + uPhase) * PI2);
float s = sx * sy * .5 + .5;
shaderOut = vec4(vec3(s) * uColor, 1.0);
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);
}

View File

@ -22,6 +22,7 @@ uniform vec3 uColor;
void main() {
vec2 uv = vUvs;
float s = sign(sin((uFreq * uv.x + uPhase) * 2. * M_PI)) * .5 + .5;
shaderOut = vec4(vec3(s) * uColor, 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);
}

View File

@ -25,6 +25,7 @@ void main() {
vec2 uv = vUvs;
float sx = sign(sin((uFreq * uv.x + uPhase) * PI2));
float sy = sign(sin((uFreq * uv.y + uPhase) * PI2));
float s = sx * sy * .5 + .5;
shaderOut = vec4(vec3(s) * uColor, 1.0);
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);
}

View File

@ -24,6 +24,8 @@ 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) * uColor, 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);
}