OpenGL Mesh Wrong Position - c++

I am trying to create a simple triangle mesh and after figuring out why I just got a blanc screen (for some reason the x64 configuration was giving me problems) I am facing a new issue:
The position of my vertices don't turn out to be how I want them. And I have no idea why.
What I should be getting is a triangle which looks about like this:
What I am getting though is this:
I use GLEW 1.10.0 for loading OpenGL, GLM 0.9.5.4 for OpenGL math stuff and SDL 2.0.3 for window stuff. Everything running on Windows 8.1 in Visual Studio 2013 Ultimate with the latest Nvidia graphics drivers.
Main.cpp:
#include "Display.h"
#include "Shader.h"
#include "Mesh.h"
using namespace std;
int main(int argc, char** argv)
{
Display display(1200, 800, "Hello World");
Vertex vertecies[] =
{
Vertex(vec3(-0.5, -0.5, 0)),
Vertex(vec3(0.5, -0.5, 0)),
Vertex(vec3(0, 0.5, 0))
};
Mesh mesh(vertecies, sizeof(vertecies) / sizeof(vertecies[0]));
Shader shader(".\\res\\BasicShader");
while (!display.IsClosed())
{
display.Clear(1.0f, 1.0f, 1.0f, 1.0f);
shader.Bind();
mesh.Draw();
display.Update();
}
return 0;
}
Mesh.cpp:
#include "Mesh.h"
Mesh::Mesh(Vertex* vertecies, unsigned int numVertecies)
{
m_drawCount = numVertecies;
glGenVertexArrays(1, &m_vertexArrayObject);
glBindVertexArray(m_vertexArrayObject);
glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertecies[0]) * numVertecies, vertecies, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, m_pos));
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteBuffers(NUM_BUFFERS, m_vertexArrayBuffers);
glDeleteVertexArrays(1, &m_vertexArrayObject);
}
void Mesh::Draw()
{
glBindVertexArray(m_vertexArrayObject);
glDrawArrays(GL_TRIANGLES, 0, m_drawCount);
glBindVertexArray(0);
}
Display.cpp:
#include "Display.h"
Display::Display(int width, int height, string title)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
m_window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
m_glContext = SDL_GL_CreateContext(m_window);
m_isClosed = false;
GLenum status = glewInit();
if (status != GLEW_OK)
cerr << "Could not initialize GLEW!" << endl;
}
Display::~Display()
{
SDL_GL_DeleteContext(m_glContext);
SDL_DestroyWindow(m_window);
SDL_Quit();
}
void Display::Clear(float r, float g, float b, float a)
{
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
}
bool Display::IsClosed()
{
return m_isClosed;
}
void Display::Update()
{
SDL_GL_SwapWindow(m_window);
SDL_Event e;
while (SDL_PollEvent(&e))
{
if (e.type == SDL_QUIT)
m_isClosed = true;
}
}
Vertex Shader:
#version 420 core
layout(location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
}
Fragment Shader:
#version 420 core
out vec4 frag;
void main()
{
frag = vec4(1.0, 0.0, 0.0, 1.0);
}
Vertex.h:
#pragma once
#include <glm\glm.hpp>
using namespace glm;
struct Vertex
{
public:
Vertex(const vec3& pos);
virtual ~Vertex();
vec3 m_pos;
};
Vertex.cpp:
#include "Vertex.h"
Vertex::Vertex(const vec3& pos)
{
m_pos = pos;
}
Vertex::~Vertex()
{
}
EDIT: Everything has now been fixed.

This is probably a data alignment issue where your Vertex class is being padded. OpenGL would then interpret the padding bytes as valid data.
You can verify this by printing the result of sizeof(Vertex) which would be 8 (you mention a 64 platform) if it is indeed padded.
This tells OpenGL that there are floats tightly packed in memory, without padding:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
A better way of setting the vertex pointer would be:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, m_pos));
This also enables you to easily add more attributes.

Related

two window share context object, do not work correctly on fedora36

I try to learn OpenGL context object sharing so I write a demo about object sharing:
#include <unistd.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include<iostream>
using namespace std;
const char* vertex_shader_text =
"#version 330 core\n"
"layout(location = 0) in vec2 vPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(vPos, 1, 1);\n"
"}\n";
const char* fragment_shader_text =
"#version 330 core\n"
"uniform vec3 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(color,1.0);\n"
"}\n";
GLuint loadShader(const char* vs, const char* fs) {
const GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vs, NULL);
glCompileShader(vertex_shader);
const GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fs, NULL);
glCompileShader(fragment_shader);
const GLuint programID = glCreateProgram();
glAttachShader(programID, vertex_shader);
glAttachShader(programID, fragment_shader);
glLinkProgram(programID);
return programID;
}
float colors[2][3] = {
{1.0, 1.0, 0.0}, {1.0, 0.0, 1.0}
};
static void key_callback(GLFWwindow* window, int key, int scancode, int action,
int mods) {
if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
void character_callback(GLFWwindow* window, unsigned int codepoint) {
printf("character_callback: %p, codepoint:%c\n", window,codepoint);
float r[3] = {1.0f, 0.0f, 0.0f};
float g[3] = {0.0f, 1.0f, 0.0f};
float b[3] = {0.0f, 0.0f, 1.0f};
if (codepoint == '1') {
for (int i = 0; i < 3; i++) {
colors[1][i] = r[i];
}
} else if (codepoint == '2') {
for (int i = 0; i < 3; i++) {
colors[1][i] = g[i];
}
}
if (codepoint == '3') {
for (int i = 0; i < 3; i++) {
colors[1][i] = b[i];
}
}
}
int main(int argc, char** argv) {
const char* description;
GLFWwindow* windows[2];
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
{
windows[0] = glfwCreateWindow(300, 300, "window1", NULL, NULL);
glfwSetCharCallback(windows[0], character_callback);
glfwMakeContextCurrent(windows[0]);
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
}
GLuint vao[2];
glGenVertexArrays(1, &vao[0]);
GLuint vbo;
glGenBuffers(1, &vbo);
const GLfloat vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f};
const GLuint program = loadShader(vertex_shader_text, fragment_shader_text);
{
glUseProgram(program);
glBindVertexArray(vao[0]);
{
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
}
// glBindVertexArray(0);
}
// window2
{
windows[1] = glfwCreateWindow(300, 300, "window2", nullptr, windows[0]);
glfwSetCharCallback(windows[1], character_callback);
glfwMakeContextCurrent(windows[1]);
{
glUseProgram(program);
glGenVertexArrays(1, &vao[1]);
glBindVertexArray(vao[1]);
{
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
}
// glBindVertexArray(0);
}
}
for (int i = 0; i < 2; i++) {
glfwSetKeyCallback(windows[i], key_callback);
glfwMakeContextCurrent(windows[i]);
glClearColor(colors[0][0], colors[0][1], colors[0][2], 1.0);
for (int k = 0; k < 3; k++) {
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(windows[i]);
}
}
int color_pos = glGetUniformLocation(program, "color");
glfwMakeContextCurrent(0);
// ==========step 2============
while (!glfwWindowShouldClose(windows[0]) &&
!glfwWindowShouldClose(windows[1])) {
for (int i = 0; i < 2; i++) {
glfwPollEvents();
glfwMakeContextCurrent(windows[i]);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao[i]);
glUniform3f(color_pos, colors[1][0], colors[1][1], colors[1][2]); //??? I change two window triangle color, why only one window work when i click the button 1,2,3 ?
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(windows[i]);
glBindVertexArray(0);
glfwMakeContextCurrent(0);
}
}
glfwTerminate();
exit(EXIT_SUCCESS);
}
I expect the each window draw the same triangle with same color, when I click key 1,2 and 3, the two window will change color to red,green and blue at the same time.
It's working on ubuntu20.04, but not working on fedora36, only one window will change the color, the other one do not.
Why does only one window's triangle color change and the another one not?
I try to use gdb to debug the program, but it's seem too difficult to figure out.
My environment is:
jack#fedora
------------
OS: Fedora release 36 (Thirty Six) x86_64
Host: 20FBA05VCD ThinkPad X1 Carbon 4th
Kernel: 5.19.8-200.fc36.x86_64
Uptime: 11 days, 14 hours, 17 mins
Packages: 6001 (rpm), 58 (flatpak), 12 (snap)
Shell: bash 5.1.16
Resolution: 1920x1080
DE: GNOME 42.5
WM: Mutter
WM Theme: Adwaita
Theme: Adwaita [GTK2/3]
Icons: Adwaita [GTK2/3]
Terminal: gnome-terminal
CPU: Intel i5-6200U (4) # 2.800GHz
GPU: Intel Skylake GT2 [HD Graphics 520]
Memory: 6008MiB / 6866MiB

OpenGL -- glGenVertexArrays, "thread 1: exc_bad_access (code =1, address=0x0)"

I am writing a openGL program(C++) which draws a ground with two 3D objects above it. The programming tool I use is Xcode version 8.0(8A218a)(OSX 10.11.6).
my code(main.cpp):
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include <fstream>
using namespace std;
using glm::vec3;
using glm::mat4;
GLint programID;
//initialize all OpenGL objects
GLuint groundVAO, groundVBO, groundEBO; //ground
bool checkStatus( //OK
GLuint objectID,
PFNGLGETSHADERIVPROC objectPropertyGetterFunc,
PFNGLGETSHADERINFOLOGPROC getInfoLogFunc,
GLenum statusType)
{
GLint status;
objectPropertyGetterFunc(objectID, statusType, &status);
if (status != GL_TRUE)
{
GLint infoLogLength;
objectPropertyGetterFunc(objectID, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* buffer = new GLchar[infoLogLength];
GLsizei bufferSize;
getInfoLogFunc(objectID, infoLogLength, &bufferSize, buffer);
cout << buffer << endl;
delete[] buffer;
return false;
}
return true;
}
bool checkShaderStatus(GLuint shaderID) //OK
{
return checkStatus(shaderID, glGetShaderiv, glGetShaderInfoLog, GL_COMPILE_STATUS);
}
bool checkProgramStatus(GLuint programID) //OK
{
return checkStatus(programID, glGetProgramiv, glGetProgramInfoLog, GL_LINK_STATUS);
}
string readShaderCode(const char* fileName) //OK
{
ifstream meInput(fileName);
if (!meInput.good())
{
cout << "File failed to load..." << fileName;
exit(1);
}
return std::string(
std::istreambuf_iterator<char>(meInput),
std::istreambuf_iterator<char>()
);
}
void installShaders() //OK
{
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar* adapter[1];
//adapter[0] = vertexShaderCode;
string temp = readShaderCode("VertexShaderCode.glsl");
adapter[0] = temp.c_str();
glShaderSource(vertexShaderID, 1, adapter, 0);
//adapter[0] = fragmentShaderCode;
temp = readShaderCode("FragmentShaderCode.glsl");
adapter[0] = temp.c_str();
glShaderSource(fragmentShaderID, 1, adapter, 0);
glCompileShader(vertexShaderID);
glCompileShader(fragmentShaderID);
if (!checkShaderStatus(vertexShaderID) ||
!checkShaderStatus(fragmentShaderID))
return;
programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
if (!checkProgramStatus(programID))
return;
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
glUseProgram(programID);
}
void keyboard(unsigned char key, int x, int y)
{
//TODO:
}
void sendDataToOpenGL()
{
//TODO:
//create solid objects here and bind to VAO & VBO
//Ground, vertices info
const GLfloat Ground[]
{
-5.0f, +0.0f, -5.0f, //0
+0.498f, +0.898, +0.0f, //grass color
+5.0f, +0.0f, -5.0f, //1
+0.498f, +0.898, +0.0f,
+5.0f, +0.0f, +5.0f, //2
+0.498f, +0.898, +0.0f,
-5.0f, +0.0f, +5.0f
};
GLushort groundIndex[] = {1,2,3, 1,0,3};
//Pass ground to vertexShader
//VAO
glGenVertexArrays(1, &groundVAO);
glBindVertexArray(groundVAO);
//VBO
glGenBuffers(1, &groundVBO);
glBindBuffer(GL_ARRAY_BUFFER, groundVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Ground), Ground, GL_STATIC_DRAW);
//EBO
glGenBuffers(1, &groundEBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, groundEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(groundIndex), groundIndex, GL_STATIC_DRAW);
//connectToVertexShader
glEnableVertexAttribArray(0); //position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, 0);
glEnableVertexAttribArray(1); //color
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (char*)(sizeof(float)*3));
}
void paintGL(void)
{
//TODO:
//render your objects and control the transformation here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//translate model
glm::mat4 modelTransformMatrix = glm::translate(glm::mat4(), vec3(+0.0f, +0.0f, -3.0f));
//perspective view
glm::mat4 projectionMatrix = glm::perspective(+40.0f, +1.0f, +1.0f, +60.0f);
//ultimate matrix
glm::mat4 ultimateMatrix;
//register location on the graphics cards
GLint ultimateMatrixUniformLocation = glGetUniformLocation(programID, "ultimateMatrix");
/*GLint modelTransformMatrixUniformLocation = glGetUniformLocation(programID, "modelTransformMatrix");
GLint projectionMatrixUniformLocation = glGetUniformLocation(programID, "projectionMatrix");*/
//drawing the ground
/*glUniformMatrix4fv(modelTransformMatrixUniformLocation, 1, GL_FALSE, &modelTransformMatrix[0][0]);
glUniformMatrix4fv(projectionMatrixUniformLocation, 1, GL_FALSE, &projectionMatrix[0][0]);*/
glBindVertexArray(groundVAO);
ultimateMatrix = projectionMatrix * modelTransformMatrix;
glUniformMatrix4fv(ultimateMatrixUniformLocation, 1, GL_FALSE, &ultimateMatrix[0][0]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
glFlush();
glutPostRedisplay();
}
void initializedGL(void) //run only once
{
glewInit();
glEnable(GL_DEPTH_TEST);
sendDataToOpenGL();
installShaders();
}
int main(int argc, char *argv[])
{
/*Initialization*/
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("Try");
glutInitWindowSize(700, 700);
//const GLubyte* glversion = glGetString(GL_VERSION);
/*Register different CALLBACK function for GLUT to response
with different events, e.g. window sizing, mouse click or
keyboard stroke */
initializedGL();
//glewExperimental = GL_TRUE;
glutDisplayFunc(paintGL);
glutKeyboardFunc(keyboard);
/*Enter the GLUT event processing loop which never returns.
it will call different registered CALLBACK according
to different events. */
//printf("OpenGL ver: %s\n", glversion);
glutMainLoop();
return 0;
}
VertexShaderCode.glsl:
#version 430 // GLSL version your computer supports
in layout(location=0) vec3 position;
in layout(location=1) vec3 vertexColor;
uniform mat4 ultimateMatrix;
out vec3 theColor;
void main()
{
vec4 v = vec4(position, 1.0);
gl_Position = ultimateMatrix * v;
theColor = vertexColor;
}
FragmentShaderCode.glsl:
#version 430 //GLSL version your computer supports
out vec4 theColor2;
in vec3 theColor;
void main()
{
theColor2 = vec4(theColor, 1.0);
}
Functions: checkStatus, checkShaderStatus, checkProgramStatus, readShaderCode, installShaders should be all fine.
void keyboard() can be ignored since I havent implemented it yet(just for keyboard control).
I implemented the object "Ground" in sendDataToOpenGL(). But when I compiled and ran the program, "thread 1: exc_bad_access (code =1, address=0x0)" occured in the line of VAO:
And the pop-out window is just a white screen instead of a green grass(3d).
I have tried a method which was provided in other stackoverflow post: using glewExperimental = GL_TRUE;. I didnt see any errors by using that, but the popout screen vanished immediately just after it appeared. It seems that it couldnt help the problem.
Can someone give me a help? Thank you!
glGenVertexArrays is available in since OpenGL version 3.0. If vertex array objects are supported can be checked by glewGetExtension("GL_ARB_vertex_array_object").
Glew can enable additional extensions by glewExperimental = GL_TRUE;. See the GLEW documantation which says:
GLEW obtains information on the supported extensions from the graphics driver. Experimental or pre-release drivers, however, might not report every available extension through the standard mechanism, in which case GLEW will report it unsupported. To circumvent this situation, the glewExperimental global switch can be turned on by setting it to GL_TRUE before calling glewInit(), which ensures that all extensions with valid entry points will be exposed.
Add this to your code:
glewExperimental = GL_TRUE;
glewInit();

Drawing points using openGL/SDL

i'm trying to track my hands then for each x,y i will draw a point on openGL window .
that's my code :
#include "GraphicsEffects.h"
#include "Errors.h"
GraphicsEffects::GraphicsEffects():
_vboID(0)
{}
void GraphicsEffects::init(){
SDL_Init(SDL_INIT_EVERYTHING);
_window = SDL_CreateWindow("2D Painting", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED , 600, 600, SDL_WINDOW_OPENGL);
if(_window == nullptr){
fatalError("SDL window could not be created! "); }
SDL_GLContext glContext = SDL_GL_CreateContext(_window);
if(glContext == nullptr) {
fatalError("SDL_GL context could not be created!");
}
GLenum error = glewInit();
if(error != GLEW_OK){
fatalError("Could not initialize glew!");
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
if(_vboID == 0){
glGenBuffers(1, &_vboID);
}
_colorProgram.compileShaders("Shaders/color.vert", "Shaders/color.frag");
_colorProgram.addAttribute("vertexPosition");
_colorProgram.linkShaders();
}
void GraphicsEffects::draw(int x, int y){
int pointData[2];
pointData[0] = x;
pointData[1] = y;
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
_colorProgram.use();
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
glBufferData(GL_ARRAY_BUFFER, sizeof(pointData), pointData, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, 0);
glDrawArrays(GL_POINT, 0, 1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
_colorProgram.unuse();
SDL_GL_SwapWindow(_window);
}
For Shaders/color.vert : "vertex shader file"
#version 130
in vec2 vertexPosition;
void main() {
gl_Position.xy = vertexPosition;
gl_Position.z = 0;
gl_Position.w = 1.0;
}
for Shader/color.frag: "fragment shader"
#version 130
out vec4 color ;
void main() {
color = vec4(1.0, 1.0, 0.0, 1.0);
}
i expected i will get points with my (x,y) movements but nothing appears on the window !
This line
glDrawArrays(GL_POINT, 0, 1);
will generate an GL_INVALID_ENUM error and do nothing else. The correct value is GL_POINTS, not GL_POINT.
You should really add error checking, at least for development builds. If possible, have a look at the debug output functionality of newer OpenGL versions.

OpenGL shader won't render Triangle

i'm working in this project (https://github.com/lupeeumeeu/WorldCraft), everything works fine, i can change the background color, but it doesn't render the triangle, i tried to set tons and tons of breakpoints, but couldn't find any problem, i think the problem should be around trhe triangle.cpp or the managers, i tried to follow the in2gpu's tutorial but i also modified a little bit.
An image link to explain just a bit:
https://imgur.com/a/HN7t2
Main.cpp:
#include "..\WorldCraft\Core\Init\Init.h"
#include "Core\Managers\Scene_Manager.h"
#include "Core\Render\Triangle.h"
using namespace Core;
using namespace Init;
int main(int argc, char **argv)
{
WindowConfig windowconfig(std::string("WorldCraft"), 800, 600, 400, 200, true);//name, x, y, w, h, reshape
OpenGLVersion version(4, 5, true);//M.m version opengl, msaa
BufferConfig bufferconfig(true, true, true, true); // Buffers
Core::Init::Init::Initialize(windowconfig, version, bufferconfig, argc, argv);
Core::Managers::Scene_Manager* mainMenu = new Core::Managers::Scene_Manager();
Core::Init::Init::SetListener(mainMenu);
Core::Render::Triangle* triangle = new Core::Render::Triangle();
triangle->SetProgram(Core::Managers::Shader_Manager::GetShader("CommonShader"));
triangle->Create();
mainMenu->GetModels_Manager()->SetModel("triangle", triangle);
Core::Init::Init::Run();
delete mainMenu;
return 0;
}
Scene_Manager.cpp:
#include "Scene_Manager.h"
using namespace Core;
using namespace Managers;
Scene_Manager::Scene_Manager()
{
glEnable(GL_DEPTH_TEST);
shader_manager = new Shader_Manager();
shader_manager->CreateProgram("CommonShader", "Core//Shaders//Common//Vertex_Shader.glsl"
, "Core//Shaders//Common//Fragment_Shader.glsl");
view_matrix = glm::mat4(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 10.0f, 1.0f);
models_manager = new Models_Manager();
}
Scene_Manager::~Scene_Manager()
{
delete shader_manager;
delete models_manager;
}
void Scene_Manager::NotifyBeginFrame()
{
models_manager->Update();
}
void Scene_Manager::NotifyDisplayFrame()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);
models_manager->Draw();
models_manager->Draw(projection_matrix, view_matrix);
}
void Scene_Manager::NotifyEndFrame()
{
}
void Scene_Manager::NotifyReshape(int width, int height, int previous_width, int previous_height)
{
float ar = (float)glutGet(GLUT_WINDOW_WIDTH) / (float)glutGet(GLUT_WINDOW_HEIGHT);
float angle = 45.0f, near1 = 0.1f, far1 = 2000.0f;
projection_matrix[0][0] = 1.0f / (ar * tan(angle / 2.0f));
projection_matrix[1][1] = 1.0f / tan(angle / 2.0f);
projection_matrix[2][2] = (-near1 - far1) / (near1 - far1);
projection_matrix[2][3] = 1.0f;
projection_matrix[3][2] = 2.0f * near1 * far1 / (near1 - far1);
}
Core::Managers::Models_Manager* Scene_Manager::GetModels_Manager()
{
return models_manager;
}
Scene_Manager.h:
#pragma once
#include "Models_Manager.h"
#include "Shader_Manager.h"
#include "../Init/FrameNotifier.h"
namespace Core
{
namespace Managers
{
class Scene_Manager : public Init::FrameNotifier
{
public:
Scene_Manager();
~Scene_Manager();
virtual void NotifyBeginFrame();
virtual void NotifyDisplayFrame();
virtual void NotifyEndFrame();
virtual void NotifyReshape(int width, int height, int previous_width, int previous_height);
Managers::Models_Manager* GetModels_Manager();
private:
Core::Managers::Shader_Manager* shader_manager;
Core::Managers::Models_Manager* models_manager;
glm::mat4 projection_matrix;
glm::mat4 view_matrix;
};
}
}
Models_Manager.cpp:
#include "Models_Manager.h"
using namespace Core::Managers;
using namespace Core::Render;
Models_Manager::Models_Manager()
{
Triangle* triangle = new Triangle();
triangle->SetProgram(Shader_Manager::GetShader("CommonShader"));
triangle->Create();
gameModelList_NDC["triangle"] = triangle;
}
Models_Manager::~Models_Manager()
{
for (auto model : gameModelList)
{
delete model.second;
}
gameModelList.clear();
for (auto model : gameModelList_NDC)
{
delete model.second;
}
gameModelList_NDC.clear();
}
void Models_Manager::Update()
{
for (auto model : gameModelList)
{
model.second->Update();
}
for (auto model : gameModelList_NDC)
{
model.second->Update();
}
}
void Models_Manager::Draw()
{
for (auto model : gameModelList_NDC)
{
model.second->Draw();
}
}
void Models_Manager::Draw(const glm::mat4& projection_matrix, const glm::mat4& view_matrix)
{
for (auto model : gameModelList)
{
model.second->Draw(projection_matrix, view_matrix);
}
}
void Models_Manager::DeleteModel(const std::string& gameModelName)
{
IGameObject* model = gameModelList[gameModelName];
model->Destroy();
gameModelList.erase(gameModelName);
}
void Models_Manager::DeleteModel_NDC(const std::string& gameModelName)
{
IGameObject* model = gameModelList_NDC[gameModelName];
model->Destroy();
gameModelList_NDC.erase(gameModelName);
}
const IGameObject& Models_Manager::GetModel(const std::string& gameModelName) const
{
return (*gameModelList.at(gameModelName));
}
const IGameObject& Models_Manager::GetModel_NDC(const std::string& gameModelName) const
{
return (*gameModelList_NDC.at(gameModelName));
}
void Models_Manager::SetModel(const std::string& gameObjectName, IGameObject* gameObject)
{
gameModelList[gameObjectName.c_str()] = gameObject;
}
Triangle.cpp:
#include "Triangle.h"
using namespace Core;
using namespace Render;
Triangle::Triangle(){}
Triangle::~Triangle(){}
static void PrintError(GLenum errorCode)
{
switch (errorCode)
{
case GL_NO_ERROR:
break;
case GL_INVALID_ENUM:
std::cout << "An unacceptable value is specified for an enumerated argument.";
break;
case GL_INVALID_VALUE:
std::cout << "A numeric argument is out of range.";
break;
default:
break;
}
}
void Triangle::Create()
{
GLuint vao;
GLuint vbo;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
std::vector<VertexFormat> vertices;
vertices.push_back(VertexFormat(glm::vec3(0.25, -0.25, -1.0), glm::vec4(1, 0, 0, 1)));
vertices.push_back(VertexFormat(glm::vec3(-0.25, -0.25, -1.0), glm::vec4(0, 1, 0, 1)));
vertices.push_back(VertexFormat(glm::vec3(0.25, 0.25, -1.0), glm::vec4(0, 0, 1, 1)));
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
PrintError(glGetError());
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexFormat) * 3, &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)(offsetof(VertexFormat, VertexFormat::color)));
glBindVertexArray(0);
this->vao = vao;
this->vbos.push_back(vbo);
}
void Triangle::Update() {}
void Triangle::Draw()
{
glUseProgram(program);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
I found the error, it was the duplicated triangle, without the camera configuration (view_matrix and projection_matrix)

OpenGL 4.1: Triangle Flashes and Disappears Immediately after Being Drawn

I want to render a green triangle.
OpenGL Version: 4.1
Shading Language Version: 4.10
Problem
The code below, when executed, shows a green triangle that flashes for an instant and disappears.
I saw this post: A red rectangle drawn on 2D texture disappears right after being drawn, who has a similar issue of disappearing triangles, but his was because he called Swap Buffer multiple times, but I only have one instance of glutSwapBuffers() in the displayFunc().
C++ Code:
#include <iostream>
#include "OpenGLMatrix.h"
#include "BasicPipelineProgram.h"
using namespace std;
int windowWidth = 1280;
int windowHeight = 720;
char windowTitle[512] = "Simple Green Triangle";
// global variables
OpenGLMatrix *matrix;
GLuint buffer;
BasicPipelineProgram *pipelineProgram;
GLint program;
GLuint vao;
// objects to render
int numVertices = 3;
float positions[9] =
{ -1, -1, -1,
1, -1, -1,
-1, 1, -1 }; // 3 vertices of triangle to render
float colors[12] =
{ 0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1 }; // all vertices green with alpha = 1
void bindProgram() {
// upload model view matrix to shader
float m[16];
matrix->SetMatrixMode(OpenGLMatrix::ModelView);
matrix->GetMatrix(m);
pipelineProgram->SetModelViewMatrix(m);
// upload projection matrix to shader
float p[16];
matrix->SetMatrixMode(OpenGLMatrix::Projection);
matrix->GetMatrix(p);
pipelineProgram->SetProjectionMatrix(p);
}
void displayFunc() {
// computing modelview matrix
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
matrix->LoadIdentity();
// camera at (0,0,1), looking in -z direction, up vector y
matrix->LookAt(0, 0, 1, 0, 0, -1, 0, 1, 0);
bindProgram();
// use the VAO
pipelineProgram->Bind();
glBindVertexArray(vao);
GLint first = 0;
GLsizei count = numVertices;
glDrawArrays(GL_TRIANGLES, first, count);
glBindVertexArray(0);
glutSwapBuffers();
}
void idleFunc() {
// make the screen update
glutPostRedisplay();
}
void reshapeFunc(int w, int h) {
GLfloat aspect = (GLfloat) w / (GLfloat) h;
glViewport(0, 0, w, h);
// setup perspective matrix
matrix->SetMatrixMode(OpenGLMatrix::Projection);
matrix->LoadIdentity();
matrix->Perspective(60.0, aspect, 0.01, 1000.0);
matrix->SetMatrixMode(OpenGLMatrix::ModelView);
}
void initPipelineProgram() {
// initialize shader pipeline program
pipelineProgram = new BasicPipelineProgram();
pipelineProgram->Init();
pipelineProgram->Bind();
program = pipelineProgram->GetProgramHandle();
// VAO (vertex array objects) to contain the VBOs
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// get location index of the "position" shader variable
GLuint loc = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(loc);
const void *offset = (const void*) 0;
GLsizei stride = 0;
GLboolean normalized = GL_FALSE;
glVertexAttribPointer(loc, 3, GL_FLOAT, normalized, stride, offset);
// get location index of the "color" shader variable
loc = glGetAttribLocation(program, "color");
glEnableVertexAttribArray(loc);
offset = (const void*) sizeOfPositions;
stride = 0;
normalized = GL_FALSE;
glVertexAttribPointer(loc, 4, GL_FLOAT, normalized, stride, offset);
glBindVertexArray(0);
}
void initVBO() {
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeOfPositions + sizeOfColors, NULL, GL_STATIC_DRAW);
// upload position data
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeOfPositions, positions);
// upload color data
glBufferSubData(GL_ARRAY_BUFFER, sizeOfPositions, sizeOfColors, colors);
}
void initScene(int argc, char *argv[])
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
matrix = new OpenGLMatrix();
initVBO();
initPipelineProgram();
}
int main(int argc, char *argv[])
{
cout << "Initializing GLUT..." << endl;
glutInit(&argc,argv);
cout << "Initializing OpenGL..." << endl;
#ifdef __APPLE__
glutInitDisplayMode(GLUT_3_2_CORE_PROFILE | GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
#else
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
#endif
glutInitWindowSize(windowWidth, windowHeight);
glutInitWindowPosition(0, 0);
glutCreateWindow(windowTitle);
// glut callback functions
glutDisplayFunc(displayFunc);
glutIdleFunc(idleFunc);
glutReshapeFunc(reshapeFunc);
initScene(argc, argv);
glutMainLoop();
}
In the code, OpenGLMatrix *matrix and BasicPipelineProgram *pipelineProgram are classes defined elsewhere, and whose code, unless requested, I don't think we need to worry about. "position" and "color" in initPipelineProgram() refer to variables in the GLSL shader specification:
#version 150
in vec3 position;
in vec4 color;
out vec4 col;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main()
{
// compute the transformed and projected vertex position (into gl_Position)
// compute the vertex color (into col)
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0f);
col = color;
}
I don't understand why the triangle flashes and then immediately disappears??
I'm a beginner in OpenGL and any help is greatly appreciated. Thank you!