I know, it's quite frustrating. I can't get anything to show up in my OpenGL application - all I see is an empty viewport.
When I first started writing the application, I was manually drawing the vertices (using GL_QUADS) and everything worked fine. Then I decided to switch to VBOs (Vertex Buffer Objects). Now nothing works.
Here is the structure for vertices:
struct SimpleVertex
{
GLfloat x, y;
GLbyte r, g, b, a;
};
As you can see, it is very simple - x and y coords for the vertices and RGBA color data. Here is the code that fills the vertex and index buffer:
const SimpleVertex rect_vertices[] = {
{ -0.8, 0.8, 0, 255, 0, 128 },
{ 0.8, 0.8, 0, 255, 0, 128 },
{ 0.8, -0.8, 0, 255, 0, 128 },
{ -0.8, -0.8, 0, 255, 0, 128 }
};
const GLuint rect_indices[] = {
0, 1, 2, 3
};
GLuint vertices;
GLuint indices;
glGenBuffers(1, &vertices);
glBindBuffer(GL_ARRAY_BUFFER, vertices);
glBufferData(GL_ARRAY_BUFFER,
sizeof(rect_vertices),
rect_vertices,
GL_STATIC_DRAW);
glGenBuffers(1, &indices);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof(rect_indices),
rect_indices,
GL_STATIC_DRAW);
And last but certainly not least, here is the code that is supposed to draw the rectangle:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindBuffer(GL_ARRAY_BUFFER, vertices);
glVertexPointer(2, GL_FLOAT, 0, NULL);
glColorPointer(4, GL_BYTE, 0,
(const GLvoid *)(sizeof(GLfloat) * 2));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, NULL);
glDisable(GL_BLEND);
I can't figure out why nothing is being rendered. The vertex and color data is essentially unchanged from the previous version that used glVertex2f().
Simply calling the gl*Pointer functions is not enough; you need to tell OpenGL that it should pull from those particular arrays. For the built-in arrays (glVertexPointer, glColorPointer, etc), you use glEnableClientState(), for the particular array in question.
For example:
glBindBuffer(GL_ARRAY_BUFFER, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, NULL);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_BYTE, 0, (const GLvoid *)(sizeof(GLfloat) * 2));
That should provide better results.
You should also use glDisableClientState() on those arrays after you are finished rendering with them.
You seem to be missing a few steps:
VAO binding
enabling client state (VBO), e.g. glEnableClientState(GL_VERTEX_ARRAY)
Related
I want to draw multiple vertex arrays. This is the initialization:
unsigned int va1;
unsigned int vb1;
void init_va1() {
glGenVertexArrays(1, &va1);
glBindVertexArray(va1);
glGenBuffers(1, &vb1);
glBindBuffer(GL_ARRAY_BUFFER, vb1);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vec2), nullptr, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(vec2), nullptr);
glEnableVertexAttribArray(0);
}
unsigned int va2;
unsigned int vb2;
void init_va2() {
glGenVertexArrays(1, &va2);
glBindVertexArray(va2);
glGenBuffers(1, &vb2);
glBindBuffer(GL_ARRAY_BUFFER, vb2);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vec2), nullptr, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(vec2), nullptr);
glEnableVertexAttribArray(0);
}
At initialization:
init_va1();
init_va2();
At draw:
glBindVertexArray(va1);
vec2 a1[] = {
vec2(0.0, 0.0),
vec2(0.1, 0.0),
vec2(0.1, 0.1),
vec2(0.0, 0.1),
};
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a1), a1);
glUniform3f(polygon_color_loc, 0, 1, 0);
glDrawArrays(GL_LINE_LOOP, 0, 4);
glBindVertexArray(va2);
vec2 a2[] = {
vec2(0.0, 0.0),
vec2(-0.1, 0.0),
vec2(-0.1, -0.1),
vec2(0.0, -0.1),
};
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a2), a2);
glUniform3f(polygon_color_loc, 1, 0, 0);
glDrawArrays(GL_LINE_LOOP, 0, 4);
Whichever vertex array I initialize last will be drawn properly, and the other one will not be drawn. For example, if I call init_va1() and then init_va2(), the drawing using va2 will be shown, and the drawing using va1 will not. If I reorder the calls, then the drawing using va1 will be shown, and the drawing using va2 will not. How do I draw both vertex arrays?
glBufferSubData changes the data of the buffer that is currently bound to the specified target. The current ARRAY_BUFFER is a globale state. you need to bind the proper buffer object when you want to update the data store of the buffer:
glBindBuffer(GL_ARRAY_BUFFER, vb1);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a1), a1);
glBindVertexArray(va1);
glDrawArrays(GL_LINE_LOOP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, vb2);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a2), a2);
glBindVertexArray(va2);
glDrawArrays(GL_LINE_LOOP, 0, 4);
In contrast to the ARRAY_BUFFER, the Index buffers (ELEMENT_ARRAY_BUFFER) is stated in the Vertex Array Object. If you want to change the contents of an index buffer, it is also possible just to bind the the VAO in which the index buffer is stated.
I've been getting back into OpenGL recently after transitioning to linux. For some reason or another, things like glGenBuffers, glBindBuffer, etc, aren't present with the normal GL headers, and cause my program to crash using GLEW. To get around this I've been using GLES2.
And now the problem:
#include <SFML/Graphics.hpp>
#include <GLES2/gl2.h>
#include <GL/gl.h>
int main() {
sf::RenderWindow window(sf::VideoMode(640, 480), "OpenGL Tests");
glOrtho(0, 640, 0, 480, -1, 1);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glClearColor(0, 0, 0, 0);
//x, y, r, g, b
GLfloat triangleVertices[15] = {
10, 10, 1, 0, 0,
110, 10, 0, 1, 0,
60, 96.6f, 0, 0, 1
};
GLuint triangleBuf;
glGenBuffers(1, &triangleBuf);
glBindBuffer(GL_VERTEX_ARRAY, triangleBuf);
glBufferData(GL_VERTEX_ARRAY, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
glBindBuffer(GL_VERTEX_ARRAY, 0);
while(window.isOpen()) {
sf::Event event;
while(window.pollEvent(event)) {
if(event.type == sf::Event::Closed) window.close();
}
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_VERTEX_ARRAY, triangleBuf);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 3, 0);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 2, (GLfloat*) 2);
glDrawArrays(GL_TRIANGLES, 0, 3);
window.display();
sf::sleep(sf::milliseconds(50));
}
glDeleteBuffers(1, &triangleBuf);
}
This is how I remember using buffers, though to be honest I don't trust my memory. With good reason it seems, since this crashes immediately after the window opens.
I've tried changing the last argument to glDrawArrays to 1 instead of 3. I've also tried binding the buffer twice, first as GL_VERTEX_ARRAY, followed by glVertexPointer, second as GL_COLOR_ARRAY, followed by glColorPointer. No dice.
The 3rd parameter of glVertexPointer respectively glColorPointer is the byte offset between consecutive (stride). If a named buffer object is bound, then the 4th parameter is treated as a byte offset, too.
The stride parameter has to be 5 * sizeof(GLfloat), because each attribute tuple consists of 5 (GLfloat) components (X, Y, R, G, B). The offset for the vertex coordinates is 0, because they are at the beginning. The offset for the color is 2 * sizeof(GLfloat), because the color comes after the 2 components of the vertex coordinate.
Further more GL_VERTEX_ARRAY is not a valid buffer target. The buffer target for vertex attributes is GL_ARRAY_BUFFER. The wrong usage of GL_VERTEX_ARRAY will cause INVALID_ENUM errors. Error information can be get by glGetError.
Do the following changes:
glGenBuffers(1, &triangleBuf);
glBindBuffer(GL_ARRAY_BUFFER, triangleBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, triangleBuf);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 5*sizeof(GLfloat), 0);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 5*sizeof(GLfloat), (GLfloat*)(2*sizeof(GLfloat)));
Since you do not bind a texture and you do net even have specified texture coordinates, do not enable 2 dimensional texturing:
glEnable(GL_TEXTURE_2D);
I am trying to draw 2 objects in OpenGL. The window/viewport is (0,0,950,1050). I am not sure this is the right way of doing it, but I thought so. I thought the idea was to create a VBO/VAO per object, bind it, set the data, and repeat that operation for each object.
Then when the objects are to be drawn:
set the shader
bind the data of the first object we want to draw using its vbo (say vbo1)
do the drawing call
bind the data of the next object we want to draw using its vbo (say vbo2)
do the drawing call
...
When I do this, I only get the points of the second object drawn on the screen, but with the color of the first object (it's blue instead of red).
My mistake must be obvious to any expert out there. What do I miss?
// BLUE -----------------------------------
GLuint vbo1, vao1;
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
float arr1[] = { 10, 10, 10, 110, 110, 110, 110, 10 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr1, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
// RED -----------------------------------
GLuint vbo2, vao2;
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
float arr2[] = { 400, 400, 400, 800, 800, 800, 800, 400 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr2, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
while (!glfwWindowShouldClose(window))
{
glClearColor(1, 1, 1, 0.1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(pointShader);
GLint loc;
loc = glGetUniformLocation(pointShader, "pointColor");
// it draws this one but with the color blue!
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
float ptColor2[3] = { 1, 0, 0 };
glUniform3fv(loc, 1, ptColor2);
glDrawArrays(GL_POINTS, 0, 4);
// it doesn't draw this one???
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
float ptColor1[3] = { 0, 0, 1 };
glUniform3fv(loc, 1, ptColor1);
glDrawArrays(GL_POINTS, 0, 4);
glfwSwapBuffers(window);
glfwWaitEvents();
}
EDIT 2 WORKING CODE
Thank you very much to both Reto Koradi and Datenwolf. Combining the answers, helped to come with the right answer. It's sad, these things are not explained properly in books. Hope this post will help other beginners (sorry if the result is a bit misleading, I swapped color between when I asked the question, and when I got the answer).
// RED -----------------------------------
GLuint vbo1, vao1;
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
float arr1[] = { 10, 10, 10, 110, 110, 110, 110, 10 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr1, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
// BLUE -----------------------------------
GLuint vbo2, vao2;
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
float arr2[] = { 400, 400, 400, 800, 800, 800, 800, 400 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glClearColor(1, 1, 1, 0.1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(pointShader);
GLint loc;
loc = glGetUniformLocation(pointShader, "pointColor");
// red
glBindVertexArray(vao1);
float ptColor1[3] = { 1, 0, 0 };
glUniform3fv(loc, 1, ptColor1);
glDrawArrays(GL_POINTS, 0, 4);
// blue
glBindVertexArray(vao2);
float ptColor2[3] = { 0, 0, 1 };
glUniform3fv(loc, 1, ptColor2);
glDrawArrays(GL_POINTS, 0, 4);
glfwSwapBuffers(window);
glfwWaitEvents();
}
EDIT 3
Note though the order from the first code fragment for the VAO/VBO order declaration would also work. So the above version and the one below are both valid:
// RED -----------------------------------
GLuint vbo1, vao1;
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
float arr1[] = { 10, 10, 10, 110, 110, 110, 110, 10 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr1, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
// BLUE -----------------------------------
GLuint vbo2, vao2;
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
float arr2[] = { 400, 400, 400, 800, 800, 800, 800, 400 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr2, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
The only thing that was really missing in the code was glBindVertexArray.
The problem is in your draw loop, where you call:
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
It does not matter which GL_ARRAY_BUFFER is currently bound when you make the draw call. The correct buffer needs to be bound when you call glVertexAttribPointer(), which you correctly did in your setup code.
The VAOs track all your vertex setup state. So before each draw call, you need to bind the corresponding VAO by calling glBindVertexArray(), instead of the glBindBuffer() calls you have in the posted code:
glBindVertexArray(vao2);
glUniform3fv(...);
glDrawArrays(...);
glBindVertexArray(vao1);
glUniform3fv(...);
glDrawArrays(...);
You must create and bind the Vertex Array Object before specifying the vertex attribute data locations (glVertexAttribPointer). The VAO kind of takes ownership of the data that belongs to the VBO currently bound when making those calls.
(EDIT accidently submitted while still typing)
Assuming you have a core profile context, when you attempt to create that first buffer object, there's no VAO to bind it to yet, so the whole creation of the BO fails. Hence when you try to draw it, nothing gets drawn at all. But what you see drawn is the BO you intended to bind to the second VAO, but because you got the order of operations wrong it ends up in the first VAO.
I've been trying to render a cube in a QGLWidget, but it comes out wrong. No matter how I rotate it, it looks like a flat square. It's like it didn't notice the Z coordinates of its vertices. Just before I added clearing of the GL_DEPTH_BUFFER_BIT, the square looked like all of the cube's sides crammed into one. Now it seems to discard vertices which don't belong in the front side, but it still isn't a cube.!
Screenshots [link]
My initializeGL() and paintGL():
typedef struct
{
float XYZW[4];
float RGBA[4];
} Vertex;
Vertex Vertices[8] =
{
//vertices
};
const GLubyte Indices[36] =
{
//indices
};
void ModelView::initializeGL()
{
m_program = new QGLShaderProgram(this);
m_program->addShaderFromSourceCode(QGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QGLShader::Fragment, fragmentShaderSource);
m_program->link();
}
void ModelView::paintGL()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearColor(.5f, .5f, .5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width(), height());
m_program->bind();
QMatrix4x4 matrix;
matrix.perspective(60, 4.0/3.0, 0.1, 100.0);
matrix.translate(0, 0, -2);
matrix.rotate(50.0, 1, 1, 1);
m_program->setUniformValue(m_matrixUniform, matrix);
m_posAttr = m_program->attributeLocation("posAttr");
m_colAttr = m_program->attributeLocation("colAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
glGenBuffers(1, &BufferId);
glGenBuffers(1, &IndexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, BufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId);
glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, VertexSize, 0);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid *)RgbOffset);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
m_program->release();
}
Vertices and Indices should be defined correctly, they're taken from a tutorial, as is most of the code. Rendering of 2D object seems to be just fine, though.
Also, why does the tutorial call matrix.translate with the -2 argument? If I change it to anything else greater than 1 or remove it, the rendered object disappears.
Qt5, Windows Vista 32-bit.
Also, why does the tutorial call matrix.translate with the -2
argument? If I change it to anything else greater than 1 or remove it,
the rendered object disappears.
This is due to clipping. When you render objects, things that are "too close" or "too far" are discarded, via the near and far clipping planes (respectively).
By moving the cube closer (changing -2 to 1 or 0), you are bringing the cube forward, past the near clipping plane, and it consequently disappears.
glVertexAttribPointer() has a size parameter, which specifies the number of components per vertex. In the code it is 2, therefore everything is 2D. Changing to 3 solves the issue.
My Vertex Buffer Object code is supposed to render textures nicely but instead the textures are being rendered oddly with some triangle shapes.
What happens - http://godofgod.co.uk/my_files/wrong.png
What is supposed to happen - http://godofgod.co.uk/my_files/right.png
This function creates the VBO and sets the vertex and texture coordinate data:
extern "C" GLuint create_box_vbo(GLdouble size[2]){
GLuint vbo;
glGenBuffers(1,&vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLsizeiptr data_size = 8*sizeof(GLdouble);
GLdouble vertices[] = {0,0, 0,size[1], size[0],0, size[0],size[1]};
glBufferData(GL_ARRAY_BUFFER, data_size, vertices, GL_STATIC_DRAW);
data_size = 8*sizeof(GLint);
GLint textcoords[] = {0,0, 0,1, 1,0, 1,1};
glBufferData(GL_ARRAY_BUFFER, data_size, textcoords, GL_STATIC_DRAW);
return vbo;
}
Here is some relavant code from another function which is supposed to draw the textures with the VBO.
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor4d(1,1,1,a/255);
glBindTexture(GL_TEXTURE_2D, texture);
glTranslated(offset[0],offset[1],0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(2, GL_DOUBLE, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer (2, GL_INT, 0, 0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawArrays(GL_TRIANGLES, 1, 3);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
I would have hoped for the code to use the first three coordinates (top-left,bottom-left,top-right) and the last three (bottom-left,top-right,bottom-right) to draw the triangles with the texture data correctly in the most efficient way. I don't see why triangles should make it more efficient but apparently that's the way to go. It, of-course, fails for some reason.
I am asking what is broken but also am I going about it in the right way generally?
Thank you.
If you want to use the one VBO for both vertex and texture coordinates you need to group them using a struct.
Define your data:
typedef struct {
GLdouble x, y;
GLint s, t;
} VertexData;
VertexData data[] = {
// x y s t
{0.0, 0.0, 0, 0},
{0.0, size[1], 0, 1},
{size[0], 0.0, 1, 0},
{size[0], size[1], 1, 1}
};
Copy it into VBO:
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), (GLvoid*)data, GL_STATIC_DRAW);
Set pointers. Note that stride is your struct's size and pointer itself serves as offset:
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(2, GL_DOUBLE, sizeof(VertexData), (GLvoid*)offsetof(VertexData, x));
glTexCoordPointer(2, GL_INT, sizeof(VertexData), (GLvoid*)offsetof(VertexData, s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
And draw.
EDIT: Implemented offset with offsetof() as Bahbar suggested.
You're loading data twice to the vbo. The second call to glBufferData is replacing the first one. Then both calls to gl*Pointer actually use the same data when calling draw.