ぬの部屋(仮)
nu-no-he-ya
  • 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
           
  • Blender Fantasy Crystals in Blender 2.8のチュートリアルを試す

    Blender Fantasy Crystals in Blender

    レンダラはCyclesを使用する。

    1.造形

    1.1 [Shift+A] → [Mesh]→ Ico Sphereを追加し、[S][Z]でZ軸方向に拡大する

    1.2 Decimateモディファイアを追加し、CollapseでRatio=0.4706に設定する

    1.3 Shift+Dで複製し、外側の透明な部分と内側の色を付ける部分を別に作成する。

    内側のみ、Bevelモディファイアを追加する

    2.ランプの追加

    Areaランプを追加し、Strength=500とする

    3.外側のマテリアル

    4.内側のマテリアル

    レンダリング結果

    Blender Cyclesでproceduralなグリッドを表示

    テクスチャでグリッドを描く。

    Planeを一枚追加し、マテリアルでX方向とY方向のWave Textureを追加。

    両方のテクスチャをGreaterThanで一定値以下を0,それ以外を1にして、Multiplyする。

    Texture CoordinateのObjectから、座標をMultiplyし、Wave Textureに繋げる。

    最後に、今作ったテクスチャをMix ShaderのFacに繋げる。

    可変長引数テンプレート関数で交換法則のない式を一気に計算する関数

    例えばsumの場合、以下のように書ける。

    転載元:http://yohshiy.blog.fc2.com/blog-entry-300.html

    // 末端 isum
    inline int isum()
    {
      return 0;
    }
    
    // 再帰呼び出し isum
    template<typename First, typename... Rest>
    int isum(const First& first, const Rest&... rest)
    {
      return first + isum(rest...);
    }
    

    +や*の場合は交換法則が成り立つ。つまり、

    (a+(b+(c+d))) == (((a+b)+c)+d)

    だ。しかし、例えば/の場合、交換法則が成り立たない

    (a/(b/(c/d))) != (((a/b)/c)/d)

    ではどうすればいいか。

    // 再起の最後
    template<typename First, typename Second>
    inline auto div(const First& first, const Second& second)
    {
      return first / second;
    }
    
    // 連続で割り算を行う関数
    template<typename First, typename Second, typename... Rest>
    inline auto div(const First& first, const Second& second, const Rest& ... rest)
    {
      return div( div(first , second) , rest...);
    }
    

    動作確認

    #include <iostream>
    
    
    //////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////
    
    // 再起の最後
    template<typename First, typename Second>
    inline auto div(const First& first, const Second& second)
    {
      return first / second;
    }
    
    // 連続で割り算を行う関数
    template<typename First, typename Second, typename... Rest>
    inline auto div(const First& first, const Second& second, const Rest& ... rest)
    {
      return div(div(first, second), rest...);
    }
    //////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////
    // 後ろから計算する場合
    
    // 再起の最後
    inline auto backDIV()
    {
      return 1.0;
    }
    
    // 連続で割り算を行う関数
    template<typename First, typename... Rest>
    inline auto backDIV(const First& first, const Rest& ... rest)
    {
      return first / backDIV(rest...) ;
    }
    //////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////
    
    
    int main()
    {
      std::cout << "普通計算:";
      double k1 = 5.0 / 8.0 / 2.0;
      std::cout << k1;
    
      std::cout << std::endl;
      std::cout << "再帰(前方):";
      double k2 = div(5.0, 8.0, 2.0);
      std::cout << k2;
    
    
      std::cout << std::endl;
      std::cout << "再帰(後方):";
      double k3 = backDIV(5.0, 8.0, 2.0);
      std::cout << k3;
    
    
    
      int i;
      std::cin >> i;
    }
    

    結果

    普通計算:0.3125
    再帰(前方):0.3125
    再帰(後方):1.25
    

    Blender Cycles PythonでTextureノードが何に接続されているかを検出する

    DAZ Importer 1.4でBlenderへExportした結果のマテリアルがある。

    これのテクスチャノードが、Bump用なのか、あるいはDiffuse用なのか...を知りたい。

    スクリプト

    import bpy
    
    
    
    # @brief 与えられたCyclesのノードツリーの中のImage Textureノードを全て取得して返す
    # @param [in] nodetree Cyclesのノードツリー
    # @return Image Textureノードの一覧
    def get_all_textures(nodetree):
        nodes = nodetree.nodes
    
        texturenodelist = []
            
        for node in nodes:
            if node.type == 'TEX_IMAGE':
                texturenodelist.append(node)
                
        return texturenodelist
    # @brief ノードのto_nodeを辿り、特定のノードが見つかるまで再帰的に検索する
    # @param [in] node Cyclesのノード
    # @return 見つかったノード
    # @retval None 見つからなかった場合
    def get_input_to(node):
        
        if node.type == 'BUMP':
            return node
        if node.type == 'NORMAL_MAP':
            return node
        elif node.type == 'BSDF_DIFFUSE':
            return node
        elif node.type == 'BSDF_GLOSSY':
            return node
        elif node.type == 'BSDF_PRINCIPLED':
            return node
    
        for output in node.outputs:
            for link in output.links:
                return get_input_to(link.to_node)# 目的のノード出ないなら再帰呼び出し
        return None
    # @brief テクスチャノードから、そのノードが繋がっているノードを探す
    # @param [in] texnode CyclesのImage Textureノード
    # @return 見つかったBump,Normalまたは各種BSDFノード
    # @retval None 見つからなかった
    def get_tex_input_to(texnode):
        for link in texnode.outputs["Color"].links:# テクスチャノードの"Color"に接続されたノードを探す
            prevnode = link.to_node
            tonode = get_input_to(prevnode)
            
            if tonode is not None:
                return tonode
    
        return None
    # @brief マテリアルスロット内の全てのマテリアルについて、テクスチャノードの接続先を検索する
    # @param [in] slots マテリアルスロット
    # @return なし
    def about_all_material(slots):
        
        for slot in slots:
            
            texturenodelist=[]
            
            material = slot.material
        
            nodetree = material.node_tree
            
            print("------" , material.name , "-------")
            texturenodelist = get_all_textures(nodetree)
            
            for texnode in texturenodelist:
                
                inputto = get_tex_input_to(texnode)
                
                print( texnode.name , inputto )
    print("---------------")
    print("---------------")
    print("---------------")
    
    # 呼び出し
    about_all_material(bpy.context.active_object.material_slots)
    

    出力結果

    ------ Torso-1 -------
    Acicia_NM_1002 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_B_1002 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1002 Base <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_1002_SSS <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_Torso_Ref_1002 <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    ------ Face-1 -------
    Acicia_NM_1001 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_B_1001 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1001 Shadow 07 <bpy_struct, ShaderNodeBsdfDiffuse("Diffuse BSDF")>
    Acicia_1001_SSS Default None
    Acicia_1001_Spec None
    ------ Lips-1 -------
    Acicia_NM_1001 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_B_1001 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia 1001 Lip 02 <bpy_struct, ShaderNodeBsdfDiffuse("Diffuse BSDF")>
    Acicia_1001_SSS Lip 02 None
    Acicia_1001_Spec None
    Acicia_Spc_1001 <bpy_struct, ShaderNodeBsdfGlossy("Glossy BSDF")>
    ------ Teeth-1 -------
    Acicia_MouthNM_1005 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_MouthB_1005 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1005 <bpy_struct, ShaderNodeBsdfDiffuse("Diffuse BSDF")>
    ------ Ears-1 -------
    Acicia_NM_1001 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_B_1001 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1001 Shadow 07 <bpy_struct, ShaderNodeBsdfDiffuse("Diffuse BSDF")>
    Acicia_1001_SSS Default None
    Acicia_1001_Spec None
    ------ Legs-1 -------
    Acicia_NM_1003 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_B_1003 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1003 Base <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_1003_SSS <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_Rh_1003 <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    ------ EyeSocket-1 -------
    Acicia_B_1001 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1001 Shadow 07 <bpy_struct, ShaderNodeBsdfDiffuse("Diffuse BSDF")>
    Acicia_1001_SSS Default None
    Acicia_1001_Spec None
    Acicia_NM_1001 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    ------ Mouth-1 -------
    Acicia_MouthNM_1005 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_MouthB_1005 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1005 <bpy_struct, ShaderNodeBsdfDiffuse("Diffuse BSDF")>
    ------ Arms-1 -------
    Acicia_NM_1004 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_B_1004 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1004 Base <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_1004_SSS <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_Rh_1004 <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    ------ Pupils-1 -------
    ------ EyeMoisture-2 -------
    ------ Fingernails-1 -------
    Acicia_NM_1004 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_B_1004 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1004 Base <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_1004_SSS <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_Rh_1004 <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    ------ Cornea-1 -------
    ------ Irises-1 -------
    Acicia_EyesNM_1006 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_EyesB_1006 <bpy_struct, ShaderNodeBump("Bump")>
    Acacia Eyes Color Red 02 <bpy_struct, ShaderNodeBsdfDiffuse("Diffuse BSDF")>
    ------ Sclera-1 -------
    Acicia_1006 <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    ------ Toenails-1 -------
    Acicia_NM_1003 <bpy_struct, ShaderNodeNormalMap("Normal Map")>
    Acicia_B_1003 <bpy_struct, ShaderNodeBump("Bump")>
    Acicia_1003 Base <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_1003_SSS <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    Acicia_Rh_1003 <bpy_struct, ShaderNodeBsdfPrincipled("Principled BSDF")>
    

    特定できなかった物はNoneが入っている

    FTGLを試す(2)文字列の描画

    FTGLを使うと日本語を出力できる。

    サンプルコード

    #include <iostream>
    
    #include <Windows.h>
    #include <gl/GL.h>
    #include <gl/GLU.h>
    #include <gl/freeglut.h>
    
    #include <FTGL/ftgl.h>
    
    #pragma comment(lib,"opengl32.lib")
    #pragma comment(lib,"freeglut.lib")
    #pragma comment(lib,"ftgl.lib")
    
    #pragma warning(disable:4996)
    
    // freeglut:
    // http://freeglut.sourceforge.net/
    
    // freetype2:
    // https://www.freetype.org/
    
    //FTGL
    // https://sourceforge.net/projects/ftgl/
    
    // 参考サイト FTGLの使い方
    // http://slis.tsukuba.ac.jp/~fujisawa.makoto.fu/lecture/iml/text/screen_character.html
    
    //ウィンドウの幅と高さ
    int width, height;
    
    
    
    struct CFtglObject {
      const char* FONT_PATHNAME = "C:\\Windows\\Fonts\\msgothic.ttc";
      FTPixmapFont* g_pFont;
      unsigned long g_ulFontSize;  // フォントサイズ
    
      ~CFtglObject() {
        delete g_pFont;
      }
     
      // フォントの初期化
      void init(const unsigned long fontsize) {
    
        g_ulFontSize = fontsize;
    
        if (!g_pFont) {
          g_pFont = new FTPixmapFont(FONT_PATHNAME);
          if (g_pFont->Error()) {
            delete g_pFont;
            g_pFont = nullptr;
          }
          else {
            g_pFont->FaceSize(g_ulFontSize);
          }
        }
      }
      // FTGLで文字列を描画
      void print(const std::wstring& wstr,float x, float y) {
    
        if (g_pFont) {
          glRasterPos2f(x, y);
          g_pFont->Render(wstr.c_str());
        }
    
      }
    };
    CFtglObject ftglo;
    
    static int rot = 0;
    
    //描画関数
    void disp(void) {
    
      glViewport(0, 0, width, height);
    
      glClearColor(0.2, 0.2, 0.2, 1);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
      glLoadIdentity();
      glScaled(0.5, 0.5, 0.5);
    
      glRotatef(rot, 1, 1, 1);
      rot++;
    
      glDisable(GL_CULL_FACE);
      double v = 0.7;
    
      glBegin(GL_QUADS);
      glColor3d(1, 0, 0);
      glVertex2d(-v, -v);
    
      glColor3d(0, 1, 0);
      glVertex2d(v, -v);
    
      glColor3d(0, 0, 1);
      glVertex2d(v, v);
    
      glColor3d(1, 1, 1);
      glVertex2d(-v, v);
    
      glEnd();
    
    
      glColor3d(1, 1, 0);
      wchar_t text[1000];
      swprintf(text, L"赤 %0.3lf %0.3lf",-v, -v);
      ftglo.print(text, -v, -v );
    
      swprintf(text, L"緑 %0.3lf %0.3lf", v, -v);
      ftglo.print(text,  v, -v);
    
      swprintf(text, L"青 %0.3lf %0.3lf", v, v);
      ftglo.print(text,  v,  v);
    
      swprintf(text, L"白 %0.3lf %0.3lf",-v, v);
      ftglo.print(text, -v,  v);
      glFlush();
    }
    
    //ウィンドウサイズの変化時に呼び出される
    void reshape(int w, int h) {
      width = w; height = h;
    
      disp();
    }
    
    //ドラッグ
    void motion(int x, int y)
    {
      disp();
    }
    
    //エントリポイント
    int main(int argc, char** argv)
    {
      glutInit(&argc, argv);
      glutInitWindowPosition(100, 50);
      glutInitWindowSize(500, 500);
      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
    
    //FTGL使用クラスの初期設定 ftglo.init(25); glutCreateWindow("sample"); glutDisplayFunc(disp); glutReshapeFunc(reshape); glutMotionFunc(motion); glutMainLoop(); return 0; }

    FTGLを試す(1)ビルド

    FTGL 2.1.3~rc5

    1.以下からダウンロード:

    https://sourceforge.net/projects/ftgl/

    2.展開

    CMakeの必要はない。

    vc8 (Visual Studio 2005)と、vc71(Visual Studio 2003)のソリューションが用意されているので、2005用slnを開いてVC++2019に変換する

    ftgl-2.1.3~rc5\msvc\vc8\ftgl.sln

    3.freetype2の設定・ビルド

    freetype2のincludeとlibディレクトリを設定してビルドする

    4.結果

    ビルド済みバイナリ・・・ ftgl-2.1.3-rc5\msvc\Build

    includeファイル群・・・ ftgl-2.1.3-rc5\src

    をそれぞれ使いやすい場所に移動する。

    Blender CyclesのTextureノードをVrayに変換

    このように、CyclesでImage Textureノードを追加し、画像を設定した上でノードを選択状態にしておき、スクリプトを走らせると、

    Vrayのノードとして追加される。

    ソースコード

    import bpy
    
    # vray for blenderに必要
    from vb30.lib import LibUtils
    from vb30.lib import BlenderUtils
    from vb30.nodes import tree_defaults
    
    
    # 選択したノードを取得する
    # Cycles側でImageTextureノードを特定するコードを書いても良いが
    # ImageTextureノードを追加して選択した上でこれを呼び出した方が多分単純なのでこれを使う
    # CyclesのImage Textureノードを取得できれば何でも良い
    def get_selected_node(material):
        node_tree = material.node_tree    
        sel = [x for x in node_tree.nodes if x.select]
        return sel[0]
    # 追加した Vray ノードを接続する
    # _VrayImageNode は _vrayNodeTree から探すこともできるけれど
    # せっかく特定できているので引数で渡す
    def connect_image_and_material(_vrayNodeTree,_VrayImageNode):
    
        # vrayのStandard Materiahを取得。デフォルトで存在しているはず
        matStandard = None
        for v in _vrayNodeTree.nodes:
            if v.name == 'Standard Material':
                matStandard = v
    
        vstand = matStandard
        vstand.location.x = -250
        vstand.location.y = 0
    
        vtex = _VrayImageNode
        vtex.location.x = vstand.location.x - vstand.width - 50
        vtex.location.y = 0
    
        # ノードを接続
        _vrayNodeTree.links.new( 
            vtex.outputs['Color'] , 
            vstand.inputs['Diffuse'] 
        )
    # マテリアルからImage Textureノードを特定し、Vrayのノードを追加する
    def set_vray_image_node(mat):
        
        # Image Textureノードがマウスで選択されている事が前提
        CyclesNode = get_selected_node(mat)
        
        # Vrayに切り替え
        bpy.context.scene.render.engine = "VRAY_RENDER_RT"
        
        # vray用のマテリアル追加
        tree_defaults.AddMaterialNodeTree(mat)
        mat.vray.ntree.name = mat.name + '-vray'
    
        # vrayのテクスチャノード追加
        VrayImageNode = mat.vray.ntree.nodes.new(type='VRayNodeMetaImageTexture')
        
    
        # vrayのテクスチャノードにテクスチャを指定。
        VrayImageNode.texture.image = bpy.data.images[CyclesNode.image.name]
        
        # ノードを繋ぎレンダリングできるようにする
        connect_image_and_material(mat.vray.ntree,VrayImageNode)
        
    
    material = bpy.data.materials['Material']
    
    set_vray_image_node(material)
    

    結果

    使用画像

    https://pixabay.com/ja/illustrations/%E8%8A%B1-%E8%8F%8A-%E5%9B%BD%E5%A2%83-%E3%82%B4%E3%83%BC%E3%83%AB%E3%83%89%E7%AE%94-5625951/

    FreeType2を試す-5- 一行のテキストを出力

    文字列を画像として出力する。

    仕組みとしては、画像と高さ、幅情報、移動量情報を全て配列にし、一行分描画してから高さ計算を行う。

    #pragma once
    
    #include <ft2build.h>
    #include FT_FREETYPE_H
    
    #include <freetype/ftbitmap.h>
    
    #include <vector>
    
    
    // 人文字の画像とサイズ・位置の情報
    struct charpict {
      std::vector<char> m_pic;
      int width;
      int height;
      int left;
      int top;
      int advancex;
      int advancey;
    };
    // 文字列をラスタライズするクラス
    class SingleLineText {
      std::vector<charpict> m_pict;
    
      int imageWidth; //!< 結果画像の幅
      int imageHeight;//!< 結果画像の高さ
      std::vector<unsigned char> m_image;//!< 結果画像
    
      FT_Library* m_plib;
      FT_Face face;      // handle to face object
      //! @brief m_imageに書き込むための座標計算関数
      //! @param [in] x 二次元座標のx
      //! @param [in] y 二次元座標のy
      //! @return 一次元配列のindex
      int pixel_pos(const int x, const int y) {
        return y * imageWidth + x;
      }
      //! @brief 作成済みの一文字の画像を全体画像に書き込む
      //! @param [in] index m_pictのindex。何文字目をレンダリングするか
      //! @param [in] pen_x この文字のm_image上の描画開始位置
      //! @param [in] maxtop 全ての文字の中の高さの最大値
      //! @return なし
      void draw_single_character(const int index, const int pen_x, const int maxtop) {
    
        char* buffer = &m_pict[index].m_pic[0];
        int Width = m_pict[index].width;
        int Height = m_pict[index].height;
        int startx = pen_x + m_pict[index].left;
        int starty = -m_pict[index].top + maxtop;
    
        for (size_t y = 0; y < Height; y++) {
          for (size_t x = 0; x < Width; x++) {
    
            int xx = startx + x;
            int yy = starty + y;
    
            if (xx < 0)continue;
            if (yy < 0)continue;
            if (xx >= imageWidth)continue;
            if (yy >= imageHeight)continue;
    
            if (buffer[y * Width + x]) {
              m_image[pixel_pos(xx, yy)] = buffer[y * Width + x];
            }
          }
        }
    
      }
      //! @brief 全ての文字を結果に書き込む
      //! @param [in] maxtop 全ての文字の中の高さの最大値
      //! @return なし
      void characters_to_image(const int maxtop) {
    
        int pen_x = 0;
    
        for (size_t i = 0; i < m_pict.size(); i++) {
          if (m_pict[i].m_pic.size()) {
            // 画像書き込み
            draw_single_character(i, pen_x,maxtop);
          }
    
          // 描画位置を更新
          pen_x += m_pict[i].advancex;
        }
    
      }
    public:
    
      //! @brief コンストラクタ
      //! @param [in] ftLib FreeTypeライブラリオブジェクトへのポインタ
      //! @param [in] fontfilename フォントファイル名
      SingleLineText(FT_Library* ftLib,const char* fontfilename) {
        m_plib = ftLib;
    
        FT_Error error;
    
        // フォントファイル読み込み
        error = FT_New_Face(
          *m_plib,
          fontfilename,
          0,
          &face
        );
    
        //文字コード指定
        error = FT_Select_Charmap(
          face,               // target face object
          FT_ENCODING_UNICODE // エンコード指定
        );
    
    
        if (error == FT_Err_Unknown_File_Format) {
          throw "FT_Err_Unknown_File_Format";
        }
        else if (error) {
          throw "FT_Err";
        }
    
      }
      //! @brief ラスタライズ
      //! @param [in] text 元のテキスト
      //! @param [in] pixel_size_y 文字サイズ
      //! @return なし
      void rasterize(std::wstring text,const int pixel_size_y) {
    
        FT_Error error;
    
        error = FT_Set_Pixel_Sizes(
          face,            // handle to face object
          0,               // pixel_width
          pixel_size_y);   // pixel_height
    
        int maxtop = INT_MIN;
        imageHeight = INT_MIN;
        imageWidth = 0;
    
        m_pict.clear();
    
        //textの各文字について画像を作成
        for (size_t k = 0; k < text.size(); k++) {
    
          // 文字の取得
          FT_ULong character = text[k];
          FT_UInt char_index = FT_Get_Char_Index(face, character);
    
          // グリフ(字の形状)読込
          //FT_LOAD_COLOR
          error = FT_Load_Glyph(face, char_index, FT_LOAD_RENDER | FT_LOAD_COLOR);
          if (error)
            return; // ignore errors
    
          // 文字を画像化
          //FT_RENDER_MODE_MONO
          //FT_RENDER_MODE_NORMAL
          FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
    
          //データを8bit画像にする
          FT_Bitmap tmpbmp;
          FT_Bitmap_Init(&tmpbmp);
          FT_Bitmap_Convert(*m_plib, &face->glyph->bitmap, &tmpbmp, 1);
    
          m_pict.emplace_back();
    
          ////////////////////////////////////////
          //画像を配列に保存
          const int Width = tmpbmp.width;
          const int Height = tmpbmp.rows;
          for (size_t y = 0; y < Height; y++) {
            for (size_t x = 0; x < Width; x++) {
    
              m_pict.back().m_pic.push_back(tmpbmp.buffer[y * Width + x]);
    
            }
          }
    
          FT_Bitmap_Done(*m_plib, &tmpbmp);
    
    
          m_pict.back().width = Width;
          m_pict.back().height = Height;
          m_pict.back().left = face->glyph->bitmap_left;
          m_pict.back().top = face->glyph->bitmap_top;
          m_pict.back().advancex = face->glyph->advance.x >> 6;
          m_pict.back().advancey = face->glyph->advance.y >> 6;
          ////////////////////////////////////////
    
          maxtop = (std::max)(maxtop, m_pict.back().top);
    
          imageHeight = (std::max)(
            imageHeight, 
            -m_pict[k].top + maxtop + m_pict[k].height
            );
          imageWidth += m_pict.back().advancex;
    
        }
    
        //結果画像のメモリ確保
        m_image.resize(imageWidth * imageHeight, 0);
    
        //画像に全ての文字を書き込む
        characters_to_image(maxtop);
    
      }
      void done_face() {
        FT_Done_Face(face);
      }
      int ImageWidth() { return imageWidth; }
      int ImageHeight() { return imageHeight; }
      const unsigned char* image()const { return &m_image[0]; }
    
    
    };
    

    呼び出し

    #include <string>
    #include <array>
    
    #include "SingleLineText.hpp"
    
    #include "pnm_rw.hpp"
    
    #pragma warning(disable:4996)
    
    #pragma comment(lib,"freetyped.lib")
    
    
    int main()
    {
      FT_Library  library; // handle to library
      FT_Error error;
    
    
      error = FT_Init_FreeType(&library);
      if (error)
        return -1;
    
      ////msgothic.ttc
      //meiryo
      SingleLineText slt(&library, "C:\\Windows\\Fonts\\msgothic.ttc");
    
      int pixel_size_y = 24;
    
      std::wstring chars = L"いろ は。にほへと,abc d";
      
      slt.rasterize(chars, pixel_size_y);//画像の作成
    
      //ファイル出力
      write_pnm(
        "C:\\test\\text.pgm", 
        slt.image(),
        slt.ImageWidth(), 
        slt.ImageHeight(), 
        PNM_TYPE::P2
      );
    
    
      slt.done_face();
      // FreeType2の解放
      FT_Done_FreeType(library);
    }
    

    FreeType2を試す-4 – アンチエイリアス

    #include <ft2build.h>
    #include FT_FREETYPE_H
    
    //FT_Bitmap_Convert
    #include <freetype/ftbitmap.h>
    
    #pragma warning(disable:4996)
    
    #pragma comment(lib,"freetype.lib")
    
    
    //! @brief PGM(1byte,テキスト)を書き込む
    //! @param [in] fname ファイル名
    //! @param [in] width 画像の幅
    //! @param [in] height 画像の高さ
    //! @param [in] p 画像のメモリへのアドレス
    //! @details 1画素1Byteのメモリを渡すと、テキストでファイル名fnameで書き込む
    void pgmP2_Write(const char* const fname, const int width, const int height,const int vmax, const unsigned char* const p) { // PPM ASCII
    
      FILE* fp = fopen(fname, "wb");
      fprintf(fp, "P2\n%d %d\n%d\n", width, height,vmax);
    
      size_t k = 0;
      for (size_t i = 0; i < (size_t)height; i++) {
        for (size_t j = 0; j < (size_t)width; j++) {
          fprintf(fp, "%d ", p[k]);
          k++;
        }
        fprintf(fp, "\n");
      }
    
      fclose(fp);
    }
    int main()
    {
    
      FT_Library  library; // handle to library
      FT_Error error;
    
      error = FT_Init_FreeType(&library);
      if (error)
        return -1;
    
      FT_Face face;      // handle to face object
    
      //msgothic.ttc
      //meiryo.ttc
      // フォントファイル読み込み
      error = FT_New_Face(
        library,
        "C:\\Windows\\Fonts\\msgothic.ttc",
        0,
        &face
      );
    
      //文字コード指定
      error = FT_Select_Charmap(
        face,               // target face object
        FT_ENCODING_UNICODE // エンコード指定
      );
    
    
      if (error == FT_Err_Unknown_File_Format)
        return -1;
      else if (error)
        return -1;
    
      int pixel_heigth = 32;
    
      //この二つの値でフォントサイズ調整
      FT_Set_Pixel_Sizes(
        face,          // handle to face object
        0,             // pixel_width  
        pixel_heigth   // pixel_height
      );
    
      // 文字の取得
      FT_ULong character = wchar_t(L'あ');
      FT_UInt char_index = FT_Get_Char_Index(face, character);
    
    
      // グリフ(字の形状)読込
      error = FT_Load_Glyph(face, char_index, FT_LOAD_RENDER | FT_LOAD_COLOR);
      if (error)
        return -1; // ignore errors
        // 文字を画像化
      FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
    
    
      FT_Bitmap glyphbitmap;
      FT_Bitmap_Convert(library, &face->glyph->bitmap, &glyphbitmap, 1);
    
      int Width = glyphbitmap.width;
      int Height = glyphbitmap.rows;
      pgmP2_Write(// ファイル保存
        "C:\\test\\freetypetest.pbm",
        Width,
        Height,
        255,
        glyphbitmap.buffer
      );
    
      // FreeType2の解放
      FT_Done_Face(face);
      FT_Done_FreeType(library);
    }
    

    FreeType2を試す-3-小さいサイズで描画

    出力用関数

    //! @brief PBM(1byte,テキスト)を書き込む
    //! @param [in] fname ファイル名
    //! @param [in] width 画像の幅
    //! @param [in] height 画像の高さ
    //! @param [in] p 画像のメモリへのアドレス
    //! @details 1画素1Byteのメモリを渡すと、0,1テキストでファイル名fnameで書き込む
    void pbmP1_Write(const char* const fname, const int width, const int height, const unsigned char* const p) { // PPM ASCII
    
      FILE* fp = fopen(fname, "wb");
      fprintf(fp, "P1\n%d\n%d\n", width, height);
    
      size_t k = 0;
      for (size_t i = 0; i < (size_t)height; i++) {
        for (size_t j = 0; j < (size_t)width; j++) {
          fprintf(fp, "%d ", p[k] ? 0 : 1);
          k++;
        }
        fprintf(fp, "\n");
      }
    
      fclose(fp);
    }

    この時、以下のコードで、以下のpixel_heightで出力すると、正常に出力されない。文字サイズが小さすぎると結果が壊れる。

    失敗例

    #include <ft2build.h>
    #include FT_FREETYPE_H
    
    
    #pragma warning(disable:4996)
    
    #pragma comment(lib,"freetype.lib")
    
    
    int main()
    {
    
      FT_Library  library; // handle to library
      FT_Error error;
    
      error = FT_Init_FreeType(&library);
      if (error)
        return -1;
    
      FT_Face face;      // handle to face object
    
      //msgothic.ttc
      //meiryo.ttc
      // フォントファイル読み込み
      error = FT_New_Face(
        library,
        "C:\\Windows\\Fonts\\msgothic.ttc",
        0,
        &face
      );
    
      //文字コード指定
      error = FT_Select_Charmap(
        face,               // target face object
        FT_ENCODING_UNICODE // エンコード指定
      );
    
    
      if (error == FT_Err_Unknown_File_Format)
        return -1;
      else if (error)
        return -1;
    
      int pixel_heigth =16;
      //この二つの値でフォントサイズ調整
      FT_Set_Pixel_Sizes(
        face,          // handle to face object
        0,             // pixel_width  
        pixel_heigth   // pixel_height
      );
    
        // 文字の取得
      FT_ULong character = wchar_t(L'あ');
      FT_UInt char_index = FT_Get_Char_Index(face, character);
    
      // グリフ(字の形状)読込
      error = FT_Load_Glyph(face, char_index, FT_LOAD_RENDER);
      if (error)
        return -1; // ignore errors
    
        // 文字を画像化
      FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
    
    
      FT_Bitmap& glyphbitmap = face->glyph->bitmap;
    
    
    
      int Width = glyphbitmap.width;
      int Height = glyphbitmap.rows;
      pbmP1_Write(// ファイル保存
        "C:\\test\\freetypetest.pbm",
        Width,
        Height,
        glyphbitmap.buffer
      );
    
      // FreeType2の解放
      FT_Done_Face(face);
      FT_Done_FreeType(library);
    }
    

    これは(多分)、フォントサイズが小さいときはビットマップフォントが使われ、pixel_typeが変わってしまっているから。

    FT_Bitmap_Convertで画像データを変換すれば、取り出したフォントの形式にかかわらず、8bppにできる。

      FT_Bitmap glyphbitmap;// 新しい画像データ
      FT_Bitmap_Init(&glyphbitmap);// 新しい画像データの初期化
      FT_Bitmap_Convert(library, &face->glyph->bitmap, &glyphbitmap, 1);// 文字画像を8bppに変換
    
      int Width = glyphbitmap.width;
      int Height = glyphbitmap.rows;
      pgmP2_Write(// ファイル保存
        "C:\\test\\freetypetest.pbm",
        Width,
        Height,
        255,
        glyphbitmap.buffer
      );
    
      FT_Bitmap_Done(library, &glyphbitmap);// 文字画像を解放
    

    成功例

    int main()
    {
    
      FT_Library  library; // handle to library
      FT_Error error;
    
      error = FT_Init_FreeType(&library);
      if (error)
        return -1;
    
      FT_Face face;      // handle to face object
    
      //msgothic.ttc
      //meiryo.ttc
      // フォントファイル読み込み
      error = FT_New_Face(
        library,
        "C:\\Windows\\Fonts\\msgothic.ttc",
        0,
        &face
      );
    
      //文字コード指定
      error = FT_Select_Charmap(
        face,               // target face object
        FT_ENCODING_UNICODE // エンコード指定
      );
    
    
      if (error == FT_Err_Unknown_File_Format)
        return -1;
      else if (error)
        return -1;
    
      int pixel_heigth = 16;
    
      //この二つの値でフォントサイズ調整
      FT_Set_Pixel_Sizes(
        face,          // handle to face object
        0,             // pixel_width  
        pixel_heigth   // pixel_height
      );
    
      // 文字の取得
      FT_ULong character = wchar_t(L'あ');
      FT_UInt char_index = FT_Get_Char_Index(face, character);
    
      // グリフ(字の形状)読込
      error = FT_Load_Glyph(face, char_index, FT_LOAD_RENDER | FT_LOAD_COLOR);
      if (error)
        return -1; // ignore errors
    
        // 文字を画像化
      FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
    
    
    
      FT_Bitmap glyphbitmap;
      FT_Bitmap_Init(&glyphbitmap);
      FT_Bitmap_Convert(library, &face->glyph->bitmap, &glyphbitmap, 1);
    
      int Width = glyphbitmap.width;
      int Height = glyphbitmap.rows;
      pgmP2_Write(// ファイル保存
        "C:\\test\\freetypetest.pbm",
        Width,
        Height,
        255,
        glyphbitmap.buffer
      );
    
      FT_Bitmap_Done(library, &glyphbitmap);
      // FreeType2の解放
      FT_Done_Face(face);
      FT_Done_FreeType(library);
    }
    

    pixel_mode

    フォントサイズによってpixel_modeが違うことがある。以下のコードで確認する。

      switch (face->glyph->bitmap.pixel_mode) {
      case FT_PIXEL_MODE_NONE:
        printf("FT_PIXEL_MODE_NONE");
        break;
      case FT_PIXEL_MODE_MONO:
        printf("FT_PIXEL_MODE_MONO");
        break;
      case FT_PIXEL_MODE_GRAY:
        printf("FT_PIXEL_MODE_GRAY");
        break;
      case FT_PIXEL_MODE_GRAY2:
        printf("FT_PIXEL_MODE_GRAY2");
        break;
      case FT_PIXEL_MODE_GRAY4:
        printf("FT_PIXEL_MODE_GRAY4");
        break;
      case FT_PIXEL_MODE_LCD:
        printf("FT_PIXEL_MODE_LCD");
        break;
      case FT_PIXEL_MODE_LCD_V:
        printf("FT_PIXEL_MODE_LCD_V");
        break;
      case FT_PIXEL_MODE_BGRA:
        printf("FT_PIXEL_MODE_BGRA");
        break;
      }
      getchar();
    
    pixel heightpixel_mode
    16FT_PIXEL_MODE_MONO
    32FT_PIXEL_MODE_GRAY