GLFW program doesn't draw triangle - c++

I am running a simple program to draw a red triangle.
However, it only shows a black window.
I suspect it might be a problem with the shader, because if I remove the shader, it perfectly draws a white triangle.
Here's my code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
static unsigned int CompileShader(unsigned int type, const std::string& source){
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int res;
glGetShaderiv(id, GL_COMPILE_STATUS, &res);
if(res == GL_FALSE){
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader!" << std::endl;
std::cout << message << std::endl;
glDeleteShader(id);
return 0;
}
return id;
}
static unsigned int CreateShader(const std::string& vertexShader, const std::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;
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 1 );
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "I Rock", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if(glewInit() != GLEW_OK)
std::cout<< "Error!" << std::endl;
float positions[6] = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6*sizeof(float), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), 0);
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vertexShader = GLSL
(
410 core,
layout( location = 0 ) in vec4 position;
void main()
{
gl_Position = position;
}
);
const char* fragmentShader = GLSL
(
410 core,
out vec4 color;
void main()
{
color = vec4( 1.0, 0.0, 0.0, 1.0 );
}
);
unsigned int shader = CreateShader(vertexShader, fragmentShader);
glUseProgram(shader);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glDeleteProgram(shader);
glfwTerminate();
return 0;
}
These are my specifications:
GLFW version : 3.2.1 Cocoa NSGL chdir menubar retina dynamic
GLEW_VERSION : 2.1.0
GL_VERSION : 4.1 ATI-1.60.26
GL_VENDOR : ATI Technologies Inc.
GL_RENDERER : AMD Radeon R9 M290 OpenGL Engine
GL_SHADING_LANGUAGE_VERSION : 4.10

You need to generate & bind a Vertex Array Object (VAO) before enabling vertex attributes, setting vertex attrib pointers, and drawing:
...
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6*sizeof(float), positions, GL_STATIC_DRAW);
// generate & bind VAO
GLuint vao = 0;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), 0);
...
VAOs aren't optional in Core contexts like they are in Compatibility.

Related

Unable to get trivial 2D shader to draw red triangle in C++ openGL (No compiler errors)

I used openGL, GLEW and GLFW3. In openGl 3.0 mesa, the default shader was used and a white triangle was drawn. In 4.2, the screen was left black. No error messages were generated.
The issue is not due to mislabeling of a fragment shader as a vertex shader or vice versa.
The program contains 3 functions:
(1) compileShader, which is supposed to take in shader type and source code as std::string and return a shader ID with compiled code.
(2) createProgram, takes in the source code of a vertex shader and a fragment shader and returns a program ID with the shaders compiled and attached.
(3) And main, where both shader source codes are defined as strings.
Sorry and Thank you.
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <string>
static unsigned int compileShader(unsigned int type, std::string const& sourceCode){
unsigned int shaderId = glCreateShader(type);
const char* source = sourceCode.c_str();
glShaderSource(shaderId, 1, &source, nullptr);
glCompileShader(shaderId);
int result;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE){
if (type == GL_FRAGMENT_SHADER) std::cout<<"Fragment\n";
else std::cout<<"Vertex";
std::cout<<"SHADER COMPILATION FAILED!"<<std::endl;
int logLength;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &logLength);
char* infoLog = new char[logLength];
glGetShaderInfoLog(shaderId, logLength, NULL, infoLog);
std::cout<<infoLog<<std::endl;
delete[] infoLog;
glDeleteShader(shaderId);
return 0;
}
return shaderId;
}
static unsigned int createProgram(std::string const& vertexCode, std::string const& fragmentCode){
unsigned int vsId = compileShader(GL_VERTEX_SHADER, vertexCode);
unsigned int fsId = compileShader(GL_FRAGMENT_SHADER, fragmentCode);
unsigned int programId = glCreateProgram();
glAttachShader(programId, vsId);
glAttachShader(programId, fsId);
glLinkProgram(programId);
glValidateProgram(programId);
glDeleteShader(vsId);
glDeleteShader(fsId);
return programId;
}
int main()
{
GLFWwindow* window;
if (!glfwInit())
{
std::cout<<"GLFW initialization failed";
return -1;
}
///switches to opengl 4.2!
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* 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);
glewInit();
std::cout << "OpenGL " << glGetString(GL_VERSION) << "\n" << std::endl;
float positions[6] = {
0.5f, 0.5f,
-0.5f, 0.5f,
0.0f, 0.0f
};
unsigned int buffer = 1;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); //enables the xy attrib of position
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), 0); //specifies layout of xy attrib
std::string vertexSource = R"(
#version 330 core
layout(location=0) in vec4 position;
void main(){
gl_Position = position;
}
)";
std::string fragmentSource = R"(
#version 330 core
layout(location=0) out vec4 color;
void main(){
color = vec4(1.0, 0.0, 0.0, 1.0);
}
)";
unsigned int programId = createProgram(vertexSource, fragmentSource);
glUseProgram(programId);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
The issue is not the shader program, but you are using a core profile OpenGL Context (GLFW_OPENGL_CORE_PROFILE). Thus you have to create a named Vertex Array Object. The default VAO (0) is not valid in a core profile context.
Generate vertex array object name by glGenVertexArrays and create and bind the object by glBindVertexArray:
unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0); //enables the xy attrib of position
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), 0); //specifies layout of xy attrib

GLFW window only displaying Clear Color and nothing else

I have issue in that the window is displaying the clear color i.e. (Orange) I tried all answers on the web but they didn't seem to help me. I'm using GLFW 3.3 precompiled binaries. I'm using GLAD for OpenGL functions.
The code does not give any errors or warnings and also glGetError() returns 0 at all points of the code.
I've already tried changing the order and gDEBugger gives me error (that is, PRIV_INSTRUCTION) and the VAO and VBO tabs are empty.
Here's my code
#define GLFW_DLL
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
using namespace std;
static const char* vshSrc = "#version 330 core \n layout (location = 0) in vec3 tPos; void main(){gl_Position = tPos.x, tPos.y, tPos.z;} \0";
static const char* fshSrc = "#version 330 core \n layout (location = 0) out vec4 FragOut; void main(){FragOut = vec4(1.0f,0.4f,0.3f,1.0f);} \0";
/** Processes the input.
*Edit the fuction to add more features. */
void getInput( GLFWwindow *win ){
if(glfwGetKey(win,GLFW_KEY_ESCAPE) == GLFW_PRESS){
glfwSetWindowShouldClose(win,true);
}
}
int main( int argc, char **argv )
{
//Initialization
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
//Make compatible for MacOSX
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT,GL_TRUE);
#endif // __APPLE__
//Window creation
GLFWwindow* window = glfwCreateWindow(640,480,"Illuminati",NULL,NULL);
if (window == NULL)
{
cout << "Window creation failed" << endl;
return -1;
}
//GLAD
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
cout << "GLAD load error." << endl;
return -1;
}
//glViewport( 0, 0, 640, 480);
//==============================================================//
//Shader programs
//Vertex Shader
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vshSrc, NULL);
glCompileShader(vertexShader);
//Check for compile errors
int compilationSuccesful;
char InfoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compilationSuccesful);
if ( !compilationSuccesful ){
glGetShaderInfoLog(vertexShader, 512, NULL, InfoLog);
cout << "Vertex Shader compilation Failed. ERROR. \n \n" << InfoLog << endl;
}
//Fragment Shader
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fshSrc, NULL);
glCompileShader(fragmentShader);
//error checking for fragment shader
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compilationSuccesful);
if ( !compilationSuccesful ){
glGetShaderInfoLog(fragmentShader, 512, NULL, InfoLog);
cout << "Fragment Shader compilation Failed. ERROR. \n \n" << InfoLog << endl;
}
//Shader Program
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
//Shader attachments
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//Checking for link errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &compilationSuccesful);
if ( !compilationSuccesful ){
glGetProgramInfoLog(shaderProgram, 512, NULL, InfoLog);
cout << "The program refused to link. ERROR. \n \n" << InfoLog << endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//----------------------------------------------------------------------------------------------------------//
//Vertex data and elements
float rect[ ] {
/* 0 bottom left*/ -0.5f, -0.5f, 0.0f,
/* 1 top left*/ -0.5, 0.5f, 0.0f,
/* 2 bottom right*/ 0.5f, -0.5f, 0.0f,
/* 3 top right*/ 0.5f, 0.5f, 0.0f
};
unsigned int indices[] {
0,1,2, //first triangle
1,3,2 //second triangle
};
//==============================================================//
//Buffers and VAO
//VAO
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//VBO
unsigned int VBO;
glGenBuffers(1,&VBO);
//EBO
unsigned int EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(rect), rect, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//================================================================//
//Vertex Attributes
//glBindVertexArray(0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//for safety
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//A useless variable
//unsigned int ui;
//===============================================================//
//Render Loop
while ( !glfwWindowShouldClose(window) )
{
//Clear the buffer
glClearColor(0.9f,0.7f,0.2f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////DRAWING//////////////////////////////////////////
glBindVertexArray(VAO);
glUseProgram(shaderProgram);
//glDrawArrays(GL_TRIANGLES, 0, 4);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//////////////////////////////////////////////END/////////////////////////////////////////////
getInput(window);
glfwSwapBuffers(window);
glfwPollEvents();
}
//Exit and destructors
glfwTerminate();
return 0;
}
//End
/*
__
<( . )____
/_______/
~~~~~~~~~
~~~~~~~~~
*/
In your shader this expression will try to assign the value of tPos.z and only tPos.z to gl_Position
gl_Position = tPos.x, tPos.y, tPos.z;
The reason for that is the semantics of the Comma operator, where all expressions delimited by , are evaluated, but only the result of the very last one is used as the whole expression's R-value.
You probably just want to swizzle it, also you must assign .w:
gl_Position = vec4(tPos.xyz, 1);

printing a red triangle in openGL

I have the following code and am trying to print a red triangle using opengl glew ect. The program builds and shows a triangle, however it only shows a triangle when I drag the window, and the triangle shows up white not red. Not sure how to fix this issue. Below is a copy of my code (I am running in xcode).
#include <iostream>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
static unsigned int CompileShader(unsigned int type, const std::string& source)
{
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
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);
std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader" << std::endl;
std::cout << message << std::endl;
glDeleteShader(id);
return 0;
}
return id;
}
static unsigned int CreateShader(const std::string& vertexShader, const std::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;
}
int main(void)
{
GLFWwindow* window;
/* 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);
if (glewInit() != GLEW_OK)
std::cout << "Error!" << std::endl;
float positions[6] = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
std::string vertexShader =
"#version 330 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}\n";
std::string fragmentShader =
"#version 330 core\n"
"\n"
"layout(location = 0) out vec4 color;\n"
"\n"
"void main()\n"
"{\n"
" color = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
unsigned int shader = CreateShader(vertexShader, fragmentShader);
glUseProgram(shader);
glBindBuffer(GL_ARRAY_BUFFER, 0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glDeleteProgram(shader);
glfwTerminate();
return 0;
}
I am using xCode and am having 2 issues:
1. the triangle is printing out white
2. the triangle only shows up when i drag the window
I have tried debugging but am not able to figure these issues out.
You need to go whole-hog on Core contexts on macOS if you want anything past GL 2.1:
Request a versioned Core context via GLFW_OPENGL_PROFILE, GLFW_CONTEXT_VERSION_MAJOR, and GLFW_CONTEXT_VERSION_MINOR; it should meet or exceed the #version you're specifying in your shaders
For macOS in particular you need a forward-compatbile context; set GLFW_OPENGL_FORWARD_COMPAT to GL_TRUE
Core contexts require a vertex array object (VAO) to draw anything; for simple stuff you can get away with creating a single one and leaving it bound
All together:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <vector>
#include <iostream>
#include <cstdarg>
struct Program
{
static GLuint Load( const char* shader, ... )
{
GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
const GLenum type = va_arg( args, GLenum );
AttachShader( prog, type, shader );
shader = va_arg( args, const char* );
}
va_end( args );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
std::exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
const char* vert = 1 + R"GLSL(
#version 330 core
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
};
)GLSL";
const char* frag = 1 + R"GLSL(
#version 330 core
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1.0, 0.0, 0.0, 1.0);
}
)GLSL";
int main(void)
{
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
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(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
std::cout << "Error!" << std::endl;
GLuint vao = 0;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
float positions[6] =
{
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
GLuint shader = Program::Load( vert, GL_VERTEX_SHADER, frag, GL_FRAGMENT_SHADER, NULL );
glUseProgram(shader);
glBindBuffer(GL_ARRAY_BUFFER, 0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glDeleteProgram(shader);
glfwTerminate();
return 0;
}
Your problem may be in vertex shader because in vertex shader "layout(location = 0) in vec4 position;\n"
here you define vec4 but in you are sending vec2 from glVertexAttribPointer() function.
Try to send vec4 or try this in vertex shader
std::string vertexShader =
"#version 330 core\n"
"\n"
"layout(location = 0) in vec2 position;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position, 0, 1);\n"
"}\n";

OpenGL, a very basic shader not working

I am learning OpenGL through TheCherno Project.
The code below is from there and I faithfully reproduce it for my learning purpose. I have also added both vertex and fragment shaders as well.
My issue here is in my square output I don't see the color at all and I am guessing it is using the default shader.
int main(void)
{
GLFWwindow* window;
/* 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);
if (glewInit() != GLEW_OK)
std::cout << "ERROR GLEW" << std::endl;
std::cout << glGetString(GL_VERSION) << std::endl;
float positions[] = {
-0.5f,-0.5f, //0
0.5f, -0.5f, //1
0.5f, 0.5f, //2
-0.5f, 0.5f //3
};
unsigned int indices[] = {
0, 1, 2,
2, 3, 0
};
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * 2 * sizeof(float), positions, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
glEnableVertexAttribArray(0);
unsigned int ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
ShaderSourceProgram shader = ParseShader("res/shaders/Basic.shader");
//std::cout << "VERTEX" << std::endl;
//std::cout << shader.VertexShader << std::endl;
unsigned int shaderProgram = CreateShader(shader.VertexShader, shader.FragmentShader);
glUseProgram(shaderProgram);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
The shaders:
#shader vertex
#version 330 core
layout(location = 0)in vec4 position;
void main()
{
gl_Position = position;
};
#shader fragment
#version 330 core
out vec4 color;
void main()
{
color = vec4(0.0,1.0,0.0,1.0);
};
EDIT: Please click here for the entire project (github)
As #Ripi2 pointed out your glBufferData() calls, while not exactly wrong (they overrequest buffer space), aren't exactly correct either. Since you're using raw arrays you can use a straight sizeof(<arrayname>) for the size parameter:
glBufferData( GL_ARRAY_BUFFER, sizeof( positions ), positions, GL_STATIC_DRAW );
...
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW );
I suspect your (unknown) shader loader might be wonky since my personal one worked fine.
All together:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <iostream>
#include <cstdarg>
struct Program
{
static GLuint Load( const char* shader, ... )
{
GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
const GLenum type = va_arg( args, GLenum );
AttachShader( prog, type, shader );
shader = va_arg( args, const char* );
}
va_end( args );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
int main( void )
{
GLFWwindow* window;
/* 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 );
if( glewInit() != GLEW_OK )
std::cout << "ERROR GLEW" << std::endl;
std::cout << glGetString( GL_VERSION ) << std::endl;
float positions[] = {
-0.5f,-0.5f, //0
0.5f, -0.5f, //1
0.5f, 0.5f, //2
-0.5f, 0.5f //3
};
unsigned int indices[] = {
0, 1, 2,
2, 3, 0
};
unsigned int buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER, 6 * 2 * sizeof( float ), positions, GL_STATIC_DRAW );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof( float ) * 2, 0 );
glEnableVertexAttribArray( 0 );
unsigned int ibo;
glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof( unsigned int ), indices, GL_STATIC_DRAW );
const char* vert = GLSL
(
330 core,
layout(location = 0)in vec4 position;
void main()
{
gl_Position = position;
};
);
const char* frag = GLSL
(
330 core,
out vec4 color;
void main()
{
color = vec4(0.0,1.0,0.0,1.0);
};
);
unsigned int shaderProgram = Program::Load
(
vert, GL_VERTEX_SHADER,
frag, GL_FRAGMENT_SHADER,
NULL
);
glUseProgram( shaderProgram );
/* Loop until the user closes the window */
while( !glfwWindowShouldClose( window ) )
{
/* Render here */
glClear( GL_COLOR_BUFFER_BIT );
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr );
/* Swap front and back buffers */
glfwSwapBuffers( window );
/* Poll for and process events */
glfwPollEvents();
}
glDeleteProgram( shaderProgram );
glfwTerminate();
return 0;
}
glUseProgram() needs to be called after shaders are compiled and linked. Here's a piece of a sample code:
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
if (window == NULL)
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
cout << "Failed to initialize GLAD" << endl;
return -1;
}
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, 800, 600);
float TriangleVertices[] = {
-0.3f, -0.3f, 0.0f,
0.0f, 0.3f, 0.0f,
0.3f, -0.3f, 0.0f
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
//BindVertexArray for modifying it
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(TriangleVertices), TriangleVertices, GL_STATIC_DRAW);
glBindVertexArray(VAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
const char* vertexShaderSource = "\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos, 1.0);\n"
"}\0";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
const char* fragmentShaderSource = "\n"
"out vec4 FragColor; \n"
"void main()\n"
"{\n"
"FragColor = vec4(1.0f, 0.7f, 0.5f, 1.0f); \n"
"} \n";
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//// draw triangle using the data from the VAO
//glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}

OpenGL doesn't seem to be reading my vertices/indices

I've been following this tutorial in a bid to learn OpenGL. I have something that works, but only if I use global variables:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
// float vertices[] = {
// -0.5f, -0.5f, 0.0f,
// 0.5f, -0.5f, 0.0f,
// 0.0f, 0.5f, 0.0f
// };
float rectVertices[] = {
0.5f, 0.5f, 0.0f, // Top Right
0.5f, -0.5f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f // Top Left
};
uint rectIndices[] = {
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main() {\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\n";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main() {\n"
"color = vec4(1.0, 0.5, 0.2, 1.0);\n"
"}\n";
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void finalize() {
glfwTerminate();
}
void programExit(int code) {
finalize();
exit(code);
}
void enforce(int success, const char* msg, const char* info) {
if (!success) {
std::cerr << msg << info << std::endl;
exit(-1);
}
}
// Initialise
// GLFW and OpenGL
void initialiseGLFW(int vMajor, int vMinor) {
// Initialising GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, vMajor);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, vMinor);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
}
// Window Creation
GLFWwindow* createWindow(int width, int height, const char* title) {
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
enforce(window != nullptr, "Failed to create GLFW window", nullptr);
return window;
}
void initialiseGLEW(bool experimental) {
glewExperimental = experimental;
enforce(glewInit() == GLEW_OK, "Failed to initialise GLEW", nullptr);
}
GLFWwindow* initialise(int width, int height, const char* title) {
initialiseGLFW(3, 3);
// Creating GLFW Window
GLFWwindow* window = createWindow(width, height, title);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
// Initialising GLEW
initialiseGLEW(true);
glViewport(0, 0, 800, 600);
return window;
}
// Creating Shaders
void checkCompilationError(uint shader) {
int success;
char infoLog[512];
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
enforce(success, "Shader compilation error: ", infoLog);
}
void checkLinkingError(uint program) {
int success;
char infoLog[512];
glGetProgramiv(program, GL_LINK_STATUS, &success);
glGetProgramInfoLog(program, 512, nullptr, infoLog);
enforce(success, "Program linking error: ", infoLog);
}
uint compileShader(GLenum type, const char* source, ushort count, int* lengths) {
uint shader = glCreateShader(type);
glShaderSource(shader, count, &source, lengths);
glCompileShader(shader);
checkCompilationError(shader);
return shader;
}
uint createProgram(uint vShader, uint fShader) {
uint program = glCreateProgram();
glAttachShader(program, vShader);
glAttachShader(program, fShader);
glLinkProgram(program);
checkLinkingError(program);
return program;
}
// Subprocedure specific to this program
uint initialiseShaders(const char* vsSource, const char* fsSource) {
// Initialising shaders
uint vShader = compileShader(GL_VERTEX_SHADER, vsSource, 1, nullptr);
uint fShader = compileShader(GL_FRAGMENT_SHADER, fsSource, 1, nullptr);
// Link program
GLuint shaderProgram = createProgram(vShader, fShader);
// clean up
glDeleteShader(vShader);
glDeleteShader(fShader);
return shaderProgram;
}
void configureVBO(float* vertices) {
for (int i = 0; i < 12; i++) std::cout << vertices[i] << std::endl;
glBufferData(
GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW
);
// Tell OpenGL how to interpret the vertices
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*) 0);
glEnableVertexAttribArray(0);
}
void configureEBO(uint* indices) {
for (int i = 0; i < 6; i++) std::cout << indices[i] << std::endl;
glBufferData(
GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW
);
}
uint intialiseVAO(float* vertices, uint* indices) {
uint VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
configureVBO(vertices);
if (indices != nullptr) {
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
configureEBO(indices);
}
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return VAO;
}
void execGameLoop(GLFWwindow* window, uint shaderProgram, uint VAO) {
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Set the program to be used
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
}
int main() {
// Config
int width = 800, height = 800;
const char* title = "Learn OpenGL";
// Initialise GLFW and GLEW
GLFWwindow* window = initialise(width, height, title);
// Initialise Shader program
uint shaderProgram = initialiseShaders(vertexShaderSource, fragmentShaderSource);
// Configuring VAO, VBO and EBO
uint VAO = intialiseVAO(rectVertices, rectIndices);
execGameLoop(window, shaderProgram, VAO);
finalize();
return 0;
}
My problem is specifically to do with:
void configureVBO(float* vertices) {
for (int i = 0; i < 12; i++) std::cout << vertices[i] << std::endl;
glBufferData(
GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW
);
// Tell OpenGL how to interpret the vertices
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*) 0);
glEnableVertexAttribArray(0);
}
void configureEBO(uint* indices) {
for (int i = 0; i < 6; i++) std::cout << indices[i] << std::endl;
glBufferData(
GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW
);
}
which works as expected when using the rectVertices/Indices global variables, but don't work when they're passed as parameters. The for-loops in each method prints the array, and they contain the values I expect them to. Why does OpenGL draw the rectangle when I use the global variables, but not when I use local parameters?
void configureVBO(float* vertices) {
for (int i = 0; i < 12; i++) std::cout << vertices[i] << std::endl;
glBufferData(
GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW
);
// Tell OpenGL how to interpret the vertices
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*) 0);
glEnableVertexAttribArray(0);
}
The problem here is that sizeof(vertices) is not doing what you think it does. It doesn't tell you how many vertices are in the array -- rather, it's telling you how many bytes a variable of type vertices occupies. Since vertices is a pointer, that number is likely to be either 4 or 8 depending on your system -- but importantly, it has nothing to do with how many vertices you're actually intending to upload.
Instead, what you need to do is tell OpenGL how big you want the buffer to be, in bytes. You calculate that by number of vertices * sizeof(vertex_type). So in your case that would be 12 * sizeof(float).
In general, you'll either need to include a second parameter to the function which includes the number of vertices, or use a std::vector<float> to hold your vertex data instead. For example, with a vector this would become:
void configureVBO(const std::vector<float>& vertices) {
for (auto v : vertices) std::cout << v << "\n";
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float),
vertices.data(), GL_STATIC_DRAW);
// etc...
}
The reason the code worked when you used a global variable is to do with the way C++ passes arrays to functions (which in turn, it inherited from C). When you pass an array, what the function receives is just a pointer to the start of the array -- the information about the length of the array has been lost, so sizeof(vertices) can't tell you how long the array actually is. However, if you use a global variable, then the compiler can see the definition float vertices[12] even within the configureVBO function, so in that case sizeof() will do what you expect.
This is a very common mix-up for people getting started with C and C++. I'd really recommend using std::vector instead (for many reasons, of which this is just one), but it's also worth reading up on how arrays and pointers work in C and C++.