multiple points lights when light defined by shader

edited March 2015 in GLSL / Shaders

don't get how to set it up and can't seem to find any examples of how to do it calling pointLight(...); consecutively only seem to work without the shader being enabled,I know the shader itself works, so there something I am missing with the processing side, any help

`#define PROCESSING_LIGHT_SHADER

define numLights 8

uniform mat4 modelview; uniform mat4 transform; uniform mat3 normalMatrix; uniform vec4 lightPosition[numLights];

// focal factor for specular highlights (positive floats) uniform float SpecularFocus; uniform float SpecularContribution; uniform float DiffuseContribution; uniform vec4 AmbientContribution;

in vec4 vertex;//attribute same as "in" in vec4 color; in vec3 normal;

varying vec4 vertColor;

void main(){ for(int i=0;i<numLights;i++){ gl_Position = transform*vertex; vec3 vertexCamera = vec3(modelview * vertex); vec3 transformedNormal = normalize(normalMatrix * normal); //Vertex normal direction vec3 dir = normalize(lightPosition[i].xyz - vertexCamera); //Vertex to light direction float amountDiffuse = max(0.0, dot(dir, transformedNormal));

    // calculate the vertex position in eye coordinates
    vec3 vertexViewDir = normalize(-vertexCamera);

    // calculate the vector corresponding to the light source reflected in the vertex surface.
    // lightDir is negated as GLSL expects an incoming (rather than outgoing) vector
    vec3 lightReflection = reflect(-dir, transformedNormal);

    // specular light is dot product of light reflection vector and our viewing vector.
    // the closer we are to the reflection angle, the greater the specular sheen.
    float amountSpecular = max(0.0, dot(lightReflection, vertexViewDir));

    // apply an additional pow() to focus the specular effect
    // (try playing with this value)
    amountSpecular = pow(amountSpecular, SpecularFocus);

    color=clamp(color,0.0f,1.0f);

    // calculate actual light intensity
    float light =AmbientContribution;

    light=light+SpecularContribution * amountSpecular + DiffuseContribution * amountDiffuse;

    vertColor = vec4(light, light, light, 1) * color;
}

}

`

Answers

  • edited March 2015

    Hello !

    Excuse me but I didn't understood...

    What is your problem exactly ?

    and please, format your code correctly

  • edited March 2015

    sorry about that I figured out the issues with the shader, but I am having issues setting up the lights from processing, how do you create multiple point lights, if the lighting is shader based at present every new point light I add overrides the previous one.....what am I missing

    #define PROCESSING_LIGHT_SHADER
    #define NUM_LIGHTS 8
    
    uniform mat4 modelview;
    uniform mat4 transform;
    uniform mat3 normalMatrix;
    
    uniform int lightCount;
    uniform vec4 lightPosition[NUM_LIGHTS];
    
    // focal factor for specular highlights (positive floats)
    uniform float SpecularFocus;
    uniform float SpecularContribution;
    uniform float DiffuseContribution;
    uniform vec4 AmbientContribution;
    
    in vec4 vertex;//attribute same as "in"
    in vec4 color;
    in vec3 normal;
    
    varying vec4 vertColor;
    
    void main(){
        gl_Position = transform*vertex;
        vec3 vertexCamera = vec3(modelview * vertex);
        vec3 transformedNormal = normalize(normalMatrix * normal); //Vertex normal direction
    
    
        float light;
    
        for (int i = 0; i < lightCount; i++){
            vec3 dir = normalize(lightPosition[i].xyz - vertexCamera); //Vertex to light direction 
            float amountDiffuse = max(0.0, dot(dir, transformedNormal));
            // calculate the vertex position in eye coordinates
            vec3 vertexViewDir = normalize(-vertexCamera);
    
            // calculate the vector corresponding to the light source reflected in the vertex surface.
            // lightDir is negated as GLSL expects an incoming (rather than outgoing) vector
            vec3 lightReflection = reflect(-dir, transformedNormal);
    
            // specular light is dot product of light reflection vector and our viewing vector.
            // the closer we are to the reflection angle, the greater the specular sheen.
            float amountSpecular = max(0.0, dot(lightReflection, vertexViewDir));
    
            // apply an additional pow() to focus the specular effect
            // (try playing with this value)
            amountSpecular = pow(amountSpecular, SpecularFocus);
    
            color=clamp(color,0.0f,1.0f);
    
            // calculate actual light intensity
            light = AmbientContribution;
            light = light+SpecularContribution * amountSpecular + DiffuseContribution * amountDiffuse;
    
            vertColor = vec4(light, light, light, 1) * color;
        }
    
    }
    

    processing code

      shader(lightShader);
      lightShader.set("SpecularFocus",10.0);//sharpness of spec highlights
      lightShader.set("SpecularContribution", 0.5);//influence of specualurity on surfaces
      lightShader.set("DiffuseContribution", 0.25);//influence of diffuse light on surfaces
      lightShader.set("AmbientContribution", 0.025, 0.025,  0.025, 0.0);
      lightShader.set("lightCount", 8);
    
    
      pointLight(100,100,100,width/2,height/2, -400);
      pointLight(100, 100, 100, mouseX, mouseY, 400); 
    
  • Hello again !

    The problem comes from your GLSL, it's logical that you experiment only one light because you didn't sum the light-values ; instead, you set the vertColor to each light value, then you experiment only the last one

    You should have some " += " in your code to do what you want

  • could swear I was getting errors when doing that some days ago strange

    thanks that is it

  • edited March 2015

    ok me again...........my problem isn't completely fixed, but I am not certain what I have to do, I can now have multiple lights, just not multiple lights with different settings, each "old" light assumes the settings of the last added light....this what I am doing below, that first light is supposed to be a base "flat" light

    shader(lightShader);
      lightShader.set("SpecularFocus",75.0);//sharpness of spec highlights
      lightShader.set("SpecularContribution", 0.25);//influence of specualurity on surfaces
      lightShader.set("DiffuseContribution", 0.175);//influence of diffuse light on surfaces
      lightShader.set("AmbientContribution", 0.025, 0.025,  0.025, 0.0);
      pointLight(50,50,50,width/2,height/2, 400);
    
      shader(lightShader);
      lightShader.set("SpecularFocus",10.0);//sharpness of spec highlights
      lightShader.set("SpecularContribution", 0.5);//influence of specualurity on surfaces
      lightShader.set("DiffuseContribution", 0.25);//influence of diffuse light on surfaces
      pointLight(100, 100, 100, mouseX, mouseY, 400); 
    

    and the shader as it stands now

    #define PROCESSING_LIGHT_SHADER
    #define NUM_LIGHTS 8
    
    uniform mat4 modelview;
    uniform mat4 transform;
    uniform mat3 normalMatrix;
    
    uniform int lightCount;
    uniform vec4 lightPosition[8];
    
    // focal factor for specular highlights (positive floats)
    uniform float SpecularFocus;
    uniform float SpecularContribution;
    uniform float DiffuseContribution;
    uniform vec4 AmbientContribution;
    
    in vec4 vertex;//attribute same as "in"
    in vec4 color;
    in vec3 normal;
    
    varying vec4 vertColor;
    
    void main(){
        gl_Position = transform*vertex;
        vec3 vertexCamera = vec3(modelview * vertex);
        vec3 transformedNormal = normalize(normalMatrix * normal); //Vertex normal direction
    
    
        float light = 0.0f;
    
        for (int i = 0; i < lightCount; i++){
            vec3 dir = normalize(lightPosition[i].xyz - vertexCamera); //Vertex to light direction 
            float amountDiffuse = max(0.0, dot(dir, transformedNormal));
            // calculate the vertex position in eye coordinates
            vec3 vertexViewDir = normalize(-vertexCamera);
    
            // calculate the vector corresponding to the light source reflected in the vertex surface.
            // lightDir is negated as GLSL expects an incoming (rather than outgoing) vector
            vec3 lightReflection = reflect(-dir, transformedNormal);
    
            // specular light is dot product of light reflection vector and our viewing vector.
            // the closer we are to the reflection angle, the greater the specular sheen.
            float amountSpecular = max(0.0, dot(lightReflection, vertexViewDir));
    
            // apply an additional pow() to focus the specular effect
            // (try playing with this value)
            amountSpecular = pow(amountSpecular, SpecularFocus);
    
            //color=clamp(color,0.0f,1.0f);
    
            // calculate actual light intensity
            light += AmbientContribution;
            light += SpecularContribution * amountSpecular + DiffuseContribution * amountDiffuse;
    
            vertColor = vec4(light, light, light, 1) * color;
        }
    
    }
    
  • Hello ! "I can now have multiple lights, just not multiple lights with different settings"

    I'm not absolutly sure about it, but I think you have to put each light-settings in an array with 8 values by array. Then you will be able to target the settings corresponding to your light in your loop

  • edited March 2015

    Can you post the final code if it works ? :)

    EDIT : Why are you calling your shader two times ?

    EDIT2 : I'm not sure about it but it sounds to me logical that you can call "pointLight" 8 times by shader-call ; it should be consistant with the array of 8 lights in the GLSL shaders. Right now, you manage a single light by shader-call and it's not how it should work in my opinion

    EDIT3 : your last line

    vertColor = vec4(light, light, light, 1) * color;

    should be outside the loop, the value contained in "light" should represents the sums of all lights from the point of view of the vertex. But you cannot do it right now because you have a single pointlight in your shader, then the sum of a single value is that single value, that's why nothing changed

  • But you cannot do it right now because you have a single pointlight in your shader,

    please elaborate, setting up that for loop is where I seem to be tripping up, its a school project so I don't want the answer as much as to be put in the right direction to getting it. thanks

    frag

    #ifdef GL_ES
    precision mediump float;
    precision mediump int;
    #endif
    
    varying vec4 vertColor;
    
    void main() {
      gl_FragColor = vertColor;
    }
    

    vert

    #define PROCESSING_LIGHT_SHADER
    #define NUM_LIGHTS 8
    
    uniform mat4 modelview;
    uniform mat4 transform;
    uniform mat3 normalMatrix;
    
    uniform int lightCount;
    uniform vec4 lightPosition[8];
    
    // focal factor for specular highlights (positive floats)
    uniform float SpecularFocus;
    uniform float SpecularContribution;
    uniform float DiffuseContribution;
    uniform vec4 AmbientContribution;
    
    in vec4 vertex;//attribute same as "in"
    in vec4 color;
    in vec3 normal;
    
    varying vec4 vertColor;
    
    void main(){
         //Vertex normal direction
    
        float light;
    
        for (int i = 0; i < lightCount; i++){
    
            gl_Position = transform*vertex;
            vec3 vertexCamera = vec3(modelview * vertex);
            vec3 transformedNormal = normalize(normalMatrix * normal);
            light = 0.0f;
    
            vec3 dir = normalize(lightPosition[i].xyz - vertexCamera); //Vertex to light direction 
            float amountDiffuse = max(0.0, dot(dir, transformedNormal));
            // calculate the vertex position in eye coordinates
            vec3 vertexViewDir = normalize(-vertexCamera);
    
            // calculate the vector corresponding to the light source reflected in the vertex surface.
            // lightDir is negated as GLSL expects an incoming (rather than outgoing) vector
            vec3 lightReflection = reflect(-dir, transformedNormal);
    
            // specular light is dot product of light reflection vector and our viewing vector.
            // the closer we are to the reflection angle, the greater the specular sheen.
            float amountSpecular = max(0.0, dot(lightReflection, vertexViewDir));
    
            // apply an additional pow() to focus the specular effect
            // (try playing with this value)
            amountSpecular = pow(amountSpecular, SpecularFocus);
    
            //color=clamp(color,0.0f,1.0f);
    
            // calculate actual light intensity
            light += AmbientContribution;
            light += SpecularContribution * amountSpecular + DiffuseContribution * amountDiffuse;
    
    
        }
        vertColor = vec4(light, light, light, 1) * color;
    }
    

    processing

    PShape can;
    import peasy.*;
    PeasyCam cam;
    
    
    PShader lightShader;
    
    
    void setup() {
      size(800, 600, P3D);
      can = createCan(100, 200, 32);
      lightShader = loadShader("lightfrag.glsl", "lightvert.glsl");
    
    }
    
    void draw() {    
      background(50);
    
      shader(lightShader);
      /*lightShader.set("SpecularFocus",75.0);//sharpness of spec highlights
      lightShader.set("SpecularContribution", 0.25);//influence of specualurity on surfaces
      lightShader.set("DiffuseContribution", 0.575);//influence of diffuse light on surfaces
      lightShader.set("AmbientContribution", 0.025, 0.025,  0.025, 0.0);
      pointLight(50,50,50,width/2,height/2, 400);*/
    
      //shader(lightShader);
      lightShader.set("SpecularFocus",10.0);//sharpness of spec highlights
      lightShader.set("SpecularContribution", 0.5);//influence of specualurity on surfaces
      lightShader.set("DiffuseContribution", 0.25);//influence of diffuse light on surfaces
      pointLight(100, 100, 100, mouseX, mouseY, 400); 
    
    
    
    
      translate(width/2, height/2);
      //shape(can);
      box(190);
      sphere(200);
    
    }
    
    PShape createCan(float r, float h, int detail) {
      textureMode(NORMAL);
      PShape sh = createShape();
      sh.beginShape(QUAD_STRIP);
      sh.noStroke();
      for (int i = 0; i <= detail; i++) {
        float angle = TWO_PI / detail;
        float x = sin(i * angle);
        float z = cos(i * angle);
        float u = float(i) / detail;
        sh.normal(x, 0, z);
        sh.vertex(x * r, -h/2, z * r, u, 0);
        sh.vertex(x * r, +h/2, z * r, u, 1);
      }
      sh.endShape(); 
      return sh;
    }
    
  • edited March 2015

    also what is the correct syntax to create an array of lights in processing

  • edited March 2015

    "its a school project so I don't want the answer as much as to be put in the right direction to getting it. thanks"

    As I said before, I'm not absolutly sure to know how all works, I'm learning too :)

    "please elaborate"

    I was not thinking about the GLSL code but the processing side. In your processing code, you define a single light by shader then... you will get a single light in your shader, that's logical :)

    In your processing code, you define your light after the shader call, it's doesn't have any sense ; the uniforms should be defined before the call of "shader" too (but it doesn't change anything cause the values are stored and updated the next frame)

    If you want to have 8 lights, I may be wrong but I think you should do 8 calls of "spotLight" before doing the call of "shader"

    "what is the correct syntax to create an array of lights in processing" There is no such things actually because the array of light is already created by processing by itself :) You just have to call "spotLight"

    I'm not 100% sure about it but I think it's how it works

    EDIT : try maybe to create what you want with default light rendering shader. When it will work as expected with default-shader, you will be at least sure that the processing side is correct

  • edited March 2015

    In your processing code, you define a single light by shader then... you will get a single light in your shader, that's logical

    how am I defining a single light by the shader ......this I what I don't understand you keep saying that but I don't get why.....

    1. is it the for loop in the shader
    2. should I be creating a loop in processing as well

    3.shouldn't calling pointLight() x times give a new light to work with that's what has me confused

    also the commented light code in the example isn't supposed to be commented out that was an oversight

    even if as you say I should declare all my lights first how do associate each light with the parameters I want, since I cant figure out how to uniquely identify and recall a particular light later on in processing....that's kind of unclear

    a have switched thing up and still does not look right

     shader(lightShader);
    
      lightShader.set("SpecularFocus",75.0);//sharpness of spec highlights
      lightShader.set("SpecularContribution", 0.25);//influence of specualurity on surfaces
      lightShader.set("DiffuseContribution", 0.575);//influence of diffuse light on surfaces
      lightShader.set("AmbientContribution", 0.025, 0.025,  0.025, 0.0);
      pointLight(250,50,50,width/2,height/2, 400);
    
      lightShader.set("SpecularFocus",10.0);//sharpness of spec highlights
      lightShader.set("SpecularContribution", 0.5);//influence of specualurity on surfaces
      lightShader.set("DiffuseContribution", 0.25);//influence of diffuse light on surfaces
      pointLight(100, 100, 100, mouseX, mouseY, 400); 
    
  • edited March 2015

    "I what I don't understand you keep saying that" because in your previous code, some code was commented and you had a single call of "pointLight", then you had a single light defined in your shader.

    "shouldn't calling pointLight() x times give a new light to work with that's what has me confused"

    In your GLSL code, you have an array of light, ok ? I suppose that the uniform "lightCount" match to the amount of "pointLight" call. If it's true, then it means that lightPosition[0] contains the position of the first light, lightPosition[1] the position of the second, etc...

    If now you want to set some custom values for each light, you will need to "copy" the structure of how lights works in your current GLSL code : it means you have to store your custom values in an array with an amount of entry that match to "lightCount" and then, in your loop in the GLSL, you 'll be able to write something like that

    for(i=0;i<lightCount;i++){
        lightPositions[i].xyz += offsetCustomPosition[i];
    }
    
  • ok I'll take a closer look

  • edited March 2015

    I understand now how you think it works, but it doesn't :)

    You think that, when you write

    lightShader.set("SpecularFocus",75.0);//sharpness of spec highlights
     lightShader.set("SpecularContribution", 0.25);//influence of specualurity on surfaces
     lightShader.set("DiffuseContribution", 0.575);//influence of diffuse light on surfaces
     lightShader.set("AmbientContribution", 0.025, 0.025,  0.025, 0.0);
     pointLight(250,50,50,width/2,height/2, 400);
    

    the uniforms are pointing to the pointLight called just after, but it doesn't work like that.

    When you send the uniform data to the shader, you send everything at the same time, then if you write 5 times (for example)

    lightShader.set("SpecularFocus",75.0);

    Actually, it's like you wrote it only once because you're saying "in my shader, there is only one variable called 'SpecularFocus' and I set it's value to 75.0"

    All what you send to the shader is numeric values. You can give them a name like "vertex", "color" or "light" but it's just a name, like a classic variable name that contains a float, a int, a bool, ...

    The way how we use the numeric values is defined in the GLSL code only. Processing has no impact at all on how the shader works, it only send a bunch of datas to OpenGL and you manage these datas with GLSL to draw what you want

    In that particular case, you are constraint by the variable-structure of processing-built-in-variable. You probably use to set single floats as uniform and Processing send all the value in a single call via an array of floats and there is nothing you can do against that : you have to use an array of floats to store your customs values and apply it inside the loop for each light !

  • edited March 2015

    yeah thanks, I think I get what u are saying I took a look at the packaged lighting shader and the uniforms similar to mine are actually declared in an array structure therefore I also need to store my uniforms in an array is that correct is there any thing else u see that I should also declared as an array structure thanks

  • got it working thanks for your help

  • If your interresting I find solution to change color for the multiple spot light with per pixel vertex The solution for the multiple spot light per pixel https://github.com/StanLepunK/processing-Shader/tree/master/MultiLightChangeColorOfLight_4a

  • Great ! Thank you !

Sign In or Register to comment.