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.
Related
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 months ago.
I'm using codeblocks and MinGW and windows 10.
I put the directory for the include folder for glad and GLFW under compiler under search directories. I put the directory for the lib folder for GLFW under compiler under search directories. I also put libopengl32.a, libglfw3.a and libglfw3dll.a under Linker settings.
Errors:
||=== Build: Debug in test (compiler: GNU GCC Compiler) ===|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_CreateDCW'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_GetDeviceCaps'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_DeleteDC'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_GetDeviceCaps'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_GetDeviceCaps'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_GetDeviceCaps'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_CreateDCW'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_GetDeviceGammaRamp'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_DeleteDC'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_CreateDCW'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_SetDeviceGammaRamp'|
C:\GL\glfw\lib\libglfw3.a(win32_monitor.c.obj):win32_monitor.c|| undefined reference to `__imp_DeleteDC'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_CreateDIBSection'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_CreateBitmap'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_DeleteObject'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_DeleteObject'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_CreateRectRgn'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_DeleteObject'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_DeleteObject'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_CreateDIBSection'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_CreateBitmap'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_DeleteObject'|
C:\GL\glfw\lib\libglfw3.a(win32_window.c.obj):win32_window.c|| undefined reference to `__imp_DeleteObject'|
C:\GL\glfw\lib\libglfw3.a(wgl_context.c.obj):wgl_context.c|| undefined reference to `__imp_SwapBuffers'|
C:\GL\glfw\lib\libglfw3.a(wgl_context.c.obj):wgl_context.c|| undefined reference to `__imp_ChoosePixelFormat'|
C:\GL\glfw\lib\libglfw3.a(wgl_context.c.obj):wgl_context.c|| undefined reference to `__imp_SetPixelFormat'|
C:\GL\glfw\lib\libglfw3.a(wgl_context.c.obj):wgl_context.c|| undefined reference to `__imp_DescribePixelFormat'|
C:\GL\glfw\lib\libglfw3.a(wgl_context.c.obj):wgl_context.c|| undefined reference to `__imp_SetPixelFormat'|
C:\GL\glfw\lib\libglfw3.a(wgl_context.c.obj):wgl_context.c|| undefined reference to `__imp_DescribePixelFormat'|
C:\GL\glfw\lib\libglfw3.a(wgl_context.c.obj):wgl_context.c|| undefined reference to `__imp_DescribePixelFormat'|
||error: ld returned 1 exit status|
||=== Build failed: 31 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|
Code:
#include <glad/glad.h>
#include <glfw3.h>
#include <iostream>
void framebuffer_size_callback( GLFWwindow* window, int width, int height );
void processInput( GLFWwindow* window );
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 0 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
#ifdef __APPLE__
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow( SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL );
if( window == NULL )
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent( window );
glfwSetFramebufferSizeCallback( window, framebuffer_size_callback );
// glad: load all OpenGL function pointers
// ---------------------------------------
if( !gladLoadGLLoader( (GLADloadproc)glfwGetProcAddress ) )
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// build and compile our shader program
// ------------------------------------
// vertex shader
int vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexShaderSource, NULL );
glCompileShader( vertexShader );
// check for shader compile errors
int success;
char infoLog[ 512 ];
glGetShaderiv( vertexShader, GL_COMPILE_STATUS, &success );
if( !success )
{
glGetShaderInfoLog( vertexShader, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// fragment shader
int fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentShaderSource, NULL );
glCompileShader( fragmentShader );
// check for shader compile errors
glGetShaderiv( fragmentShader, GL_COMPILE_STATUS, &success );
if( !success )
{
glGetShaderInfoLog( fragmentShader, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// link shaders
int shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
glLinkProgram( shaderProgram );
// check for linking errors
glGetProgramiv( shaderProgram, GL_LINK_STATUS, &success );
if( !success )
{
glGetProgramInfoLog( shaderProgram, 512, NULL, infoLog );
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader( vertexShader );
glDeleteShader( fragmentShader );
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
unsigned int VBO, VAO;
glGenVertexArrays( 1, &VAO );
glGenBuffers( 1, &VBO );
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray( VAO );
glBindBuffer( GL_ARRAY_BUFFER, VBO );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ), (void*)0 );
glEnableVertexAttribArray( 0 );
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer( GL_ARRAY_BUFFER, 0 );
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray( 0 );
// uncomment this call to draw in wireframe polygons.
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// render loop
// -----------
while( !glfwWindowShouldClose( window ) )
{
// input
// -----
processInput( window );
// render
// ------
glClearColor( 0.2f, 0.3f, 0.3f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// draw our first triangle
glUseProgram( shaderProgram );
// seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glBindVertexArray( VAO );
glDrawArrays( GL_TRIANGLES, 0, 3 );
// glBindVertexArray(0); // no need to unbind it every time
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers( window );
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays( 1, &VAO );
glDeleteBuffers( 1, &VBO );
glDeleteProgram( shaderProgram );
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput( GLFWwindow* window )
{
if( glfwGetKey( window, GLFW_KEY_ESCAPE ) == GLFW_PRESS )
glfwSetWindowShouldClose( window, true );
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback( GLFWwindow* window, int width, int height )
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport( 0, 0, width, height );
}
I fixed it by linking my project to libgdi32.a, which should be located in the lib folder in your MinGW install folder.
I'm not sure how it works on Code::Blocks, but on the command line with g++ you just add -lgdi32 to your command line options.
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;
}
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.
I just begin my journey in graphical computing, so I started by understanding this tutorial: https://learnopengl.com/Getting-started/Hello-Triangle.
Before adventuring myself to do some "dynamic" drawing I thought transform
this into a "Renderer" class would be interesting this was the result:
#pragma once
#include <fstream>
#include <vector>
#include "pch.h"
class Renderer {
public:
Renderer(GLFWwindow*);
void initVertexShaders(std::vector<std::string>&);
void initFragmentShaders(std::vector<std::string>&);
void load(float*, size_t);
void draw();
const GLubyte* renderer;
const GLubyte* version;
private:
GLFWwindow* window = nullptr;
GLuint vbo;
GLuint vao;
GLuint shaderProgram = 0; //= glCreateProgram();
GLuint vs[100];
GLuint fs[100];
};
pch.h is a precompiled header in order to not compile glm, glfw and glew everytime y build the project.
The idea was to isolate different utilities, I would use load(float*, size_t) to send information to the gpu, and draw() during the main window loop. The idea is to make a first approximation to a 2d, cameraless render engine.
Anyway, source code is:
#include "Renderer.hpp"
Renderer::Renderer(GLFWwindow* window) {
this->window = window;
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
glewInit();
this->renderer = glGetString(GL_RENDERER);
this->version = glGetString(GL_VERSION);
this->vao = 0;
this->vbo = 0;
}
void Renderer::load(float* points, size_t memory) {
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, memory, points, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
}
void Renderer::draw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
void Renderer::initVertexShaders(std::vector<std::string>& paths) {
int i = 0;
std::ifstream ifs;
if(this->shaderProgram == 0) shaderProgram = glCreateProgram();
for (const auto& path : paths){
ifs.open(path);
std::string program_str(( std::istreambuf_iterator<char>(ifs)),
( std::istreambuf_iterator<char>() ));
const char* program_src = program_str.c_str();
vs[i] = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs[i], 1, &program_src, NULL);
glCompileShader(vs[i]);
glAttachShader(shaderProgram, vs[i]);
i++;
}
glLinkProgram(shaderProgram);
}
void Renderer::initFragmentShaders(std::vector<std::string>& paths) {
int i = 0;
std::ifstream ifs;
if(this->shaderProgram == 0) shaderProgram = glCreateProgram();
for (const auto& path : paths){
ifs.open();
std::string program_str(( std::istreambuf_iterator<char>(ifs)),
( std::istreambuf_iterator<char>() ));
const char* program_src = program_str.c_str();
fs[i] = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs[i], 1, &program_src, NULL);
glCompileShader(fs[i]);
glAttachShader(shaderProgram, fs[i]);
i++;
}
glLinkProgram(shaderProgram);
}
The problem comes at shader time, I can read the files without problem, but they do nothing.
The questions are: Does store all the shaders in an array make sense?
Can a shader program consist in more than one vertex shader/fragment shader?
Is the error in another spot?
Does the whole class make sense in any way?
Thank you.
edit: Code from main.cpp
#include "Renderer.hpp"
float points[] = {
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
//
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
int main() {
std::vector<std::string> vertexShaders;
std::vector<std::string> fragmentShaders;
vertexShaders.push_back("shader/vs.glsl");
fragmentShaders.push_back("shader/fs.glsl");
glfwInit(); //glfwGetPrimaryMonitor()
GLFWwindow *window = glfwCreateWindow(960, 540, "Hello Triangle", NULL, NULL);
Renderer Ren(window);
Ren.load(points, sizeof(points));
Ren.initVertexShaders(vertexShaders);
Ren.initFragmentShaders(fragmentShaders);
while (!glfwWindowShouldClose(window)) {
Ren.draw();
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
It is sufficient to link the shader program object once, after all attached shader objects have been compiled.
OpenGL 4.6 API Core Profile Specification; 7.3. PROGRAM OBJECTS; page 94:
Shader objects may be attached to program objects before source code has been loaded into the shader object, or before the shader object has been compiled or specialized.
Note, it is sufficient that the shader object is successfully compiled, before the shader program object, where it is attached to, gets linked.
OpenGL 4.6 API Core Profile Specification; 7.3. PROGRAM OBJECTS; page 94:
Multiple shader objects of the same type may be attached to a single program object, and a single shader object may be attached to more than one program object.
e.g.
One shader object contains a function (FragColor)
#version 460
uniform sampler2D u_texture;
vec4 FragColor(vec2 uv)
{
return texture(u_texture, uv);
}
A second shader object of the same type contains the function signature (but not the implementation) and the usage of the function.
#version 460
in vec2 vUV;
out vec4 fragColor;
vec4 FragColor(vec2 uv);
void main()
{
fragColor = FragColor(vUV);
}
Both of the above code snippets can be placed to 2 separate shader objects of type GL_FRAGMENT_SHADER. Each of the 2 shader objects can be successfully compiled. And if they are attached to the same shader program object, then the shader program object can be successfully liked.
See also Attaching multiple shaders of the same type in a single OpenGL program?
Further, I recommend to check if a shader object was successfully compiled:
GLuint shaderObj = .... ;
glCompileShader( shaderObj );
GLint status = GL_TRUE;
glGetShaderiv( shaderObj, GL_COMPILE_STATUS, &status );
if ( status == GL_FALSE )
{
GLint logLen;
glGetShaderiv( shaderObj, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetShaderInfoLog( shaderObj, logLen, &written, log.data() );
std::cout << "compile error:" << std::endl << log.data() << std::endl;
}
and a shader program object was successfully linked:
GLuint progObj = ....;
glLinkProgram( progObj );
GLint status = GL_TRUE;
glGetProgramiv( progObj, GL_LINK_STATUS, &status );
if ( status == GL_FALSE )
{
GLint logLen;
glGetProgramiv( progObj, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetProgramInfoLog( progObj, logLen, &written, log.data() );
std::cout << "link error:" << std::endl << log.data() << std::endl;
}
Hello everyone im trying to learn openGL using shaders so i made a triangle that changes its color while it moves but for some reason the trigle does not appear in the window, just a black background , it doesn't crash or show any kind of error, i believe the libraries set up is ok since i've used them before.
Im using CLion on Ubuntu 16.04. Here is my code so hopefully you can check it out and give me a hand. Thanks!
#define GLEW_STATIC
#include <stdlib.h>
#include <stdio.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
int CurrentWidth = 800,
CurrentHeight = 600,
WindowHandle = 0;
GLuint
VertexShaderId,
FragmentShaderId,
ProgramId;
GLuint s_vertexLoc, s_colorLoc , s_factorLoc;
GLfloat runner = 0.0;
const GLchar* VertexShader =
{
"#version 150\n"
"attribute vec3 in_vertex;"
"attribute vec3 in_color;"
"uniform float factor;"
"varying vec3 intp_color;"
"void main(void)"
"{"
"intp_color = in_color;"
"gl_Position = vec4( in_vertex , 1.0 ) ;"
"gl_Position.y += factor; "
"}"
};
//Telling every single pixel is going to be red
const GLchar* FragmentShader =
{
"#version 150\n"
"uniform float factor;"
"varying vec3 intp_color;"
"void main(void){"
"gl_FragColor = vec4( intp_color , 1.0) * factor;"
"}"
};
// for. dec.
void ResizeFunction(int, int);
void RenderFunction(void);
void IdleFunction(void);
void CreateShaders(void);
// set up an array for the geometry of the object
GLfloat Vertices[] = {
-0.5f , -0.2f , 0.0f, // point A - x , y , z
0.5f , -0.2f , 0.0f, // point B - x , y , z
0.0f , 0.8f , 0.0f // point C - x , y , z
};
GLfloat Colors[] = {
1.0f , 0.0f , 0.0f, // point A - x , y , z
0.0f , 1.0f , 0.0f, // point B - x , y , z
0.0f , 0.0f , 1.0f // point C - x , y , z
};
int main( int argc , char* argv[] )
{
glutInit( &argc , argv);
//Target version 3.1
glutInitContextVersion(3 , 1 );
glutInitWindowSize(CurrentWidth, CurrentHeight);
glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA );
WindowHandle = glutCreateWindow( "OpenGL - Shader example" );
glutReshapeFunc( ResizeFunction );
glutDisplayFunc( RenderFunction );
glutIdleFunc( IdleFunction );
/// init GLEW
GLenum GlewInitResult;
GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult)
exit(EXIT_FAILURE);
/// Create our shaders
CreateShaders();
glutMainLoop();
exit(EXIT_SUCCESS);
}
void ResizeFunction(int Width, int Height)
{
CurrentWidth = Width;
CurrentHeight = Height;
glViewport( 0, 0, CurrentWidth, CurrentHeight );
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
}
void RenderFunction(void)
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//We enable the shader variable
glEnableVertexAttribArray( s_vertexLoc );
glEnableVertexAttribArray( s_colorLoc );
//How to send data to the variable:
//( Where to send the data , how its grouped , data type , dont normalize the data,
// there is no offset, you find it here)
glVertexAttribPointer( s_vertexLoc , 3 , GL_FLOAT , GL_FALSE , 0 , Vertices );
glVertexAttribPointer ( s_colorLoc , 3 , GL_FLOAT , GL_FALSE , 0 , Colors);
glUniform1f( s_factorLoc , runner );
runner += 0.01;
if(runner > 1.0f)
runner = -1.0f;
glDrawArrays( GL_TRIANGLES , 0 , 3 );
glDisableVertexAttribArray( s_vertexLoc );
glDisableVertexAttribArray( s_colorLoc );
glutSwapBuffers();
}
void IdleFunction(void)
{
glutPostRedisplay();
}
//Error checking
void printLog(GLuint obj)
{
int infologLength = 0;
int maxLength;
if( glIsShader( obj ) )
glGetShaderiv( obj , GL_INFO_LOG_LENGTH , &maxLength );
else
glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &maxLength);
char infoLog[1255];
if ( glIsShader(obj) )
glGetShaderInfoLog( obj, maxLength, &infologLength, infoLog );
else
glGetProgramInfoLog( obj, maxLength, &infologLength, infoLog );
if ( infologLength > 0 )
printf( "\n Error detail: %s\n" , infoLog );
}
void CreateShaders(void)
{
GLenum ErrorCheckValue = glGetError();
if( glCreateShader )
printf(" ---- shader suppot ok ---");
else
{
printf(" ---- no shader support ---");
return ;
}
///The VERTEX shader is created (tell it what it is)
VertexShaderId = glCreateShader( GL_VERTEX_SHADER );
//(shader we want to set the source, how many are they, the source of the shader , )
glShaderSource( VertexShaderId , 1 , &VertexShader , nullptr );
//Compile the shader
glCompileShader( VertexShaderId );
//Error checking
printLog( VertexShaderId );
///The FRAGMENT shader is created (tell it what it is)
FragmentShaderId = glCreateShader( GL_FRAGMENT_SHADER );
//(shader we want to set the source, how many are they, the source of the shader , )
glShaderSource( FragmentShaderId , 1 , &FragmentShader , nullptr );
//Compile the shader
glCompileShader( FragmentShaderId );
//Error checking
printLog( FragmentShaderId );
///Program Object links both shaders
ProgramId = glCreateProgram();
//Attach the compiled shaders to the program
glAttachShader( ProgramId , VertexShaderId );
glAttachShader( ProgramId , FragmentShaderId );
//Links the shaders to the program
glLinkProgram( ProgramId );
//Error checking
printLog( ProgramId );
//Uses the program to render
glUseProgram( ProgramId );
//( check this program , for this variable and return it)
s_vertexLoc = glGetAttribLocation( ProgramId , "in_vertex" );
s_colorLoc = glGetAttribLocation( ProgramId , "in_color" );
s_factorLoc = glGetUniformLocation( ProgramId , "factor" );
}
You have several issues.
First, using OpenGL 3.1 (GLSL 1.30) is discouraged. Try with at least
3.2 (GLSL 1.50) and ask for that Core Profile in your glut initialization. Then replace "attribute" with "in" in your
vertex shader and "varying" with "in" or "out" depending
if this var is going to be used as an input or an output.
Second. This
//How to send data to the variable:
//( Where to send the data , how its grouped , data type , dont normalize the data,
// there is no offset, you find it here)
glVertexAttribPointer( s_vertexLoc , 3 , GL_FLOAT , GL_FALSE , 0 , Vertices );
glVertexAttribPointer ( s_colorLoc , 3 , GL_FLOAT , GL_FALSE , 0 , Colors);
is not true. That last value is a byte offset into the buffer object's data store, not the data itself.
Third: You need a buffer for your vertices coordinates. Use
glGenBuffers(), glBufferData(), and glBindBuffer()
If I were in your case I'd follow some tutorial on "modern OpenGL". Search the web, there are a lot.