Can't render to GtkGLArea - c++

I try to render a triangle to a GtkGLArea but I only see the color with which I cleared the frame with glClearColor().
Please note:
I know that the triangle is so big that it would fill the whole screen, but I also tried smaller ones and it didn't work either.
I also know that I should normally not create the program before each rendering, I only did it here to keep the example short.
I'm fairly certain that the error is neither in LoadShaders nor in the shaders themselves because I've tried the exact same functions with GLFW and they've worked fine their.
Things which might cause the problem:
I'm not flushing the frame currently or swapping framebuffers because the documentation (https://developer.gnome.org/gtk3/stable/GtkGLArea.html) doesn't mention that I have to. I've tried glFlush() but it didn't help either.
I assume that the screen coordinates go from -1 to 1 on all axis like in normal OpenGL. Maybe that's wrong but I couldn't find anything in the documentation there either.
Could somebody help me?
This is how I compile it:
g++ -O3 -s -o main main.cpp -isystem include -Llibs -DNDEBUG `pkg-config --cflags gtk+-3.0` `pkg-config --libs gtk+-3.0` -lepoxy -lm
This is my code:
#include <gtk/gtk.h>
#include <epoxy/gl.h>
#include <epoxy/glx.h>
#include <iostream>
#include <vector>
GLuint LoadShaders(char const* vertex, char const* fragment){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
glShaderSource(VertexShaderID, 1, &vertex , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
// Compile Fragment Shader
glShaderSource(FragmentShaderID, 1, &fragment , NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if ( InfoLogLength > 0 ){
std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
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);
if ( InfoLogLength > 0 ){
std::vector<char> ProgramErrorMessage(InfoLogLength+1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
char const* vertShader = R"GLSL(
#version 330 core
void main(){
gl_Position.z = 0.0;
gl_Position.w = 1.0;
if (0 == gl_VertexID) {
gl_Position.x = -100.0;
gl_Position.y = -100.0;
}
if (2 == gl_VertexID) {
gl_Position.x = 0.0;
gl_Position.y = 100.0;
}
if (1 == gl_VertexID) {
gl_Position.x = 100.0;
gl_Position.y = -100.0;
}
}
)GLSL";
char const* fragShader = R"GLSL(
#version 330 core
layout(location = 0) out vec4 color;
void main(){
color = vec4(1.0, 0.0, 0.0, 1.0);
}
)GLSL";
gboolean
render(GtkGLArea*, GdkGLContext*, gpointer) {
glClearColor(0.5, 0.5, 0.5, 0);
glClear(GL_COLOR_BUFFER_BIT);
GLuint programID;
programID = LoadShaders(vertShader, fragShader);
glUseProgram(programID);
glDrawArrays(GL_TRIANGLES, 0, 3);
//glFlush();
glDeleteProgram(programID);
return TRUE;
}
int
main(int argc, char** argv) {
gtk_init(&argc, &argv);
auto window{gtk_window_new(GTK_WINDOW_TOPLEVEL)};
auto glWidget{gtk_gl_area_new()};
gtk_container_add(GTK_CONTAINER(window), glWidget);
g_signal_connect (glWidget, "render", G_CALLBACK(render), nullptr);
gtk_widget_show_all(window);
gtk_main();
return EXIT_SUCCESS;
}

Two things I can think of:
You aren't requesting a Core context from the OS. Looks like you have to override create-context & create + return a gdk_gl_context_set_required_version'd GdkGLContext.
When you do get a Core context up & going I'm pretty sure you still need a VAO bound even if you're generating geometry entirely within your vertex shader.
RE: missing VAOs:
With this GLFW program and the VAO creation/bind commented out:
#include <glad/glad.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <iostream>
void CheckStatus( GLuint obj, bool isShader )
{
GLint status = GL_FALSE, log[ 1 << 11 ] = { 0 };
( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status );
( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log );
if( status == GL_TRUE ) return;
std::cerr << (GLchar*)log << "\n";
std::exit( EXIT_FAILURE );
}
void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader, true );
glAttachShader( program, shader );
glDeleteShader( shader );
}
const char* vert = 1 + R"GLSL(
#version 330 core
void main(){
gl_Position.z = 0.0;
gl_Position.w = 1.0;
if (0 == gl_VertexID) {
gl_Position.x = -100.0;
gl_Position.y = -100.0;
}
if (2 == gl_VertexID) {
gl_Position.x = 0.0;
gl_Position.y = 100.0;
}
if (1 == gl_VertexID) {
gl_Position.x = 100.0;
gl_Position.y = -100.0;
}
}
)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( int, char** )
{
glfwSetErrorCallback( []( int, const char* desc ) { std::cerr << desc << "\n"; std::exit( EXIT_FAILURE ); } );
glfwInit();
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
glfwMakeContextCurrent( window );
gladLoadGLLoader( (GLADloadproc)glfwGetProcAddress );
//GLuint vao = 0;
//glGenVertexArrays( 1, &vao );
//glBindVertexArray( vao );
GLuint prog = glCreateProgram();
AttachShader( prog, GL_VERTEX_SHADER, vert );
AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog, false );
while( !glfwWindowShouldClose( window ) )
{
glfwPollEvents();
int w, h;
glfwGetFramebufferSize( window, &w, &h );
glViewport( 0, 0, w, h );
glClearColor( 0.5, 0.5, 0.5, 0 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram( prog );
glDrawArrays( GL_TRIANGLES, 0, 3 );
glfwSwapBuffers( window );
}
glfwTerminate();
}
Running on Linux with Mesa 13.0.6's llvmpipe backend & the MESA_DEBUG=1 envvar gives me a grey window and this message on stdout:
Mesa: User error: GL_INVALID_OPERATION in glDrawArrays(no VAO bound)
Restoring the VAO gives the expected red window.

Related

code error : Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

I'm trying to write a code in C ++ using OpenGL (I use GLFW and GLEW libraries). Here is the code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define numVAOs 1
GLuint renderingProgram;
GLuint vao[numVAOs];
GLuint createShaderProgram(){
const char*vshaderSource =
"#version 430 \n"
"void main(void) \n"
"{gl_Position = vec4(0.0,0.0,0.0,1.0)};";
const char*fshaderSource =
"#version 430 \n"
"out vec4 color; \n"
"void main(void) \n"
"{gl_Position = vec4(0.0,0.0,1.0,1.0)};";
GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vShader,1,&vshaderSource,NULL);
glShaderSource(fShader,1,&fshaderSource,NULL);
glCompileShader(vShader);
glCompileShader(fShader);
GLuint vfProgram = glCreateProgram();
glAttachShader(vfProgram,vShader);
glAttachShader(vfProgram,fShader);
glLinkProgram(vfProgram);
return vfProgram;
}
int main()
{
glfwInit();
// Define version and compatibility settings
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);
glGenVertexArrays(numVAOs,vao);
glBindVertexArray(vao[0]);
glUseProgram(renderingProgram);
glDrawArrays(GL_POINT,0,1);
// Create OpenGL window and context
GLFWwindow* window = glfwCreateWindow(1430, 800, "Davide", NULL, NULL);
glfwMakeContextCurrent(window);
// Check for window creation failure
if (!window)
{
// Terminate GLFW
glfwTerminate();
return 0;
}
glewExperimental = GL_TRUE; glewInit();
// Event loop
while(!glfwWindowShouldClose(window))
{
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
// Terminate GLFW
glfwTerminate(); return 0;
}
Unfortunately when I run the code I get an error code:
Thread 1: EXC_BAD_ACCESS (code = 1, address = 0x0).
It should appear a black screen with a dot in the center.
Multiple issues:
You're calling GL functions before you have a current GL context:
glGenVertexArrays(numVAOs,vao); // nope
glBindVertexArray(vao[0]); // nope
glUseProgram(renderingProgram); // nope
glDrawArrays(GL_POINT,0,1); // nope
// Create OpenGL window and context
GLFWwindow* window = glfwCreateWindow(1430, 800, "Davide", NULL, NULL);
glfwMakeContextCurrent(window);
Move those calls to after glfwMakeContextCurrent() (and your GL loader init) so they have a GL context to operate on (and check if window is NULL before using it in glfwMakeContextCurrent()):
// Create OpenGL window and context
GLFWwindow* window = glfwCreateWindow(1430, 800, "Davide", NULL, NULL);
// Check for window creation failure
if (!window)
{
// Terminate GLFW
glfwTerminate();
return 0;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE; glewInit();
glGenVertexArrays(numVAOs,vao);
glBindVertexArray(vao[0]);
glUseProgram(renderingProgram);
glDrawArrays(GL_POINT,0,1);
You should also initialize renderingProgram before glUseProgram()ing it, perhaps with createShaderProgram()?
gl_Position isn't valid in a fragment shader. You're thinking of gl_Color or a user-defined output like your color output.
If you're requesting a GL 3.2 context then #version 430 isn't valid either. Either upgrade to GL 4.3 or downgrade your shaders to #version 150.
GL_POINT isn't a valid input to glDrawArrays(). You're thinking of GL_POINTS.
Call glDrawArrays() each frame instead of once at the beginning of your draw-loop so you have a chance to actually see your point.
GLSL statements require a semicolon after them.
Invalid:
void main(void)
{
gl_Position = vec4(0.0,0.0,0.0,1.0)
};
Valid:
void main(void)
{
gl_Position = vec4(0.0,0.0,0.0,1.0); // note the semicolon
} // note the lack of semicolon
All together:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
void CheckStatus( GLuint obj, bool isShader )
{
GLint status = GL_FALSE, log[ 1 << 11 ] = { 0 };
( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log );
std::cerr << (GLchar*)log << "\n";
std::exit( EXIT_FAILURE );
}
void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader, true );
glAttachShader( program, shader );
glDeleteShader( shader );
}
const char* const vert = 1 + R"GLSL(
#version 150
void main()
{
gl_Position = vec4(0.0,0.0,0.0,1.0);
}
)GLSL";
const char* const frag = 1 + R"GLSL(
#version 150
out vec4 color;
void main()
{
color = vec4(0.0,0.0,1.0,1.0);
}
)GLSL";
#define numVAOs 1
GLuint renderingProgram;
GLuint vao[ numVAOs ];
int main()
{
glfwInit();
// Define version and compatibility settings
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 OpenGL window and context
GLFWwindow* window = glfwCreateWindow( 320, 240, "Davide", NULL, NULL );
// Check for window creation failure
if( !window )
{
// Terminate GLFW
glfwTerminate();
return 0;
}
glfwMakeContextCurrent( window );
glewExperimental = GL_TRUE;
glewInit();
glGenVertexArrays( numVAOs, vao );
glBindVertexArray( vao[ 0 ] );
GLuint renderingProgram = glCreateProgram();
AttachShader( renderingProgram, GL_VERTEX_SHADER, vert );
AttachShader( renderingProgram, GL_FRAGMENT_SHADER, frag );
glLinkProgram( renderingProgram );
CheckStatus( renderingProgram, false );
glUseProgram( renderingProgram );
// Event loop
while( !glfwWindowShouldClose( window ) )
{
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
glDrawArrays( GL_POINTS, 0, 1 );
glfwSwapBuffers( window );
glfwPollEvents();
}
// Terminate GLFW
glfwTerminate();
return 0;
}

OpenGL shaders don't compile

The shaders in my OpenGL project don't compile. I have Ubuntu 16.04 LTS, using CLion. Didn't find any solution, that's why asking here.
Here is my errorlist:
ATTENTION: default value of option force_s3tc_enable overridden by environment.
ERROR::SHADER::VERTEX::COMPILATION_FAILED
0:1(1): error: syntax error, unexpected $end
ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
0:1(1): error: syntax error, unexpected $end
ERROR::SHADER::PROGRAM::LINKING_FAILED
error: linking with uncompiled shadererror: linking with uncompiled shader
Here's my main.cpp code:
#include <iostream>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// Other includes
#include "Shader.h"
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
// The MAIN function, from here we start the application and run the game loop
int main( )
{
// Init GLFW
glfwInit( );
// Set all the required options for GLFW
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 );
glfwWindowHint( GLFW_RESIZABLE, GL_FALSE );
// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow *window = glfwCreateWindow( WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr );
int screenWidth, screenHeight;
glfwGetFramebufferSize( window, &screenWidth, &screenHeight );
if ( nullptr == window )
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate( );
return EXIT_FAILURE;
}
glfwMakeContextCurrent( window );
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers
if ( GLEW_OK != glewInit( ) )
{
std::cout << "Failed to initialize GLEW" << std::endl;
return EXIT_FAILURE;
}
// Define the viewport dimensions
glViewport( 0, 0, screenWidth, screenHeight );
// Build and compile our shader program
Shader ourShader( "core.vs", "core.frag" );
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[] =
{
// Positions // Colors
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom Left
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // Top
};
GLuint VBO, VAO;
glGenVertexArrays( 1, &VAO );
glGenBuffers( 1, &VBO );
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
glBindVertexArray( VAO );
glBindBuffer( GL_ARRAY_BUFFER, VBO );
glBufferData( GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW );
// Position attribute
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof( GLfloat ), ( GLvoid * ) 0 );
glEnableVertexAttribArray( 0 );
// Color attribute
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof( GLfloat ), ( GLvoid * )( 3 * sizeof( GLfloat ) ) );
glEnableVertexAttribArray( 1 );
glBindVertexArray( 0 ); // Unbind VAO
// Game loop
while ( !glfwWindowShouldClose( window ) )
{
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents( );
// Render
// Clear the colorbuffer
glClearColor( 0.2f, 0.3f, 0.3f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw the triangle
ourShader.Use( );
glBindVertexArray( VAO );
glDrawArrays( GL_TRIANGLES, 0, 3 );
glBindVertexArray(0);
// Swap the screen buffers
glfwSwapBuffers( window );
}
// Properly de-allocate all resources once they've outlived their purpose
glDeleteVertexArrays( 1, &VAO );
glDeleteBuffers( 1, &VBO );
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate( );
return EXIT_SUCCESS;
}
Shader.h code:
#ifndef SHADER_H
#define SHADER_H
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>
#include <cstring>
class Shader
{
public:
GLuint Program;
// Constructor generates the shader on the fly
Shader( const GLchar *vertexPath, const GLchar *fragmentPath )
{
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensures ifstream objects can throw exceptions:
vShaderFile.exceptions ( std::ifstream::badbit );
fShaderFile.exceptions ( std::ifstream::badbit );
try
{
// Open files
vShaderFile.open( vertexPath );
fShaderFile.open( fragmentPath );
std::stringstream vShaderStream, fShaderStream;
// Read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf( );
fShaderStream << fShaderFile.rdbuf( );
// close file handlers
vShaderFile.close( );
fShaderFile.close( );
// Convert stream into string
vertexCode = vShaderStream.str( );
fragmentCode = fShaderStream.str( );
}
catch ( std::ifstream::failure e )
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const GLchar *vShaderCode = vertexCode.c_str( );
const GLchar *fShaderCode = fragmentCode.c_str( );
// 2. Compile shaders
GLuint vertex, fragment;
GLint success;
GLchar infoLog[512];
// Vertex Shader
vertex = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertex, 1, &vShaderCode, NULL);
glCompileShader( vertex );
// Print compile errors if any
glGetShaderiv( vertex, GL_COMPILE_STATUS, &success );
if ( !success )
{
glGetShaderInfoLog( vertex, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment Shader
fragment = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragment, 1, &fShaderCode, NULL);
glCompileShader( fragment );
// Print compile errors if any
glGetShaderiv( fragment, GL_COMPILE_STATUS, &success );
if ( !success )
{
glGetShaderInfoLog( fragment, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Shader Program
this->Program = glCreateProgram( );
glAttachShader( this->Program, vertex );
glAttachShader( this->Program, fragment );
glLinkProgram( this->Program );
// Print linking errors if any
glGetProgramiv( this->Program, GL_LINK_STATUS, &success );
if (!success)
{
glGetProgramInfoLog( this->Program, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// Delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader( vertex );
glDeleteShader( fragment );
}
// Uses the current shader
void Use( )
{
glUseProgram( this->Program );
}
};
#endif
Here's my core.vs:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(position, 1.0f);
ourColor = color;
// We swap the y-axis by substracing our coordinates from 1. This is done because most images have the top y-axis inversed with OpenGL's top y-axis.
// TexCoord = texCoord;
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
}
...and core.frag:
#version 330 core
in vec3 ourColor;
in vec2 TexCoord;
out vec4 color;
// Texture samplers
uniform sampler2D ourTexture1;
void main()
{
// Linearly interpolate between both textures (second texture is only slightly combined)
color = texture(ourTexture1, TexCoord);
}
I've also attached my CMakeLists.txt. Hope it helps:
cmake_minimum_required(VERSION 3.9)
project(STUDY_GL)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -pthread -fpermissive")
find_package (OpenGL REQUIRED)
find_package (GLUT REQUIRED)
find_package (glfw3 REQUIRED)
find_library (glew REQUIRED)
find_library (glad REQUIRED)
include_directories(${/usr/include/GLFW/})
include_directories(${/usr/include/GL/})
file(GLOB SOURCE_FILES
*.cpp
*.h
)
add_executable(main.cpp ${SOURCE_FILES} Shader.h)
target_link_libraries (main.cpp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${GLFW3_LIBRARIES} -lGL -lglfw -lglut -lGLEW)
I have an SOIL2 directory inside a project. Here's its link.
In general you code is fine, but you have to pass std::ifstream::failbit to std::ios::exceptions, because if std::ifstream::open fails, the failbit state flag is set.
vShaderFile.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
fShaderFile.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
try
{
vShaderFile.open( vertexPath );
fShaderFile.open( fragmentPath );
.....
}
catch ( std::ifstream::failure e )
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
I bet that your working directory is not proper set. Use an absolute file path to the shader files for debug reasons.
If the shader source files cannot be accessed, and your code does not throw any exception, then you try to compile empty strings. This causes the error messages.
By the way, since you do not use any texture in the code snippet posted in your question, you should do the following changes to your fragment shader:
// color = texture(ourTexture1, TexCoord); <--- skip
color = vec4(ourColor,1.0); <--- add
The error you see normally happens, when shader source without a null terminator at the end is passed to glShaderSource without specifying the source string length. Since typical files usually don't contain a null terminator, OpenGL will read past the end of the source string.
The solution is to pass in the exact length of the shader source string.

Opengl Sierpinski Shader based C code in Visual Studio2012 & 2010

I'm doing my first steps in OpenGl Shader base programming and computer graphics. I'm trying the following example, but when I try to compile the project I got the following error:
fragment shader failed to link. vertex shader failed to link.
ERROR: Not all shaders has valid object code
i tried running the program in Visual Studio 2012 and 2010. glut library version is 3.7 and glew library version is 1.10.0. what is the problem?
.cpp Program
#include <stdio.h>
#include <stdlib.h>
#include <glew.h>
#include <glut.h>
#include <gl.h>
#pragma comment(lib,"glew32.lib")
#define NoP 50000
GLuint InitShader(char *, char *);
void mydisplay();
struct points
{ GLfloat x,y,z;
};
void init();
void Sierpinski(points Num[]);
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE|GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutInitWindowPosition(0,0);
glutCreateWindow("Sierpinski 3D");
glewInit();
init();
glEnable(GL_DEPTH_TEST);
glutDisplayFunc(mydisplay);
glutMainLoop();
}
void init()
{
points Num[NoP];
Sierpinski(Num);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);//set the color for clearing the display
glPointSize(2); // set the point size
// Creating a program object containing shader files
GLuint program;
program = InitShader("vshader.glsl","fshader.glsl");
glUseProgram(program);
//Creating a buffer object containing Sirepinski verteces data
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Num), Num, GL_STATIC_DRAW);
//Make a conncetion between data in object buffer and "vPosition in vertex shader
GLuint location = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray ( location );
glVertexAttribPointer( location, 3, GL_FLOAT, GL_FALSE,0, 0);//BUFFER_OFFSET(0));
}
void mydisplay()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //the clear call will affect the color buffer
glDrawArrays(GL_POINTS,0,NoP);//Rendering verteces data
glFlush(); //Empty all commands buffer, causing all issued commands to be executed as quickly as they are accepted by the actual rendering engine
}
static char * ReadShaderSource(char * ShaderFile)
{
FILE *fp;
fp = fopen(ShaderFile,"rt");
if (!fp) return NULL;
long size=0;
while (!feof(fp))
{
fgetc (fp);
size++;
}
size--;//EOF should not be counted
fseek(fp, 0, SEEK_SET);
char * buf= new char[size + 1];
fread(buf, 1, size,fp);
buf[size]=0;// string is NULL terminated
fclose(fp);
return buf;
}
GLuint InitShader(char * vShaderFile, char * fShaderFile)
{
char * svs, * sfs;
GLuint program, VertexShader, FragmentShader;
program = glCreateProgram();
VertexShader = glCreateShader(GL_VERTEX_SHADER);
svs=ReadShaderSource(vShaderFile);
glShaderSource(VertexShader,1,(const GLchar **)&svs,NULL);
glCompileShader(VertexShader);
// reading GLSL compiler error messages for vertex shader
GLint compiled;
glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{ printf("/n failed to compile");
GLint logSize;
glGetShaderiv(VertexShader, GL_INFO_LOG_LENGTH,&logSize);
char * logMsg = new char[logSize];
glGetShaderInfoLog(VertexShader, logSize, NULL, logMsg);
printf("\n %s",logMsg);
delete [] logMsg;
getchar();
exit(EXIT_FAILURE);
}
FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
sfs = ReadShaderSource(fShaderFile);
glShaderSource(FragmentShader, 1, (const GLchar **)&sfs, NULL);
glCompileShader(FragmentShader);
// reading GLSL compiler error messages for fragment shader
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{ printf("\n failed to compile");
GLint logSize2;
glGetShaderiv(FragmentShader, GL_INFO_LOG_LENGTH,&logSize2);
char * logMsg2 = new char[logSize2];
glGetShaderInfoLog(FragmentShader, logSize2, NULL, logMsg2);
printf("\n %s",logMsg2);
delete [] logMsg2;
getchar();
exit(EXIT_FAILURE);
}
glAttachShader(program,VertexShader);
glAttachShader(program, FragmentShader);
glLinkProgram(program);
// reading GLSL linker error messages for program object
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if(!linked)
{ printf("/n failed to link");
GLint logSize;
glGetProgramiv(program, GL_INFO_LOG_LENGTH,&logSize);
char * logMsg = new char[logSize];
glGetProgramInfoLog(program, logSize, NULL, logMsg);
printf("\n %s",logMsg);
delete [] logMsg;
getchar();
exit(EXIT_FAILURE);
}
glUseProgram(program);
return program;
}
void Sierpinski(points Num[])
{
int j;
points Vertices[4]={{-1.0,-1.0, -1.0},{1.0,-1.0,-1.0},{0.0,1.0,-1.0},{0.0,0.0,1.0}};
Num[0].x = 0;
Num[0].y = 0;
Num[0].z = 0;
for(int i=1;i<NoP;i++)
{
j = rand() % 4;
Num[i].x = (Vertices[j].x + Num[i - 1].x)/2;
Num[i].y = (Vertices[j].y + Num[i - 1].y)/2;
Num[i].z = (Vertices[j].z + Num[i - 1].z)/2;
}
}
vshader.glsl
#version 130
in vec4 vPosition;
out vec4 color;
void main()
{
gl_Position = vPosition;
color = vPosition;
}
fshader.glsl
#version 130
in vec4 color;
void main()
{
gl_FragColor = vec4((1.0 + color.xyz)/2.0,1.0);
}
Seems to work fine:
#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>
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 << 17 ] = { 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( -1 );
}
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 );
}
GLuint LoadProgram( 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;
}
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
130,
in vec4 vPosition;
out vec4 color;
void main()
{
gl_Position = vPosition;
color = vPosition;
}
);
const char* frag = GLSL
(
130,
precision mediump float;
in vec4 color;
void main()
{
gl_FragColor = vec4((1.0 + color.xyz)/2.0,1.0);
}
);
#define NoP 50000
struct points
{
GLfloat x,y,z;
};
void Sierpinski(points Num[])
{
int j;
points Vertices[4]={{-1.0,-1.0, -1.0},{1.0,-1.0,-1.0},{0.0,1.0,-1.0},{0.0,0.0,1.0}};
Num[0].x = 0;
Num[0].y = 0;
Num[0].z = 0;
for(int i=1;i<NoP;i++)
{
j = rand() % 4;
Num[i].x = (Vertices[j].x + Num[i - 1].x)/2;
Num[i].y = (Vertices[j].y + Num[i - 1].y)/2;
Num[i].z = (Vertices[j].z + Num[i - 1].z)/2;
}
}
void init()
{
points Num[NoP];
Sierpinski(Num);
GLuint program = LoadProgram( vert, NULL, frag );
glUseProgram(program);
//Creating a buffer object containing Sirepinski verteces data
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Num), Num, GL_STATIC_DRAW);
//Make a conncetion between data in object buffer and "vPosition in vertex shader
GLuint location = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray ( location );
glVertexAttribPointer( location, 3, GL_FLOAT, GL_FALSE,0, 0);//BUFFER_OFFSET(0));
}
void mydisplay()
{
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);//set the color for clearing the display
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //the clear call will affect the color buffer
glPointSize(2); // set the point size
glDrawArrays(GL_POINTS,0,NoP);//Rendering verteces data
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE|GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutInitWindowPosition(0,0);
glutCreateWindow("Sierpinski 3D");
glewInit();
init();
glEnable(GL_DEPTH_TEST);
glutDisplayFunc(mydisplay);
glutMainLoop();
}
Make sure you use FreeGLUT, Nate's GLUT is way, way old.

OpenGL Red Book 8th - First Example gives black box (Ubuntu)

After getting the first example program compiled from the 8th edition OpenGL Programming Guide after many alterations suggested by many sites, I am the proud owner of a black box - a vast improvement from the hours before, but it's embarrassing to admit that I've watch most of this with a debugger and unless something basic is wrong with the program, I have no clue where to look. Other OpenGL examples have run, but I'm trying to get the first example in the new book to run.
My box:
john#zerofluid:~/Downloads$ glxinfo | grep OpenGL
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce GT 610/PCIe/SSE2
OpenGL version string: 4.3.0 NVIDIA 313.30
OpenGL shading language version string: 4.30 NVIDIA via Cg compiler
OpenGL extensions:
Linux zerofluid 3.8.0-26-generic #38-Ubuntu SMP Mon Jun 17 21:43:33 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
(latest 13.04 Ubuntu)
I have a problem - it's way too much code to post here, but it is the first example of the book - as small as it gets and I have no idea of where the problem really is. It would be cool if someone actually wants to help - I'd feed it back to the author of the book. Yes, the LoadShader was found elsewhere and might be the problem, but it was supposed to be a solution. It's kind of hard to have any faith in the book when I can't get the first example to compile.
It can be found here:
https://github.com/kestess/opengl8thfirstexample.git
it's way too much code to post here
Not really.
Try this:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <vector>
#include <iostream>
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, len = 10;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &len );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &len );
std::vector< char > log( len, 'X' );
if( glIsShader(obj) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
std::cerr << &log[0] << std::endl;
exit( -1 );
}
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
(
400 core,
layout( location = 0 ) in vec4 vPosition;
void main()
{
gl_Position = vPosition;
}
);
const char* frag = GLSL
(
400 core,
out vec4 fColor;
void main()
{
fColor = vec4( 0.0, 0.0, 1.0, 1.0 );
}
);
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;
void init(void)
{
glGenVertexArrays(NumVAOs, VAOs);
glBindVertexArray(VAOs[Triangles]);
GLfloat vertices[NumVertices][2] = {
{ -0.90, -0.90 }, // Triangle 1
{ 0.85, -0.90 },
{ -0.90, 0.85 },
{ 0.90, -0.85 }, // Triangle 2
{ 0.90, 0.90 },
{ -0.85, 0.90 }
};
glGenBuffers(NumBuffers, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint program = Program::Load( vert, NULL, frag );
glUseProgram(program);
glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0) );
glEnableVertexAttribArray(vPosition);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize(512, 512);
glutInitContextVersion(4, 0);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow(argv[0]);
glewExperimental = GL_TRUE;
if( GLEW_OK != glewInit() )
exit(EXIT_FAILURE);
init();
glutDisplayFunc(display);
glutMainLoop();
}
No reason to request a 4.3 context if you're using #version 400 core.

Error 1282 if I attach a fragment shader to the program

I'm trying to run a program using shaders. In Another question I made, I discovered that I was mixing the fixed pipeline functions with the newer stuff (from OpenGL 2.0), so I tried to remove all the "old stuff" like glMatrixMode, but I'm not sure if I'm doing it correctly. In the doubt I also removed calls like glLightfv which I'm not really sure if they're allowed if I used a programmable pipeline.
This is the main code:
#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>
#include <vector>
#include "utility.hpp"
#include "program.hpp"
GLfloat width=600, height=800;
Program* program_ref;
void init()
{
glewInit();
Shader vertex_shader= Shader("vertex_shader",GL_VERTEX_SHADER);
// This just reads the file "vertex_shader", creates the shader and compiles it
Shader geometry_shader= Shader(); // This means that the shader is empty
// So the program class will be enough smart to recognize it and don't attach it
Shader fragment_shader= Shader("fragment_shader",GL_FRAGMENT_SHADER);
program_ref= new Program(vertex_shader,geometry_shader,fragment_shader);
// This creates a program, attaches the shaders to it, links and uses it
}
void display()
{
vector<GLfloat> quad{-0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,0.5};
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2,GL_FLOAT,0,quad.data());
glDrawArrays(GL_QUADS,0,4);
glDisableClientState(GL_VERTEX_ARRAY);
glutSwapBuffers();
cout << glGetError() << endl;
}
void reshape(int w, int h)
{
width=w;
height=h;
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(500,500);
glutCreateWindow("test");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
init();
glewInit();
glutMainLoop();
return 0;
}
(Optional classes to see, in the comments I wrote how are Program and Shader are behaving)
shader.hpp:
#ifndef shader_hpp
#define shader_hpp
#include "utility.hpp"
#include "shader.hpp"
#include <fstream>
#define MAX_SIZE (size_t)1.0e5
class Shader
{
private:
GLuint id;
GLenum type;
bool null;
public:
Shader()
{
id=-1;
type= -1;
null= true;
}
Shader(const string& filename,GLenum type)
{
GLchar* data= new GLchar[MAX_SIZE];
streamsize count;
this->type= type;
ifstream is;
is.open(filename);
is.read(data,MAX_SIZE);
count= is.gcount();
is.close();
id=glCreateShader(type);
glShaderSource(id,1,(const GLchar**)&data,&count);
glCompileShader(id);
delete[] data;
null= false;
}
GLuint getId() const
{
return id;
}
GLenum getType() const
{
return type;
}
bool isNull() const
{
return null;
}
};
#endif
program.hpp:
#ifndef program_hpp
#define program_hpp
#include "utility.hpp"
#include "shader.hpp"
class Program
{
private:
GLuint id;
public:
Program(const Shader& vertex_shader, const Shader& geometry_shader, const Shader& fragment_shader)
{
id= glCreateProgram();
if(!vertex_shader.isNull())
{
glAttachShader(id,vertex_shader.getId());
}
if(!geometry_shader.isNull())
{
glAttachShader(id,geometry_shader.getId());
}
if(!fragment_shader.isNull())
{
glAttachShader(id,fragment_shader.getId());
}
glLinkProgram(id);
glUseProgram(id);
}
GLuint getId()
{
return id;
}
};
#endif
There two classes are just made to simplify everything when using glew to compile the shaders and attach them to the program.
The problem is the following: If I just attach the vertex shader and not the fragment shader, all is fine and I see the quad drawn with the right color (red, because in the vertex shader below I'll set the color to red). If instead I also attach the fragment shader I see that the quad is white. I also tried to see what wasn't right and I printed the result of glGetError(). If I include the fragment shader I get error 1282, if I don't include it I don't get any error (0).
Vertex shader:
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = vec4(1,0,0,1);
// The only relevant thing I do is to set the color to red
// I see the quad red if I attach only the vertex shader and not the fragment shader
gl_TexCoord[0] = gl_MultiTexCoord0;
}
Fragment shader:
void main()
{
gl_fragColor= gl_Color;
}
Give this a shot:
#include <GL/glew.h>
#include <GL/glut.h>
#include <vector>
#include <iostream>
using namespace std;
void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE, len = 10;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &len );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &len );
vector< char > log( len, 'X' );
if( glIsShader(obj) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
cerr << &log[0] << endl;
exit( -1 );
}
GLuint LoadShader( GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
return shader;
}
GLuint LoadProgram( const char* vert, const char* geom, const char* frag )
{
GLuint program = glCreateProgram();
if( vert ) glAttachShader( program, LoadShader( GL_VERTEX_SHADER, vert ) );
if( geom ) glAttachShader( program, LoadShader( GL_GEOMETRY_SHADER, geom ) );
if( frag ) glAttachShader( program, LoadShader( GL_FRAGMENT_SHADER, frag ) );
glLinkProgram( program );
CheckStatus( program );
return program;
}
#define GLSL(version, shader) "#version " #version "\n" #shader
const GLchar* vert = GLSL
(
120,
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = vec4(1.0,0.0,0.0,1.0);
// The only relevant thing I do is to set the color to red
// I see the quad red if I attach only the vertex shader and not the fragment shader
gl_TexCoord[0] = gl_MultiTexCoord0;
}
);
const GLchar* frag = GLSL
(
120,
void main()
{
gl_FragColor= gl_Color;
}
);
void display()
{
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
static GLuint prog = LoadProgram( vert, NULL, frag );
glUseProgram( prog );
glEnableClientState(GL_VERTEX_ARRAY);
GLfloat quad[] = {-0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,0.5};
glVertexPointer(2,GL_FLOAT,0,quad);
glDrawArrays(GL_QUADS,0,4);
glDisableClientState(GL_VERTEX_ARRAY);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(500,500);
glutCreateWindow("test");
glutDisplayFunc(display);
glewInit();
glutMainLoop();
return 0;
}
As Antonie Blom pointed out gl_fragColor should be gl_FragColor. The lower-case f chokes the GLSL compiler on my system.