我的节目是一个聚光灯在中心的房间(由球体描绘)。
我想在房间的角落再添加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 :(得分: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;
}