GLM や GLSL の正方行列はデフォルトコンストラクタで単位行列に初期化されない

試した環境

  • glm 0.9.9.7
  • glsl 4.3

本題

glm::mat4 などのGLMの正方行列はデフォルトコンストラクタで単位行列に初期化されません。 単位行列にしたい場合は、glm::mat4(1.f) と引数付きのコンストラクタを呼び出す必要があります。
以下は試したコードです。

template<glm::length_t C, glm::length_t R, typename T>
std::ostream& operator << (std::ostream& out, const glm::mat<C, R, T>& mtx) {
    out << "[";
    for (int i = 0; i < mtx.length(); ++i) {
        out << "[";
        for (int j = 0; j < mtx[i].length(); ++j) {
            out << mtx[i][j] << "  ";
        }
        if (i != mtx.length() - 1) { out << "],\n"; }
        else { out << "]"; }
    }
    out << "]\n";
    return out;
}

int main(int argc, char* argv[]) {
    glm::mat4 m1;
    std::cout << "glm::mat4 default constructor\n";
    std::cout << m1 <<;
    glm::mat4 m2 = glm::mat4(1.f);
    std::cout << "glm::mat4 constructor glm::mat4(1.f)\n";
    std::cout << m2;
}

結果は以下の通りです。 デフォルトコンストラクタの結果は実行の度に変わると思います。

glm::mat4 default constructor
[[0  0  -2.66069e+19  4.59163e-41  ],
[0  0  0  0  ],
[0  0  0  0  ],
[-1.01008e-34  4.59037e-41  -2.66679e+19  4.59163e-41  ]]

glm::mat4 constructor glm::mat4(1.f)
[[1  0  0  0  ],
[0  1  0  0  ],
[0  0  1  0  ],
[0  0  0  1  ]]

この挙動は GLSL も同様です。 おそらくGLM は GLSL と同じ挙動になるように作られているので、そこも合わせているのでしょう。
以下は試したコードの一部です。 シェーダのソースと compute() 関数以外は前回の記事に載せていますので、そちらを参照ください。

const char* compute_shader_source = R"(
#version 430

layout(std430, binding = 3) buffer layout_dst
{
    mat4 dst[];
};

layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;

void main() {
    mat4 m1;
    dst[0] = m1;
    mat4 m2 = mat4(1.0);
    dst[1] = m2;
}
)";

void compute() {
    GLuint shader_program = createComputeShaderProgram(compute_shader_source);

    // create buffer
    GLuint uniform_element_size = glGetUniformLocation(shader_program, "element_size");
    GLuint ssbo;
    glGenBuffers(1, &ssbo);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
    glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(glm::mat4) * 2, nullptr, GL_DYNAMIC_COPY);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

    glUseProgram(shader_program);

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo);

    glDispatchCompute(1, 1, 1);

    glUseProgram(0);

    glm::mat4 data[2];
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
    glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(glm::mat4) * 2, &data[0][0][0]);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);

    std::cout << "glsl mat4 default constructor\n";
    std::cout << data[0] << std::endl;
    std::cout << "glsl mat4 constructor mat4(1.0)\n";
    std::cout << data[1] << std::endl;

    glDeleteBuffers(1, &ssbo);

    deleteComputeShaderProgram(shader_program);
}

結果は以下の通りです。

glsl mat4 default constructor
[[0.767708  0.483333  1  1  ],
[0.767708  0.483333  1  1  ],
[0.767708  0.483333  1  1  ],
[0.767708  0.483333  1  1  ]]

glsl mat4 constructor mat4(1.0)
[[1  0  0  0  ],
[0  1  0  0  ],
[0  0  1  0  ],
[0  0  0  1  ]]

参考

Data Type (GLSL) - OpenGL Wiki