[edited]
As dletozeun said, my code maybe is too complicated (anyway I let it), so let’s change the question… Is there no problem on using VBO and glsl? Do you know any page with an example? What I’d like to do transform with vertex shaders 3 textures which should be mapped over a mesh.
Thanks!!
[edited]
Hi again!
I’m working with 3 textures, and glsl to create a RBG image from a YUV image. As the the image should be transformed by an extern function, the 3 textures must be mapped over a mesh (this mesh is created using the http://www.java-tips.org/other-api-tips/jogl/vertex-buffer-objects-nehe-tutorial-jogl-port-2.html example, also with vbo). While with just one texture and no GLSL it works, I get the problems trying the new config; the result image is shown all over the frame and If I try to use glTranslatef in order to move more than 10 units it breaks. Am I sending the wrong pixels? Is is a problem between vbo and the textures or from glsl?
Mesh:
public class MeshYUV {
// Mesh Data
private int vertexCount; // Vertex Count
private FloatBuffer vertices; // Vertex Data
private FloatBuffer texCoordsY, texCoordsU; // Texture Coordinates
// Vertex Buffer Object Names
private int[] VBOVertices = new int[1]; // Vertex VBO Name
private int[] VBOTexCoords = new int[2]; // Texture Coordinate VBO Name
private boolean fUseVBO;
public int getVertexCount() {
return vertexCount;
}
public boolean isVBOSupported(GL gl){
// Check For VBO support
return gl.isFunctionAvailable("glGenBuffersARB") &&
gl.isFunctionAvailable("glBindBufferARB") &&
gl.isFunctionAvailable("glBufferDataARB") &&
gl.isFunctionAvailable("glDeleteBuffersARB");
}
public boolean init(GL gl, int texWidth, int texHeight, float flHeightScale, float flResolution) {
fUseVBO = isVBOSupported(gl);
// Generate Vertex Field
vertexCount = (int) (texWidth * texHeight * 6 / (flResolution * flResolution));
vertices = BufferUtil.newFloatBuffer(vertexCount * 3); // Allocate Vertex Data
texCoordsY = BufferUtil.newFloatBuffer(vertexCount * 2); // Allocate Tex Coord Data
texCoordsU = BufferUtil.newFloatBuffer(vertexCount * 2);
for (int nY = 0; nY < texHeight; nY += (int) flResolution) {
for (int nX = 0; nX < texWidth; nX += (int) flResolution) {
for (int nTri = 0; nTri < 6; nTri++) {
// Using This Quick Hack, Figure The X,Y Position Of The Point
float flY = (float) nY + ((nTri == 1 || nTri == 2 || nTri == 5) ? flResolution : 0.0f);
float flX = (float) nX + ((nTri == 2 || nTri == 4 || nTri == 5) ? flResolution : 0.0f);
// Set The Data
vertices.put(flX - (texWidth / 2.0f));
vertices.put(flY - (texHeight / 2.0f));
vertices.put(0.0f); //
// Stretch The Texture Across The Entire Mesh
texCoordsY.put(flX);
texCoordsY.put(flY);
texCoordsU.put(flX / 2.0f);
texCoordsU.put(flY / 2.0f);
}
}
}
vertices.flip();
texCoordsY.flip();
texCoordsU.flip();
if (fUseVBO) {
// Load Vertex Data Into The Graphics Card Memory
buildVBOs(gl); //Build The VBOs
}
return true;
}
public void render(GL gl) {
// Enable Pointers
gl.glEnableClientState(GL.GL_VERTEX_ARRAY); // Enable Vertex Arrays
gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
// Set Pointers To Our Data
if (fUseVBO) {
gl.glActiveTexture(GL.GL_TEXTURE0);
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, VBOTexCoords[0]);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0); // Set The TexCoord Pointer To The TexCoord Buffer
gl.glActiveTexture(GL.GL_TEXTURE1);
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, VBOTexCoords[1]);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0); // Set The Vertex Pointer To The Vertex Buffer
gl.glActiveTexture(GL.GL_TEXTURE2);
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, VBOTexCoords[1]);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0); // Set The Vertex Pointer To The Vertex Buffer
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, VBOVertices[0]);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0); // Set The TexCoord Pointer To The TexCoord Buffer
} else {
gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertices); // Set The Vertex Pointer To Our Vertex Data
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, texCoordsY); // Set The Vertex Pointer To Our TexCoord Data
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, texCoordsU); // Set The Vertex Pointer To Our TexCoord Data
}
// Render
gl.glDrawArrays(GL.GL_TRIANGLES, 0, vertexCount); // Draw All Of The Triangles At Once
// Disable Pointers
gl.glDisableClientState(GL.GL_VERTEX_ARRAY); // Disable Vertex Arrays
gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY); // Disable Texture Coord Arrays
}
private void buildVBOs(GL gl) {
// Generate And Bind The Vertex Buffer
gl.glGenBuffersARB(1, VBOVertices, 0); // Get A Valid Name
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, VBOVertices[0]); // Bind The Buffer
// Load The Data
gl.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB, vertexCount * 3 * BufferUtil.SIZEOF_FLOAT, vertices, GL.GL_STATIC_DRAW_ARB);
// Generate And Bind The TextureY Coordinate Buffer
gl.glGenBuffersARB(2, VBOTexCoords, 0); // Get A Valid Name
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, VBOTexCoords[0]); // Bind The Buffer
// Load The Data
gl.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB, vertexCount * 2 * BufferUtil.SIZEOF_FLOAT, texCoordsY, GL.GL_STATIC_DRAW_ARB);
// Generate And Bind The TextureUV Coordinate Buffer
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, VBOTexCoords[1]); // Bind The Buffer
// Load The Data
gl.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB, vertexCount * 2 * BufferUtil.SIZEOF_FLOAT, texCoordsU, GL.GL_STATIC_DRAW_ARB);
// Generate And Bind The TextureUV Coordinate Buffer
// Our Copy Of The Data Is No Longer Necessary, It Is Safe In The Graphics Card
vertices = null;
texCoordsY = null;
texCoordsU = null;
fUseVBO = true;
}
}
Renderer:
// Mesh Generation Paramaters
private static final float MESH_RESOLUTION = 4.0f; // Pixels Per Vertex
private static final float MESH_HEIGHTSCALE = 1.0f; // Mesh Height Scale
private int programObject = 0;
private boolean textureChanged = false;
private GlShaders glFragment = null;
private GlShaders glVertex = null;
private int[] textures = new int[3];
private UnicapFrame text = null;
private int yTexture,uTexture,vTexture;
private MeshYUV mesh = null;
private GLErrorChecker glErrorCheker = new GLErrorChecker();
public TestYUVMeshRenderer(int width, int height) {
super(width, height);
}
@Override
public void init(GLAutoDrawable gLDrawable) {
final GL gl = gLDrawable.getGL();
mesh = new MeshYUV(); // Instantiate Our Mesh
mesh.init(gl,this.texWidth,this.texHeight ,
MESH_HEIGHTSCALE,
MESH_RESOLUTION
);
glVertex = new GlShaders(gl,"yuvToRgb.vert",true);
glFragment = new GlShaders(gl, "yuvToRgb.frag", false);
GlShaders.checkShaderExtensions(gl);
programObject = gl.glCreateProgramObjectARB();
programObject = glFragment.load(programObject);
programObject = glVertex.load(programObject);
gl.glLinkProgramARB(programObject);
gl.glValidateProgramARB(programObject);
// Setup GL States
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
gl.glClearDepth(1.0f);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glShadeModel(GL.GL_SMOOTH);
gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
gl.glGenTextures(3, textures, 0);
yTexture = textures[0];
uTexture = textures[1];
vTexture = textures[2];
}
@Override
public void display(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glUseProgramObjectARB(programObject);
if (textureChanged) {
int offset = 0;
offset += updateTexture(gl, yTexture, GL.GL_TEXTURE0, "yTex", offset, text.getWidth(), text.getHeight());
offset += updateTexture(gl, uTexture, GL.GL_TEXTURE1, "uTex", offset, text.getWidth() / 2, text.getHeight() / 2);
offset += updateTexture(gl, vTexture, GL.GL_TEXTURE2, "vTex", offset, text.getWidth() / 2, text.getHeight() / 2);
textureChanged = false;
}
glErrorCheker.checkErrors(gl, "After creating textures");
gl.glTranslatef(0.0f, 0.0f, -1000.0f);
mesh.render(gl);
gl.glUseProgramObjectARB(0);
glErrorCheker.checkErrors(gl, "after all ");
}
private int updateTexture(GL gl, int texture, int glTextureUnit, String variableName, int byteOffset, int width, int height) {
int i;
gl.glActiveTexture(glTextureUnit);
i = gl.glGetUniformLocationARB(programObject, variableName);
gl.glBindTexture (GL.GL_TEXTURE_RECTANGLE_ARB, texture);
gl.glUniform1iARB(i, texture);
text.getPixels().position(byteOffset);
updateTextureData (gl, BufferUtil.copyByteBuffer(text.getPixels()), width, height);
return width * height;
}
private void updateTextureData(GL gl, ByteBuffer pixels, int width, int height) {
glErrorCheker.checkErrors(gl, "displayGlElement");
gl.glTexImage2D (GL.GL_TEXTURE_RECTANGLE_ARB,
0,
1,
width , height,
0,
GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE,
pixels
);
gl.glTexParameteri (GL.GL_TEXTURE_RECTANGLE_ARB, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri (GL.GL_TEXTURE_RECTANGLE_ARB, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
glErrorCheker.checkErrors(gl, "gl.glTexParameteri");
}
As you see, the textures are re-bind each display-time, because the images came from a video camera.
All advice are welcome and thanks to everyone.