I was trying to create an OpenGL application which simply draws a triangle, but im getting Linker error: linking with uncompiled shader. from the call to glLinkProgram:
#include <GL/glew.h>
#include <GL/glut.h>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <assert.h>
using namespace std;
GLuint VBO;
void draw();
void CreateVBO();
GLuint MakeShader(const string& shaderFile);
GLuint CreateProgram();
string GetCode(const string& path);
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(768, 512);
glutInitWindowPosition(0, 0);
glutCreateWindow("Test");
glutDisplayFunc(draw);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLenum var = glewInit();
if(var != GLEW_OK){
cerr << "Couldn't initialize glew" << endl;
return -1;
}
CreateVBO();
glutMainLoop();
return 0;
}
void draw(){
glClear(GL_COLOR_BUFFER_BIT);
static GLuint program = CreateProgram();
glUseProgram(program);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
GLuint CreateProgram(){
GLuint program = glCreateProgram();
vector<GLuint> shaders;
shaders.push_back(MakeShader("shade.frag"));
shaders.push_back(MakeShader("shader.vert"));
for(size_t i = 0; i!= shaders.size(); ++i){
glAttachShader(program, shaders[i]);
}
glLinkProgram(program);
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if(linked == GL_FALSE){
GLint infoLogLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* strInfoLog = new GLchar[infoLogLength+1];
glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
printf("Linker failure: %s \n", strInfoLog);
delete strInfoLog;
}
return program;
}
string GetCode(const string &path){
ifstream file(path);
string ret = "";
string line;
if(file.is_open()){
while(getline(file, line)){
ret += line + '\n';
}
}
return ret;
}
GLuint MakeShader(const string& shaderFile){
string extension = shaderFile.substr(shaderFile.length()-4, 4);
GLenum type;
string shaderType;
if(extension == "vert")
{
type = GL_VERTEX_SHADER;
shaderType = "Vertex";
}
else if(extension == "frag")
{
type = GL_FRAGMENT_SHADER;
shaderType = "Fragment";
}
const char* code = (GetCode(shaderFile)).c_str();
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &code, NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status != GLEW_OK){
GLint logSize;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize);
GLchar* errorLog = new GLchar[logSize+1];
glGetShaderInfoLog(shader, logSize, NULL, errorLog);
printf("Compile failed in %s shader: %s \n", shaderType.c_str(), errorLog);
delete errorLog;
}
return shader;
}
void CreateVBO(){
float Vertices[12]= {
0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f
};
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
I'm sorry if my question is noobish, but i'm sort of struggling with OpenGL
You are incorrectly checking for shader compilation success. You compare GL_COMPILE_STATUS against GLEW_OK (which is 0 and has nothing to do with OpenGL), while you should compare with GL_TRUE (which is 1). Also the code does not do anything besides reporting the failure to stdout (i.e. there is no way for the caller to know if it failed or succeeded).
Related
After several tests I still don't see my red triangle, what am I doing wrong? It's funny because it is not the first time for me to work with OpenGL, and I am pretty sure I am not missing any setup step. Here is a code snippet:
GLFWwindow* window;
glfwSetErrorCallback(onError);
if ( !glfwInit() ) {
std::cout << "glfwInit() failed." << std::endl;
return;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow( GetWindowWidth(), GetWindowHeight(), "The Game", NULL, NULL );
if ( !window )
{
std::cout << "couldn't create a proper window, exiting." << std::endl;
glfwTerminate();
return;
}
glfwSetKeyCallback( window, handleKeysEvents );
glfwMakeContextCurrent( window );
gladLoadGL(); // no glfwGetProcAddress required
glfwSwapInterval(1);
/// init opengl things ...
GLuint VAO, VBO, program;
GLuint VertexShader, FragmentShader;
VertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(VertexShader, 1, &vertex_shader_text, NULL);
glCompileShader(VertexShader);
GLint isCompiled = 0;
glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(VertexShader, GL_INFO_LOG_LENGTH, &maxLength);
std::cout << "ERROR IN COMPILING VERTEX SHADER." << std::endl;
// The maxLength includes the NULL character
std::vector<GLchar> errorLog(maxLength);
glGetShaderInfoLog(VertexShader, maxLength, &maxLength, &errorLog[0]);
for ( int i = 0; i < errorLog.size(); ++i )
std::cout << errorLog[i];
glDeleteShader(VertexShader); // Don't leak the shader.
return;
}
FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(FragmentShader, 1, &fragment_shader_text, NULL);
glCompileShader(FragmentShader);
isCompiled = 0;
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(FragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
std::cout << "ERROR IN COMPILING VERTEX SHADER." << std::endl;
// The maxLength includes the NULL character
std::vector<GLchar> errorLog(maxLength);
glGetShaderInfoLog(FragmentShader, maxLength, &maxLength, &errorLog[0]);
for ( int i = 0; i < errorLog.size(); ++i )
std::cout << errorLog[i];
glDeleteShader(FragmentShader); // Don't leak the shader.
return;
}
program = glCreateProgram();
glAttachShader(program, VertexShader);
glAttachShader(program, FragmentShader);
glLinkProgram(program);
// Note the different functions here: glGetProgram* instead of glGetShader*.
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
if (isLinked == GL_FALSE)
{
std::cout << "ERROR IN LINKING PROGRAM." << std::endl;
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
// We don't need the program anymore.
glDeleteProgram(program);
// Don't leak shaders either.
glDeleteShader(VertexShader);
glDeleteShader(FragmentShader);
// Use the infoLog as you see fit.
for ( int i = 0; i < infoLog.size(); ++i )
std::cout << infoLog[i];
// In this simple program, we'll just leave
return;
}
glDeleteShader(VertexShader);
glDeleteShader(FragmentShader);
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_VERTEX_ARRAY, VBO);
glBufferData(GL_VERTEX_ARRAY, sizeof(vertices), reinterpret_cast<const void*>(vertices), GL_STATIC_DRAW);
glBindBuffer(GL_VERTEX_ARRAY, 0);
glBindBuffer(GL_VERTEX_ARRAY, VBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glBindBuffer(GL_VERTEX_ARRAY, 0);
glBindVertexArray(0);
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
while( !glfwWindowShouldClose(window) )
{
Float wWidth = GetWindowWidth();
Float wHeight = GetWindowHeight();
glViewport(0, 0, (GLsizei)wWidth, (GLsizei)wHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
std::cout << "closing the game." << std::endl;
return;
And here are the shaders:
Vertex Shader:
#version 460 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos, 1.0f);
}
And fragment shader:
#version 460 core
out vec4 FragCol;
void main()
{
FragCol = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
OpenGL context is created, in fact clearing the screen with a specific color works just fine. I just don't get to see my triangle on the screen, any suggestions?
GL_VERTEX_ARRAY is not a valid buffer type. GL_VERTEX_ARRAY is a client-side capability (fixed function attribute, legacy OpenGL). The buffer type for vertex attributes is GL_ARRAY_BUFFER:
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), reinterpret_cast<const void*>(vertices), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
I'm actually learning OpenGL3.3 to create a multiplatform application, which draws some sprites.
Currently, I'm struggling at the compilation of vertexShader and fragShader. The OpenGL shows me information, that my device doesn't support the 3.3 version. When It's clear that it supports it.
main.cpp
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <string>
#include <fstream>
#include <sstream>
#include <filesystem>
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f};
std::string readFile(const std::string &fileLoc)
{
std::ifstream file;
file.open(fileLoc, std::ios::in);
std::stringstream contex;
if (!file.fail())
{
contex << file.rdbuf();
}
return contex.str();
}
GLuint createandComplieShader(const std::string &fileLoc, GLuint shaderType)
{
GLuint shader = glCreateShader(shaderType);
std::string shaderString = readFile(fileLoc);
const char *ShaderSource = shaderString.c_str();
glShaderSource(shader, 1, &ShaderSource, nullptr);
glCompileShader(shader);
int success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
char infoLog[512];
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
std::cerr << "Shader Error :" << infoLog << std::endl;
exit(-1);
}
return shader;
}
GLuint createAndLinkShader()
{
std::string path = std::filesystem::current_path();
std::string VertexShader = "/vertShader.vert" ;
std::string FragmentShader = "/fragShader.vert";
GLuint vertexShader = createandComplieShader(path + VertexShader , GL_VERTEX_SHADER);
GLuint fragmentShader = createandComplieShader(path + FragmentShader , GL_FRAGMENT_SHADER);
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
int succes;
glGetProgramiv(program, GL_LINK_STATUS, &succes);
if (!succes)
{
char infoLog[512];
glGetProgramInfoLog(program, 512, nullptr, infoLog);
std::cerr << "Linking Error: " << infoLog << std::endl;
exit(-2);
}
return program;
}
int main(int argc, char **argv)
{
if (!glfwInit())
{
std::cerr << "GLFW init failed..." << std::endl;
return -1;
}
GLFWwindow *window = glfwCreateWindow(1280, 720, "A-Engine", nullptr, nullptr);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
if (window == nullptr)
{
std::cerr << "Window init failed..." << std::endl;
glfwTerminate();
return -2;
}
glfwMakeContextCurrent(window);
// glfwSetKeyCallback (window, HandleKeyInput);
if (glewInit() != GLEW_OK)
{
std::cerr << "Glew init failed..." << std::endl;
glfwDestroyWindow(window);
glfwTerminate();
return -3;
}
glClearColor(0.2f, 0.2f, 0.45f, 1.0f);
GLuint ShaderProgram = createAndLinkShader();
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
int width;
int height;
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glUseProgram(ShaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(ShaderProgram);
glfwDestroyWindow(window);
return EXIT_SUCCESS;
}
fragShader.vert
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
vertShader.vert
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
The main binary file is located under this same folder as vertShader and fragShader
Shader Error :ERROR: 0:1: '' : version '330' is not supported
ERROR: 0:1: '' : syntax error: #version
ERROR: 0:2: 'layout' : syntax error: syntax error
As per the comment, at the very least you should set the glfw window hints before creating the window. So the window creation code in main should probably be...
if (!glfwInit())
{
std::cerr << "GLFW init failed..." << std::endl;
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
GLFWwindow *window = glfwCreateWindow(1280, 720, "A-Engine", nullptr, nullptr);
.
.
.
Otherwise the OpenGL version associated with the newly created context can be anything (as far as I'm aware).
I have this OpenGL program, a fragment shader, and a vertex shader.
This is the program source
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "ogldev_util.h"
#include "ogldev_math_3d.h"
GLuint VBO;
const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";
static void RenderSceneCB()
{
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
static void InitializeGlutCallbacks()
{
glutDisplayFunc(RenderSceneCB);
}
static void CreateVertexBuffer()
{
Vector3f Vertices[3];
Vertices[0] = Vector3f(-1.0f, -1.0f, 0.0f);
Vertices[1] = Vector3f(1.0f, -1.0f, 0.0f);
Vertices[2] = Vector3f(0.0f, 1.0f, 0.0f);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
GLuint ShaderObj = glCreateShader(ShaderType);
if (ShaderObj == 0) {
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
exit(0);
}
const GLchar* p[1];
p[0] = pShaderText;
GLint Lengths[1];
Lengths[0]= strlen(pShaderText);
glShaderSource(ShaderObj, 1, p, Lengths);
glCompileShader(ShaderObj);
GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar InfoLog[1024];
glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
exit(1);
}
glAttachShader(ShaderProgram, ShaderObj);
}
static void CompileShaders()
{
GLuint ShaderProgram = glCreateProgram();
if (ShaderProgram == 0) {
fprintf(stderr, "Error creating shader program\n");
exit(1);
}
string vs, fs;
if (!ReadFile(pVSFileName, vs)) {
exit(1);
};
if (!ReadFile(pFSFileName, fs)) {
exit(1);
};
AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);
GLint Success = 0;
GLchar ErrorLog[1024] = { 0 };
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
if (Success == 0) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
exit(1);
}
glValidateProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
if (!Success) {
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
exit(1);
}
glUseProgram(ShaderProgram);
}
int main(int argc, char** argv)
{
glutInitContextVersion(3, 3);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize(1024, 768);
glutInitWindowPosition(100, 100);
glutCreateWindow("Tutorial 04");
InitializeGlutCallbacks();
// Must be done after glut is initialized!
GLenum res = glewInit();
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
printf("GL version: %s\n", glGetString(GL_VERSION));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
CreateVertexBuffer();
CompileShaders();
glutMainLoop();
return 0;
}
This vertex shader
#version 330 core
layout (location = 0) in vec3 Position;
void main()
{
gl_Position = vec4(0.5 * Position.x, 0.5 * Position.y, Position.z, 1.0);
}
and this fragment shader
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
The result is a black screen And i wonder why
Is somebody having an hint ?
(I'm using an integrated Intel GPU)
Vertex Array Objects (VAOs) are capital-R Required in Core contexts.
Make sure you create/bind/populate one before attempting to glDraw*().
This question already has an answer here:
Linking with uncompiled shader in Ubuntu
(1 answer)
Closed 8 years ago.
I've only recently started learning OpenGL and i can't figure out what is wrong with the following code. The error that I am getting is: "Error compiling shader type 35633: '0(1) : error C0000: syntax error, unexpected, '.', expecting "::" at token "."
#include <iostream>
#include <stdio.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#pragma comment(lib, "glew32.lib")
using namespace std;
struct Vector3f
{
float x;
float y;
float z;
Vector3f()
{
}
Vector3f(float _x, float _y, float _z)
{
x = _x;
y = _y;
z = _z;
}
};
GLuint VBO;
const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";
static void RenderSceneCB()
{
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
}
static void InitializeGlutCallbacks()
{
glutDisplayFunc(RenderSceneCB);
}
static void CreateVertexBuffer()
{
Vector3f Vertices[3];
Vertices[0] = Vector3f(-1.0f, -1.0f, 0.0f);
Vertices[1] = Vector3f(1.0f, -1.0f, 0.0f);
Vertices[2] = Vector3f(0.0f, 1.0f, 0.0f);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
GLuint ShaderObj = glCreateShader(ShaderType);
if (ShaderObj == 0)
{
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
exit(0);
}
const GLchar* p[1];
p[0] = pShaderText;
cout << "p[0] :" << pShaderText << endl;
GLint Lengths[1];
Lengths[0] = strlen(pShaderText);
cout << "Lengths[0] :" << Lengths[0] << endl;
glShaderSource(ShaderObj, 1, p, Lengths);
glCompileShader(ShaderObj);
GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
if (!success)
{
GLchar InfoLog[1024];
glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
exit(1);
}
glAttachShader(ShaderProgram, ShaderObj);
}
static void CompileShaders()
{
GLuint ShaderProgram = glCreateProgram();
if (ShaderProgram == 0)
{
fprintf(stderr, "Error creating shader program\n");
exit(1);
}
const char* vs = "shader.vs";
const char* fs = "shader.fs";
AddShader(ShaderProgram, vs, GL_VERTEX_SHADER);
AddShader(ShaderProgram, fs, GL_FRAGMENT_SHADER);
GLint Success = 0;
GLchar ErrorLog[1024] = { 0 };
glLinkProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
if (Success == 0)
{
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
exit(1);
}
glValidateProgram(ShaderProgram);
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
if (!Success)
{
glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
exit(1);
}
glUseProgram(ShaderProgram);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(1024, 768);
glutInitWindowPosition(100, 100);
glutCreateWindow("Tutorial 04");
InitializeGlutCallbacks();
GLenum res = glewInit();
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
printf("GL version: %s\n", glGetString(GL_VERSION));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
CreateVertexBuffer();
CompileShaders();
glutMainLoop();
return 0;
}
The shaders are the following:
#version 330
layout (location = 0) in vec3 Position;
void main()
{
gl_Position = vec4(0.5 * Position.x, 0.5 * Position.y, Position.z, 1.0);
}
and
#version 330
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Thanks in advance!
You aren't actually loading the contents of the shaders. Instead, you're passing vs and fs, which are the names of the shader files, to AddShader. This tries to compile the names as though they were shader programs.
You need to load the contents of the shader files first and then pass that to AddShader (or do the loading inside AddShader, but then pShaderText should be named pShaderFileName).
I am trying to render the model in two windows in glut. But it is rendered in only one of the windows. Is it possible to render in two windows with different callback functions?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#define WINDOW_TITLE_PREFIX "Chapter 2"
int CurrentWidth = 800,
CurrentHeight = 600,
WindowHandle = 0;
unsigned FrameCount = 0;
GLuint
VertexShaderId,
FragmentShaderId,
ProgramId,
VaoId,
VboId,
ColorBufferId;
const GLchar* VertexShader =
{
"#version 400\n"\
"layout(location=0) in vec4 in_Position;\n"\
"layout(location=1) in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\
"void main(void)\n"\
"{\n"\
" gl_Position = in_Position;\n"\
" ex_Color = in_Color;\n"\
"}\n"
};
const GLchar* FragmentShader =
{
"#version 400\n"\
"in vec4 ex_Color;\n"\
"out vec4 out_Color;\n"\
"void main(void)\n"\
"{\n"\
" out_Color = ex_Color;\n"\
"}\n"
};
void Initialize(int, char*[]);
void InitWindow(int, char*[]);
void ResizeFunction(int, int);
void ResizeFunction1(int, int);
void RenderFunction(void);
void RenderFunction1(void);
void TimerFunction(int);
void TimerFunction1(int);
void IdleFunction(void);
void IdleFunction1(void);
void Cleanup(void);
void CreateVBO(void);
void DestroyVBO(void);
void CreateShaders(void);
void DestroyShaders(void);
int Wh1;
int main(int argc, char* argv[])
{
Initialize(argc, argv);
glutMainLoop();
exit(EXIT_SUCCESS);
}
void Initialize(int argc, char* argv[])
{
GLenum GlewInitResult;
InitWindow(argc, argv);
glewExperimental = GL_TRUE;
GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult) {
fprintf(
stderr,
"ERROR: %s\n",
glewGetErrorString(GlewInitResult)
);
exit(EXIT_FAILURE);
}
fprintf(
stdout,
"INFO: OpenGL Version: %s\n",
glGetString(GL_VERSION)
);
CreateShaders();
CreateVBO();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
void InitWindow(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitContextVersion(4, 0);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
glutInitWindowSize(CurrentWidth, CurrentHeight);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX);
std::cout<<WindowHandle<<std::endl;
if(WindowHandle < 1) {
fprintf(
stderr,
"ERROR: Could not create a new rendering window.\n"
);
exit(EXIT_FAILURE);
}
glutSetWindow(WindowHandle);
glutReshapeFunc(ResizeFunction);
glutDisplayFunc(RenderFunction);
glutTimerFunc(0, TimerFunction, 0);
glutCloseFunc(Cleanup);
#if 1
Wh1 = glutCreateWindow("sasd");
// std::cout<<i<<"s"<<std::endl;
glutReshapeFunc(ResizeFunction1);
glutDisplayFunc(RenderFunction1);
glutTimerFunc(0, TimerFunction1, 0);
glutCloseFunc(Cleanup);
glutSetWindow(Wh1);
#endif
}
void ResizeFunction(int Width, int Height)
{
CurrentWidth = Width;
CurrentHeight = Height;
glViewport(0, 0, CurrentWidth, CurrentHeight);
}
void ResizeFunction1(int Width, int Height)
{
CurrentWidth = Width;
CurrentHeight = Height;
glViewport(0, 0, CurrentWidth, CurrentHeight);
}
void RenderFunction(void)
{
++FrameCount;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
glutSetWindow(WindowHandle);
glutPostRedisplay();
glutSetWindow(Wh1);
glutPostRedisplay();
}
void RenderFunction1(void)
{
++FrameCount;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
glutSetWindow(WindowHandle);
glutPostRedisplay();
glutSetWindow(Wh1);
glutPostRedisplay();
}
void IdleFunction(void)
{
glutSetWindow(WindowHandle);
glutPostRedisplay();
glutSetWindow(Wh1);
glutPostRedisplay();
}
void IdleFunction1(void)
{
glutSetWindow(WindowHandle);
glutPostRedisplay();
glutSetWindow(Wh1);
glutPostRedisplay();
}
void TimerFunction(int Value)
{
if (0 != Value) {
char* TempString = (char*)
malloc(512 + strlen(WINDOW_TITLE_PREFIX));
sprintf(
TempString,
"%s: %d Frames Per Second # %d x %d",
WINDOW_TITLE_PREFIX,
FrameCount * 4,
CurrentWidth,
CurrentHeight
);
//glutSetWindowTitle(TempString);
free(TempString);
}
FrameCount = 0;
glutTimerFunc(250, TimerFunction, 1);
}
void TimerFunction1(int Value)
{
if (0 != Value) {
char* TempString = (char*)
malloc(512 + strlen(WINDOW_TITLE_PREFIX));
sprintf(
TempString,
"%s: %d Frames Per Second # %d x %d",
WINDOW_TITLE_PREFIX,
FrameCount * 4,
CurrentWidth,
CurrentHeight
);
//glutSetWindowTitle(TempString);
free(TempString);
}
FrameCount = 0;
glutTimerFunc(250, TimerFunction, 1);
}
void Cleanup(void)
{
DestroyShaders();
DestroyVBO();
}
void CreateVBO(void)
{
GLfloat Vertices[] = {
-0.8f, -0.8f, 0.0f, 1.0f,
0.0f, 0.8f, 0.0f, 1.0f,
0.8f, -0.8f, 0.0f, 1.0f
};
GLfloat Colors[] = {
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f
};
GLenum ErrorCheckValue = glGetError();
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
glGenBuffers(1, &VboId);
glBindBuffer(GL_ARRAY_BUFFER, VboId);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glGenBuffers(1, &ColorBufferId);
glBindBuffer(GL_ARRAY_BUFFER, ColorBufferId);
glBufferData(GL_ARRAY_BUFFER, sizeof(Colors), Colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not create a VBO: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
void DestroyVBO(void)
{
GLenum ErrorCheckValue = glGetError();
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &ColorBufferId);
glDeleteBuffers(1, &VboId);
glBindVertexArray(0);
glDeleteVertexArrays(1, &VaoId);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not destroy the VBO: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
void CreateShaders(void)
{
GLenum ErrorCheckValue = glGetError();
VertexShaderId = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(VertexShaderId, 1, &VertexShader, NULL);
glCompileShader(VertexShaderId);
FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL);
glCompileShader(FragmentShaderId);
ProgramId = glCreateProgram();
glAttachShader(ProgramId, VertexShaderId);
glAttachShader(ProgramId, FragmentShaderId);
glLinkProgram(ProgramId);
glUseProgram(ProgramId);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not create the shaders: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
void DestroyShaders(void)
{
GLenum ErrorCheckValue = glGetError();
glUseProgram(0);
glDetachShader(ProgramId, VertexShaderId);
glDetachShader(ProgramId, FragmentShaderId);
glDeleteShader(FragmentShaderId);
glDeleteShader(VertexShaderId);
glDeleteProgram(ProgramId);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not destroy the shaders: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
glutDisplayFunc, and all of the other callbacks, set callbacks for whatever window is current at the time the function is called. So if you want to set the display callback for a certain window, call glutDisplayFunc after calling glutSetWindow.
I figured out the problem that gldrawArrays requires to create new vbo to redraw. i dunno why.
That's because each window represents a separate OpenGL context. Unless you explicitly share objects (via a platform-specific call), then each context will have its own, separate objects. You can't use buffers created in one in another, without explicitly sharing (and doing so before creating objects in the new context).
Opengl functions are not thread safe. So gldrawArrays in multiple windows might be running in two threads. SO their behaviour is undefined.