Shader doesn't compile

this fragment shader always fails to compile, irrespective of what I try. Why???

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 resolution;
uniform sampler2D ppixels;

uniform float DA;
uniform float DB;
uniform float feed;
uniform float kill;
uniform float dt;

void main (void) {
    vec2 position = ( gl_FragCoord.xy / resolution.xy );
    vec2 pixel = 1./resolution;

    float A = texture2D(ppixels, position).r;

    float sumA = -A;

    sumA += 0.05*texture2D(ppixels, position + pixel * vec2(-1., -1.)).r;
    sumA += 0.05*texture2D(ppixels, position + pixel * vec2(-1., 1.)).r;
    sumA += 0.05*texture2D(ppixels, position + pixel * vec2(1., -1.)).r;
    sumA += 0.05*texture2D(ppixels, position + pixel * vec2(1., 1.)).r;
    sumA += 0.2*texture2D(ppixels, position + pixel * vec2(1., 0.)).r;
    sumA += 0.2*texture2D(ppixels, position + pixel * vec2(-1., 0.)).r;
    sumA += 0.2*texture2D(ppixels, position + pixel * vec2(0., -1.)).r;
    sumA += 0.2*texture2D(ppixels, position + pixel * vec2(0., 1.)).r;


    float B = texture2D(ppixels, position).g;
    float sumB = -B;
    sumB += 0.05*texture2D(ppixels, position + pixel * vec2(-1., -1.)).g;
    sumB += 0.05*texture2D(ppixels, position + pixel * vec2(-1., 1.)).g;
    sumB += 0.05*texture2D(ppixels, position + pixel * vec2(1., -1.)).g;
    sumB += 0.05*texture2D(ppixels, position + pixel * vec2(1., 1.)).g;
    sumB += 0.2*texture2D(ppixels, position + pixel * vec2(1., 0.)).g;
    sumB += 0.2*texture2D(ppixels, position + pixel * vec2(-1., 0.)).g;
    sumB += 0.2*texture2D(ppixels, position + pixel * vec2(0., -1.)).g;
    sumB += 0.2*texture2D(ppixels, position + pixel * vec2(0., 1.)).g

    float nA = A + ((DA*sumA) - (A*B*B) + (feed*(1.0 - A)))*dt;
    float nB = B + ((DB*sumB) + (A*B*B) - ((kill + feed)*B))*dt;


    gl_FragColor = vec4(nA, nB, 0.0, 1.0);
}  

The code I use is this -

PShader algorithm;
PGraphics pg;

public static final float DA = 1;
public static final float DB = 0.5;
public static final float feed = 0.055;
public static final float kill = 0.062;
public static final float dt = 1;

void setup() {
  size(500, 500, P2D);

  algorithm = loadShader("algorithm.glsl");

  pg = createGraphics(width, height, P2D);
  pg.noSmooth();

  pg.beginDraw();
  pg.fill(255, 255, 0);
  pg.noStroke();
  pg.background(255, 0, 0);
  pg.rect(width/2 - 10, height/2 - 10, 20, 20);
  pg.endDraw();

  algorithm.set("resolution", float(pg.width), float(pg.height));
  algorithm.set("DA", DA);
  algorithm.set("DB", DB);
  algorithm.set("feed", feed);
  algorithm.set("kill", kill);
  algorithm.set("dt", dt);
}
void draw() {
  pg.beginDraw();
  //pg.background(0);
  pg.shader(algorithm);
  pg.rect(0, 0, pg.width, pg.height);
  pg.endDraw();  
  image(pg, 0, 0, width, height);
}

Answers

  • edited May 2017

    Notes -

    • Uncommenting line 34 is useless.
    • Renaming shader to "algorithm.frag" is also useless.
    • I think the error may be on lines 43-47.
  • Answer ✓

    fragment shader line 41 missing semilicon.

  • Answer ✓

    this fragment shader always fails to compile

    line number and exact error message is always better than 'fails to compile'

  • @koogs I couldn't even read the error message, so I couldn't really post the error message.
    Note that no stack trace was printed, nor was it printed to the console.

    @nabr I think that should be it, thanks! I wonder why I did the notice that :P

  • Answer ✓

    @Lord_of_the_Galaxy OFFTOPIC:

    Processing Scetch

        public static final float DA = 1;
        public static final float DB = 0.5;
        public static final float feed = 0.055;
        public static final float kill = 0.062;
        public static final float dt = 1;
    

    looks like a lot of work (&bytes) for the compiler would it make more sence:

    fragment:

     void main (void) {
        const float DA = 1.f, DB = 0.5f, feed = 0.055f, kill = 0.062f, dt = 1.f;
    

    or is it the common the way you java guys do this stuff?

    just a note for myself : texture2d is deprecated<=OpenGL 3.3 use texture() the default precision is highp otherwise you targeting mobile devices. can also save few frames on older graphic hardware.

  • @nabr Actually, the "shortest" method would be this - float DA = 1, DB = 0.5, feed = 0.055, kill = 0.062, dt = 1;, and the "best" method would be public static final float DA = 1, DB = 0.5, feed = 0.055, kill = 0.062, dt = 1;, but I chose that long method for readability. In fact, in most of my code, I do that do that, but since I'm posting to the forum, I did that. You must admit that it looks better when fully typed out.
    Note that I've omitted the f suffix because we're using Processing, otherwise Java has it too.

  • edited May 2017

    just a note for myself : texture2d is deprecated<=OpenGL 3.3 use texture() the default precision is highp otherwise you targeting mobile devices. can also save few frames on older graphic hardware.

    I thought GL_ES is only defined for mobile devices?
    I'll use texture() from now on.

  • edited May 2017

    @Lord_of_the_Galaxy Great! I also often confuse myself with GL_ES :) I learned how to use ppixel. Thank you!

  • edited May 2017

    @nabr -- re:

    looks like a lot of work (&bytes) for the compiler

    Is your question "why declare static/final arguments in the Processing(Java) sketch, then pass them to the shader at setup() -- why not just declare them directly in the shader?"

    One advantage to this approach is that once the GLSL shader is written and parameterized, it can be manipulated entirely at the sketch level in the future -- with any mix of static and dynamic arguments -- without further modifying the shader.

    or is it the common the way you java guys do this stuff?

    In general, Java is very verbose, and the compiler doing bytes of extra work is a non-issue outside very specialized circumstances. If there is a performance penalty from calling PShader.set() it would be very small and incurred only once, during setup -- or am I misunderstanding how GLSL works, and would there be an ongoing penalty? Shaders aren't my area of expertise.

  • @jeremydouglass Even if the penalty was ongoing, it won't matter as passing in a few floats every frame is insignificant compared to the amount of work already happening.

  • edited May 2017 Answer ✓

    @jeremydouglass

    i know few things, also not a shader expert, - and if i scroll down in the docs, i see their some crazy stuff is going on just to overload a "position" or uniform from processing to glsl. (at least at low level, - you have to type a lot) idk, i going to put as much as possibel in the frag. (actually, if we are talking about opimatation i would put as much as possible in the vertex, because fragment shader runs per pixel computation) https://github.com/processing/processing/wiki/Advanced-OpenGL

    (also discovered that Processing using #version 150 per default)

    i'm using sometimes processing, with 2years of break in between and java stuff that looks like public static final is kind of weird, just to replace a singel "char" in a string array.

    this is what it might look like one state after uploading .glsl file to the scetch (minimal version)

    String[] vertSource={"#version 150"
        ,"in vec4 position;"
        ,"void main() {"
        ,"gl_Position = vec4(position.xy*.5-1.,0.,1.);"
     ,"}"
    };String[] fragSource={"#version 150"
        ,"out vec4 fragColor;"
        ,"uniform vec2 res;"
        ,"void main() {"
        ,"vec2 p = gl_FragCoord.xy/res;"
        ,  "fragColor = vec4(vec3(p.x>=p.y),1.);"
       ,"}"
      };/*setup*/
         size(640,360,P2D);
         PShader shader=new PShader(this,vertSource,fragSource);
                 shader.set("res",float(width),float(height)); 
         filter(shader);
    
  • Actually, in most cases, you use the fragment shader if you need to compute things in parallel.
    This is because in that case, you can compute thousands of things in parallel, and it is comparatively easy to access the information, even through something like Processing.
    Of course, libraries exist that help you directly run code on the GPU in parallel, but they are very complex.

  • edited May 2017 Answer ✓

    @Lord_of_the_Galaxy

    No i mean sometimes its also efficient!

    Compute math based on Pixels : 640X360*4(RGBA) = Fragment Shader

    Compute same math based on Rect : 12 vertices = Vertex Shader

    could make a difference. Is also know for inaccuracy (at large scale)

  • Oh, you're talking of actually manipulating what is on the screen. I'm talking of using the GPU to run actual math in the background, in parallel.

  • edited May 2017
  • (In Processing) Say, for example, the Reaction Diffusion algorithm, or Conway's game of life. Instead of using a grid and trying to calculate each cell one by one on the CPU, you convert the data to an image and send it to the GPU. Then each pixel of the image (each pixel contains one piece of the data) is processed by the same math, as it runs through the fragment shader. Then, you have the final output, which can then be converted back to data. Voilà, you have just done the math on the GPU.

    Note that the overhead is only worth it when you're doing the same math on thousands of pieces of data.

Sign In or Register to comment.