質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

[opengl ]3D描画で行列計算をシェーダーを使って描画ができない原因が知りたい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 793
退会済みユーザー

退会済みユーザー

提示コードの頂点シェーダーコードなのですが参考サイトを参考にモデル行列計算やすべての行列計算をシェーダーで行いたいのですが画面に正方形の四角い線が描画されません。これはなぜなのでしょうか?そもそもシェーダーでは出来ないのでしょうか?行列をかける順番や処理の内容を参考サイトを参考によく考えましたがどうしても原因がわかりません。

参考サイト

#include "DrawTest.hpp"

#include <iostream>
#include "Shader.hpp"

#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
//コンストラクタ
DrawTest::DrawTest()
{
    shader = std::make_shared<Shader>("Basic_2D.vert", "Basic_2D.frag");    //シェーダー

    //頂点配列
    struct Vertex
    {
        GLfloat position[2];
    };

    //頂点情報
    Vertex rectangleVertex[4] =
    {
        //頂点、頂点色
        {-0.5f,-0.5f},
        {0.5f,-0.5f},
        {0.5f,0.5f},
        {-0.5f,0.5f}
    };

    //vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    //vbo
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);



    //頂点    
    GLint attrib = shader->getAttribLocation("vertexPosition");
    glEnableVertexAttribArray(attrib);
    glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(Vertex), rectangleVertex, GL_STATIC_DRAW);
    glVertexAttribPointer(attrib, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
    shader->setBindAttribVertex("vertexPosition");


    //モデル行列
    translate = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, -5.0f));    //平行移動
    rotate = glm::rotate(0.0f, glm::vec3(0.0f, 0.0f, 0.0f));                //回転
    scale = glm::scale(glm::mat4(), glm::vec3(1.0f, 1.0f, 1.0f));            //拡大縮小

    //ビュー
    glm::vec3 pos = glm::vec3(0, 0, 50);
    glm::vec3 center = glm::vec3(0, 0, -1);
    glm::vec3 up = glm::vec3(0,1,0);

    view = glm::lookAt(pos,center,up);    

    //透視射形
    projection = glm::perspective(glm::radians(90.0f),4.0f / 3.0f ,0.1f,100.0f);






}

//更新
void DrawTest::Update()
{





}

//描画
void DrawTest::Draw()
{
    shader->setEnable();


    shader->setUniform4f("uFragment", glm::vec4(0.0, 0.0, 1.0, 1.0));
    shader->setUniformMatrix4fv("uTranslate", translate);
    shader->setUniformMatrix4fv("uRotate", rotate);
    shader->setUniformMatrix4fv("uScale", scale);

    shader->setUniformMatrix4fv("uProjection", projection);
    shader->setUniformMatrix4fv("uView", view);






    glDrawArrays(GL_LINE_LOOP, 0, 4);

    shader->setDisable();
}

//デストラクタ
DrawTest::~DrawTest()
{
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);    
}
#ifndef ___DRAWTEST_HPP
#define ___DRAWTEST_HPP


#include <iostream>
#include <glew/include/GL/glew.h>

#include <glm/gtx/matrix_transform_2d.hpp>
#include <glm/glm.hpp>


class Shader;
class DrawTest
{
public:
    DrawTest();        //コンストラクタ
    ~DrawTest();    //デストラクタ

    void Update();    //更新
    void Draw();    //描画

private:

    std::shared_ptr<Shader> shader;    //シェーダークラス


    GLuint vao;    //VertexArrayObject
    GLuint vbo;    //VertexBufferObject


    glm::mat4 scale;        //拡大縮小
    glm::mat4 rotate;        //回転
    glm::mat4 translate;    //平行移動



    glm::mat4 view;            //ビュー
    glm::mat4 projection;    //射形


};

#endif
#extension GL_ARB_explicit_attrib_location: enable 

//頂点情報
layout(location = 0) in vec2 vertexPosition;    //頂点座標
//layout(location = 1) in vec4 vertexColor;        //頂点カラー

//フラグメントに転送
layout(location = 2) out vec4 vFragment;    //頂点カラー



uniform mat4 uScale;        //スケール
uniform mat4 uRotate;        //回転
uniform mat4 uTranslate;    //平行移動

uniform mat4 uProjection;    //透視行列
uniform mat4 uView;            //ビュー行列




uniform vec4 uFragment;    //色








void main()
{
    vec4 vertex = vec4(vertexPosition,-20.0,1.0);        //頂点座標
    mat4 model = uTranslate * uRotate * uScale;        //モデル行列



    gl_Position =  (uProjection * uView * model) * vertex;
    //gl_Position =  vec4(position,0.0,1.0);    //座標




    vFragment = uFragment;                //カラー
}
#extension GL_ARB_explicit_attrib_location: enable 


layout(location = 2) in vec4 vfragment;    


//出力
out vec4 fragment;

void main()
{

    fragment = vfragment;
    //fragment = vec4(0.0,0.0,1.0,1.0);

}
#include "Shader.hpp"

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

#include <glm/gtc/type_ptr.hpp>

//コンストラクタ
Shader::Shader(const char* vert, const char* frag)
{
    program = loadProgram(vert,frag);
    if (program == 0)
    {
        std::cerr << "シェーダープログラム作成エラー"<<std::endl;
        exit(1);
    }




    //std::cout<< program << std::endl;

}

//シェーダーをロード
GLuint Shader::loadProgram(const char* vert, const char* frag)
{
    std::vector<GLchar> vsrc;
    const bool vstat = ReadShaderSource(vert, vsrc);

    std::vector<GLchar> fsrc;
    const bool fstat = ReadShaderSource(frag, fsrc);


    if (vstat && fstat)
    {
        return CreateProgram(vsrc.data(), fsrc.data());
    }
    else {
        return 0;
    }
}



//シェーダーファイルを読み込む
bool Shader::ReadShaderSource(const char* name, std::vector<GLchar>& buffer)
{
    if (name == NULL)
    {
        return false;
    }


    std::ifstream file(name, std::ios::binary);
    if (file.fail())
    {
        std::cerr << "ソースファイルが読み込めません: " << name << std::endl;
        file.close();
        return false;
    }

    file.seekg(0L, std::ios::end);
    GLsizei length = static_cast<GLsizei>(file.tellg());
    buffer.resize(length + 1);

    file.seekg(0L, std::ios::beg);
    file.read(buffer.data(), length);
    buffer[length] = '\0';

    if (file.fail())
    {
        std::cerr << "ソースファイルを読み込めません: " << name << std::endl;
        file.close();

        return false;
    }

    file.close();
    return true;
}


//シェーダーエラーログを取得
GLboolean Shader::CompileInfoLog(GLuint shader,const char* str)
{
    GLint status;

    //コンパイル結果
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE)
    {
        std::cerr <<"Compile Error: " << str << std::endl;
    }

    //エラーログの長さを得る
    GLsizei bufSize;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &bufSize);

    if (bufSize > 1)
    {
        std::vector<GLchar> infoLog(bufSize);
        GLsizei length;
        glGetShaderInfoLog(shader, bufSize, &length, &infoLog[0]);

        std::cerr<< &infoLog[0] << std::endl;
    }



    return (GLboolean)status;
}




//プログラムオブジェクト作成
GLuint Shader::CreateProgram(const char* vsrc, const char* fsrc)
{
    const GLuint program = glCreateProgram();    //シェーダープログラムを作成

    //std::cout << program << std::endl;

    if (vsrc != NULL)
    {
        const GLuint vobj = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vobj, 1, &vsrc, NULL);
        glCompileShader(vobj);

        CompileInfoLog(vobj, vsrc);

        glAttachShader(program, vobj);
        glDeleteShader(vobj);

    }
    else {
        std::cout << "頂点シェーダー読み込み失敗" << std::endl;
    }

    if (fsrc != NULL)
    {
        const GLuint fobj = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fobj, 1, &fsrc, NULL);
        glCompileShader(fobj);

        CompileInfoLog(fobj, fsrc);

        glAttachShader(program, fobj);
        glDeleteShader(fobj);
    }
    else {
        std::cout << "フラグメントシェーダー読み込み失敗" << std::endl;

    }

    glLinkProgram(program);

    ProgramInfoLog(program);


    return program;
}

//プログラムのエラーを表示
GLboolean Shader::ProgramInfoLog(GLuint program)
{
    GLsizei bufSize;
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufSize);

    if (bufSize > 1) 
    {
        std::vector<GLchar> infoLog(bufSize);

        GLsizei length;
        glGetProgramInfoLog(program, bufSize, &length, &infoLog[0]);
        std::cerr<<"Program Info Log: "<< infoLog.data() <<std::endl;

        return false;
    }
    else
    {
        return true;
    }
}




//locationを取得
GLint Shader::getAttribLocation(const char* str)
{
    return glGetAttribLocation(program,str);
}



//頂点シェーダーに属性変数を関連ずける
void Shader::setBindAttribVertex(const char* str)
{
    GLint n = glGetAttribLocation(program, str);

    //エラー処理
    if (n == -1)
    {
        std::cerr <<"setBindAttribVertex(): "<< n << std::endl;
    }
    else 
    {
        glBindAttribLocation(program, n, str);
    }
}


//フラグメントシェーダーに属性変数を関連ずける
void Shader::setBindAttribFragment(const char* str)
{
    GLint n = glGetAttribLocation(program, str);

    //エラー処理
    if (n == -1)
    {
        std::cerr << "setBindAttribFragment(): " << n << std::endl;
    }
    else 
    {
        glBindFragDataLocation(program, n, str);
    }
}

//有効にする
void Shader::setEnable()
{
    glUseProgram(program);

}

//無効にする
void Shader::setDisable()
{
    glUseProgram(0);

}


// ######################################################### Uniform 設定

//vec1
void Shader::setUniform1f(const char* name, const float vec)
{
    const GLuint object = glGetUniformLocation(program, name);
    glUniform1f(object,vec);
}

//vec2
void Shader::setUniform2f(const char* name, const glm::vec2 vec)
{
    const GLuint object = glGetUniformLocation(program, name);
    glUniform2f(object,vec.x,vec.y);
}

//vec3
void Shader::setUniform3f(const char* name, const glm::vec3 vec)
{
    const GLuint object = glGetUniformLocation(program, name);
    glUniform3f(object,vec.x, vec.y,vec.z);
}

//vec4
void Shader::setUniform4f(const char* name, const glm::vec4 vec)
{    
    const GLuint object = glGetUniformLocation(program,name);
    glUniform4f(object, vec.x, vec.y, vec.z, vec.w);    
}


//行列2
void Shader::setUniformMatrix2fv(const char* name, const glm::mat2 m)
{
    const GLuint object = glGetUniformLocation(program, name);
    glUniformMatrix2fv(object,1,false,glm::value_ptr(m));
}

//行列3
void Shader::setUniformMatrix3fv(const char* name, const glm::mat3 m)
{
    const GLuint object = glGetUniformLocation(program, name);
    glUniformMatrix3fv(object, 1, false, glm::value_ptr(m));
}

//行列4
void Shader::setUniformMatrix4fv(const char* name, const glm::mat4 m)
{
    const GLuint object = glGetUniformLocation(program, name);
    glUniformMatrix4fv(object, 1, false, glm::value_ptr(m));

}

//デストラクタ
Shader::~Shader()
{

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2021/04/26 15:30

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

  • fluid_love

    2021/04/26 15:40

    「Shader.hpp」のコードを見せていただくことは可能でしょうか?

    1回ビルドしてみたいです

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2021/04/26 15:44

    提示しましたがヘッダーファイルは文字数の関係で載せられませんでした。

    キャンセル

回答 2

checkベストアンサー

+1

私もOpenGLを今日初めて触ったので,詳しいことはよくわかりませんが,行列の計算が怪しいようです.

元のコードの平行移動回転拡大縮小行列を全て単位行列にして,カメラの位置を常識的な値にして,shader(vert)のz座標を-20.0から0にすると添付画像の結果になりました.

なので,行列の計算に問題があると思います.

*色は白に変えてます.

    translate = glm::mat4(1);//glm::translate(glm::mat4(1), glm::vec3(0.0f, 0.0f, 0.1f));    //平行移動
    rotate = glm::mat4(1);// glm::rotate(0.0f, glm::vec3(0.0f, 0.0f, 0.0f));                //回転
    scale = glm::mat4(1);// glm::scale(glm::mat4(1), glm::vec3(1.0f, 1.0f, 1.0f));            //拡大縮小

    //ビュー
    glm::vec3 pos = glm::vec3(0, 0, 1);
    glm::vec3 center = glm::vec3(0, 0, -1);
    glm::vec3 up = glm::vec3(0, 1, 0);

    view = glm::lookAt(pos, center, up);
 vec4 vertex = vec4(vertexPosition,-20.0,1.0); //-20.0を0.0にvec4 vertex = vec4(vertexPosition,0.0,1.0);   

イメージ説明


あとはお好みで,translateとかrotateとかを使ってください.

    translate = glm::translate(glm::mat4(1), glm::vec3(1.0f, 0.0f, 0.0f));    //平行移動


x軸方向にずらすと↓になりました.
期待通りの動きだと思います.

イメージ説明

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/04/26 18:44

    glm::translate(glm::mat4(1), glm::vec3(1.0f, 0.0f, 0.0f));
    ですが第一引数は何をしているかわかりますでしょか?調べましたがリファレンスに詳しい説明がなく困っています?

    キャンセル

  • 2021/04/26 18:53

    普通にドキュメントに引数の意味が書いてあるが?

    > Input matrix multiplied by this translation matrix.

    って.

    キャンセル

  • 2021/04/26 18:56

    失礼しました。自分のミスです。

    キャンセル

+1

お使いのglmのバージョン等(?)によって異なってくるのかもしれませんので,確かなことは言えませんが…
各マトリクスの内容が妥当でないならば,当然ながら,それを乗じた結果も妥当ではないでしょう.

私の手元の環境では以下のようなことになるように見えるので,このあたりを確認されてみてはいかがでしょうか.
(私が使っているglmは,ver 0.9.9.7 である模様)

//モデル行列
translate = glm::translate(glm::mat4(), glm::vec3(0.0f, 0.0f, -5.0f));    //平行移動
rotate = glm::rotate(0.0f, glm::vec3(0.0f, 0.0f, 0.0f));                //回転
scale = glm::scale(glm::mat4(), glm::vec3(1.0f, 1.0f, 1.0f));            //拡大縮小

(1) glm::mat4() がどのような内容になるのか?
私が持っているglmのヘッダを見ると,この記述は #if ディレクティブ次第で結果が異なるように見えます.
この記述で単位行列が得られるのであれば問題無いと思いますが,私の環境ではどうやら要素が全0になってしまうようです.
(これが全0になる場合,translateなどが全0になってしまいます.)

(2) glm::rotate(0.0f, glm::vec3(0.0f, 0.0f, 0.0f)); で大丈夫ですか?
この記述,この形のオーバーロードが見つからず,コンパイルが通せませんでした.

translateやrotateと同様に最初の引数にマトリクスを与える形のオーバーロードは存在しますので,第1引数としてglm::mat4(1.0)を追加してやればコンパイルが通せましたが,その結果のrotateの要素値はnanだらけになりました.
glm::vec3(0.0f, 0.0f, 0.0f) では,引数として不正だからではないか?と推測します.

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/04/26 19:06

    使ってる関数の第一引数の意味も把握しないままにBA選んでるけども,結局ご自身でマトリクスの内容確認したんですか?
    ・glm::mat4() で良いのかダメなのか
    ・glm::vec3(0.0f, 0.0f, 0.0f) は不正なんじゃないか?
    みたいな話にはまともな反応が欲しいのだが…

    キャンセル

  • 2021/04/26 19:11

    glm::vec3(0.0f, 0.0f, 0.0f) は関係ありませんでした。しかし拡大縮小はglm::vec3(1.0,1.0,1.0);という形にして等倍にする必要があります。glm::mat4();では全部が0の値なので掛け算で何をしても0なのでこれが原因でした。対処法はglm:mat4(1),glm::vec3(0.0,0.0,0.0);とすべきです。

    キャンセル

  • 2021/04/26 19:35

    > glm::mat4();では全部が0

    やっぱそちらでも glm::mat4() だと全0になっちゃってるのですね.
    「glm::mat4()」 って書いたら何になるの? ってのは字面から不明瞭だから,そこに疑問が湧くのが普通だと思うので,
    何はともあれ,そういうことを真っ先に確認すべきだと思いますぞ.
    うまく動くとか動かんとか言う前の段階として.


    > glm::vec3(0.0f, 0.0f, 0.0f) は関係ありませんでした。

    そもそもの引数の意味的に考えて glm::rotate() に (0,0,0) を渡すという行動があり得ないと思うけど…
    あえて怪しい値を与えるような冒険しなくてもいいんじゃないかなー.

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る