Been hacking at this for ages now and still can’t get it to work using a texcoord buffer, so going to post more code:
First the program makes resources as such:
int Draw::make_resources()
{
vertex_buffer = make_buffer(
GL_ARRAY_BUFFER,
g_vertex_buffer_data,
3 * sizeof(GLfloat) * g_total_verts
);
element_buffer = make_buffer(
GL_ELEMENT_ARRAY_BUFFER,
g_element_buffer_data,
3 * sizeof(GLushort) * g_total_tris
);
for (int i =0; i < g_texCoords_array_size; i += 2)
{
g_texCoords_array[i+1] = 1.0 - (g_texCoords_array[i+1]); //t value must be flipped to get UV mapping
}
texCoord_buffer = make_buffer(
GL_ARRAY_BUFFER,
g_texCoords_array,
sizeof(GLfloat) * g_texCoords_array_size
);
//Make textures here
g_textures[0] = read_texture(g_tex);
if (g_textures[0] == 0)
return 0;
glGenTextures(1, &tex_id);
vertex_shader = make_shader(
GL_VERTEX_SHADER,
"src/hello-gl.v.glsl"
);
if (vertex_shader == 0)
return 0;
fragment_shader = make_shader(
GL_FRAGMENT_SHADER,
"src/hello-gl.f.glsl"
);
if (fragment_shader == 0)
return 0;
program = make_program(vertex_shader, fragment_shader);
if (program == 0)
return 0;
//shader variables
position = glGetAttribLocation(program, "position");
//texCoord_buffer = glGetAttribLocation(program, "texCoord_buffer");
rotate_x = glGetUniformLocation(program, "rotate_x_theta");
camera_uniform = glGetUniformLocation(program, "camera");
GLint texSampler;
texSampler = glGetUniformLocation(program, "tex");
glUniform1i(texSampler, 1);
return 1;
}
That gets executed from the class constructor. Then the draw function is called 60 times per second in an SDL loop:
void Draw::draw() {
glUseProgram(program);
glUniform1f(rotate_x, rotate_x_theta++);
float * camera = Camera::getInstance().getCameraMat();
glUniformMatrix4fv(camera_uniform, 1, false, camera);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer(
position, /* attribute */
3, /* size */
GL_FLOAT, /* type */
GL_FALSE, /* normalized? */
0, /* stride */
(void*)0 /* array buffer offset */
);
glEnableVertexAttribArray(position);
glBindBuffer(GL_ARRAY_BUFFER, texCoord_buffer);
glVertexAttribPointer(
texCoord_buffer, /* attribute */
2, /* size */
GL_FLOAT, /* type */
GL_FALSE, /* normalized? */
0, /* stride */
(void*)0 /* array buffer offset */
);
glEnableVertexAttribArray(texCoord_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer);
glDrawElements(
GL_TRIANGLES,
3 * g_total_tris,
GL_UNSIGNED_SHORT,
(GLvoid*) 0
);
glDisableVertexAttribArray(position);
glDisableVertexAttribArray(texCoord_buffer);
}
Vertex shader:
#version 110
attribute vec3 position;
attribute vec2 texCoord_buffer;
uniform float rotate_x_theta;
uniform mat4 camera;
varying vec2 tex_coord;
varying vec4 frag_colour;
mat4 view_frustum(
float angle_of_view,
float aspect_ratio,
float z_near,
float z_far
) {
return mat4(
vec4(1.0/tan(angle_of_view), 0.0, 0.0, 0.0),
vec4(0.0, aspect_ratio/tan(angle_of_view), 0.0, 0.0),
vec4(0.0, 0.0, (z_far+z_near)/(z_far-z_near), 1.0),
vec4(0.0, 0.0, -2.0*z_far*z_near/(z_far-z_near), 0.0)
);
}
mat4 translate(float x, float y, float z)
{
return mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0),
vec4(x, y, z, 1.0)
);
}
mat4 rotate_x(float theta)
{
return mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, cos(theta), sin(theta), 0.0),
vec4(0.0, -sin(theta), cos(theta), 0.0),
vec4(0.0, 0.0, 0.0, 1.0)
);
}
void main()
{
gl_Position = view_frustum(radians(45.0), 4.0/3.0, 0.5, 100.0)
* translate(0.0, 0.0, 50.0)
* rotate_x(radians(rotate_x_theta))
* vec4(position.x, position.y, position.z, 1.0);
tex_coord = texCoord_buffer;
}
Fragment shader:
#version 110
uniform sampler2D tex;
varying vec2 tex_coord;
void main()
{
vec2 st;
st[0] = 0.1674 * 0.33927;
st[1] = 0.1648 * 1.1;
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0) * texture2D(tex, tex_coord);
}
With this code, my model is drawn, but it is all the same colour - if I replace tex_coord with st in the gl_FragColor line of the fragment shader it changes the colour of the model. So it would appear that it is reading reading the texture, but applying the same texture coordinate to every vertex. Alternatively, if I uncomment the line
texCoord_buffer = glGetAttribLocation(program, "texCoord_buffer");
at the end of the make_resources function, the model is textured with a mixture of brown and orange (and maybe black?) as follows:
My (probably uneducated) guess is that I’m screwing something up with the buffer and it’s only reading a single texture coordinate or some garbage memory.
Help still greatly appreciated.