Reputation: 899
A single channel R32F texture can be created quite easily (and safely) in Eigen:
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());
The code above generates this image:
A similar approach can be used to generate RGB32F textures:
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());
The code above generates this image: :
Everything seems to work well on my machine, however, can this procedure result in any problem? especially considering what is mentioned in the Eigen documentation: http://eigen.tuxfamily.org/dox/TopicCustomizingEigen.html#user_defined_scalars
Upvotes: 1
Views: 238
Reputation: 29225
As Avi said, such use case is perfectly fine.
For the fun, here are loop-less versions:
Array<float,Dynamic,Dynamic,RowMajor> A;
A.colwise() = 0.5f + 0.5*sin(ArrayXf::LinSpaced(rows,0,10*2*3.14));
and:
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); });
The second one can also be achieved through some setup to get a view for each channel:
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));
and then, you get all the power of Eigen's API to work on individual channels:
A_red.colwise() = ArrayXf::LinSpaced(rows,0,1);
A_green.rowwise() = ArrayXf::LinSpaced(cols,0,1).transpose();
A_blue.setZero();
In your case that's overkill, but might be useful to perform more complicated operation, or to write a small wrapper around Array<Array3f>
for images.
Upvotes: 4
Reputation: 10596
It is all fine and legal. However, there may (sometimes) be some issues. In your case, all you did with A(i,j)
was assign. When attempting to use arithmetic operations, some issues sometimes arise (e.g. subtracting a Vector3d
from the entire matrix). You may not run into any such issues, depending on your use.
Upvotes: 2