2017-08-16 2 views
1

Mein Programm ist ein Raum mit einem Scheinwerfer in der Mitte (durch die Kugel dargestellt).Wie kann ich meinen Fragment-Shader ändern, um zwei weitere Scheinwerfer zuzulassen?

enter image description here

Ich möchte zwei weitere Lichter in den Ecken des Raumes hinzuzufügen, aber ich bin nicht sicher, wie die main Funktion in meinem Fragment-Shader dies zu ermöglichen, ändern. Ich habe mein Hauptprogramm bearbeitet, um die Eigenschaften von 2 neuen Lichtern festzulegen und sie an den Fragment-Shader zu binden.

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;  
} 

Hauptprogramm

#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 
    } 

    ... 
} 

Antwort

0

Da Sie bereits eine Reihe von Lichtquellen haben Sie nur die Lichtfarbe Berechnungen der einzelnen Lichtquellen zusammenzufassen haben.

ein neues Uniform-Variable erstellen, die die Anzahl der Lichtquellen gelten:

uniform int u_noOfLights; 

Vergessen Sie nicht, die Uniform zu setzen, wenn Sie die Lichteigenschaften einrichten.

Verschieben Sie den Code, der die Lichtfarbe für eine Lichtquelle in einer Funktion berechnet. Die Funktion sollte einen Eingangsparameter haben, in dem der Index der zu berechnenden Lichtquelle übergeben werden kann.

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; 
} 

Im main des Fragments Sie eine for Schleife zu implementieren, die die Lichtquellen iteriert und fasst die Lichtfarben durch die Funktion berechnet:

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

du bist ein Wundertäter – Zolly

+0

@Zolly Nein, aber 2 Jahrzehnte Programmiererfahrung. – Rabbid76

+0

woah das ist viel. Scheint wie im 18 Jahre weg – Zolly

Verwandte Themen