Page 1 of 1

ISF program - problem with PASSES

Posted: Sat Jun 24, 2017 5:15 pm
by Psyne
I've been experimenting with ISF programming, and have run into a problem with a simple ISF fragment shader I was using to test persistent buffers. The program is supposed to allow a frame to be captured, strobing the captured frame instead of the current frame every 1/2 sec. My program:

Code: Select all

/*{
	"CREDIT": "Psyne",
	"ISFVSN": "2.0",
	"DESCRIPTION": "Strobes captured material every 1/2 second",
	"CATEGORIES": [
		"filter"
	],
	"INPUTS": [
		{
			"NAME": "inputImage",
			"TYPE": "image"
		},
		{
			"NAME": "capture",
			"TYPE": "event"
		}
	],
	"PASSES": [
		{
			"TARGET": "captureImage",
			"PERSISTENT": true
		}
	]
}*/

void main() {
	vec4 inputPixel = IMG_NORM_PIXEL(inputImage, isf_FragNormCoord);
	if (capture == true || FRAMEINDEX == 0)
		gl_FragColor = inputPixel;
	else if (PASSINDEX == 1)
		gl_FragColor = (fract(TIME) < 0.5) ? inputPixel : IMG_NORM_PIXEL(captureImage, isf_FragNormCoord);
	else
		discard;
}

At present the effect just displays the last frame captured by the "capture" event. What am I missing here?

Re: ISF program

Posted: Mon Jun 26, 2017 3:54 pm
by Magic
Just a quick thought, have you looked at the ISF Freeze Frame effect? It works similarly to what you're doing.

Re: ISF program

Posted: Mon Jun 26, 2017 5:23 pm
by Psyne
Nope - only the tutorials available on the ISF spec website. I'll have a look at that after work, and see if it helps illuminate my problem. Thanks!

Re: ISF program

Posted: Mon Jun 26, 2017 8:59 pm
by Psyne
Pointing me toward MMV's standard ISFs was definitely the way to go!

I've managed to deduce my problem after examining the Gaussian Blur ISF. Revised, working code below with problem details afterward.

Code: Select all

    /*{
       "CREDIT": "Psyne",
       "ISFVSN": "2.0",
       "DESCRIPTION": "Strobes captured material at the specified frequency and duty cycle",
       "CATEGORIES": [
          "filter"
       ],
       "INPUTS": [
          {
             "NAME": "inputImage",
             "TYPE": "image"
          },
          {
             "NAME": "capture",
             "TYPE": "event"
          },
          {
             "NAME": "frequency",
             "TYPE": "float",
             "MAX": 30.0
          },
          {
             "NAME": "dutyCycle",
             "TYPE": "float"
          }
       ],
       "PASSES": [
          {
             "TARGET": "captureImage",
             "PERSISTENT": true,
             "DESCRIPTION": "Pass 0"
          },
          {
          	"TARGET": "outImage",
            "DESCRIPTION": "Pass 1"
          }
       ]
    }*/

    void main() {
        if (capture) {
            gl_FragColor = IMG_THIS_PIXEL(inputImage);
        }
        else if (PASSINDEX == 0) {
            gl_FragColor = IMG_THIS_PIXEL(captureImage);
        }
       	else if (PASSINDEX == 1) {
          	gl_FragColor = fract(TIME * frequency) < dutyCycle ? IMG_THIS_PIXEL(captureImage) : IMG_THIS_PIXEL(inputImage);
       	}
    }
My mistake was in an assumption about how the PASSES array is used. If no PASSES array is specified there is one "output pass" to render the output of the shader. The second a PASSES array is specified, however, the output of the last pass is used; if you specify only one pass in PASSES, there is no "output pass" that follows those defined in the array. I assume this is mainly to allow the output pass to be persistent, differently sized, etc. without requiring the creation of an additional buffer if none is needed. Adding a second, non-persistent pass to render output was all that I needed to do (past a bit of cleanup).