【问题标题】:extract glsl function body with regexp用正则表达式提取 glsl 函数体
【发布时间】:2021-03-29 17:15:53
【问题描述】:

我无法使用 javascript 在 glsl 脚本中提取函数。

这里是 glsl 内容:

 precision highp float;                           
  varying vec4 v_color;                                 
  #if USE_TEXTURE                                       
      varying vec2 v_uv0;                               
      uniform sampler2D texture;                        
  #endif                                                
vec2 sfx_func_uv_to_01(vec4 ucrect, vec2 uv) {
    return vec2(
        sfx_func_uv_to_01(ucrect[0], ucrect[0] + ucrect[2], uv.x),
        1.0 - sfx_func_uv_to_01(ucrect[1], ucrect[1] - ucrect[3], uv.y)
    );
}
vec2 sfx_func_uv_to_01(vec4 ucrect, vec2 uv) {
    return vec2(1.0, 2.0);
}
vec4 sfx_fs_output_uv_quarter(vec2 uv, vec4 color) {
    vec4 result = color;
    return result;
}
 void main () {                                    
    vec2 uv = v_uv0;                                  
    vec4 color = texture2D(texture, uv);              
    gl_FragColor = color;
}                                             

我想用正文提取脚本中的 4 个函数。所以我尝试了注册:

/^(vec4|vec3|vec2|float|int).*\{.*\}/gms

而js代码是:

for (const match of glsl1.matchAll(/^(vec4|vec3|vec2|float|int).*\{.*\}/gms)) {
    console.log(match[0]);
}

我只得到一个结果,而不是 4 个函数:

vec2 sfx_func_uv_to_01(vec4 ucrect, vec2 uv) {
    return vec2(
        sfx_func_uv_to_01(ucrect[0], ucrect[0] + ucrect[2], uv.x),
        1.0 - sfx_func_uv_to_01(ucrect[1], ucrect[1] - ucrect[3], uv.y)
    );
}
vec2 sfx_func_uv_to_01(vec4 ucrect, vec2 uv) {
    return vec2(1.0, 2.0);
}
vec4 sfx_fs_output_uv_quarter(vec2 uv, vec4 color) {
    vec4 result = color;
    return result;
}
 void main () {                                    
    vec2 uv = v_uv0;                                  
    vec4 color = texture2D(texture, uv);              
    gl_FragColor = color;
}    

我为多行文本搜索了非贪婪模式的解决方案,但徒劳无功。

任何建议将不胜感激,谢谢:)

【问题讨论】:

  • 对于您当前的情况,稍作修改就足够了 - ^(vec4|vec3|vec2|float|int).*?{.*?}。参考-regex101.com/r/Bukyh0/1。但它不处理函数中有{} 的情况。然后模式会变得有点复杂

标签: javascript regex


【解决方案1】:

使用

/^(\s*)(vec4|vec3|vec2|float|int|void).*?{[\s\S]*?^\1}\s*$/gm

proof

说明

--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    \s*                      whitespace (\n, \r, \t, \f, and " ") (0
                             or more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  (                        group and capture to \2:
--------------------------------------------------------------------------------
    vec4                     'vec4'
--------------------------------------------------------------------------------
   |                        OR
--------------------------------------------------------------------------------
    vec3                     'vec3'
--------------------------------------------------------------------------------
   |                        OR
--------------------------------------------------------------------------------
    vec2                     'vec2'
--------------------------------------------------------------------------------
   |                        OR
--------------------------------------------------------------------------------
    float                    'float'
--------------------------------------------------------------------------------
   |                        OR
--------------------------------------------------------------------------------
    int                      'int'
--------------------------------------------------------------------------------
   |                        OR
--------------------------------------------------------------------------------
    void                     'void'
--------------------------------------------------------------------------------
  )                        end of \2
--------------------------------------------------------------------------------
  .*?                      any character except \n (0 or more times
                           (matching the least amount possible))
--------------------------------------------------------------------------------
  {                        '{'
--------------------------------------------------------------------------------
  [\s\S]*?                 any character of: whitespace (\n, \r, \t,
                           \f, and " "), non-whitespace (all but \n,
                           \r, \t, \f, and " ") (0 or more times
                           (matching the least amount possible))
--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  \1                       what was matched by capture \1
--------------------------------------------------------------------------------
  }                        '}'
--------------------------------------------------------------------------------
  \s*                      whitespace (\n, \r, \t, \f, and " ") (0 or
                           more times (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

【讨论】:

  • 抱歉我的回复晚了。我尝试了正则表达式,它几乎是正确的。但是当函数内部有} 时,函数体将在第一个} 字符处中断。
  • 你可以看到这个示例:regex101.com/r/wrZf7s/1 我试图解决这个问题,但没有成功。你能帮我看看吗,谢谢。
  • @supersuraccoon 已更新。
【解决方案2】:

我不敢尝试使用正则表达式来跟踪花括号的无限嵌套,而是尝试使用 g 开关沿着函数头使用 split()(因此保留分隔符),然后连接头 -身体对。该代码假定在第一个函数定义之前有一些序言,这对于大多数 GLSL 源来说可能是正确的,并且不希望函数之间有任何东西(尽管 code=code.substr(0,code.lastIndexOf("}")+1); 可能会解决这种情况)。

const source=`precision highp float;                           
  varying vec4 v_color;                                 
  #if USE_TEXTURE                                       
      varying vec2 v_uv0;                               
      uniform sampler2D texture;                        
  #endif                                                
vec2 sfx_func_uv_to_01(vec4 ucrect, vec2 uv) {
    return vec2(
        sfx_func_uv_to_01(ucrect[0], ucrect[0] + ucrect[2], uv.x),
        1.0 - sfx_func_uv_to_01(ucrect[1], ucrect[1] - ucrect[3], uv.y)
    );
}
vec2 sfx_func_uv_to_01(vec4 ucrect, vec2 uv) {
    return vec2(1.0, 2.0);
}
vec4 sfx_fs_output_uv_quarter(vec2 uv, vec4 color) {
    vec4 result = color;
    return result;
}
int trap(){if(true){whatever}}
 void main () {                                    
    vec2 uv = v_uv0;                                  
    vec4 color = texture2D(texture, uv);              
    gl_FragColor = color;
}               `;

const blocks=source.split(/((?:vec4|vec3|vec2|float|int|void)\s+[\w]+\s*\(.*?\))/gs);
console.log("Header");
console.log(blocks.shift());
for(let i=1;blocks.length;i++){
  console.log("Function #"+i);
  console.log(blocks.shift()+blocks.shift());
}

添加了int trap(){if(true){whatever}} fake 函数以表明这种方法不必担心嵌套的花括号。

【讨论】:

    猜你喜欢
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    相关资源
    最近更新 更多