Using custom `main(String[] args)` breaks file reading functions in Windows (e.g. `loadShader()`, `loadImage()`)


I’m using loadShader() and loading a file which is saved to the data folder. I changed my sketch to include a custom main() function, however the loadShader function doesn’t work after that (Processing 3.3.7, Windows 10 64).
Any tips on how to make this work? Hardcoding the full path to the shader file works, but obviously not a practical solution.

static public void main(String[] args) {
  String[] appletArgs = new String[] {  "BlurFilter"};

PS: I raised this issue also in Github (issue 5615. I doubt I’m the first one to face this problem, therefore I’m cross posting, hoping there is a workaround, by writing the code in a different way.

AFAIK, either remove main() or export the sketch. :dizzy_face:

What about using sketchPath or dataPath ?


Exporting the sketch doesn’t make any difference.

adding a custom main() changes the output of sketchPath() to the location of Processing executable:

  • Without main(String[] args) , sketchPath("") returns the location of the .pde file: C:\processing-3.3.7\modes\java\examples\Basics\Image\Alphamask\
  • With main(String[] args) , sketchPath("") returns the location of my Processing installation: C:\processing-3.3.7\

Well, it used to. Running the exported sketch should use its current folder as its sketchPath. :thinking:

Since you were more interested in the dataPath where the shaders should be located, did you try that too?

hi @GoToLoop
You are right, in the sense that file loading functions will work, if you export the sketch works without a custom main(String[] args) in the sketch

pretty much the same thing, dataPath() returns Processing installation path, appended with /data

Just to make sure if the sketchPath is still recognized in recent Processing versions when we run the exported sketch using a customized main(), I’ve coded this simple test sketch below: :crazy_face:

 * PApplet.main() (v1.0)
 * GoToLoop (2018/Aug/12)
 * using-custom-main-string-args-breaks-file-reading-functions-
 * in-windows-e-g-loadshader-loadimage/2572/10

public static void main(final String[] args) {
  final String sketch = Thread.currentThread().getStackTrace()[1].getClassName();
  main(sketch, args);

@Override public void settings() {
  size(800, 60);


@Override public void draw() {
  text(sketchPath(), 20, 20);
  if (args != null)  text(join(args, " : "), 20, 40);

BtW, I’m using most recent 64-bit PDE v3.4 on Win 8.1 to export the sketch above. :computer:

I went to the exported’s subfolder “application.windows64/” and double-clicked the “.exe” file there. :open_file_folder:

And the sketchPath shown there matches the full path where I’m running it! :ok_hand:

I can even open a command prompt and run the “.exe” passing typed args to it, and they’re also displayed! :star_struck:

Hi @GoToLoop, thank you for engaging and for your time testing it. I was wondering, does it matter where you have Processing installed, and where you have your sketches saved?
Does your example also returns the correct path when running from Processing (before exporting)?

In my computer Processing is installed (=unzipped) at C:\processing-3.3.7, which is the path returned by sketchPath. My sketches are not under that path, they are at e.g. c:\Github\RepositoryName\SketchName

If you someone is interested, here is the source code for sketchPath. I didn’t find anything…

My response is the same as my 1st reply to you: :nerd_face:

My example sketch works correctly when we run its exported “.exe”. Am I clear now? :+1:

I understood it works in you setup once you export the app.
Any idea how to make it work from the Processing environment?

By default, field PApplet::sketchPath would point to the “Current Working Directory” (CWD):

Unless a special “–sketch-path=” argument is passed to PApplet.runSketch():

I believe the PDE (Processing’s IDE) creates its own customized main(String[] args) which passes all of those custom args to the compiled sketch.

And when we override it by making our own main(String[] args), the PDE can’t pass “–sketch-path=” to our sketch.

And since the CWD is where the PDE is located, our sketch inherits that path. :confounded:

It makes sense! I will try to find another solution to my problem, thanks @GoToLoop