Hello everyone,
I am trying to use Shaders in Processing for some real time intensive rendering projects and I am writing some shaders to run it. It is a particle system, and when I try to run
gl_PointSize = 10.0;
the particles stay at the same size.
I understood that I need to run
gl.Enable(GL_VERTEX_PROGRAM_POINT_SIZE);
but there is not such a thing in Processing. I tried with
pgl.Enable( PGL.VERTEX_PROGRAM_POINT_SIZE );
and
pgl.Enable( PGL.VERTEX_POINT_SIZE );
and it keeps saying "The global variable “VERTEX_PROGRAM_POINT_SIZE” does not exist.
Am I doing something wrong?
MainSketch:
// Import PeasyCam, for easy camera controls
import peasy.*;
PeasyCam cam;
// 2D arrays for points and to keep track of noise, so we don't calculate it everytime
PVector[][] points;
PVector[][] noise;
// Radius of the sphere
float radius = 200;
// Total number of points
// 2D array means 250*250=62.500 points in total
int total = 250;
// This creates the animation for the sphere
float updateNoise = 0;
void settings() {
  size(1280, 720, P3D);
}
void setup() {
  // Maximum speed, for testing purpose
  frameRate(1000);
  
  // Initialize the shader, check the shader tab
  initShader();
  // Disable the depth test to not have weird shading on the colors
  hint(DISABLE_DEPTH_TEST);
  // field of view and perspective of the camera
  float fov = PI/3.0; 
  float cameraZ = (height/2.0) / tan(fov/2.0);
  perspective(fov, float(width)/float(height), 
    cameraZ/10.0, cameraZ*10000.0);
  // Initialize the points and noise arrays
  points = new PVector[total][total];
  noise = new PVector[total][total];
  // Initialize the camera
  cam = new PeasyCam(this, 500);
  // Variable for the 2D noise, x coordinate
  float nx = 0;
  for (int i = 0; i < total; i++) {
    // Calculate the latitude
    float lat = map(i, 0, total-1, 0, PI);
    // Second variable for the noise
    float ny = 0;
    for (int j = 0; j < total; j++) {
      // Longitude
      float lon = map(j, 0, total-1, 0, TWO_PI);
      // Radius with noise applied
      float r = radius * noise(nx, ny);
      // Spherical coordinates
      float x = r * sin(lat) * cos(lon);
      float y = r * sin(lat) * sin(lon);
      float z = r * cos(lat);
      points[i][j] = new PVector(x, y, z);
      noise[i][j] = new PVector(nx, ny);
      ny += 0.01;
    }
    nx += 0.02;
  }
}
void draw() {
  background(0);
  update();        // Update the coordinates
  updateShader();  // Update the buffer in the openGL shader
  showShader();    // Display the shader
}
void update() {
  // TODO: optimize the update method
  
  for (int i = 0; i < total; i++) {
    float lat = map(i, 0, total, 0, PI);
    for (int j = 0; j < total; j++) {
      float lon = map(j, 0, total-1, 0, TWO_PI);
      float r = radius * noise(noise[i][j].x + updateNoise, noise[i][j].y + updateNoise);
      points[i][j].x = r * sin(lat) * cos(lon);
      points[i][j].y = r * sin(lat) * sin(lon);
      points[i][j].z = r * cos(lat);
    }
  }
  updateNoise += 0.01;
}
PShader:
// Import NIO from Java, for I/O operations, and to exchange data from Java to C# in the shader
import java.nio.*;
// Declare shader variables
float[] shaderPoints;              // The points to share with openGL
int  vertLoc;                      // Keeps the vertex location for the buffer
PGL     pgl;                       // PGL, Processing openGL
PShader sh;                        // Vertex and Fragment shader
FloatBuffer pointCloudBuffer;      // FloatBuffer of the openGL implementation
ByteBuffer byteBuf;                // ByteBuffer to share floats between Processing sketch and OpenGL
int vertexVboId;                   // Vertex Buffer Object ID
void initShader() {
  // Load the vertex and fragment shader
  sh = loadShader("frag.glsl", "vert.glsl");
  // Set the color, in the uniform float fragColor (check the shader code)
  sh.set("fragColor", 255.0/255.0, 255.0/255.0, 255.0/255.0, 255.0/255.0);
  // In openGL there are no vectors, or multivalue variables,
  // it will take every 3 values as x, y and z for each vertex.
  shaderPoints = new float[total*total*3];
  // Start new PGL
  PGL pgl = beginPGL();
  // Declare an int buffer, it  will identify our vertex buffer
  IntBuffer intBuffer = IntBuffer.allocate(1);
  // Generate 1 buffer, put the resulting identifier in vertexbuffer
  pgl.genBuffers(1, intBuffer);
  // The the ID from the int buffer
  vertexVboId = intBuffer.get(0);
  // Allocate the float array in a byte buffer
  byteBuf = ByteBuffer.allocateDirect(shaderPoints.length * Float.BYTES); //4 bytes per float
  // End the PGL
  endPGL();
}
void updateShader() {
  // This will update the values in our shader, by sharing the buffer from Processing to OpenGL.
  // In the float array we will share the coordinates of the vertices. Each value is one f the x, y or z
  // coordinate from our vertices. THe index is to keep track of the actual value in the array
  int index = 0;
  for (int i = 0; i < total; i++) {
    for (int j = 0; j < total; j++) {
      shaderPoints[index+0] = points[i][j].x;  // X
      shaderPoints[index+1] = points[i][j].y;  // Y
      shaderPoints[index+2] = points[i][j].z;  // Z
      index += 3;                              // index increments by 3
    }
  }
  // Allocate the float array in a byte buffer
  // This has been moved to the Shader setup because it was draining the memory, thanks to Neil Smith for the fix
  // byteBuf = ByteBuffer.allocateDirect(shaderPoints.length * Float.BYTES); //4 bytes per float
  // Order the byte byuffer
  byteBuf.order(ByteOrder.nativeOrder());
  // Converts the byte buffer in a float buffer
  pointCloudBuffer = byteBuf.asFloatBuffer();
  // Put the values in the float buffer
  pointCloudBuffer.put(shaderPoints);
  // Set the position to 0, starting point of the buffer
  pointCloudBuffer.position(0);
}
void showShader() {
  // Begin PGL
  pgl = beginPGL();
  // Bind the Shader
  sh.bind();
  // Set the vertex location, from the shader
  vertLoc = pgl.getAttribLocation(sh.glProgram, "vertex");
  // Enable the generic vertex attribute array specified by vertLoc
  pgl.enableVertexAttribArray(vertLoc);
  // Get the size of the float buffer
  int vertData = shaderPoints.length;
  // Binds the buffer object
  pgl.bindBuffer(PGL.ARRAY_BUFFER, vertexVboId);
  // Give our vertices to OpenGL.
  pgl.bufferData(PGL.ARRAY_BUFFER, Float.BYTES * vertData, pointCloudBuffer, PGL.DYNAMIC_DRAW);
  pgl.vertexAttribPointer(vertLoc, // Gets the vertex location, must match the layout in the shader.
    3, // Size, 3 values for each vertex from the float buffer
    PGL.FLOAT, // Type of the array / buffer
    false, // Normalized?
    Float.BYTES * 3, // Size of the float byte, 3 values for x, y and z
    0                   // Stride
    );
  // Here I try to enable gl_PointSize
  //pgl.Enable( PGL.VERTEX_POINT_SIZE );
  // The following commands will talk about our 'vertexbuffer' buffer
  pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
  // Draw the sphere
  pgl.drawArrays(PGL.POINTS, // Type of draw, in this case POINTS
    0, // Starting from vertex 0
    vertData                     // Drawing all the points from vertData, the array size
    );
  // Disable the generic vertex attribute array specified by vertLoc
  pgl.disableVertexAttribArray(vertLoc);
  // Unbind the vertex
  sh.unbind();
  // End the POGL
  endPGL();
}
Vertex Shader:
uniform mat4 transform;
attribute vec4 vertex;
attribute vec4 color;
varying vec4 vertColor;
void main() {
  gl_Position = transform * vertex;  
  gl_PointSize = 10.0;  
  vertColor = color;
}
Fragment Shader:
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
varying vec4 vertColor;
//input color
uniform vec4 fragColor;
void main() {
  //outputColor
  gl_FragColor = vec4(fragColor.xyzw);
}