I've tried to display a simple triangle, but nothing appears on screen.
I can clear the color but, nothing else. (I've put averything in one big file).
I'm using SDL to create the window. Everything else should be just OpenGL.
Here is my code:
int main(){
// Init window
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_Window* window = SDL_CreateWindow("Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL);
SDL_GLContext context = SDL_GL_CreateContext(m_window);
GLenum status = glewInit();
if(status != GLEW_OK){
std::cerr << "Glew failed!" << std::endl;
}
isClosed = false;
// Init everything else
GLuint vaoID;
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
GLuint vboID;
glGenBuffers(1, &vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
GLfloat vert2[] = {-1,-1,0, 1,-1,0, 0,0,0};
glBufferData(GL_ARRAY_BUFFER, sizeof(vert2), vert2, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
GLuint frag = glCreateShader(GL_FRAGMENT_SHADER);
GLuint vert = glCreateShader(GL_VERTEX_SHADER);
std::string sFrag = "#version 130 \n out vec4 out_color; \n void main(void){out_color = vec4(1, 0, 1, 1);}";
std::string sVert = "#version 130 \n in vec3 pos; \n void main(void){gl_Position = vec4(pos, 1);}";
char const* cFrag = sFrag.c_str();
char const* cVert = sVert.c_str();
GLint success = 0;
glShaderSource(frag, 1, &cFrag, NULL);
glCompileShader(frag);
glGetShaderiv(frag, GL_COMPILE_STATUS, &success);
if(success == GL_FALSE) std::cerr << "Möb" << std::endl;
else std::cout << "YES" << std::endl;
glShaderSource(vert, 1, &cVert, NULL);
glCompileShader(vert);
glGetShaderiv(vert, GL_COMPILE_STATUS, &success);
if(success == GL_FALSE) std::cerr << "Möb" << std::endl;
else std::cout << "YES" << std::endl;
GLuint program = glCreateProgram();
glAttachShader(program, vert);
glAttachShader(program, frag);
glBindAttribLocation(program, 0, "pos");
glDeleteShader(vert);
glDeleteShader(frag);
glLinkProgram(program);
//glValidateProgram(program);
while(!isClosed){
glUseProgram(program);
glBindVertexArray(vaoID);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
glUseProgram(0);
// Update
SDL_GL_SwapWindow(window);
SDL_Event e;
while(SDL_PollEvent(&e)){
if(e.type == SDL_QUIT){
isClosed = true;
}
}
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
return 0;
}
You are calling glClear() before display.update(), which seems to suggest you are clearing the back buffer before swapping it. Granted the other code is correct, if you swap the position of glClear() and display.update(), you may see something.
Related
After several tests I still don't see my red triangle, what am I doing wrong? It's funny because it is not the first time for me to work with OpenGL, and I am pretty sure I am not missing any setup step. Here is a code snippet:
GLFWwindow* window;
glfwSetErrorCallback(onError);
if ( !glfwInit() ) {
std::cout << "glfwInit() failed." << std::endl;
return;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow( GetWindowWidth(), GetWindowHeight(), "The Game", NULL, NULL );
if ( !window )
{
std::cout << "couldn't create a proper window, exiting." << std::endl;
glfwTerminate();
return;
}
glfwSetKeyCallback( window, handleKeysEvents );
glfwMakeContextCurrent( window );
gladLoadGL(); // no glfwGetProcAddress required
glfwSwapInterval(1);
/// init opengl things ...
GLuint VAO, VBO, program;
GLuint VertexShader, FragmentShader;
VertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(VertexShader, 1, &vertex_shader_text, NULL);
glCompileShader(VertexShader);
GLint isCompiled = 0;
glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(VertexShader, GL_INFO_LOG_LENGTH, &maxLength);
std::cout << "ERROR IN COMPILING VERTEX SHADER." << std::endl;
// The maxLength includes the NULL character
std::vector<GLchar> errorLog(maxLength);
glGetShaderInfoLog(VertexShader, maxLength, &maxLength, &errorLog[0]);
for ( int i = 0; i < errorLog.size(); ++i )
std::cout << errorLog[i];
glDeleteShader(VertexShader); // Don't leak the shader.
return;
}
FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(FragmentShader, 1, &fragment_shader_text, NULL);
glCompileShader(FragmentShader);
isCompiled = 0;
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(FragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
std::cout << "ERROR IN COMPILING VERTEX SHADER." << std::endl;
// The maxLength includes the NULL character
std::vector<GLchar> errorLog(maxLength);
glGetShaderInfoLog(FragmentShader, maxLength, &maxLength, &errorLog[0]);
for ( int i = 0; i < errorLog.size(); ++i )
std::cout << errorLog[i];
glDeleteShader(FragmentShader); // Don't leak the shader.
return;
}
program = glCreateProgram();
glAttachShader(program, VertexShader);
glAttachShader(program, FragmentShader);
glLinkProgram(program);
// Note the different functions here: glGetProgram* instead of glGetShader*.
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
if (isLinked == GL_FALSE)
{
std::cout << "ERROR IN LINKING PROGRAM." << std::endl;
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
// We don't need the program anymore.
glDeleteProgram(program);
// Don't leak shaders either.
glDeleteShader(VertexShader);
glDeleteShader(FragmentShader);
// Use the infoLog as you see fit.
for ( int i = 0; i < infoLog.size(); ++i )
std::cout << infoLog[i];
// In this simple program, we'll just leave
return;
}
glDeleteShader(VertexShader);
glDeleteShader(FragmentShader);
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_VERTEX_ARRAY, VBO);
glBufferData(GL_VERTEX_ARRAY, sizeof(vertices), reinterpret_cast<const void*>(vertices), GL_STATIC_DRAW);
glBindBuffer(GL_VERTEX_ARRAY, 0);
glBindBuffer(GL_VERTEX_ARRAY, VBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glBindBuffer(GL_VERTEX_ARRAY, 0);
glBindVertexArray(0);
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
while( !glfwWindowShouldClose(window) )
{
Float wWidth = GetWindowWidth();
Float wHeight = GetWindowHeight();
glViewport(0, 0, (GLsizei)wWidth, (GLsizei)wHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
std::cout << "closing the game." << std::endl;
return;
And here are the shaders:
Vertex Shader:
#version 460 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos, 1.0f);
}
And fragment shader:
#version 460 core
out vec4 FragCol;
void main()
{
FragCol = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
OpenGL context is created, in fact clearing the screen with a specific color works just fine. I just don't get to see my triangle on the screen, any suggestions?
GL_VERTEX_ARRAY is not a valid buffer type. GL_VERTEX_ARRAY is a client-side capability (fixed function attribute, legacy OpenGL). The buffer type for vertex attributes is GL_ARRAY_BUFFER:
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), reinterpret_cast<const void*>(vertices), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
I have encountered this question on stackoverflow but the code shown are mostly legacy. How do I draw a circle in modern OpenGL?
Here's my code,
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cmath>
#include <vector>
GLfloat pi() { return atan(1) * 4; }
int degToRad(float degree)
{
return (pi() / 180) * degree;
}
int main()
{
if (!glfwInit())
{
return -1;
}
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);
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
gladLoadGL();
// clang-format off
std::vector<GLfloat> vertices = {
};
GLfloat radius = 0.5;
for(int i = 0; i < 360; i++) {
GLfloat x = radius * cos(degToRad(i));
GLfloat y = radius * sin(degToRad(i));
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(0.0f);
}
unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STATIC_DRAW);
const char *vertexShaderSource =
"#version 410 core\n"
"precision mediump float;\n"
"layout (location = 0) in vec3 position;\n"
"void main() {\n"
" gl_Position = vec4(position, 1.0);\n"
"}";
const char *fragmentShaderSource =
"#version 410 core\n"
"precision mediump float;\n"
"out vec4 color;\n"
"void main() {\n"
" color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
"}";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
unsigned int vertexArray;
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
while (!glfwWindowShouldClose(window))
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glDrawArrays(GL_LINES, 0, vertices.size() / 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
It draws these lines,
I'm actually learning OpenGL3.3 to create a multiplatform application, which draws some sprites.
Currently, I'm struggling at the compilation of vertexShader and fragShader. The OpenGL shows me information, that my device doesn't support the 3.3 version. When It's clear that it supports it.
main.cpp
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <string>
#include <fstream>
#include <sstream>
#include <filesystem>
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f};
std::string readFile(const std::string &fileLoc)
{
std::ifstream file;
file.open(fileLoc, std::ios::in);
std::stringstream contex;
if (!file.fail())
{
contex << file.rdbuf();
}
return contex.str();
}
GLuint createandComplieShader(const std::string &fileLoc, GLuint shaderType)
{
GLuint shader = glCreateShader(shaderType);
std::string shaderString = readFile(fileLoc);
const char *ShaderSource = shaderString.c_str();
glShaderSource(shader, 1, &ShaderSource, nullptr);
glCompileShader(shader);
int success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
char infoLog[512];
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
std::cerr << "Shader Error :" << infoLog << std::endl;
exit(-1);
}
return shader;
}
GLuint createAndLinkShader()
{
std::string path = std::filesystem::current_path();
std::string VertexShader = "/vertShader.vert" ;
std::string FragmentShader = "/fragShader.vert";
GLuint vertexShader = createandComplieShader(path + VertexShader , GL_VERTEX_SHADER);
GLuint fragmentShader = createandComplieShader(path + FragmentShader , GL_FRAGMENT_SHADER);
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
int succes;
glGetProgramiv(program, GL_LINK_STATUS, &succes);
if (!succes)
{
char infoLog[512];
glGetProgramInfoLog(program, 512, nullptr, infoLog);
std::cerr << "Linking Error: " << infoLog << std::endl;
exit(-2);
}
return program;
}
int main(int argc, char **argv)
{
if (!glfwInit())
{
std::cerr << "GLFW init failed..." << std::endl;
return -1;
}
GLFWwindow *window = glfwCreateWindow(1280, 720, "A-Engine", nullptr, nullptr);
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, GLFW_TRUE);
if (window == nullptr)
{
std::cerr << "Window init failed..." << std::endl;
glfwTerminate();
return -2;
}
glfwMakeContextCurrent(window);
// glfwSetKeyCallback (window, HandleKeyInput);
if (glewInit() != GLEW_OK)
{
std::cerr << "Glew init failed..." << std::endl;
glfwDestroyWindow(window);
glfwTerminate();
return -3;
}
glClearColor(0.2f, 0.2f, 0.45f, 1.0f);
GLuint ShaderProgram = createAndLinkShader();
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
int width;
int height;
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glUseProgram(ShaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(ShaderProgram);
glfwDestroyWindow(window);
return EXIT_SUCCESS;
}
fragShader.vert
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
vertShader.vert
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
The main binary file is located under this same folder as vertShader and fragShader
Shader Error :ERROR: 0:1: '' : version '330' is not supported
ERROR: 0:1: '' : syntax error: #version
ERROR: 0:2: 'layout' : syntax error: syntax error
As per the comment, at the very least you should set the glfw window hints before creating the window. So the window creation code in main should probably be...
if (!glfwInit())
{
std::cerr << "GLFW init failed..." << std::endl;
return -1;
}
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, GLFW_TRUE);
GLFWwindow *window = glfwCreateWindow(1280, 720, "A-Engine", nullptr, nullptr);
.
.
.
Otherwise the OpenGL version associated with the newly created context can be anything (as far as I'm aware).
I am learning openGL in C++ and I got to the point where I could draw a triangle.
I decided to put the creation of the triangle into a class so that all the code wasn't just in one file and now when I execute the draw function nothing happens. I've been looking through this code for a while now I can't figure out why this happens.
The program dosen't crash it just draws a black background. Also OpenGL does not return any errors.
Here is my main function:
int main(int argc, char* args[]){
GLrenderer renderer;
setRendererSettings(&renderer);
renderer.init();
//triangle tri = createTriangle();
//compileShaders();
glslShader triangle("VertexShader.glsl", "FragShader.glsl");
std::vector<GLfloat> vertices = {
-1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f
};
triangle.createShape(vertices);
triangle.compileShaders();
while(renderer.shouldRun()){
input(&renderer);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
triangle.draw();
renderer.swapBuffers();
}
renderer.destroy();
return 0;
}
Here is my GLrenderer header
class GLrenderer {
private:
SDL_Window* window;
SDL_GLContext GLcontext;
bool isRunning = false;
bool initSDL();
bool initGL();
public:
GLrenderer();
int width = 1, height = 1;
int winX = 0, winY = 0;
int versionMajor = 3, versionMinor = 3;
const char* title = "OpenGL window";
Uint32 flags = SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN;
bool init();
bool shouldRun();
void setShouldRun(bool value);
void destroy();
void swapBuffers();
SDL_Window* getWindow();
};
The source for GLrenderer
GLrenderer::GLrenderer() {}
bool GLrenderer::init(){
if(!initSDL()) return false;
if(!initGL()) return false;
isRunning = true;
return true;
}
bool GLrenderer::initSDL(){
if(SDL_Init(SDL_INIT_EVERYTHING) < 0){
printf("Failed to init SDL.\n");
return false;
}
window = SDL_CreateWindow(
title,
winX, winY,
width, height,
flags
);
if(window == NULL){
printf("Failed to create SDL_Window.\n");
return false;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, versionMajor);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, versionMinor);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
GLcontext = SDL_GL_CreateContext(window);
if(!GLcontext){
printf("Failed to create OpenGl context.\n");
return false;
}
SDL_GL_MakeCurrent(window, GLcontext);
return true;
}
bool GLrenderer::initGL(){
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK){
printf("Failed to init glew.\n");
return false;
}
return true;
}
bool GLrenderer::shouldRun(){
return isRunning;
}
void GLrenderer::setShouldRun(bool value){
isRunning = value;
}
void GLrenderer::destroy(){
SDL_DestroyWindow(window);
SDL_GL_DeleteContext(GLcontext);
SDL_Quit();
}
SDL_Window* GLrenderer::getWindow(){
return window;
}
void GLrenderer::swapBuffers(){
SDL_GL_SwapWindow(window);
}
Header for my class im using to create the triangle
class glslShader;
std::string readShader(std::string file);
class glslShader {
private:
GLuint ShaderProgram, VAO, VBO;
std::string vertexFile, fragFile;
public:
glslShader(std::string _vertexFile, std::string _fragFile);
void createShape(std::vector<GLfloat> vertices);
bool compileShaders();
void draw();
};
And finally the source for that header
bool fileExsists(std::string file){
std::fstream test(file);
return test.good();
}
std::string readShader(std::string file){
if(!fileExsists(file)){
printf("Not able to locate shader\n");
return "";
}
const int maxLine = 130;
std::string shader = "";
std::fstream shaderFile(file);
while(!shaderFile.eof()){
char line[maxLine];
shaderFile.getline(line, 130);
shader += line;
shader += "\n";
}
return shader;
}
glslShader::glslShader(std::string _vertexFile, std::string _fragFile) : vertexFile{_vertexFile}, fragFile{_fragFile} {}
void glslShader::createShape(std::vector<GLfloat> vertices){
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices.data()), vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
bool addShader(GLuint program, const char* shaderSRC, GLenum type){
GLuint shader = glCreateShader(type);
const GLchar* src[1];
src[0] = shaderSRC;
GLint size[1];
size[0] = strlen(shaderSRC);
glShaderSource(shader, 1, src, size);
GLint result = 0;
GLchar log[1024];
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
if(!result){
glGetShaderInfoLog(shader, 1024, NULL, log);
printf("ERROR: Failed to compile shader: &s\n", log);
return false;
}
glAttachShader(program, shader);
return true;
}
bool glslShader::compileShaders(){
ShaderProgram = glCreateProgram();
if (!ShaderProgram){
printf("ERROR: Failed to create shader program.\n");
return false;
}
if (!addShader(ShaderProgram, readShader("VertexShader.glsl").c_str(), GL_VERTEX_SHADER)){
printf("ERROR: failed to create vertex shader.\n");
return false;
}
if (!addShader(ShaderProgram, readShader("FragShader.glsl").c_str(), GL_FRAGMENT_SHADER)){
printf("ERROR: failed to create fragment shader.\n");
return false;
}
GLint result = 0;
GLchar log[1024];
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &result);
if(!result){
glGetProgramInfoLog(ShaderProgram, sizeof(log), NULL, log);
printf("ERROR: Failed to link program: %s", log);
return false;
}
glValidateProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &result);
if (!result){
glGetProgramInfoLog(ShaderProgram, sizeof(log), NULL, log);
printf("ERROR: Failed to validate program: %s\n", log);
return false;
}
return true;
}
void glslShader::draw(){
glUseProgram(ShaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glUseProgram(0);
}
I am certain its not my shader code because I am using the same shaders that I used to render my last triangle before I was using a class.
glBufferData(GL_ARRAY_BUFFER, sizeof(_verticies.data()), _verticies.data(), GL_STATIC_DRAW);
Should have been:
glBufferData(GL_ARRAY_BUFFER, _verticies.size() * sizeof(Glfloat), _verticies.data(), GL_STATIC_DRAW);
I am new to openGL and I've got a code like this learning from the tutorial
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow *window, int width, int height);
void processInput(GLFWwindow *window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
int main() {
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
GLFWwindow *window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr);
if (window == nullptr) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, 0.5f, 0.0f // top left
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// render loop
while (!glfwWindowShouldClose(window)) {
processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
vertices[0] += 0.1f;
vertices[1] += 0.1f;
vertices[2] += 0.1f;
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), &vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
void processInput(GLFWwindow *window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}
As you noticed in render loop I am trying to change the vertices value e.g. move my drawn triangle, while not creating a new VBO but updating its data...
I've read that glBuferSubData is for updating VBO's sub data without creating a new one, and I've done that like this
while (!glfwWindowShouldClose(window)) {
processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
vertices[0] += 0.1f;
vertices[1] += 0.1f;
vertices[2] += 0.1f;
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), &vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
I think I am doing something wrong as the triangle does not move... How can I solve this?
glBufferSubData updates a subset of a buffer object's data store of the buffer which is currently bound to the GL_ARRAY_BUFFER target. The array buffer binding is a global state. As soon as you call glBindBuffer(GL_ARRAY_BUFFER, 0); the binding of the VBO buffer is lost.
Either skip glBindBuffer(GL_ARRAY_BUFFER, 0); or bind the buffer just before calling glBufferSubData:
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), &vertices);