2017-08-16 33 views
1

我的程序是一個房間,中間有一個聚光燈(由球體描繪)。如何更改我的片段着色器以允許另外兩個聚光燈?

enter image description here

我想在房間的角落增加2個燈,但我不知道如何改變main功能在我的片段着色器允許這樣。我編輯了我的主程序來設置2個新燈的屬性並將它們綁定到片段着色器。

片段着色器

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

主程序

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

    ... 
} 

回答

0

既然你已經有光源,你只需要總結的單一光源的光色計算陣列。

創建一個新的統一的變量,它持有的光源數量:

uniform int u_noOfLights; 

不要忘記,當您設置光屬性來設置統一。

將函數中的所有計算光源顏色的代碼移動到一個函數中。 該函數應該有一個輸入參數,在該參數中可以傳遞要計算的光源的索引。

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

在片段的main你必須實現一個for循環它迭代光源和總結了由函數計算的 光色:

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

你是一個創造奇蹟的人 – Zolly

+0

@Zolly不,但有二十年的編程經驗。 – Rabbid76

+0

哇這是很多。看起來就像18年之後 – Zolly

相關問題