I have an obj file with the the following mtl, see below. I am using mesh.cpp and model.cpp based on Assimp and from learnopengl. The relevant parts of the code are below. I think that everything works except Fragment Shader.
newmtl k909090
Ns 163
Tr 1
Ni 0.001
illum 2
Ka 0.20 0.20 0.20
Kd .566 .566 .566
Ks 0.25 0.25 0.25
newmtl kff0d0d
Ns 163
Tr 1
Ni 0.001
illum 2
Ka 0.20 0.20 0.20
Kd 1 .055 .055
Ks 0.25 0.25 0.25
newmtl kffffff
Ns 163
Tr 1
Ni 0.001
illum 2
Ka 0.20 0.20 0.20
Kd 1 1 1
Ks 0.25 0.25 0.25
In the relevant code parts I described :
struct Material {
float shininess;
float opacity;
float density;
float illum;
glm::vec3 ambient;
glm::vec3 diffuse;
glm::vec3 specular;
};
// render the mesh
void Draw(Shader &shader)
{
shader.setFloat("material.shininess", material.shininess);
shader.setFloat("material.opacity", material.opacity);
shader.setFloat("material.density", material.shininess);
shader.setFloat("material.illum", material.opacity);
shader.setVec3("material.ambient", material.ambient);
shader.setVec3("material.diffuse", material.diffuse);
shader.setVec3("material.specular", material.specular);
// draw mesh
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(indices.size()), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
The model class:
Material loadMaterial(aiMaterial *mat)
{
Material material{};
aiColor3D color(0.f, 0.f, 0.f);
float shininess;
float opacity;
float density;
float illum;
glm::vec3 ambient;
glm::vec3 diffuse;
glm::vec3 specular;
mat->Get(AI_MATKEY_SHININESS, shininess);
material.shininess = shininess;
mat->Get(AI_MATKEY_OPACITY, opacity);
material.opacity = opacity;
mat->Get(AI_MATKEY_COLOR_TRANSPARENT, density);
material.density = density;
mat->Get(AI_MATKEY_SHADING_MODEL, illum);
material.illum = illum;
mat->Get(AI_MATKEY_COLOR_AMBIENT, color);
material.ambient = glm::vec3(color.r, color.g, color.b);
mat->Get(AI_MATKEY_COLOR_DIFFUSE, color);
material.diffuse = glm::vec3(color.r, color.g, color.b);
mat->Get(AI_MATKEY_COLOR_SPECULAR, color);
material.specular = glm::vec3(color.r, color.g, color.b);
return material;
}
Mesh processMesh(aiMesh *mesh, const aiScene *scene)
{
// data to fill
vector<Vertex> vertices;
vector<unsigned int> indices;
Material matProps;
// walk through each of the mesh's vertices
for(unsigned int i = 0; i < mesh->mNumVertices; i )
{
Vertex vertex;
glm::vec3 vector; // we declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to glm's vec3 class so we transfer the data to this placeholder glm::vec3 first.
// positions
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
// normals
if (mesh->HasNormals())
{
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
}
vertices.push_back(vertex);
}
// now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
for(unsigned int i = 0; i < mesh->mNumFaces; i )
{
aiFace face = mesh->mFaces[i];
for(unsigned int j = 0; j < face.mNumIndices; j )
indices.push_back(face.mIndices[j]);
}
// process materials
aiMaterial *mat = scene->mMaterials[mesh->mMaterialIndex];
matProps = loadMaterial(mat);
return {vertices, indices, matProps};
}
And now I am struggling with fragment shader that gives me various errors and cannot compile. Question: what would be the right setup for fragment shader?
#version 330 core
out vec4 FragColor;
struct Material {
float shininess;
float opacity;
float density;
float illum;
vec3 ambient;
vec3 diffuse;
vec3 specular;
}
struct Light {
//vec3 position;
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
in vec3 FragPos;
in vec3 Normal;
uniform vec3 viewPos;
uniform Material material;
void main()
{
// ambient
vec3 ambient = light.ambient;
// diffuse
vec3 norm = normalize(Normal);
// vec3 lightDir = normalize(light.position - FragPos);
vec3 lightDir = normalize(-light.direction);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec;
vec3 result = ambient diffuse specular;
FragColor = vec4(result, 1.0);
}
CodePudding user response:
The most important part that is missing in your light model implementation is the consideration of material colors. Ka
, Kd
and Ks
specify the ambient color, diffuse color and specular color of the material.
Tr
specifies the alpha value and transparency of the material. You only can use it together with Blending. Ni
is the refraction of the material, which can be used e.g. with environment maps. illum
specifies the lighting model and is only useful if you have implemented different lighting models. In your case, you can just ignore it. There are many resources about that all over the web (e.g. Wikipedia - Wavefront).
With your actual render implementation you can use the properties Ka
(ambient
), Kd
(diffuse
), Ks
(specular
) and Ns
(shininess
). e.g:
void main()
{
// ambient
vec3 ambient = light.ambient * material.ambient;
// diffuse
vec3 norm = normalize(Normal);
// vec3 lightDir = normalize(light.position - FragPos);
vec3 lightDir = normalize(-light.direction);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * material.diffuse;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * material.specular;
vec3 result = ambient diffuse specular;
FragColor = vec4(result, 1.0);
}