I am trying to display two cubes using modern opengl (https://preview.ibb.co/hif8t6/Screenshot_2017_10_31_09_59_27.png). The first cube is displayed by orthographic projection (left) and the second by perspective projection (right). That is working fine but i am unable to get the left cube to go behind the right cube.
Here is the relavant snippet of code
ourShader_ortho.Use();
ourShader_persp.Use();
glm::mat4 model_ortho, model1, model2, model;
glm::mat4 view_ortho, view_persp;
glm::mat4 orthographic;
glm::mat4 perspective;
model1 = glm::rotate(model, (GLfloat)glfwGetTime()*1.0f, glm::vec3(0.5f, 1.0f, 0.0f));
model2 = glm::rotate(model, (GLfloat)glfwGetTime()*1.0f, glm::vec3(0.0f, 1.0f, 0.5f));
model = model1 * model2;
view_ortho = glm::translate(view_ortho, glm::vec3(200.0f, 200.0f, -150.0f));
orthographic = glm::ortho(0.0f, (GLfloat)width, 0.0f, (GLfloat)height, 0.1f, 200.0f);
view_persp = glm::translate(view_persp, glm::vec3(1.0f, 0.0f, -3.0f));
perspective = glm::perspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 200.0f);
GLint modelLoc_ortho = glGetUniformLocation(ourShader_ortho.Program, "model");
GLint viewLoc_ortho = glGetUniformLocation(ourShader_ortho.Program, "view");
GLint projLoc_ortho = glGetUniformLocation(ourShader_ortho.Program, "orthographic");
glUniformMatrix4fv(modelLoc_ortho, 1, GL_FALSE, glm::value_ptr(model_ortho));
glUniformMatrix4fv(viewLoc_ortho, 1, GL_FALSE, glm::value_ptr(view_ortho));
glUniformMatrix4fv(projLoc_ortho, 1, GL_FALSE, glm::value_ptr(orthographic));
glBindVertexArray(VAO_O);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
GLint modelLoc_persp = glGetUniformLocation(ourShader_persp.Program, "model");
GLint viewLoc_persp = glGetUniformLocation(ourShader_persp.Program, "view");
GLint projLoc_persp = glGetUniformLocation(ourShader_persp.Program, "perspective");
glUniformMatrix4fv(modelLoc_persp, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc_persp, 1, GL_FALSE, glm::value_ptr(view_persp));
glUniformMatrix4fv(projLoc_persp, 1, GL_FALSE, glm::value_ptr(perspective));
glBindVertexArray(VAO_P);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
What do i do to get the cube with orthographic projection to go behind the cube with perspective projection?
I'm not a OpenGL programmer but this is what I think.
You are drawing the object twice using the glDrawArrays lines. For the projection matrices they are using your orthographic and perspective matrices.
However these matrices are created using different parameters:
view_ortho = glm::translate(view_ortho, glm::vec3(200.0f, 200.0f, -150.0f));
view_persp = glm::translate(view_persp, glm::vec3(1.0f, 0.0f, -3.0f));
My guess is that you want to unify the translation parameters so that the cubes lie exactly on top of each other.
E.g.
view_ortho = glm::translate(view_ortho, glm::vec3(200.0f, 200.0f, -150.0f));
view_persp = glm::translate(view_persp, glm::vec3(200.0f, 200.0f, -150.0f));
Related
I'm learning the basics of OpenGL and trying to translate a triangle with ortho projection. I don't see what I expect, what am I doing wrong?
My Vertex buffer:
Vertices[0] = Vector3f(-1.0f, -1.0f, 0.0f);
Vertices[1] = Vector3f(1.0f, -1.0f, 0.0f);
Vertices[2] = Vector3f(-1.0f, 1.0f, 0.0f);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
Vertex shader:
#version 330
layout (location = 0) in vec3 Position;
uniform mat4 gMVP;
void main()
{
gl_Position = gMVP * vec4(Position, 1.0);
}
MVP calculation and rendering:
glm::mat4 p = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, -2.0f, 2.0f);
glm::mat4 v = glm::lookAt(glm::vec3(0,0,1), glm::vec3(0,0,0), glm::vec3(0,1,0));
glm::mat4 m = glm::translate(glm::mat4(1.0f), glm::vec3(0.5f, 0.0f, 0.0f));
glm::mat4 MVP = p * v * m;
glUniformMatrix4fv(gMVPLocation, 1, GL_TRUE, &MVP[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
the result:
Shouldn't it just move to the right along the X axis?
The 3rd parameter of glUniformMatrix4fv causes that the matrix will be transposed when it is set to the uniform. OpenGL Mathematics (GLM) constructs the matrices in the same way, as GLSL constructs variables of type mat4.
The matrix has not to be transposed when it is set to the uniform:
glUniformMatrix4fv(gMVPLocation, 1, GL_TRUE, &MVP[0][0]);
glUniformMatrix4fv(gMVPLocation, 1, GL_FALSE, &MVP[0][0]);
In GLSL the vector has to be multiplied to the matrix from the right. See GLSL Programming/Vector and Matrix Operations
I have 25 cubes that i want to rotate each one differently this is my code on both x and y axis
i tried using rand() but it kept rotating them weirdly and all of them rotate in the same directions
this is in the game loop
for (unsigned int i = 0; i < 25; i++)
{
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, cubePositions[i]);
view = glm::translate(model, glm::vec3(0.0f, 0.0f, -10.0f));
float angle = 20.0f * i;
angle = glfwGetTime() * 20.0f;
model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.0f, 0.5f));
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");
glUniformMatrix4fv(projLoc, 1, GL_FALSE,
glm::value_ptr(projection));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
Since there is no actual question, I try to give some comments on the posted code
that could explain the unexpected behavior of the resulting program.
The angle variable is initialised, then assigned immediately with a new
value ; only this new value is relevant, then the cubes should all rotate
at the rate of 20 degrees per second. (this is not a problem)
The view matrix is reassigned with a new value for each object! It is
extremely unlikely that this is what you want.
It's like if, while drawing a single frame, you move the camera in front of
each object being drawn ; if you move the camera and the object the same way,
then everything is displayed at the same place in the rendered frame.
(I think this is the main problem)
You should choose once for all the view matrix (as well as the projection
matrix) for the whole frame.
Some other comments, not directly related:
You should retrieve the uniform locations once for all before the loop
(and even at the beginning of the program) since they won't change as long
as you use the same shader program.
The glUniformMatrix4fv() calls for projection and view should
occur once for all before the loop; only the model matrix changes from
one object to another.
That could look like this
GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");
glm::mat4 projection = ... already known ...
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glm::mat4 view = glm::mat4(1.0f);
// adjust to the layout of your scene
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -10.0f));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
for(unsigned int i = 0; i < 25; i++)
{
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, cubePositions[i]);
// the same rotation rate but a different offset for each object
float angle = 20.0f * i;
angle += std::fmod(glfwGetTime() * 20.0f, 360.0f);
// choose x or y rotation axis
auto axis=(i%2) ? glm::vec3(1.0f, 0.0f, 0.0f) : glm::vec3(0.0f, 1.0f, 0.0f);
model = glm::rotate(model, glm::radians(angle), axis);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
This is my game loop. I know I don't need to declare these variables twice, but I did them just in case:
while (!glfwWindowShouldClose(window))
{
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram);
glm::mat4 view;
view = glm::rotate(view, 50.0f, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 projection;
projection = glm::perspective(-45.0f, float(WIDTH / HEIGHT), 0.1f, 100.0f);
GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLint projLoc = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(VAO);
glm::mat4 model;
model = glm::scale(model, glm::vec3(0.5f, 0.5f, 0.5f));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glUseProgram(shaderProgram2);
glm::mat4 view2;
view2 = translate(view2, glm::vec3(0.0f, 0.0f, -0.6f));
GLint modelLoc2 = glGetUniformLocation(shaderProgram2, "lightmodel");
GLint viewLoc2 = glGetUniformLocation(shaderProgram2, "lightview");
GLint projLoc2 = glGetUniformLocation(shaderProgram2, "lightprojection");
glm::mat4 model2;
model2 = glm::scale(model2, glm::vec3(0.5f, 0.5f, 0.5f));
glUniformMatrix4fv(viewLoc2, 1, GL_FALSE, glm::value_ptr(view2));
glUniformMatrix4fv(projLoc2, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(modelLoc2, 1, GL_FALSE, glm::value_ptr(model2));
glBindVertexArray(lightVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
And this the output:
https://imgur.com/a/arEd7
I'm not clear if glm::perspective() input should be radians or degrees, but I tried both and they all gave the same zoomed-in, non-3D result. I don't know what I'm doing wrong here. I'm doing these according to this tutorial. My body of code looks exactly like the tutorial's save for a few classes that I created myself. What could be the problem here?
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 am trying to draw a basic mesh loaded from an .obj file using stereoscopic 3D rendering on a NVIDIA Quadro 5000. From what I can tell I think I got my left eye and right eye frustums and offsets set accordingly, but my main issue is with writing and clearing the BACK_LEFT and BACK_RIGHT buffers. It seems that it misses the first part completely and only draws the BACK_RIGHT buffer (second part of the rendering loop). If I could get some pointers on how to write/read and clear these buffers in the same frame that would be great. It's a Linux application hence the glXSwap(), not using glut or glew and using glm for maths. Here is my drawing loop:
void GLDraw::Draw()
{
//initialise shader in frame
shader->UseShaderProgram();
//select back_left buffer
glDrawBuffer(GL_BACK_LEFT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//set projection and view for back_left
projectionMatrix = glm::frustum(-xCoord - frustumAssymmetry, xCoord - frustumAssymmetry, -yCoord, yCoord, 0.1f, 200.0f);
projectionMatrix *= glm::translate(glm::mat4(1.0f), glm::vec3(eyeOffset, 0.0f, 0.0f));
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, value_ptr(projectionMatrix));
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]);
//set model matrix for rendering calls
modelMatrix = scale(mat4(1.0f), vec3(0.7, 0.7, 0.5f));
modelMatrix *= translate(mat4(1.0f), vec3(0.0f, 0.0f, 0.0f));
modelMatrix *= rotate(mat4(1.0f), i+=0.04, vec3(0.0f, 1.0f, 0.0f));
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]);
//draw VAO
glBindVertexArray(vikingVAO);
glDrawElements(GL_TRIANGLES, viking_elements.size() * sizeof(viking_elements[0]), GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
//select back_right buffer <-- SEEMS TO ONLY RENDER FROM HERE, MISSING THE FIRST PART
glDrawBuffer(GL_BACK_RIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//set projection and view for back_right
projectionMatrix = glm::frustum(-xCoord + frustumAssymmetry, xCoord + frustumAssymmetry, -yCoord, yCoord, 0.1f, 200.0f);
projectionMatrix *= glm::translate(glm::mat4(1.0f), glm::vec3(-eyeOffset, 0.0f, 0.0f));
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, value_ptr(projectionMatrix));
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]);
//set model matrix for rendering calls
modelMatrix = scale(mat4(1.0f), vec3(0.7, 0.7, 0.5f));
modelMatrix *= translate(mat4(1.0f), vec3(0.0f, 0.0f, 0.0f));
modelMatrix *= rotate(mat4(1.0f), i+=0.04, vec3(0.0f, 1.0f, 0.0f));
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]);
//draw VAO
glBindVertexArray(vikingVAO);
glDrawElements(GL_TRIANGLES, viking_elements.size() * sizeof(viking_elements[0]), GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
//clear shader
shader->ClearShaderProgram();
//swap buffers
glXSwapBuffers(display, win);
}
EDIT: Realised that if I run my application on the right screen it renders the GL_BACK_RIGHT buffer. Running it on the left screen draws the GL_BACK_LEFT.
Any ideas? Monitor settings maybe?