2012-05-02 3 views
5

이것은 하나의 코드입니다. 적절한 설명을 위해서 제가하고 싶은 일을 설명하겠습니다. 코드 목록을 작성한 다음 코드를 자세히 설명합니다.GLSL 쉐이더 문자열을 파싱하여 Android NDK에서 변수 이름을 찾습니다.

나는 내가 가진 모든 GLSL 쉐이더 파일의 변수의 이름을 얻으려고

목표. 지금은 단 하나의 버텍스 쉐이더와 그것을 보완하는 프래그먼트 쉐이더 만 있습니다. 이것의 목적은 각 변수 이름을 입력 할 필요없이 셰이더에 값을 동적으로 바인딩 할 수 있기 때문입니다.

코드

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; 
    } 

레드 필

촬영 그래서, 아이디어는 가장 일반적으로 사용되는 변수 유형를 포함하는 키 룩업 테이블이있을 것입니다. 우선,받은 Shader는 핸들, 타입 (Fragment, Vertex, Texture 등) 및 소스와 같은 데이터에 대한 정보를 보유하는 클래스입니다. 나는 셰이더 파일에서 문자열을 제외한 모든 것을 구문 분석하고 있습니다.

쉐이더 파일에서 구문 분석되는 각 행을 반복하는 그랜드 아빠 루프가 발생합니다. 각각의 라인에서 키 룩업 테이블에 일치가있는 경우 keyLookupTable[]을 반복하는 두 번째 루프는 iKey 값을 취하는 인덱스 값으로 중단됩니다 (즉, 일치하는 항목이있는 배열의 인덱스) . 그런 다음 루프가 중단됩니다.

일치하는 것이 발견되면 일치 항목이있는 행의 위치 (예 : vec4 또는 mat3)가 사용됩니다. 여기서부터 pos에 저장된 위치를 사용하여 pos을 사용하여 문자 배열에 필요한 문자 양을 지정하여 수행되는 변수 이름 길이의 기초로 사용됩니다. 필요한 양은 행의 길이에서 위치를 뺀 값입니다.

거기에서 세 번째이자 마지막 루프는 char*을 사용하여 행을 반복하고 값을 line으로 가져와 할당 된 var 문자 배열로 복사합니다.

마지막으로 std::vector 키는 var을 삽입하고 반복 과정을 반복합니다. 자신이 자바를 통해 분석 한 다음 C에 JNI ++를 통해 전송되는 셰이더로

주목할만한 우려

  • 내가 쉐이더 문자열을 얻기 위해 JNI를 사용하고 있습니다.나는 이와 같은 출력을 받았는데으로
  • 유니 코드가 우려 될 수 쉐이더 SRC는 env->GetStringUTFChars()

결론 통해 JNI에서 const를 숯불 *에 전달 Shader Variable Found is: |uԯ|uԯ/

  • std::stringstream 또는 뭔가를 사용하여이를 수행하는 더 좋은 방법이있을 것이라고 확신하지만이 알고리즘에 익숙하지 않아서이 알고리즘을 어떻게 든 또는 어딘지로 작동시키고 싶습니다. 그러나 이것이 이것이 "순진한"방법이라면, 나는 제안에 개방적이다.

    [질문

    구문 분석이 작동하도록하려면이 옵션을 달성하기 위해 가장 좋은 방법은 무엇입니까?

  • 답변

    9

    직접해야합니까? GLSL은 이미이 구문 분석을 수행합니다. 모든 입력 변수의 목록을 원하면 glGetActiveAttrib/glGetActiveUniform을 통해 얻을 수 있습니다.

    연결된 셰이더의 활성 속성/유니폼 수를 쿼리 한 다음 입력 변수의 이름을 쿼리하는 각 인덱스를 반복합니다.

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

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

    +1

    미안 해요, 난 여기에 조금 혼란 느낌 : 당신이 활성 attribs/링크 된 쉐이더의 유니폼의 수를 조회 말할 때, 않습니다 당신은 당신이 제시 한 두 가지 기능 중 하나를 사용하여 의미 , 또는 다른 기능을 사용합니까? 당신이 "설명"아래의 첫 번째 단락에서 설명한 것 설명서를 읽어 보면 – zeboidlund

    +1

    는 "glGetActiveAttrib 프로그램에 의해 지정된 프로그램 객체 \t에 적극적으로 속성 변수에 대한 정보 \t를 반환 \t 활성 속성의 수는 호출하는 것으로 취득 할 수 있습니다. \t glGetProgram \t 값이 GL_ACTIVE_ATTRIBUTES입니다. " – Tim

    +1

    좋습니다. 고맙습니다. – zeboidlund

    관련 문제