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

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

Related

OpenGL texture does not work with no errors - black screen [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I just don't understand why it does not work - it just shows a white screen... (or a black one, because glClearColor)
PS. > the texture also broke everything else...
I checked the shaders and the code: no errors, no responses, nothing. Including the texture.
I think the shaders are right, but i don't know about anything else. I also have all the libraries: GLEW, GLFW, OPENGL, a single header file copied from stb_image...
Here is the code:
#include <iostream>
#include <fstream>
#include <string>
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#define ASSERT(x) if(!(x)) __debugbreak();
#define CALL(x) OpenGlClError(); x; ASSERT(OpenGlError(#x, __LINE__, __FILE__));
#define STB_IMAGE_IMPLEMENTATION
#include "extern/stb_image/stb_image_vendor/stb_image.h"
void OpenGlClError() {
while (glGetError());
}
bool OpenGlError(const char* func, int line, const char* file) {
while (GLenum error = glGetError()) {
std::cout << "GLTest: OPENGL ERROR: " << error << " in function " << func << " at line " << line << ", FILE: " << file << "\n";
return false;
}
return true;
}
#define ASSERT(x) if(!(x)) __debugbreak();
#define CALL(x) OpenGlClError(); x; ASSERT(OpenGlError(#x, __LINE__, __FILE__));
class Texture {
private:
unsigned int TextID;
std::string FilePath;
unsigned char* LocalBuffer;
int Width, Height, BytesPixel;
public:
Texture(const std::string path)
: TextID(0), FilePath(path), LocalBuffer(nullptr), Width(0), Height(0), BytesPixel(0) {
CALL(glGenTextures(1, &TextID));
CALL(glBindTexture(GL_TEXTURE_2D, TextID));
stbi_set_flip_vertically_on_load(1);
LocalBuffer = stbi_load(path.c_str(), &Width, &Height, &BytesPixel, 4);
CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, LocalBuffer));
CALL(glBindTexture(GL_TEXTURE_2D, 0));
if (LocalBuffer) { //if localbuffer exists
stbi_image_free(LocalBuffer);
}
}
~Texture() {
glDeleteTextures(1, &TextID);
}
void Bind(unsigned int slot = 0){
CALL(glActiveTexture(GL_TEXTURE0 + slot));
CALL(glBindTexture(GL_TEXTURE_2D, TextID));
}
void Unbind() {
glBindTexture(GL_TEXTURE_2D, 0);
}
};
static std::string ReadShader(const std::string& filename) {
std::ifstream stream;
std::string line;
std::string str;
stream.open(filename);
while (getline(stream, line)) {
str.append(line).append("\n");
}
std::cout << str;
stream.close();
return str;
}
static unsigned int CompileShader(const std::string& source, unsigned int type) {
unsigned int shader = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
int result;
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
// i - int
// v - vector
if (result == GL_FALSE) {
std::cout << "Shader cannot be compiled.\n" << (type == GL_VERTEX_SHADER ? "vertex s." : "fragments.") << "\n";
int length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)_malloca(length * sizeof(char));
glGetShaderInfoLog(shader, length, &length, message);
std::cout << message << "\n";
glDeleteShader(shader);
}
return shader;
}
static int CreateShader(const std::string& vShader, const std::string& fShader) {
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(vShader, GL_VERTEX_SHADER);
unsigned int fs = CompileShader(fShader, GL_FRAGMENT_SHADER);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
int main() {
glfwInit();
//make window
GLFWwindow* window;
//std::cout << "GLTest:" << glGetString(GL_VERSION) << "\n";
window = glfwCreateWindow(800, 500, "Modern OpenGL Test", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
float texver[16] = {
-1.0f, -1.0f , 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 1.0f
};
float texindex[6] = {
0, 1, 2,
2, 3, 0
};
float vertices[12] = {
1.0f, 1.0f,
0.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
0.0f, 1.0f,
-1.0f, -1.0f
};
//unsigned int varray; //< dont actually need it...
//glGenVertexArrays(1, &varray);
//glBindVertexArray(varray);
//unsigned int vb;
//glGenBuffers(1, &vb);
//glBindBuffer(GL_ARRAY_BUFFER, vb);
//glBufferData(GL_ARRAY_BUFFER, 6 * 2 * sizeof(float), vertices, GL_STATIC_DRAW);
//
//glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0); //said hey we have this set up like that, links in vertex array
//glEnableVertexAttribArray(0); //yea remember it
unsigned int tb;
glGenBuffers(1, &tb);
glBindBuffer(GL_ARRAY_BUFFER, tb);
glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float), texver, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); //said hey we have this set up like that, links in vertex array
glEnableVertexAttribArray(0); //yea remember it
unsigned int shaders = CreateShader(ReadShader("shaders/basic_texture_vertex.shader"), ReadShader("shaders/basic_texture_fragment.shader"));
glUseProgram(shaders);
Texture tt("../!Assets/editor/img/intro_logo.png");
tt.Bind();
CALL(int location = glGetUniformLocation(shaders, "u_Texture"));
CALL(glUniform1i(location, 0));
CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1, 1, 1, 1);
//Drawing
glDrawArrays(GL_TRIANGLES, 0, 6 * 2);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteProgram(shaders);
glfwTerminate();
}
You missed to specify the vertex attribute for the texture coordinates. For instance
unsigned int tb;
glGenBuffers(1, &tb);
glBindBuffer(GL_ARRAY_BUFFER, tb);
glBufferData(GL_ARRAY_BUFFER, 4 * 4 * sizeof(float), texver, GL_STATIC_DRAW);
// vertex cooridnates
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
glEnableVertexAttribArray(0);
// texture coordinates
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (void*)(sizeof(float)*2));
glEnableVertexAttribArray(1);
The last argument of glDrawArrays is the number of vertices. Since you just have 4 vertices, the argument cannot be 6*2.
Anyway, since you have specified an array indices it seems that you want to specify an Index buffer. You have to use glDrawElements for indexed rendering.
The indices have to be an integral data type:
int texindex[6] = {
0, 1, 2,
0, 2, 3
};
Generate the index (GL_ELEMENT_ARRAY_BUFFER) buffer:
unsigned int ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(int), texindex, GL_STATIC_DRAW);
Draw the tringles:
glDrawArrays(GL_TRIANGLES, 0, 6 * 2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

How do I draw vertices that are stored in a SSBO?

This is a question following OpenGL and loading/reading data in AoSoA (hybrid SoA) format.
I am trying to use a shader storage buffer object (SSBO) to store vertex data which is represented in AoSoA format. I am having trouble drawing the vertices, which obviously means that I am doing something wrong somewhere. The problem is that I can't seem to figure out what or where. The answer to the initial question above seems to indicate that I should not be using vertex attribute arrays, so the question then becomes, how do I render this SSBO, given the code I am about to present?
VertexData structure
constexpr auto VECTOR_WIDTH = 4;
constexpr auto VERTEX_COUNT = 16;
struct VertexData
{
std::array<float, VECTOR_WIDTH> px;
std::array<float, VECTOR_WIDTH> py;
};
// Later stored in a std::vector
std::vector<VertexData> vertices(VERTEX_COUNT / VECTOR_WIDTH);
Vertex shader (should this really be a compute shader?)
struct Vertex4
{
float px[4]; // position x
float py[4]; // position y
};
layout(std430, binding=0) buffer VertexData
{
Vertex4 vertices[];
};
void main()
{
int dataIx = gl_VertexID / 4;
int vertexIx = gl_VertexID % 4;
vec2 vertexPosition = vec2(vertices[dataIx].px[vertexIx], vertices[dataIx].py[vertexIx]);
}
Assign vertexPosition index
// Do I need this? Where do I use it? glEnableVertexAttribArray(position_attrib_index)?
const GLuint position_attrib_index = 0;
glBindAttribLocation(program, position_attrib_index, "vertexPosition");
SSBO setup
const GLuint ssbo_binding_point = 0;
GLuint ssbo{};
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
//glBufferStorage(GL_SHADER_STORAGE_BUFFER, vertices.size() * sizeof(VertexData), vertices.data(), GL_MAP_WRITE_BIT);
glBufferData(GL_SHADER_STORAGE_BUFFER, vertices.size() * sizeof(VertexData), vertices.data(), GL_STATIC_DRAW);
const auto block_index = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "VertexData");
glShaderStorageBlockBinding(program, block_index, ssbo_binding_point);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, ssbo_binding_point, ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
Render loop
while (!glfwWindowShouldClose(window)) {
process_input(window);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
// ???
glfwSwapBuffers(window);
glfwPollEvents();
}
I just can't seem to figure out how this is supposed to work. Grabbing at straws, I also tried creating a VAO with a later call to glDrawArrays(GL_POINTS, 0, VERTEX_COUNT), but it didn't work either:
GLuint vao{};
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(position_attrib_index);
glVertexAttribPointer(position_attrib_index, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
It seems to me that I should be using position_attrib_index (which should point to vertexPosition) for something, the question is for what?
Complete example code
requires OpenGL 4.3, GLEW and GLFW
build command example: g++ -std=c++17 main.cpp -lGLEW -lglfw -lGL -o ssbo
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <array>
#include <iostream>
#include <vector>
void process_input(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
}
void glfw_error_callback(int error_code, const char *description)
{
std::cerr << "GLFW Error: [" << error_code << "] " << description << '\n';
}
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
}
auto create_glfw_window()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
return glfwCreateWindow(800, 600, "OpenGL and AoSoA layout", nullptr, nullptr);
}
void set_callbacks(GLFWwindow *window)
{
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetErrorCallback(glfw_error_callback);
}
void print_versions()
{
std::cout << "Using GLFW " << glfwGetVersionString() << '\n';
std::cout << "Using GLEW " << glewGetString(GLEW_VERSION) << '\n';
}
bool init_loader()
{
GLenum err = glewInit();
if (GLEW_OK != err) {
std::cerr << "GLEW error: " << glewGetErrorString(err);
}
return err == GLEW_OK;
}
void GLAPIENTRY MessageCallback(
GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam = nullptr)
{
std::cerr << "[GL DEBUG] " << (type == GL_DEBUG_TYPE_ERROR ? "Error: " : "") << message << '\n';
}
constexpr auto VECTOR_WIDTH = 4;
constexpr auto VERTEX_COUNT = 16;
struct VertexData
{
std::array<float, VECTOR_WIDTH> px;
std::array<float, VECTOR_WIDTH> py;
};
static const char* vertex_shader_source =
"#version 430\n"
"struct Vertex4\n"
"{\n"
" float px[4]; // position x\n"
" float py[4]; // position y\n"
"};\n"
"layout(std430, binding=0) buffer VertexData\n"
"{\n"
" Vertex4 vertices[];\n"
"};\n"
"void main()\n"
"{\n"
" int dataIx = gl_VertexID / 4;\n"
" int vertexIx = gl_VertexID % 4;\n"
" vec2 vertexPosition = vec2(vertices[dataIx].px[vertexIx], vertices[dataIx].py[vertexIx]);\n"
"}\n";
static const char* fragment_shader_source =
"#version 430\n"
"out vec4 out_color;\n"
"void main()\n"
"{\n"
" out_color = vec4(1.0, 0.5, 0.5, 0.25);\n"
"}\n";
int main(int argc, char *argv[])
{
glewExperimental = GL_TRUE;
auto window = create_glfw_window();
if (window == nullptr) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
set_callbacks(window);
init_loader();
print_versions();
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(MessageCallback, nullptr);
std::vector<VertexData> vertices(VERTEX_COUNT / VECTOR_WIDTH);
vertices[0] = {
{-0.75f, 0.75f, 0.75f, -0.75f},
{-0.75f, -0.75f, 0.75f, 0.75f}
};
vertices[1] = {
{-0.50f, 0.50f, 0.50f, -0.50f},
{-0.50f, -0.50f, 0.50f, 0.50f},
};
vertices[2] = {
{-0.25f, 0.25f, 0.25f, -0.25f},
{-0.25f, -0.25f, 0.25f, 0.25f},
};
vertices[3] = {
{-0.05f, 0.05f, 0.05f, -0.05f},
{-0.05f, -0.05f, 0.05f, 0.05f},
};
auto vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, nullptr);
glCompileShader(vertex_shader);
auto fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, nullptr);
glCompileShader(fragment_shader);
auto program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
const GLuint position_attrib_index = 0;
glBindAttribLocation(program, position_attrib_index, "vertexPosition");
glLinkProgram(program);
//glUseProgram(program);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
//
// SSBO
//
const GLuint ssbo_binding_point = 0;
GLuint ssbo{};
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
//glBufferStorage(GL_SHADER_STORAGE_BUFFER, vertices.size() * sizeof(VertexData), vertices.data(), GL_MAP_WRITE_BIT);
glBufferData(GL_SHADER_STORAGE_BUFFER, vertices.size() * sizeof(VertexData), vertices.data(), GL_STATIC_DRAW);
const auto block_index = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "VertexData");
glShaderStorageBlockBinding(program, block_index, ssbo_binding_point);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, ssbo_binding_point, ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
//
// VAO
//
//GLuint vao{};
//glGenVertexArrays(1, &vao);
//glBindVertexArray(vao);
//glEnableVertexAttribArray(position_attrib_index);
//glVertexAttribPointer(position_attrib_index, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glClearColor(0.15f, 0.15f, 0.2f, 1.0f);
glPointSize(10.0f);
while (!glfwWindowShouldClose(window)) {
process_input(window);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
//glDrawArrays(GL_POINTS, 0, VERTEX_COUNT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
This is the correct way to issue a draw with the data you have:
glBindVertexArray(vao);
glDrawArrays(GL_POINTS, 0, VERTEX_COUNT);
However, your issue is that your vertex shader does not write to gl_Position, therefore nothing gets rasterized (whatever undefined behavior happens). You should set the position of the vertices in the shader as follows:
//...
out gl_PerVertex {
vec4 gl_Position;
};
void main()
{
int dataIx = gl_VertexID / 4;
int vertexIx = gl_VertexID % 4;
vec2 vertexPosition = vec2(vertices[dataIx].px[vertexIx], vertices[dataIx].py[vertexIx]);
gl_Position = vec4(vertexPosition, 0, 1);
}
You can get rid of "Assign vertexPosition index", and your VAO doesn't need to have any attributes.

Segmentation Fault: 11 On DrawElementsCall

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.

opengl crashes when trying to apply textures

I'm trying to apply textures to opengl program, but the program just crashes for some reason, can someone tell me what I did wrong? Trying to fix this problem for two days now :/ works fine when color in fragment shader is set to some random color, but when color is:
vec4 textColor = texture(u_Texture, v_TextCoord);
color = textColor;
Edited:
#define GLEW_STATIC
#define alloca __builtin_alloca
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stb_image.h>
using namespace std;
static string ParseShader(const string& filepath);
static unsigned int CompileShader(unsigned int type, const string& source);
static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader);
void glCheckError();
float vertex[] =
{
0.5f, 0.5f, 0.0f,
1.0f, 1.0f, // 0
0.5f, -0.5f, 0.0f,
1.0f, 0.0f, // 1
-0.5f, -0.5f, 0.0f,
0.0f, 0.0f, // 2
-0.5f, 0.5f, 0.0f,
0.0f, 1.0f // 3
};
float vertexBack[] =
{
-0.6, -0.6f, -0.5f, // 0
0.6f, -0.6f, -0.5f, // 1
0.6f, 0.6f, -0.5f, // 2
-0.6f, 0.6f, -0.5f // 3
};
unsigned int indexes[] =
{
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
{
cout << "GLFW failed to load!" << endl;
return -1;
}
else
cout << "GLFW loaded" << endl << endl;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(800, 600, "Window", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK)
cout << "Error loading GLEW" << endl;
else
cout << "GLEW loaded - version: " << glGetString(GL_VERSION) << endl;
unsigned int shader = CreateShader(ParseShader("shaders/vertex.shader"), ParseShader("shaders/fragment.shader"));
glUseProgram(shader);
// Make vertex position array
unsigned int buffers;
glGenBuffers(1, &buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
// Make vertex position indexes out of arrays
unsigned int ib;
glGenBuffers(1, &ib);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexes), indexes, GL_STATIC_DRAW);
// Position layout
unsigned int posAttrib = glGetAttribLocation(shader, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
// Texture layout
unsigned int texAttrib = glGetAttribLocation(shader, "texCoord");
glEnableVertexAttribArray(texAttrib);
glCheckError();
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(3 * sizeof(float)));
// Load image
int h, w, v_bpp;
unsigned char *image = stbi_load("texture.png", &w, &h, &v_bpp, 4);
if(image == nullptr)
cout << "failed to load image!" << endl;
unsigned int texture_id;
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(image);
// Set slot
glActiveTexture(GL_TEXTURE0);
int location = glGetUniformLocation(shader, "u_Texture");
glUniform1i(location, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window) && glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS)
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glCheckError();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
static string ParseShader(const string& filepath) {
ifstream stream(filepath);
string line;
stringstream code;
while(getline(stream, line))
code << line << "\n";
return code.str();
}
static unsigned int CompileShader(unsigned int type, const string& source) {
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, NULL);
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 << "Failed to compile " << (type == GL_VERTEX_SHADER ? "Vertex" : "Fragment") << " shader!" << endl;
cout << message << endl;
glDeleteShader(id);
return 0;
}
return id;
}
static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader) {
unsigned int 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);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
void glCheckError() {
GLenum err = glGetError();
while(err!=GL_NO_ERROR) {
string error;
switch(err) {
case GL_INVALID_OPERATION: error="INVALID_OPERATION"; break;
case GL_INVALID_ENUM: error="INVALID_ENUM"; break;
case GL_INVALID_VALUE: error="INVALID_VALUE"; break;
case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break;
}
cerr << err << " (" << error.c_str() << ")" <<endl;
err=glGetError();
}
}
You totally screwed up your vertex attribute ponter setup:
// Position layout
unsigned int posAttrib = glGetAttribLocation(shader, "position");
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
First, you query for an attribute named position, but you never use that index, you instead use 0.
// Texture layout
unsigned int texAttrib = glGetAttribLocation(shader, "texCoord");
glEnableVertexAttribArray(1);
glCheckError();
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(3 * sizeof(float)));
Then, you query for texCoord, ignore it again, enable attribute array 1, and overwrite the attribute pointer for attribute 0.
THis means that attribute 1 has some undefined pointer value, and you have undefined behavior.
What most likely happens is that you are lucky when you not use the texture, because you only have one active attribute which happens to get location 0. And your GL implementation seems to ignore attribute arrays for non-active attributes, so it does not crash. When you have both attributes enables, chances are that they will be 0 and 1, and there is no way not to dereference that invalid pointer.

OpenGL, FreeGlut and Glew crash with glGenVertexArrays call

I have a program like below:
#include <iostream>
#include <fstream>
#include <sstream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
GLuint prog, verShader, fragShader;
GLint attrPos, attrNor;
GLint uniModelView, uniProjection, uniModelViewTransposeInverse;
glm::mat4 modelMatrix, viewMatrix, projectionMatrix, MV, MVP;
glm::mat3 MVI;
const string loadFile(string name)
{
ifstream in(name.c_str(), ios::in);
if (in.fail()) {
cout << "File: '" << name << "' could not exist!!" << endl;
return "";
}
stringstream data;
data << in.rdbuf();
in.close();
return data.str();
}
GLuint createShader(GLenum type, const string name)
{
GLint isCompileOk;
GLuint shader;
string shaderText, shaderType;
const char *shaderSource;
switch(type)
{
case GL_VERTEX_SHADER:
shaderType = "GL_VERTEX_SHADER";
break;
case GL_FRAGMENT_SHADER:
shaderType = "GL_FRAGMENT_SHADER";
break;
}
shaderText = loadFile(name);
shaderSource = shaderText.c_str();
shader = glCreateShader(type);
glShaderSource(shader, 1, &shaderSource, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompileOk);
if (isCompileOk == GL_FALSE) {
char *shaderErr;
int errLength, errRetrieve;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &errLength);
shaderErr = new char [errLength + 1];
glGetShaderInfoLog(shader, errLength, &errRetrieve, shaderErr);
cout << "Compile '" << shaderType << "' error:" << endl;
cout << shaderErr << endl;
delete [] shaderErr;
return 0;
} else {
cout << "Compile '" << shaderType << "' ok!" << endl;
}
return shader;
}
bool makeShader()
{
GLint isLinkOk;
verShader = createShader(GL_VERTEX_SHADER, "vert.glsl");
fragShader = createShader(GL_FRAGMENT_SHADER, "frag.glsl");
prog = glCreateProgram();
glAttachShader(prog, verShader);
glAttachShader(prog, fragShader);
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &isLinkOk);
if (isLinkOk == GL_FALSE) {
char *progErr;
int errLenght, errRetrieve;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &errLenght);
progErr = new char[errLenght + 1];
glGetProgramInfoLog(prog, errLenght, &errRetrieve, progErr);
cout << "Link program error:" << endl;
cout << progErr << endl;
delete [] progErr;
return false;
} else {
cout << "Link program Ok!" << endl;
}
attrPos = glGetAttribLocation(prog, "position");
uniModelView = glGetUniformLocation(prog, "ModelViewMatrix");
uniProjection = glGetUniformLocation(prog, "ProjectionMatrix");
uniModelViewTransposeInverse = glGetUniformLocation(prog, "ModelViewTransposeInverseMatrix");
return true;
}
float vertexs[] = {
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f
};
unsigned short indicates[] = {
0, 1, 2,
2, 3, 0
};
GLuint vao, vbo, ibo;
void display()
{
MV = viewMatrix * modelMatrix;
MVP = projectionMatrix * MV;
MVI = glm::transpose(glm::inverse(glm::mat3(MV)));
glUseProgram(prog);
glUniformMatrix4fv(uniModelView, 1, GL_FALSE, glm::value_ptr(MV));
glUniformMatrix3fv(uniModelViewTransposeInverse, 1, GL_FALSE, glm::value_ptr(MVI));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, sizeof(indicates)/sizeof(unsigned short), GL_UNSIGNED_SHORT, 0);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
projectionMatrix = glm::perspective(45.0f, float(w)/h, 0.1f, 1000.0f);
glUseProgram(prog);
glUniformMatrix4fv(uniProjection, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
}
void idle()
{
glutPostRedisplay();
}
void Init()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
modelMatrix = glm::mat4(1.0f);
viewMatrix = glm::lookAt(
glm::vec3(0.0f, 5.0f, 10.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f)
);
projectionMatrix = glm::mat4(1.0f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW);
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
glEnableVertexAttribArray(attrPos);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicates), indicates, GL_STATIC_DRAW);
glBindVertexArray(0);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("Rectangle!");
if (glewInit() != GLEW_OK) {
cout << "glewInit() fail!" << endl;
return -1;
}
if (!makeShader()) {
cout << "makeShader() error!!" << endl;
return -1;
}
Init();
reshape(WINDOW_WIDTH, WINDOW_HEIGHT);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}
when i adds VAO buffer, freeglut going to crash in glutMainLoop(), if i removes glGenVertexArrays call (of couse, removed what relatives to VAO too), it run ok, so my guess is problem in freeglut with glGenVertexArrays.
Question: What is my problem?
ps: My graphic cal support opengl 2.1, i use Visual Studio 2008.
Update: With VAO, above program work well but only crash when i close freeglut window.
Update shader: My shaders is very simple:
Vertex shader:
#version 120
attribute vec3 position;
// attribute vec3 normal;
uniform mat4 ModelViewMatrix;
uniform mat3 ModelViewTransposeInverseMatrix;
uniform mat4 ProjectionMatrix;
void main(void)
{
gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(position, 1.0);
}
Fragment shader:
#version 120
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
Your vertex data is tightly packed. Use a stride of 0 instead of sizeof(float) * 3.
My graphic cal support opengl 2.1
Also, VAOs only became core in 3.0. You should check for ARB_vertex_array_object support before using that functionality.