ぬの部屋(仮)
nu-no-he-ya
  •      12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
         12
    3456789
    10111213141516
    17181920212223
    2425262728  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
       1234
    567891011
    12131415161718
    19202122232425
    26272829   
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28      
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • GLSLを試す (5) 点の表示(gl_PointSize)

    順序が大幅にずれた感があるが点の表示について。

    • glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); を使う
    • 頂点シェーダgl_PointSize=30.0; と点のサイズを指定する
    • glDrawArrays(GL_POINTS, 0, 5); とGL_POINTSで描画

    バッファの準備

    データの定義

    typedef GLfloat point_t[3]; //モデルの座標用 x y z
    typedef GLfloat color_t[4];//テクスチャ座標用 r g b a
    
    /////////////////////////////////
    //バッファとデータ
    GLuint vertexbufferName;
    point_t vertex[5];
    GLuint colorbufferName;
    color_t color[5];
    

    データの準備

    //////////////////////////////////////////
    //////////////////////////////////////////
    
    vertex[0][0] = -0.7;
    vertex[0][1] =  0.7;
    vertex[0][2] = 0;
    
    vertex[1][0] = -0.7;
    vertex[1][1] = -0.7;
    vertex[1][2] = 0;
    
    vertex[2][0] =  0.7;
    vertex[2][1] = -0.7;
    vertex[2][2] = 0;
    
    vertex[3][0] = +0.7;
    vertex[3][1] = +0.7;
    vertex[3][2] = 0;
    
    vertex[4][0] = 0;
    vertex[4][1] = 0;
    vertex[4][2] = 0;
    
    
    //////////////////////////////////////////
    //////////////////////////////////////////
    color[0][0] = 1.0;
    color[0][1] = 0.0;
    color[0][2] = 0.0;
    color[0][3] = 1.0;//α
    
    color[1][0] = 0.0;
    color[1][1] = 1.0;
    color[1][2] = 0.0;
    color[1][3] = 1.0;//α
    
    color[2][0] = 0.0;
    color[2][1] = 0.0;
    color[2][2] = 1.0;
    color[2][3] = 1.0;//α
    
    color[3][0] = 1.0;
    color[3][1] = 0.0;
    color[3][2] = 1.0;
    color[3][3] = 1.0;//α
    
    color[4][0] = 1.0;
    color[4][1] = 1.0;
    color[4][2] = 1.0;
    color[4][3] = 1.0;//α
    
    //////////////////////////////////////////
    //////////////////////////////////////////
    
    glGenBuffers(1, &vertexbufferName);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbufferName);
    glBufferData(GL_ARRAY_BUFFER, 3 * 5 * sizeof(GLfloat), vertex, GL_STATIC_DRAW);
    
    glGenBuffers(1, &colorbufferName);
    glBindBuffer(GL_ARRAY_BUFFER, colorbufferName);
    glBufferData(GL_ARRAY_BUFFER, 4 * 5 * sizeof(GLfloat), color, GL_STATIC_DRAW);
    

    描画 (CPU側)

    glUseProgram(ProgramID);
    
    //gl_PointSizeを有効にする
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    
    // 頂点バッファ
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbufferName);
    glVertexAttribPointer(
      0,                  // 属性0
      3,                  // 1要素の要素数 x y z
      GL_FLOAT,           // タイプ
      GL_FALSE,           // 正規化しない(データが整数型の時)
      0,                  // ストライド
      (void*)0            // 配列バッファオフセット
    );
    
    // カラーバッファ
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, colorbufferName);
    glVertexAttribPointer(
      1,                  // 属性1
      4,                  // 1要素の要素数 r g b a
      GL_FLOAT,           // タイプ
      GL_FALSE,           // 正規化しない(データが整数型の時)
      0,                  // ストライド
      (void*)0            // 配列バッファオフセット
    );
    
    // 5頂点を描く
    glDrawArrays(GL_POINTS, 0, 5);
    
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    
    ////////////////////////////////////////
    ////////////////////////////////////////
    

    頂点シェーダ

    #version 460 core
    
    layout (location = 0) in vec3 vtx;
    layout (location = 1) in vec4 color;
    
    out vec4 vColor;
    
    uniform mat4 gl_ModelViewMatrix;
    uniform mat4 gl_ProjectionMatrix;
    
    void main()
    {
      gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(vtx, 1.0);
      vColor = color;
      gl_PointSize=30.0; // 頂点のサイズ(ピクセル)
    }
    

    フラグメントシェーダ

    #version 460 core
    
    out vec4 FragColor;
    
    in vec4 vColor;
    
    void main()
    {
      FragColor = vColor;
    
    }
    

    実行結果

    C++CLIでXDocumentでXML

    準備

    参照の追加

    System::XML::Linqをリンクする

    1. プロジェクトを右クリック
    2. 追加→参照
    3. アセンブリ→System.Xml.Linqをチェック
    4. OKボタン

    名前空間

    以下を先頭に追加

    using namespace System::Xml::Linq;

    使い方

    XML書き出し

    書き出しコード

    using namespace System::Xml::Linq;
    
    int main(array<System::String^>^ args)
    {
    
      // ② 追加する要素を作成
      XElement ^man1;
      {
        XElement^ ext;
    
        ext = gcnew XElement("その他");
        ext->Add(gcnew XElement("特技", L"昼寝"));
    
        man1 =
          gcnew XElement("個人データ",
            gcnew XElement("名前", "山田太郎"),
            gcnew XElement("年齢", 45),
            gcnew XElement("住所", "愛媛県松山市"),
            ext
          );
      }
    
      // ② 追加する要素を作成
      XElement^ man2;
      {
        XElement^ ext;
        ext = gcnew XElement("その他");
        ext->Add(gcnew XElement("特技", L"懸垂"));
    
        man2 =
          gcnew XElement("個人データ",
            gcnew XElement("名前", "西田花子"),
            gcnew XElement("年齢", 15),
            gcnew XElement("住所", "北海道札幌市"),
            ext
          );
      }
    
      // ② 追加する要素を作成
      XElement^ man3;
      {
        XElement^ ext;
        ext = gcnew XElement("その他");
        ext->Add(gcnew XElement("特技", L"読書"));
    
        man3 =
          gcnew XElement("個人データ",
            gcnew XElement("名前", "岡田広美"),
            gcnew XElement("年齢", 35),
            gcnew XElement("住所", "沖縄県中城村"),
            ext
          );
      }
    
      XElement^ root = gcnew XElement("root");
    
      // ① XDocumentオブジェクトを作成
      XDocument^ alldata = gcnew XDocument(
        gcnew XComment("利用者の全情報"),
        root
      );
    
      // ③ XDocumentにXElementを追加
      root->Add(man1);
      root->Add(man2);
      root->Add(man3);
    
      // ④ ファイル保存
      alldata->Save("C:\\mydata\\others\\個人データ1.xml");
    
    }
    

    書き出し結果

    <?xml version="1.0" encoding="utf-8"?>
    <!--利用者の全情報-->
    <root>
      <個人データ>
        <名前>山田太郎</名前>
        <年齢>45</年齢>
        <住所>愛媛県松山市</住所>
        <その他>
          <特技>昼寝</特技>
        </その他>
      </個人データ>
      <個人データ>
        <名前>西田花子</名前>
        <年齢>15</年齢>
        <住所>北海道札幌市</住所>
        <その他>
          <特技>懸垂</特技>
        </その他>
      </個人データ>
      <個人データ>
        <名前>岡田広美</名前>
        <年齢>35</年齢>
        <住所>沖縄県中城村</住所>
        <その他>
          <特技>読書</特技>
        </その他>
      </個人データ>
    </root>
    

    XML読み込み

    読み込みコード

    using namespace System::Xml::Linq;
    
    int main(array<System::String ^> ^args)
    {
    
      // XMLファイルを開く
      XDocument^ xml = XDocument::Load("C:\\mydata\\others\\個人データ1.xml");
    
      XElement^ root = xml->Element("root");
    
      //イテレータの取得
      System::Collections::Generic::IEnumerable<XElement^>^ 
        xelements = root->Elements();
    
      for each (XElement ^ k in xelements)
      {
        // k には<個人データ>の内容が入っている
        System::String^ name = k->Element("名前")->Value;
        int age = int::Parse(k->Element("年齢")->Value);
        System::String^ addr = k->Element("住所")->Value;
    
        System::String^ adv = k->Element("その他")->Element("特技")->Value;
    
        //読み取った内容表示
        System::Console::WriteLine(name);
        System::Console::WriteLine(age);
        System::Console::WriteLine(addr);
        System::Console::WriteLine(adv);
        System::Console::WriteLine("--------------");
    
      }
    
      return 0;
    }
    

    読み込みコード実行結果

    この記事を書いた理由

    CSharpの情報はたくさん出てくる。そしてそれを真似ればうまくいく。99.9%うまくいく。しかしC++CLIから使う場合CSharpのコードからは必要な情報が読み取りにくい。具体的には型情報と名前空間あたりがさっぱりわからない。そもそもC++CLIなんて積極的に使う言語じゃないから自分の中に技術が蓄積しない。加えて情報が少ない。公式にすらろくに無い。その上CSharpの情報で大抵事足りる。故に逆に一度詰まると基本的なことがわからなくて彷徨うことになる。というか、彷徨った。

    doxygenの@warningと@attentionには何を書くか

    @warningと@attentionの違いが今ひとつわからない。英語を母国語とするものにとっては明確に違うのかもしれない。意味が全然違うとか言われそうだ。しかし私にはわからないので調べてみる。

    PCLのソースコード内を検索検索

    ちょうど手元にあったPCLのソースコードでwarningとattentionを検索してみた。

    attention

    • @attention Holds a reference to the environment it was created from.
    • \attention A second version of this function template exists which explicitly
    • \attention It will be invoked from the new process.
    • \attention alnum is equivalent to /[[:alnum:]]/ in perl. ~alnum is equivalent
    • \attention keep(expr) is equivalent to the perl (?>…) extension.
    • \attention Skipping does not affect how nested regexes are handled because
    • \attention The default implementation doesn't do proper Unicode
    • \attention Not currently used
    • \attention Since 1.4.0, Eigen matrices are forced to Row Major to increase the efficiency of the algorithms in PCL
    • \attention The input normals given by setInputNormalsSmall and setInputNormalsLarge have
    • @attention untested code
    • \attention The focal length may change, depending whether the depth stream is registered/mapped to the RGB stream or not.
    • \attention its not the system time, thus can not be used directly to synchronize different sensors.
    • \attention The PCD data is \b always stored in ROW major format!
    • \attention This method does not do any bounds checking for the input index

    warning

    • \warning If the launching and the child process use the input, this leads to undefined behaviour.
    • \warning This feature requires boost/process/async.hpp to be included and a reference to boost::asio::io_service to be passed to the launching function.
    • \warning Invalid arguments cause undefined behaviour.
    • \warning Throwing an exception may cause data loss. This will also throw if a small vector resize throws, in which case there will be no data loss.
    • \warning This method will be removed in the future. Use setNegative() instead.
    • \warning The vertices must be valid and unique (each vertex may be contained only once). Not complying with this requirement results in undefined behavior!
    • \warning Please make sure to NOT add or remove elements from the cloud.
    • \warning Does NOT check if the stored mesh pointer is valid. You have to ensure this yourself when constructing the circulator.
    • \warning The vertices must be valid and unique (each vertex may be contained only once). Not complying with this requirement results in undefined behavior!
    • \warning PCLPointCloud2 inserted into the tree must have x,y,z fields, and must be of same type of any other points inserted in the tree
    • @warning Image type changes if a calibration pattern is discovered/lost;
    • @warning This functionality is not supported with the legacy OpenGL backend.

    所感

    @attention ... 使う上で考慮しておくべき項目など。たとえば、 @attention untested code などは使ってはいけないとも、使うと問題が起こるとも限らないが、考慮必須の項目である。

    @warning ... やってはいけない使い方・問題が起こる条件など。たとえば、
    \warning Invalid arguments cause undefined behaviour. は無効な引数に対して動作保証がないことを示している。

    Windowsにdoxygen+doxywizardをインストール

    最適な解

    Windowsにdoxygenをインストールします。結論を言うと、以下が自分の中で最適。

    1. 公式からインストーラをダウンロード
    2. ダウンロードしたインストーラをUniversal Extractor 2で展開
    3. 中のexeファイルを適切な場所にコピー

    ダウンロード

    http://www.doxygen.nl/download.html

    からダウンロードできるのだけれど、

    doxygen-1.8.15-setup.exe

    と、

    32-bit doxygen binary in a zip (18.2MB) or the 64-bit version

    があって、ここでは、doxygen-1.8.15-setup.exeをダウンロードします。

    なぜかというと、zip版にはdoxywizardが入っていないからです。

    展開

    普通にインストーラからインストールしてもいいのだけれど、勝手にPATH通されたりレジストリをいじられたりとかしたらたまったものではないのでインストーラを手動で展開して中身をほじくり出します。Universal Extractor 2を使います。

    UniExtract.exeを実行したら、 doxygen-1.8.15-setup.exe のパスと展開先を入力してOKします。

    展開された中にあるbinフォルダを適当な場所にコピーします

    doxywizardが起動できたら成功。


    Visual Studio 2019のタイトルバーを復活する

    Visual Studio2019をインストールしたはいいがタイトルバーがメニューバーと一体化してしまった。

    ウィンドウを移動するのにものすごく不便なので元に戻す。

    https://stackoverflow.com/questions/53636350/re-enable-title-bar-in-visual-studio-2019

    1. %LOCALAPPDATA%\Microsoft\VisualStudio\16.0_xxxxxxxx\Settings\CurrentSettings.vssettings
      を開く
    2. <PropertyValue name="IsMinimalVsEnabled">True</PropertyValue>
      という個所を見つける
    3. <PropertyValue name="IsMinimalVsEnabled">False</PropertyValue>
      に変更する

    GL_LUMINANCEの使い方復習

    巷の例がGL_RGBかGL_RGBAばかりなのでGL_LUMINACEを使った例を置いておく。

    データ準備

    typedef GLubyte gray_t;    //テクスチャ用
    typedef GLfloat points_t[3]; //モデルの座標用
    typedef GLfloat texcoord_t[2];//テクスチャ座標用
    
    const int P_COUNT = 4;
    
    //頂点データ
    GLuint vertexbuffer;
    points_t position[P_COUNT];
    
    //テクスチャ座標データ
    texcoord_t texcoord[P_COUNT];
    GLuint texcoordbuffer;
    
    //テクスチャデータ
    gray_t texdata[P_COUNT];
    GLuint textureID;
    
    //////////////////////////////////////////////////
    void prepare_buffers() {
    
      //テクスチャ(画像)作成
      // 2*2の画像
      texdata[0] = 255;
      texdata[1] = 128;
      texdata[2] = 50;
      texdata[3] = 0;
    
      //////////////////////////////////////////
      //////////////////////////////////////////
    
      //頂点座標の定義 (四角形)
      position[0][0] = -0.7;
      position[0][1] = 0.7;
      position[0][2] = 0;
    
      position[1][0] = -0.7;
      position[1][1] = -0.7;
      position[1][2] = 0;
    
      position[2][0] = 0.7;
      position[2][1] = -0.7;
      position[2][2] = 0;
    
      position[3][0] = +0.7;
      position[3][1] = +0.7;
      position[3][2] = 0;
    
      //////////////////////////////////////////
      //////////////////////////////////////////
    
      //テクスチャ座標の定義
      texcoord[0][0] = 0;
      texcoord[0][1] = 1;
    
      texcoord[1][0] = 0;
      texcoord[1][1] = 0;
    
      texcoord[2][0] = 1;
      texcoord[2][1] = 0;
    
      texcoord[3][0] = 1;
      texcoord[3][1] = 1;
    
      //////////////////////////////////////////
      //////////////////////////////////////////
    
      //テクスチャの作成
      // 普通のテクスチャ作成
      glGenTextures(1, &textureID);
      glBindTexture(GL_TEXTURE_2D, textureID);
    
      int TEXWIDTH = 2;  // 2*2の画素数
      int TEXHEIGHT = 2;
    
      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    
    
      // テクスチャの割り当て
      glTexImage2D(
    GL_TEXTURE_2D,
    0,
    GL_LUMINANCE,
    TEXWIDTH,
    TEXHEIGHT,
    0, GL_LUMINANCE,
    GL_UNSIGNED_BYTE,
    texdata
    );
    // テクスチャを拡大・縮小する方法の指定 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); }

    描画

    void display(void)
    {
      glClearColor(0, 0, 0, 1);
      glClear(GL_COLOR_BUFFER_BIT);
      glDisable(GL_CULL_FACE);//カリングを無効にする
    
    
      ///////////////////////////////////
      // 行列の設定
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(65, 1, 0.1, 10);
    
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslated(0.0, 0.0, -3);
    
    
      ///////////////////////////////////
      // 四角形の描画
    
      glEnable(GL_TEXTURE_2D);
      glBegin(GL_TRIANGLE_FAN);
    
      glTexCoord2fv(texcoord[0]);
      glVertex3fv(position[0]);
    
      glTexCoord2fv(texcoord[1]);
      glVertex3fv(position[1]);
    
      glTexCoord2fv(texcoord[2]);
      glVertex3fv(position[2]);
    
      glTexCoord2fv(texcoord[3]);
      glVertex3fv(position[3]);
    
      glEnd();
    
    
    
    
      glFlush();
    }
    

    描画結果


    GLSLを試す (4) グレイスケールテクスチャを着色する

    グレイスケールデータの定義

    グレイスケール(1画素が輝度値で表現されている)データをテクスチャとして使用することを考える。RGB(A)に変換しないでできれば何かと便利になる。

    グレイスケールデータの定義

    typedef GLshort gray_t;
    const int P_COUNT = 4;
    gray_t texdata[P_COUNT];
    
    //テクスチャ(画像)作成
    // 2*2のグレイスケール画像
    texdata[0] = 255;
    texdata[1] = 128;
    texdata[2] = 50;
    texdata[3] = 0;
    

    GL_R8UI等を使う

    GL_LUMINANCEなどを指定すればよいのだが、これは最近では非推奨らしい。

    代わりに、GL_R8I,GL_R8UI,GL_R16I,GL_R16UI,GL_R32I,GL_R32UI等を使えば、RGBではなくグレイスケールとしてテクスチャを転送できる。

    例1 テクスチャがunsigned charの場合

    glTexImage2D(
      GL_TEXTURE_2D,
      0,
      GL_R8UI,          //8bitのunsinged int
      TEXWIDTH,     //テクスチャ画素数
      TEXHEIGHT,    //テクスチャ画素数
      0,
      GL_RED_INTEGER,   //整数
      GL_UNSIGNED_BYTE, //unsigned の 1byte
    texdata
    );

    例2 テクスチャがsigned shortの場合

    glTexImage2D(
      GL_TEXTURE_2D,
      0,
      GL_R16I,           //16bitのsigned int
      TEXWIDTH,    //テクスチャ画素数
      TEXHEIGHT,   //テクスチャ画素数
      0,
      GL_RED_INTEGER,    //整数
      GL_SHORT,          //signed の 2byte
      texdata
    );
    

    フラグメントシェーダ

    sampler2Dを使うと、データ範囲が0.0~1.0の間で正規化されて取得できる。それでいい時も多いと思うのだが、グレースケールデータの値を正確に参照したい場合は不便というか、元の値を正確に得られる保証がない。そこでisampler2Dを使うと、テクスチャのデータをもとのままで参照できる。

    #version 460 core
    
    out vec4 FragColor; //色の出力はfloatでいい
    
    uniform isampler2D uTex; //データをint型で受け取る。符号なしintのときはusampler2D
      
    in vec2 vTexCoord; //テクスチャ座標
    
    void main()
    {
      int c = texture(uTex,vTexCoord).x;
    
      //分岐はどうのとか今はいい。本題ではない。
      if( c == 255)
          FragColor =vec4( 1.0,0,0,1);
      else if( c == 128)
          FragColor =vec4( 0.0,1.0,0,1);
      else if( c == 50)
          FragColor =vec4( 0.0,0.0,1.0,1);
      else
          FragColor =vec4( float(c)/255.0,float(c)/255.0,float(c)/255.0,1.0);
    }
    
    unsigned byteをそのまま輝度として表示
    (上記 例1)
    unsinged byteに着色して表示
    (上記 例1+上記フラグメントシェーダ)

    GLSLを試す (3) テクスチャ

    変数の定義

    typedef GLubyte rgb_t[3];    //テクスチャ用
    typedef GLfloat points_t[3]; //モデルの座標用
    typedef GLfloat texcoord_t[2];//テクスチャ座標用
    
    const int P_COUNT = 4;
    
    //頂点データ
    GLuint vertexbuffer;
    points_t position[P_COUNT];
    
    //テクスチャ座標データ
    texcoord_t texcoord[P_COUNT];
    GLuint texcoordbuffer;
    
    //テクスチャデータ
    rgb_t texdata[P_COUNT];
    GLuint textureID;
    

    データとバッファの準備

    void prepare_buffers() {
    
      //テクスチャ(画像)作成
      // 2*2の画像
      texdata[0][0] = 255;
      texdata[0][1] = 0;
      texdata[0][2] = 0;
    
      texdata[1][0] = 0;
      texdata[1][1] = 255;
      texdata[1][2] = 0;
    
      texdata[2][0] = 0;
      texdata[2][1] = 0;
      texdata[2][2] = 255;
    
      texdata[3][0] = 255;
      texdata[3][1] = 255;
      texdata[3][2] = 255;
    
      //////////////////////////////////////////
      //////////////////////////////////////////
    
      //頂点座標の定義 (四角形)
      // いつもなら glVertex3fv等て指定するもの
      position[0][0] = -0.7;
      position[0][1] = 0.7;
      position[0][2] = 0;
    
      position[1][0] = -0.7;
      position[1][1] = -0.7;
      position[1][2] = 0;
    
      position[2][0] = 0.7;
      position[2][1] = -0.7;
      position[2][2] = 0;
    
      position[3][0] = +0.7;
      position[3][1] = +0.7;
      position[3][2] = 0;
    
      //////////////////////////////////////////
      //////////////////////////////////////////
    
      //テクスチャ座標の定義
      //いつもならglTexCoord2f等で指定するもの
      texcoord[0][0] = 0;
      texcoord[0][1] = 1;
    
      texcoord[1][0] = 0;
      texcoord[1][1] = 0;
    
      texcoord[2][0] = 1;
      texcoord[2][1] = 0;
    
      texcoord[3][0] = 1;
      texcoord[3][1] = 1;
    
      //////////////////////////////////////////
      //////////////////////////////////////////
    
      //テクスチャの作成
      // 普通のテクスチャ作成
      glGenTextures(1, &textureID);
      glBindTexture(GL_TEXTURE_2D, textureID);
    
      int TEXWIDTH = 2;  // 2*2の画素数
      int TEXHEIGHT = 2;
    
      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    
      // テクスチャの割り当て
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXWIDTH, TEXHEIGHT, 0,
        GL_RGB, GL_UNSIGNED_BYTE, texdata);
    
      // テクスチャを拡大・縮小する方法の指定
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    
      //////////////////////////////////////////
      //////////////////////////////////////////
    
      //頂点バッファの作成
      glGenBuffers(1, &vertexbuffer);
      glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
      glBufferData(GL_ARRAY_BUFFER, 3 * P_COUNT * sizeof(GLfloat), position, GL_STATIC_DRAW);
    
      //テクスチャ座標バッファの作成
      glGenBuffers(1, &texcoordbuffer);
      glBindBuffer(GL_ARRAY_BUFFER, texcoordbuffer);
      glBufferData(GL_ARRAY_BUFFER, 2 * P_COUNT * sizeof(GLfloat), texcoord, GL_STATIC_DRAW);
    
    }
    

    描画関数

    void display(void)
    {
      glClearColor(0, 0, 0, 1);
      glClear(GL_COLOR_BUFFER_BIT);
      glDisable(GL_CULL_FACE);//カリングを無効にする
    
    
      ///////////////////////////////////
      // 行列の設定
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(65, 1, 0.1, 10);
    
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslated(0.0, 0.0, -3);
    
      ///////////////////////////////////
      // シェーダを使う
      glUseProgram(ProgramID);
    
      ///////////////////////////////////
      // 頂点バッファを有効化
      glEnableVertexAttribArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
      glVertexAttribPointer(
        0,                  // 属性0
        3,                  // 1要素の個数。GLfloatのx,y,zなので3
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
      ///////////////////////////////////
      //テクスチャ座標バッファの有効化
      glEnableVertexAttribArray(1);
      glBindBuffer(GL_ARRAY_BUFFER, texcoordbuffer);
      glVertexAttribPointer(
        1,                  // 属性1
        2,                  // 1要素の個数。GLfloatのu,vなので2
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
    
      ///////////////////////////////////
      // 四角形の描画
      glDrawArrays(GL_TRIANGLE_FAN, 0, P_COUNT);
    
      glDisableVertexAttribArray(0);
      glDisableVertexAttribArray(1);
    
      glFlush();
    }
    

    頂点シェーダ

    #version 460 core
    
    layout (location = 0) in vec3 aPos;//ポリゴンの頂点座標
    layout (location = 1) in vec2 texcd;//座標に対応するテクスチャ座標
    
    out vec2 vTexCoord;//テクスチャ座標の出力先
    
    uniform mat4 gl_ModelViewMatrix;
    uniform mat4 gl_ProjectionMatrix;
    
    void main()
    {
      gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(aPos, 1.0);
      vTexCoord = texcd;//フラグメントシェーダへテクスチャ座標を渡す
    }
    

    フラグメントシェーダ

    #version 460 core
    
    out vec4 FragColor;//色の出力先
    
    uniform sampler2D uTex;//テクスチャデータ(自動でセットされている)
      
    in vec2 vTexCoord;//頂点シェーダから渡されたテクスチャ座標
    
    void main()
    {
    //テクスチャデータとテクスチャ座標から色を決定
    FragColor = texture(uTex,vTexCoord); }

    GLSLを試す (2) 変換行列の受け渡し

    頂点シェーダへの変換行列の受け渡しの方法は二つ。

    built-in変数を使う場合

    C言語側

    void display(void)
    {
      glClearColor(0, 0, 0, 1);
      glClear(GL_COLOR_BUFFER_BIT);
    
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(65, 1, 0.1, 10);
    
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslated(0.0, 0.0, -0.8);
    
      // シェーダを使う
      glUseProgram(ProgramID);
    
      // 最初の属性バッファ:頂点
      glEnableVertexAttribArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
      glVertexAttribPointer(
        0,                  // シェーダ内のlayoutとあわせる
        3,                  // サイズ
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
      // カラーバッファを有効にする
      glEnableVertexAttribArray(1);
      glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
      glVertexAttribPointer(
        1,                  // シェーダ内のlayoutとあわせる
        3,                  // サイズ
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
      // 三角形を描きます!
      glDrawArrays(GL_TRIANGLES, 0, 3); // 頂点0から始まります。合計3つの頂点です。&rarr;1つの三角形です。
    
      glDisableVertexAttribArray(0);
      glDisableVertexAttribArray(1);
    
      glFlush();
    }
    

    頂点シェーダ側

    uniform変数 gl_ModelViewMatrixやgl_ProjectionMatrixでOpenGLの行列にアクセス出来る。これらはglUniformMatrix4fvで設定する必要が無い。

    #version 460 core
    
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 incolor;
    
    out vec4 vertexColor;
    
    uniform mat4 gl_ModelViewMatrix;
    uniform mat4 gl_ProjectionMatrix;
    
    void main()
    {
      gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(aPos, 1.0);
      vertexColor = vec4(incolor, 1.0);
    }
    

    この他のBuilt-In-Matrixは以下を参照

    https://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations

    glUniformMatrix4fvで共有する場合

    C言語側

    自分のプログラム内で行列を用意してglUniformMatrix4fvでGPUへ転送する。Projection Matrixを計算するコードを自前で書くのも間抜けなので

    https://www.khronos.org/opengl/wiki/GluPerspective_code

    などをコピペすると良い。

    void display(void)
    {
      glClearColor(0, 0, 0, 1);
      glClear(GL_COLOR_BUFFER_BIT);
    
      // シェーダを使う
      glUseProgram(ProgramID);
    
      //変換行列を定義
      // uniform mat4がfloatのため、こちらもfloatでないといけない
      GLfloat mfproj[16];
      GLfloat mftran[16];
    
      mfproj[ 0] = 2.26961231;
      mfproj[ 1] = 0.0;
      mfproj[ 2] = 0.0;
      mfproj[ 3] = 0.0;
      mfproj[ 4] = 0.0;
      mfproj[ 5] = 2.41421366;
      mfproj[ 6] = 0.0;
      mfproj[ 7] = 0.0;
      mfproj[ 8] = 0.0;
      mfproj[ 9] = 0.0;
      mfproj[10] = -1.00020003;
      mfproj[11] = -1.00000000;
      mfproj[12] = 0.0;
      mfproj[13] = 0.0;
      mfproj[14] = -0.0200020000;
      mfproj[15] = 0.0;
    
      mftran[ 0] = 1.0;
      mftran[ 1] = 0.0;
      mftran[ 2] = 0.0;
      mftran[ 3] = 0.0;
      mftran[ 4] = 0.0;
      mftran[ 5] = 1.0;
      mftran[ 6] = 0.0;
      mftran[ 7] = 0.0;
      mftran[ 8] = 0.0;
      mftran[ 9] = 0.0;
      mftran[10] = 1.0;
      mftran[11] = 0.0;
      mftran[12] = 0.2;
      mftran[13] = 0.0;
      mftran[14] = 0.0;
      mftran[15] = 1.0;
    
    
      GLint proj = glGetUniformLocation(ProgramID, "m_projection");
      GLint tran = glGetUniformLocation(ProgramID, "m_transform");
      glUniformMatrix4fv(proj, 1, GL_FALSE, mfproj);
      glUniformMatrix4fv(tran, 1, GL_FALSE, mftran);
    
      // 最初の属性バッファ:頂点
      glEnableVertexAttribArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
      glVertexAttribPointer(
        0,                  // 属性0
        3,                  // サイズ
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
      // 2nd attribute buffer : colors
      glEnableVertexAttribArray(1);
      glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
      glVertexAttribPointer(
        1,                  // 属性1
        3,                  // サイズ
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
      // 三角形を描きます!
      glDrawArrays(GL_TRIANGLES, 0, 3);
    
      glDisableVertexAttribArray(0);
      glDisableVertexAttribArray(1);
    
      glFlush();
    }
    

    頂点シェーダ側

    #version 460 core
    
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 incolor;
    
    out vec4 vertexColor;
    
    uniform mat4 m_transform;
    uniform mat4 m_projection;
    
    void main()
    {
      gl_Position = m_projection * m_transform * vec4(aPos, 1.0);
      vertexColor = vec4(incolor, 1.0);
    }
    

    GLSLを試す (1)

    glBegin - glEndが大好きなのだけれどそろそろモダンOpenGLにも触っておかないとまずいということでVBOと頂点シェーダとフラグメントシェーダの基礎を触っておく。

    ややこしいのは、VBO(=頂点バッファ)のコードと頂点シェーダ関連コードが、直接的な関連性が低いのに密接に絡み合っているところ。

    CPU側ソースコード

    glut初期化コード

    glutを使わないのなら勿論必要ない。ただしglewを使うのでその初期化が必要。

    余談だけれどもgl.hを使うのならinclude順はglew.h→gl.hとなる。さらにwindowsではgl.hの前にwindows.hを入れなければならない。つまりwgl等でウィンドウを作成する場合、

    #include <windows.h>
    #include <gl/glew.h>
    #include <gl/GL.h>

    のような順番になる。この例ではglutだけなのでgl.hは自分でincludeしない。ただしglut.hの中でgl.hがincludeされているので、順番はglew.h→glut.hでなければならない。さもなくば

    fatal error C1189: #error: gl.h included before glew.h

    と言われる。

    #pragma warning(disable:4996)
    
    #pragma comment(lib,"glew32.lib")
    
    
    #include <gl/glew.h>
    #include <GL/glut.h>
    
    #include <fstream>
    #include <sstream>
    #include <vector>
    #include <algorithm>
    
    
    void init(void);
    void display(void);
    
    int main(int argc, char *argv[])
    {
      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_RGBA);
      glutCreateWindow(argv[0]);
      glutDisplayFunc(display);
    glewInit(); // glewの初期化
    init(); glutMainLoop(); return 0; }

    初期化コード呼び出し元

    void init(void)
    {
    
      //頂点データと色情報の作成
      prepare_buffers();
    
      //頂点シェーダの準備
      prepare_vertex_shader();
    
      //フラグメントシェーダの準備
      prepare_fragment_shader();
    
      //プログラムのリンク
      link_program();
    
    }
    

    頂点データとバッファの作成コード

    今までglBegin~glEndで囲んでいたデータを配列として作成して先にGPUへ転送しておく。

    //バッファとデータ
    typedef GLfloat points_t[3];
    GLuint vertexbuffer;//バッファのIDを格納する変数
    GLuint colorbuffer;//バッファのIDを格納する変数
    points_t position[3];
    points_t color[3];
    
    //////////////////////////////////////////////////
    void prepare_buffers() {
    
      //頂点座標
      position[0][0] = 0;
      position[0][1] = 0.5;
      position[0][2] = 0;
    
      position[1][0] = 0.5;
      position[1][1] = -0.5;
      position[1][2] = 0;
    
      position[2][0] = -0.5;
      position[2][1] = -0.5;
      position[2][2] = 0;
    
    
      //色
      color[0][0] = 1.0;
      color[0][1] = 0.0;
      color[0][2] = 0.0;
    
      color[1][0] = 0.0;
      color[1][1] = 1.0;
      color[1][2] = 0.0;
    
      color[2][0] = 0.0;
      color[2][1] = 0.0;
      color[2][2] = 1.0;
    
      glGenBuffers(1, &vertexbuffer);
      glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
      glBufferData(
    GL_ARRAY_BUFFER,
         
    3 * 3 * sizeof(GLfloat),
    position,
    GL_STATIC_DRAW); glGenBuffers(1, &colorbuffer); glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); glBufferData(
    GL_ARRAY_BUFFER,
    3 * 3 * sizeof(GLfloat),
    color,
    GL_STATIC_DRAW); }

    頂点シェーダの準備

    クソ長く見えるがやっていることは
    ①glCreateShaderでシェーダのIDを作成
    ②glShaderSourceでシェーダのソースコードをシェーダに教える
    ③glCompileShaderでシェーダをコンパイル
    ④glGetShaderivでシェーダのコンパイルに成功したかを確認
    ⑤glGetShaderInfoLogでエラー内容を確認

    だけで本質的には十行程度。ファイル読み込み部がコードの長さを異常に長くみせている。本質とは直接関係ないのに。

    GLuint VertexShaderID;

    void
    prepare_vertex_shader() { ////////////////////////////////////////////// // シェーダを作ります // (作るといっても宣言みたいなもの) VertexShaderID = glCreateShader(GL_VERTEX_SHADER); //////////////////////////////////////////// // ファイルから頂点シェーダを読み込みます。
    // 注意 ここはSTLのifstreamとかstringstreamの使い方の話で、
    // OpenGL命令は一つも無い。
    const char * vertex_file_path = "C:\\test\\verts.sh"; std::string VertexShaderCode; std::ifstream VertexShaderStream(vertex_file_path, std::ios::in); if (VertexShaderStream.is_open()) { std::stringstream sstr; sstr << VertexShaderStream.rdbuf(); VertexShaderCode = sstr.str(); VertexShaderStream.close(); } //////////////////////////////////////////// // 頂点シェーダをコンパイルします。 printf("Compiling shader : %s\n", vertex_file_path); char const * VertexSourcePointer = VertexShaderCode.c_str(); glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL); glCompileShader(VertexShaderID); //////////////////////////////////////////// // エラーチェック GLint Result = GL_FALSE; int InfoLogLength; // 頂点シェーダをチェックします。 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); if (Result == FALSE) { std::vector<char> VertexShaderErrorMessage(InfoLogLength); glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]); } }

    あとエラー処理が行数を嵩張らせている。普通(?)OpenGLで描画とかするときに、エラーを無視してもなんとなく上手く動いているように見えることも多いけれど、シェーダのコンパイルをする以上、コンパイルエラーをちゃんと見ないとデバッグ出来ないのでエラー処理はちゃんと入れないとまずい。

    これはエラーを見る癖をつけましょうとかの精神論ではなく、見ないと何故動かないのかが全くわからないから省きようがない

    フラグメントシェーダの準備

    頂点シェーダとの違いは、読み込むファイルと、glCreateShaderに渡す定数がGL_FRAGMENT_SHADERになっているところぐらいで、ほぼ同じ。

    GLuint FragmentShaderID;

    void
    prepare_fragment_shader() { ///////////////////////////////////////////// // シェーダを作ります。 FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); ///////////////////////////////////////////// // ファイルからフラグメントシェーダを読み込みます。 const char * fragment_file_path = "C:\\test\\frags.sh"; std::string FragmentShaderCode; std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in); if (FragmentShaderStream.is_open()) { std::stringstream sstr; sstr << FragmentShaderStream.rdbuf(); FragmentShaderCode = sstr.str(); FragmentShaderStream.close(); } ///////////////////////////////////////////// // フラグメントシェーダをコンパイルします。 printf("Compiling shader : %s\n", fragment_file_path); char const * FragmentSourcePointer = FragmentShaderCode.c_str(); glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL); glCompileShader(FragmentShaderID); GLint Result = GL_FALSE; int InfoLogLength; /////////////////////////////////////////////
    /
    / フラグメントシェーダをチェックします。 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); if (Result == GL_FALSE) { std::vector<char> FragmentShaderErrorMessage(InfoLogLength); glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]); } }

    プログラムのリンク

    頂点シェーダとフラグメントシェーダのセットをProgramとして一つに束ねる。

    ここもやっていることは、
    ①glCreateProgram でプログラムIDを取得
    ②glAttachShader でシェーダを登録
    ③glLinkProgram プログラムをリンク
    ④glGetProgramiv でプログラムのエラーをチェック
    ⑤glGetProgramInfoLog でプログラムのエラーの内容をチェックする

    GLuint ProgramID;

    void
    link_program() { GLint Result = GL_FALSE; int InfoLogLength; //////////////////////////////////////// // プログラムをリンクします。 fprintf(stdout, "Linking program\n"); ProgramID = glCreateProgram(); glAttachShader(ProgramID, VertexShaderID); glAttachShader(ProgramID, FragmentShaderID); glLinkProgram(ProgramID); //////////////////////////////////////// // プログラムをチェックします。 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); std::vector<char> ProgramErrorMessage((std::max)(InfoLogLength, int(1))); glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); fprintf(stdout, "%s\n", &ProgramErrorMessage[0]); }

    シェーダ側ソースコード

    頂点シェーダ (verts.sh)

    拡張子は何でもいい。shだとシェルスクリプトと勘違いしそうなら.verts、.fragsなどでいい。

    #version 460 core
    
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 incolor;
    
    out vec4 vertexColor;
    
    uniform mat4 gl_ModelViewMatrix;
    uniform mat4 gl_ProjectionMatrix;
    
    void main()
    {
      gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(aPos, 1.0);
      vertexColor = vec4(incolor, 1.0);
    }
    

    フラグメントシェーダ(frags.sh)

    #version 460 core
    
    out vec4 FragColor;
      
    in vec4 vertexColor;
    
    void main()
    {
      FragColor = vertexColor;
    } 
    

    CPU側 描画

    void display(void)
    {
      glClearColor(0, 0, 0, 1);
      glClear(GL_COLOR_BUFFER_BIT);
    
      glLoadIdentity();
      glTranslated(0.5, 0.0, 0.0);//平行移動
    
      // シェーダを使う
      glUseProgram(ProgramID);
    
      // 頂点バッファ:頂点
      glEnableVertexAttribArray(0);
      glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
      glVertexAttribPointer(
        0,                  // シェーダ内のlayoutとあわせる
        3,                  // 1要素の要素数(x,y,z)で3要素
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
      // カラーバッファを有効にする
      glEnableVertexAttribArray(1);
      glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
      glVertexAttribPointer(
        1,                  // シェーダ内のlayoutとあわせる
        3,                  // 1要素の要素数(r,g,b)で3要素
        GL_FLOAT,           // タイプ
        GL_FALSE,           // 正規化しない(データが整数型の時)
        0,                  // ストライド
        (void*)0            // 配列バッファオフセット
      );
    
      // 三角形を描きます!
      glDrawArrays(GL_TRIANGLES, 0, 3);
    
      glDisableVertexAttribArray(0);//バッファを無効にする
      glDisableVertexAttribArray(1);
    
      glFlush();
    }
    

    その他

    後半へ続く・・・