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'm trying to render multiple objects in OpenGL using multiple VAO's and VBO's. To render multiple objects using the same vertices I've done it, but what I want to do is to use different vertices for each object, for example to draw a square and a circle. For a square I only need 6 vertices but for circle I need 360.
I have error with reading or creating the shaders.
Here is the Vertex Shader:
#version 330 core
layout (location = 0) in vec4 position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * position;
}
Fragment Shader:
#version 330 core
layout(location = 0) out vec4 color;
uniform vec4 u_Color;
void main()
{
color = u_Color;
}
The VAO and VBO generating and binding
// Circle
std::vector<VertexFormat> vertices;
for (int i = 0; i < 360; i++)
{
GLfloat angle = i * ((2.0f * 3.14159f) / 360);
vertices.push_back(VertexFormat(glm::vec3(cos(angle) * 100.0f, sin(angle) * 100.0f, 0.0f)));
}
// Pipette object
std::vector<VertexFormat> pipetteVertices;
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 500.0f, injPipette.y + 500.0f, 0.0f))); // 0
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 700.0f, injPipette.y + 500.0f, 0.0f))); // 1
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 700.0f, injPipette.y + 700.0f, 0.0f))); // 2
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 500.0f, injPipette.y + 700.0f, 0.0f))); // 3
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 500.0f, injPipette.y + 500.0f, 0.0f)));
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 700.0f, injPipette.y + 700.0f, 0.0f)));
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexFormat) * 6, &pipetteVertices[0], GL_STATIC_DRAW);
//Position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (GLvoid *)0);
GLuint vao2;
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
GLuint vbo2;
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexFormat) * 360, &vertices[0], GL_STATIC_DRAW);
//Position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (GLvoid *) 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
And the draw call in the rendering loop:
//Get the uniform locations of model, view and projection matrices
modelID = glGetUniformLocation(program, "model");
viewID = glGetUniformLocation(program, "view");
projectionID = glGetUniformLocation(program, "projection");
//View transform
glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 2), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
//Projection transform
//glm::mat4 projection = glm::perspective(45.0f, (GLfloat)screenWidth / (GLfloat)screenHeight, 0.1f, 1000.0f);
glm::mat4 projection = glm::ortho(0.0f, (GLfloat)screenWidth, 0.0f, (GLfloat)screenHeight, 0.1f, 10.0f);
{
glUniformMatrix4fv(viewID, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionID, 1, GL_FALSE, glm::value_ptr(projection));
glm::mat4 translate = glm::translate(glm::mat4(1.0), glm::vec3(100.0f + move_x, 100.0f + move_y, 0.0f));
glm::mat4 rotate = glm::rotate(glm::mat4(1.0), 0.0f, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 scale = glm::scale(glm::mat4(1.0), glm::vec3(1.0f, 1.0f, 2.0f));
glm::mat4 model = translate * rotate * scale;
glUniformMatrix4fv(modelID, 1, GL_FALSE, glm::value_ptr(model));
glUniform4f(color, 0.0f, 0.0f, 1.0f, 1.0f);
//Render
glDrawArrays(GL_TRIANGLE_FAN, 0, 360);
}
{
glUniformMatrix4fv(viewID, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionID, 1, GL_FALSE, glm::value_ptr(projection));
glm::mat4 translate = glm::translate(glm::mat4(1.0), glm::vec3(300.0f + injPipette.x, 300.0f + injPipette.y, 0.0f));
glm::mat4 rotate = glm::rotate(glm::mat4(1.0), 0.0f, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 scale = glm::scale(glm::mat4(1.0), glm::vec3(1.0f, 1.0f, 2.0f));
glm::mat4 model = translate * rotate * scale;
glUniformMatrix4fv(modelID, 1, GL_FALSE, glm::value_ptr(model));
glUniform4f(color, 1.0f, 0.0f, 0.0f, 0.5f);
//Render
glDrawArrays(GL_TRIANGLES, 0, 6);
}
I repeat, to draw multiple objects using the same vertices I've done it. I need to know how to draw multiple objects using the same vertex and fragment shader but different number of vertices. The project is small, just rendering maximum 10 objects in 2D.
Drawing commands such as glDrawArrays process and draw the arrays of generic vertex attribute data specified in the currently bound Vertex Array Object.
This means that you need to bind the correct vertex array object before executing the Draw call:
// [...]
glBindVertexArray(vao2);
glDrawArrays(GL_TRIANGLE_FAN, 0, 360);
// [...]
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
I found a project with the code:
#pragma once
#include "glm\glm.hpp"
struct VertexFormat
{
glm::vec3 position;
VertexFormat(const glm::vec3 &iPos)
{
position = iPos;
}
VertexFormat()
{
}
};
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));
I am trying to integrate 2 programs together.
One displays a 2D hollow red circle
Another is a 3D "planet system". (There are cubes moving/orbiting around a "sun")
I want to get the red circle to display in the "planet system". It is not supposed to move. I have tried integrating the code, but the circle does not appear as I want it to.
I noticed that when I uncomment these sections of code (below), the circle appears, but it moves around just like a planet.
static void init(GLFWwindow* window){
/*------------------------Circle----------------------*/
//// generate vertices of triangle fan
//generate_circle();
//// create VBO and buffer the data
//glGenBuffers(1, &g_VBO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
//glGenBuffers(1, &g_VBO[2]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_colors_circle, GL_STATIC_DRAW);
//// create VAO and specify VBO data
//glGenVertexArrays(1, &g_VAO[1]);
//glBindVertexArray(g_VAO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
/*----------------------------------------------------*/
}
static void render_scene(){
// glBindVertexArray(g_VAO[1]); // make VAO active
//
////Circle 1
// glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//
// glBindVertexArray(g_VAO[0]); // make VAO active
}
And also, my planet system disappears. I'm pretty sure this has something to do with my vertices being multiplied by the matrix in the vertex shader. How can I place the circle without it moving and making my "planets" disappear?
Here is my vertex shader
#version 330 core
// input data (different for all executions of this shader)
in vec3 aPosition;
in vec3 aColor;
// ModelViewProjection matrix
uniform mat4 uModelViewProjectionMatrix;
// output data (will be interpolated for each fragment)
out vec3 vColor;
void main()
{
// set vertex position
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);
// the color of each vertex will be interpolated
// to produce the color of each fragment
vColor = aColor;
}
Here is my main program:
#include <cstdio> // for C++ i/o
#include <iostream>
#include <string>
#include <cstddef>
using namespace std; // to avoid having to use std::
#define GLEW_STATIC // include GLEW as a static library
#include <GLEW/glew.h> // include GLEW
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header)
#include <glm/glm.hpp> // include GLM (ideally should only use the GLM headers that are actually used)
#include <glm/gtx/transform.hpp>
using namespace glm; // to avoid having to use glm::
#include "shader.h"
#define PI 3.14159265
#define MAX_SLICES 50
#define MIN_SLICES 8
#define MAX_VERTICES (MAX_SLICES+2)*3 // a triangle fan should have a minimum of 3 vertices
#define CIRCLE_RADIUS 1.0
#define WINDOW_WIDTH 1500
#define WINDOW_HEIGHT 800
// struct for vertex attributes
struct Vertex
{
GLfloat position[3];
GLfloat color[3];
};
// global variables
GLfloat g_vertices_circle[MAX_VERTICES] = {
0.0f, 0.0f, 0.0f, // try adjusting this value to get rid of red line
0.0f, 0.0f, 0.0f
};
GLfloat g_colors_circle[MAX_VERTICES] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
GLuint g_slices = MAX_SLICES; // number of circle slices
Vertex g_vertices[] = {
// vertex 1
-0.5f, 0.5f, 0.5f, // position
1.0f, 0.0f, 1.0f, // colour
// vertex 2
-0.5f, -0.5f, 0.5f, // position
1.0f, 0.0f, 0.0f, // colour
// vertex 3
0.5f, 0.5f, 0.5f, // position
1.0f, 1.0f, 1.0f, // colour
// vertex 4
0.5f, -0.5f, 0.5f, // position
1.0f, 1.0f, 0.0f, // colour
// vertex 5
-0.5f, 0.5f, -0.5f, // position
0.0f, 0.0f, 1.0f, // colour
// vertex 6
-0.5f, -0.5f, -0.5f,// position
0.0f, 0.0f, 0.0f, // colour
// vertex 7
0.5f, 0.5f, -0.5f, // position
0.0f, 1.0f, 1.0f, // colour
// vertex 8
0.5f, -0.5f, -0.5f, // position
0.0f, 1.0f, 0.0f, // colour
};
GLuint g_indices[] = {
0, 1, 2, // triangle 1
2, 1, 3, // triangle 2
4, 5, 0, // triangle 3
0, 5, 1, // ...
2, 3, 6,
6, 3, 7,
4, 0, 6,
6, 0, 2,
1, 5, 3,
3, 5, 7,
5, 4, 7,
7, 4, 6, // triangle 12
};
GLuint g_IBO = 0; // index buffer object identifier
GLuint g_VBO[3]; // vertex buffer object identifier
GLuint g_VAO[2]; // vertex array object identifier
GLuint g_shaderProgramID = 0; // shader program identifier
GLuint g_MVP_Index = 0; // location in shader
glm::mat4 g_modelMatrix[5]; // object model matrices
glm::mat4 g_viewMatrix; // view matrix
glm::mat4 g_projectionMatrix; // projection matrix
float g_orbitSpeed[5] = { 0.3f, 1.0f, 0.7f, 0.9f, 1.2f }; // for speed of rotation around sun
float g_rotationSpeed[5] = { 0.07f, 0.7f, 3.0f, 5.0f, 1.0f }; // for speed of rotation on own axis
float g_scaleSize[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f }; // for scaling the orbiting planets
float g_axisOfRotation[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; // for offsetting the axis of rotation
void generate_circle()
{
float angle = PI * 2 / static_cast<float>(g_slices); // used to generate x and y coordinates
float scale_factor = static_cast<float>(WINDOW_HEIGHT) / WINDOW_WIDTH; // scale to make it a circle instead of an elipse
int index = 0; // vertex index
g_vertices_circle[3] = CIRCLE_RADIUS * scale_factor; // set x coordinate of vertex 1
// generate vertex coordinates for triangle fan
for (int i = 2; i < g_slices + 2; i++)
{
// multiply by 3 because a vertex has x, y, z coordinates
index = i * 3;
g_vertices_circle[index] = CIRCLE_RADIUS * cos(angle) * scale_factor;
g_vertices_circle[index + 1] = CIRCLE_RADIUS * sin(angle);
g_vertices_circle[index + 2] = 0.0f;
//Color for edges. See stackoverflow
g_colors_circle[index] = 1.0f;
g_colors_circle[index + 1] = 0.0f;
g_colors_circle[index + 2] = 0.0f;
// update to next angle
angle += PI * 2 / static_cast<float>(g_slices);
}
// Gets rid of line from middle of circle
g_vertices_circle[0] = g_vertices_circle[3];
g_vertices_circle[1] = g_vertices_circle[4];
g_vertices_circle[2] = g_vertices_circle[5];
}
static void init(GLFWwindow* window)
{
glClearColor(0.0, 0.0, 0.0, 1.0); // set clear background colour
glEnable(GL_DEPTH_TEST); // enable depth buffer test
// create and compile our GLSL program from the shader files
g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag");
// enable point size
glEnable(GL_PROGRAM_POINT_SIZE);
// set line width
glLineWidth(5.0);
// find the location of shader variables
GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix");
// initialise model matrix to the identity matrix
g_modelMatrix[0] = g_modelMatrix[1] = g_modelMatrix[2] = g_modelMatrix[3] = g_modelMatrix[4] = glm::mat4(1.0f);
// initialise view matrix
g_viewMatrix = glm::lookAt(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); //perspective
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspectRatio = static_cast<float>(width) / height;
// initialise projection matrix
g_projectionMatrix = glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f);
// generate identifier for VBO and copy data to GPU
glGenBuffers(1, &g_VBO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW);
// generate identifier for IBO and copy data to GPU
glGenBuffers(1, &g_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);
// generate identifiers for VAO
glGenVertexArrays(1, &g_VAO[0]);
// create VAO and specify VBO data
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO);
// interleaved attributes
glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position)));
glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color)));
/*------------------------Circle----------------------*/
//// generate vertices of triangle fan
//generate_circle();
//// create VBO and buffer the data
//glGenBuffers(1, &g_VBO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW);
//glGenBuffers(1, &g_VBO[2]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_colors_circle, GL_STATIC_DRAW);
//// create VAO and specify VBO data
//glGenVertexArrays(1, &g_VAO[1]);
//glBindVertexArray(g_VAO[1]);
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]);
//glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
//glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
//glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data
/*----------------------------------------------------*/
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
}
//Generates a random value between 0.1 and 0.9
double generateRandomFloat(float min, float max)
{
return min + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (max - min)));
}
// function used to update the scene
static void update_scene()
{
// static variables for rotation angles
static float orbitAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
static float rotationAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
float scaleFactor = 0.05;
orbitAngle[0] += g_orbitSpeed[0] * scaleFactor;
orbitAngle[1] += g_orbitSpeed[1] * scaleFactor;
orbitAngle[2] += g_orbitSpeed[2] * scaleFactor;
orbitAngle[3] += g_orbitSpeed[3] * scaleFactor;
orbitAngle[4] += g_orbitSpeed[4] * scaleFactor;
// update rotation angles
rotationAngle[0] += g_rotationSpeed[0] * scaleFactor;
rotationAngle[1] += g_rotationSpeed[1] * scaleFactor;
rotationAngle[2] += g_rotationSpeed[2] * scaleFactor;
rotationAngle[3] += g_rotationSpeed[3] * scaleFactor;
rotationAngle[4] += g_rotationSpeed[4] * scaleFactor;
// update model matrix
g_modelMatrix[0] = glm::rotate(rotationAngle[0], glm::vec3(0.0f, 1.0f, 0.0f));
g_modelMatrix[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) //moves the axis of rotation along x-axis
* glm::rotate(orbitAngle[1], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(2.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[1], glm::vec3(0.0f, -1.0f, 0.0f)) //enables rotation on own axis. try comment
* glm::rotate(glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0.0f)) //rotates into a diamond shape
* glm::rotate(glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f)) //rotates into a diamond shape
* glm::scale(glm::vec3(g_scaleSize[1], g_scaleSize[1], g_scaleSize[1]));
g_modelMatrix[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f))
* glm::rotate(orbitAngle[2], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::translate(glm::vec3(4.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[2], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[2], g_scaleSize[2], g_scaleSize[2]));
g_modelMatrix[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f))
* glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::translate(glm::vec3(6.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3]));
g_modelMatrix[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f))
* glm::rotate(orbitAngle[4], glm::vec3(0.0f, -1.0f, 0.0f)) // -y changes orbit to clock-wise
* glm::translate(glm::vec3(8.0f, 0.0f, 0.0f))
* glm::rotate(rotationAngle[4], glm::vec3(0.0f, -1.0f, 0.0f))
* glm::scale(glm::vec3(g_scaleSize[4], g_scaleSize[4], g_scaleSize[4]));
}
// function used to render the scene
static void render_scene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer
glUseProgram(g_shaderProgramID); // use the shaders associated with the shader program
// glBindVertexArray(g_VAO[1]); // make VAO active
//
////Circle 1
// glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type
//
// glBindVertexArray(g_VAO[0]); // make VAO active
// Object 1
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[0];
// set uniform model transformation matrix
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 2
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[1];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 3
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[2];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 4
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[3];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
// Object 5
MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[4];
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type
glFlush(); // flush the pipeline
}
int main(void)
{
GLFWwindow* window = NULL; // pointer to a GLFW window handle
glfwSetErrorCallback(error_callback); // set error callback function
// initialise GLFW
if (!glfwInit())
{
// if failed to initialise GLFW
exit(EXIT_FAILURE);
}
// minimum OpenGL version 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// create a window and its OpenGL context
window = glfwCreateWindow(1500, 1000, "Assignment 2", NULL, NULL);
// if failed to create window
if (window == NULL)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window); // set window context as the current context
glfwSwapInterval(1); // swap buffer interval
// initialise GLEW
if (glewInit() != GLEW_OK)
{
// if failed to initialise GLEW
cerr << "GLEW initialisation failed" << endl;
exit(EXIT_FAILURE);
}
// set key callback function
glfwSetKeyCallback(window, key_callback);
// initialise rendering states
init(window);
// variables for simple time management
float lastUpdateTime = glfwGetTime();
float currentTime = lastUpdateTime;
// the rendering loop
while (!glfwWindowShouldClose(window))
{
currentTime = glfwGetTime();
// only update if more than 0.02 seconds since last update
if (currentTime - lastUpdateTime > 0.02)
{
update_scene(); // update the scene
render_scene(); // render the scene
glfwSwapBuffers(window); // swap buffers
glfwPollEvents(); // poll for events
lastUpdateTime = currentTime; // update last update time
}
}
// clean up
glDeleteProgram(g_shaderProgramID);
glDeleteBuffers(1, &g_IBO);
glDeleteBuffers(1, &g_VBO[0]);
glDeleteBuffers(1, &g_VBO[1]);
glDeleteVertexArrays(1, &g_VAO[0]);
glDeleteVertexArrays(1, &g_VAO[1]);
// close the window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
You have to set the uniform variable uModelViewProjectionMatrix before you draw the circle.
For all other objects you set a proper model view projection matrix, but you don't do so for the circle.
Since the circle does not move and has no other location data you only need the projection matrix and the view matrix.
In this case the model matrix is the identity matrix, so you can skip it.
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix;
glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]);
glBindVertexArray(g_VAO[1]);
glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2);
If you want to place the circle to another position in the scene you have to set up a model matrix for the circle and you have to concatenate the model matrix of the circle with the view matrix and the projection matrix.
glm::vec3 circlePos = ....;
glm::mat4 circleModelMat = glm::translate(glm::mat4(1.0f), circlePos);
glm::mat4 MVP = g_projectionMatrix * g_viewMatrix * circleModelMat;
Extension to the answer:
However, my cubes are still missing. All I can see is a static circle.
Do you know how I can get the cubes to appear as well?
You have to enable the vertex attributes vor both vertex array objects:
glBindVertexArray(g_VAO[0]);
// ... bind buffer and set vetex attribute pointer
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
/*------------------------Circle----------------------*/
// ...
glBindVertexArray(g_VAO[1]);
// ... bind buffer and set vetex attribute pointer
glEnableVertexAttribArray(positionIndex); // enable vertex attributes
glEnableVertexAttribArray(colorIndex);
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();
}