Circular cursor + dragging
[opengl.git] / material.cpp
1 #include "material.hpp"
2 #include "image.hpp"
3 #include <assimp/pbrmaterial.h>
4
5 Material::Material(const aiMaterial &ai, const aiScene &scene, GLuint progId): progId(progId) {
6         aiString name;
7         ai.Get(AI_MATKEY_NAME, name);   
8
9         aiString path;
10         ai.GetTexture(aiTextureType_DIFFUSE, 1, &path);
11         if (path.length != 0)
12                 albedo = new Texture(path, scene);
13         path = "";
14
15         ai.GetTexture(aiTextureType_NORMALS, 0, &path);
16         if (path.length != 0)
17                 normal = new Texture(path, scene);
18         path = "";
19
20         ai.GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &path);
21         if (path.length != 0)
22                 metallicRoughness = new Texture(path, scene);
23         path = "";
24         
25         ai.GetTexture(aiTextureType_LIGHTMAP, 0, &path);
26         if (path.length != 0)
27                 ambientOcclusion = new Texture(path, scene);
28 }
29
30 Material::Texture::Texture(const aiString fileName, const aiScene &scene) {
31         glGenTextures(1, &texId);
32         glBindTexture(GL_TEXTURE_2D, texId);
33         
34         std::string path;
35         if (fileName.data[0] == '*') {
36                 // embedded
37                 int embIdx = atoi(&fileName.data[1]);
38                 aiTexture *texture = scene.mTextures[embIdx];
39                 if (texture->mHeight == 0) {
40                         Image img((unsigned char*)texture->pcData, texture->mWidth, texture->achFormatHint);
41                         glTexImage2D(GL_TEXTURE_2D, 0, img.internalFormat(), img.width(), img.height(), 0, img.format(), img.type(), img.data());
42                 } else {
43                         fprintf(stderr, "TODO: handle uncompressed embedded textures");
44                         abort();
45                 }
46         } else {
47                 // not embedded
48                 Image img("models/" + std::string(fileName.C_Str()));
49                 glTexImage2D(GL_TEXTURE_2D, 0, img.internalFormat(), img.width(), img.height(), 0, img.format(), img.type(), img.data());
50         }
51
52         // magnifying - no bigger mipmap available, so use linear filtering
53         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
54         // minifying - use a linear blend of two mipmaps
55         // which are themselves filtered linearly
56         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
57
58         float aniso = 0;
59         glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso);
60         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso); 
61     
62     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
63     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
64     
65         glGenerateMipmap(GL_TEXTURE_2D);
66 }
67
68 void Material::bind() const {
69         if (albedo != nullptr) {
70                 glUniform1i(glGetUniformLocation(progId, "mat.albedoMap"), 0);
71                 glActiveTexture(GL_TEXTURE0);
72                 glBindTexture(GL_TEXTURE_2D, albedo->texId);
73                 glUniform1i(glGetUniformLocation(progId, "mat.hasAlbedo"), 1);
74         } else {
75                 glUniform1i(glGetUniformLocation(progId, "mat.hasAlbedo"), 0);
76         }
77
78         if (normal != nullptr) {
79                 glUniform1i(glGetUniformLocation(progId, "mat.normalMap"), 1);
80                 glActiveTexture(GL_TEXTURE1);
81                 glBindTexture(GL_TEXTURE_2D, normal->texId);
82                 glUniform1i(glGetUniformLocation(progId, "mat.hasNormal"), 1);
83         } else {
84                 glUniform1i(glGetUniformLocation(progId, "mat.hasNormal"), 0);
85         }
86
87         if (metallicRoughness != nullptr) {
88                 glUniform1i(glGetUniformLocation(progId, "mat.metallicRoughnessMap"), 2);
89                 glActiveTexture(GL_TEXTURE2);
90                 glBindTexture(GL_TEXTURE_2D, metallicRoughness->texId);
91                 glUniform1i(glGetUniformLocation(progId, "mat.hasMetallicRoughness"), 1);
92         } else {
93                 glUniform1i(glGetUniformLocation(progId, "mat.hasMetallicRoughness"), 0);
94         }
95
96         if (ambientOcclusion != nullptr) {
97                 glUniform1i(glGetUniformLocation(progId, "mat.aoMap"), 3);
98                 glActiveTexture(GL_TEXTURE3);
99                 glBindTexture(GL_TEXTURE_2D, ambientOcclusion->texId);
100                 glUniform1i(glGetUniformLocation(progId, "mat.hasAo"), 1);
101         } else {
102                 glUniform1i(glGetUniformLocation(progId, "mat.hasAo"), 0);
103         }
104 }