### 问题描述

```// Inputs from application.
// Generally, "in" like the position and normal vectors for things that change frequently,
// and "uniform" for things that change less often (think scene versus vertices).

in vec3 position_cam, normal_cam;
uniform mat4 view_mat;

// This light setup would usually be passed in from the application.

vec3 light_position_world  = vec3 (10.0, 25.0, 10.0);
vec3 Ls = vec3 (1.0, 1.0, 1.0);    // neutral, full specular color of light
vec3 Ld = vec3 (0.8, 0.8, 0.8);    // neutral, lessened diffuse light color of light
vec3 La = vec3 (0.12, 0.12, 0.12); // ambient color of light - just a bit more than dk gray    bg

// Surface reflectance properties for Phong model below.

vec3 Ks = vec3 (1.0, 1.0, 1.0);    // fully reflect specular light
vec3 Kd = vec3 (0.32, 0.18, 0.5);  // purple diffuse surface reflectance
vec3 Ka = vec3 (1.0, 1.0, 1.0);    // fully reflect ambient light

float specular_exponent = 400.0;   // specular 'power' -- controls "roll-off"

// Shader programs can also designate outputs.
out vec4 fragment_color;           // color of surface to draw in this case

void main ()
{

fragment_color = vec4 (Kd, 1.0);

}
```

1. 如何在我的代码中添加 2 个额外的定向光源?我是简单地在我的灯光设置中添加更多 vec3 Ld 变量还是我必须做的其他事情?
2. 如何将 Phong 指数设置得足够高以产生清晰明亮的高光?

## 推荐答案

```const int no_of_lights = 2;

struct TLightSource
{
vec3 lightPos;
vec3 Ls;
vec3 Ld;
vec3 La;
float shininess;
};

TLightSource lightSources[no_of_lights] = TLightSource[no_of_lights](
TLightSource(vec3(10.0, 25.0, 10.0), vec3(1.0, 1.0, 1.0), vec3(0.8, 0.8, 0.8), vec3(0.12, 0.12, 0.12), 10.0),
TLightSource(vec3(-10.0, 25.0, 10.0), vec3(1.0, 0.0, 0.0), vec3(0.8, 0.0, 0.0), vec3(0.12, 0.0, 0.0), 10.0)
);
```

```void main()
{
vec3 normalInterp;
vec3 vertPos;

vec3 normal = normalize(normalInterp);

vec3 color = vec3(0.0);
for (int i=0; i < no_of_lights; i++)
{
color += Ka * lightSources[i].La;

vec3 lightDir = normalize(lightSources[i].lightPos - vertPos);
float lambertian = max(dot(lightDir, normal), 0.0);
color += lambertian * lightSources[i].Ld;

if (lambertian > 0.0)
{
vec3 viewDir = normalize(-vertPos);
vec3 reflectDir = reflect(-lightDir, normal);
float RdotV = max(dot(reflectDir, viewDir), 0.0);
float specular = pow(RdotV, lightSources[i].shininess/4.0);
color += specular * lightSources[i].Ls;
}
}

frag_color = vec4(color, 1.0);
}
```

### 问题描述

In the code below I am trying to implement a fragment shader program for Phong:

```// Inputs from application.
// Generally, "in" like the position and normal vectors for things that change frequently,
// and "uniform" for things that change less often (think scene versus vertices).

in vec3 position_cam, normal_cam;
uniform mat4 view_mat;

// This light setup would usually be passed in from the application.

vec3 light_position_world  = vec3 (10.0, 25.0, 10.0);
vec3 Ls = vec3 (1.0, 1.0, 1.0);    // neutral, full specular color of light
vec3 Ld = vec3 (0.8, 0.8, 0.8);    // neutral, lessened diffuse light color of light
vec3 La = vec3 (0.12, 0.12, 0.12); // ambient color of light - just a bit more than dk gray    bg

// Surface reflectance properties for Phong model below.

vec3 Ks = vec3 (1.0, 1.0, 1.0);    // fully reflect specular light
vec3 Kd = vec3 (0.32, 0.18, 0.5);  // purple diffuse surface reflectance
vec3 Ka = vec3 (1.0, 1.0, 1.0);    // fully reflect ambient light

float specular_exponent = 400.0;   // specular 'power' -- controls "roll-off"

// Shader programs can also designate outputs.
out vec4 fragment_color;           // color of surface to draw in this case

void main ()
{

fragment_color = vec4 (Kd, 1.0);

}
```

I have two questions:

1. How do I add 2 additional directional light sources to my code? Do I simply add more vec3 Ld variables to my light setup or is there something else I must do?
2. How do I set the Phong exponent high enough to produce sharp and bright highlights?

## 推荐答案

In glsl you can use arrays and structures. Define an array of light sources. See Array constructors and Struct constructors:

```const int no_of_lights = 2;

struct TLightSource
{
vec3 lightPos;
vec3 Ls;
vec3 Ld;
vec3 La;
float shininess;
};

TLightSource lightSources[no_of_lights] = TLightSource[no_of_lights](
TLightSource(vec3(10.0, 25.0, 10.0), vec3(1.0, 1.0, 1.0), vec3(0.8, 0.8, 0.8), vec3(0.12, 0.12, 0.12), 10.0),
TLightSource(vec3(-10.0, 25.0, 10.0), vec3(1.0, 0.0, 0.0), vec3(0.8, 0.0, 0.0), vec3(0.12, 0.0, 0.0), 10.0)
);
```

User a for loop to iterate through the light sources and sum up the light color for ambient, diffuse and specular light (e.g Phong reflection model):

```void main()
{
vec3 normalInterp;
vec3 vertPos;

vec3 normal = normalize(normalInterp);

vec3 color = vec3(0.0);
for (int i=0; i < no_of_lights; i++)
{
color += Ka * lightSources[i].La;

vec3 lightDir = normalize(lightSources[i].lightPos - vertPos);
float lambertian = max(dot(lightDir, normal), 0.0);
color += lambertian * lightSources[i].Ld;

if (lambertian > 0.0)
{
vec3 viewDir = normalize(-vertPos);
vec3 reflectDir = reflect(-lightDir, normal);
float RdotV = max(dot(reflectDir, viewDir), 0.0);
float specular = pow(RdotV, lightSources[i].shininess/4.0);
color += specular * lightSources[i].Ls;
}
}

frag_color = vec4(color, 1.0);
}
```