OpenGL Texture flickers - opengl

I have the following Rust code to render a cube with a texture. I am using piston2d-opengl_graphics to load the textures.
My main.rs
extern crate sdl2;
extern crate glm;
extern crate gl;
extern crate libc;
extern crate num_traits;
extern crate opengl_graphics;
mod graphics;
use graphics::shader::Shader;
use sdl2::video::GLProfile;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use std::ffi::CString;
use std::ptr;
use num_traits::identities::One;
use gl::types::*;
use std::mem;
use std::path::Path;
fn find_sdl_gl_driver() -> Option<u32> {
for (index, item) in sdl2::render::drivers().enumerate() {
if item.name == "opengl" {
return Some(index as u32);
}
}
None
}
fn main() {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let gl_attr = video_subsystem.gl_attr();
gl_attr.set_context_profile(GLProfile::Core);
gl_attr.set_context_flags().debug().set();
gl_attr.set_context_version(3, 3);
gl_attr.set_depth_size(24);
gl_attr.set_red_size(8);
gl_attr.set_green_size(8);
gl_attr.set_blue_size(8);
gl_attr.set_alpha_size(8);
gl_attr.set_stencil_size(8);
let window = video_subsystem.window("Renderer", 1024, 768,).opengl().build().unwrap();
let renderer = window.renderer().present_vsync().index(find_sdl_gl_driver().unwrap()).build().unwrap();
unsafe {
gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);
renderer.window().unwrap().gl_set_context_to_current().unwrap();
gl::ClearColor(0.0, 0.0, 0.0, 1.0);
gl::Enable(gl::DEPTH_TEST);
gl::DepthFunc(gl::LESS);
}
let mut vao = 0;
unsafe {
gl::GenVertexArrays(1, &mut vao);
gl::BindVertexArray(vao);
}
let shader_program = Shader::new("shader.vert", "shader.frag").unwrap();
let mvp_location;
let texture_sampler_id;
unsafe {
mvp_location = gl::GetUniformLocation(shader_program.program, CString::new("MVP").unwrap().as_ptr());
texture_sampler_id = gl::GetUniformLocation(shader_program.program, CString::new("texture_sampler").unwrap().as_ptr());
}
let projection = glm::ext::perspective(45f32, 4f32 / 3f32, 0.1f32, 100f32);
let view = glm::ext::look_at(glm::Vec3::new(4f32, 3f32, 3f32),
glm::Vec3::new(0f32, 0f32, 0f32),
glm::Vec3::new(0f32, 1f32, 0f32));
let model_mat = glm::Matrix4::<f32>::one();
let mvp = projection * view * model_mat;
let mvp_array_vec4 = mvp.as_array();
let mut mvp_array: Vec<f32> = Vec::new();
for i in 0..mvp_array_vec4.len() {
for j in 0..4 {
mvp_array.push(mvp_array_vec4[i][j]);
}
}
let cube_vertices = vec![
-1.0f32,-1.0f32,-1.0f32,
-1.0f32,-1.0f32, 1.0f32,
-1.0f32, 1.0f32, 1.0f32,
1.0f32, 1.0f32,-1.0f32,
-1.0f32,-1.0f32,-1.0f32,
-1.0f32, 1.0f32,-1.0f32,
1.0f32,-1.0f32, 1.0f32,
-1.0f32,-1.0f32,-1.0f32,
1.0f32,-1.0f32,-1.0f32,
1.0f32, 1.0f32,-1.0f32,
1.0f32,-1.0f32,-1.0f32,
-1.0f32,-1.0f32,-1.0f32,
-1.0f32,-1.0f32,-1.0f32,
-1.0f32, 1.0f32, 1.0f32,
-1.0f32, 1.0f32,-1.0f32,
1.0f32,-1.0f32, 1.0f32,
-1.0f32,-1.0f32, 1.0f32,
-1.0f32,-1.0f32,-1.0f32,
-1.0f32, 1.0f32, 1.0f32,
-1.0f32,-1.0f32, 1.0f32,
1.0f32,-1.0f32, 1.0f32,
1.0f32, 1.0f32, 1.0f32,
1.0f32,-1.0f32,-1.0f32,
1.0f32, 1.0f32,-1.0f32,
1.0f32,-1.0f32,-1.0f32,
1.0f32, 1.0f32, 1.0f32,
1.0f32,-1.0f32, 1.0f32,
1.0f32, 1.0f32, 1.0f32,
1.0f32, 1.0f32,-1.0f32,
-1.0f32, 1.0f32,-1.0f32,
1.0f32, 1.0f32, 1.0f32,
-1.0f32, 1.0f32,-1.0f32,
-1.0f32, 1.0f32, 1.0f32,
1.0f32, 1.0f32, 1.0f32,
-1.0f32, 1.0f32, 1.0f32,
1.0f32,-1.0f32, 1.0f32
];
let cube_uv_coords: Vec<GLfloat> = vec![
0.000059, 1.0-0.000004,
0.000103, 1.0-0.336048,
0.335973, 1.0-0.335903,
1.000023, 1.0-0.000013,
0.667979, 1.0-0.335851,
0.999958, 1.0-0.336064,
0.667979, 1.0-0.335851,
0.336024, 1.0-0.671877,
0.667969, 1.0-0.671889,
1.000023, 1.0-0.000013,
0.668104, 1.0-0.000013,
0.667979, 1.0-0.335851,
0.000059, 1.0-0.000004,
0.335973, 1.0-0.335903,
0.336098, 1.0-0.000071,
0.667979, 1.0-0.335851,
0.335973, 1.0-0.335903,
0.336024, 1.0-0.671877,
1.000004, 1.0-0.671847,
0.999958, 1.0-0.336064,
0.667979, 1.0-0.335851,
0.668104, 1.0-0.000013,
0.335973, 1.0-0.335903,
0.667979, 1.0-0.335851,
0.335973, 1.0-0.335903,
0.668104, 1.0-0.000013,
0.336098, 1.0-0.000071,
0.000103, 1.0-0.336048,
0.000004, 1.0-0.671870,
0.336024, 1.0-0.671877,
0.000103, 1.0-0.336048,
0.336024, 1.0-0.671877,
0.335973, 1.0-0.335903,
0.667969, 1.0-0.671889,
1.000004, 1.0-0.671847,
0.667979, 1.0-0.335851
];
let texture = opengl_graphics::Texture::from_path(&Path::new("uvtemplate.jpg")).unwrap();
let mut vertex_buffer: GLuint = 0;
let mut uv_buffer: GLuint = 0;
unsafe {
// generate buffer for the cube vertices
gl::GenBuffers(1, &mut vertex_buffer);
gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer);
gl::BufferData(gl::ARRAY_BUFFER, (cube_vertices.len() * mem::size_of::<f32>()) as GLsizeiptr,
mem::transmute(&cube_vertices[0]), gl::STATIC_DRAW);
// generate buffer for the uv coordinates
gl::GenBuffers(1, &mut uv_buffer);
gl::BindBuffer(gl::ARRAY_BUFFER, uv_buffer);
gl::BufferData(gl::ARRAY_BUFFER, (cube_uv_coords.len() * mem::size_of::<f32>()) as GLsizeiptr,
mem::transmute(&cube_uv_coords[0]), gl::STATIC_DRAW);
}
let mut event_pump = sdl_context.event_pump().unwrap();
'running: loop {
for event in event_pump.poll_iter() {
match event {
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
break 'running
},
_ => {}
}
}
unsafe { gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT) };
shader_program.use_program();
unsafe {
gl::UniformMatrix4fv(mvp_location, 1, gl::FALSE, mvp_array.as_ptr());
// bind texture to texture unit 0 and tell sampler to use unit 0
gl::ActiveTexture(gl::TEXTURE0);
gl::BindTexture(gl::TEXTURE_2D, texture.get_id());
gl::Uniform1i(texture_sampler_id, 0);
// set vertex data
gl::EnableVertexAttribArray(0);
gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer);
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, 0, ptr::null_mut());
// set uv data
gl::EnableVertexAttribArray(1);
gl::BindBuffer(gl::ARRAY_BUFFER, uv_buffer);
gl::VertexAttribPointer(1, 2, gl::FLOAT, gl::FALSE, 0, ptr::null_mut());
gl::DrawArrays(gl::TRIANGLES, 0, 12 * 3);
gl::DisableVertexAttribArray(0);
gl::DisableVertexAttribArray(1);
}
renderer.window().unwrap().gl_swap_window();
}
}
My shader.rs:
extern crate glm;
extern crate gl;
use self::gl::types::*;
use std::fs::File;
use std::io::Read;
use std::io;
use std::fmt;
use std::error;
use std::ffi::CString;
use std::ptr;
use std::str;
#[derive(Debug)]
pub enum ShaderError {
IoError(io::Error),
CompilationError(String),
LinkError(String),
InfoLogError(str::Utf8Error)
}
impl fmt::Display for ShaderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ShaderError::IoError(ref error) => write!(f, "IO Error: {}", error),
ShaderError::CompilationError(ref error) => write!(f, "Shader compilation error: {}", error),
ShaderError::LinkError(ref error) => write!(f, "Linking error: {}", error),
ShaderError::InfoLogError(ref error) => write!(f, "InfoLog Error: {}", error),
}
}
}
impl error::Error for ShaderError {
fn description(&self) -> &str {
match *self {
ShaderError::IoError(ref err) => err.description(),
ShaderError::CompilationError(..) => "Error during shader compilation",
ShaderError::LinkError(..) => "Error during linking",
ShaderError::InfoLogError(ref err) => err.description(),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
ShaderError::IoError(ref error) => Some(error),
ShaderError::InfoLogError(ref error) => Some(error),
_ => None
}
}
}
impl From<io::Error> for ShaderError {
fn from(err: io::Error) -> ShaderError {
ShaderError::IoError(err)
}
}
impl From<str::Utf8Error> for ShaderError {
fn from(err: str::Utf8Error) -> ShaderError {
ShaderError::InfoLogError(err)
}
}
pub struct Shader
{
pub vertex_path: String,
pub fragment_path: String,
pub program: GLuint
}
impl Shader
{
pub fn new(vert_path: &str, frag_path: &str) -> Result<Shader, ShaderError> {
let vertex_shader = try!(Shader::compile_shader(vert_path, gl::VERTEX_SHADER));
let fragment_shader = try!(Shader::compile_shader(frag_path, gl::FRAGMENT_SHADER));
let program = try!(Shader::link_program(vertex_shader, fragment_shader));
Ok(Shader {
vertex_path: vert_path.to_string(),
fragment_path: frag_path.to_string(),
program: program
})
}
fn compile_shader(path: &str, shader_type: GLenum) -> Result<GLuint, ShaderError> {
let mut shader_data = String::new();
let mut file = try!(File::open(path));
try!(file.read_to_string(&mut shader_data));
let shader;
unsafe {
shader = gl::CreateShader(shader_type);
let shader_src = CString::new(shader_data.as_bytes()).unwrap();
gl::ShaderSource(shader, 1, &shader_src.as_ptr(), ptr::null());
gl::CompileShader(shader);
// Get the compile status
let mut status = gl::FALSE as GLint;
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
// Fail on error
if status != (gl::TRUE as GLint) {
let mut len = 0;
gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
let mut buf = Vec::with_capacity(len as usize);
buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character
gl::GetShaderInfoLog(shader, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
return match str::from_utf8(&buf) {
Ok(msg) => Err(ShaderError::CompilationError(msg.to_string())),
Err(err) => Err(ShaderError::InfoLogError(err))
}
}
}
Ok(shader)
}
fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> Result<GLuint, ShaderError> {
unsafe {
let program = gl::CreateProgram();
gl::AttachShader(program, vertex_shader);
gl::AttachShader(program, fragment_shader);
gl::LinkProgram(program);
// get link status
let mut status = gl::FALSE as GLint;
gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
// Fail on error
if status != (gl::TRUE as GLint) {
let mut len: GLint = 0;
gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
let mut buf = Vec::with_capacity(len as usize);
buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character
gl::GetProgramInfoLog(program, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
return match str::from_utf8(&buf) {
Ok(msg) => Err(ShaderError::LinkError(msg.to_string())),
Err(err) => Err(ShaderError::InfoLogError(err))
}
}
Ok(program)
}
}
pub fn use_program(&self) {
unsafe {
gl::UseProgram(self.program);
}
}
}
My vertex shader:
#version 330 core
layout(location = 0) in vec3 vertex_position_modelspace;
layout(location = 1) in vec2 vertex_uv;
out vec2 uv_coord;
uniform mat4 MVP;
void main()
{
gl_Position = MVP * vec4(vertex_position_modelspace, 1);
uv_coord = uv_coord;
}
My fragment shader:
#version 330 core
in vec2 uv_coord;
out vec3 color;
uniform sampler2D texture_sampler;
void main()
{
color = texture(texture_sampler, uv_coord).rgb;
}
Whenever I try and render the cube, I always end up with a results like
It always flickers and doesn't show the proper result:
I tried using glutin as the window manager, but that didn't work, so I tried switching to SDL2, but that doesn't work either. I also tried it with a BMP file instead of a JPEG, but I got the same result. However, if I write the same code in C++, then I get the correct result.
Here's my C++ code, which renders the cube correctly:
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/ext.hpp>
using namespace glm;
GLuint LoadShader(const char * vertex_file_path, const char * fragment_file_path) {
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if (VertexShaderStream.is_open()) {
std::string Line = "";
while (getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}
else {
printf("Impossible to open %s. \n", vertex_file_path);
getchar();
return 0;
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if (FragmentShaderStream.is_open()) {
std::string Line = "";
while (getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
printf("Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
GLuint loadBMP(const char * imagepath) {
printf("Reading %s\n", imagepath);
// Data read from the header of the BMP file
unsigned char header[54];
unsigned int dataPos;
unsigned int imageSize;
unsigned int width, height;
// Actual RGB data
unsigned char * data;
// Open the file
FILE * file = fopen(imagepath, "rb");
if (!file)
{
printf("%s could not be opened.\n", imagepath);
getchar();
return 0;
}
// Read the header, i.e. the 54 first bytes
// If less than 54 bytes are read, problem
if (fread(header, 1, 54, file) != 54) {
printf("Not a correct BMP file\n");
return 0;
}
// A BMP files always begins with "BM"
if (header[0] != 'B' || header[1] != 'M') {
printf("Not a correct BMP file\n");
return 0;
}
// Make sure this is a 24bpp file
if (*(int*)&(header[0x1E]) != 0)
{
printf("Not a correct BMP file\n");
return 0;
}
if (*(int*)&(header[0x1C]) != 24)
{
printf("Not a correct BMP file\n");
return 0;
}
// Read the information about the image
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
if (imageSize == 0) imageSize = width*height * 3;
if (dataPos == 0) dataPos = 54;
data = new unsigned char[imageSize];
// Read the actual data from the file into the buffer
fread(data, 1, imageSize, file);
fclose(file);
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
delete[] data;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenerateMipmap(GL_TEXTURE_2D);
return textureID;
}
int main(void)
{
// Initialise GLFW
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(1024, 768, "Tutorial 05 - Textured Cube", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true;
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint programID = LoadShader("shader.vert", "shader.frag");
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(4, 3, 3),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * View * Model;
GLuint Texture = loadBMP("uvtemplate.bmp");
// Get a handle for "textureSampler" uniform
GLuint TextureID = glGetUniformLocation(programID, "textureSampler");
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
static const GLfloat g_uv_buffer_data[] = {
0.000059f, 1.0f - 0.000004f,
0.000103f, 1.0f - 0.336048f,
0.335973f, 1.0f - 0.335903f,
1.000023f, 1.0f - 0.000013f,
0.667979f, 1.0f - 0.335851f,
0.999958f, 1.0f - 0.336064f,
0.667979f, 1.0f - 0.335851f,
0.336024f, 1.0f - 0.671877f,
0.667969f, 1.0f - 0.671889f,
1.000023f, 1.0f - 0.000013f,
0.668104f, 1.0f - 0.000013f,
0.667979f, 1.0f - 0.335851f,
0.000059f, 1.0f - 0.000004f,
0.335973f, 1.0f - 0.335903f,
0.336098f, 1.0f - 0.000071f,
0.667979f, 1.0f - 0.335851f,
0.335973f, 1.0f - 0.335903f,
0.336024f, 1.0f - 0.671877f,
1.000004f, 1.0f - 0.671847f,
0.999958f, 1.0f - 0.336064f,
0.667979f, 1.0f - 0.335851f,
0.668104f, 1.0f - 0.000013f,
0.335973f, 1.0f - 0.335903f,
0.667979f, 1.0f - 0.335851f,
0.335973f, 1.0f - 0.335903f,
0.668104f, 1.0f - 0.000013f,
0.336098f, 1.0f - 0.000071f,
0.000103f, 1.0f - 0.336048f,
0.000004f, 1.0f - 0.671870f,
0.336024f, 1.0f - 0.671877f,
0.000103f, 1.0f - 0.336048f,
0.336024f, 1.0f - 0.671877f,
0.335973f, 1.0f - 0.335903f,
0.667969f, 1.0f - 0.671889f,
1.000004f, 1.0f - 0.671847f,
0.667979f, 1.0f - 0.335851f
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_uv_buffer_data), g_uv_buffer_data, GL_STATIC_DRAW);
do {
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
glUniform1i(TextureID, 0);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawArrays(GL_TRIANGLES, 0, 12 * 3);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
// Cleanup VBO and shader
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &uvbuffer);
glDeleteProgram(programID);
glDeleteTextures(1, &TextureID);
glDeleteVertexArrays(1, &VertexArrayID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}

Related

OpenGL with GLFW and GLEW not rendering cube? C++, GLM

I don't have very much experience with OpenGL, GLFW, or GLEW so my troubleshooting ability with these libraries is slim to none. I have managed to render a triangle ([-1, -1, 0], [1, -1, 0], [0, 1, 0]) but when using the vertex attribute coordinates for a cube, along with color attributes it seems to not render. There could be a lot wrong with my code, the shaders, and my matrix operations. I wish I had a clearer understanding of what I'm doing so I could give a more descriptive account of my error. Currently the above code only renders the window. I followed https://learnopengl.com/ initially and got the first tutorials working, the following code is my "testing" file where I've attempted to reimplement some of the elements myself. There are lots of copy pasted portions that may be shared with that tutorial if it helps at all.
Any insight or suggestions would be appreciated very much.
Main Source
#include "global.hpp"
using namespace std;
using namespace glm;
static const GLfloat g_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f,-1.0f, // triangle 2 : begin
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f, // triangle 2 : end
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
extern const char* VertexShader = R"(
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;
uniform mat4 MVP;
out vec3 fragmentColor;
//out vec2 UV;
void main(){
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
//UV = vertexUV;
fragmentColor = vertexColor;
}
)";
extern const char* FragmentShader = R"(
#version 330 core
in vec3 fragmentColor;
out vec3 color;
void main(){
//color = vec3(1,0,0);
color = fragmentColor;
}
)";
static const float tri_vertex_array[] = {
-.8, .8, 0,
-.8, -.8, 0,
.8, -.8, 0
};
int main()
{
if (!glfwInitFull()) {
printf("Unable To Init\n");
return 1;
}
uint width = 1200, height = 720;
GLFWwindow* window = glfwCreateWindow(width, height, "ME", 0, 0);
if (!window)
return -1;
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
return 0;
//
GLuint VertexArrayId;
glGenVertexArrays(1, &VertexArrayId);
glBindVertexArray(VertexArrayId);
//
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
//glBufferData(GL_ARRAY_BUFFER, sizeof(tri_vertex_array), tri_vertex_array, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint colorBuffer;
glGenBuffers(1, &colorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
GLuint vertexShaderId = compileShader(VertexShader, GL_VERTEX_SHADER);
GLuint fragmentShaderId = compileShader(FragmentShader, GL_FRAGMENT_SHADER);
GLuint programId = glCreateProgram();
linkShader(programId, vertexShaderId);
linkShader(programId, fragmentShaderId);
// maybe nessacary?
//glMatrixMode(GL_PROJECTION);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LESS);
glEnable(GL_CULL_FACE);
glViewport(0, 0, width, height);
//vec3 cameraPos = vec3(0.f, 0.f, 3.f);
//vec3 cameraTarget = vec3(0.f, 0.f, 0.f);
//vec3 cameraDirection = normalize(cameraPos - cameraTarget);
//
//vec3 up = vec3(0.f, 1.f, 0.f);
//vec3 right = normalize(
// cross(
// up,
// cameraDirection
// )
//);
//
//vec3 cameraUp = cross(cameraDirection, right);
//
//mat4 view = lookAt(
// vec3(4.f, 3.f, 3.f),
// vec3(0.f, 0.f, 0.f),
// vec3(0.f, 1.f, 0.f)
//);
mat4 projection = perspective(radians(45.f), width / (float)height, .1f, 100.f);
mat4 view = lookAt(
vec3(4, 3, -3),
vec3(0, 0, 0),
vec3(0, 1, 0)
);
mat4 model = mat4(1.0f); // identity
mat4 mvp = projection * view * model;
GLuint mvpId = glGetUniformLocation(programId, "MVP");
do {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.f, 0.f, .4f, 0.f);
glUseProgram(programId);
//gluLookAt(
// 4, 3, 3,
// 0, 0, 0,
// 0, 1, 0
//);
glUniformMatrix4fv(mvpId, 1, 0, &mvp[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
NULL
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glVertexAttribPointer(
1,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawArrays(GL_TRIANGLES, 0, 3*12);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glfwSwapBuffers(window);
glfwPollEvents();
} while (
!glfwWindowShouldClose(window)
&&
!glfwGetKey(window, GLFW_KEY_ESCAPE)
);
glfwTerminate();
}
global.hpp
#ifndef _glfw3_h_
// opengl extensions
#include <GL/glew.h>
// opengl utility / wrapper
#include <GLFW/glfw3.h>
// operations in space
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#endif // !_glfw3_h_
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include <fstream>
#include <random>
#include <ctime>
#include <cmath>
static void glfwErrorCb(int errorCode, const char* error) {
printf("GLFW Error Thrown\n -> %d\n%s\n", errorCode, error);
}
static bool glfwInitFull() {
srand(time(0));
if (!glfwInit())
return 0;
glfwSetErrorCallback(glfwErrorCb);
glewExperimental = true;
glfwWindowHint(GLFW_SAMPLES, 4); // anti-aliasing
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // version
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // version
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // no-old-gl
return 1;
}
static GLuint compileShader(const char* content, GLenum type) {
GLuint shaderId = glCreateShader(type);
GLint returnValBuf;
glShaderSource(shaderId, 1, &content, NULL);
glCompileShader(shaderId);
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &returnValBuf);
if (returnValBuf == GL_FALSE) {
printf("Unable To Compile Shader\n```\n%s\n```\n\nInfo Log:\n", content);
GLint logLen;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLen);
if (logLen <= 0)
return 0;
char* infoBuffer = new char[logLen + 1];
infoBuffer[logLen] = '\0';
glGetShaderInfoLog(shaderId, logLen, &returnValBuf, infoBuffer);
printf("%s\n", infoBuffer);
delete[] infoBuffer;
return 0;
}
return shaderId;
}
static GLuint linkShader(GLuint programId, GLuint shaderId) {
glAttachShader(programId, shaderId);
glLinkProgram(programId);
GLint returnValBuf;
glGetProgramiv(programId, GL_LINK_STATUS, &returnValBuf);
if (returnValBuf == GLFW_FALSE) {
printf("Unable To Link Shader\nInfo Log:\n");
GLint logLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);
if (logLen <= 0)
return 0;
char* infoBuffer = new char[logLen + 1];
infoBuffer[logLen] = '\0';
glGetProgramInfoLog(programId, logLen, &returnValBuf, infoBuffer);
printf("%s\n", infoBuffer);
delete[] infoBuffer;
}
glDetachShader(programId, shaderId);
glDeleteShader(shaderId);
return programId;
}
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long long ullong;
#pragma once
The problem is that you call linkShader separately for each shader. It is possible to link a program multiple times. The function linkShader, however, attaches the shader to the program, linkes the program and detaches the shader from the program. Hence, the vertex and the fragment shader are never attached at the same time.
Attach the vertex and fragment shader and call linkShader once:
static GLuint linkShader(GLuint programId) {
glLinkProgram(programId);
GLint returnValBuf;
glGetProgramiv(programId, GL_LINK_STATUS, &returnValBuf);
if (returnValBuf == GLFW_FALSE) {
printf("Unable To Link Shader\nInfo Log:\n");
GLint logLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);
if (logLen <= 0)
return 0;
char* infoBuffer = new char[logLen + 1];
infoBuffer[logLen] = '\0';
glGetProgramInfoLog(programId, logLen, &returnValBuf, infoBuffer);
printf("%s\n", infoBuffer);
delete[] infoBuffer;
}
return programId;
}
int main()
{
// [...]
GLuint vertexShaderId = compileShader(VertexShader, GL_VERTEX_SHADER);
GLuint fragmentShaderId = compileShader(FragmentShader, GL_FRAGMENT_SHADER);
GLuint programId = glCreateProgram();
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
linkShader(programId);
glDetachShader(programId, vertexShaderId);
glDeleteShader(vertexShaderId);
glDetachShader(programId, fragmentShaderId);
glDeleteShader(fragmentShaderId);
// [...]
}

Correct way to switch vertex / color buffers OpenGL

I am trying to use a common function I wrote called box() to draw multiple boxes in OpenGL 4.5. It seems to work reasonably well, and I can get it to make multiple boxes.
However, I'm having trouble drawing what will become the bottom of a cylinder. I'm trying to generate the faces by making multiple triangles. The triangles share a vertex at the center, and the other vertices are based on the angle.
I know you can do this with a triangle fan or strip, but I need to be able to specify normals for each vertex later on, too.
My problem is, when I render this scene, I just see a single, lonely, triangle floating about. This brings up two major questions:
1) Where am I going wrong? I verified the x and z coordinates are correct via printf output just to see what was getting generated.
2) What is the correct method for swapping the vertex and color buffers out when drawing completely different shapes. For instance, I need to be able to eventually call box(), make some transforms, call cylinder(), etc.
//compiled with g++ -std=c++11 test.cpp -Wall -Werror -lglut -lGLU -lGL -lm -lGLEW
// Link statically with GLEW
#define GLEW_STATIC
// Headers
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace glm;
//Glut
#include <GL/glut.h>
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <chrono>
using namespace std::chrono;
#include "cube.h"
#define Cos(x) (cos((x)*3.1415927/180))
#define Sin(x) (sin((x)*3.1415927/180))
GLuint MatrixID;
glm::mat4 MVP;
GLuint vertexbuffer;
GLuint colorbuffer;
GLuint shaderProgram;
high_resolution_clock::time_point t_start;
static const GLchar* vertexSource = {
"#version 330 core\n"
"\n"
"// Input vertex data, different for all executions of this shader.\n"
"layout(location = 0) in vec3 vertexPosition_modelspace;"
"layout(location = 1) in vec3 vertexColor;"
"\n"
"// Output data ; will be interpolated for each fragment.\n"
"out vec3 fragmentColor;"
"// Values that stay constant for the whole mesh.\n"
"uniform mat4 MVP;"
"\n"
"void main(){ "
"\n"
" // Output position of the vertex, in clip space : MVP * position\n"
" gl_Position = MVP * vec4(vertexPosition_modelspace,1);"
"\n"
" // The color of each vertex will be interpolated\n"
" // to produce the color of each fragment\n"
" fragmentColor = vertexColor;"
"}"
};
static const GLchar* fragmentSource = {
"#version 330 core\n"
"\n"
"// Interpolated values from the vertex shaders\n"
"in vec3 fragmentColor;"
"\n"
"// Ouput data\n"
"out vec3 color;"
"\n"
"void main(){"
"\n"
" // Output color = color specified in the vertex shader, \n"
" // interpolated between all 3 surrounding vertices\n"
" color = fragmentColor;"
"\n"
"}"
};
void checkError(int line)
{
GLint err;
do
{
err = glGetError();
switch (err)
{
case GL_NO_ERROR:
//printf("%d: No error\n", line);
break;
case GL_INVALID_ENUM:
printf("%d: Invalid enum!\n", line);
break;
case GL_INVALID_VALUE:
printf("%d: Invalid value\n", line);
break;
case GL_INVALID_OPERATION:
printf("%d: Invalid operation\n", line);
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
printf("%d: Invalid framebuffer operation\n", line);
break;
case GL_OUT_OF_MEMORY:
printf("%d: Out of memory\n", line);
break;
default:
printf("%d: glGetError default case. Should not happen!\n", line);
}
} while (err != GL_NO_ERROR);
}
int loadShaders()
{
GLuint vertexShader;
GLuint fragmentShader;
// Create shaders
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
checkError(__LINE__);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
checkError(__LINE__);
// Create program and link to shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "color");
glLinkProgram(shaderProgram);
checkError(__LINE__);
glUseProgram(shaderProgram);
//TODO: add error checking and return code.
checkError(__LINE__);
return 0;
}
glm::mat4 Projection;
glm::mat4 View;
glm::mat4 Model;
void box()
{
MVP = Projection * View * Model;
// Send our transformation to the currently bound shader
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangles
Model = glm::mat4(1.0);
}
typedef struct __vertex
{
GLfloat x;
GLfloat y;
GLfloat z;
} vertex_t;
typedef struct __color
{
GLfloat r;
GLfloat g;
GLfloat b;
} color_t;
void cylinder()
{
int theta = 0;
int dt = 15;
int i = 0;
vertex_t *pVert;
color_t *pColor;
// Bottom face
// 360 / dt = number of triangles
// Multiplied by 3 verticies per triangle
// Multiplied by 3 floating points to describe each vertex
GLfloat *vertex_buffer_data = new GLfloat[360 / dt * 9];
GLfloat *color_buffer_data = new GLfloat[360 / dt * 9];
for (theta=0; theta < 360; theta += dt, i += sizeof(vertex_t) / sizeof(GLfloat))
{
pVert = (vertex_t *)(vertex_buffer_data + i);
pColor = (color_t *)(color_buffer_data + i);
printf("theta: %d\n", theta);
pVert[0].x = 0;
pVert[0].y = 0;
pVert[0].z = 0;
pVert[1].x = Cos(theta);
pVert[1].y = 0;
pVert[1].z = Sin(theta);
printf("Vertex 1: %f %f %f\n", pVert[1].x, pVert[1].y, pVert[1].z);
pVert[2].x = Cos(theta + dt);
pVert[2].y = 0;
pVert[2].z = Sin(theta + dt);
printf("Vertex 2: %f %f %f\n", pVert[2].x, pVert[2].y, pVert[2].z);
pColor[0].r = 1.0f;
pColor[0].g = 1.0f;
pColor[0].b = 1.0f;
pColor[1].r = Cos(theta)*Cos(theta);
pColor[1].g = Sin(theta)*Sin(theta);
pColor[1].b = Cos(theta)*Cos(theta);
pColor[1].r = Cos(theta + dt)*Cos(theta + dt);
pColor[1].g = Sin(theta + dt)*Sin(theta + dt);
pColor[1].b = Cos(theta + dt)*Cos(theta + dt);
}
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 360 / dt * 9, vertex_buffer_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 360 / dt * 9, color_buffer_data, GL_STATIC_DRAW);
MVP = Projection * View * Model;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glDrawArrays(GL_TRIANGLES, 0, 360 / dt * 9); // 12*3 indices starting at 0 -> 12 triangles
Model = glm::mat4(1.0);
delete[] vertex_buffer_data;
delete[] color_buffer_data;
}
void display()
{
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
View = glm::lookAt(
glm::vec3(0,3,0), // Camera is at (4,3,-3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,0,1) // Head is up (set to 0,-1,0 to look upside-down)
);
//auto t_now = high_resolution_clock::now();
//float time = duration_cast<duration<float>>(t_now - t_start).count();
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Model = glm::mat4(1.0);
cylinder();
/*
Model = glm::scale(Model, glm::vec3(0.5, 0.5, 0.5)) * glm::rotate(Model, glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f));
box();
Model = glm::translate(Model, glm::vec3(0.5, 2.5, 0.0)) * glm::scale(Model, glm::vec3(0.25, 0.25, 0.25)) * glm::rotate(Model, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 1.0f));
box();
*/
glFlush();
glutSwapBuffers();
}
void reshape(int width,int height)
{
// Set viewport as entire window
glViewport(0,0, width,height);
glutPostRedisplay();
}
void idle()
{
//glutPostRedisplay();
}
int init(int argc, char** argv)
{
t_start = high_resolution_clock::now();
glutInitWindowSize(640, 400);
glutInitWindowPosition (140, 140);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInit(&argc, argv);
glutCreateWindow( "OpenGL Application" );
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
loadShaders();
glEnable(GL_DEPTH_TEST);
MatrixID = glGetUniformLocation(shaderProgram, "MVP");
// Load models
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_cube_vertex_buffer_data), g_cube_vertex_buffer_data, GL_STATIC_DRAW);
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_cube_color_buffer_data), g_cube_color_buffer_data, GL_STATIC_DRAW);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
return 0;
}
int main(int argc, char** argv)
{
if (init(argc, argv) != 0) { return -1; }
glutMainLoop();
return 0;
}
cube.h is just a buffers of vertices and colors:
#ifndef __CUBE_H__
#define __CUBE_H__
static const GLfloat g_cube_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
// One color for each vertex. They were generated randomly.
static const GLfloat g_cube_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
#endif // __CUBE_H__

Can't catch keys press events in GLFW

The piece of code you find below draws a cube with a camera inside of it.
I don't understand why when I press escape key or the right, left, up and down arrow keys the program doesn't catch the event.
Inside key_callback I've added std::cout << key << std::endl; expecting to see on the console the identifier of the pressed keys, but everytime I press any keys nothing is printed in the console.
#include <cstdlib>
#include <iostream>
#include <vector>
#include <array>
#include <chrono>
using timer = std::chrono::high_resolution_clock;
#ifdef _WIN32
#include <GL/glew.h>
#else
#define GLFW_INCLUDE_GLCOREARB
#define GL_GLEXT_PROTOTYPES
#endif
#define PI 3.1415926535897932384626433832795f
#include <GLFW/glfw3.h>
#include "lodepng.hpp"
#define GLM_FORCE_RADIANS
#include "glm/glm.hpp"
#include "glm/gtx/norm.hpp"
#include "glm/gtx/rotate_vector.hpp"
#include "glm/gtc/matrix_transform.hpp"
#if defined(_MSC_VER)
#pragma comment(lib,"user32")
#pragma comment(lib,"gdi32")
#pragma comment(lib,"opengl32")
#pragma comment(lib,"glew32")
#pragma comment(lib,"glfw3")
#endif
glm::vec3 camera_position(0.0f, 0.0f, 6.0f);
glm::vec3 camera_direction(0.0f, 0.0f, -1.0f);
glm::vec3 camera_up(0.0f, 1.0f, 0.0f);
using timer = std::chrono::high_resolution_clock;
timer::time_point start_time, last_time;
float t = 0.0;
float dt = 0.0;
bool translate_forward = false;
bool translate_backward = false;
bool translate_right = false;
bool translate_left = false;
bool rotate_up = false;
bool rotate_down = false;
bool rotate_right = false;
bool rotate_left = false;
bool rotate_z_left = false;
bool rotate_z_right = false;
bool sky_on = true;
bool sun_visible = true;
bool earth_visible = true;
bool moon_visible = true;
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
GLuint tex_flag;
static void error_callback(int error, const char* description)
{
std::cerr << description << std::endl;
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
std::cout << key << std::endl;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_UP)
{
if (action)
rotate_up = true;
else
rotate_up = false;
}
if (key == GLFW_KEY_DOWN)
{
if (action)
rotate_down = true;
else
rotate_down = false;
}
if (key == GLFW_KEY_RIGHT)
{
if (action)
rotate_right = true;
else
rotate_right = false;
}
if (key == GLFW_KEY_LEFT)
{
if (action)
rotate_left = true;
else
rotate_left = false;
}
}
// Shader sources
const GLchar* vertexSource =
#if defined(__APPLE_CC__)
"#version 150 core\n"
#else
"#version 130\n"
#endif
"in vec3 position;"
"in vec3 color;"
"in vec2 coord;"
"out vec3 Color;"
"out vec2 Coord;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main() {"
" Color = color;"
" Coord = coord;"
" gl_Position = projection * view * model * vec4(position, 1.0);"
"}";
const GLchar* fragmentSource =
#if defined(__APPLE_CC__)
"#version 150 core\n"
#else
"#version 130\n"
#endif
"in vec3 Color;"
"in vec2 Coord;"
"out vec4 outColor;"
"uniform sampler2D textureSampler;"
"void main() {"
" outColor = vec4(Color, 1.0)*texture(textureSampler, Coord);"
"}";
const GLfloat vertices[] = {
// Position Color Texcoords
-0.5f, 0.5f, -0.5f, 0.15f, 0.33f, 0.55f, .25f, 0.0f, // 0
0.5f, 0.5f, -0.5f, 0.15f, 0.33f, 0.55f, 0.5f, 0.0f, // 1
-0.5f, 0.5f, -0.5f, 0.15f, 0.33f, 0.55f, 0.0f, 1.f / 3.f, // 2
-0.5f, 0.5f, 0.5f, 0.15f, 0.33f, 0.55f, .25f, 1.f / 3.f, // 3
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.5f, 1.f / 3.f, // 4
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, .75f, 1.f / 3.f, // 5
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.f / 3.f, // 6
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 2.f / 3.f, // 7
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, .25f, 2.f / 3.f, // 8
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.5f, 2.f / 3.f, // 9
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, .75f, 2.f / 3.f, // 10
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 2.f / 3.f, // 11
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, .25f, 1.0f, // 12
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.5f, 1.0f, // 13
};
const GLuint elements[] = {
0, 3, 4, 0, 4, 1,
2, 7, 8, 2, 8, 3,
3, 8, 9, 3, 9, 4,
4, 9,10, 4,10, 5,
5,10,11, 5,11, 6,
8,12,13, 8,13, 9
};
GLuint vao;
GLuint vbo;
GLuint ibo;
GLuint shaderProgram;
GLuint textures[1];
float t = 0;
void check(int line)
{
GLenum error = glGetError();
while (error != GL_NO_ERROR)
{
switch (error)
{
case GL_INVALID_ENUM: std::cout << "GL_INVALID_ENUM : " << line << std::endl; break;
case GL_INVALID_VALUE: std::cout << "GL_INVALID_VALUE : " << line << std::endl; break;
case GL_INVALID_OPERATION: std::cout << "GL_INVALID_OPERATION : " << line << std::endl; break;
case GL_OUT_OF_MEMORY: std::cout << "GL_OUT_OF_MEMORY : " << line << std::endl; break;
default: std::cout << "Unrecognized error : " << line << std::endl; break;
}
error = glGetError();
}
}
void initialize_shader()
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
void destroy_shader()
{
glDeleteProgram(shaderProgram);
}
void initialize_vao()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
// shaderProgram must be already initialized
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
GLint cooAttrib = glGetAttribLocation(shaderProgram, "coord");
glEnableVertexAttribArray(cooAttrib);
glVertexAttribPointer(cooAttrib, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
}
void destroy_vao()
{
glDeleteBuffers(1, &ibo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
}
void initialize_texture()
{
glGenTextures(1, &textures[0]);
std::vector<unsigned char> image;
unsigned width, height;
unsigned error = lodepng::decode(image, width, height, "cube3.png");
if (error) std::cout << "decode error " << error << ": " << lodepng_error_text(error) << std::endl;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.data());
// shaderProgram must be already initialized
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void destroy_texture()
{
glDeleteTextures(1, &textures[0]);
}
void update_camera()
{
glm::vec3 right = glm::cross(camera_direction, camera_up);
glm::vec3 left = glm::cross(right, camera_up);
if (translate_forward)
{
camera_position += camera_direction*dt;
}
if (translate_backward)
{
camera_position -= camera_direction*dt;
}
if (translate_right)
{
camera_position += right * dt;
}
if (translate_left)
{
camera_position -= right * dt;
}
if (rotate_up)
{
camera_direction = glm::rotate(camera_direction, dt, right);
camera_up = glm::rotate(camera_up, dt, right);
}
if (rotate_down)
{
camera_direction = glm::rotate(camera_direction, -dt, right);
camera_up = glm::rotate(camera_up, -dt, right);
}
if (rotate_right)
{
camera_direction = glm::rotate(camera_direction, -dt, camera_up);
}
if (rotate_left)
{
camera_direction = glm::rotate(camera_direction, dt, camera_up);
}
if (rotate_z_left)
{
camera_direction = glm::rotate(camera_direction, dt, left);
camera_up = glm::rotate(camera_up, dt, left);
}
if (rotate_z_right)
{
camera_direction = glm::rotate(camera_direction, -dt, left);
camera_up = glm::rotate(camera_up, -dt, left);
}
}
void draw(GLFWwindow* window)
{
t = (timer::now() - start_time).count() * (float(timer::period::num) / float(timer::period::den));
dt = (timer::now() - last_time).count() * (float(timer::period::num) / float(timer::period::den));
update_camera();
last_time = timer::now();
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 projection = glm::perspective(PI / 4, 1.f / 1.f, 1.0f, 10.0f);
glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, -1.3f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 model = glm::rotate(glm::mat4(1.f), PI, glm::vec3(0.0f, 1.0f, 0.0f));
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation(shaderProgram, "textureSampler"), tex_flag);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, &projection[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, &view[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, &model[0][0]);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6 * 2 * 3, GL_UNSIGNED_INT, 0); // facce * triangoli per faccia * vertici per triangolo
}
int main(int argc, char const *argv[])
{
GLFWwindow *window;
glfwSetErrorCallback(error_callback);
tex_flag = 0;
if (!glfwInit())
return EXIT_FAILURE;
#if defined(__APPLE_CC__)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
#endif
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Project", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
#if defined(_MSC_VER)
glewExperimental = true;
if (glewInit() != GL_NO_ERROR)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
#endif
glfwSetKeyCallback(window, key_callback);
initialize_shader(); check(__LINE__);
initialize_vao(); check(__LINE__);
initialize_texture(); check(__LINE__);
//start = timer::now();
glEnable(GL_DEPTH_TEST); check(__LINE__);
while (!glfwWindowShouldClose(window))
{
draw(window); check(__LINE__);
glfwSwapBuffers(window);
glfwPollEvents();
}
destroy_vao(); check(__LINE__);
destroy_shader(); check(__LINE__);
destroy_texture(); check(__LINE__);
glfwDestroyWindow(window);
glfwTerminate();
return EXIT_SUCCESS;
}
First order of business when hunting down problems like yours it to minimize the surface area and reduce the program as far as possible yet retaining the problematic behaviour. Your code snippet does not constitute a Minimal Complete Verifyable Example (MCVE). I stripped it down to a MCVE:
#include <cstdlib>
#include <iostream>
#include <GLFW/glfw3.h>
static void error_callback(int error, const char* description)
{
std::cerr << description << std::endl;
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
std::cout << key << std::endl;
}
int main(int argc, char const *argv[])
{
GLFWwindow *window;
glfwSetErrorCallback( error_callback );
if (!glfwInit())
return EXIT_FAILURE;
window = glfwCreateWindow(100, 100, "Project", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return EXIT_SUCCESS;
}
Given this minimal example I am unable to reproduce your particular problem; i.e. I am getting key events out of this.
That can mean two things: Either the problem resides somewhere else in your code, or it is something about your particular system and development environment. This is why MCVEs are so important (especially the minimal part); it's the only way to pinpoint the actual culprit.
So here's my suggestion: Try the minimal code I put up and see if it still does not report key events. If so, then it's a problem with your system and not with the code. Otherwise you can re-add layers of functionality piece by piece until it breaks.

C++ OpenGL rendering two rectangles with different colors

I have tried to create two rectangle objects with two different colors and moving in opposite direction. However, I am stuck in rendering the two rectangle with different colors (currently they are the same color).
What is the way to do it?
Here is the code:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "ogldev_util.h"
#include "ogldev_math_3d.h"
GLuint VBO1;
GLuint VBO2;
GLuint gScaleLocation1;
GLuint gScaleLocation2;
const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";
static void RenderSceneCB()
{
glClear(GL_COLOR_BUFFER_BIT);
static float Scale1 = 0.0f;
Scale1 += 0.01f;
glUniform1f(gScaleLocation1, sinf(Scale1));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
static float Scale2 = 0.0f;
Scale2 -= 0.01f;
glUniform1f(gScaleLocation2, sinf(Scale2));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
static void InitializeGlutCallbacks()
{
glutDisplayFunc(RenderSceneCB);
glutIdleFunc(RenderSceneCB);
}
static void CreateVertexBuffer()
{
Vector3f Vertices[6];
Vertices[0] = Vector3f(1.0f, -0.5f, 0.0f);
Vertices[1] = Vector3f(1.0f, 0.5f, 0.0f);
Vertices[2] = Vector3f(3.0f, -0.5f, 0.0f);
Vertices[3] = Vector3f(1.0f, 0.5f, 0.0f);
Vertices[4] = Vector3f(3.0f, 0.5f, 0.0f);
Vertices[5] = Vector3f(3.0f, -0.5f, 0.0f);
glGenBuffers(1, &VBO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
Vector3f Vertices2[6];
Vertices2[0] = Vector3f(-3.0f, -0.5f, 0.0f);
Vertices2[1] = Vector3f(-3.0f, 0.5f, 0.0f);
Vertices2[2] = Vector3f(-1.0f, -0.5f, 0.0f);
Vertices2[3] = Vector3f(-3.0f, 0.5f, 0.0f);
Vertices2[4] = Vector3f(-1.0f, 0.5f, 0.0f);
Vertices2[5] = Vector3f(-1.0f, -0.5f, 0.0f);
glGenBuffers(1, &VBO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW);
}
static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
GLuint ShaderObj = glCreateShader(ShaderType);
if (ShaderObj == 0) {
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
exit(1);
}
const GLchar* p[1];
p[0] = pShaderText;
GLint Lengths[1];
Lengths[0]= strlen(pShaderText);
glShaderSource(ShaderObj, 1, p, Lengths);
glCompileShader(ShaderObj);
GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar InfoLog[1024];
glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
exit(1);
}
glAttachShader(ShaderProgram, ShaderObj);
}
static void CompileShaders()
{
GLuint ShaderProgram = glCreateProgram();
if (ShaderProgram == 0) {
fprintf(stderr, "Error creating shader program\n");
exit(1);
}
string vs, fs;
if (!ReadFile(pVSFileName, vs)) {
exit(1);
};
if (!ReadFile(pFSFileName, fs)) {
exit(1);
};
AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);
GLint Success = 0;
GLchar ErrorLog[1024] = { 0 };
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
if (Success == 0) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
exit(1);
}
glValidateProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
if (!Success) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
exit(1);
}
glUseProgram(ShaderProgram);
gScaleLocation1 = glGetUniformLocation(ShaderProgram, "gScale");
assert(gScaleLocation1 != 0xFFFFFFFF);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowSize(1024, 768);
glutInitWindowPosition(100, 100);
glutCreateWindow("Tutorial 05");
InitializeGlutCallbacks();
// Must be done after glut is initialized!
GLenum res = glewInit();
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
printf("GL version: %s\n", glGetString(GL_VERSION));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
CreateVertexBuffer();
CompileShaders();
glutMainLoop();
return 0;
}
Fragment Shader
#version 330
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
It depends. Easiest way in this case is to add uniform vec3 color; and gl_FragColor = vec4(color, 1.0); inside your fragment shader and then initialize it with desired color by invoking glUniform3f before rendering of each rectangle. However, with rectangle count growth you would be better to create your vertex struct that will carry not only coordinates, but a color as well.
Also, I highly recommend this http://www.opengl-tutorial.org/ opengl tutorials web site.

OpenGL Simple Cube not Appearing, Using Uniform Blocks

I am trying to draw a simple cube for a homework assignment for a class but for some reason it isn't showing up.
I am using uniform blocks and modern OpenGL. I am sure I am not doing something correctly.
My complete code is below. The below example depends on GLEW + GLFW + GLM.
What I found interesting is that for my light and material uniform blocks I get the index but the uniform block for my MVP matrix I don't get the index.
Any ideas?
Here is the C++ code:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#ifndef OPENGL_INCLUDES_
#define OPENGL_INCLUDES_
#include "GL\glew.h"
#ifndef GLFW_INCLUDES_
#define GLFW_INCLUDES_
#if defined(_WIN32)
#include <Windows.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#elif defined(__linux__)
#include <X11/X.h>
#include <X11/extensions/Xrandr.h>
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#endif
#include "GLFW\glfw3.h"
#include "GLFW\glfw3native.h"
#endif
#endif
#ifndef GLM_INCLUDES_
#define GLM_INCLUDES_
#include <glm/glm.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#endif
GLFWwindow* MainWindow;
#ifdef _WIN32
HWND MainWindowWin32Handle;
#endif
GLint WindowWidth = 1024;
GLint WindowHeight = 768;
GLulong SizeDivizor = 1;
GLboolean RiftAvailable = false;
GLboolean UseApplicationWindowFrame = false;
GLuint MainOpenGLShaderProgramID;
GLuint MatricesUniformBlockID;
GLuint MatricesUniformBufferID;
GLuint LightsUniformBlockID;
GLuint LightsUniformBufferID;
GLuint MaterialsUniformBlockID;
GLuint MaterialsUniformBufferID;
glm::mat4 ViewMatrix;
glm::mat4 ViewModelMatrix;
glm::mat4 ProjectionMatrix;
glm::mat4 MVPMatrix;
glm::mat3 NormalMatrix;
class StandardCube;
std::vector<StandardCube> Cubes;
class StandardCube {
private:
GLfloat* Vertices;
GLfloat* Normals;
GLuint* Indices;
GLuint VAO;
glm::mat4 ModelMatrix;
public:
void LoadIntoOpenGL() {
Vertices = new GLfloat[72]
{
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f
};
Normals = new GLfloat[72] {
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f
};
Indices = new GLuint[36] {0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12,
16, 17, 18, 18, 19, 16,
20, 21, 22, 22, 23, 20
};
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLuint MeshBufferID;
glGenBuffers(1, &MeshBufferID);
glBindBuffer(GL_ARRAY_BUFFER, MeshBufferID);
GLuint TotalBufferData = (sizeof(GLfloat) * 72) + (sizeof(GLfloat) * 72);
glBufferData(GL_ARRAY_BUFFER, TotalBufferData, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, NULL, sizeof(GLfloat) * 72, Vertices);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 72, sizeof(GLfloat) * 72, Normals);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(sizeof(GLfloat) * 72));
glEnableVertexAttribArray(1);
GLuint IndexBufferID;
glGenBuffers(1, &IndexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 36, Indices, GL_STATIC_DRAW);
glBindVertexArray(NULL);
ModelMatrix = glm::mat4(1.0f);
}
void DrawMe() {
MVPMatrix = ProjectionMatrix * ViewMatrix * ModelMatrix;
ViewModelMatrix = ViewMatrix * ModelMatrix;
NormalMatrix = glm::transpose(glm::inverse(glm::mat3(MVPMatrix)));
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBufferSubData(GL_UNIFORM_BUFFER, NULL, sizeof(glm::mat4), glm::value_ptr(MVPMatrix));
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(ViewModelMatrix));
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) + sizeof(glm::mat4), sizeof(glm::mat3), glm::value_ptr(NormalMatrix));
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL, 1);
glBindVertexArray(NULL);
}
};
static void GLFWKeyCallback(GLFWwindow* p_Window, GLint p_Key, GLint p_Scancode, GLint p_Action, GLint p_Mods) {
if (p_Key == GLFW_KEY_ESCAPE && p_Action == GLFW_PRESS) {
glfwSetWindowShouldClose(p_Window, GL_TRUE);
}
if (p_Key == GLFW_KEY_O && p_Action == GLFW_PRESS) {
glClearColor(0.2f, 0.1f, 0.3f, 1.0f);
}
if (p_Key == GLFW_KEY_I && p_Action == GLFW_PRESS) {
glClearColor(1.0f, 0.5f, 0.5f, 1.0f);
}
}
static void GLFWWindowResizeCallBack(GLFWwindow* p_Window, GLint width, GLint height) {
//CurrentGLFWApplication->WindowResizeCallBack(p_Window, width, height);
}
static void GLFWMouseMovementCallBack(GLFWwindow* p_Window, GLdouble MouseX, GLdouble MouseY) {
//CurrentGLFWApplication->MouseMovementCallBack(p_Window, MouseX, MouseY);
}
static void GLFWFramebufferSizeCallback(GLFWwindow* window, GLint width, GLint height)
{
glViewport(0, 0, width, height);
}
int initializeGLFWGLEW() {
MainWindow = NULL;
if (!glfwInit())
{
fprintf(stderr, "GLFW failed to initialize.");
glfwTerminate();
return EXIT_FAILURE;
}
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
if (UseApplicationWindowFrame) {
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", NULL, NULL);
}
else {
if (!RiftAvailable) {
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", NULL, NULL);
}
else {
GLint MonitorCount;
GLFWmonitor** GLFW_Monitors = glfwGetMonitors(&MonitorCount);
GLFWmonitor* MonitorToUse;
switch (MonitorCount)
{
case 0:
printf("No monitors found, exiting.\n");
return EXIT_FAILURE;
break;
case 1:
printf("Two monitors expected, found only one, using primary...\n");
MonitorToUse = glfwGetPrimaryMonitor();
break;
case 2:
printf("Two monitors found, using second monitor\n");
MonitorToUse = GLFW_Monitors[1];
break;
default:
printf("More than two monitors found, using second monitor\n");
MonitorToUse = GLFW_Monitors[1];
}
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", MonitorToUse, NULL);
}
}
if (!MainWindow)
{
fprintf(stderr, "Could not determine OpenGL version; exiting.");
glfwTerminate();
return EXIT_FAILURE;
}
glfwMakeContextCurrent(MainWindow);
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return EXIT_FAILURE;
}
glfwSetInputMode(MainWindow, GLFW_STICKY_KEYS, GL_TRUE);
glfwSetKeyCallback(MainWindow, GLFWKeyCallback);
glfwSetWindowSizeCallback(MainWindow, GLFWWindowResizeCallBack);
glfwSetCursorPosCallback(MainWindow, GLFWMouseMovementCallBack);
glfwSetFramebufferSizeCallback(MainWindow, GLFWFramebufferSizeCallback);
glfwSwapBuffers(MainWindow);
glfwPollEvents();
return EXIT_SUCCESS;
}
int prepareOpenGL() {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MULTISAMPLE);
return EXIT_SUCCESS;
}
int loadShaders() {
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Compile Vertex Shader
printf("Compiling Vertext Shader.\n\n");
char const * VertexSource = "#version 330 \n\n\
layout(std140) uniform MatrixInformation {\n\
mat4 m_pvm;\n\
mat4 m_viewModel;\n\
mat3 m_normal;\n\
};\n\
layout(std140) uniform Lights {\n\
vec3 l_dir; \n\
};\n\
in vec4 position;\n\
in vec3 normal;\n\
\n\
\n\
out Data{\n\
vec3 normal;\n\
vec4 eye;\n\
} DataOut;\n\
\n\
void main() {\n\
\n\
DataOut.normal = normalize(m_normal * normal);\n\
DataOut.eye = -(m_viewModel * position);\n\
\n\
gl_Position = m_pvm * position;\n\
}\n\
\n";
glShaderSource(VertexShaderID, 1, &VertexSource, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
GLint Result = GL_FALSE;
int InfoLogLength;
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){
std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
std::string ErrorMessage = std::string(&VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
printf("Compiling Fragment Shader.\n\n");
char const * FragmentSource = "#version 330\n\
layout(std140) uniform Materials {\n\
vec4 diffuse;\n\
vec4 ambient;\n\
vec4 specular;\n\
vec4 emissive;\n\
float shininess;\n\
int texCount;\n\
};\
\n\
layout(std140) uniform Lights {\n\
vec3 l_dir; \n\
};\
\n\
in Data{\n\
vec3 normal;\n\
vec4 eye;\n\
} DataIn;\n\
\n\
out vec4 colorOut;\
\n\
void main() {\n\
\n\
vec4 spec = vec4(0.0);\n\
\n\
vec3 n = normalize(DataIn.normal);\n\
vec3 e = normalize(vec3(DataIn.eye));\n\
\n\
float intensity = max(dot(n, l_dir), 0.0);\n\
\n\
if (intensity > 0.0) {\n\
vec3 h = normalize(l_dir + e);\n\
\n\
float intSpec = max(dot(h, n), 0.0);\n\
spec = specular * pow(intSpec, shininess);\n\
}\n\
\n\
colorOut = max(intensity * diffuse + spec, ambient);\n\
}";
glShaderSource(FragmentShaderID, 1, &FragmentSource, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){
std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
std::string ErrorMessage = std::string(&FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
printf("Linking shader program.\n\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){
std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
std::string ErrorMessage = std::string(&ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
MainOpenGLShaderProgramID = ProgramID;
return EXIT_SUCCESS;
}
int prepareShaderUniforms() {
glUseProgram(MainOpenGLShaderProgramID);
LightsUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "Lights");
glUniformBlockBinding(MainOpenGLShaderProgramID, LightsUniformBlockID, 2);
glGenBuffers(1, &LightsUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, LightsUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 2, LightsUniformBufferID);
GLfloat LightDirection[3] = { 1.0f, 1.0f, 0.0f };
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDirection), &LightDirection, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
MatricesUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "MatrixInformation");
glUniformBlockBinding(MainOpenGLShaderProgramID, MatricesUniformBlockID, 1);
glGenBuffers(1, &MatricesUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, MatricesUniformBufferID);
GLsizeiptr TotalBufferSize = sizeof(glm::mat4) + sizeof(glm::mat4);
TotalBufferSize += sizeof(glm::mat3);
glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
MaterialsUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "Materials");
glUniformBlockBinding(MainOpenGLShaderProgramID, MaterialsUniformBlockID, 3);
glGenBuffers(1, &MaterialsUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, MaterialsUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 3, MaterialsUniformBufferID);
GLfloat Material[18];
//Diffuse
Material[0] = 0.5f;
Material[1] = 0.0f;
Material[2] = 0.0f;
Material[3] = 1.0f;
//Ambient
Material[4] = 0.2f;
Material[5] = 0.2f;
Material[6] = 0.2f;
Material[7] = 1.0f;
//Specular
Material[8] = 0.0f;
Material[9] = 0.0f;
Material[10] = 0.0f;
Material[11] = 1.0f;
//Emissive
Material[12] = 0.0f;
Material[13] = 0.0f;
Material[14] = 0.0f;
Material[15] = 1.0f;
//Shininess
Material[16] = 2.0f;
//Texture Count
Material[17] = 0.0f;
glBufferData(GL_UNIFORM_BUFFER, sizeof(Material), &Material, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
return EXIT_SUCCESS;
}
int loadCubes() {
StandardCube NewCube;
NewCube.LoadIntoOpenGL();
Cubes.push_back(NewCube);
return EXIT_SUCCESS;
}
int prepareMatricies() {
GLfloat AspectRatio = (GLfloat)(WindowWidth) / (GLfloat)(WindowHeight);
ProjectionMatrix = glm::perspective(45.0f, AspectRatio, 1.0f, 1000.0f);
ViewMatrix = glm::lookAt(
glm::vec3(4.0f, 3.0f, 3.0f), // camera is at (4,3,3), in world space - Where the camera is inside world.
glm::vec3(0.0f, 0.0f, 0.0f), // and looks at the origin - What point the camera is looking at inside world.
glm::vec3(0.0f, 1.0f, 0.0f)// head is up(set to 0,1,0) - the direction of up for camera.
);
glViewport(0, 0, WindowWidth, WindowHeight);
return EXIT_SUCCESS;
}
int main(int argc, char** argv) {
if (initializeGLFWGLEW() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (prepareOpenGL() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (loadShaders() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (prepareShaderUniforms() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (loadCubes() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
if (prepareMatricies() == EXIT_FAILURE) {
exit(EXIT_FAILURE);
}
while (!glfwWindowShouldClose(MainWindow))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (auto & C : Cubes) {
C.DrawMe();
}
glfwSwapBuffers(MainWindow);
glfwPollEvents();
}
exit(EXIT_SUCCESS);
}
Here is my vertex shader:
#version 330
layout(std140) uniform MatrixInformation {
mat4 m_pvm;
mat4 m_viewModel;
mat3 m_normal;
};
layout(std140) uniform Lights {
vec3 l_dir;
};
in vec4 position;
in vec3 normal;
out Data{
vec3 normal;
vec4 eye;
} DataOut;
void main() {
DataOut.normal = normalize(m_normal * normal);
DataOut.eye = -(m_viewModel * position);
gl_Position = m_pvm * position;
}
And here is my fragment shader:
#version 330
layout(std140) uniform Materials {
vec4 diffuse;
vec4 ambient;
vec4 specular;
vec4 emissive;
float shininess;
int texCount;
};
layout(std140) uniform Lights {
vec3 l_dir;
};
in Data{
vec3 normal;
vec4 eye;
} DataIn;
out vec4 colorOut;
void main() {
vec4 spec = vec4(0.0);
vec3 n = normalize(DataIn.normal);
vec3 e = normalize(vec3(DataIn.eye));
float intensity = max(dot(n, l_dir), 0.0);
if (intensity > 0.0) {
vec3 h = normalize(l_dir + e);
float intSpec = max(dot(h, n), 0.0);
spec = specular * pow(intSpec, shininess);
}
colorOut = max(intensity * diffuse + spec, ambient);
}
So the issue is this part:
//Binding uniform buffer
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, MatricesUniformBufferID);
GLsizeiptr TotalBufferSize = sizeof(glm::mat4) + sizeof(glm::mat4);
TotalBufferSize += sizeof(glm::mat3);
//uploading to the unbound array buffer
glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);
So you need to change
glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
to
glBufferData(GL_UNIFORM_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
Additionally uploading NULL doesn't work on my OpenGL driver (although it should), so I had to
std::array<unsigned char,sizeof(glm::mat4)*2+sizeof(glm::mat3)> buff;
glBufferData(GL_UNIFORM_BUFFER, TotalBufferSize, buff.data(), GL_DYNAMIC_DRAW);
As for how you would find that out: the old-school method is to litter your code with glGetError calls that only go off in debug mode. The more modern method is to create a debug context and print break on the callback to find out whereabouts the error is (then you can make glGetError calls in that area to get the exact function call if you don't know it by then, since modern OpenGL drivers are threaded and the callback may be triggered one or two function calls later).