I’m trying to project a texture onto a regular grid (terrain). It kinda works, but I need to generate a mesh at runtime on the CPU, which is slow. My algorithm is as follows:
- find out which part of the grid the texture projects onto (project the 4 texture vertices onto the grid, get the closest vertices on the grid),
- create a triangle mesh covering the approximate area the texture projects onto,
- project the vertices of this generated mesh onto the texture to obtain texture coordinates,
- render the mesh
This has to be done every frame. Can I speed up these steps somehow using math trickery or maybe doing them on the GPU?
Hrmmm, I’ll try to do part of the job in the vertex shader.
Use the tessellation shaders introduced with Opengl 4.0 .
not sure whether I understood your question right but in OpenGL projective texture mapping can be automated for example by using the texture transformation matrix or by specifying projector frustum layers.
Maybe this helps:
A minimal approach would be:
- Define a “projector” which is a virtual camera by specifying a projection matrix and a modelview matrix. These matrices are not put on the openGL stack but defined by using custom matrix classes or so. It is for example combined of: translate(0.5, 0.5, 0.5) * scale(0.5) * perspective(fovy, aspect, znear, zfar) * lookat(projector_position, projector_target, projector_up)
The scale and translation is for converting the normalized coordinates (-1 to +1) to 0 - 1 for texture coordinates. The perspective matrix is a normal 4x4 perspective projection matrix and the lookat matrix is - as the name says - a look-at-matrix just the way openGL would create. You can either build the last two matrices by constructing them or by pushing the openGL stack, using gluLookAt and gluPerspective, reading the matrix into memory and popping the stack. The projector_position and projector_target vectors could be placed in world space relative to your terrain.
- give the matrix to openGL and enable projective texture mapping by doing:
glTexGenfv(GL_S, GL_OBJECT_PLANE, Matrix.row(0));
glTexGenfv(GL_T, GL_OBJECT_PLANE, Matrix.row(1));
glTexGenfv(GL_R, GL_OBJECT_PLANE, Matrix.row(2));
glTexGenfv(GL_Q, GL_OBJECT_PLANE, Matrix.row(3));
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
glTexGeni( GL_R, GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
where Matrix is the matrix product of the above mentioned matrices. Do not forget to enable texture mapping before.
3. Render your terrain as usual without explicitly specifying texture coordinates. They are now calculated automatically from the vertex positions.
4. Turn off projective mapping.
Hope that helps