2012-05-02 19 views
5

değişken adlarını bulmak için bir GLSL shader dizesini ayrıştırma Bu bir doozy. Doğru açıklama uğruna ne yapmaya çalıştığımı açıklamama izin verin. Bir kod listesi ile takip edeceğim ve sonra kodu açık bir şekilde açıklayacağım.Android NDK

Ben var her GLSL shader dosyasındaki değişkenlerin isimlerini almaya çalışıyorum

Hedef. Şu anda, sadece tek bir köşe gölgelendiricisi ve onu tamamlamak için bir parça gölgelendiricim var. Bunun amacı, her bir değişken adını girmek zorunda kalmadan, değerlerini gölgeleyicilere dinamik olarak bağlayabilmem.

Kod

std::vector< const char* > GetShaderVariableNames(const Shader& shader) 
    { 
     Config::Log::info("Getting shader variable names."); 

     static const char* keyLookupTable[] = 
     { 
      "vec2", "vec3", "vec4", 
      "mat2", "mat3", "mat4", 
      "float", "int", "double" 
     }; 

     std::vector< const char* > keys; 
     std::vector<std::string> lines; 

     SplitIntoLines(&lines, std::string(shader.shaderSrc)); 

     for(int32_t iLines = 0; iLines < lines.size(); ++iLines) 
     { 
      const char* line = lines[ iLines ].c_str(); 

      int32_t index = 0; 
      bool foundMatch = false; 

      for(int32_t iKey = 0; iKey < sizeof(keyLookupTable)/sizeof(char); ++iKey) 
      { 
       if(strContains(lines[ iLines ], keyLookupTable[ iKey ])) 
       { 
        index = iKey; 
        foundMatch = true; 
        break; 
       } 
      } 

      if(foundMatch) 
      { 
       const int32_t pos = lines[ iLines ].find(keyLookupTable[ index ]); 

       Config::Log::info("Position found is %i", pos); 

       const int32_t lineLen = strlen(line); 

       char* var = new char[ lineLen - pos ]; 

       int32_t iLine = pos + strlen(keyLookupTable[ index ]); 

       for(; iLine < lineLen; ++iLine) 
       { 
        var[ iLine ] = line[ iLine ]; 
       } 

       Config::Log::info("Shader Variable Found is: %s", var); 

       keys.push_back(var); 
      } 
     } 

     return keys; 
    } 

Kırmızı Pill

alarak Yani, fikir, en sık kullanılan değişken türleri içeren bir anahtar aramak tablo var olmasıdır. İlk olarak, Gölgelendirici, tanıtıcısı, türü (Fragment, Vertex, Texture, vb.) Ve tabii ki kaynağı gibi veriler hakkında bilgi tutan bir sınıftır. Bunları shader dosyalarından değil, dizelerden ayırıyorum.

Olan şey, gölgelendirici dosyasında ayrıştırılan her satırın üzerinde yinelenen bir büyük baba döngüdür. Her bir satırda, anahtar arama tablosunda bir eşleşme varsa, keyLookupTable[] üzerinde yinelenen ikinci döngü iKey değerini alan bir dizin değeriyle (yani dizinin, eşleşmenin bulunduğu dizindeki) kesilir. . Döngü daha sonra kırılır.

Bir eşleşme bulunursa, eşleşmenin bulunduğu satırdaki konum (ör. vec4 veya mat3) alındı. Oradan, pos'da saklanan konumu kullanarak, bir char dizisindeki gerekli karakter miktarını belirterek yapılan değişken adının uzunluğuna temel olarak hareket etmek için pos kullanırız. Gerekli miktar, satırın uzunluğu, pozisyonun uzunluğudır.

kaynaktan orada üçüncü ve son çevrim daha sonra hat üzerinden dolaşır, line değerleri almak ve ayrılan var karakter dizisine kopyalayarak, referans olarak kullanmak için bir char* kullanılmıştır.

Son olarak, std::vector anahtarları var ekler ve işlemi tekrarlayarak döngüde devam eder. kendilerini Java yoluyla çözümlenir ve sonra C JNI ++ aracılığıyla gönderilir shader olarak

Önemli Kaygılar

  • Ben gölgelendirici dizeleri almak için JNI kullanıyorum.Ben bu gibi çıkışlarını alıyorum olarak
  • Unicode, bir endişe olabilir: gölgelendirici src env->GetStringUTFChars()

Sonuç aracılığıyla JNI bir const char * geçirilir Shader Variable Found is: |uԯ|uԯ/

  • Eminim bunu yapmak için daha iyi bir yol var, belki std::stringstream veya bir şey kullanarak, ama ben çok aşina değilim ve bu algoritma bir şekilde veya bir şekilde çalışmasını isterim. Ancak, eğer bunu yapmak için "naif" yol buysa, öneriye açığım.

    Soru

    ayrıştırma işe almak için bu ulaşmanın en iyi yolu nedir?

  • cevap

    9

    Bunu kendiniz yapmanız gerektiğinden emin misiniz? GLSL zaten sizin için ayrıştırma işlemini yapıyor ve tüm giriş değişkenlerinin bir listesini istiyorsanız bunları glGetActiveAttrib/glGetActiveUniform aracılığıyla edinebilirsiniz.

    Yalnızca bağlantılı bir gölgelendiricinin etkin yakalama/üniformalarının sayısını sorgulayın ve sonra giriş değişkeninin adı için her bir dizin sorgulaması üzerinde yineleyin.

    http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttrib.xml

    http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml

    +1

    Üzgünüm, burada küçük bir kararsızlık yaşar: Etkin ATTRIBS/bağlantılı bir shader üniforma sayısını sorgulamak derken, yok sen önerilen iki işlevlerinden birini kullanarak anlamına veya farklı bir işlev mi kullanıyorsunuz? Eğer "Açıklaması" altında birinci paragrafta anlatılmış belgeleri okursanız – zeboidlund

    +1

    : "glGetActiveAttrib program tarafından belirlenen bir program nesne \t aktif nitelik değişkeni hakkında bilgi \t döndürür \t aktif niteliklerin sayısı arayarak elde edilebilir. GL_ACTIVE_ATTRIBUTES değeriyle \t glGetProgram \t. " – Tim

    +1

    Tamam, harika. Teşekkür ederim. – zeboidlund