
#version 330 core
out vec4 FragColor;
in vec3 Normal;
in vec3 FragPos;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform vec3 objectColor;
void main()
{
// ambient
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
// specular
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;
vec3 result = (ambient + diffuse + specular) * objectColor;
FragColor = vec4(result, 1.0);
}
fragment shader의 원래 코드는 이랬음
3D materials parameter
이런거나
OpenGL Materials
이런 웹사이트를 보면
ambient, diffuse, specular는 RGB(A)값으로 vec3를 사용하고
shiness는 float을 사용하는걸 알 수 있음
즉, 우리가 설정한 object color에서 색상을 결정짓는게 아니라
각 ambient, diffuse, specular에서 각각 적용되는 색상이 따로 존재한다는거임
이런 머티리얼을 사용하려면서 fragment shader를 약간 수정해줘야함
#version 330 core
struct Material
{
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
uniform Material mat;
먼저 이런 struct를 만들어줌
GLSL, 쉐이더 내부에서도 이렇게 구조체를 선언해서
그걸 uniform으로 외부에 노출시켜 값을 지정해서 사용하도록 할 수 있음
그리고
위의 웹사이트 등을 기반으로 머티리얼을 설정할거라,
color가 필요한곳에 직접 머티리얼의 변수들을 사용해주면 됨
#version 330 core
struct Material
{
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec3 LightPos;
uniform vec3 viewPos;
uniform Material mat;
void main()
{
// ambient
vec3 ambient = mat.ambient * lightColor;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(LightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * mat.diffuse * lightColor;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), mat.shininess);
vec3 specular = mat.specular * spec * lightColor;
vec3 result = (ambient + diffuse + specular);
FragColor = vec4(result, 1.0);
}
이렇게 코드가 바뀌게 됨

이 brass라는 머티리얼을 사용해볼거임

대충 이런 재질임
//material 설정
normalCubeShader.use();
normalCubeShader.setVec3("mat.ambient", glm::vec3(0.329412f, 0.223529f, 0.027451f));
normalCubeShader.setVec3("mat.diffuse", glm::vec3(0.780392f, 0.568627f, 0.113725f));
normalCubeShader.setVec3("mat.specular", glm::vec3(0.992157f, 0.941176f, 0.807843f));
normalCubeShader.setFloat("mat.shininess", 27.8974f);
이렇게 머티리얼을 설정해줌

이게 맞음?ㅋㅋㅋㅋㅋㅋㅋㅋㅋ
빛도 세기를 가지고 있음
ambient나 diffuse나 specular에 적용될 세기는 다 달라야함
void main()
{
// ambient
vec3 ambient = mat.ambient * lightColor;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(LightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * mat.diffuse * lightColor;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), mat.shininess);
vec3 specular = mat.specular * spec * lightColor;
vec3 result = (ambient + diffuse + specular);
FragColor = vec4(result, 1.0);
}
근데 우리 fragment shader를 보면
다 일정한 lightColor를 곱하주고 있는걸 볼 수 있음
따라서 이를 위한 struct도 하나 만들어주는게 좋음
전체 fragment shader는 아래처럼 바뀜
#version 330 core
struct Material
{
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
struct Light
{
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
uniform vec3 viewPos;
uniform Material mat;
uniform Light light;
void main()
{
// ambient
vec3 ambient = mat.ambient * light.ambient;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * mat.diffuse * light.diffuse;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), mat.shininess);
vec3 specular = mat.specular * spec * light.specular;
vec3 result = (ambient + diffuse + specular);
FragColor = vec4(result, 1.0);
}
보면 light 구조체를 만들어서 사용하고 있다는걸 알 수 있음
그리고 main.cpp도 아래처럼 바뀜
렌더링로직 밖
//....
//material 설정
normalCubeShader.use();
normalCubeShader.setVec3("mat.ambient", glm::vec3(0.329412f, 0.223529f, 0.027451f));
normalCubeShader.setVec3("mat.diffuse", glm::vec3(0.780392f, 0.568627f, 0.113725f));
normalCubeShader.setVec3("mat.specular", glm::vec3(0.992157f, 0.941176f, 0.807843f));
normalCubeShader.setFloat("mat.shininess", 27.8974f);
//light 설정
normalCubeShader.setVec3("light.ambient", glm::vec3(0.8f));
normalCubeShader.setVec3("light.diffuse", glm::vec3(0.5f, 0.5f, 0.5f));
normalCubeShader.setVec3("light.specular", glm::vec3(1.0f, 1.0f, 1.0f));
//...
while (!glfwWindowShouldClose(window))
{
//...
//light position수정
normalCubeShader.setVec3("light.position", lightPos);
normalCubeShader.setVec3("viewPos", camera.Position);
}

좀 비슷하네잉~