保持应该表示相同功能的同步 glsl 代码和 C++ 代码

Keeping synced glsl code and c++ code that ought to represent the same function

我有以下挑战。我正在做一系列图形实验,我需要编写 sdf 函数。为了不同的目的,这些函数必须同时存在于 glsl 和 c++ 中。换句话说,在 glsl 和 c++ 中,必须有一个函数 SdfFunction 计算完全相同的 SDF。

当前可能的方法:

我有其他选择吗?

我使用的方法有点不同。我为 CPU 侧 C++ 代码创建了 GLSL_math.h 模板,其语法和功能与 GLSL 相同(包括调配),因此我可以 运行 GLSL 上的相同数学代码和 CPU调试目的。该模板还包含原生 GLSL 中不存在的局部和全局旋转(因为我打算用它来替代我的旧 reper 和矢量数学 类 并且需要该功能)

该模板是在 Embarcadero (Borland) BDS2006 Turbo C++ 中完成的,因此可能需要在不同的 C++ IDE / 编译器中进行一些调整。大多数代码是使用函数 _vec_generate 自动生成的,该函数包含在内但被注释掉,因为它使用 AnsiString,它在 VCL 之外不存在,因为手动编码会很疯狂(~244KByte)。

CPU/GLSL 之间的纹理访问和内容差异我通过宏语句处理,如下所示:

只有 GLSL 和 CPU 的宏不同...

这样我就可以使用我的 C++ IDE 调试功能,例如断点、跟踪、监视...没有这些功能,我将永远无法完成更复杂的着色器,例如通过网格或体素贴图的光线跟踪器...

对于行为不同的情况(不同的 FPU 实现或与驱动程序相关的 GLSL 怪癖和错误)我使用这个:

直接从片段着色器打印出sub-results

这里是一个示例测试代码,用于测试模板运算符语法的功能(不同的编译器可能需要稍微更改运算符 header 语法,直到它编译):

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
template <class mat,class vec,class T> void test_operators_syntax()
    {
    mat m0,m1,m2;
    vec v0,v1,v2;
    T   c1=1;

    m0=+m1;
    m0=-m1;
    m0=m1*m2;
    m0=c1*m1;
    m0=m1*c1;
    m0=m1/c1;

    m0*=m1;
    m0*=c1;
    m0/=c1;

    v0=m1*v1;
    v0=m1*v1;
    v0=m1*v1;

    v0=+v1;
    v0=-v1;
    v0=v1++;
    v0=++v1;
    v0=v1--;
    v0=--v1;

    v0=v1+v2;
    v0=v1-v2;
    v0=v1*v2;
    v0=v1/v2;

    v0+=v1;
    v0-=v1;
    v0*=v1;
    v0/=v1;
    v0++=v1;
    v0--=v1;

    v0=c1+v1;
    v0=c1-v1;
    v0=c1*v1;

    v0=v1+c1;
    v0=v1-c1;
    v0=v1*c1;
    v0=v1/c1;

    v0+=c1;
    v0-=c1;
    v0*=c1;
    v0/=c1;
    };
//---------------------------------------------------------------------------
void test_operators()
    {
    test_operators_syntax< mat2, vec2,float >();  vec2  v2= vec2(0.0,0.0);           mat2  m2= mat2(0.0,0.0,0.0,0.0);
    test_operators_syntax< mat3, vec3,float >();  vec3  v3= vec3(0.0,0.0,0.0);       mat3  m3= mat3(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0);
    test_operators_syntax< mat4, vec4,float >();  vec4  v4= vec4(0.0,0.0,0.0,0.0);   mat4  m4= mat4(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0);
    test_operators_syntax<dmat2,dvec2,double>(); dvec2 dv2=dvec2(0.0,0.0);          dmat2 dm2=dmat2(0.0,0.0,0.0,0.0);
    test_operators_syntax<dmat3,dvec3,double>(); dvec3 dv3=dvec3(0.0,0.0,0.0);      dmat3 dm3=dmat3(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0);
    test_operators_syntax<dmat4,dvec4,double>(); dvec4 dv4=dvec4(0.0,0.0,0.0,0.0);  dmat4 dm4=dmat4(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0);

    m3=rotate(m3,15.0*deg,v2);
    m4=rotate(m4,15.0*deg,v3,v3);
    m3=grotz(m3,15.0*deg); m3=lrotz(m3,15.0*deg);
    m4=grotx(m4,15.0*deg); m4=lrotx(m4,15.0*deg);
    m4=groty(m4,15.0*deg); m4=lroty(m4,15.0*deg);
    m4=grotz(m4,15.0*deg); m4=lrotz(m4,15.0*deg);
    m2=inverse(m2); m2=inverse2(m2); m2=transpose(m2);
    m3=inverse(m3); m3=inverse2(m3); m3=transpose(m3);
    m4=inverse(m4); m4=inverse2(m4); m4=transpose(m4);
    float  f=1.0; f=max(0.0f,f); f=min(0.0f,f); f=abs(f);
    double d=2.0; d=max(0.0 ,d); d=min(0.0 ,d); d=abs(d);
    f=length(v2)+length2(v2)+dot(normalize(v2),cross(v2));
    f=length(v3)+length2(v3)+dot(normalize(v3),cross(v3,v3));
    f=length(v4)+length2(v4)+dot(normalize(v4),cross(v4,v4,v4));
    }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------