2017-08-16 4 views
1

Mon programme est une pièce avec un projecteur au centre (représenté par la sphère).Comment puis-je changer mon fragment shader pour permettre 2 projecteurs de plus?

enter image description here

Je veux ajouter 2 autres lumières dans les coins de la pièce, mais je ne suis pas sûr de savoir comment changer la fonction main dans mon fragment shader pour le permettre. J'ai édité mon programme principal pour définir les propriétés de 2 nouvelles lumières et les lier au fragment shader.

Fragment Shader

#version 330 core 

#define MAX_MATERIALS 12 
#define MAX_LIGHTS 3 

// interpolated values from the vertex shaders 
in vec3 vNormal; 
in vec3 vPosition; 

// uniform input data 
struct LightProperties 
{ 
    vec4 position; 
    vec4 ambient; 
    vec4 diffuse; 
    vec4 specular; 
    float shininess; 
    vec3 attenuation; 
    float cutoffAngle; 
    vec3 direction; 
}; 

struct MaterialProperties 
{ 
    vec4 ambient; 
    vec4 diffuse; 
    vec4 specular; 
}; 

uniform int uMaterialIndex; 
uniform LightProperties uLightingProperties[MAX_LIGHTS]; 
uniform MaterialProperties uMaterialProperties[MAX_MATERIALS]; 
uniform vec3 uViewPoint; 

// output data 
out vec3 fColor; 

void main() 
{ 
    // calculate vectors for lighting 
    vec3 N = normalize(vNormal); 
    vec3 L; 
    float attenuation = 1.0f; 

    // calculate the attenuation based on distance 
    L = (uLightingProperties.position).xyz - vPosition; 
    float distance = length(L); 
    L = normalize(L); 
    attenuation = 1/(uLightingProperties.attenuation.x 
     + uLightingProperties.attenuation.y * distance 
     + uLightingProperties.attenuation.z * distance * distance); 

    vec3 V = normalize(uViewPoint - vPosition); 
    vec3 R = reflect(-L, N); 

    // the direction of the spotlight 
    vec3 direction = normalize(uLightingProperties.direction); 
    // the angle between the vector from the light to the fragment’s position and the spotlight’s direction 
    float angle = degrees(acos(dot(-L, direction))); 

    vec3 colour = vec3(0.0f, 0.0f, 0.0f); 

    // only compute if angle is less than the cutoff angle 
    if(angle <= uLightingProperties.cutoffAngle) 
    { 
     int i = uMaterialIndex; 

     // calculate Phong lighting 
     vec4 ambient = uLightingProperties.ambient * uMaterialProperties[i].ambient; 
     vec4 diffuse = uLightingProperties.diffuse * uMaterialProperties[i].diffuse * max(dot(L, N), 0.0); 
     vec4 specular = vec4(0.0f, 0.0f, 0.0f, 1.0f); 

     if(dot(L, N) > 0.0f) 
     { 
      specular = uLightingProperties.specular * uMaterialProperties[i].specular 
       * pow(max(dot(V, R), 0.0), uLightingProperties.shininess); 
     } 

     colour = (attenuation * (diffuse + specular)).rgb + ambient.rgb; 
     // fade the spotlight's intensity linearly with angle 
     colour *= 1.0f - angle/uLightingProperties.cutoffAngle; 
    } 

    // set output color 
    fColor = colour;  
} 

programme principal

#define MAX_LIGHTS 3 
#define MAX_MATERIALS 12 

// struct for lighting properties 
struct LightProperties 
{ 
    vec4 position; 
    vec4 ambient; 
    vec4 diffuse; 
    vec4 specular; 
    float shininess; 
    vec3 attenuation; 
    float cutoffAngle; 
    vec3 direction; 
}; 

// struct for material properties 
struct MaterialProperties 
{ 
    vec4 ambient; 
    vec4 diffuse; 
    vec4 specular; 
}; 

LightProperties g_lightProperties[MAX_LIGHTS]; 
MaterialProperties g_materialProperties[MAX_MATERIALS]; 

// Meshes 
Vertex* g_pMeshVertices[MAX_MESH] = { NULL }; // pointer to mesh vertices 
GLint g_numberOfVertices[MAX_MESH] = { 0 };  // number of vertices in the mesh 
GLint* g_pMeshIndices[MAX_MESH] = { NULL };  // pointer to mesh indices 
GLint g_numberOfFaces[MAX_MESH] = { 0 };  // number of faces in the mesh 

GLuint g_IBO[4];    // index buffer object identifier 
GLuint g_VBO[5];    // vertex buffer object identifier 
GLuint g_VAO[5];    // vertex array object identifier 
GLuint g_shaderProgramID = 0; // shader program identifier 

// Values for spotlight 
glm::vec3 g_spotlight_ambient(0.2f, 0.2f, 0.2f); 
glm::vec3 g_spotlight_diffuse(0.5f, 0.5f, 0.5f); 
glm::vec3 g_spotlight_specular(0.0f, 0.5f, 0.5f); 

// locations in shader 
GLuint g_MVP_Index; 
GLuint g_M_Index = 0; 
GLuint g_viewPointIndex = 0; 
GLuint g_lightPositionIndex[MAX_LIGHTS]; 
GLuint g_lightAmbientIndex[MAX_LIGHTS]; 
GLuint g_lightDiffuseIndex[MAX_LIGHTS]; 
GLuint g_lightSpecularIndex[MAX_LIGHTS]; 
GLuint g_lightShininessIndex[MAX_LIGHTS]; 
GLuint g_lightAttenuationIndex[MAX_LIGHTS]; 
GLuint g_lightCutoffAngleIndex[MAX_LIGHTS]; 
GLuint g_lightDirectionIndex[MAX_LIGHTS]; 
GLuint g_materialIndex = 0; 
GLuint g_materialAmbientIndex[MAX_MATERIALS]; 
GLuint g_materialDiffuseIndex[MAX_MATERIALS]; 
GLuint g_materialSpecularIndex[MAX_MATERIALS]; 

static void init(GLFWwindow* window) 
{ 
    glEnable(GL_DEPTH_TEST); // enable depth buffer test 

    // create and compile our GLSL program from the shader files 
    g_shaderProgramID = loadShaders("PerFragLightingVS.vert", "PerFragLightingFS.frag"); 

    // find the location of shader variables 
    GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition"); 
    GLuint normalIndex = glGetAttribLocation(g_shaderProgramID, "aNormal"); 
    g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix"); 
    g_M_Index = glGetUniformLocation(g_shaderProgramID, "uModelMatrix"); 
    g_viewPointIndex = glGetUniformLocation(g_shaderProgramID, "uViewPoint"); 

    g_lightPositionIndex[0] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[0].position"); 
    g_lightAmbientIndex[0] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[0].ambient"); 
    g_lightDiffuseIndex[0] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[0].diffuse"); 
    g_lightSpecularIndex[0] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[0].specular"); 
    g_lightShininessIndex[0] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[0].shininess"); 
    g_lightAttenuationIndex[0] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[0].attenuation"); 
    g_lightCutoffAngleIndex[0] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[0].cutoffAngle"); 
    g_lightDirectionIndex[0] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[0].direction"); 

    g_lightPositionIndex[1] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[1].position"); 
    g_lightAmbientIndex[1] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[1].ambient"); 
    g_lightDiffuseIndex[1] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[1].diffuse"); 
    g_lightSpecularIndex[1] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[1].specular"); 
    g_lightShininessIndex[1] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[1].shininess"); 
    g_lightAttenuationIndex[1] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[1].attenuation"); 
    g_lightCutoffAngleIndex[1] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[1].cutoffAngle"); 
    g_lightDirectionIndex[1] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[1].direction"); 

    g_lightPositionIndex[2] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[2].position"); 
    g_lightAmbientIndex[2] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[2].ambient"); 
    g_lightDiffuseIndex[2] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[2].diffuse"); 
    g_lightSpecularIndex[2] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[2].specular"); 
    g_lightShininessIndex[2] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[2].shininess"); 
    g_lightAttenuationIndex[2] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[2].attenuation"); 
    g_lightCutoffAngleIndex[2] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[2].cutoffAngle"); 
    g_lightDirectionIndex[2] = glGetUniformLocation(g_shaderProgramID, "uLightingProperties[2].direction"); 

    g_materialIndex = glGetUniformLocation(g_shaderProgramID, "uMaterialIndex"); // to change the index for material in fragment shader 

    // Find location for uniform matrix (material properties) 
    for (int i = 0; i < MAX_MATERIALS; i++) { 
     std::string str = "uMaterialProperties[" + std::to_string(i); 
     g_materialAmbientIndex[i] = glGetUniformLocation(g_shaderProgramID, (str + "].ambient").data()); 
     g_materialDiffuseIndex[i] = glGetUniformLocation(g_shaderProgramID, (str + "].diffuse").data()); 
     g_materialSpecularIndex[i] = glGetUniformLocation(g_shaderProgramID, (str + "].specular").data()); 
    } 

    ... 

// initialise light and material properties 
    g_lightProperties[0].position = glm::vec4(0.0f, 2.0f, 0.0f, 1.0f); 
    g_lightProperties[0].ambient = glm::vec4(g_spotlight_ambient[0], g_spotlight_ambient[1], g_spotlight_ambient[2], 1.0f); 
    g_lightProperties[0].diffuse = glm::vec4(g_spotlight_diffuse[0], g_spotlight_diffuse[1], g_spotlight_diffuse[2], 1.0f); 
    g_lightProperties[0].specular = glm::vec4(g_spotlight_specular[0], g_spotlight_specular[1], g_spotlight_specular[2], 1.0f); 
    g_lightProperties[0].shininess = 10.0f; 
    g_lightProperties[0].attenuation = glm::vec3(1.0f, 0.0f, 0.0f); 
    g_lightProperties[0].cutoffAngle = 150.0f; 
    g_lightProperties[0].direction = glm::vec3(0.0f, -1.0f, 0.0f); 

    g_lightProperties[1].position = glm::vec4(-2.0f, 2.0f, 0.0f, 1.0f); 
    g_lightProperties[1].ambient = glm::vec4(g_spotlight_ambient[0], g_spotlight_ambient[1], g_spotlight_ambient[2], 1.0f); 
    g_lightProperties[1].diffuse = glm::vec4(g_spotlight_diffuse[0], g_spotlight_diffuse[1], g_spotlight_diffuse[2], 1.0f); 
    g_lightProperties[1].specular = glm::vec4(g_spotlight_specular[0], g_spotlight_specular[1], g_spotlight_specular[2], 1.0f); 
    g_lightProperties[1].shininess = 10.0f; 
    g_lightProperties[1].attenuation = glm::vec3(1.0f, 0.0f, 0.0f); 
    g_lightProperties[1].cutoffAngle = 150.0f; 
    g_lightProperties[1].direction = glm::vec3(0.0f, -1.0f, 0.0f); 

    g_lightProperties[2].position = glm::vec4(2.0f, 2.0f, 0.0f, 1.0f); 
    g_lightProperties[2].ambient = glm::vec4(g_spotlight_ambient[0], g_spotlight_ambient[1], g_spotlight_ambient[2], 1.0f); 
    g_lightProperties[2].diffuse = glm::vec4(g_spotlight_diffuse[0], g_spotlight_diffuse[1], g_spotlight_diffuse[2], 1.0f); 
    g_lightProperties[2].specular = glm::vec4(g_spotlight_specular[0], g_spotlight_specular[1], g_spotlight_specular[2], 1.0f); 
    g_lightProperties[2].shininess = 10.0f; 
    g_lightProperties[2].attenuation = glm::vec3(1.0f, 0.0f, 0.0f); 
    g_lightProperties[2].cutoffAngle = 150.0f; 
    g_lightProperties[2].direction = glm::vec3(0.0f, -1.0f, 0.0f); 

    ... 
} 

// function used to render the scene 
static void render_scene() 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer 

    glUseProgram(g_shaderProgramID); // use the shaders associated with the shader program 

    glBindVertexArray(g_VAO[0]);  // make VAO active 

// Set uniform matrix for material properties 
    for (int i = 0; i < MAX_MATERIALS; i++) { 
     glUniform4fv(g_materialAmbientIndex[i], 1, &g_materialProperties[i].ambient[0]); 
     glUniform4fv(g_materialDiffuseIndex[i], 1, &g_materialProperties[i].diffuse[0]); 
     glUniform4fv(g_materialSpecularIndex[i], 1, &g_materialProperties[i].specular[0]); 
    } 
// Set uniform matrix for light properties 
    for (int i = 0; i < MAX_LIGHTS; i++) { 
     glUniform4fv(g_lightPositionIndex[i], 1, &g_lightProperties[i].position[0]); 
     glUniform4fv(g_lightAmbientIndex[i], 1, &g_lightProperties[i].ambient[0]); 
     glUniform4fv(g_lightDiffuseIndex[i], 1, &g_lightProperties[i].diffuse[0]); 
     glUniform4fv(g_lightSpecularIndex[i], 1, &g_lightProperties[i].specular[0]); 
     glUniform1fv(g_lightShininessIndex[i], 1, &g_lightProperties[i].shininess); 
     glUniform3fv(g_lightAttenuationIndex[i], 1, &g_lightProperties[i].attenuation[0]); 
     glUniform1fv(g_lightCutoffAngleIndex[i], 1, &g_lightProperties[i].cutoffAngle); 
     glUniform3fv(g_lightDirectionIndex[i], 1, &g_lightProperties[i].direction[0]); 
    } 

    ... 
} 

int main(void) 
{ 
    ... 

    // initialise AntTweakBar 
    TwInit(TW_OPENGL_CORE, NULL); 

    // give tweak bar the size of graphics window 
    TwWindowSize(g_windowWidth, g_windowHeight); 
    TwDefine(" TW_HELP visible=false "); // disable help menu 
    TwDefine(" GLOBAL fontsize=3 ");  // set large font size 

    // create a tweak bar 
    TweakBar = TwNewBar("Main"); 
    TwDefine(" Main label='Controls' refresh=0.02 text=light size='220 600' "); 

    // create display entries 
    TwAddVarRW(TweakBar, "Wireframe", TW_TYPE_BOOLCPP, &g_wireFrame, " group='Display' "); 

    // display a separator 
    TwAddSeparator(TweakBar, NULL, NULL); 

    // create spotlight entries 
    TwAddVarRW(TweakBar, "Cutoff", TW_TYPE_FLOAT, &g_lightProperties[0].cutoffAngle, " group='Spotlight' min=-180.0 max=180.0 step=1.0 "); 
    TwAddVarRW(TweakBar, "Direction: x", TW_TYPE_FLOAT, &g_lightProperties[0].direction[0], " group='Spotlight' min=-1.0 max=1.0 step=0.1"); 
    TwAddVarRW(TweakBar, "Direction: y", TW_TYPE_FLOAT, &g_lightProperties[0].direction[1], " group='Spotlight' min=-1.0 max=1.0 step=0.1"); 
    TwAddVarRW(TweakBar, "Direction: z", TW_TYPE_FLOAT, &g_lightProperties[0].direction[2], " group='Spotlight' min=-1.0 max=1.0 step=0.1"); 
    // create transformation entries 
    TwAddVarRW(TweakBar, "A Red", TW_TYPE_FLOAT, &g_spotlight_ambient[0], " group='Ambient' min=-1.0 max=1.0 step=0.01"); 
    TwAddVarRW(TweakBar, "A Green", TW_TYPE_FLOAT, &g_spotlight_ambient[1], " group='Ambient' min=-1.0 max=1.0 step=0.01"); 
    TwAddVarRW(TweakBar, "A Blue", TW_TYPE_FLOAT, &g_spotlight_ambient[2], " group='Ambient' min=-1.0 max=1.0 step=0.01"); 

    TwAddVarRW(TweakBar, "D Red", TW_TYPE_FLOAT, &g_spotlight_diffuse[0], " group='Diffuse' min=-1.0 max=1.0 step=0.01"); 
    TwAddVarRW(TweakBar, "D Green", TW_TYPE_FLOAT, &g_spotlight_diffuse[1], " group='Diffuse' min=-1.0 max=1.0 step=0.01"); 
    TwAddVarRW(TweakBar, "D Blue", TW_TYPE_FLOAT, &g_spotlight_diffuse[2], " group='Diffuse' min=-1.0 max=1.0 step=0.01"); 

    TwAddVarRW(TweakBar, "S Red", TW_TYPE_FLOAT, &g_spotlight_specular[0], " group='Specular' min=-1.0 max=1.0 step=0.01"); 
    TwAddVarRW(TweakBar, "S Green", TW_TYPE_FLOAT, &g_spotlight_specular[1], " group='Specular' min=-1.0 max=1.0 step=0.01"); 
    TwAddVarRW(TweakBar, "S Blue", TW_TYPE_FLOAT, &g_spotlight_specular[2], " group='Specular' min=-1.0 max=1.0 step=0.01"); 

    TwAddVarRW(TweakBar, "Light", TW_TYPE_BOOLCPP, &g_switchOn, " group='Toggle ON/OFF' "); 
    TwAddVarRW(TweakBar, "Disco", TW_TYPE_BOOLCPP, &g_disco_mode, " group='Toggle ON/OFF' "); 

    // initialise rendering states 
    init(window); 

    // the rendering loop 
    while (!glfwWindowShouldClose(window)) 
    { 
     g_camera.update(window); // update camera 

     if (g_wireFrame) 
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 

     update_scene();  // update the scene 
     render_scene();  // render the scene 

     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 

     TwDraw();   // draw tweak bar(s) 

     glfwSwapBuffers(window); // swap buffers 
     glfwPollEvents();   // poll for events 
    } 

    ... 
} 

Répondre

0

Puisque vous avez déjà un réseau de sources lumineuses vous suffit de résumer les calculs de couleur claire des sources lumineuses individuelles.

Créer une nouvelle variable uniforme qui détient le nombre des sources lumineuses:

uniform int u_noOfLights; 

Ne pas oublier de mettre l'uniforme lorsque vous configurez les propriétés de la lumière.

Déplace tout le code qui calcule la couleur de la lumière pour la source de lumière dans une fonction. La fonction doit avoir un paramètre d'entrée dans lequel l'indice de la source lumineuse à calculer peut être passé.

vec3 Light(vec3 N, int index) 
{ 
    float attenuation = 1.0f; 

    // calculate the attenuation based on distance 
    vec3 L = (uLightingProperties[index].position).xyz - vPosition; 
    float distance = length(L); 
    L = normalize(L); 
    attenuation = 1/(uLightingProperties[index].attenuation.x 
     + uLightingProperties[index].attenuation.y * distance 
     + uLightingProperties[index].attenuation.z * distance * distance); 

    vec3 V = normalize(uViewPoint - vPosition); 
    vec3 R = reflect(-L, N); 

    // the direction of the spotlight 
    vec3 direction = normalize(uLightingProperties[index].direction); 
    // the angle between the vector from the light to the fragment’s position and the spotlight’s direction 
    float angle = degrees(acos(dot(-L, direction))); 

    vec3 colour = vec3(0.0f, 0.0f, 0.0f); 

    // only compute if angle is less than the cutoff angle 
    if(angle <= uLightingProperties[index].cutoffAngle) 
    { 
     int i = uMaterialIndex; 

     // calculate Phong lighting 
     vec4 ambient = uLightingProperties[index].ambient * uMaterialProperties[i].ambient; 
     vec4 diffuse = uLightingProperties[index].diffuse * uMaterialProperties[i].diffuse * max(dot(L, N), 0.0); 
     vec4 specular = vec4(0.0f, 0.0f, 0.0f, 1.0f); 

     if(dot(L, N) > 0.0f) 
     { 
      specular = uLightingProperties[index].specular * uMaterialProperties[i].specular 
       * pow(max(dot(V, R), 0.0), uLightingProperties[index].shininess); 
     } 

     colour = (attenuation * (diffuse + specular)).rgb + ambient.rgb; 
     // fade the spotlight's intensity linearly with angle 
     colour *= 1.0f - angle/uLightingProperties[index].cutoffAngle; 
    } 
    return colour; 
} 

Dans le main du fragment que vous devez mettre en œuvre une boucle for qui itère les sources lumineuses et résume les couleurs claires calculées par la fonction:

void main() 
{ 
    vec3 N = normalize(vNormal); 
    vec3 colour = vec3(0.0f, 0.0f, 0.0f); 
    for (int i = 0; i < u_noOfLights; ++i) 
     colour += Light(N, i); 

    // set output color 
    fColor = colour;  
} 
+0

vous êtes un travailleur miracle – Zolly

+0

@Zolly Non, mais 2 décennies d'expérience en programmation. – Rabbid76

+0

woah c'est beaucoup. On dirait im dans 18 ans – Zolly