Before adding a perspective matrix (orthographic or perspective) my object would print out completely fine, but after adding them i can no longer view my object. I have debugged the program enough to know that the object's normal drawing procedures are being used; however i do not know whether it is being deleted/not loaded, or if it is simply out of view. I've included where i declared the matrices and my animation loop. Any help would be much appreciated!
//enables matrix uniform
GLuint uTransform = glGetUniformLocation(mProgram, "u_transform");
//enables depth testing
glEnable(GL_DEPTH_TEST);
//creates aspect ratio variable
float aspect = 500.0f / 500.0f;
//enables projection matrix
glm::mat4 pmat = glm::perspective(70.0f, aspect, 0.01f, 1000.0f);
//enables view matrix
glm::vec3 eye(0, -5, 2);
glm::vec3 center(0, 0, 0);
glm::vec3 up(0, 0, 1);
glm::mat4 vmat = glm::lookAt(eye, center, up);
while (!glfwWindowShouldClose(mWindow)) //animation loop
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
tmat = pmat * vmat * tmat;
glUniformMatrix4fv(uTransform, 1, GL_FALSE, glm::value_ptr(tmat)); //sets data type of matrix
for(int i = 0; i <= numberofshapes; i++)
{
glBindVertexArray(shapes[i].vao);
glDrawArrays(shapes[i].drawtype, 0, shapes[i].numOfvertices);
}
if(w==true){
tmat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.001f, 0.0f)) * tmat;
}if(a==true){
tmat = glm::translate(glm::mat4(1.0f), glm::vec3(-0.001f, 0.0f, 0.0f)) * tmat;
}if(s==true){
tmat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -0.001f, 0.0f)) * tmat;
}if(d==true){
tmat = glm::translate(glm::mat4(1.0f), glm::vec3(0.001f, 0.0f, 0.0f)) * tmat;
}if(r==true){
tmat = glm::rotate(glm::mat4(1.0f), glm::radians(0.1f), glm::vec3(0.0f, 1.0f, 0.0f)) * tmat;
}
glfwSwapBuffers(mWindow);
counter+=1;
glfwPollEvents();
}
Following the documentation of glm::perspective, the filed of view angle has to be in radians not in degrees (since glm version 0.9.4).
Convert the angle from degrees to radians:
glm::perspective(glm::radians(70.0f), aspect, 0.01f, 1000.0f);
With the code
tmat = pmat * vmat * tmat;
glUniformMatrix4fv(uTransform, 1, GL_FALSE, glm::value_ptr(tmat));
you are continually concatenating the view and projection matrix to the final model view projection matrix in every frame.
Change it to:
glm::mat4 mvp = pmat * vmat * tmat;
glUniformMatrix4fv(uTransform, 1, GL_FALSE, glm::value_ptr(mvp));
Related
The output of this code is 25 cubs rotating .
The problem that I'm facing is the location of each cubes I don not know how to make them be in one line , Like for example every 5 cubes in one line and so on.
Note : I have added the Positions of cubes.
glm::vec3 cubePositions[] = {
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3(2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3(1.3f, -2.0f, -2.5f),
glm::vec3(1.5f, 2.0f, -2.5f),
glm::vec3(1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
while (!glfwWindowShouldClose(mainWindow))
{
glfwPollEvents();
glClearColor(0.0f, 0.1f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Camera transformation
glm::mat4 projection = glm::mat4(1.0f);
glm::mat4 view = glm::mat4(1.0f);
projection = glm::perspective(glm::radians(45.0f), (float)WIDTH / (float)HEIGHT, 0.1f, 100.0f);
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
//Get uniform locations
GLint viewlLoc = glGetUniformLocation(ourShader.Program, "view");
glUniformMatrix4fv(viewlLoc, 1, GL_FALSE, glm::value_ptr(view));
GLint projlLoc = glGetUniformLocation(ourShader.Program, "projection");
glUniformMatrix4fv(projlLoc, 1, GL_FALSE, glm::value_ptr(projection));
// Call Shader Program
ourShader.Use();
glBindVertexArray(VAO);
for(unsigned int i = 0; i < 25; i++)
{
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, cubePositions[i]);
float angle = 20.0f * i;
angle = glfwGetTime() * 25.0f;
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glBindVertexArray(0);
glfwSwapBuffers(mainWindow);
glfwPollEvents();
}
Use glm::translate to add a translation to the model matrix of each individual cube, dependent on the index of the cube. e.g.:
for(unsigned int i = 0; i < 25; i++)
{
float dist = ; // distance between the cubes
float x = (i % 5) * dist;
float y = (i / 5) * dist;
float angle = 20.0f * i;
angle = glfwGetTime() * 25.0f;
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, glm::vector3(x, y, 0.0f));
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
Note, you've to define the distance (dist) between the cubes.
Note, the concatenation (multiplication *) of matrices is not Commutative.
If you want to rotate the entire block of cubes, then you've to do the translation before the rotation:
model = rotate * translate
Since glm::rotate respectively glm::translate, define a matrix and multiply the input matrix by the new matrix, glm::rotate has to be done before glm::translate:
glm::mat4 model = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
model = glm::translate(model, glm::vector3(x, y, 0.0f));
You can use the algorithm to calculate the cubePositions:
#include <vector>
std::vector<glm::vec3> cubePositions;
for(unsigned int i = 0; i < 25; i++)
{
float dist = 5.0f; // distance between the cubes
float x = (i % 5) * dist;
float y = (i / 5) * dist;
cubePositions.push_back(glm::vec3(x, y, 0.0f));
}
I want to rotate my camera around the scene and an object which is in the center. I've tried doing it this way:
glm::mat4 view;
float radius = 10.0f;
float camX = sin(SDL_GetTicks()/1000.0f) * radius;
float camZ = cos(SDL_GetTicks()/1000.0f) * radius;
view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glUniformMatrix4fv(glGetUniformLocation(shader, "viewingMatrix"), 1, false, &view[0][0]);
but my object loads up further away on the screen and the object rotates around the scene, not the camera.
That's my vertex shader:
void main()
{
FragPos = vec3(modelMatrix * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(modelMatrix))) * aPos;
TexCoord = aTexture;
vec4 transformedPosition = projectionMatrix * viewingMatrix * vec4(FragPos, 1.0f);
gl_Position = transformedPosition;
}
How do I make it such that the camera is the one rotating around in the scene without the object rotating around?
I'm following this tutorial and I'm trying to work out the what happens in the first animation.
https://learnopengl.com/Getting-started/Camera
modelMatrix
glm::mat4 modelMat(1.0f);
modelMat = glm::translate(modelMat, parentEntity.position);
modelMat = glm::rotate(modelMat, parentEntity.rotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
modelMat = glm::rotate(modelMat, parentEntity.rotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
modelMat = glm::rotate(modelMat, parentEntity.rotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
modelMat = glm::scale(modelMat, parentEntity.scale);
int modelMatrixLoc = glGetUniformLocation(shader, "modelMatrix");
glUniformMatrix4fv(modelMatrixLoc, 1, false, &modelMat[0][0]);
The target of the view (2nd parameter of glm::lookAt) should be the center of the object. The position of the object (and the center of the object) is changed by the model matrix (modelMatrix) in the vertex sahder.
You have to add the world position of the object to the 1st and 2nd parameter of glm::lookAt. The position of the object is the translation of the model matrix.
Further the object is to far away from the camera, because the radius is to large.
To solve your issue, the code has to look somehow like this:
glm::mat4 view;
float radius = 2.0f;
float camX = sin(SDL_GetTicks()/1000.0f) * radius;
float camZ = cos(SDL_GetTicks()/1000.0f) * radius;
view = glm::lookAt(
glm::vec3(camX, 0.0f, camZ) + parentEntity.position,
parentEntity.position,
glm::vec3(0.0f, 1.0f, 0.0f));
glUniformMatrix4fv(
glGetUniformLocation(shader, "viewingMatrix"), 1, false, glm::value_ptr(view));
I created a sphere floating above a ground. The sphere is centered around (0,0,0). I have set up a camera with a twist, elevation, azimuth as well as moving in closer and farther from the sphere. The problem I have is that the sphere is always drawn on top of the ground. For example, if I move the camera below the ground I should see the ground be drawn on top of the sphere but that's not the case. Here are my ground and draw functions.
void init_ground()
{
GLfloat x = -static_cast<GLfloat>(NUM_GROUND_LINES/2);
GLfloat z = -static_cast<GLfloat>(NUM_GROUND_LINES/2);
for(int i=0; i<NUM_GROUND_LINES*2; i += 2)
{
GLfloat x = NUM_GROUND_LINES/2;
glm::vec3 vertex1 = glm::vec3(-x, -4.0, z);
glm::vec3 vertex2 = glm::vec3(x, -4.0, z);
ground[i] = vertex1;
ground[i+1] = vertex2;
z += 1.0;
}
for(int i=NUM_GROUND_LINES*2; i<NUM_GROUND_LINES*4; i += 2)
{
GLfloat z = NUM_GROUND_LINES/2;
glm::vec3 vertex1 = glm::vec3(x, -4.0, -z);
glm::vec3 vertex2 = glm::vec3(x, -4.0, z);
ground[i] = vertex1;
ground[i+1] = vertex2;
x += 1.0;
}
}
glm::vec3 cameraPos = glm::vec3(0.0, 0.0, 3.0);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
void draw()
{
glm::mat4 view;
glm::mat4 projection;
glm::mat4 model;
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
view = glm::rotate(view, glm::radians(GLfloat(twist)), glm::vec3(0.0, 0.0, 1.0));
view = glm::rotate(view, glm::radians(GLfloat(elevation)), glm::vec3(1.0, 0.0, 0.0));
view = glm::rotate(view, glm::radians(GLfloat(azimuth)), glm::vec3(0.0, 0.0, 1.0));
projection = glm::perspective(45.0f, (GLfloat)WIDTH/(GLfloat)HEIGHT, 0.1f, 100.0f);
glUseProgram(program_ground);
GLint ground_proj_loc = glGetUniformLocation(program_ground, "projection");
GLint ground_view_loc = glGetUniformLocation(program_ground, "view");
GLint ground_model_loc = glGetUniformLocation(program_ground, "model");
glUniformMatrix4fv(ground_proj_loc, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(ground_view_loc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(ground_model_loc, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(vao_ground);
glDrawArrays(GL_LINES, 0, NUM_GROUND_LINES*2*4);
glBindVertexArray(0);
glUseProgram(program_sphere);
GLint sphere_model_loc = glGetUniformLocation(program_sphere, "model");
GLint sphere_view_loc = glGetUniformLocation(program_sphere, "view");
GLint sphere_proj_loc = glGetUniformLocation(program_sphere, "projection");
glUniformMatrix4fv(sphere_view_loc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(sphere_proj_loc, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(sphere_model_loc, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(vao_sphere);
glDrawArrays(GL_LINE_LOOP, 0, 342);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
To be able to remove hidden superficies, you need to enable the Depth Test.
To do that, first you must ask, at the context creation time, a buffer to store the relative z positional value of a vertex, in relation to the camera. If you are using GLFW library, this creation is done automatically.
The second step is to enable the depth test itself. To do that, you need to call:
glEnable(GL_DEPTH_TEST);
somewhere before you call your draw functions.
And, at last, at every frame draw, you must clear you depth buffer, calling:
glClear(GL_DEPTH_BUFFER_BIT);
but usually it is called as:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
to clear the color buffer as well.
I'm trying to model the Solar System and I'm experiencing the Fish-eyes effects.
As you can see from the picture, the sun is at the centre, the Earth is translated 20 units to the x-axis and it doesn't look like a sphere anymore.
In glm::lookAt function, I set the field of view (is this FoVx?, I read from wiki, this is horizontal field of view so I think this is FoVx.) to be 80 degree, aspect ratio is 5.4f / 3.0f (most of application set the aspect ratio to be 4/3 but if I use this ratio, these planets look exactly like an ellipse!).
So how can I solve this problem? As the Earth would be orbiting around the Sun, and it should be always be a sphere at any angle and distance of view. Maybe I haven't completely understand the perspective, view matrix etc. Really need some help.
Here is the code which I used to render the Sun and the Earth:
void renderSun(int i){
glPushMatrix();
glLoadIdentity();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_ID[0]);
glUniform1i(texture_Location, 0);
glm::mat4 Projection = glm::perspective(90.0f, 5.4f / 3.0f, 1.0f, 100.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(0, 30, 1),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);
/* Animations */
GLfloat angle = (GLfloat) (i);
//View = glm::translate(View, glm::vec3(-2.0f, 0.0f, 0.0f));
View = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
/* ******* */
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * View * Model;
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "mvpMatrix"), 1, GL_FALSE, glm::value_ptr(MVP));
glDrawElements(GL_TRIANGLES, numsToDraw, GL_UNSIGNED_INT, NULL);
glPopMatrix();
}
void renderEarth(int i){
glPushMatrix();
glLoadIdentity();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_ID[3]);
glUniform1i(texture_Location, 0);
//glm::mat4 Projection = glm::ortho(0.f, 800.f, 0.f, 400.f, -5.f, 5.f );
glm::mat4 Projection = glm::perspective(80.0f, 5.4f / 3.0f, 1.0f, 100.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(0, 30, 2),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);
/* Animations */
GLfloat angle = (GLfloat) (i);
View = glm::translate(View, glm::vec3(30.0f, 0.0f, 0.0f));
//View = glm::scale(View, glm::vec3(4.0f, 5.0f, 4.0f));
View = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
/* ******* */
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * View * Model;
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "mvpMatrix"), 1, GL_FALSE, glm::value_ptr(MVP));
glDrawElements(GL_TRIANGLES, numsToDraw, GL_UNSIGNED_INT, NULL);
glPopMatrix();
}
I'm modelling the solar system and testing the orbit of the Earth around the Sun, using orthogonal projection.
The starting point of the Earth is to the right of the Sun, direction of moving is to the left hand side. But the Earth is not completely rendered when it is in front of the Sun and when go further behind the Sun, as you can see from 3 images below:
Starting point:
Next frame:
Final frame:
Can some one explain what exactly happening here? I think this is the cull face problem, I tried:
glEnable(GL_CULL_FACES);
glCullFace(GL_FRONT);
It doesn't work actually.
This is my code:
// global vars
int width = 1820, height = 960;
#define CENTRE_X static_cast<float>(width/2)
#define CENTRE_Z static_cast<float>(-height/2)
#define EARTH_SIZE glm::vec3(30.0f, 40.0f, 30.0f)
#define SUN_SIZE EARTH_SIZE*3.0f
void renderSun(int i){
glPushMatrix();
glLoadIdentity();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_ID[0]);
glUniform1i(texture_Location, 0);
glm::mat4 Projection = glm::ortho(0.0f, static_cast<float>(width), 0.0f, static_cast<float>(height), 0.0f, 100.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(0, 120, 1),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);
/* Animations */
GLfloat angle = (GLfloat) (i);
View = glm::translate(View, glm::vec3(static_cast<float>(width/2), 0.0f, static_cast<float>(-height/2)));
View = glm::scale(View, SUN_SIZE);
View = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
/* ******* */
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * View * Model;
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "mvpMatrix"), 1, GL_FALSE, glm::value_ptr(MVP));
glDrawElements(GL_TRIANGLES, numsToDraw, GL_UNSIGNED_INT, NULL);
glPopMatrix();
}
void renderEarth(int i){
glPushMatrix();
glLoadIdentity();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_ID[3]);
glUniform1i(texture_Location, 0);
glm::mat4 Projection = glm::ortho(0.0f, static_cast<float>(width), 0.0f, static_cast<float>(height), 0.0f, 100.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(0, 150, 1),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);
/* Animations */
GLfloat angle = (GLfloat) (i);
View = glm::translate(View, glm::vec3(cos(orbitPos)*150, sin(orbitPos)*150, 0.0f));
View = glm::translate(View, glm::vec3(CENTRE_X, 0.0f, CENTRE_Z));
View = glm::scale(View, EARTH_SIZE);
View = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
/* ******* */
glm::mat4 Model = glm::mat4(1.0f);
orbitPos += 0.005;
glm::mat4 MVP = Projection * View * Model;
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "mvpMatrix"), 1, GL_FALSE, glm::value_ptr(MVP));
glDrawElements(GL_TRIANGLES, numsToDraw, GL_UNSIGNED_INT, NULL);
glPopMatrix();
}
You are using inconsistent View matrices, your code is essentially rotating the view of the earth, which causes it to move relative to the sun. This is very unusual way to do things, and is probably the cause of your problems. It is (presumably) causing the models to collide in clip space, and intersect with one another. You should instead use the same View matrix for both, and modify the Model matrix for the earth model. Keeping the renderSun method the same, you could do this by modifying renderEarth:
void renderEarth(int i){
//...
/* Animations */
GLfloat angle = (GLfloat) (i);
glm::mat4 M0 = glm::translate(View, glm::vec3(cos(orbitPos)*150, sin(orbitPos)*150, 0.0f));
glm::mat4 M1 = glm::translate(View, glm::vec3(CENTRE_X, 0.0f, CENTRE_Z));
glm::mat4 M2 = glm::scale(View, EARTH_SIZE);
glm::mat4 M3 = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
/* ******* */
orbitPos += 0.005;
glm::mat4 MVP = Projection * View * M3 * M2 * M1 * M0;
// ...