Segmentation Fault: 11 On DrawElementsCall - c++

In Mesh.h, I am getting a segmentation error: 11 in my draw function on the "glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);" function call.
I tried calling "glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)" after the VAO buffer was bound like some people suggested but it has not helped.
Modeloading.cpp:
// ModelLoading.cpp
// LightingTutorials
//
// Created by Roma Desai on 6/6/19.
// Copyright © 2019 Roma Desai. All rights reserved.
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Camera.cpp"
#include <../include/Model.h>
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <iostream>
/*
int main () {
std::cout<<"hello";
}
*/
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
std::string loadShaderString (const char* file);
//object shaders
std::string temp1 = loadShaderString("../shaders/vertexShader7a.glsl");
const char* vertex_shader = temp1.c_str();
std::string temp2 = loadShaderString("../shaders/fragmentShader7a.glsl");
const char* fragment_shader = temp2.c_str();
int main()
{
// glfw: initialize and configure
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif
// glfw window creation
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Window", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// configure global opengl state
glEnable(GL_DEPTH_TEST);
// build and compile shaders
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
GLint status = GL_TRUE;
glGetShaderiv( vs, GL_COMPILE_STATUS, &status );
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
GLuint shader_program = glCreateProgram(); //creating joint shader program
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
// load models
Model ourModel("../model/nanosuit/nanosuit.obj", shader_program);
// render loop
while (!glfwWindowShouldClose(window))
{
// render
glClearColor(0.05f, 0.05f, 0.05f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
// view/projection transformations
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glm::mat4 view = camera.GetViewMatrix();
glUniformMatrix4fv(glGetUniformLocation(shader_program,"projection"), 1, GL_FALSE, &projection[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shader_program,"view"), 1, GL_FALSE, &view[0][0]);
// render the loaded model
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f)); // translate down
model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // scale it down
glUniformMatrix4fv(glGetUniformLocation(shader_program,"model"), 1, GL_FALSE, &model[0][0]);
ourModel.Draw(shader_program);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
glfwSwapBuffers(window);
glfwPollEvents();
}
// glfw: terminate, clearing all previously allocated GLFW resources.
glfwTerminate();
return 0;
}
/* function for loading shader from text file */
std::string loadShaderString (const char* file) {
std::ifstream input(file);
return std::string(std::istreambuf_iterator<char>(input),
std::istreambuf_iterator<char>());
}
Model.h:
//
// Model.cpp
// LightingTutorials
//
// Created by Roma Desai on 6/6/19.
// Copyright © 2019 Roma Desai. All rights reserved.
//
#ifndef MODEL_H
#define MODEL_H
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
//#define STB_IMAGE_IMPLEMENTATION
#include <../include/stb_image.h>
#include <../include/Mesh.h>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include <stdio.h>
/*
int main() {
std::cout << "hello";
}
*/
using namespace std;
unsigned int TextureFromFile(const char *path, const string &directory, bool gamma = false);
class Model
{
public:
// Model Data
vector<Texture> textures_loaded; // stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once.
vector<Mesh> meshes;
string directory;
bool gammaCorrection;
GLuint shader;
// Functions
// constructor, expects a filepath to a 3D model.
Model(string const &path, GLuint shader, bool gamma = false) : gammaCorrection(gamma)
{
this->shader = shader;
loadModel(path);
}
// draws the model, and thus all its meshes
void Draw(GLuint shader)
{
for(unsigned int i = 0; i < meshes.size(); i++) {
meshes[i].Draw(shader);
}
}
private:
// Functions
// loads a model with supported ASSIMP extensions from file and stores the resulting meshes in the meshes vector.
void loadModel(string const &path)
{
// read file via ASSIMP
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
// check for errors
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero
{
cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl;
return;
}
// retrieve the directory path of the filepath
directory = path.substr(0, path.find_last_of('/'));
// process ASSIMP's root node recursively
processNode(scene->mRootNode, scene);
}
// processes a node in a recursive fashion. Processes each individual mesh located at the node and repeats this process on its children nodes (if any).
void processNode(aiNode *node, const aiScene *scene)
{
// process each mesh located at the current node
for(unsigned int i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for(unsigned int i = 0; i < node->mNumChildren; i++)
{
processNode(node->mChildren[i], scene);
}
}
Mesh processMesh(aiMesh *mesh, const aiScene *scene)
{
// data to fill
vector<Vertex> vertices;
vector<unsigned int> indices;
vector<Texture> textures;
// Walk through each of the mesh's vertices
for(unsigned int i = 0; i < mesh->mNumVertices; i++)
{
Vertex vertex;
glm::vec3 vector; // we declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to glm's vec3 class so we transfer the data to this placeholder glm::vec3 first.
// positions
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
// normals
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
// texture coordinates
if(mesh->mTextureCoords[0]) // does the mesh contain texture coordinates?
{
glm::vec2 vec;
// a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoords = vec;
}
else {
vertex.TexCoords = glm::vec2(0.0f, 0.0f);
// tangent
vector.x = mesh->mTangents[i].x;
vector.y = mesh->mTangents[i].y;
vector.z = mesh->mTangents[i].z;
vertex.Tangent = vector;
// bitangent
vector.x = mesh->mBitangents[i].x;
vector.y = mesh->mBitangents[i].y;
vector.z = mesh->mBitangents[i].z;
vertex.Bitangent = vector;
vertices.push_back(vertex);
}
}
for(unsigned int i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for(unsigned int j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]);
}
// process materials
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
// we assume a convention for sampler names in the shaders. Each diffuse texture should be named
// as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER.
// Same applies to other texture as the following list summarizes:
// diffuse: texture_diffuseN
// specular: texture_specularN
// normal: texture_normalN
// 1. diffuse maps
vector<Texture> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
// 2. specular maps
vector<Texture> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
// 3. normal maps
std::vector<Texture> normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal");
textures.insert(textures.end(), normalMaps.begin(), normalMaps.end());
// 4. height maps
std::vector<Texture> heightMaps = loadMaterialTextures(material, aiTextureType_AMBIENT, "texture_height");
textures.insert(textures.end(), heightMaps.begin(), heightMaps.end());
// return a mesh object created from the extracted mesh data
return Mesh(vertices, indices, textures, shader);
}
// checks all material textures of a given type and loads the textures if they're not loaded yet.
// the required info is returned as a Texture struct.
vector<Texture> loadMaterialTextures(aiMaterial *mat, aiTextureType type, string typeName)
{
vector<Texture> textures;
for(unsigned int i = 0; i < mat->GetTextureCount(type); i++)
{
aiString str;
mat->GetTexture(type, i, &str);
bool skip = false;
for(unsigned int j = 0; j < textures_loaded.size(); j++)
{
if(std::strcmp(textures_loaded[j].path.data(), str.C_Str()) == 0)
{
textures.push_back(textures_loaded[j]);
skip = true; // a texture with the same filepath has already been loaded, continue to next one. (optimization)
break;
}
}
if(!skip)
{ // if texture hasn't been loaded already, load it
Texture texture;
texture.id = TextureFromFile(str.C_Str(), this->directory);
texture.type = typeName;
texture.path = str.C_Str();
textures.push_back(texture);
textures_loaded.push_back(texture); // store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
}
}
return textures;
}
};
unsigned int TextureFromFile(const char *path, const string &directory, bool gamma)
{
string filename = string(path);
filename = directory + '/' + filename;
unsigned int textureID;
glGenTextures(1, &textureID);
int width, height, nrComponents;
unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0);
if (data)
{
GLenum format;
if (nrComponents == 1)
format = GL_RED;
else if (nrComponents == 3)
format = GL_RGB;
else if (nrComponents == 4)
format = GL_RGBA;
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_image_free(data);
}
else
{
std::cout << "Texture failed to load at path: " << path << std::endl;
stbi_image_free(data);
}
return textureID;
}
#endif
Mesh.h:
// Mesh.cpp
// LightingTutorials
// Created by Roma Desai on 6/6/19.
// Copyright © 2019 Roma Desai. All rights reserved.
#include <iostream>
#include <GL/glew.h>
#define GLFW_DLL
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
struct Vertex {
glm::vec3 Position;
glm::vec3 Normal;
glm::vec2 TexCoords;
glm::vec3 Tangent;
glm::vec3 Bitangent;
};
struct Texture {
unsigned int id;
std::string type;
std::string path;
};
class Mesh {
public:
/* Mesh Data */
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture> textures;
unsigned int VAO;
GLuint shader;
/* Functions */
Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<Texture> textures, GLuint shader)
{
this->vertices = vertices;
this->indices = indices;
this->textures = textures;
this->shader = shader;
// set the vertex buffers/attribute pointers.
setupMesh();
}
void Draw(GLuint shader)
{
unsigned int diffuseNr = 1;
unsigned int specularNr = 1;
unsigned int normalNr = 1;
unsigned int heightNr = 1;
for(unsigned int i = 0; i < textures.size(); i++)
{
glActiveTexture(GL_TEXTURE0 + i); // activate proper texture unit before binding
// retrieve texture number (the N in diffuse_textureN)
std::string number;
std::string name = textures[i].type;
if(name == "texture_diffuse") {
number = std::to_string(diffuseNr++);
}
else if(name == "texture_specular") {
number = std::to_string(specularNr++);
}
else if(name == "texture_normal") {
number = std::to_string(normalNr++); // transfer unsigned int to stream
}
else if(name == "texture_height") {
number = std::to_string(heightNr++);
}
//glUseProgram(shader);
glUniform1i(glGetUniformLocation(shader, (name + number).c_str()), i);
glBindTexture(GL_TEXTURE_2D, textures[i].id);
}
glActiveTexture(GL_TEXTURE0);
// draw mesh
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
private:
/* Render data */
unsigned int VBO, EBO;
/* Functions */
void setupMesh()
{
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
&indices[0], GL_STATIC_DRAW);
//find locations
GLint loc_pos = glGetAttribLocation(shader, "aPos" );
GLint loc_texCoords = glGetAttribLocation(shader, "aTexCoords" );
//std::cout << "apos position: " << loc_pos << " ";
//std::cout << "texCoords position: " << loc_texCoords << " ";
// vertex positions
glEnableVertexAttribArray(loc_pos);
glVertexAttribPointer(loc_pos, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
// vertex normals
//glEnableVertexAttribArray(1);
// glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
// vertex texture coords
glEnableVertexAttribArray(loc_texCoords);
glVertexAttribPointer(loc_texCoords, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
// vertex tangent
// glEnableVertexAttribArray(3);
// glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Tangent));
// vertex bitangent
//glEnableVertexAttribArray(4);
//glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Bitangent));
glBindVertexArray(0);
}
};
I read many posts online but I seem to be getting the same error despite having fixed implemented some of the changes.

Related

my simple OpenGL program can't draw a model load by assimp

I divide my code to two cpp files, one cpp contains main()function and another one contains model loading codes.
here's the first part
#define STB_IMAGE_IMPLEMENTATION
//OpenGL relations
#include "stb_image.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
//math and time
#include <math.h>
#include <cstdio>
#include <time.h>
#include <iostream>
//matrix
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
//
#include "modelload.h"
// const values here //
const char* defaultpath = "woodenbox.jpeg";
const char* cottagetex = "cottage.fbx";
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTexCoord;\n"
"out vec2 TexCoord;\n"
"uniform mat4 transform;\n"
"void main()\n"
"{\n"
" gl_Position = transform * vec4(aPos.x, aPos.y, aPos.z, 1.0f);\n"
" TexCoord = aTexCoord;\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec2 TexCoord;\n"
"uniform sampler2D ourTexture;\n"
"void main()\n"
"{\n"
" FragColor = texture(ourTexture, TexCoord);\n"
"}\n\0";
// functions here //
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void loadtexture(unsigned int& texture, const char* path = defaultpath) {
int width, height, nrChannels;
unsigned char* data = stbi_load(path, &width, &height, &nrChannels, 4);
glGenTextures(1, &texture);
//glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
}
void renderInit(unsigned int& shaderProgram) {
unsigned int vertexShader, fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
}
// main function //
int main(int argc, char* argv[])
{
//初始化glfw
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL-1", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
//渲染初始化,生成着色器程序、VAO、顶点初始数据
clock_t start, ends;
start = clock();
//build shader
unsigned int shaderProgram;
renderInit(shaderProgram);
unsigned int texture;
glGenTextures(1, &texture);
// 为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
loadtexture(texture);
model* ct1 = new model(cottagetex);
glm::mat4 ori_trans = glm::mat4(1.0f);
glm::mat4 view_trans = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));//glm::translate(ori_trans, glm::vec3(0.0f, 0.0f, -3.0f));
glm::mat4 proj_trans = glm::perspective(glm::radians(45.0f), (float)(800 / 600), 0.1f, 100.0f);
glm::mat4 rotate_trans = glm::mat4(1.0f);
unsigned int count = 0;
float radius = 10.0f;
glEnable(GL_DEPTH_TEST);
// initialization completed
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
float camX = sin(glfwGetTime()) * radius;
float camZ = cos(glfwGetTime()) * radius;
view_trans = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));
//glEnableVertexAttribArray(0);
glUseProgram(shaderProgram);
rotate_trans = proj_trans * view_trans * glm::rotate(ori_trans, glm::radians((float)((clock() - start) - cos(clock() - start) * 4) / 40), glm::vec3(1.0, 1.0, -1.0));
unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(rotate_trans));
ct1->draw();
//glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
rotate_trans = glm::translate(proj_trans * view_trans, glm::vec3(1.0f, 1.0f, -3.0f));
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(rotate_trans));
ct1->draw();
//glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
//std::cout << count << " frame updated" << (float)-(0.25 + sin(clock() - start) / 4) << std::endl;
count++;
glfwSwapBuffers(window);
glfwPollEvents();
}
/*
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
*/
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
and the second part
//OpenGL relations
#include <glad/glad.h>
#include <GLFW/glfw3.h>
//math and time
#include <math.h>
#include <vector>
#include <time.h>
#include <iostream>
//matrix
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
//assets
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
struct Vertex {
glm::vec3 Position;
glm::vec2 TexCoords;
glm::vec3 Normal;
};
class Mesh {
public:
/* 网格数据 */
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
//std::vector<unsigned int> textures;// materials
/* 函数 */
Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices) {
this->vertices = vertices;
this->indices = indices;
}//, std::vector<unsigned int> textures
void Draw();
void setupMesh();
private:
/* 渲染数据 */
unsigned int VAO, VBO, EBO;
/* 函数 */
};
class model {
public:
model(const char* path);
void draw();
private:
std::vector<Mesh> meshes;
void processnode(aiNode* node, const aiScene* scene);
Mesh processmesh(aiMesh* mesh, const aiScene* scene);
// loadmaterials
};
#include "modelload.h"
//STL vector in namespace std
void Mesh::setupMesh() {
/*
for (int i = 0; i < vertices.size(); i++) {
std::cout<<vertices[i].Position.x<<std::endl;
}
*/
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//std::cout << sizeof(Vertex) << std::endl;
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
//glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(5 * sizeof(float)));
//glEnableVertexAttribArray(2);
//glBindVertexArray(0);// reload VAO before rendering
}
void Mesh::Draw() {
//std::cout << vertices.size() << std::endl; //vertices:988 indices:1434
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
}
model::model(const char* path) {
Assimp::Importer import;
const aiScene* scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
std::cout << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl;
return;
}
processnode((scene->mRootNode), scene);
}
void model::processnode(aiNode* node, const aiScene* scene) {
for (int i = 0; i < node->mNumMeshes; i++) {
meshes.push_back(processmesh(scene->mMeshes[node->mMeshes[i]], scene));
meshes.back().setupMesh();
}
for (int i = 0; i < node->mNumChildren; i++) {
processnode(node->mChildren[i], scene);
}
}
Mesh model::processmesh(aiMesh* mesh, const aiScene* scene) {
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
for (int i = 0; i < (mesh->mNumVertices); i++) {
Vertex tvertex;
tvertex.Position.x = mesh->mVertices[i].x/3;
tvertex.Position.y = mesh->mVertices[i].y/3;
tvertex.Position.z = mesh->mVertices[i].z/3;
tvertex.Normal.x = mesh->mNormals[i].x;
tvertex.Normal.y = mesh->mNormals[i].y;
tvertex.Normal.z = mesh->mNormals[i].z;
tvertex.TexCoords.x = mesh->mTextureCoords[0][i].x;
tvertex.TexCoords.y = mesh->mTextureCoords[0][i].y;
vertices.push_back(tvertex);
//std::cout << tvertex.Position.x<<" "<< tvertex.Position.y<<" "<< tvertex.Position.z << std::endl;
//std::cout << tvertex.TexCoords.x << " " << tvertex.TexCoords.y << std::endl;
}
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
{
aiFace face = mesh->mFaces[i];
for (unsigned int j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]);
}
return Mesh(vertices, indices);
}
void model::draw() {
for (int i = 0; i < meshes.size(); i++) {
//std::cout << i << std::endl;
meshes[i].Draw();
}
}
It can only draw the background color, but it works when I draw a model I made by myself like:
-0.5, -0.5f, 0.5f, 0.0f,0.0f,//left bottom front 0
-0.5, 0.5f, 0.5f, 0.0f,1.0f,//left ceil front 1
0.5, 0.5f, 0.5f, 1.0f,1.0f,//right ceil front 2
0.5, -0.5f, 0.5f, 1.0f,0.0f,//right bottom front 3
-0.5, -0.5f, -0.5f, 1.0f,0.0f,//left bottom behind 4
-0.5, 0.5f, -0.5f, 1.0f,1.0f,//left ceil behind 5
0.5, 0.5f, -0.5f, 0.0f,1.0f,//right ceil behind 6
0.5, -0.5f, -0.5f, 0.0f,0.0f//right bottom behind 7
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 2,
0, 2, 3,
0, 4, 1,
1, 4, 5,
1, 2, 6,
1, 6, 5,
4, 5, 6,
4, 6, 7,
2, 3, 7,
2, 7, 6,
0, 3, 4,
4, 7, 3
};
I checked memory where the model data is, it seems like many same points was loaded.
enter image description here

VAO isn't rendering my simple triangle, what could be causing this?

I've already looked all over the internet for the past couple days and I cannot find a fix to this problem. I believe I've got the basic debugging stuff setup yet I get no errors telling me what I've done wrong. This is my first attempt at a renderer, and I'm also trying to use a OOP/DOD (Data oriented design) structure. I think the error is just something small that I am blind to, or I'm completely doing this wrong... please help if you can.
Also I'm using shaders, EBOs, VBOs, linking to a VAO (I think)
Additional information: I'm using SDL + GLAD(opengl 4.6, core)
If you need me to reply with anything else that could help you help me, let me know.
Here is my console output:
screenshot
All I see on the window: screenshot
Here are my files (that might have the error):
vertex shader
#version 460 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 ourColor;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
}
fragment shader
#version 460 core
out vec4 FragColor;
in vec3 ourColor;
void main()
{
FragColor = vec4(ourColor, 1.0f);
}
main.cpp (the window)
#include <loader.h>
using namespace testProgram;
int close(SDL_Window* window, SDL_GLContext glContext) {
IMG_Quit();
SDL_DestroyWindow(window);
SDL_GL_DeleteContext(glContext);
SDL_Quit();
return 0;
}
// Simple debugger callback, will most likely modify in the future.
static void APIENTRY openglCallbackFunction(
GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam
){
(void)source; (void)type; (void)id;
(void)severity; (void)length; (void)userParam;
fprintf(stderr, "%s\n", message);
if (severity==GL_DEBUG_SEVERITY_HIGH) {
fprintf(stderr, "Aborting...\n");
abort();
}
}
std::vector<GLfloat> vertices {
// positions // colors
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // bottom left
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // top
};
std::vector<GLuint> indices {
0, 1, 2
};
std::vector<int> vertexAttribSizes {
3
};
int main(int argc, char* argv[]) {
// Variables
bool quit = false;
// Initializations
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(IMG_INIT_PNG);
setGLAttributes();
// Creating the window
SDL_Window* window = SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, winW, winH, flags);
SDL_GLContext glContext = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, glContext);
SDL_Surface* icon = IMG_Load("images/icon.png");
setIcon(window, icon);
// Setting up OpenGL
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) {
printf("Failed to initialize GLAD\n");
return -1;
}
glViewport(0, 0, winW, winH);
// Enable the debug callback
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(openglCallbackFunction, nullptr);
glDebugMessageControl
(
GL_DONT_CARE,
GL_DONT_CARE,
GL_DONT_CARE,
0, NULL, true
);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Renderer::Queue queue;
Renderer::Shader shader;
Renderer::Object object;
shader.Update("CUT OUT THE DIRECTORY FOR THIS POST (because it doesn't matter)", "CUT OUT THE DIRECTORY FOR THIS POST (because it doesn't matter)");
object.Update(vertices, indices, shader.id, "triangle", vertexAttribSizes);
object.Attach(queue);
while(!quit) {
SDL_Event event;
mouseX = event.motion.x;
mouseY = event.motion.y;
while (SDL_PollEvent(&event) != 0) {
inputCollection(event, quit);
}
SDL_SetWindowHitTest(window, hitCallback, 0);
glClearColor(0.085f, 0.085f, 0.085f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
queue.Render();
SDL_GL_SwapWindow(window);
}
// Closes all processes
object.Detach(queue);
close(window, glContext);
return 0;
}
renderer.h (it is included in loader.h, which is included in main.cpp. loader.h I believe doesn't contain the issue, so I dont want to pollute this post with even more code haha)
// Includes
#include <glad/glad.h>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <ctype.h>
#include <fstream>
#include <cstring>
#include <sstream>
// Renderer
namespace Renderer {
class Shader {
private:
// Read the shader's source code.
std::string readFile(const char* _path);
// Check the shader.
bool checkShader(GLuint &_shader);
// Check the program.
bool checkProgram(GLuint &_program);
public:
const char* vertexPath;
const char* fragmentPath;
GLuint id;
void Update(const char* _vertexPath, const char* _fragmentPath); // Update the shader's parameters.
void Use() { glUseProgram(id); } // Use the shader.
};
class Queue {
public:
GLuint VAO;
void listObjects(); // List all objects in the queue (BY NAME, INDEX IS THE ID FOR ALL VALUES/PARAMETERS)
GLuint getObject(std::string objName); // Grab an object from the queue (BY NAME, INDEX IS THE ID FOR ALL VALUES/PARAMETERS) [Returns the id of the object]
bool findObject(std::string objName); // Returns true or false if the object is found.
void Render(); // Render all objects in the queue. (Sets VAOs)
std::vector<std::vector<GLfloat>> vertices;
std::vector<std::vector<int>> indices;
std::vector<std::vector<int>> vertexAttribs;
std::vector<int> shaderProgramIDs;
std::vector<std::string> names;
};
class Object {
public:
GLuint VBO, EBO;
std::vector<GLfloat> vertices;
std::vector<int> indices;
std::vector<int> vertexAttribSizes; // This is the sizes of the vertex attributes, not the values.
GLuint shaderProgramID;
std::string name;
// Set the object's parameters.
void Update(
std::vector<GLfloat> _vertices,
std::vector<GLuint> _indices,
int _shaderProgramID,
std::string _name,
std::vector<int> _vertexAttribSizes
);
void Attach(Queue &queue);
void Detach(Queue &queue);
};
};
renderer.cpp
#include <renderer.h>
using namespace Renderer;
// List all objects in the queue.
void Queue::listObjects() {
for (auto name : names) {
std::cout << name << std::endl;
}
}
// Returns true or false if the object is found.
bool Queue::findObject(std::string objName) {
auto index = std::find(names.begin(), names.end(), objName);
if (index != names.end()) {
return true;
} else {
return false;
}
}
// Returns the object id.
GLuint Queue::getObject(std::string objName) {
auto index = std::find(names.begin(), names.end(), objName);
if (findObject(objName)) {
return index - names.begin();
} else {
return -1;
}
}
// Renders all objects linked to the current queue.
void Queue::Render() {
for (int i = 0; i < names.size(); i++) {
glUseProgram(shaderProgramIDs[i]);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices[i].size(), GL_UNSIGNED_INT, 0);
}
}
std::string Shader::readFile(const char* _path) {
std::string content;
std::ifstream fileStream(_path, std::ios::in);
if (!fileStream.is_open()) {
std::cerr << "Could not read file " << _path << ". File does not exist." << std::endl;
return "";
}
std::string line = "";
while (!fileStream.eof()) {
std::getline(fileStream, line);
content.append(line + "\n");
}
fileStream.close();
return content;
}
bool Shader::checkShader(GLuint &_shader) {
GLint success;
glGetShaderiv(_shader, GL_COMPILE_STATUS, &success);
if(!success) {
GLint maxLength = 0;
glGetShaderiv(_shader, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> errorLog(maxLength);
glGetShaderInfoLog(_shader, maxLength, &maxLength, &errorLog[0]);
std::cout << "Shader compilation failed: " << std::endl;
std::cout << &errorLog[0] << std::endl;
return false;
}
return true;
}
bool Shader::checkProgram(GLuint &_program) {
GLint success;
glGetProgramiv(_program, GL_LINK_STATUS, &success);
if(!success) {
GLint maxLength = 0;
glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> errorLog(maxLength);
glGetProgramInfoLog(_program, maxLength, &maxLength, &errorLog[0]);
std::cout << "Program linking failed: " << std::endl;
std::cout << &errorLog[0] << std::endl;
return false;
}
return true;
}
void Shader::Update(
const char* _vertexPath,
const char* _fragmentPath
){
GLuint vertex, fragment;
vertex = glCreateShader(GL_VERTEX_SHADER);
fragment = glCreateShader(GL_FRAGMENT_SHADER);
vertexPath = _vertexPath;
fragmentPath = _fragmentPath;
std::string vertexString = readFile(_vertexPath);
std::string fragmentString = readFile(_fragmentPath);
const char *vertexSource = vertexString.c_str();
const char *fragmentSource = fragmentString.c_str();
glShaderSource(vertex, 1, &vertexSource, NULL);
glCompileShader(vertex);
checkShader(vertex);
glShaderSource(fragment, 1, &fragmentSource, NULL);
glCompileShader(fragment);
checkShader(fragment);
this->id = glCreateProgram();
glAttachShader(this->id, vertex);
glAttachShader(this->id, fragment);
glLinkProgram(this->id);
checkProgram(this->id);
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Object::Attach(Queue &queue) {
queue.names.push_back(this->name);
GLuint id = queue.getObject(this->name);
queue.shaderProgramIDs.insert(queue.shaderProgramIDs.begin()+id, this->shaderProgramID);
queue.vertices.insert(queue.vertices.begin()+id, this->vertices);
queue.indices.insert(queue.indices.begin()+id, this->indices);
queue.vertexAttribs.insert(queue.vertexAttribs.begin()+id, this->vertexAttribSizes);
glGenBuffers(1, &this->VBO);
glGenBuffers(1, &this->EBO);
glGenVertexArrays(1, &queue.VAO);
glBindVertexArray(queue.VAO);
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(this->vertices), &this->vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(this->indices), &this->indices, GL_STATIC_DRAW);
int stride = 3;
for (int i = 0; i < this->vertexAttribSizes.size(); i++) {
stride+=this->vertexAttribSizes[i];
}
// Positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Other attributes
int totalSize = 3;
for (int i = 0; i < this->vertexAttribSizes.size(); i++) {
glVertexAttribPointer(i+1, this->vertexAttribSizes[i], GL_FLOAT, GL_FALSE, stride * sizeof(float), (void*)(totalSize * sizeof(float)));
glEnableVertexAttribArray(i+1);
totalSize+=this->vertexAttribSizes[i];
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Object::Detach(Queue &queue) {
GLuint id = queue.getObject(this->name);
queue.names.erase(std::remove(queue.names.begin(), queue.names.end(), this->name), queue.names.end());
queue.vertices.erase(queue.vertices.begin()+id, queue.vertices.begin()+id+this->vertices.size());
queue.indices.erase(queue.indices.begin()+id, queue.indices.begin()+id+this->indices.size());
queue.vertexAttribs.erase(queue.vertexAttribs.begin()+id, queue.vertexAttribs.begin()+id+this->vertexAttribSizes.size());
glDeleteBuffers(1, &this->VBO);
glDeleteBuffers(1, &this->EBO);
}
void Object::Update(
std::vector<GLfloat> _vertices,
std::vector<GLuint> _indices,
int _shaderProgramID,
std::string _name,
std::vector<int> _vertexAttribSizes
){
// TODO: Clear all vectors, also detach and reattach automatically.
for (int i = 0; i < _vertices.size(); i++) {
vertices.push_back(_vertices[i]);
}
for (int i = 0; i < _indices.size(); i++) {
indices.push_back(_indices[i]);
}
for (int i = 0; i < _vertexAttribSizes.size(); i++) {
vertexAttribSizes.push_back(_vertexAttribSizes[i]);
}
shaderProgramID = _shaderProgramID;
name = _name;
}
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(this->vertices), &this->vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(this->indices), &this->indices, GL_STATIC_DRAW);
this->vertices is a std::vector. You are uploading raw pointer values where there should be actual data in the buffer.
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * this->vertices.size(), this->vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * this->indices.size(), this->indices.data(), GL_STATIC_DRAW);

Rendering a single triangle using TriangleStrip renders a rectangle

I am trying to render a triangle with a triangle strip, but the word thing is that I am getting a rectangle.
Here is my client application code. I hardcoded points and the indices, create a VBO and an index buffer, and just call glDrawElements.
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
using namespace std;
#define PI 3.14159265359
static string ParseShader(string filepath) {
ifstream stream(filepath);
string line;
stringstream stringStream;
while (getline(stream, line))
{
stringStream << line << '\n';
}
return stringStream.str();
}
static unsigned int CompileShader(unsigned int type, const string& source) {
unsigned int id = glCreateShader(type);
const char* src = source.c_str(); // this returns a pointer to data inside the string, the first character
glShaderSource(id, 1, &src, nullptr); // shader id, count of source codes, a pointer to the array that holds the strings
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
cout << type << endl;
cout << message << endl;
glDeleteShader(id);
return 0;
}
return id;
}
// takes the shader codes as a string parameters
static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader)
{
GLuint program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program); // validate if the program is valid and can be run in the current state of opengl
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
int main(void)
{
GLFWwindow* window;
float Angle = 40;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
// call glewInit after creating the context...
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
const int vertexCoordinateCount = 2;
const int coordinateCount = 6;
const int indexCount = 3;
GLfloat coordinates[coordinateCount] = {
500.0f, 0.0f,
-250.0f, 250.f,
-250.f, -250.f,
};
GLuint indices[indexCount] = { 0, 1, 2 };
GLuint position_buffer;
glGenBuffers(1, &position_buffer);
glBindBuffer(GL_ARRAY_BUFFER, position_buffer);
glBufferData(GL_ARRAY_BUFFER, coordinateCount * sizeof(float), coordinates, GL_STATIC_DRAW);
glVertexAttribPointer(0, vertexCoordinateCount, GL_FLOAT, GL_FALSE, sizeof(float) * vertexCoordinateCount, 0);
glEnableVertexAttribArray(0);
GLuint index_buffer;
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(GLuint), indices, GL_STATIC_DRAW);
string vertexSource = ParseShader("vertex.shader");
string fragmentSource = ParseShader("fragment.shader");
unsigned int program = CreateShader(vertexSource, fragmentSource);
glUseProgram(program);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, nullptr);
//Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glDeleteProgram(program);
glfwTerminate();
return 0;
}
My vertex shader :
#version 330 core
layout(location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos, 1.0);
}
And my fragment shader:
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
Edit: Adding a screenshot of the render result.
You do not transform the vertex coordinates. Therefore the vertices must be spepcified in Normalized Device Space, in range [-1.0, 1.0]. e.g.:
GLfloat coordinates[coordinateCount] = {
1.0f, 1.0f,
-1.0f, 1.0f,
1.0f, -1.0f,
};
You're actually drawing a triangle, but you only see an inner part of it. The rest is clipped.

Assimp can't load other textures except diffuse texture of FBX

I try to load the FBX model in the last contains of this learnopengl tutorial, but I only can load diffuse texture of the FBX. I had tried the solution of adjusting the order of layout in vertex shader, but it didn't work. The result of material->GetTextureCount(type) is 0 when type isn't aiTextureType_DIFFUSE.
Here is my code:
mesh.h
#ifndef Mesh_h
#define Mesh_h
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "ReviewShader.h"
struct Vertex{
glm::vec3 Position;
glm::vec3 Normal;
glm::vec2 TexCoord;
};
struct Texture{
unsigned int id;
string type;
string path;
};
class Mesh{
public:
vector<Texture> textures;
vector<unsigned int> indices;
unsigned int VAO;
Mesh(vector<Vertex> vertices, vector<Texture> textures, vector<unsigned int> indices){
this->vertices = vertices;
this->textures = textures;
this->indices = indices;
setupMesh();
}
void Draw(ReviewShader shader){
int diffuseCount = 1;
int specularCount = 1;
int reflectionCount = 1;
shader.use();
for(int i = 0; i < textures.size(); i++){
string name = textures[i].type;
string num;
if(name == "texture_diffuse")
num = to_string(diffuseCount++);
else if(name == "texture_specular")
num = to_string(specularCount++);
else if(name == "texture_reflection")
num = to_string(reflectionCount++);
shader.setInt((name+num).c_str(), i);
glActiveTexture(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D, textures[i].id);
}
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(0);
}
private:
vector<Vertex> vertices;
unsigned int VBO, EBO;
void setupMesh(){
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoord));
glEnableVertexAttribArray(2);
glBindVertexArray(0);
}
};
#endif /* Mesh_h */
model.h
#ifndef Model_h
#define Model_h
#include <iostream>
using namespace std;
#include <string>
#include <vector>
#include "Mesh.h"
#include "ReviewShader.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
//#define STB_IMAGE_IMPLEMENTATION
#include <stb-master/stb_image.h>
vector<Texture> loaded_textures;
class Model{
public:
vector<Mesh> meshes;
string directory;
Model(char *path){
loadModel(path);
}
void Draw(ReviewShader shader){
for(int i = 0; i < meshes.size(); i++){
meshes[i].Draw(shader);
}
}
private:
void loadModel(string path){
Assimp::Importer importer;
// const aiScene *scene = importer.ReadFile(path, aiProcess_FlipUVs | aiProcess_Triangulate);
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode){
cout << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
return;
}
directory = path.substr(0, path.find_last_of("/"));
processNode(scene->mRootNode, scene);
}
void processNode(aiNode *node, const aiScene *scene){
for(int i = 0; i < node->mNumMeshes; i++){
aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(processMesh(mesh, scene));
}
for(int i = 0; i < node->mNumChildren; i++){
processNode(node->mChildren[i], scene);
}
}
Mesh processMesh(aiMesh *mesh, const aiScene *scene){
vector<Vertex> vertices;
vector<Texture> textures;
vector<unsigned int> indices;
for(int i = 0; i < mesh->mNumVertices; i++){
Vertex vertex;
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
if(mesh->mTextureCoords[0]){
glm::vec2 tex;
tex.x = mesh->mTextureCoords[0][i].x;
tex.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoord = tex;
}
else{
vertex.TexCoord = glm::vec2(0.0, 0.0);
}
vertices.push_back(vertex);
}
for(int i = 0; i < mesh->mNumFaces; i++){
aiFace face = mesh->mFaces[i];
for(int j = 0; j < face.mNumIndices; j++){
indices.push_back(face.mIndices[j]);
}
}
aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
vector<Texture> texture_diffuse = loadMaterialTexture(material, aiTextureType_DIFFUSE, "texture_diffuse");
textures.insert(textures.end(), texture_diffuse.begin(), texture_diffuse.end());
vector<Texture> texture_specular = loadMaterialTexture(material, aiTextureType_SPECULAR, "texture_specular");
textures.insert(textures.end(), texture_specular.begin(), texture_specular.end());
vector<Texture> texture_ambient = loadMaterialTexture(material, aiTextureType_SHININESS, "texture_reflection");
textures.insert(textures.end(), texture_ambient.begin(), texture_ambient.end());
return Mesh(vertices, textures, indices);
}
vector<Texture> loadMaterialTexture(aiMaterial *material, aiTextureType type, string Typename){
vector<Texture> textures;
cout << material->GetTextureCount(type) << endl;
for(int i = 0; i < material->GetTextureCount(type); i++){
bool skip = false;
aiString str;
material->GetTexture(type, i, &str);
string tempStr = str.C_Str();
tempStr.replace(tempStr.find("\\"), 1, "/");
cout << tempStr << endl;
for(int j = 0; j < loaded_textures.size(); j++){
if(strcmp(loaded_textures[j].path.c_str(), tempStr.c_str()) == 0){
skip = true;
textures.push_back(loaded_textures[i]);
break;
}
}
if(!skip){
Texture tex;
tex.id = loadTextureFromFile(tempStr, directory);
tex.type = Typename;
tex.path = str.C_Str();
textures.push_back(tex);
loaded_textures.push_back(tex);
}
}
return textures;
}
unsigned int loadTextureFromFile(string path, string &Directory){
unsigned int textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
string filepath = Directory + "/" + path;
int width, height, urChannel;
unsigned char *data = stbi_load(filepath.c_str(), &width, &height, &urChannel, 0);
if(data){
GLenum format;
if(urChannel == 1)
format = GL_RED;
if(urChannel == 3)
format = GL_RGB;
if(urChannel == 4)
format = GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(data);
}
else{
cout << "Read texture Data failed\n";
stbi_image_free(data);
}
return textureID;
}
};
#endif /* Model_h */
model.vs
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aUV;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 Normal;
out vec2 UV;
out vec3 Position;
void main(){
gl_Position = projection * view * model * vec4(aPos, 1.0);
UV = aUV;
Normal = mat3(transpose(inverse(model))) * aNormal;
Position = vec3(model * vec4(aPos, 1.0));
}
model.fs
#version 330 core
out vec4 FragColor;
uniform sampler2D texture_diffuse;
uniform sampler2D texture_specular;
uniform sampler2D texture_roughness;
in vec3 Normal;
in vec2 UV;
in vec3 Position;
void main(){
FragColor = texture(texture_diffuse, UV);
}
main.cpp
#include <...>
...
using namespace std;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);
unsigned int loadTexture(const char *path);
unsigned int loadHDRTexture(char const * path);
unsigned int loadCubemap(vector<string> faces);
void renderQuad();
void renderCube();
void renderPlane();
void renderSphere();
float lerp(float a, float b, float scale);
// size settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
glm::vec3 lightPos = glm::vec3(2.0, 4.0, -2.0);
glm::vec3 lightColor = glm::vec3(0.2, 0.2, 0.7);
// calculation parameter
const float Pi = 3.14159265359;
const float doublePi = Pi * 2.0;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 10.0f));
float lastX = (float)SCR_WIDTH / 2.0;
float lastY = (float)SCR_HEIGHT / 2.0;
bool firstMouse = true;
// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;
// texture normal
glm::vec3 normal(0.0, 0.0, 1.0);
// plane normal
glm::vec3 planeNormal = glm::vec3(0.0, 1.0, 0.0);
int main()
{
// glfw: initialize and configure
// ------------------------------
...
// Create shaders
...
ReviewShader modelShader("shader/model.vs", "shader/model.fs");
// pbr configure
...
Model gunModel = Model("Gun_Model/Cerberus_LP.FBX");
while(!glfwWindowShouldClose(window))
{
// avoid delay
// -----------
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// process input
// -------------
processInput(window);
glViewport(0, 0, SCR_WIDTH * 2, SCR_HEIGHT * 2);
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 model = glm::mat4(1.0);
glm::mat4 view = camera.getViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
modelShader.use();
model = glm::mat4(1.0);
model = glm::scale(model, glm::vec3(0.1));
model = glm::rotate(model, glm::radians(-90.0f), glm::vec3(1.0, 0.0, 0.0));
modelShader.setMat4("model", model);
modelShader.setMat4("view", view);
modelShader.setMat4("projection", projection);
gunModel.Draw(modelShader);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
At first: which version of the Asset-Importer-Lib do you use? We made a lot of improvements in the FBX-Importer, so switching to the latest 5.0-release is strongly recommended.
Normally when the number of textures shows zero it is a sign that there is only one texture used in our model. To verify that yo can just use Blender, The interal Asset-Importer-Viewer or the Editor of the Godot-Engine to check that your model is right.
If there is more than just a diffuse-texture stored in your model please create a new issue report here: Assimp-Bugtracker . And please add a model which we can use to reproduce the issue. Thanks in advance!

OpenGL Program Shader Linking Error

I have been working to create a circle based on a shader that changes color periodically. My code prints out a blank window. I decided to set-up some methods to check for errors using GL_LINK_STATUS and it seems that my code is encountering an issue linking the program and the shader.
I did some research into similar issues that people have had but they don't seem to have similar causes.
I have posted my shader code, the driver program(named Priomary) and the Shader Program below.
Vertex Shader
#version 330 core
layout (location = 0) in vec3 pos;
uniform vec2 posOffset;
void main()
{
gl_Position = vec4(pos.x + posOffset.x, pos.y + posOffset.y, pos.z, 1.0);
}
Fragment Shader
#version 330 core
uniform vec4 vertColor;
out vec4 frag_color;
void main()
{
frag_color = vertColor;
}
Shader Program
#include "ShaderProgram.h"
#include <fstream>
#include <iostream>
#include <sstream>
ShaderProgram::ShaderProgram()
: mProgram(0){
}
ShaderProgram::~ShaderProgram()
{
glDeleteProgram(mProgram);
}
bool ShaderProgram::assignShaders(const char* vertFileName, const char* fragFileName)
{
//Shaders output objects called programs that define their relationship and lead to .exe functionality
//assigning pointer to the shader
string vsString = readFile(vertFileName);
string fsString = readFile(fragFileName);
// c_str returns a const char* that points to a null-terminated string (i.e. a C-style string). It is useful when you want to pass the "contents"¹ of an std::string to a function that expects to work with a C-style string.
const GLchar* vsSourcePtr = vsString.c_str();
const GLchar* fsSourcePtr = fsString.c_str();
//creating vertex shader(vs) shader object
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
//assigning shader source using address. Replaces the source code in a shader object //#arg (shader, count Strings, pointer to const File ,size)
glShaderSource(vs, 1, &vsSourcePtr, NULL);
glShaderSource(fs, 1, &fsSourcePtr, NULL);
glCompileShader(vs);
testShaderCompile(vs);
glCompileShader(fs);
testShaderCompile(fs);
//createProgram returns GLUint which is basically an unsigned int... we will use This Handler to create a program object
mProgram = glCreateProgram();
if (mProgram == 0)
{
std::cerr << "Shader cannot be created" << std::endl;
return false;
}
//assign the program object(mProgram) to the Shader
glAttachShader(mProgram, vs);
glAttachShader(mProgram, fs);
//this method accepts a GLuint "program" . If its an object of type GL_VERTEX_SHADER,
//itll create a .exe that runs on the programmable vertex processor. same goes for geometric and fragment shaders if they were included
//it will also bind all user defined uniform variables and attributes to the program
//The program can then be made part of a defined state by calling useProgram
glLinkProgram(mProgram);
testProgramCompile();
//cleaning up the elements we already used
glDeleteShader(vs);
glDeleteShader(fs);
//clear the identifier lookup map(in this case, there's only one)
mUniformIdentifiers.clear();
return true;
}//end main
//Read the shaderFile. strngstream for reading multiple lines
string ShaderProgram:: readFile(const string& filename) {
std::stringstream strgstream;
std::ifstream file;
try
{
file.open(filename, std::ios::in);
if (!file.fail())
{
strgstream << file.rdbuf();
}
file.close();
}
catch (std::exception ex)
{
std::cerr << "Error: File or File Name Issues" << std::endl;
}
return strgstream.str();
}
//use the Program Object we created in this current state(color)
void ShaderProgram::use()
{
//check if it is not null
if (mProgram > 0)
glUseProgram(mProgram);
}
void ShaderProgram::dumpShaderLog(bool is_shader, GLuint obj)
{
int maxlen = 0;
if (is_shader) glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &maxlen);
else glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &maxlen);
if (maxlen > 0)
{
char *log = new char[maxlen];
int len;
if (is_shader) glGetShaderInfoLog(obj, maxlen, &len, log);
else glGetProgramInfoLog(obj, maxlen, &len, log);
if (len > 0 && log[0] != '\0')
fprintf(stderr, "%s\n", log);
delete[] log;
}
}
void ShaderProgram::testProgramCompile() {
int status = 0;
GLuint program = mProgram;
// ///CHECKING GL_LINK_STATUS to see if Program Link was successul. Link Status will return GL_TRUE if it was
glGetProgramiv( mProgram, GL_LINK_STATUS, &status); //requesting the status
if (status == GL_FALSE)
{
GLint length = 0;
glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &length);
string errorLog(length, ' '); // Resize and fill with space character
glGetProgramInfoLog(mProgram, length, &length, &errorLog[0]);
dumpShaderLog(false, mProgram);
std::cerr << "Linking Error with Program and Shader" << std::endl;
}
}
void ShaderProgram :: testShaderCompile(GLuint shader) {
int status = 0;
// ///CHECKING GL_LINK_STATUS to see if Program Link was successul. Link Status will return GL_TRUE if it was
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);//requesting the status
if (status == GL_FALSE)
{
GLint length = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
string errorLog(length, ' '); // Resize and fill with space character
glGetShaderInfoLog(shader, length, &length, &errorLog[0]);
std::cerr << "SHADER COMPILE TEST ERROR " << std::endl;
}
}
////GETTERS AND SETTERS
GLuint ShaderProgram::getProgram() const
{
return mProgram;
}
void ShaderProgram::setUniform(const GLchar* name, const glm::vec2& v)
{
GLint address = getUniformIdentifier(name);
glUniform2f(address, v.x, v.y);
}
void ShaderProgram::setUniform(const GLchar* name, const glm::vec3& v)
{
GLint address = getUniformIdentifier(name);
glUniform3f(address, v.x, v.y, v.z);
}
void ShaderProgram:: setUniform(const GLchar* name, const glm::vec4& v) {
GLint address = getUniformIdentifier(name);
glUniform4f(address, v.x, v.y, v.z, v.w);
}
//Maybe need to switch places with setUniform
GLint ShaderProgram :: getUniformIdentifier(const GLchar* name) {
std::map<std::string, GLint>::iterator it;
it = mUniformIdentifiers.find(name);
//std::map<std::string, GLint>
// Only need to query the shader program IF it doesn't already exist.
if (it == mUniformIdentifiers.end())
{
// Find it and add it to the map
mUniformIdentifiers[name] = glGetUniformLocation(mProgram, name);
}
// Return it
return mUniformIdentifiers[name];
}
Primary Program
#include <iostream>
#include <vector>
#include <sstream>
#define GLEW_STATIC
//always GLEW before GLFW
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "glm/glm.hpp"
#include "ShaderProgram.h"
#ifndef M_PI
# define M_PI 3.141592653
#endif
/////gLOBAL
GLFWwindow* w = NULL;
const int wWidth = 800;
const int wHeight = 600;
std::vector<glm::vec3> vertices;
std::vector<unsigned int> indices;
GLfloat Radius = 6;
GLfloat Stacks = 5;
GLfloat Slices = 5;
void key_callback(GLFWwindow *w, int key, int scancode, int action, int mode);
//update colors based on average framerate
void averageFPS(GLFWwindow* window);
//screen resizing
void glfw_onFramebufferSize(GLFWwindow* window, int width, int height);
bool initOpenGL();
static void error(int error, const char *desc)
{
fputs(desc, stderr);
}
//setting up values for keys
int main() {
//pointing to GLFW window
//GLFWwindow *w; //may want to initialize as null outside before main
if (!initOpenGL()) ///5IMPR
{
// An error occured
std::cerr << "GLFW not initialized" << std::endl;
return -1;
}
glfwSetErrorCallback(error);
///TEMP CIRCLE VERTICES
// Calc The Vertices
for (int i = 0; i <= Stacks; ++i) {
float V = i / (float)Stacks;
float phi = V * M_PI; //change to glm:: pi
// Loop Through Slices
for (int j = 0; j <= Slices; ++j) {
float U = j / (float)Slices;
float theta = U * (M_PI * 2);
// Calc The Vertex Positions
float x = cosf(theta) * sinf(phi);
float y = cosf(phi);
float z = sinf(theta) * sinf(phi);
// Push Back Vertex Data //push_back is a standard vector function which adds a parameter to the end of the vector
//std::vector<glm::vec3> vertices; //moved to global variables at top
vertices.push_back(glm::vec3(x, y, z) * Radius);
}
}
// Calc The Index Positions
for (int i = 0; i < Slices * Stacks + Slices; ++i) {
indices.push_back(i);
indices.push_back(i + Slices + 1);
indices.push_back(i + Slices);
indices.push_back(i + Slices + 1);
indices.push_back(i);
indices.push_back(i + 1);
}
////TEMP CIRCLE VERTICES END
// 2. Set up buffers on the GPU
GLuint vbo, ibo, vao; ///5IMPROVEdown
glGenBuffers(1, &vbo); // Generate an empty vertex buffer on the GPU
glBindBuffer(GL_ARRAY_BUFFER, vbo); // "bind" or set as the current buffer we are working with
//3rd argument of glBufferData needs a pointer to the std:vector data...A pointer to the data can be obtained by vertices.data() accrding to std: ector docs...
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW);// copy the data from CPU to GPU
glGenVertexArrays(1, &vao); // Tell OpenGL to create new Vertex Array Object
glBindVertexArray(vao); // Make it the current one
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); // Define a layout for the first vertex buffer "0"
glEnableVertexAttribArray(0); // Enable the first attribute or attribute "0"
// Set up index buffer
glGenBuffers(1, &ibo); // Create buffer space on the GPU for the index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
// glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); - REPLACED
glBindVertexArray(0); // unbind to make sure other code doesn't change it
ShaderProgram shaderProgram; ///5ADD
shaderProgram.assignShaders("shaders\\ColorShader.vert", "shaders\\ColorShader.frag"); ///5ADD
////////SETUP RENDERING
while (!glfwWindowShouldClose(w))
{
averageFPS(w);
//process events
glfwPollEvents();
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT);
shaderProgram.use(); ///5ADD
GLfloat time = (GLfloat)glfwGetTime(); ///5ADD
GLfloat blueSetting = (sin(time) / 2) + 0.5f; ///5ADD
glm::vec2 pos;
pos.x = sin(time) / 2;
pos.y = cos(time) / 2;
shaderProgram.setUniform("vertColor", glm::vec4(0.0f, 0.0f, blueSetting, 1.0f)); ///5ADD
shaderProgram.setUniform("posOffset", pos);
glBindVertexArray(vao);
//og for quad
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//glDrawElements(GL_LINE_LOOP, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
// Swap buffers and look for events
glfwSwapBuffers(w);
}
//clean up
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ibo);
//glfwDestroyWindow(w);
glfwTerminate();
return 0;
}
///////START Initializing glfw glew etc
bool initOpenGL(){
//this method will exit on these conditions
GLuint error = glfwInit();
if (!error)
return false;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
w = glfwCreateWindow(wWidth, wHeight, "Exercise", NULL, NULL);
if (w== NULL)
{
std::cerr << "glfw window not created" << std::endl;
glfwTerminate();
return false;
}
//update context
glfwMakeContextCurrent(w);
// Initialize GLEWunifor
glewExperimental = GL_TRUE;
GLuint err = glewInit();
if (err != GLEW_OK)
{
std::cerr << "initialize GLEW Failed" << std::endl;
return false;
}
//setup key callbacks
glfwSetKeyCallback(w, key_callback);
glfwSetFramebufferSizeCallback(w, glfw_onFramebufferSize);
glClearColor(0.23f, 0.38f, 0.47f, 1.0f); ///5ADD
// Define the viewport dimensions
glViewport(0, 0, wWidth, wHeight); //necessary?
return true;
}
void key_callback(GLFWwindow *w, int key, int scancode, int action, int mode)
{
// See http://www.glfw.org/docs/latest/group__keys.html
if ((key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) && action == GLFW_PRESS)
glfwSetWindowShouldClose(w, GL_TRUE);
if (key == GLFW_KEY_W && action == GLFW_PRESS)
{
bool showWires = false;
if (showWires)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
//whever window resizes, do this
void glfw_onFramebufferSize(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void averageFPS(GLFWwindow* window) ///5ADDdown
{
static double previousSeconds = 0.0;
static int frameCount = 0;
double passedSeconds;
double currentSeconds = glfwGetTime(); //seconds since GLFW started
passedSeconds = currentSeconds - previousSeconds;
// Limit time updates to 4 times per second
if (passedSeconds > 0.25)
{
previousSeconds = currentSeconds;
double fps = (double)frameCount / passedSeconds;
// double frameInMilSecs = 1000.0 / fps;
frameCount = 0;}
frameCount++;
}
While glGetShaderiv returns a parameter from a shader object, glGetProgramiv returns a parameter from a program object.
This means you have to change your code like this:
// glGetProgramiv(shader, GL_COMPILE_STATUS, &status); <--- delete
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
Ensure that the shader files are correctly loaded and trace them for debug reasons:
glShaderSource(vs, 1, &vsSourcePtr, NULL);
glShaderSource(fs, 1, &fsSourcePtr, NULL);
std::cout << "VERTEX SHADER:" << std::endl << vsSourcePtr << std::endl << std::endl;
glCompileShader(vs);
testShaderCompile(vs);
std::cout << "FRAGMENT SHADER:" << std::endl << fsSourcePtr << std::endl << std::endl;
glCompileShader(fs);
testShaderCompile(fs);
Since you don't set any matrices, you have to set up all the vertex coordinates in normalized device space, which is in [-1.0, 1.0].
To make the mesh proper "visible" on the viewport set the radius of the sphere to 0.5:
GLfloat Radius = 0.5f;
and draw all the primitives:
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);