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)
Related
I started working on a github project (a logic gate simulator) with gtkmm and epoxy. I have an optimus laptop with debian buster and nvidia-bumblebee drivers installed and everything works fine except that if I start the program using optirun or primusrun, neither the glArea->queue_render, nor glArea->queue_draw function seems to work. I have to resize the window in order to rerender the glArea widget. Also sometimes when I restart the system and compile the program it won't start with bumblebee at all and outputs the following error:
311-0-no gl implementation is available
It might be something with my system, but optirun and primusrun usually work fine.
Any Idea what might be the cause of this problem?
the renderer class:
#ifndef RENDERER_DATA_H
#define RENDERER_DATA_H
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
struct scene{ //viewport data
glm::mat4 proj;
glm::mat4 view;
glm::mat4 model;
glm::mat4 mvp;
float zoom = 1.0f;
glm::vec2 dim;
glm::vec3 pos = {0, 0, 1.0f};
};
struct pointer{ //mouse data
int button;
int x, y;
};
struct keyboard{ //keyboard data
};
#endif
#ifndef RENDERER_H
#define RENDERER_H
/*
This is the renderer of the viewport
*/
#include "viewport/shader.hpp"
#include "viewport/vertexbuffer.hpp"
#include "viewport/indexbuffer.hpp"
#include "viewport/vertexarray.hpp"
#include "viewport/objects/grid.hpp"
#include <gtkmm-3.0/gtkmm.h>
#include <gtkmm-3.0/gtkmm/glarea.h>
#include <glm/glm.hpp>
//#include <glm/gtx/transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
//#include <gdkmm-3.0/gdkmm/glcontext.h>
//#include <glibmm-2.4/glibmm/refptr.h>
//#include <epoxy/gl.h>
//#include <epoxy/glx.h>
#include <iostream>
class Renderer{
public:
Renderer(Gtk::GLArea*); //constructor connects the following callbacks:
void realize(); //called when widget glArea is created
void unrealize(); //called when widget glArea is destroyed
void resize(int width, int height); //called when the glArea is resized
bool render(const Glib::RefPtr<Gdk::GLContext>&); //called when the viewport should render itself
bool mouse_move(GdkEventMotion* event); //called when both mouse button pressed and mouse moved
bool mouse_scroll(GdkEventScroll* event); //called when the mouse is wheel is rotated
bool button_press(GdkEventButton* button); //called when a button is pressed
bool button_release(GdkEventButton* button); //called when a button is released
private:
Gtk::GLArea* glArea; //pointer to the glArea widget, created in ui object
GLuint vao;
IndexBuffer* ibptr;
VertexBuffer* vbptr;
VertexArray* vaptr;
VertexBufferLayout* vblptr;
Shader* shader_program;
Grid* grid;
pointer mouse; //mouse variable obj
scene viewport; //viewport variable obj
void update_view(); //This function is resposible for paning and zooming the viewport
glm::vec3 mouse_translate(glm::vec3); //translates screen coords to world coords
};
#endif //
implementation:
//#include <ui.hpp>
#include "./renderer.hpp"
Renderer::Renderer(Gtk::GLArea* glarea)
/*:glArea(glarea)*/{
glArea = glarea;
glArea->add_events(Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON1_MOTION_MASK | Gdk::BUTTON2_MOTION_MASK | Gdk::BUTTON3_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::SCROLL_MASK);
glArea->signal_realize().connect(sigc::mem_fun(*this, &Renderer::realize));
glArea->signal_unrealize().connect(sigc::mem_fun(*this, &Renderer::unrealize), false);
glArea->signal_render().connect(sigc::mem_fun(*this, &Renderer::render), false);
glArea->signal_resize().connect(sigc::mem_fun(*this, &Renderer::resize));
glArea->signal_motion_notify_event().connect(sigc::mem_fun(*this, &Renderer::mouse_move));
glArea->signal_scroll_event().connect(sigc::mem_fun(*this, &Renderer::mouse_scroll));
glArea->signal_button_press_event().connect(sigc::mem_fun(*this, &Renderer::button_press));
glArea->signal_button_release_event().connect(sigc::mem_fun(*this, &Renderer::button_release));
}
void Renderer::realize(){
std::clog<<"realize"<<std::endl;
//glArea->set_required_version(4, 5);
glArea->make_current();
glArea->set_auto_render(true);
std::clog<<"make current"<<std::endl;
//std::clog<<epoxy_gl_version()<<"\n";
//std::clog<<epoxy_glsl_version()<<"\n";
glArea->make_current();
std::cout<<glGetString(GL_VERSION)<<std::endl;
std::cout<<"realize\n";
try{
glArea->throw_if_error();
std::clog<<glGetString(GL_VERSION)<<"\n";
std::clog<<glGetString(GL_VENDOR)<<"\n";
char path[] = "./src/res/shaders";
shader_program = new Shader(path);
shader_program->bind();
//shader_program = Shader::create_shader_program(nullptr);
//glUseProgram(shader_program);
GLfloat pos[] = {
-0.5f, -0.5f, -1,
0.5f, -0.5f, -1,
0.5f, 0.5f, -1,
-0.5f, 0.5f, -1
};
GLuint ind[] = {
0, 1, 2,
2, 3, 0
};
vaptr = new VertexArray();
//glGenVertexArrays(1, &vao);
//glBindVertexArray(vao);
vbptr = new VertexBuffer(pos, 4 * 3 * sizeof(GLfloat));
vblptr = new VertexBufferLayout;
vblptr->add(3, GL_FLOAT);
//vblptr->add(3, GL_FLOAT);
//vblptr->add(2, GL_FLOAT);
vaptr->addBuffer(*vbptr, *vblptr);
//glEnableVertexAttribArray(0);
//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
ibptr = new IndexBuffer(ind, 6);
//int location = epoxy_glGetUniformLocation(shader_program->get_program(), "u_Color");
//glUniform4f(location, 0.2f, 0.3f, 0.8f, 1.0f);
//glm::vec4 data = {0.2f, 0.3f, 0.8f, 1.0f};
shader_program->set_uniform4f ("u_Color", {0.2f, 0.3f, 0.8f, 1.0f});
//viewport.proj = glm::ortho(-width/height/2, width/height/2, -height/width/2, height/width/2);
//shader_program->set_uniform_mat4f ("mvp", viewport.proj);
//glBindVertexArray(0);
//glUseProgram(0);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}catch(const Gdk::GLError& gle){
std::cerr << "An error occured making the context current during realize:" << std::endl;
std::cerr << gle.domain() << "-" << gle.code() << "-" << gle.what() << std::endl;
}
grid = new Grid(glm::vec3(-3.0, 0.0, -1.0), glm::vec3(3.0, 0.0, -1.0));
}
void Renderer::unrealize(){
glArea->make_current();
delete vbptr;
delete ibptr;
delete vaptr;
delete vblptr;
delete shader_program;
try
{
glArea->throw_if_error();
}
catch(const Gdk::GLError& gle)
{
std::cerr << "An error occured making the context current during unrealize" << std::endl;
std::cerr << gle.domain() << "-" << gle.code() << "-" << gle.what() << std::endl;
}
}
void Renderer::resize(int width, int height){
viewport.dim.x = width;
viewport.dim.y = height;
}
bool Renderer::render(const Glib::RefPtr<Gdk::GLContext>& context ){
std::clog<<"render\n";
update_view();
//glArea->attach_buffers();
glClear(GL_COLOR_BUFFER_BIT);
grid->draw();
grid->m_shader->set_uniform_mat4f("mvp", viewport.mvp);
grid->draw();
shader_program->bind();
vaptr->bind();
//ibptr->bind();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);
glUseProgram(0);
return true;
}
bool Renderer::mouse_move(GdkEventMotion* event){
glm::vec3 diff = mouse_translate(glm::vec3(mouse.x, mouse.y, 0.0)) - mouse_translate(glm::vec3(event->x, event->y, 0.0));
std::clog<<diff.x<<" "<<diff.y<<"\n";
if(mouse.button == 1){
viewport.pos = viewport.pos - diff;
std::clog<<viewport.pos .x<<" "<<viewport.pos.y<<" "<<viewport.pos.z<<"\n";
//glArea->queue_draw();
//glArea->queue_draw();
glArea->queue_render();
//glArea->signal_render();
}
mouse.x = event->x;
mouse.y = event->y;
return true;
}
bool Renderer::mouse_scroll(GdkEventScroll* event){
if(event->direction == GDK_SCROLL_DOWN && viewport.zoom>1){
viewport.zoom = viewport.zoom - 0.1;
}else if(event->direction == GDK_SCROLL_UP && viewport.zoom<10){
viewport.zoom = viewport.zoom + 0.1;
}
glArea->queue_render();
std::clog<<viewport.zoom<<"\n";
return true;
}
bool Renderer::button_press(GdkEventButton* event){
std::clog<<event->button<<"\n";
mouse.button = event->button;
mouse.x = event->x;
mouse.y = event->y;
//if(event->mouse.button == 1){ //left mouse button
//
//}
return true;
}
bool Renderer::button_release(GdkEventButton* button){
mouse.button = 0;
return true;
}
void Renderer::update_view(){
std::clog<<"update view\n";
viewport.view = glm::translate(glm::mat4(1.0f), glm::vec3(viewport.pos.x, -viewport.pos.y, -viewport.pos.z));
viewport.model = glm::translate(glm::mat4(1.0f), glm::vec3( 0, 0, 1.0));
if(viewport.dim.x<viewport.dim.y){
viewport.proj = glm::ortho(-viewport.dim.x/viewport.dim.y/viewport.zoom, viewport.dim.x/viewport.dim.y/viewport.zoom, -1.0f/viewport.zoom, 1.0f/viewport.zoom);
}else{
viewport.proj = glm::ortho(-1.0f/viewport.zoom, 1.0f/viewport.zoom, -viewport.dim.y/viewport.dim.x/viewport.zoom, viewport.dim.y/viewport.dim.x/viewport.zoom);
}
viewport.mvp = viewport.proj * viewport.view * viewport.model;
shader_program->bind();
shader_program->set_uniform_mat4f ("mvp", viewport.mvp);
}
glm::vec3 Renderer::mouse_translate(glm::vec3 pos){
return glm::unProject(pos, viewport.model, viewport.proj, glm::vec4(0.0f, 0.0f, viewport.dim.x, viewport.dim.y));
}
Full project on github: LinuxGameGeek/logix
OpenGL is poorly integrated with GTK+3, for example on OS X, you'll have this error displayed because OpenGL is simply not implemented. Maybe this is the same case for you
In addition in gtkmm-3.18 a bug (fixed since this version) displaying this error when GLArea class was derived. But this is not your case.
If that may help you I have a similar application mixing OpenGL/GTKmm in Lecrapouille/SimTaDyn I guess this will give you the same error.
I recently created this VertexBuffer class to and added it to my opengl based engine; but it seems to fail in my main code, causing an "access violation at 0x00000000."...
Here is VertexBuffer.h :
#pragma once
#include "Type.h"
#include "Tags.h"
namespace Spiky {
namespace GLLayer {
template<>
struct GLObjDelAlloc<Tags::VertexBuffer> {
static void Allocate(GLTypeCT<GLType::Integer> count,
Tags::VertexBuffer::internal* names) {
glGenBuffers(count, names);
}
static void Delete(GLTypeCT<GLType::Integer> count, Tags::VertexBuffer::internal* names) {
glDeleteBuffers(count, names);
}
};
template<>
struct GLObjBind<Tags::VertexBuffer> {
private:
static Tags::VertexBuffer::internal _active;
public:
static const int ZERO_BUFFER = GL_NONE;
static void BindRequest(Tags::VertexBuffer::internal name = ZERO_BUFFER) {
if(_active != name) {
glBindBuffer(GL_ARRAY_BUFFER, 0);
_active = name;
}
}
};
Tags::VertexBuffer::internal
GLObjBind<Tags::VertexBuffer>::_active = 0;
//wrapper around GLObjDelAlloc & GLObjBind
class VertexBuffer {
public:
explicit VertexBuffer() {
GLObjDelAlloc<Tags::VertexBuffer>::Allocate(1, &handle_);
}
inline void Bind() {
GLObjBind<Tags::VertexBuffer>::BindRequest(handle_);
}
template<typename T>
static void BufferData(const GLTypeCT<GLType::Integer> count, GLTypeCT<T>* data) {
glBufferData(GL_ARRAY_BUFFER, count *
sizeof(data->stride), data, GL_STATIC_DRAW);
}
VertexBuffer& operator=(const VertexBuffer& other) = delete;
VertexBuffer(const VertexBuffer& other) = delete;
private:
Tags::VertexBuffer::internal handle_;
};
} //namespace GLLayer
} //namespace Spiky
And here is my main:
int main(int argc, char** args)
{
GLTypeCT<GLfloat> quadVertices[] = {
// Positions // Texture Coords
-1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f,
};
// Setup plane VAO
glGenVertexArrays(1, &quadVAO);
VertexBuffer buffer{};
glBindVertexArray(quadVAO);
buffer.Bind();
VertexBuffer::BufferData(12, quadVertices);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat),
(GLvoid*)(0));
glBindVertexArray(0);
auto RenderQuad = [&] {
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
};
//render calls later on...
}
Do you think the error comes from VertexBuffer ?
I see a few possible issues here.
But first, 1280 means GL_INVALID_ENUM, where did you get this? After which opengl call?
In this:
static void BindRequest(Tags::VertexBuffer::internal name = ZERO_BUFFER) {
if(_active != name) {
glBindBuffer(GL_ARRAY_BUFFER, 0);
_active = name;
}
You should probably pass glBindBuffer what you want to bind. glBindBuffer(GL_ARRAY_BUFFER, name)
I doubt this is causing it to crash but, when you call glVertexAttribPointer you're passing it 3 * sizeof(float) when it should be 6 * sizeof(float), why? Because the stride should be the size of your entire "Vertex" which in your case contains the positions and texcoords, which sums up to 6 floats.
And when you're calling glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) you're saying that the count is 4, but as far as I can tell it's only 2.
The "access violation at 0x00000000", you get that if the function pointer to that function hasn't been retrieved, what are you using to get those pointers? I saw in the comments that you use SDL but that won't do any of that for you. You could do it yourself or use GLEW.
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.
I am trying to implement soft particles in my projects.
Everything is fine , I implement the texture also. But when the mouse is moved to a certain angle,
the particles get distorted. The particle is generated in view space.
So, I would like to know how could I implement the billboard in my project so that every particles seem uniform.Here is my code:
bool CETSmokeRenderer::InitBuffers()
{
size_t vertexSize = 3 * 4 * m_NumVertex * sizeof(float);
size_t colorSize = 4 * 4 * m_NumVertex * sizeof(float);
size_t texCoordSize = 2 * 4 * m_NumVertex * sizeof(float);
if(!vertexBuffer)
{
glDeleteBuffersARB(1, &vertexBuffer);
glDeleteBuffersARB(1, &colorBuffer);
glDeleteBuffersARB(1, &texCoordBuffer);
}
glGenBuffersARB(1, &vertexBuffer);
glGenBuffersARB(1, &colorBuffer);
glGenBuffersARB(1, &texCoordBuffer);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexSize, NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, colorSize, NULL, GL_STREAM_DRAW_ARB);
// Creates the static texture data
size_t len = 2 * 4 * m_NumVertex;
if(0 > m_NumVertex)
{
return false;
}
else if(0 == m_NumVertex)
{
return true;
}
float *texCoords = new float[len];
{
size_t i = 0;
while(i < len)
{
// u v
texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;
texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;
texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;
texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;
}
}
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texCoordBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, texCoordSize, (void*)texCoords, GL_STATIC_DRAW_ARB);
delete texCoords;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
return 0;
}
void CETSmokeRenderer::Draw(Camera &cam, bool useTex)
{
if(useTex)
glBindTexture(GL_TEXTURE_2D, texID);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
mBaseView->SetupViewingTransform();
size_t len = particleStore.size();
std::vector<SimpleSmokeParticle> toDraw;
for(size_t i = 0; i < len; i++)
{
SimpleSmokeParticle sp;
sp.transP = particleStore[i].p;
sp.index = i;
toDraw.push_back(sp);
}
//std::sort(toDraw.begin(), toDraw.end(), ParticleCmp);
#ifdef USE_VBO
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 3 * 4 * m_NumVertex * sizeof(float), NULL, GL_STREAM_DRAW_ARB);
float *vertexPtr = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
assert(vertexPtr);
for(size_t i = 0, count = 0; count < len; count++)
{
SmokeParticle &prt = particleStore[ toDraw[count].index ];
Point3f &p = toDraw[count].transP;
float w = prt.w / 0.5f;
float h = prt.h / 1.0f;
vertexPtr[i++] = p.x - w; vertexPtr[i++] = p.y - h; vertexPtr[i++] = p.z;
vertexPtr[i++] = p.x + w; vertexPtr[i++] = p.y - h; vertexPtr[i++] = p.z;
vertexPtr[i++] = p.x + w; vertexPtr[i++] = p.y + h; vertexPtr[i++] = p.z;
vertexPtr[i++] = p.x - w; vertexPtr[i++] = p.y + h; vertexPtr[i++] = p.z;
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 4 * 4 * m_NumVertex * sizeof(float), NULL, GL_STREAM_DRAW_ARB);
float *colorPtr = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
assert(colorBuffer);
for(size_t i = 0, count = 0; count < len; count++)
{
SmokeParticle &prt = particleStore[ toDraw[count].index ];
// r g b a
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
// Draws buffered data
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texCoordBuffer);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawArrays(GL_QUADS, 0, (GLsizei)len *4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
#else
{..}
glPopMatrix();
}
void CETSmokeRenderer::Render()
{
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Renders depth information
if(useSoftParticles)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
glClearColor(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX);
glClear(GL_COLOR_BUFFER_BIT);;
glUseProgramObjectARB(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_TRUE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_TRUE);
glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_TRUE);
glBindTexture(GL_TEXTURE_2D, 0);
// renders the soft particles
glUseProgramObjectARB(particleShader);
// Sets texture data
GLint texloc = glGetUniformLocationARB(particleShader, "tex");
GLint depthTexloc = glGetUniformLocationARB(particleShader, "depthInfo");
GLint powerloc = glGetUniformLocationARB(particleShader, "power");
glUniform1fARB(powerloc, (float)softParticlePower);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TextureID());
glUniform1iARB(texloc, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthTex);
glUniform1iARB(depthTexloc, 1);
Draw(m_pCamera, false);
// Unbinds shader and textures
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
}
else
{
glUseProgramObjectARB(particleShader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TextureID());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthTex);
Draw(m_pCamera, true);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
}
}
One way of achieving what you are looking for is to utilise point sprites, I have attached some code below that illustrates this in a simple way, hope this helps:
main.cpp
/*
Simple point-sprite particle demo - renders particles using spheres
Requirements:
GLM maths library
Freeglut
*/
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <iostream>
#include "GLSLShader.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_projection.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <cassert>
#define GL_CHECK_ERRORS assert(glGetError()== GL_NO_ERROR)
using namespace std;
class Screen
{
public:
int width, height;
string title;
unsigned int displayFlags, contextFlags;
Screen(string ititle, int iwidth = 1024, int iheight = 768){
Screen(ititle, (GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA), (GLUT_CORE_PROFILE | GLUT_DEBUG), iwidth, iheight)
}
Screen(string ititle, unsigned int disFlags, unsigned int contFlags, int iwidth = 1024, int iheight = 768){
title = ititle; width = iwidth; height = iheight;
displayFlags = disFlags;
contextFlags = contFlags;
}
};
const int TOTAL= 9;
GLfloat positions[3*TOTAL]={-1,0,-1, 0,0,-1, 1,0,-1,-1,0, 0, 0,0, 0, 1,0, 0,-1,0, 1, 0,0, 1, 1,0,1};
GLuint vboID, vaoID;
GLsizei stride = sizeof(GLfloat)*3;
GLSLShader shader;
int filling=1;
// Absolute rotation values (0-359 degrees) and rotiation increments for each frame
float rotation_x=0, rotation_x_increment=0.1f;
float rotation_y=0, rotation_y_increment=0.05f;
float rotation_z=0, rotation_z_increment=0.03f;
glm::mat4 P; //projection matrix;
bool bRotate=true;
void InitShaders(void)
{
shader.LoadFromFile(GL_VERTEX_SHADER, "shader.vert");
shader.LoadFromFile(GL_FRAGMENT_SHADER, "shader.frag");
shader.CreateAndLinkProgram();
shader.Use();
shader.AddAttribute("vVertex");
shader.AddUniform("Color");
shader.AddUniform("lightDir");
shader.AddUniform("MVP");
glUniform3f(shader("lightDir"), 0,0,1);
glUniform3f(shader("Color"),1,0,0);
shader.UnUse();
GL_CHECK_ERRORS;
}
void InitVAO() {
GL_CHECK_ERRORS;
//Create vao and vbo stuff
glGenVertexArrays(1, &vaoID);
glGenBuffers (1, &vboID);
GL_CHECK_ERRORS;
glBindVertexArray(vaoID);
glBindBuffer (GL_ARRAY_BUFFER, vboID);
glBufferData (GL_ARRAY_BUFFER, sizeof(positions), &positions[0], GL_STATIC_DRAW);
GL_CHECK_ERRORS;
glEnableVertexAttribArray(shader["vVertex"]);
glVertexAttribPointer (shader["vVertex"], 3, GL_FLOAT, GL_FALSE,stride,0);
glBindVertexArray(0);
GL_CHECK_ERRORS;
}
void SetupGLBase() {
glGetError();
GL_CHECK_ERRORS;
glClearColor(0.0f,0.0f,0.2f,0.0f);
GL_CHECK_ERRORS;
InitShaders();
InitVAO();
glEnable(GL_DEPTH_TEST); // We enable the depth test (also called z buffer)
GL_CHECK_ERRORS;
glPointSize(50);
}
void OnRender() {
GL_CHECK_ERRORS;
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
//setup matrices
glm::mat4 T = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, -5));
glm::mat4 Rx = glm::rotate(T, rotation_x, glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 Ry = glm::rotate(Rx, rotation_y, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 MV = glm::rotate(Ry, rotation_z, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 MVP = P*MV;
//draw the points
shader.Use();
glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glBindVertexArray(vaoID);
glDrawArrays(GL_POINTS, 0, TOTAL);
glBindVertexArray(0);
shader.UnUse();
glutSwapBuffers();
}
void OnResize(int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
//setup the projection matrix
P = glm::perspective(45.0f, (GLfloat)w/h, 1.f, 1000.f);
}
void OnShutdown() {
glDeleteBuffers(1, &vboID);
glDeleteVertexArrays(1, &vaoID);
}
void OnKey(unsigned char key, int x, int y)
{
switch (key)
{
case ' ': bRotate=!bRotate; break;
case 'r': case 'R':
if (filling==0)
{
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); // Filled Polygon Mode
filling=1;
}
else
{
glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); // Outline Polygon Mode
filling=0;
}
break;
}
}
void OnSpecialKey(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP: rotation_x_increment = rotation_x_increment +0.005f; break;
case GLUT_KEY_DOWN: rotation_x_increment = rotation_x_increment -0.005f; break;
case GLUT_KEY_LEFT: rotation_y_increment = rotation_y_increment +0.005f; break;
case GLUT_KEY_RIGHT: rotation_y_increment = rotation_y_increment -0.005f; break;
}
}
void OnIdle() {
if(bRotate) {
rotation_x = rotation_x + rotation_x_increment;
rotation_y = rotation_y + rotation_y_increment;
rotation_z = rotation_z + rotation_z_increment;
}
if (rotation_x > 359) rotation_x = 0;
if (rotation_y > 359) rotation_y = 0;
if (rotation_z > 359) rotation_z = 0;
glutPostRedisplay();
}
void glTestAndInfo(GLEnum glewInitResponse)
{
if (GLEW_OK != glewInitResponse) {
cerr<<"Error: "<<glewGetErrorString(glewInitResponse)<<endl;
} else {
if (GLEW_VERSION_3_3)
{
cout<<"Driver supports OpenGL 3.3 or greater.\nDetails:"<<endl;
}
}
cout<<"Using GLEW "<<glewGetString(GLEW_VERSION)<<endl;
cout<<"Vendor: "<<glGetString (GL_VENDOR)<<endl;
cout<<"Renderer: "<<glGetString (GL_RENDERER)<<endl;
cout<<"Version: "<<glGetString (GL_VERSION)<<endl;
cout<<"GLSL: "<<glGetString (GL_SHADING_LANGUAGE_VERSION)<<endl;
}
void main(int argc, char** argv) {
Screen *screen = news Screen("Point sprites as spheres in OpenGL 3.3");
atexit(OnShutdown);
glutInit(&argc, argv);
glutInitDisplayMode(screen->displayFlags);
glutInitContextVersion (3, 3);
glutInitContextFlags (screen->contextFlags);
glutInitWindowSize(screen->width, screen->height);
glutCreateWindow(screen->title);
glewExperimental = GL_TRUE;
glTestAndInfo(glewInit());
SetupGLBase();
glutDisplayFunc(OnRender);
glutReshapeFunc(OnResize);
glutKeyboardFunc(OnKey);
glutSpecialFunc(OnSpecialKey);
glutIdleFunc(OnIdle);
glutMainLoop();
}
GLSLShader.h
#pragma once
#ifndef GLSL_SHADER_H
#define GLSL_SHADER_H
#include <GL/glew.h>
#include <map>
#include <string>
using namespace std;
class GLSLShader
{
public:
GLSLShader(void);
~GLSLShader(void);
void LoadFromString(GLenum whichShader, const string source);
void LoadFromFile(GLenum whichShader, const string filename);
void CreateAndLinkProgram();
void Use();
void UnUse();
void AddAttribute(const string attribute);
void AddUniform(const string uniform);
GLuint operator[](const string attribute);// indexer: returns the location of the named attribute
GLuint operator()(const string uniform);
private:
enum ShaderType {VERTEX_SHADER, FRAGMENT_SHADER, GEOMETRY_SHADER};
GLuint _program;
int _totalShaders;
GLuint _shaders[3];//0 vertexshader, 1 fragmentshader, 2 geometryshader
map<string,GLuint> _attributeList;
map<string,GLuint> _uniformLocationList;
};
#endif
GLSLShader.cpp
/*
Really basic glsl shader class
*/
#include "GLSLShader.h"
#include <iostream>
#include <fstream>
// constructor
GLSLShader::GLSLShader(void)
{
_totalShaders=0;
_shaders[VERTEX_SHADER]=0;
_shaders[FRAGMENT_SHADER]=0;
_shaders[GEOMETRY_SHADER]=0;
_attributeList.clear();
_uniformLocationList.clear();
}
// destructor
GLSLShader::~GLSLShader(void)
{
_attributeList.clear();
_uniformLocationList.clear();
glDeleteProgram(_program);
}
// loader functions
void GLSLShader::LoadFromString(GLenum type, const string source) {
GLuint shader = glCreateShader (type);
const char * ptmp = source.c_str();
glShaderSource (shader, 1, &ptmp, NULL);
//check whether the shader loads fine
GLint status;
glCompileShader (shader);
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *infoLog= new GLchar[infoLogLength];
glGetShaderInfoLog (shader, infoLogLength, NULL, infoLog);
cerr<<"Compile log: "<<infoLog<<endl;
delete [] infoLog;
}
_shaders[_totalShaders++]=shader;
}
void GLSLShader::LoadFromFile(GLenum whichShader, const string filename){
ifstream fp;
fp.open(filename.c_str(), ios_base::in);
if(fp) {
string line, buffer;
while(getline(fp, line)) {
buffer.append(line);
buffer.append("\r\n");
}
//copy to source
LoadFromString(whichShader, buffer);
} else {
cerr<<"Error loading shader: "<<filename<<endl;
}
}
// utilitarian functions
void GLSLShader::CreateAndLinkProgram() {
_program = glCreateProgram ();
if (_shaders[VERTEX_SHADER] != 0) {
glAttachShader (_program, _shaders[VERTEX_SHADER]);
}
if (_shaders[FRAGMENT_SHADER] != 0) {
glAttachShader (_program, _shaders[FRAGMENT_SHADER]);
}
if (_shaders[GEOMETRY_SHADER] != 0) {
glAttachShader (_program, _shaders[GEOMETRY_SHADER]);
}
//link and check whether the program links fine
GLint status;
glLinkProgram (_program);
glGetProgramiv (_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetProgramiv (_program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *infoLog= new GLchar[infoLogLength];
glGetProgramInfoLog (_program, infoLogLength, NULL, infoLog);
cerr<<"Link log: "<<infoLog<<endl;
delete [] infoLog;
}
glDeleteShader(_shaders[VERTEX_SHADER]);
glDeleteShader(_shaders[FRAGMENT_SHADER]);
glDeleteShader(_shaders[GEOMETRY_SHADER]);
}
void GLSLShader::Use() {
glUseProgram(_program);
}
void GLSLShader::UnUse() {
glUseProgram(0);
}
void GLSLShader::AddAttribute(const string attribute) {
_attributeList[attribute]= glGetAttribLocation(_program, attribute.c_str());
}
// indexer: returns the location of the named attribute
GLuint GLSLShader::operator [](const string attribute) {
return _attributeList[attribute];
}
void GLSLShader::AddUniform(const string uniform) {
_uniformLocationList[uniform] = glGetUniformLocation(_program, uniform.c_str());
}
GLuint GLSLShader::operator()(const string uniform){
return _uniformLocationList[uniform];
}
This code is pretty old and I have no way to test rendering here (no distinct GFX card) so if there are any issues let me know and I can fix it once at my GFX dev machine.
Addendum:
Shaders may help too (dont know how I forgot them, old age maybe catching up on me!) so here they are:
Vertex shader (shader.vert)
#version 330 // set this to whatever minimum version you want to support
in vec3 vVertex;
uniform mat4 MVP;
void main()
{
gl_Position = MVP*vec4(vVertex,1);
}
Fragment shader (shader.frag)
#version 330
out vec4 vFragColour;
uniform vec3 Colour;
uniform vec3 lightDirection;
void main(void)
{
// calculate normal from texture coordinates
vec3 N;
N.xy = gl_PointCoord* 2.0 - vec2(1.0);
float mag = dot(N.xy, N.xy);
if (mag > 1.0) discard; // kill pixels outside the circle we want
N.z = sqrt(1.0-mag); // this might be expensive depending on your hardware
float diffuse = max(0.0, dot(lightDirection, N)); // calculate lighting
vFragColour = vec4(Colour,1) * diffuse;
}
Addendum 2:
To add the freeglut libraries to your build and resolve LNK 1104 errors simply go to *Project >> Properties >> VC++ Directories* and add the directories where your freeglut includes, source libraries and dlls are stored, for example for lib files go to
Add the folders as follows:
DLL Directories: add to Executable Directories
.h file Directories(include folder): add to Include Directories
.cpp file Directories: add to Source Directories
.lib file Directories: add to Library Directories
Hope this helps:)
OS : mac osx 10.8.3
compiler : clang3.2
I am a beginner of opengl, trying to play opengl with Qt5
There are two problems about this simple program(plot a triangle)
I can't see the triangle
The program could not exit even I close the window
hpp
#include <QGLWidget>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
class QWidget;
class ch1HelloTriangle : public QGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit ch1HelloTriangle(QWidget *parent = 0);
protected:
virtual void initializeGL();
void initShaders();
void InitializeVertexBuffer();
virtual void resizeGL(int w, int h);
virtual void paintGL();
private:
QOpenGLShaderProgram program;
GLuint positionBufferObject;
};
.cpp
#include <locale.h>
#include <QWidget>
#include "ch1HelloTriangle.hpp"
namespace
{
float const vertexPositions[] = {
0.75f, 0.75f, 0.0f, 1.0f,
0.75f, -0.75f, 0.0f, 1.0f,
-0.75f, -0.75f, 0.0f, 1.0f,
};
}
ch1HelloTriangle::ch1HelloTriangle(QWidget *parent) :
QGLWidget(parent)
{
}
void ch1HelloTriangle::initializeGL()
{
initializeOpenGLFunctions();
InitializeVertexBuffer();
initShaders();
}
void ch1HelloTriangle::initShaders()
{
// Override system locale until shaders are compiled
setlocale(LC_NUMERIC, "C");
// Compile vertex shader
if (!program.addShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute vec4 position;\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}\n"))
{
close();
}
// Compile fragment shader
if (!program.addShaderFromSourceCode(QOpenGLShader::Fragment,
"out vec4 outputColor;\n"
"void main()\n"
"{\n"
" outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"
"}\n"))
{
close();
}
// Link shader pipeline
if (!program.link())
close();
// Bind shader pipeline for use
if (!program.bind())
close();
// Restore system locale
setlocale(LC_ALL, "");
}
void ch1HelloTriangle::InitializeVertexBuffer()
{
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void ch1HelloTriangle::resizeGL(int w, int h)
{
// Set OpenGL viewport to cover whole widget
glViewport(0, 0, w, h);
}
void ch1HelloTriangle::paintGL()
{
/*
//codes propose by http://stackoverflow.com/questions/13111291/displaying-a-triangle-with-qt-and-opengl?rq=1, can't see the triangle either
QSize viewport_size = size();
glViewport(0, 0, viewport_size.width(), viewport_size.height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1, 1, -1, 1, 5, 7); // near and far match your triangle Z distance
glMatrixMode(GL_MODELVIEW);*/
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
int vertexLocation = program.attributeLocation("position");
program.enableAttributeArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
main.cpp
#include <QApplication>
#include "ch1HelloTriangle.hpp"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ch1HelloTriangle ch1;
ch1.show();
return a.exec();
}
After a lot of trial and error, I solved the problem.
Change two things :
1 : read the shader by files
// Compile vertex shader
if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, "modernOpenGLShader/ch1/vertex")){
QMessageBox::warning(this, "QOpenGLShader::Vertex", "QOpenGLShader::Vertex" + program.log());
close();
}
// Compile fragment shader
if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, "modernOpenGLShader/ch1/frag")){
QMessageBox::warning(this, "QOpenGLShader::Fragment", "QOpenGLShader::Fragment" + program.log());
close();
}
2 : change the fragment shader, remove the output variable
void main() {
//set every drawn pixel to white
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
From the websites, "modern opengl":http://www.arcsynthesis.org/gltut/
and "another site":tomdalling.com/blog/modern-opengl/01-getting-started-in-xcode-and-visual-cpp/
The output qualify should exist(atleast the codes of the second website will work on my pc)
But Qt will throw error message
QOpenGLShader::FragmentERROR: 0:4: Invalid qualifiers 'out' in global variable context
Do anyone know why?Thanks