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.
Related
I want to draw an isometric cube such as below so I can get straight edge lines for 3d graphing. The third pic is an example of what I want - straight lines on the outer cube. From experiment this doesn't work with 3D using a perspective transform.
Off the infographic I tried drawing what would be the bottom square (shear 30, rotate -30) but its still a bit off.
void draw_outer()
{
int ii;
int w, h;
float equiv = 0.0f;
Matrix transform = IDENTITY_MATRIX;
w = glutGet(GLUT_WINDOW_WIDTH);
h = glutGet(GLUT_WINDOW_HEIGHT);
equiv = h/(float)w;
//vert scale
ScaleMatrix(&projection, 1.0f, .861f, 1.0f);
//shear x adjusted for aspect ratio
ConstructShearMatrixX(&projection, .5236f * equiv);
//rotation
//fix aspect ratio
RotateAboutZ(&projection, -.5236f);
ScaleMatrix(&projection, equiv, 1.0f, 1.0f);
glUniformMatrix4fv(uniform_ids[0], 1, GL_FALSE, model.m);
glUniformMatrix4fv(uniform_ids[1], 1, GL_FALSE, view.m);
glUniformMatrix4fv(uniform_ids[2], 1, GL_FALSE, projection.m);
}
My vertex shader is just glPosition = (Projection * View * Model * position.xyz).
I try program a simple industrie-roboter arm in C + OpenGl 3.3. I have 3 simple models set up in a single buffer element (Vertex, Index and ColorBuffer) and i can rotate/translate the whole thing around. However, i am unable to translate/rotate a single section.
The Vertex Data is saved in an HEADER file. The Red segment is called "base", blue is "seg1" and green is "seg2". I loaded them into the buffer like so.
size = sizeof(base_verticies) + sizeof(seg1_verticies) + sizeof(seg2_verticies);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(base_verticies), base_verticies);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(base_verticies), sizeof(seg1_verticies), seg1_verticies);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(base_verticies)+sizeof(seg1_verticies), sizeof(seg2_verticies), seg2_verticies);
size = sizeof(base_indices) + sizeof(seg1_indices) + sizeof(seg2_indices);
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, 0, GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(base_indices), base_indices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, sizeof(base_indices), sizeof(seg1_indices), seg1_indices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, sizeof(base_indices)+sizeof(seg1_indices), sizeof(seg2_indices), seg2_indices);
size = sizeof(base_colors) + sizeof(seg1_colors) + sizeof(seg2_colors);
glGenBuffers(1, &CBO);
glBindBuffer(GL_ARRAY_BUFFER, CBO);
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_STATIC_DRAW);
glBufferSubData( ... ); ...; // same for colors
I can now draw those section seperatly like so
//base (red)
glDrawElements(GL_TRIANGLES, sizeof(base_indices)/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
//seg1 (blue)
glDrawElements(GL_TRIANGLES, sizeof(base_indices)/sizeof(GLushort), GL_UNSIGNED_SHORT, (void*)sizeof(base_indices));
//seg2 (green)
glDrawElements(GL_TRIANGLES, sizeof(base_indices)/sizeof(GLushort), GL_UNSIGNED_SHORT, (void*)(sizeof(base_indices)+sizeof(seg1_indices)));
But my Problem is, that I can only rotate and translate the whole thing, but not single sections. I do rotate the whole model in the onIdle() function like so:
float angle = 1;
float RotationMatrixAnim[16];
SetRotationY(angle, RotationMatrixAnim);
/* Apply model rotation */
MultiplyMatrix(RotationMatrixAnim, InitialTransform, ModelMatrix);
MultiplyMatrix(TranslateDown, ModelMatrix, ModelMatrix);
Is there a way to modify the position,translation,... for single segments? The only tutorials I find are from legacy OpenGl with glPushMatrix() and glPopMatrix, which are deprecated.
Is it a good idea to store those Segments in the same buffer?
Thanks in advance for any help & precious time of yours.
Thanks to #Rabbid76 suggestion i was able to solve my issue.
I made 3 ModelMatrices, that is one for each section
float ModelMatrix[3][16]; /* Model matrix */
I rotate/translate the section i want like so
float RotationMatrixSeg2[16];
SetRotationY(angle, RotationMatrixSeg2);
MultiplyMatrix(RotationMatrixSeg2, InitialTransform, ModelMatrix[2]);
MultiplyMatrix(TranslateDown, ModelMatrix[2], ModelMatrix[2]);
I set the corresbonding ModelMatrix befor drawing the section.
/* Draw each section */
glUniformMatrix4fv(RotationUniform, 1, GL_TRUE, ModelMatrix[0]);
glDrawElements(GL_TRIANGLES, sizeof(base_indices)/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
glUniformMatrix4fv(RotationUniform, 1, GL_TRUE, ModelMatrix[1]);
glDrawElements(GL_TRIANGLES, sizeof(base_indices)/sizeof(GLushort), GL_UNSIGNED_SHORT, (void*)sizeof(base_indices));
glUniformMatrix4fv(RotationUniform, 1, GL_TRUE, ModelMatrix[2]);
glDrawElements(GL_TRIANGLES, sizeof(base_indices)/sizeof(GLushort), GL_UNSIGNED_SHORT, (void*)(sizeof(base_indices)+sizeof(seg1_indices)));
In my application (running on Mali-400 GPU) I am using OpenGL ES 2.0 to draw UI. For that I setup orthogonal projection matrix and use 2D vectors to describe the geometry (only x, y attributes).
So my vertex structure looks something like this:
struct my_vertext {
struct vec2 pos;
struct unsigned int color;
}
later then I prepare GL context, setup shaders:
vertex:
uniform mat4 matrix;
attribute vec2 pos;
attribute vec4 color;
varying vec4 frag_color;
void main() {
frag_color = color;
gl_Position = matrix * vec4(pos.xy, 0, 1);
};
fragment:
precision mediump float;
varying vec4 frag_color;
void main() {
gl_FragColor = frag_color;
};
and bind them with attribute arrays:
GLuint prog = glCreateProgram(); CHECK_GL;
// create shaders, load source and compile them
...
/// binding with attributes
GLuint attrib_pos, attrib_col, vertex_index = 0;
glBindAttribLocation(prog, vertex_index, "pos"); CHECK_GL;
attrib_pos = vertex_index++;
glBindAttribLocation(prog, vertex_index, "color"); CHECK_GL;
attrib_col = vertex_index++;
// link program
glLinkProgram(prog); CHECK_GL;
glUseProgram(prog); CHECK_GL;
When I render my geometry (for simplicity I am drawing 2 rectangles one behind another) - only the first call to glDrawElements produces an image on the screen (dark gray rectangle), the second (red) - doesn`t.
For rendering I am using Vertex Array Object with 2 bound buffers - one for geometry (GL_ARRAY_BUFFER) and the second one for indices (GL_ELEMENT_ARRAY_BUFFER). All the geometry is placed to this buffers and later is drawn with glDrawElements calls providing needed offsets.
My drawing code:
glBindVertexArray(vao); CHECK_GL;
...
GLuint *offset = 0;
for each UI object:
{
glDrawElements(GL_TRIANGLES, (GLsizei)ui_object->elem_count,
GL_UNSIGNED_SHORT, offset); CHECK_GL;
offset += ui_object->elem_count;
}
This puzzles me a lot since I check each and every return code of glXXX functions and all of them return GL_NO_ERROR. Additionally, I ran my program in Mali Graphics Debugger and the latter hasn`t revealed any problems/errors.
Geometry and indices for both calls (obtained from Mali Graphics Debugger):
First rectangle geometry (which is shown on screen):
0 Position=[30.5, 30.5] Color=[45, 45, 45, 255]
1 Position=[1250.5, 30.5] Color=[45, 45, 45, 255]
2 Position=[1250.5, 690.5] Color=[45, 45, 45, 255]
3 Position=[30.5, 690.5] Color=[45, 45, 45, 255]
Indices: [0, 1, 2, 0, 2, 3]
Second rectangle geometry (which isnt` shown on screen):
4 Position=[130.5, 130.5] Color=[255, 0, 0, 255]
5 Position=[230.5, 130.5] Color=[255, 0, 0, 255]
6 Position=[230.5, 230.5] Color=[255, 0, 0, 255]
7 Position=[130.5, 230.5] Color=[255, 0, 0, 255]
Indices: [4, 5, 6, 4, 6, 7]
P.S.: On my desktop everything works perfectly. I suppose it has something to do with limitations/peculiarities of embedded Open GL.
On my desktop:
$ inxi -F
$ ....
$ GLX Renderer: Mesa DRI Intel Ivybridge Desktop GLX Version: 3.0 Mesa 10.1.3
I know very little of OpenGL ES, but this part looks wrong:
glBindVertexArray(vao); CHECK_GL;
...
GLuint *offset = 0;
for each UI object:
{
glDrawElements(GL_TRIANGLES, (GLsizei)ui_object->elem_count,
GL_UNSIGNED_SHORT, offset); CHECK_GL;
offset += ui_object->elem_count;
}
compared to
glBindVertexArray(vao); CHECK_GL;
...
GLuint offset = 0;
for each UI object:
{
glDrawElements(GL_TRIANGLES, (GLsizei)ui_object->elem_count,
GL_UNSIGNED_SHORT, &offset); CHECK_GL;
offset += ui_object->elem_count;
}
It seems to be the standart that polygon are drawn in a convex shape. See stackoverflow.com/questions/15556929/open-gl-polygon However it is not for me if I choose it to be filled. How can I have my polygon filled while maintaining the shape I defined?
void drawFloor(){
// White
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // GL_LINE works the way I want it too
//glDisable(GL_POLYGON_SMOOTH); // has no effect :(
glBegin(GL_POLYGON);
glColor3f(1.0, 1.0, 1.0);
glVertex3f(0, 0, 0); //0
glVertex3f(2*boxSize, 0, 0); //1
glVertex3f(2 * boxSize, -boxSize, 0); //2
glVertex3f(5 * boxSize, -boxSize, 0); //3
glVertex3f(5 * boxSize, 4 * boxSize, 0); //4
glVertex3f(6 * boxSize, 4 * boxSize, 0); //5
glVertex3f(6 * boxSize, 6 * boxSize, 0); //6
glVertex3f(0 * boxSize, 6 * boxSize, 0); //7
glVertex3f(0 * boxSize, 2 * boxSize, 0); //8
glVertex3f(1 * boxSize, 2 * boxSize, 0); //9
glVertex3f(1 * boxSize, 4 * boxSize, 0); //10
glVertex3f(2 * boxSize, 4 * boxSize, 0); //11
glVertex3f(2 * boxSize, 3 * boxSize, 0); //12
glVertex3f(3 * boxSize, 3 * boxSize, 0); //13
glVertex3f(3 * boxSize, 2 * boxSize, 0); //14
glVertex3f(2 * boxSize, 2 * boxSize, 0); //15
glVertex3f(2 * boxSize, 1 * boxSize, 0); //16
glVertex3f(0, 1 * boxSize, 0); //17
glEnd();
}
This code results in:
http://postimg.org/image/o4wt9ij33/ with GL_LINE
http://postimg.org/image/l31fltgkf/ with GL_FILL
I want only the inside of the polygon filled, keeping the shape of the version with the GL_LINE. I did not expect the output of GL_FILL to be so different.
What I want (created with MS paint):
http:// postimg.org/image/d3gbf613d/
I am using Win7+ Visula studio express2013+ Renderer Intel HD Graphics Version: 3.1.0 - Bulid 8.15.10.2509+ GLSL Version 1.40
Note: This answer shares content with my recent answer to a similar question here: Black out everything outside a polygon. I did not nominate the questions as duplicates because they sound different, and could potentially have different answers, even though this one happens to be mostly the same.
One approach for drawing non-convex polygons is to break them down into triangles. There are a number of algorithms that can do this, which can be found by searching for keywords like "polygon triangulation".
OpenGL has another mechanism that works great for this: stencil buffers. An explanation of this approach is in the Red Book under Drawing Filled, Concave Polygons Using the Stencil Buffer. The main idea is that one can draw a triangle fan with an arbitrary origin and your polygon vertices. The pixels that are inside the polygon will then be drawn an odd number of times, while the pixels outside the polygons are drawn an even number of times. The stencil buffer is used to track the odd/even count.
To outline the main steps:
While setting up the context and drawing surface, make sure that a configuration with a stencil buffer is requested.
During drawing, clear the stencil buffer along with the color buffer, and enable the stencil test.
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
Set up state for the render pass that counts if pixels are rendered an odd/even number of times. Note that this must only write to the stencil buffer, so color writes are disabled. The key part is the GL_INVERT for the stencil op, which flips the stencil value each time a pixel is rendered, which ends up storing the odd/even count in the stencil buffer.
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilFunc(GL_ALWAYS, 0, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT);
glStencilMask(1);
Render a triangle fan with an arbitrary point, e.g. (0.0, 0.0), as the first vertex, and the polygon corners as the remaining vertices. The polygon must be closed, so the first and last polygon corner must be the same. If p1, p2, ... , pN are the polygon corners, the sequence of vertices for the GL_TRIANGLE_FAN draw call is:
(0.0f, 0.0f), p1, p2, ... , pN, p1
A trivial shader can be used for this pass since the color value is not even written.
Enable color writes again, and set up the stencil test attributes to render only pixels that were rendered an odd number of times in the previous pass.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
Draw geometry that covers the entire area of the polygon, and possibly more. This can for example be the triangle fan from step 4, or a bounding box of the polygon. Only the part within the polygon outline will be rendered, the rest is eliminated by the stencil test.
I have a single 640x480 texture that needs to fill the screen. So far, I can make it work with a square texture, but not a rectangular one.
glViewport(0, 0, display->w, display->h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double aspectRatio = (double)display->w / (double)display->h;
if (display->w <= display->h)
glOrtho(-1, 1, -1 / aspectRatio, 1 / aspectRatio, -1, 1);
else
glOrtho(-1 * aspectRatio, 1 * aspectRatio, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
What modifications do I need to make so that it will fit any texture to the screen, regardless of its aspect ratio?
This may have some relevance.
Tiling texture bmp file as texture onto a rectangle in OpenGL?
You may wish to consider ARB extension texture rectangle as an alternative approach to (assuming glTexImage2D?) http://glprogramming.com/red/chapter09.html