I'd need help with my point shader

edited July 2015 in GLSL / Shaders

Hi, I'm trying to code a shader with processing: My aim is to pass an array of points to the shader, calculate their distance to the fragment and paint them with a circle colored with a gradient depending of that computation. For example:cattura2 - this is a working test with Shader Toy

Unfortunately it isn't clear to me how I should calculate and convert the coordinates passed for processing inside the shader, because the result I get is that all the point are black and I suspect the calculation of the distance is somehow wrong. This is what I get with Processing: Cattura

What I'm currently trying is to pass two array of floats - one for x positions and one for y positions of each point - to the shader though a uniform. Then inside the shader iterate through each point like so: This is the sketch's code:

PShader pointShader;

float[] sourceX;
float[] sourceY;


void setup()
{

  size(1024, 1024, P3D);
  background(255);

  sourceX = new float[100];
  sourceY = new float[100];
  for (int i = 0; i<100; i++)  
  {
    sourceX[i] = random(0, 1023);
    sourceY[i] = random(0, 1023);
  }


  pointShader = loadShader("pointfrag.glsl", "pointvert.glsl");  
  shader(pointShader, POINTS);
  pointShader.set("sourceX", sourceX);
  pointShader.set("sourceY", sourceY);
}


void draw()
{
  for (int i = 0; i<100; i++) {   
    strokeWeight(60);
    point(sourceX[i], sourceY[i]);
  }
}

While this is the vertex's code:

#define PROCESSING_POINT_SHADER

uniform mat4 projection;
uniform mat4 transform;


attribute vec4 vertex;
attribute vec4 color;
attribute vec2 offset;

varying vec4 vertColor;
varying vec2 center;

//varying mat4 t;
//varying mat4 proj;
//varying vec2 off;

void main() {

  vec4 clip = transform * vertex;
  gl_Position = clip + projection * vec4(offset, 0, 0);

  vertColor = color;
  center = clip.xy;

  //off = offset;
  //t = transform;
  //proj = projection;
}

And this is the frag code:

uniform float sourceX[100];
uniform float sourceY[100];
uniform vec2 resolution;

//in vec4 gl_FragCoord;
layout(pixel_center_integer, origin_upper_left) in vec4 gl_FragCoord;


varying vec4 vertColor;
varying vec2 center;

void main()
{
    float intensity = 0.0;

    for(int i=0; i<100; i++)
    {
        vec2 source_1 = vec2(sourceX[i],sourceY[i]);
        vec2 source = (source_1.xy  / resolution.xy) ;

        vec2 position = ( gl_FragCoord.xy / resolution.xy );
        float d = distance(position, source);
        intensity += exp(-0.5*d*d);
    }

    intensity=3.0*pow(intensity,0.02);
    if (intensity<=1.0) 
        gl_FragColor=vec4(0.0,intensity*0.5,0.0,1.0);
    else if (intensity<=2.0) {
        gl_FragColor=vec4(intensity-1.0, 0.5+(intensity-1.0)*0.5,0.0,1.0);
    } else 
        vec4(1.0,3.0-intensity,0.0,1.0);
}

Could anyone explain to me how to make this work? Thanks

Tagged:

Answers

  • there's obviously a bit missing from line 32 (based on lines 28 and 30). not sure if that's the only problem though.

    try replacing lines 26 with a constant as a test, see if it's setting the pixel correctly.

  • Yes, it was a mistake, I copied an older version of the code, the correct line would be: gl_FragColor=vec4(intensity*0.5,0.0,0.0,1.0); but the code I am currently running is the most updated I've done.

    Probably I should have specified earlier, I've already tried to set the intensity to a specified value to see if that part of the code is correct: while testing with something like intensity = 1.0 intensity = 2.0; intensity = 50.0;

    the result is that the circles are drawn with the correct colour (obliviously one colour at time). They're black only if I put some unacceptable values, like non-float or 0.0, so my conclusion is that the d or intensity value are somehow wrong.

    Another thing that could help me is if there is any way to check their values during executions - from what I understand it's not possible to "debug" glsl, but there is at least a way to print some value on screen?

  • Answer ✓

    i don't know the first thing about glsl. but are you setting resolution? lines 24 and 25 set sourceX and sourceY for the 100 dots and are picked up on lines 1 and 2 of the frag code. but where's the same thing for resolution?

  • edited July 2015

    result isn't still what I need, as the circles are drawn like the distance is calculated from a single central point, and not with the I've described and tried to code.

    What I'm currently getting is: Cattura

    but is really weird for me: I can't get how is possible to have a result like that. As far I know , for each call of point() a different shape is drawn through a different shader, and in each of those the distance\intensity is calculated between the frag coordinate and the list of array I passed, so I don't really get why it's all drawn in relation of a single central point.

  • you have a for loop in the draw() and a for loop in the frag shader.

    what's the one in the shader doing? don't you just want the distance from the centre of the current spot? not all 100?

  • The question isn't totally clear to me, so I hope this is going to answer: I want to make each circle going from green to red in relation of how many other circles are close, so:

    • The loop in the drawn() is needed to drawn the 100 different circles
    • The loop in the shader is to calculate the intensity from which the colour of the frag is decided, which consider the distance from the current fragcoordinate and the center of the 100 circles: for each cycle, first is calculate the distance between the fragcoordinate and the circle center's coordinate (stored in the uniform arrays). Then the intensity is calculated with intensity+=exp(-0.04*d);
  • i don't think that second point is true though - looking at the original image the colours are based on centre of the dot, not the centre of all dots. and that the loop in the ShaderToy link is generating the 10x10 grid of dots. (although it is also summing over them all...)

    (shaders confuse me 8) i have been playing with them a bit, prompted by this question, but i think processing's implementation might be a bit peculiar)

  • edited July 2015

    (maybe the other dots are too far away to influence the colour choices?)

    yeah, i think this is the case. change the 100 to 85 in the box on the right and you can see the colour extending further than the dots. i think the shader is being called for every pixel in the box on the left and is calculating the colour of that pixel based on the distance from 100 different points, which happen to be the centres of those circles.

  • edited July 2015

    Could you rephrase your last post? I don't get what you're saying: what do you mean for right and left box? What have you changed from 100 to 85? Anyway in the code it's right that the 100 points are the center of the circles, is what I need.

  • hit the link to ShaderToy in the top post. it has the code that generates the pic with 100 dots.

  • what exactly are you expecting? dots like the first picture but randomly distributed?

  • Yes, with colour of each one varying depending on how far is from the others.

  • i have been reading learning shaders... to the point where i can answer this question

    i've made this a colour shader, not a point shader. and then write a quad to cover the entire screen, calculating the colours purely in the shader, based on the distances from the passed in points

    // forum.processing.org/two/discussion/11609/i-d-need-help-with-my-point-shader
    
    PShader pointShader;
    static int COUNT = 100;
    
    float[] sourceX = new float[COUNT];
    float[] sourceY = new float[COUNT];
    
    void setup()
    {
      size(600, 600, P3D);
      background(255);
    
      for (int i = 0; i < COUNT; i++) {
        sourceX[i] = random(0, width);
        sourceY[i] = random(0, height);
      }
    
      pointShader = loadShader("pointfrag.glsl");
      pointShader.set("sourceX", sourceX);
      pointShader.set("sourceY", sourceY);
      shader(pointShader);
    }
    
    void draw() {
      rect(0, 0, width, height);
      noLoop();
    }
    

    frag shader (pointfrag.glsl)

    #define PROCESSING_COLOR_SHADER
    
    #version 120
    
    #ifdef GL_ES
    precision mediump float;
    precision mediump int;
    #endif
    
    uniform float[100] sourceX;
    uniform float[100] sourceY;
    
    void main() {
        float intensity = 0.0;
    
        // sum the distances from the points
        for(int i = 0; i < 100; i++) {
            float d = distance(gl_FragCoord.xy, vec2(sourceX[i], sourceY[i]));
            intensity += exp(-0.05 * d * d);
        }
    
        // map the colours
        intensity = 3.0 * pow(intensity, 0.02);
        if (intensity <= 1.0) {
            gl_FragColor = vec4(0.0, intensity * 0.5, 0.0, 1.0);
        } else if (intensity <= 2.0) {
            gl_FragColor = vec4(intensity - 1.0, 0.5 + (intensity - 1.0) * 0.5, 0.0, 1.0);
        } else {
            gl_FragColor = vec4(1.0, 3.0 - intensity, 0.0, 1.0);
        }
    }
    

    this looks like the original shadertoy example but with random points. the colours fade away quickly (as per the original). that'll be controlled by the intensity calculation, the pow() call.

Sign In or Register to comment.