I'm trying to write some code that will render a texture onto a simple square, but have been having a lot of trouble getting it to work. I downloaded some example source code for texture mapping here and compiled it and it seems to do texture mapping fine onto their cylinder. Then, I added some of my code to see if it would render the texture onto my square, but it just textures it with a solid color that seems to be halfway between red and black instead of a checkerboard like it appears on the cylinder. Here is the code I added, right after the call to gluCylinder on the first pass:
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(1,0);
glVertex2f(1, -1);
glTexCoord2f(1, 1);
glVertex2f(1, 1);
glTexCoord2f(0,1);
glVertex2f(-1, 1);
glEnd();
Is there any reason why textures would render normally on the cylinder but not on my quad?
The example code is enabling automatic texture coordinate generation, so your glTexCoord2f calls are being ignored. The automatic generation is being projected onto a Z plane. Since your quad is a Y plane, it's essentially just stretching one pixel of your texture across the entire quad.
To get it to work, disable the automatic texture generation before your glBegin, and then re-enable it after the glEnd.
i.e.:
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(1,0);
glVertex2f(1, -1);
glTexCoord2f(1, 1);
glVertex2f(1, 1);
glTexCoord2f(0,1);
glVertex2f(-1, 1);
glEnd();
glEnable (GL_TEXTURE_GEN_S);
glEnable (GL_TEXTURE_GEN_T);
Alternatively, you could set the automatic texture generation to project on the Y plane, and omit the glTexCoord2f calls, and then set it back to Z when you're done:
float zPlane[4] = {0., 0., 1., 0.};
float yPlane[4] = {0., 1., 0., 0.};
glTexGenfv (GL_T, GL_OBJECT_PLANE, yPlane);
glBegin(GL_QUADS);
glVertex2f(-1, -1);
glVertex2f(1, -1);
glVertex2f(1, 1);
glVertex2f(-1, 1);
glEnd();
glTexGenfv (GL_T, GL_OBJECT_PLANE, zPlane);
Related
I'm adding transformations to my C OpenGL program. I'm using CGLM as my maths library. The program has no warnings or errors. Still however, when I compile and run the program, I get a distorted version of my intended image (it was not distorted before adding transformations).
The following is my program's main loop:
// Initialize variables for framerate counting
double lastTime = glfwGetTime();
int frameCount = 0;
// Program loop
while (!glfwWindowShouldClose(window)) {
// Calculate framerate
double thisTime = glfwGetTime();
frameCount++;
// If a second has passed.
if (thisTime - lastTime >= 1.0) {
printf("%i FPS\n", frameCount);
frameCount = 0;
lastTime = thisTime;
}
processInput(window);
// Clear the window
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Bind textures on texture units
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
// Create transformations
mat4 transform = {{1.0f}};
glm_mat4_identity(transform);
glm_translate(transform, (vec3){0.5f, -0.5f, 0.0f});
glm_rotate(transform, (float)glfwGetTime(), (vec3){0.0f, 0.0f, 1.0f});
// Get matrix's uniform location and set matrix
shaderUse(myShaderPtr);
GLint transformLoc = glGetUniformLocation(myShaderPtr->shaderID, "transform");
// mat4 transform;
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, (float*)transform);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window); // Swap the front and back buffers
glfwPollEvents(); // Check for events (mouse movement, mouse click, keyboard press, keyboard release etc.)
}
The Program is up on github here if you'd like to check out the full code.
The Output of the program is this (The square also rotates):
However, the intended output of the program is the penguin at 20% opacity on top and the box at 100% opacity underneath the penguin.
In the vertex shader, the location of the texture coordinate is 1:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
However, when you specify the vertices, location 1 is used for the color attribute and position 2 for the text coordinates:
// Colour attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// Texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
Remove the color attribute and use location 1 for the texture coordinates. e.g.:
// Texture coord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(1);
Looking at your source code, you're passing in three attributes (position, color and texture coordinates), but your vertex shader only takes two.
Removing the color attribute and instead passing the texture coordinates as attribute #1 instead of #2 should make it look like intended.
I'm trying to draw text using FreeType2 and OpenGL in C, but it's just rendering a square. I've been following tutorials here, here, and here. This code is running on Red Hat 5.6, which only has OpenGL 1.4.
Here's the code I have. First, I load the font with FreeType. I've printed out the buffer for the character I want to the terminal, and it appears to be loading correctly. I'm omitting some error checks for clarity. Also, I've had to manually transcribe this code, so please ignore any syntax errors if they look like an obvious mistype.
FT_Library ft;
FT_Init_Freetype(&ft);
FT_Face face;
FT_New_Face(ft, fontpath, 0, &face);
Ft_Set_Pixel_Sizes(face, 0, 16);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
FT_Load_Char(face, c, FT_LOAD_RENDER);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_INTENSITY,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer);
FT_Done_Face(face);
FT_Done_Freetype(ft);
As previously stated, if I loop over the rows and width of the buffer and print the values they look good. I think the call to glTexImage2D is what I want, considering each pixel is a binary intensity value.
The code to draw the symbol is below, but it doesn't seem to work. Instead it just draws a rectangle:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glColor3f(1,1,1);
GLfloat x = 0;
GLfloat y = 0;
GLfloat w = 5;
GLfloat h = 5;
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex2f(x,y);
glTexCoord2f(1,0);
glVertex2f(x+w,y);
glTexCoord2f(1,1);
glVertex2f(x+w,y+h);
glTexCoord2f(0,1);
glVertex2f(x,y+h);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
At this point I'm at a loss. I've read the OpenGL documentation and I don't see anything obviously wrong. Can someone tell me what I'm missing?
I found the solution after a lot of trial and error. OpenGL 1.4 requires textures to be a power of two. I allocated a temporary array and used that. Also the GL_INTENSITY setting didn't seem to work so I manually made a RGBA array.
I currently have a cylinder
glPushMatrix();
glTranslatef(cylinder->pos[0], cylinder->pos[1], cylinder->pos[2]);
glRotatef(cylinder->angle, -1.0, 0, 0);
gluDisk(quad, 0.0, cylinder->radius, 300, 90);
gluCylinder(quad, cylinder->radius, cylinder->radius, cylinder->height, 30, 1);
gluDeleteQuadric(quad);
glPopMatrix();
but it only renders half of a cylinder instead of the whole thing (the half coming towards the view). Second issue is I don't know how to close the cylinder. The gludisk only closes the bottom of the cylinder and I'm not sure how to close the top side.
If I understand what you're describing, it sounds like you might have back face culling enabled. Do you have a glEnable(GL_CULL_FACE) call in your code? This will eliminate all polygons that face away from you. In any case, once you draw a cylinder that is closed at both sides, it will be fine to keep it enabled.
You can close the cylinder at the top with another gluDisk() call, after applying a translation that moves it to (0, 0, height). For correctness, I believe you need to rotate the disk that closes the cylinder at the bottom. Otherwise it will face to the inside of the cylinder instead of to the outside, which affects the normals, and would get it eliminated by back face culling when it should be visible.
For the full thing, it should look something like this (untested):
glPushMatrix();
glTranslatef(cylinder->pos[0], cylinder->pos[1], cylinder->pos[2]);
glRotatef(cylinder->angle, -1.0f, 0.0f, 0.0f);
gluCylinder(quad, cylinder->radius, cylinder->radius, cylinder->height, 30, 1);
glPushMatrix();
glTranslatef(0.0f, 0.0f, cylinder->height);
gluDisk(quad, 0.0f, cylinder->radius, 30, 1);
glPopMatrix();
glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
gluDisk(quad, 0.0f, cylinder->radius, 30, 1);
gluDeleteQuadric(quad);
glPopMatrix();
I have the two methods hich are doing the same thing. Now I am wondering what is their differences and which one can perform faster.
Here are the methods:
1th Method
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f( 0, 0); glVertex2f( x, y);
glTexCoord2f( 1, 0); glVertex2f( x+texWidth, y);
glTexCoord2f( 1, 1); glVertex2f( x+texWidth, y+texHeight);
glTexCoord2f( 0, 1); glVertex2f( x, y+texHeight);
glEnd();
x++; y++;
2th Method
glPushMatrix();
glTranslatef(x, y, 0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f( 0, 0); glVertex2f( 0.0f, 0.0f);
glTexCoord2f( 1, 0); glVertex2f( 1.0f, 0.0f);
glTexCoord2f( 1, 1); glVertex2f( 1.0f, 1.0f);
glTexCoord2f( 0, 1); glVertex2f( 0.0f, 1.0f);
glEnd();
glPopMatrix();
x++; y++;
Regarding performance, you are using immediate mode, which is slow anyway (its the "old" way of doing things; unfortunately most OpenGL tutorials on the web are hopelessly outdated). Use buffers (gpu-side) like VBOs and VAOs if you really care about performance.
A nice modern tutorial is http://open.gl/ which introduces VBOs here: http://open.gl/drawing
The second method is alot faster, because it is translating the whole matrix, and doesn't do many calculations as it does in method one.
The second method is a lot faster, because it translates the whole QUAD matrix with less calculations.
I drew two rectangles in my scene, and now I'm trying to rotate one rectangle around the other.
When I press the "Left key" my first rectangle moves in direction to the other, but I don't have the effect of rotate because it is only moving in a straight line in direction of the other rectangle.
How do I change the Z direction of the first rectangle?
tl;dr: It's like a solar system, but I don't understand how can I have the depth effect.
I'm using GLUT and OpenGL.
EDIT: More Info:
This is my current code (function that shows the scene):
void RenderScene(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glPushMatrix();
glTranslatef(-70.0f, 0.0f, 0.0f);
glRectf(-25.0f, 25.0f, 25.0f, -25.0f);
glPopMatrix();
glColor3f(1.0f, 1.0f, 0.0f);
glPushMatrix();
glTranslatef(xCor, 0.0f, 0.0f);
glRectf(-25.0f, 25.0f, 25.0f, -25.0f);
glPopMatrix();
glFlush();
}
And a image to help:
Please enable depth test to hide objects beyond other objects.
Give a high value z vaue for the far object.
glEnable( GL_DEPTH_TEST );
glClear( GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(-70.0f, 0.0f, 0.0f);
glRectf(-25.0f, 25.0f, 25.0f, -25.0f);
glPopMatrix();
glColor3f(1.0f, 1.0f, 0.0f);
glPushMatrix();
glTranslatef(xCor, 0.0f, 0.0f);
glRectf(-25.0f, 25.0f, 25.0f, -26.0f); // Z value of behind object is set far from eye
glPopMatrix();
What you want to do is moderately complicated.
The only way I know to locate rectangles in 3-space is to build them using glVertex3f() like this:
glBegin(GL_QUADS);
glVertex3f(x0, y0, z0);
glVertex3f(x1, y1, z1);
glVertex3f(x2, y2, z2);
glVertex3f(x3, y3, z3);
glEnd();
Your "solar system" will have to be located in screen coordinates: X->left/right, Y->up/down, Z->into/out of screen. To create the effect of orbiting, you'll have to recalculate all four X and Z for each movement increment.
I also suggest using gluLookAt() if you want to see a different view.
The man page for glPerspective() says that zNear is always positive but you've given it a negative number. I'd leave that line commented out until I saw some orbiting.
HTH.