It's been a while since I've wrote some graphics programming and I've been staring at this for quite some time now and can't figure out what i'm doing wrong.
This is how I am creating my texture.
GLuint create_texture(const char* filename) {
SDL_Surface* surface;
GLenum tex_format;
GLint num_colors;
GLuint tex_id;
char* file_path;
file_path = get_resource(filename);
surface = IMG_Load(file_path);
if (!surface) {
SDL_Log("failed to create surface\n");
SDL_Quit();
return -1;
} else {
if ((surface->w & (surface->w - 1)) != 0) {
SDL_Log("image { %s } width is not power of 2\n", filename);
}
if ((surface->h & (surface->h - 1)) != 0) {
SDL_Log("image { %s } height is not power of 2\n", filename);
}
num_colors = surface->format->BytesPerPixel;
if (num_colors == 4) {
if (surface->format->Rmask == 0x000000ff)
tex_format = GL_RGBA;
else
tex_format = GL_BGRA;
}
if (num_colors == 3) {
if (surface->format->Rmask == 0x000000ff)
tex_format = GL_RGB;
else
tex_format = GL_BGR;
} else {
SDL_Log("pixel image format shouldn't get here! Quitting\n");
SDL_Quit();
};
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, tex_format, surface->w, surface->h, 0,
tex_format, GL_UNSIGNED_BYTE, surface->pixels);
}
if (surface) SDL_FreeSurface(surface);
free(file_path);
return tex_id;
}
this code above works correctly for loading the image data.
vertex shader
#version 330 core
layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec4 a_col;
layout (location = 2) in vec2 a_tex;
uniform mat4 u_mvp_mat;
uniform mat4 u_mod_mat;
uniform mat4 u_view_mat;
uniform mat4 u_proj_mat;
out vec4 f_color;
out vec2 f_tex;
void main()
{
gl_Position = u_mvp_mat * vec4(a_pos, 1.0);
f_tex = a_tex;
f_color = a_col;
}
fragment shader.
#version 330 core
in vec4 f_color;
out vec4 o_color;
in vec2 f_tex;
uniform sampler2D u_sprite_tex;
void main (void)
{
o_color = f_color;
o_color = texture(u_sprite_tex, f_tex);
}
this is how i setup my VBO
quad = ren2d_new(); //just a wrapper around a quad or two tri.
ren2d_set_tint(quad, 0, 1, 0, 1); //setting the color to green
pos_loc = get_attrib_location(ce_get_default_shader(), "a_pos");
col_loc = get_attrib_location(ce_get_default_shader(), "a_col");
mvp_matrix_loc = get_uniform_location(ce_get_default_shader(), "u_mvp_mat");
model_mat_loc = get_uniform_location(ce_get_default_shader(), "u_mod_mat");
view_mat_loc = get_uniform_location(ce_get_default_shader(), "u_view_mat");
proj_matrix_loc =
get_uniform_location(ce_get_default_shader(), "u_proj_mat");
tex_loc = get_uniform_location(ce_get_default_shader(), "u_sprite_tex");
camera = cam_2d_new(ce_get_width(), ce_get_height());
model_mat = mat4_identity();
mat4_scale(model_mat, 128, 128, 1);
tex_id = create_texture("test.png");
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vert_buff);
glBindBuffer(GL_ARRAY_BUFFER, vert_buff);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->vertices), quad->vertices,
GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &col_buff);
glBindBuffer(GL_ARRAY_BUFFER, col_buff);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->colors), quad->colors,
GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(quad->tex_coords),
quad->tex_coords);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &ind_buff);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind_buff);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad->indices), quad->indices,
GL_STATIC_DRAW);
glBindVertexArray(0);
this is my render function:
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//could my texturing problems be here?
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_id);
glUniform1i(tex_loc, 0);
glUseProgram(ce_get_default_shader()->shader_program);
glBindVertexArray(vao);
//excuse the silly names
ce_get_view_matrices(&vview_mat, &pproj_mat, &mmvp_mat);
mat4_multi(&mmvp_mat, &vview_mat, model_mat);
mat4_multi(&mmvp_mat, &pproj_mat, &mmvp_mat);
glUniformMatrix4fv(mvp_matrix_loc, 1, GL_FALSE, mat4_get_data(&mmvp_mat));
glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, mat4_get_data(model_mat));
glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, mat4_get_data(&vview_mat));
glUniformMatrix4fv(proj_matrix_loc, 1, GL_FALSE, mat4_get_data(&pproj_mat));
glDrawElements(GL_TRIANGLES, quad->vertex_count, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
I am just getting a black quad. I can't track it down and i've been staring at this for quite a few hours now.
doing some very basic testing in the fragment shader like this.
#version 330 core
in vec4 f_color;
out vec4 o_color;
in vec2 f_tex;
uniform sampler2D u_sprite_tex;
void main (void)
{
//o_color = f_color;
vec4 c;
if(f_tex.y == 1.0) { c = vec4(1.0, 0.0, 0.0, 1.0); }
if(f_tex.y == 0.0) { c = vec4(0.0, 0.0, 1.0, 1.0); }
o_color = c;
o_color = texture(u_sprite_tex, f_tex);
}
my quads turn out to be blue both along the x and the y axis. That seems to be that the only value being passed in in 0.0 which doesn't make sense.
okay this was definitely a problem of my own creation. The reason that I was getting segmentation fault was because of this code.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vert_buff);
glBindBuffer(GL_ARRAY_BUFFER, vert_buff);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->vertices), quad->vertices,
GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &col_buff);
glBindBuffer(GL_ARRAY_BUFFER, col_buff);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->colors), quad->colors,
GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0); //right here
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(quad->tex_coords),
quad->tex_coords);
glEnableVertexAttribArray(2);
glGenBuffers(1, &ind_buff);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind_buff);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad->indices), quad->indices,
GL_STATIC_DRAW);
glBindVertexArray(0);
after you bind your vbo buffer to zero attempting to access it will cause a segmentation fault...
After that just making sure that I sent the proper data to the gpu and all other code worked as expected.
GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &col_buff);
glBindBuffer(GL_ARRAY_BUFFER, col_buff);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad->colors), quad->colors,
GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
//glBindBuffer(GL_ARRAY_BUFFER, 0); //right here remove this
//properly setup the local data to gpu data
glBufferData(GL_ARRAY_BUFFER, rend2d_get_sizeof_tex_coord(quad),
rend2d_get_tex_coord_data(quad), GL_STATIC_DRAW);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0); //put it here after finished with vbo
after those two changes everything worked as expected. Hopefully this can save someone some time.
There are at least two things that might be wrong:
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(quad->tex_coords),
quad->tex_coords);
Are you sure that quad->tex_coords contains 4-dimensional vectors? The fragment shader expects vec2. If you only supply two floats per vertex, you have to change the second parameter to two. When OpenGL tries to read from a too small ARRAY_BUFFER this can also cause segmentation faults. Note, that attributes are set to inactive if they do not contribute to the final color, thus the texture coordinates might only be read when textures are used.
Second: You are calling glGenerateMipmap before uploading data to the texture.
Related
I'm trying to render a textured triangle. I'm using STB image to load a png. The triangle is displayed as a single color for a host of different images that I've tried. The color seems to be an average of the total colors displayed in the image.
I've looked into many solutions for similar questions and have ensured (or so I think) that I've not fallen into the common 'gotchas': glEnable(GL_TEXTURE_2D) is called. My calls to glVertexAttribPoitners() are set up correctly. I've tried to tell OpenGl that I don't want to use mipmapping with glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR), and I've enabled the relevant vertex arrays via glEnableVertexAttribArray(). My shaders compile with no errors.
#include <practice/practice.h>
#include <test_dep/stb_image.h>
void
initRenderer_practice()
{
const char* vertex_shader = GLSL(450 core,
layout (location = 0) in vec2 vCoords;
layout (location = 1) in vec2 tCoords;
out vec2 ftCoords;
void main()
{
gl_Position = vec4(vCoords.x, vCoords.y, 0.0, 1.0);
ftCoords = tCoords;
}
);
const char* fragment_shader = GLSL(450 core,
uniform sampler2D texture_data;
in vec2 ftCoords;
out vec4 fragColor;
void main()
{
fragColor = texture(texture_data, ftCoords.st);
}
);
GLfloat vCoordsLocal[] =
{
//
// POSITION COORDS
//
// bottom left
-0.5, -0.5,
// bottom right
0.5, -0.5,
// top center
0.0, 0.5,
//
// TEXTURE COORDS
//
// left bottom
0.0, 0.0,
// right bottom
1.0, 0.0,
// center top
0.5, 1.0,
};
if (!practice_target)
{
practice_target = (uGLRenderTarget*)malloc(sizeof(uGLRenderTarget));
practice_target->shader_program = 0;
practice_target->vertex_array_object = (GLuint) -1;
practice_target->vertex_buffer_object = (GLuint) -1;
}
practice_target->shader_program = uGLCreateShaderProgram_vf(&vertex_shader,
&fragment_shader);
assert(practice_target->shader_program);
glUseProgram(practice_target->shader_program);
glError;
glGenVertexArrays(1, &practice_target->vertex_array_object);
glBindVertexArray(practice_target->vertex_array_object);
glError;
glGenBuffers(1, &practice_target->vertex_buffer_object);
glBindBuffer(GL_ARRAY_BUFFER, practice_target->vertex_buffer_object);
glBufferData(GL_ARRAY_BUFFER,
sizeof(vCoordsLocal),
vCoordsLocal,
GL_STATIC_DRAW);
glError;
glGenTextures(1, &practice_target->texture_id);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, practice_target->texture_id);
practice_target->shdr_texture_2d_location = glGetUniformLocation(practice_target->shader_program, "texture_data");
glUniform1i(practice_target->shdr_texture_2d_location, 0);
assert(practice_target->shdr_texture_2d_location != -1);
glError;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glError;
stbi_set_flip_vertically_on_load(true);
u8* texture_data = NULL;
GLint width, height, channels = 0;
texture_data = stbi_load("./assets/index.png", &width, &height, &channels, 0);
if (texture_data)
{
/*
void glTexImage2D(GLenum target,
GLint level,
GLint internalFormat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const GLvoid * data);
*/
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
texture_data);
glGenerateMipmap(GL_TEXTURE_2D);
glError;
printf("\n\n numchannels: %d\n\n", channels);
}
else
{
puts("[ debug ] Load texture failed\n");
assert(0);
}
stbi_image_free(texture_data);
/*
void glVertexAttribPointer(GLuint index,
GLint size,
GLenum type,
GLboolean normalized,
GLsizei stride,
const GLvoid * pointer);
*/
// Vertex coordinate attribute
glVertexAttribPointer(0,
2,
GL_FLOAT,
GL_FALSE,
0,
(void*) 0);
glEnableVertexAttribArray(0);
// Texture coordinate attribute
glVertexAttribPointer(1,
2,
GL_FLOAT,
GL_FALSE,
0,
(void*) 6);
glEnableVertexAttribArray(1);
glError;
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
glError;
}
void
render_practice()
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(practice_target->shader_program);
glEnable(GL_TEXTURE_2D);
glBindVertexArray(practice_target->vertex_array_object);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, practice_target->texture_id);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
glError;
}
The expected result is to have the texture mapped onto the triangle, rather than a single color.
The vertex attribute specification for the texture coordinates is misaligned.
The memory layout of the attributes is
x0 y0, x1, y1, x2, y2, u0 v0, u1, v1, u2, v2
So the first texture coordinate is 6th element in the buffer.
But, the last parameter of glVertexAttribPointer is a byte offset into the buffer object's data store.
This mean the offset has to be 6*sizeof(GLfloat) rather than 6
glVertexAttribPointer(1,
2,
GL_FLOAT,
GL_FALSE,
0,
(void*)(6*sizeof(GLfloat)); // <-----
I recommend to change the vertex attribute arrangement, to an extendable layout:
x0 y0 u0 v0 x1 y1 u1 v1 x2 y2 u2 v2 ...
and to use the corresponding vertex attribute specification:
GLsizei stride = (GLsizei)(4*sizeof(GLfloat)); // 4 because of (x, y, u ,v)
void* vertOffset = (void*)(0); // 0 because the vertex coords are 1st
void* texOffset = (void*)(2*sizeof(GLfloat)); // 2 because u, v are after x, y
// Vertex coordinate attribute
glVertexAttribPointer(0,
2,
GL_FLOAT,
GL_FALSE,
stride,
vertOffset);
glEnableVertexAttribArray(0);
// Texture coordinate attribute
glVertexAttribPointer(1,
2,
GL_FLOAT,
GL_FALSE,
stride,
texOffset;
glEnableVertexAttribArray(1);
I'm trying to render a tetrahedron that I could expand to other objects.
Using static arrays works fine, draws the tetrahedron.
But when I read in an OFF file into a dynamic array, nothing appears. No errors appear when I compile.
GLfloat *tetra_vertices = NULL; //This is declared at the start
The following is used in the function that grabs the data from the OFF file.
mod->faces grabs the number of faces from the OFF file. In this case it is 4.
I checked reading in the vertices from the OFF file and that is accurate. Even compared it to the static array.
tetra_vertices = (GLfloat *)malloc(sizeof(GLfloat) * mod->faces * 3 * 3);
for(i=0; i< (mod->faces * 3); i++){
tetra_vertices[i*3]=mod->verts[(mod->face[i])*3];
tetra_vertices[i*3+1]=mod->verts[(mod->face[i])*3+1];
tetra_vertices[i*3+2]=mod->verts[(mod->face[i])*3+2];
}
In init():
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(tetra_vertices), tetra_vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(tetra_colors), tetra_colors, GL_STATIC_DRAW);
program = initshader( "a4a_vs.glsl", "a4a_fs.glsl" );
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
pos = glGetAttribLocation(program, "vPos");
glEnableVertexAttribArray(pos);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, NULL);
color = glGetAttribLocation(program, "vColor");
glEnableVertexAttribArray(color);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, 0, NULL);
ModelView = glGetUniformLocation(program, "modelview");
Projection = glGetUniformLocation(program, "projection");
glEnable (GL_DEPTH_TEST);
glClearColor( 0.0, 0.0, 0.0, 1.0 );
glewExperimental = GL_TRUE;
glewInit();
And finally in my main():
GLFWwindow *window = glfwCreateWindow (512, 512, "Hello Cube", NULL, NULL);
glfwMakeContextCurrent (window);
setup(argc, argv); //This creates reads in the OFF file and creates the arrays.
init();
reshape(window, 512, 512);
glfwSetKeyCallback(window, keyboard);
glfwSetWindowSizeCallback(window, reshape);
while (!glfwWindowShouldClose (window)) {
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
identity(transform);
lookat(transform, eye, at, up);
glUseProgram(program);
glBindVertexArray(vao);
glUniformMatrix4fv(ModelView, 1, GL_FALSE, transform);
glUniformMatrix4fv(Projection, 1, GL_FALSE, projection);
glDrawArrays(GL_TRIANGLES, 0, (mod->faces * 3));
glfwSwapBuffers (window);
if (animation)
update();
glfwPollEvents ();
}
Eventually I want to store the array into a list so I can cycle throw different objects from different OFF files. But for now I just want it to draw something. Any assistance would be greatly appreciated. Thank you.
The sizeof operator queries the size of the object or type, it returns the size in bytes of the type that would be returned by the expression you pass to it. Since the type of tetra_vertices is GLfloat*, sizeof(tetra_vertices) returns the size of the pointer type, which probably is 4 or 8 depending on the hardware.
The 2nd parameter of glBufferData is the size of the data buffer in bytes.
This means you have to change your code like this:
size_t vertex_size = sizeof(GLfloat) * mod->faces * 3 * 3;
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)vertex_size, tetra_vertices, GL_STATIC_DRAW);
You have to do the same for the color attribute buffer tetra_colors.
I'm trying to render a white square in OpenGL and I have this function to do so:
void main_loop(window_data *window)
{
printf("%s\n", glGetString(GL_VERSION));
GLuint vertex_array_objects, vertex_buffer_objects;
glGenVertexArrays(1, &vertex_array_objects);
glBindVertexArray(vertex_array_objects);
glGenBuffers(1, &vertex_buffer_objects);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_objects);
GLfloat vertices[6][2] = {
{-0.90, -0.90},
{0.85, -0.90},
{-0.90, 0.85},
{0.90, -0.85},
{0.90, 0.90},
{-0.85, 0.90}};
glBufferData(
GL_ARRAY_BUFFER,
sizeof(vertices),
vertices,
GL_STATIC_DRAW);
glVertexAttribPointer(0,
2,
GL_FLOAT,
GL_FALSE,
0,
(void*)0);
glEnableVertexAttribArray(0);
while (!glfwWindowShouldClose(window->glfw_window))
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vertex_array_objects);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window->glfw_window);
glfwPollEvents();
}
return;
}
Which works perfectly fine, but then I tried to split this up into two functions like so:
void initialize_image(GLuint *vArray, GLuint *vBuffer, GLfloat vertices[][2])
{
glGenVertexArrays(1, vArray);
glBindVertexArray(*vArray);
glGenBuffers(1, vBuffer);
glBindBuffer(GL_ARRAY_BUFFER, *vBuffer);
glBufferData(
GL_ARRAY_BUFFER,
sizeof(vertices),
vertices,
GL_STATIC_DRAW);
glVertexAttribPointer(
0,
2,
GL_FLOAT,
GL_FALSE,
0,
(void*)0);
glEnableVertexAttribArray(0);
return;
}
And then I call it in the main_loop function (just before the while loop):
initialize_image(&vArray, &vBuffer, vertices);
But that keeps giving me a black screen of nothingness.
What could be causing this?
When you pass pointer to vertices array its sizeof() is the pointer size and not your data size!
Pass additional vertices size argument to your function and use it instea d of sizeof for glBufferData call.
I am having some trouble in OpenGL, making a render to texture example work. At initialization, i generate a texture 'randtex' with random values of green and black. If i render this texture directly to the window (mapped into a quad) it works all well.
like this:
But if i render 'randtex' into another texture 'tex' which is attached to a framebuffer object, then rendering 'tex' on the screen just gives me a black image on the fbo's blue background and from what i know it should give me the original texture over the blue background. In other words, this is what i am getting
vertex shader for display only (display_shaderp).
#version 420
in vec4 pos;
in vec2 tex_coord;
out vec2 vtex_coord;
uniform mat4 projection;
uniform mat4 modelview;
void main(){
gl_Position = projection * modelview * pos;
vtex_coord = tex_coord;
}
fragment shader for display only (display_shaderp)
#version 420
in vec2 vtex_coord;
uniform sampler2D tex;
out vec4 color;
void main(){
color = texture2D(tex, vtex_coord);
//color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
shader program compiles and links ok, i get no gl errors and framebuffer is complete without errors too.
This is the rendering code:
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, win_width, win_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (GLfloat)win_width / (GLfloat) win_height, 0.1f, 50.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslate3f(0.0f, 0.0f, -3.0f)
// render to texture
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0,0, win_width, win_height);
glClearColor(0.0, 0.0, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(fbo_shaderp);
GLfloat m_matrix[16], p_matrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, m_matrix);
glGetFloatv(GL_PROJECTION_MATRIX, p_matrix);
glUniformMatrix4fv(glGetUniformLocation(fbo_shaderp, "modelview"),1,GL_FALSE,m_matrix);
glUniformMatrix4fv(glGetUniformLocation(fbo_shaderp, "projection"),1,GL_FALSE,p_matrix);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, randtex);
glUniform1i(glGetUniformLocation(fbo_shaderp, "tex"), randtex);
GLuint _p = glGetAttribLocation(fbo_shaderp, "pos");
GLuint _t = glGetAttribLocation(fbo_shaderp, "tex_coord");
glVertexAttribPointer(_p, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
glVertexAttribPointer(_t, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(sizeof(float)*3));
glEnableVertexAttribArray(_p);
glEnableVertexAttribArray(_t);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
glUseProgram(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// render to the window
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0,0, win_width, win_height);
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(display_shaderp);
glUniformMatrix4fv(glGetUniformLocation(display_shaderp,"modelview"),1,GL_FALSE,m_matrix);
glUniformMatrix4fv(glGetUniformLocation(display_shaderp,"projection"),1,GL_FALSE,p_matrix);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(glGetUniformLocation(display_shaderp, "tex"), 0);
GLuint _p = glGetAttribLocation(display_shaderp, "pos");
GLuint _t = glGetAttribLocation(display_shaderp, "tex_coord");
glVertexAttribPointer ( _p, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0 );
glVertexAttribPointer ( _t, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*) (sizeof(float) * 3) );
glEnableVertexAttribArray(_p);
glEnableVertexAttribArray(_t);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
glUseProgram(0);
And the code to create textures and framebuffer
int i = 0;
// create a random texture 'randtex'
glGenTextures(1, &randtex);
glBindTexture(GL_TEXTURE_2D, randtex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// random data
GLubyte* data = (GLubyte *) malloc(width*height*4*sizeof(GLubyte));
GLubyte val;
for (i = 0; i < width * height * 4; i+=4){
if ((double)rand()/(double)RAND_MAX > 0.8)
val = 255;
else
val = 0;
data[i] = 0;
data[i+1] = val;
data[i+2] = 0;
data[i+3] = 255;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,GL_UNSIGNED_BYTE, data);
// create an empty texture 'tex'
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,GL_UNSIGNED_BYTE, 0);
// create framebuffer and attach 'tex'
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, tex, 0);
GLenum status;
if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE)
fprintf(stderr, "glCheckFramebufferStatus: error %p", status);
shaders for render to texture (fbo_shaderp)
render to texture vertex shader
in vec4 pos;
in vec2 tex_coord;
out vec2 vtex_coord;
uniform mat4 projection;
uniform mat4 modelview;
void main(){
gl_Position = projection * modelview * pos;
vtex_coord = tex_coord;
}
render to texture fragment shader
#version 420
in vec2 vtex_coord;
layout(location = 0) out vec4 color;
uniform sampler2D tex;
void main(){
color = texture2D(tex, vtex_coord);
//color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
In this last shader, if i use the commented line to paint all white and comment out the
texture one, i do get a white image but also opengl error right after rendering to texture "OpenGL Error: invalid value", so this actually confuses me more.
glUniform1i(glGetUniformLocation(fbo_shaderp, "tex"), randtex);
You must not give the ID of the texture, but the slot you bind the texture to. So in your case, that should be
glUniform1i(glGetUniformLocation(fbo_shaderp, "tex"), 0);
Im trying to render a non power of 2 texture using a model class that creates a texture and stores it's ID and size (thanks to ADC and another stackoverflow member), and additional code the create VBO's and render it (The code for VBO's and rendering is for testing purposes, it is properly divided in my models).
When I use this code, but remove the texture-specific code, it works fine. When adding the texture specific code however, it only renders what I believe to be the bottom-right pixel, from trying out multiple complex images and using DigitalColor Meter to check the images and output.
I don't suppose that texture coordinates have to be specified explicitly when using this setup, and if they do, how would I?
Main OpenGL Code
// Create vertex buffer
GLuint memoryPointer = 0;
GLuint colourMemoryPointer = 0;
GLfloat *vertices;
size_t vertex_size = 0;
int check = AllocateVertexBuffer(2, 4, &vertices, &vertex_size);
CDMeshVertexesCreateRectangle(200, 200, vertices);
// Create colour buffer
GLfloat *colors;
size_t color_size;
int check2 = AllocateVertexBuffer(4, 4, &colors, &color_size);
CDMeshColorsCreateGrey(1.0, 4, colors);
// Create texture buffer
CDTexture *texture = [CDTexture loadPngTexture:#"Rawr"];
// Allocate the buffer
glGenBuffers(1, &memoryPointer);
// Bind the buffer object (tell OpenGL what to use)
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
// Allocate space for the VBO
glBufferData(GL_ARRAY_BUFFER, vertex_size, vertices, GL_STATIC_DRAW);
// Allocate the buffer
glGenBuffers(1, &colourMemoryPointer);
// Bind the buffer object (tell OpenGL what to use)
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
// Allocate space for the VBO
glBufferData(GL_ARRAY_BUFFER, color_size, colors, GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY); // Activate vertex coordinates array
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture.ID);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
//[texture render];
//render
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY); // Deactivate vertex coordinates array
glDisableClientState(GL_COLOR_ARRAY);
free(vertices);
free(colors);
CDTexture loadPngTexture: Method
CFURLRef textureURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
(CFStringRef)fileName,
CFSTR("png"),
NULL);
NSAssert(textureURL, #"Texture name invalid");
// Get the image source using a file path
CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(textureURL, NULL);
NSAssert(myImageSourceRef, #"Invalid Image Path.");
NSAssert((CGImageSourceGetCount(myImageSourceRef) > 0), #"No Image in Image Source.");
// Get the image reference using the source reference, -_-
CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL);
NSAssert(myImageSourceRef, #"Image not created.");
// Start gathering data from the image, before releasing it
GLuint myTextureName;
size_t width = CGImageGetWidth(myImageRef);
size_t height = CGImageGetHeight(myImageRef);
CGRect rect = {{0, 0}, {width, height}};
void * myData = calloc(width * 4, height);
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGContextRef myBitmapContext = CGBitmapContextCreate (myData,
width, height, 8,
width*4, space,
kCGBitmapByteOrder32Host |
kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(space);
// Flip so that it isn't upside-down
CGContextTranslateCTM(myBitmapContext, 0, height);
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
CGContextSetBlendMode(myBitmapContext, kCGBlendModeCopy);
CGContextDrawImage(myBitmapContext, rect, myImageRef);
CGContextRelease(myBitmapContext);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
// Generate texture buffer
glGenTextures(1, &myTextureName);
// Bind buffer for use
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
// Set storage methods
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Set the parameter required for non power of two textures
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Load the texture data into the buffer
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, width, height,
0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, myData);
// Free the data used, as it's now in the buffer
free(myData);
// Return information on texture object
CDTexture *texture = [[CDTexture alloc] init];
texture.ID = myTextureName;
texture.size = NSMakeSize(width, height);
return texture;
UPDATE
I've tried using a texture pointer to define the area, and this results in the same problem. The colour/texture it draws will do so even without binding and using a pointer. I have also tried enabling and disabling GL_TEXTURE_COORD_ARRAY before and after it is used and rendered, and results in the same problem.
Unless i've done something wrong, the problem doesn't seem related with texture pointers.
GLfloat texCoords[8] = {
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
1.0, 0.0
};
...
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture.ID);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
//[texture render];
//render
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
UPDATE 2
I've tried obtaining an error code from OpenGL to try and solve the problem, but no error codes have been printed.
UPDATE 3
I have tried using a different method to get raw image data, and the same result happens (albeit with some discolouration, as I must not be using the right colour settings). OpenGL's interpretation of the data must be flawed here. I have experimented with glPixelStorei() but nothing has changed so far. As OpenGL isn't reporting any error, it must be with the programs interpretation of the data, so either the parameters I have set for how data is stored, or vertex problems that is causing only 1 pixel to be displayed, although because of this precision, it is most likely to be parameters.
New process for raw image data (thanks to another stackoverflow user). Posted for reference.
NSBitmapImageRep *theImage;
int bitsPPixel, bytesPRow;
NSSize size;
unsigned char *theImageData;
NSData* imgData = [NSData dataWithContentsOfFile:fileName options:NSUncachedRead error:nil]; // use FileURL
theImage = [NSBitmapImageRep imageRepWithData:imgData];
if( theImage != nil )
{
bitsPPixel = [theImage bitsPerPixel];
bytesPRow = [theImage bytesPerRow];
size.width = [theImage pixelsWide];
size.height = [theImage pixelsHigh];
}
enter code here
UPDATE 4
Changed to GL_TEXTURE_2D for efficiency. The bottom-left pixel is still only being rendered. Here is the full order of the code:
// Create vertex buffer
GLuint memoryPointer = 0;
GLuint colourMemoryPointer = 0;
GLfloat *vertices;
size_t vertex_size = 0;
AllocateVertexBuffer(2, 4, &vertices, &vertex_size);
CDMeshVertexesCreateRectangle(200, 200, vertices);
// Create colour buffer
GLfloat *colors;
size_t color_size;
AllocateVertexBuffer(4, 4, &colors, &color_size);
CDMeshColorsCreateGrey(1.0, 4, colors);
// Create Texture UV Coordinates
GLfloat *texture;
size_t texture_size;
AllocateVertexBuffer(4, 2, &texture, &texture_size);
CDMeshVertexesCreateRectangle(1, 1, texture);
// Create texture buffer
NSString *fileName = #"Rawr3";
CFURLRef textureURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
(CFStringRef)fileName,
CFSTR("png"),
NULL);
NSAssert(textureURL, #"Texture name invalid");
// Get the image source using a file path
CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(textureURL, NULL);
NSAssert(myImageSourceRef, #"Invalid Image Path.");
NSAssert((CGImageSourceGetCount(myImageSourceRef) > 0), #"No Image in Image Source.");
// Get the image reference using the source reference, -_-
CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL);
NSAssert(myImageSourceRef, #"Image not created.");
// Start gathering data from the image, before releasing it
GLuint myTextureName;
size_t width = CGImageGetWidth(myImageRef);
size_t height = CGImageGetHeight(myImageRef);
CGRect rect = {{0, 0}, {width, height}}; //Doesnt need fiddling
void * myData = calloc(width * 4, height); //Fiddled
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGContextRef myBitmapContext = CGBitmapContextCreate (myData,
width, height, 8,
width*4, space,
kCGBitmapByteOrder32Host |
kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(space);
// Flip so that it isn't upside-down
CGContextTranslateCTM(myBitmapContext, 0, height);
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
CGContextSetBlendMode(myBitmapContext, kCGBlendModeCopy);
CGContextDrawImage(myBitmapContext, rect, myImageRef);
CGContextRelease(myBitmapContext);
// Generate texture buffer
glGenTextures(1, &myTextureName);
// Bind buffer for use
glBindTexture(GL_TEXTURE_2D, myTextureName);
// Set storage methods
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_STORAGE_HINT_APPLE,
GL_STORAGE_CACHED_APPLE);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
// Set clamping and rendering preferences
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
// Load the texture data into the buffer
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, myData);
glGetError();
// Free the data used, as it's now in the buffer
free(myData);
// Return information on texture object
CDTexture *textureObj = [[CDTexture alloc] init];
textureObj.ID = myTextureName;
textureObj.size = NSMakeSize(width, height);
// Allocate the buffer
glGenBuffers(1, &memoryPointer);
// Bind the buffer object (tell OpenGL what to use)
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
// Allocate space for the VBO
glBufferData(GL_ARRAY_BUFFER, vertex_size, vertices, GL_STATIC_DRAW);
// Allocate the buffer
glGenBuffers(1, &colourMemoryPointer);
// Bind the buffer object (tell OpenGL what to use)
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
// Allocate space for the VBO
glBufferData(GL_ARRAY_BUFFER, color_size, colors, GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY); // Activate vertex coordinates array
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindTexture(GL_TEXTURE_2D, textureObj.ID);
glTexCoordPointer(2, GL_FLOAT, 0, texture);
GetGLError();
//render
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY); // Deactivate vertex coordinates array
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glDeleteBuffers(1, &memoryPointer);
glDeleteBuffers(1, &colourMemoryPointer);
GLuint texID = textureObj.ID;
glDeleteBuffers(1, &texID);
free(vertices);
free(colors);
free(texture);
}
UPDATE 5
From glTexImage2D(), it will render the bottom-left pixel of the texture even if I don't bind the texture and add coordinates for it, which seems strange, considering that it should be drawn using glTexCoordPointer().
UPDATE 6
Probably the last update, used the texture initialisation code with another more, 'manual' technique of drawing and it worked fine. I have removed the Apple specific elements. When removing the colour VBO and pointer from this code, a white box is still rendered for some odd reason. The problem is with the VBO's, but I cant see why. GL_TEXTURE_RECTANGLE_ARB is just being used for my coloured texture right now, will be changed when this problem is solved.
// Create vertex buffer
GLuint memoryPointer = 0;
GLuint colourMemoryPointer = 0;
GLfloat *vertices;
size_t vertex_size = 0;
AllocateVertexBuffer(2, 4, &vertices, &vertex_size);
CDMeshVertexesCreateRectangle(200, 200, vertices);
GetGLError();
// Create colour buffer
GLfloat *colors;
size_t color_size;
AllocateVertexBuffer(4, 4, &colors, &color_size);
CDMeshColorsCreateGrey(0.4, 4, colors);
// Allocate the buffer
glGenBuffers(1, &memoryPointer);
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glBufferData(GL_ARRAY_BUFFER, vertex_size, vertices, GL_STATIC_DRAW);
// Allocate the buffer
glGenBuffers(1, &colourMemoryPointer);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glBufferData(GL_ARRAY_BUFFER, color_size, colors, GL_STATIC_DRAW);
// Enable client states for drawing the various arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Bind each buffer and use the VBO's to draw (apart from the texture buffer)
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName); //
glTexCoordPointer(2, GL_FLOAT, 0, texture);
//render
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// Disale client states as were done with them.
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
GetGLError();
// Delete buffers to avoid problems
glDeleteBuffers(1, &memoryPointer);
glDeleteBuffers(1, &colourMemoryPointer);
glDeleteBuffers(1, &myTextureName);
free(vertices);
free(colors);
free(texture);
Of course you must supply texture coordinates. Either as part of the vertex attribute vector, or by generating them (in a shader). But you must supply texture coordinates somehow, you can't get around this.
I solved the problem (finally) by creating a Vertex Buffer Object (VBO) for the texture, instead of trying to supply vertex data directly to glTextureCoordPointer(). I guess the lesson here is that if you are going to use VBO's, use them for everything! For reference, here is the complete code:
Texture Creation
// Create texture buffer, start with the name of the image.
NSString *fileName = #"Rawr";
CFURLRef textureURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(),
(CFStringRef)fileName,
CFSTR("png"),
NULL);
NSAssert(textureURL, #"Texture name invalid");
// Get the image source using a file path
CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(textureURL, NULL);
NSAssert(myImageSourceRef, #"Invalid Image Path.");
NSAssert((CGImageSourceGetCount(myImageSourceRef) > 0), #"No Image in Image Source.");
// Get the image reference using the source reference, -_-
CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL);
NSAssert(myImageSourceRef, #"Image not created.");
// Start gathering data from the image, before releasing it
GLuint myTextureName;
size_t width = CGImageGetWidth(myImageRef);
size_t height = CGImageGetHeight(myImageRef);
CGRect rect = {{0, 0}, {width, height}}; //Doesnt need fiddling
void * myData = calloc(width * 4, height); //Fiddled
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGContextRef myBitmapContext = CGBitmapContextCreate (myData,
width, height, 8,
width*4, space,
kCGBitmapByteOrder32Host |
kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(space);
// Flip so that it isn't upside-down
CGContextTranslateCTM(myBitmapContext, 0, height);
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
CGContextSetBlendMode(myBitmapContext, kCGBlendModeCopy);
CGContextDrawImage(myBitmapContext, rect, myImageRef);
CGContextRelease(myBitmapContext);
GetGLError();
// The extension GL_TEXTURE_RECTANGLE_ARB can be used for non-power of two textures, but it is slower than GL_TEXTURE_2D and not
// supported by all graphics cards.
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glGenTextures(1, &myTextureName);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, myData);
//glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT ,GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB,myTextureName, 0);
free(myData);
VBO Creation
// Create vertex buffer
GLuint memoryPointer = 0;
GLuint colourMemoryPointer = 0;
GLuint texPointer = 0;
GLfloat *vertices;
size_t vertex_size = 0;
AllocateVertexBuffer(2, 4, &vertices, &vertex_size);
CDMeshVertexesCreateRectangle(200, 200, vertices);
GetGLError();
// Create colour buffer
GLfloat *colors;
size_t color_size;
AllocateVertexBuffer(4, 4, &colors, &color_size);
CDMeshColorsCreateGrey(0.0, 4, colors);
// Create Texture UV Coordinates
GLfloat *texture;
size_t texture_size;
AllocateVertexBuffer(2, 4, &texture, &texture_size);
CDMeshVertexesCreateRectangle(200, 200, texture);
// Allocate the vertex VBO
glGenBuffers(1, &memoryPointer);
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glBufferData(GL_ARRAY_BUFFER, vertex_size, vertices, GL_STATIC_DRAW);
// Allocate the colour VBO
glGenBuffers(1, &colourMemoryPointer);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glBufferData(GL_ARRAY_BUFFER, color_size, colors, GL_STATIC_DRAW);
// Allocate the texture VBO
glGenBuffers(1, &texPointer);
glBindBuffer(GL_ARRAY_BUFFER, texPointer);
glBufferData(GL_ARRAY_BUFFER, texture_size, texture, GL_STATIC_DRAW);
Rendering and Deleting VBO and Data
// Enable client states for drawing the various arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Bind each buffer and use the VBO's to draw
glBindBuffer(GL_ARRAY_BUFFER, memoryPointer);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colourMemoryPointer);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, texPointer);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
// RENDER!
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// Disale client states as were done with them.
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
GetGLError();
// Delete buffers when they arent being used.
glDeleteBuffers(1, &memoryPointer);
glDeleteBuffers(1, &colourMemoryPointer);
glDeleteBuffers(1, &myTextureName);
glGenTextures(GL_TEXTURE_RECTANGLE_ARB, 0);
// Free vertexes when done using them
free(vertices);
free(colors);
free(texture);