psychopy.org | Reference | Downloads | Github

Turn off artificial noise when using blendMode 'add'

Hi,
I am running into an issue when layering multiple greyscale gratings using blendMode=‘add’.

In the psychopy docs (http://www.psychopy.org/general/rendering.html), it suggests that when in ‘add’ mode (as opposed to ‘avg’ mode), the stimuli are combined in such a way that when a luminance value is requested that is out of bounds the pixel will either be clipped to the nearest possible value, or this will be artificially colored noise.

I’m finding that when this happens and I exceed a possible luminance value my stimulus contains artificial blues and reds. Presumably this is the artificial noise, but how can I turn it off?! Am I missing something here?

I want my luminance values to be clipped once they exceed ± 1, so that there are no artificial reds and blues presented. I’m using pyglet with Python 2.7 on a 2015 mac. This is what I get:

Here’s the code to replicate (note that this is simplified for ease of reproducibility, hence the 48 repetitions of drawing a grating do serve a purpose for the stimuli I am designing). Thanks:

from psychopy import visual, event, core

imageSize = 128
winHeight = 256
winLength = 256

win = visual.Window(
size=[winLength, winHeight],
units=“pix”,
fullscr=False,
allowGUI=True,
allowStencil=True,
blendMode=‘add’,
useFBO=True,
color=[0, 0, 0])

grating = visual.GratingStim(
win=win,
units=‘pix’,
tex=‘sin’,
interpolate=True,
size=[imageSize, imageSize])

for i in range(48):
grating.sf = 2.0 / imageSize
grating.contrast = 1
grating.opacity = 0.1
grating.pos = [0,0]
grating.draw()

win.flip()

event.waitKeys()

win.close()

The following (inserted after the ‘win = …’ block) might work - if you’re sure that you don’t want a visual indication when going out of range.

import psychopy.visual.shaders

fragFBOtoFrame = '''
    uniform sampler2D texture;

    void main() {
        vec4 textureFrag = texture2D(texture,gl_TexCoord[0].st);
        gl_FragColor.rgb = textureFrag.rgb;
    }
    '''

win._progFBOtoFrame = psychopy.visual.shaders.compileProgram(
    psychopy.visual.shaders.vertSimple,
    fragFBOtoFrame
)
1 Like

@lf208, was your problem solved? If yes, please tick solved. If not, it would be nice with a follow-up on what happened, so we can solve this.

Thanks for the response, I didn’t use this code in the end so can’t vouch for it.

I found that while the image displayed by Psychopy contained this artificial noise, when the image was copied (win.getMovieFrame(buffer=‘back’), and then saved as a PNG (win.saveMovieFrames(‘image_name.png’)), this PNG image did not contain the noise.

I agree that there should be a setting for this (set to clipping instead of noise when exceeding monitor gamut) but I haven’t gotten around to implementing that yet. One day! :slight_smile:

Thanks, this worked great for me.