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 5 years ago.
Improve this question
I'm trying to write a modern OpenGL application from scratch and I can't get a basic Triangle to render. This is odd because I've managed this in some older code and I cant find a difference in how I've done everything.
I'm using shaders, and as far as I can tell they're compiled and linked properly.
I'm using GLFW and gl3w.
All I get from this code is my window with the clear color on it.
I'll Dump my code
Main.cpp
#include <GL/gl3w.h>
#include "Display/Display.h"
#include "Shader/Shader.h"
#include "Mesh/Mesh.h"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_TITLE "CompSci Coursework"
int main() {
//Create Display and Context
Display display( WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE );
//Create Basic Shaders
Shader basicShader( "BasicShader" );
basicShader.useShader();
//Create VAO
GLuint VAO;
glGenVertexArrays( 1, &VAO );
glBindVertexArray( VAO );
std::vector<float> verticies = {
-0.5f, -0.5f,
0.5f, -0.5f,
0.0f, 0.5f
};
//Create Mesh
Mesh triangle( verticies );
//While Open Loop
while ( !display.CheckShouldClose()) {
//Clear Buffer
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//Draw Triangle
glDrawArrays( GL_TRIANGLES, 0, 3 );
//Update Display
display.Update();
}
return 0;
}
Display.cpp
#include <iostream>
#include <GL/gl3w.h>
#include "Display.h"
Display::Display( int width, int height, const char* title ) {
//Init GLFW
if ( glfwInit() == 0 ) {
std::cerr << "Could not initialise GLFW\n";
return;
} else {
std::cout << "GLFW initialised\n";
}
//Window Hints
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 2 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
glfwWindowHint( GLFW_RESIZABLE, GL_FALSE );
//Create Window
m_window = glfwCreateWindow( width, height, title, NULL, NULL );
//Make Context
glfwMakeContextCurrent( m_window );
//Initialise GL3W
if ( gl3wInit() != 0 ) {
std::cerr << "Could not init GL3W\n";
return;
} else {
std::cout << "Initialised GL3W\n";
}
}
Display::~Display() {
//Delete Context
glfwMakeContextCurrent( 0 );
//Destroy Window
glfwDestroyWindow( m_window );
//Terminate GLFW
glfwTerminate();
}
bool Display::CheckShouldClose() {
return (bool)glfwWindowShouldClose( m_window );
}
void Display::Update() {
//Swap Buffers
glfwSwapBuffers( m_window );
//Poll Events
glfwPollEvents();
}
Mesh.cpp
#include <GL/gl3w.h>
#include <iostream>
#include "Mesh.h"
Mesh::Mesh( std::vector<float> verticies ) {
m_verticies = verticies;
//Generate VBO
glGenBuffers( 1, &m_vbo );
//Bind VBO
glBindBuffer( GL_ARRAY_BUFFER, m_vbo );;
//Pass Buffer Data
glBufferData( GL_ARRAY_BUFFER, m_verticies.size() * sizeof( float), &m_verticies[0], GL_STATIC_DRAW );
}
Mesh::~Mesh() {
glDeleteBuffers( 1, &m_vbo );
}
Shader.cpp
#include <fstream>
#include <iostream>
#include <vector>
#include <GL/gl3w.h>
#include "Shader.h"
#define SHADER_LIST { VERTEX_SHADER, FRAGMENT_SHADER }
Shader::Shader( std::string shaderName ) {
//Load Source Code
std::vector<std::string> shaderSources;
shaderSources.push_back( loadShaderSource( shaderName + ".vert" ));
shaderSources.push_back( loadShaderSource( shaderName + ".frag" ));
//Cast into C-Style Strings
const char* shaderSourcesCString[NUM_SHADER];
for ( int i : SHADER_LIST ) {
shaderSourcesCString[ i ] = shaderSources[ i ].c_str();
}
//Create Shaders
m_shaders[ VERTEX_SHADER ] = glCreateShader( GL_VERTEX_SHADER );
m_shaders[ FRAGMENT_SHADER ] = glCreateShader( GL_FRAGMENT_SHADER );
//Source Shaders
glShaderSource( m_shaders[ VERTEX_SHADER ], 1, &shaderSourcesCString[ VERTEX_SHADER ], NULL );
glShaderSource( m_shaders[ FRAGMENT_SHADER ], 1, &shaderSourcesCString[ FRAGMENT_SHADER ], NULL );
//Compile Shaders
for ( int i : SHADER_LIST ) {
glCompileShader( m_shaders[ i ] );
GLint status;
glGetShaderiv( m_shaders[ i ], GL_COMPILE_STATUS, &status );
if ( status != GL_TRUE ) {
char buffer[512];
glGetShaderInfoLog( m_shaders[ i ], 512, NULL, buffer );
std::cerr << "Shader Compilation Error on shader " << i << ": " << buffer << "\n";
return;
}
}
//Create Program
m_program = glCreateProgram();
//Attach Shaders
for ( int i : SHADER_LIST ) {
glAttachShader( m_program, m_shaders[ i ] );
}
//Link Shader
glLinkProgram( m_program );
//Find Link Error
{
GLint status;
glGetProgramiv(m_program, GL_LINK_STATUS, &status);
if (status != GL_TRUE){
std::cerr << "Unable to link shaders\n";
char buffer[512];
glGetProgramInfoLog(m_program, 512, NULL, buffer);
std::cerr << buffer;
return;
}
}
//Bind outColor
glBindFragDataLocation(m_program, 0, "outColor");
//Attributes
GLint posAttrib = glGetAttribLocation(m_program, "position");
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(posAttrib);
std::cout << "Shaders Compiled Successfully\n";
}
Shader::~Shader() {
for ( int i : SHADER_LIST ) {
//Detach Shader
glDetachShader( m_program, m_shaders[ i ] );
//Delete Shader
glDeleteShader( m_shaders[ i ] );
}
//Delete Program
glDeleteProgram( m_program );
}
std::string Shader::loadShaderSource( std::string filename ) {
//Locals
std::string output, line;
//Open File
std::fstream file;
file.open( "Shaders/" + filename );
//Check for error loading file
if ( file.bad()) {
std::cerr << "Could not load shader file: " << filename << "\n";
return NULL;
} else {
std::cout << "Loaded shader file: " << filename << "\n";
}
//Read file into locals
while ( file.good()) {
getline( file, line );
if ( line != "" )
output += line + "\n";
}
//Return C-String
return output;
}
void Shader::useShader() {
glUseProgram( m_program );
}
GLuint Shader::getProgram() {
return m_program;
}
These Are my shaders
Vertex Shader
#version 150 core
in vec2 position;
void main(){
gl_Position = vec4(position, 0.0, 1.0);
}
Fragment Shader
#version 150 core
out vec4 outColor;
void main(){
outColor = vec4(1.0, 1.0, 1.0, 1.0);
}
First you have to create the vertex array buffer:
std::vector< GLfloat > verticies;
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (GLsizeiptr)verticies.size(), verticies.data(), GL_STATIC_DRAW);
Once your shader program is linked you have to determine the index of the vertex attribute(s):
GLuint prog = ...;
GLint posAttrLoc = glGetAttribLocation(prog, "position");
Before drawing, you have to bind and enable the vertex attribute(s):
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(posAttrLoc );
glVertexAttribPointer(posAttrLoc , 2, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays( GL_TRIANGLES, 0, 3 );
Related
I'm having classes of computer graphics on OpenGL. There we study and work with Visual Studio 2015 while I run Linux on my laptop. So there some differences between composing a program in our classes and in lessons I found on Wikibooks. I tried to run one tutorial code from there and everything was fine, while I couldn't run my code I wrote at my lesson.
So I tried manipulating with my and tutorial code. I succeeded a few. The program runs but not shows my figures. So it actually must show a chesstable. But, for my regret, it shows a background color only. What may be wrong with that?
The first part on onDisplay() is not displayed. The commented part is from tutorial which works and shows a triangle.
Full code:
#include <stdio.h>
#include <stdlib.h>
/* Use glew.h instead of gl.h to get all the GL prototypes declared */
#include <GL/glew.h>
/* Using the GLUT library for the base windowing setup */
#include <GL/freeglut.h>
GLuint program;
GLint attribute_coord2d;
int init_resources()
{
GLint compile_ok = GL_FALSE, link_ok = GL_FALSE;
GLuint vs = glCreateShader( GL_VERTEX_SHADER );
const char *vs_source =
#ifdef GL_ES_VERSION_2_0
"#version 100\n" // OpenGL ES 2.0
#else
"#version 120\n" // OpenGL 2.1
#endif
"attribute vec2 coord2d; "
"void main(void) { "
" gl_Position = vec4(coord2d, 0.0, 1.0); "
"}";
glShaderSource( vs, 1, &vs_source, NULL );
glCompileShader( vs );
glGetShaderiv( vs, GL_COMPILE_STATUS, &compile_ok );
if( !compile_ok )
{
fprintf( stderr, "Error in vertex shader\n" );
return 0;
}
GLuint fs = glCreateShader( GL_FRAGMENT_SHADER );
const char *fs_source =
#ifdef GL_ES_VERSION_2_0
"#version 100\n" // OpenGL ES 2.0
#else
"#version 120\n" // OpenGL 2.1
#endif
"void main(void) { "
" gl_FragColor[0] = 0.0; "
" gl_FragColor[1] = 0.0; "
" gl_FragColor[2] = 1.0; "
"}";
glShaderSource( fs, 1, &fs_source, NULL );
glCompileShader( fs );
glGetShaderiv( fs, GL_COMPILE_STATUS, &compile_ok );
if( !compile_ok )
{
fprintf( stderr, "Error in fragment shader\n" );
return 0;
}
program = glCreateProgram();
glAttachShader( program, vs );
glAttachShader( program, fs );
glLinkProgram( program );
glGetProgramiv( program, GL_LINK_STATUS, &link_ok );
if( !link_ok )
{
fprintf( stderr, "glLinkProgram:" );
return 0;
}
const char* attribute_name = "coord2d";
attribute_coord2d = glGetAttribLocation( program, attribute_name );
if( attribute_coord2d == -1 )
{
fprintf( stderr, "Could not bind attribute %s\n", attribute_name );
return 0;
}
return 1;
}
void chess( double x, double y, double w, double h, int k )
{
glColor3f( 0.6, 0.6, 0.6 );
glRecti( 20, 20, 480, 480 );
for( int i = 0; i < 8; i++ )
{
glRasterPos2i( ( i + 1 )*x + 20, 30 );
glutBitmapCharacter( GLUT_BITMAP_9_BY_15, 'A' + i );
}
for( int j = 0; j < 8; j++ )
{
for( int i = 0; i < 8; i++ )
{
if( k % 2 == 0 )
{
glColor3f( 1, 1, 1 );
}
else glColor3f( 0, 0, 0 );
glRecti( x + w*i, y + h*j, 2 * x + w*i, 2 * y + h*j );
k++;
}
k++;
}
}
void onDisplay()
{
glClearColor( 0.5, 1.0, 1.0, 1.0 );
glClear( GL_COLOR_BUFFER_BIT );
glUseProgram( program );
glEnableVertexAttribArray( attribute_coord2d );
double x, y, w, h;
int k;
x = 50;
y = 50;
h = 50;
w = 50;
k = 1;
chess( x, y, w, h, k );
glFlush();
/*
GLfloat triangle_vertices[] = {
0.0, 0.8,
-0.8, -0.8,
0.8, -0.8,
};
// Describe our vertices array to OpenGL (it can't guess its format automatically)
glVertexAttribPointer(
attribute_coord2d, // attribute
2, // number of elements per vertex, here (x,y)
GL_FLOAT, // the type of each element
GL_FALSE, // take our values as-is
0, // no extra data between each position
triangle_vertices // pointer to the C array
);
// Push each element in buffer_vertices to the vertex shader
glDrawArrays(GL_TRIANGLES, 0, 3);
*/
glDisableVertexAttribArray( attribute_coord2d );
glutSwapBuffers();
}
void free_resources()
{
glDeleteProgram( program );
}
int main( int argc, char* argv[] )
{
glutInit( &argc, argv );
glutInitContextVersion( 2, 0 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 640, 640 );
glutCreateWindow( "chesstable" );
GLenum glew_status = glewInit();
if( glew_status != GLEW_OK )
{
fprintf( stderr, "Error: %s\n", glewGetErrorString( glew_status ) );
return 1;
}
if( init_resources() )
{
glutDisplayFunc( onDisplay );
glutMainLoop();
}
free_resources();
return 0;
}
Well, as in the title the Shaders aren't doing a thing they should draw a point but it isn't appearing in the screen :/. I have being checking for solutions but it appears that they don't work. Also glfw and glew are initialising okay and the red color is appearing.
#include <GL/glew.h>
#define GLFW_DLL
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <iostream>
#include "jelly/lua_manager.h"
#include "jelly/keysManager.h"
jelly::keys_buttons::KeysManager km;
GLuint vertex_array_obj;
GLuint program;
GLuint startRender(GLFWwindow* window)
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
std::cout << "ASD" << std::endl;
static const GLchar * vertexShader_src[] =
{
"#version 430 core \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_Position = vec4(0, 0.5, 0.0, 1); \n"
"} \n"
};
static const GLchar * fragmentShader_src[] =
{
"#version 430 core \n"
" \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.0, 0.8, 1.0, 1.0); \n"
"} \n"
};
glShaderSource(vertexShader, 1, vertexShader_src, NULL);
glCompileShader(vertexShader);
glShaderSource(fragmentShader, 1, fragmentShader_src, NULL);
glCompileShader(fragmentShader);
GLuint tprogram = glCreateProgram();
glAttachShader(tprogram, vertexShader);
glAttachShader(tprogram, fragmentShader);
glLinkProgram(tprogram);
glValidateProgram(tprogram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glGenVertexArrays(1, &vertex_array_obj);
glBindVertexArray(vertex_array_obj);
return tprogram;
}
void render(GLFWwindow* window)
{
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_POINTS, 0, 1);
}
void mouseCallback(GLFWwindow* window, int button, int action, int mods)
{
km.mouseClick(button, action, mods);
}
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
km.keyPressed(key, action, mods);
}
int main()
{
jelly::lua::LuaManager lm;
// 0 = Build | 1 = Release | 2 = Alpha | 3 = Beta
int buildType = 0;
std::string title = "Relieved";
if (buildType != 1)
{
switch (buildType) {
case 0 :
title += " | Build Version";
break;
case 2 :
title += " | Alpha Version";
break;
case 3 :
title += " | Beta Version";
break;
default :
break;
}
}
GLFWwindow* window;
if (!glfwInit()) {
glfwTerminate();
return -1;
}
window = glfwCreateWindow(640, 400, title.c_str(), NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
glLoadIdentity();
program = startRender(window);
glUseProgram(program);
glfwSetKeyCallback(window, keyCallback);
glfwSetMouseButtonCallback(window, mouseCallback);
while(!glfwWindowShouldClose(window))
{
render(window);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &vertex_array_obj);
glDeleteProgram(program);
glDeleteVertexArrays(1, &vertex_array_obj);
glfwTerminate();
return 0;
}
You are creating your vertexarray
glGenVertexArrays(1, &vertex_array_obj);
glBindVertexArray(vertex_array_obj);
but there is not data in it. You need to add some data so that the shaders are fired (even if the value is hardcoded in the vertex shader, as it is your case)
So, add some vertices to your vertex array like this:
std::vector<float> v({0.0f,0.0f,0.0f});
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, v.size() *sizeof(float), &v[0], GL_STATIC_DRAW); //v is a std::vector<float>, it size is the size of the data (buffer), and &v[0] gives the pointer of the data
glEnableVertexAttribArray(0); //layout 0. In this example, position
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glVertexAttribPointer(
0, // layout in shader
3, // number of elements
GL_FLOAT, // type
GL_FALSE, // normalized?
0,
reinterpret_cast<void*>(0)
);
A good way to send data is to pack everything in a std::vector and just arrange the layouts
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, v.size() *sizeof(float), &v[0], GL_STATIC_DRAW); //v is a std::vector<float>, it size is the size of the data (buffer), and &v[0] gives the pointer of the data
const int s[] = { 3, 3, 2 }; //size of data, in my case 3 floats for position, 3 for normals and 2 for texture coordinates
size_t accum = 0;
for (int z = 0; z < 3; ++z){
glEnableVertexAttribArray(z);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glVertexAttribPointer(
z, // layout in shader
s[z], // number of elements
GL_FLOAT, // type
GL_FALSE, // normalized?
8 * sizeof(float), // stride (3+3+2)
reinterpret_cast<void*>(accum*sizeof(float)) //shift from the previous data [3,3,2]
);
accum += s[z];
}
Read about vertex arrays here:
https://stackoverflow.com/a/17517103/5729376
I attach a vertex and fragment shader to a program object, then attempt to link the said program. GL_LINK_STATUS returns false. I check the info log, it's a bunch of gibberish characters. I check GL_INFO_LOG_LENGTH, it's 0. How do I debug this situation?
//this is the end of my LoadBasicShaders function
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glLinkProgram(program);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
GLint logLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
std::vector<GLchar> log(logLength + 1);
glGetProgramInfoLog(program, logLength, &logLength, &log[0]);
fprintf(stderr, "%s\n\n", log);
//logLength returns 0, log returns seemingly random chars
return -3;//just my error code
}
My shaders are the simplest ones possible, since I'm just starting out.
Here's the vertex shader:
#version 330
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
And here's the fragment shader:
#version 330
out vec4 outputColor;
void main()
{
outputColor = vec4(1.0, 1.0, 1.0, 1.0);
}
I use GLFW to create the OpenGL window, and GLEW to load the functions:
if (!glfwInit())
{/*error checking*/}
window = glfwCreateWindow(800, 600, "Swash", NULL, NULL);
if (!window)
{/*more error checking*/}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwSetKeyCallback(window, key_callback);
if (glewInit() != GLEW_OK)
{/*you guessed it*/}
//don't call anything that involves nonstandard OpenGL functions before this point
GLuint shaderProgram;
int shaderLoadResult = LoadBasicShaders(shaderProgram, "../res/vert.shader", "../res/frag.shader");
Use the GLFW error callback
Bullet-proof your shader loader
Use ARB_debug_output or KHR_debug
Request an explicit GL version and profile (Core/Compatibility) via glfwWindowHint()
All together (this is what I meant by posting a MCVE):
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cstdlib>
struct GlDebugOutput
{
static void Install()
{
if( !glewIsSupported( "GL_ARB_debug_output" ) )
{
std::cerr << "GL_ARB_debug_output not supported" << std::endl;
return;
}
glEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB );
glDebugMessageCallbackARB( DebugCallback, 0 );
glDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE );
}
private:
static const char* Source( GLenum source )
{
switch( source )
{
case GL_DEBUG_SOURCE_API_ARB : return "API";
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB : return "WINDOW_SYSTEM";
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB : return "SHADER_COMPILER";
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB : return "THIRD_PARTY";
case GL_DEBUG_SOURCE_APPLICATION_ARB : return "APPLICATION";
case GL_DEBUG_SOURCE_OTHER_ARB : return "OTHER";
default : return "Unknown source";
}
}
static const char* Type( GLenum type )
{
switch( type )
{
case GL_DEBUG_TYPE_ERROR_ARB : return "ERROR";
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB : return "DEPRECATED_BEHAVIOR";
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB : return "UNDEFINED_BEHAVIOR";
case GL_DEBUG_TYPE_PORTABILITY_ARB : return "PORTABILITY";
case GL_DEBUG_TYPE_PERFORMANCE_ARB : return "PERFORMANCE";
case GL_DEBUG_TYPE_OTHER_ARB : return "OTHER";
default : return "Unknown type";
}
}
static const char* Severity( GLenum severity )
{
switch( severity )
{
case GL_DEBUG_SEVERITY_HIGH_ARB : return "HIGH";
case GL_DEBUG_SEVERITY_MEDIUM_ARB : return "MEDIUM";
case GL_DEBUG_SEVERITY_LOW_ARB : return "LOW";
default : return "Unknown severity";
}
}
static void APIENTRY DebugCallback
(
GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam
)
{
std::cerr << "GL_DEBUG"
<< ": " << Source( source )
<< ": " << Type( type )
<< ": " << Severity( severity )
<< ": " << message
<< std::endl;
}
};
struct Program
{
static GLuint Load( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
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
const char* vert = GLSL
(
330,
layout( location = 0 ) in vec4 position;
void main()
{
gl_Position = position;
}
);
const char* frag = GLSL
(
330,
out vec4 outputColor;
void main()
{
outputColor = vec4( 1.0, 1.0, 1.0, 1.0 );
}
);
GLuint VAO;
GLuint VBO;
GLuint prog;
void init()
{
glGenVertexArrays( 1, &VAO );
glBindVertexArray( VAO );
glGenBuffers( 1,&VBO );
glBindBuffer( GL_ARRAY_BUFFER, VBO );
float verts[] =
{
-1.0, -1.0,
1.0, -1.0,
0.0, 1.0,
};
glBufferData( GL_ARRAY_BUFFER, sizeof( verts ), verts, GL_STATIC_DRAW );
prog = Program::Load( vert, NULL, frag );
glUseProgram( prog );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, 0 );
}
void display()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT );
glUseProgram( prog );
glBindVertexArray( VAO );
glDrawArrays( GL_TRIANGLES, 0, 3 );
}
void glfwErrorCallback( int error, const char* description )
{
std::cerr << "GLFW error: " << description << std::endl;
}
int main( int argc, char** argv )
{
glfwSetErrorCallback( glfwErrorCallback );
if( GL_FALSE == glfwInit() )
{
return EXIT_FAILURE;
}
std::cout << "GLFW version : " << glfwGetVersionString() << std::endl;
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE );
glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE );
GLFWwindow* window = glfwCreateWindow( 640, 480, "Test", NULL, NULL );
if( NULL == window )
{
glfwTerminate();
return EXIT_FAILURE;
}
glfwMakeContextCurrent( window );
glfwSwapInterval( 1 );
glewExperimental = GL_TRUE;
const GLenum glewErr = glewInit();
if( GLEW_OK != glewErr )
{
std::cerr << "glewInit() failed: " << glewGetErrorString( glewErr ) << std::endl;
glfwTerminate();
return EXIT_FAILURE;
}
// consume spurious GL error from GLEW init
glGetError();
GlDebugOutput::Install();
init();
while( !glfwWindowShouldClose( window ) )
{
glfwPollEvents();
int w, h;
glfwGetFramebufferSize( window, &w, &h );
glViewport( 0, 0, w, h );
display();
glfwSwapBuffers( window );
}
return EXIT_SUCCESS;
}
If anything is even just a little bit off with your OpenGL implementation and/or shaders that program should scream bloody murder to stderr and exit.
Sorry for the very slow update, I've been busy with other things.
Anyways, the problem was that while writing the code, I had included the line
program = glCreateProgram();
but at some point, while tidying up, I accidentally deleted it. That's why the shaders were compiling but weren't linking, they weren't being linked to a program object.
I am trying to render a simple Triangle in OpenGL ES 2.x using c++ and SDL 2.
But the glCreateShader and glCreatProgram returning zero.
Bellow Is the code I am using
#include "SDL.h"
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#include <iostream>
#include <string>
#include <memory>
using namespace std;
GLuint programObject;
class Graphics
{
private:
SDL_Window* _window;
public:
Graphics(SDL_Window* window)
{
_window = window;
}
void update()
{
glClearColor(255.0f, 0.0f, 255.0f, 1);
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vVertices[] = {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
glViewport (0, 0, 320, 480);
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glClear (GL_COLOR_BUFFER_BIT);
glUseProgram (programObject);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray (0);
glDrawArrays (GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(_window);
}
};
void UpdateFrame(void* param)
{
Graphics* graphics = (Graphics*)param;
graphics->update();
}
///
// Create a shader object, load the shader source, and
// compile the shader.
//
GLuint LoadShader(GLenum type, const GLchar *shaderSrc)
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader(type);
if(shader == 0)
{
cerr << "Could not create OpenGL shader " << endl;
return 0;
}
// Load the shader source
glShaderSource(shader, 1, &shaderSrc, NULL);
// Compile the shader
glCompileShader(shader);
// Check the compile status
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
SDL_Log("Error compiling shader:\n%s\n", infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
///
// Initialize the shader and program object
//
int Init()
{
const char vertexShaderString[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
const char fragmentShaderString[] =
"precision mediump float;\n"\
"void main() \n"
"{ \n"
" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
"} \n";
GLuint vertexShader;
GLuint fragmentShader;
GLint linked;
vertexShader = LoadShader (GL_VERTEX_SHADER, vertexShaderString);
fragmentShader = LoadShader (GL_FRAGMENT_SHADER, fragmentShaderString);
programObject = glCreateProgram ();
if (programObject == 0) {
cerr << "Could not create OpenGL program" << endl;
return 0;
}
glAttachShader (programObject, vertexShader);
glAttachShader (programObject, fragmentShader);
glBindAttribLocation (programObject, 0, "vPosition");
glLinkProgram (programObject);
glGetProgramiv (programObject, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infoLen = 0;
glGetProgramiv (programObject, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = (char*) malloc (sizeof (char) * infoLen);
glGetProgramInfoLog (programObject, infoLen, NULL, infoLog);
cerr << "Error linking program: " << infoLog << endl;
free (infoLog);
}
glDeleteProgram (programObject);
return 0;
}
glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
return true;
}
int EventFilter(void* userdata, SDL_Event* event)
{
switch (event->type)
{
case SDL_FINGERMOTION:
SDL_Log("Finger Motion");
return 0;
case SDL_FINGERDOWN:
SDL_Log("Finger Down");
return 0;
case SDL_FINGERUP:
SDL_Log("Finger Up");
return 0;
}
return 1;
}
int main(int argc, char** argv)
{
/* initialize SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("Could not initialize SDL\n");
return 1;
}
SDL_DisplayMode displayMode;
SDL_GetDesktopDisplayMode(0, &displayMode);
/* create window and renderer */
SDL_Window* window = SDL_CreateWindow(NULL, 0, 0, displayMode.w, displayMode.h, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE);
if (!window) {
printf("Could not initialize Window\n");
return 1;
}
auto gl = SDL_GL_CreateContext(window);
if (!Init()) {
cerr << "Error initializing OpenGL" << endl;
return 1;
}
unique_ptr<Graphics> graphics = unique_ptr<Graphics>(new Graphics(window));
SDL_iPhoneSetAnimationCallback(window, 1, UpdateFrame, graphics.get());
SDL_AddEventWatch(EventFilter, NULL);
//Game Loop
SDL_Event event;
auto done = false;
while (!done)
{
SDL_PumpEvents();
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
done = true;
break;
case SDL_APP_DIDENTERFOREGROUND:
SDL_Log("SDL_APP_DIDENTERFOREGROUND");
break;
case SDL_APP_DIDENTERBACKGROUND:
SDL_Log("SDL_APP_DIDENTERBACKGROUND");
break;
case SDL_APP_LOWMEMORY:
SDL_Log("SDL_APP_LOWMEMORY");
break;
case SDL_APP_TERMINATING:
SDL_Log("SDL_APP_TERMINATING");
break;
case SDL_APP_WILLENTERBACKGROUND:
SDL_Log("SDL_APP_WILLENTERBACKGROUND");
break;
case SDL_APP_WILLENTERFOREGROUND:
SDL_Log("SDL_APP_WILLENTERFOREGROUND");
break;
case SDL_WINDOWEVENT:
{
switch (event.window.event)
{
case SDL_WINDOWEVENT_RESIZED:
{
SDL_Log("Window %d resized to %dx%d", event.window.windowID, event.window.data1, event.window.data2);
break;
}
}
}
}
}
}
SDL_GL_DeleteContext(gl);
// Done! Close the window, clean-up and exit the program.
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Maybe I am missing something here, any help would be appreciated .
Thanks,
Khaled
This is most likely caused by a problem with the context created by SDL, specifically there were no attributes for the MAJOR/MINOR and MASK attributes which tend to be more important for iOS, OS X etc
What needs to be done is as follows. Before the creation of the SDL_Window do the following:
/* Set the correct attributes for MASK and MAJOR version */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
/* create window and renderer */
SDL_Window* window = SDL_CreateWindow(NULL, 0, 0, displayMode.w, displayMode.h, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE);
Another situation which can cause the same error output is calling glCreateShader or glCreateProgram inside of a glBegin / glEnd block.
I am trying to have OpenGL automatically assign an ID to a glsl-attribute, but it is failing.
My main program:
#include <iostream>
#include <GL/glew.h>
#include <GL/glfw3.h>
#include "test.h"
#include "shader_utils.h"
static void error_callback(int error, const char* description) {
std::cout << description << std::endl;
}
static void key_callback(GLFWwindow* window, int a, int b) {
if (a == GLFW_KEY_ESCAPE && b == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
void test()
{
std::cout << "Starting up" << std::endl;
init();
run();
}
GLFWwindow *window;
GLuint shaders;
GLuint vertexBuffer;
int init() {
glfwSetErrorCallback(error_callback);
if(!glfwInit()) {
return -1;
}
window = glfwCreateWindow(640, 480, "GLFW test", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glewExperimental = true;
glewInit();
shaders = LoadShaders("vertex.glsl", "fragment.glsl");
GLuint vao_id;
glGenVertexArrays(1, &vao_id);
glBindVertexArray(vao_id);
static const GLfloat vertex_data[] = {
// Bottom
-.5f, -.5f, -.5f, 1.f, 0.f, 0.f,
-.5f, -.5f, .5f, 1.f, 0.f, 0.f,
.5f, -.5f, .5f, 1.f, 0.f, 0.f,
};
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
}
void checkE() {
std::cout << "Checking for errors: ";
int err;
int a = 0;
while((err = glGetError()) != GL_NO_ERROR) {
std::cout << "Error: " << err << std::endl;
a = 1;
}
if(a == 0) {
std::cout << "no errors" << std::endl;
}
std::cout.flush();
}
int run() {
GLfloat angle = 0;
while(!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaders);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
GLuint attrLocation = glGetAttribLocation(shaders, "location");
GLuint attrColor = glGetAttribLocation(shaders, "color");
std::cout << "AttribLocation('location'): ";
std::cout << glGetAttribLocation(shaders, "location") << std::endl;
std::cout << "AttribLocation('color'): ";
std::cout << glGetAttribLocation(shaders, "color") << std::endl;
checkE();
std::cout << std::endl;
std::cout << "glEnableVertexAttribArray()" << std::endl;
glEnableVertexAttribArray(attrLocation);
glEnableVertexAttribArray(attrColor);
checkE();
std::cout << std::endl;
std::cout << "glVertexAttribPointer();" << std::endl;
glVertexAttribPointer(
glGetAttribLocation(shaders, "location"), // Attribute
3, // Size
GL_FLOAT, // Size
GL_FALSE, // Normalized
24, // Stride
(GLvoid*) 0 // Offset
);
checkE();
std::cout << std::endl;
std::cout << "glVertexAttribPointer();" << std::endl;
glVertexAttribPointer(
glGetAttribLocation(shaders, "color"),
3,
GL_FLOAT,
GL_FALSE,
24,
(GLvoid*) (3*sizeof(GLfloat))
);
checkE();
std::cout << std::endl;
glDrawArrays(GL_TRIANGLES, 0, 3);
checkE();
std::cout << std::endl;
glDisableVertexAttribArray(attrLocation);
glDisableVertexAttribArray(attrColor);
checkE();
std::cout << std::endl;
glfwSwapBuffers(window);
glfwPollEvents();
glfwSetWindowShouldClose(window, GL_TRUE);
}
glfwDestroyWindow(window);
glfwTerminate();
}
Output from program:
Starting up
Compiling shader : vertex.glsl
Compiling shader : fragment.glsl
Linking program
AttribLocation('location'): -1
AttribLocation('color'): -1
Checking for errors: no errors
glEnableVertexAttribArray()
Checking for errors: Error: 1281
glVertexAttribPointer();
Checking for errors: Error: 1281
glVertexAttribPointer();
Checking for errors: Error: 1281
Checking for errors: no errors
Checking for errors: Error: 1281
Shader loader:
#include "shader_utils.h"
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include "GL/glew.h"
#include "GL/glfw3.h"
GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if(VertexShaderStream.is_open())
{
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
} else {
std::cout << "could not open\n";
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if(FragmentShaderStream.is_open()){
std::string Line = "";
while(getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
// Link the program
fprintf(stdout, "Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
std::cout.flush();
return ProgramID;
}
Vertex shader:
#version 130
in vec4 position;
in vec3 color;
out vec3 f_color;
void main() {
f_color = color;
gl_Position = position * gl_ModelViewProjectionMatrix;
}
Fragment shader:
#version 130
in vec3 color;
void main() {
gl_FragColor = vec4(color, 1);
}
For some reason I get just -1 as the location for both the attributes. Obviously the rest of the errors are caused by invalid location indices?
From OpenGL docs:
If the named attribute variable is not an active attribute in the specified program object or if name starts with the reserved prefix "gl_", a value of -1 is returned.
The names do not begin with gl_ and they are in use in the shaders, so I shouldn't get a value of -1. What am I missing?
You are failing to get an attribute location for color because it is not active. While it is true that color is used to calculate f_color in this example, the fragment shader does not use f_color so the linker determines that the vertex attribute named: color is inactive.
The solution is quite simple, really:
Fragment Shader:
#version 130
in vec3 f_color; // RENAMED from color, so that this matches the output from the VS.
void main() {
gl_FragColor = vec4(f_color, 1);
}
It is not an error to re-use the name color for different purposes in the Vertex Shader (input vertex attribute) and Fragment Shader (input varying) stages so the compiler/linker will not complain. It would be an error if you tried to do something like inout color though, so this is why you have to pass vertex attributes to geometry/tessellation/fragment shaders using a differently named varying. If the input/output names between stages do not match then chances are quite good that the original vertex attribute will be considered inactive.
Also, unless you are transposing your ModelViewProjection matrix, you have the matrix multiplication in your vertex shader backwards. Column-major matrix multiplication, as OpenGL uses, should read right-to-left. That is, you start with an object space position (right-most) and transform to clip space (left-most).
In other words, this is the proper way to transform your vertices...
gl_Position = gl_ModelViewProjectionMatrix * position;
~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
clip space object space to clip space obj space