【问题标题】:Create OpenGL textures using Eigen使用 Eigen 创建 OpenGL 纹理
【发布时间】:2015-11-03 05:14:16
【问题描述】:

在 Eigen 中可以非常轻松(且安全)地创建单通道 R32F 纹理:

    glGenTextures(1, &_tex);
    glBindTexture(GL_TEXTURE_2D, _tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    int rows = 480, cols = 640;
    static Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> A(rows,cols);
    A.setConstant(rows, cols, 0.0f);
    for(int row=0; row<A.rows(); row++)
        for(int col=0; col<A.cols(); col++)
            A(row,col) = .5f + .5*sin( 10* /*period*/ 2*3.14*row/A.rows() );
    glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cols, rows, 0, GL_RED, GL_FLOAT, A.data());

上面的代码生成这个图片:

可以使用类似的方法来生成 RGB32F 纹理:

    glGenTextures(1, &_tex);
    glBindTexture(GL_TEXTURE_2D, _tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    int rows = 480;
    int cols = 640;
    static Eigen::Matrix<Eigen::Vector3f, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> A(rows,cols);
    for(int row=0; row<A.rows(); row++)
        for(int col=0; col<A.cols(); col++)
            A(row,col) = vec3(row/((float)A.rows()), col/((float)A.cols()), 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, cols, rows, 0, GL_RGB, GL_FLOAT, A.data());

上面的代码生成这个图片::

在我的机器上似乎一切正常,但是,此过程会导致任何问题吗?尤其是考虑到 Eigen 文档中提到的内容: http://eigen.tuxfamily.org/dox/TopicCustomizingEigen.html#user_defined_scalars

【问题讨论】:

    标签: textures eigen opengl-3


    【解决方案1】:

    正如 Avi 所说,这样的用例非常好。

    为了好玩,这里有无循环版本:

    Array<float,Dynamic,Dynamic,RowMajor> A;
    A.colwise() = 0.5f + 0.5*sin(ArrayXf::LinSpaced(rows,0,10*2*3.14));
    

    和:

    Array<Array3f,Dynamic,Dynamic,RowMajor> A(rows,cols);
    A.block(0,0,rows,cols) = A.NullaryExpr(rows, cols, [&] (long i, long j) { return Array3f(float(i)/float(rows), float(j)/float(cols), 0); });
    

    第二个也可以通过一些设置来获得每个频道的视图:

    typedef Array<float,Dynamic,Dynamic,RowMajor> RowArrayXXf;
    typedef Map<RowArrayXXf,0,Stride<Dynamic,3> > Channel;
    Channel A_red(  A.data()->data()+0, rows, cols, Stride<Dynamic,3>(3*cols,3));
    Channel A_green(A.data()->data()+1, rows, cols, Stride<Dynamic,3>(3*cols,3));
    Channel A_blue( A.data()->data()+2, rows, cols, Stride<Dynamic,3>(3*cols,3));
    

    然后,您就可以使用 Eigen 的 API 的所有功能来处理各个通道:

    A_red.colwise() = ArrayXf::LinSpaced(rows,0,1);
    A_green.rowwise() = ArrayXf::LinSpaced(cols,0,1).transpose();
    A_blue.setZero();
    

    在您的情况下,这有点矫枉过正,但可能有助于执行更复杂的操作,或者为图像编写一个围绕 Array&lt;Array3f&gt; 的小包装器。

    【讨论】:

    • 我看到您使用“数组”而不是矩阵。为什么会这样?
    • 因为Array 更适合存储我们想要在其上进行系数处理的数字集合。例如,sin(Array&lt;&gt;) 应用正弦系数,而sin(Matrix&lt;&gt;) 表示矩阵运算符正弦。
    【解决方案2】:

    一切正常且合法。但是,可能(有时)会出现一些问题。在您的情况下,您对 A(i,j) 所做的一切都是分配。尝试使用算术运算时,有时会出现一些问题(例如subtracting a Vector3d from the entire matrix)。根据您的使用情况,您可能不会遇到任何此类问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-31
      • 2014-03-12
      • 2016-03-06
      • 1970-01-01
      • 2011-08-13
      • 2020-11-27
      • 2016-11-02
      • 1970-01-01
      相关资源
      最近更新 更多