wooseokyourself / shmup

OpenGL based game
MIT License
0 stars 0 forks source link

Texture mapping through assimp #41

Open wooseokyourself opened 3 years ago

wooseokyourself commented 3 years ago
  1. aiMesh 는 다수의 aiVertex와 aiFace, 그리고 하나의 aiMaterial 을 가지고 있음.
  2. aiMaterial은 여러 texture type 을 가지고 있으며, 각각의 타입은 aiMaterial::GetTextureTypeCount(uint type) 을 통해 그 수를 알 수 있고, aiMaterial::GetTexture(uint type, uint index, string& outFilePath) 를 통해 index번 째 type 텍스쳐의 파일경로를 outFilePath에 저장할 수 있음. (assimp texture type enum)
  3. 어플리케이션은 텍스쳐맵을 나타내는 구조체를 가져야 함
    struct Texture {
    uint ID, 
    std::string type
    /*
    "diffuse"
    "specular"
    */
    };
  4. 위에 대응하여, 셰이더에 정의되어야 하는 텍스쳐 구조체는 다음과 같음.
    struct Material {
    sampler2D diffuse; // OpenGL에 바인드된 텍스쳐의 ID
    sampler2D specular; // OpenGL에 바인드된 텍스쳐의 ID
    float shininess;
    };
    uniform Material material;
  5. 어플리케이션의 Mesh 클래스가 std::vector textures 를 멤버변수로 가져야 함. 여기에 해당 Mesh 의 aiMaterial이 가지고 있는 모든 텍스쳐맵을 순차적으로 저장해야 함.
  6. 어플리케이션의 Mesh 클래스 내에 있는 모든 Texture는 glGenTextures, glBindTexture, glTexImage2D를 거쳐야 함.
  7. aiMesh 를 Mesh 클래스로 매핑할 때 대강 다음과 같은 시퀀스로 텍스쳐를 aiMesh로부터 가져옴

    // input: aiMaterial, vector<Texture> textures (<-- Mesh의 멤버변수)
    // output: save all textures in aiMaterial to textures
    for(all aiTextureType in aiMaterial: type) {
    string myTypeName = // aiTextureType 에 따라 내가 임의로 지정=> "diffuse" 혹은 "specular"
    for(i = 0 to i < aiMaterial->GetTextureCount(aiTextureType)) {
        string filePath;
        aiMaterial->getTexture(aiTextureType, i, &filePath);
        Texture t;
    
        /* Texture.ID processing */
        glGenTextures(1, &t.ID);
        glBindTexture(GL_TEXTURE_2D, ID);
        // stbi_load() 를 이용해서 @filePath 이미지파일의 format, w, h, pixelData 구하기
        glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, pixelData);
        // glGenerateMipmap, glTexParameter 진행
    
        /* Texture.type */
        texture.type = myTypeName;
    
        textures.push_back(t); // Mesh::textures 에 저장
    }
    }
wooseokyourself commented 3 years ago

Mesh::textures 에 저장된 텍스쳐들은 순차적으로 texture unit으로 사용됨. Mesh::draw() 에서 텍스쳐를 그릴 때 이 텍스쳐유닛을 셰이더의 sampler2D에 적절하게 할당해주어야 함.

textures = { "diffuse", "diffuse", "diffuse", "specular", "specular" } 이런 식으로 저장되어 있을 경우
textures[0] = GL_TEXTURE0
textures[1] = GL_TEXTURE1
textures[2] = GL_TEXTURE2
textures[3] = GL_TEXTURE3
textures[4] = GL_TEXTURE4
로 texture unit id 를 가지게 되며, 각 texture 들은 fragment shader로 다음과 같이 전달됨.
textures[0] --> uniform sampler2D diffuse0
textures[1] --> uniform sampler2D diffuse1
textures[2] --> uniform sampler2D diffuse2
textures[3] --> uniform sampler2D specular0 textures[4] --> uniform sampler2D specular1

또한 이런식으로 텍스쳐유닛이 적용되었을경우, fragment shader 의 Material 은 다음과 같이 변경되어야함?

struct Material {
    sampler2D diffuse0;
    sampler2D diffuse1;
    sampler2D diffuse2;
    sampler2D diffuse3;
    sampler2D specular0;
    sampler2D specular1;
    sampler2D specular2;
    sampler2D specular3;
    sampler2D ambient0;
    sampler2D ambient1;
    sampler2D ambient2;
    sampler2D ambient3;
    float shininess;
};