I need help with some OpenGL code I am trying to create. Essentially I am trying to create a triangle that is colored green.
Below is the environment, error and code. Can someone please help ?
Env:
Mac OS: High Sierra
Video : Intel HD Graphics 4000 1536 MB graphics
Error Message:
2018-11-14 20:25:46.416648-0800 GLFW opengl[41517:6223602] MessageTracer: load_domain_whitelist_search_tree:73: Search tree file's format version number (0) is not supported
2018-11-14 20:25:46.416773-0800 GLFW opengl[41517:6223602] MessageTracer: Falling back to default whitelist
INFO: OpenGL Version: 2.1 INTEL-10.36.19/n
ERROR: 0:1: '' : Invalid Directive: version440
ERROR: 0:2: '(' : syntax error: syntax error
code :
#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sstream>
#include <iostream>
#include "glew.h"
#include "freeglut.h" // Include the freeGLUT header file
using namespace std;
#define WINDOW_TITLE "Modern OpenGL"
#ifndef GLSL
#define GLSL(Version, source) "#version" #Version "\n" #source
#endif
int WindowWidth = 800, WindowHeight = 600;
void UInitialize(int,char*[]);
void UInitWindow(int,char*[]);
void UResizeWindow(int,int);
void URenderGraphics(void);
void UCreateVBO(void);
void UCreateShaders(void);
const GLchar * VertexShader = GLSL(440,
in layout(location=0) vec4 vertex_Postion;
void main(){
gl_Postion = vertex_Postion;
}
);
const GLchar * FragmentShader = GLSL(440,
void main(){
gl_FragColor = vec4(0.0f,1.0f,0.0f,1.0f);
}
);
int main(int argc, char* argv[]){
UInitialize(argc, argv);
glutMainLoop();
exit(EXIT_SUCCESS);
}
void UInitialize(int argc, char* argv[]){
GLenum GlewInitResult;
UInitWindow(argc, argv);
GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult) {
fprintf(stderr,"ERROR:%s/n",glewGetErrorString(GlewInitResult));
}
fprintf(stdout, "INFO: OpenGL Version: %s/n",glGetString(GL_VERSION));
UCreateVBO();
UCreateShaders();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
void UInitWindow(int argc, char* argv[]){
glutInit(&argc,argv);
glutInitWindowSize(WindowWidth, WindowHeight);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutCreateWindow(WINDOW_TITLE);
glutReshapeFunc(UResizeWindow);
glutDisplayFunc(URenderGraphics);
}
void UResizeWindow(int width, int height){
glViewport(0, 0, width, height);
}
void URenderGraphics(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLuint totalVertices = 3;
//creates tirangle
glDrawArrays(GL_TRIANGLES, 0, totalVertices);
glutSwapBuffers();
}
void UCreateVBO(void){
GLfloat verts[]={
0.0f,1.0f,
-1.0f,-1.0f,
1.0f,-1.0f
};
float numVertices = sizeof(verts);
GLuint myBufferID;
glGenBuffers(1,&myBufferID);
glBindBuffer(GL_ARRAY_BUFFER,myBufferID);
glBufferData(GL_ARRAY_BUFFER,numVertices,verts,GL_STATIC_DRAW);
GLuint floatsPerVertex = 2;
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,floatsPerVertex,GL_FLOAT,GL_FALSE,0,0);
}
void UCreateShaders(void){
GLuint ProgramId = glCreateProgram();
GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertexShaderId,1,&VertexShader,NULL);
glShaderSource(fragmentShaderId,1,&FragmentShader,NULL);
glCompileShader(vertexShaderId);
glCompileShader(fragmentShaderId);
GLint isCompiled = 0;
glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &isCompiled);
char *infoLog;
int infologLength = 0;
int charsWritten = 0;
if(isCompiled == GL_FALSE)
{
glGetShaderiv(vertexShaderId, GL_INFO_LOG_LENGTH, &infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetShaderInfoLog(vertexShaderId, infologLength, &charsWritten, infoLog);
printf("\n%s\n",infoLog);
free(infoLog);
}
// Provide the infolog in whatever manor you deem best.
// Exit with failure.
glDeleteShader(vertexShaderId); // Don't leak the shader.
return;
}
fprintf(stdout, "OK!!!!!!!!!");
glAttachShader(ProgramId,vertexShaderId);
glAttachShader(ProgramId,fragmentShaderId);
glLinkProgram(ProgramId);
glUseProgram(ProgramId);
}
Read the error message:
ERROR: 0:1: '' : Invalid Directive: version440
ERROR: 0:2: '(' : syntax error: syntax error
this is caused, because the first line in your shader code is:
#version440
but the correct syntax would be #version 440.
This line is automatically generated by the macro GLSL. You have to insert a blank at the end of "#version", so it has to be:
#ifndef GLSL
#define GLSL(Version, source) "#version " #Version "\n" #source
#endif
There is a typo in you vertex shader program. It has to be gl_Position instead of gl_Postion.
You have to check the compilation state of the vertex shader and fragment shader separately:
GLint isCompiled = 0;
glCompileShader(vertexShaderId);
glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &isCompiled);
if ( isCompiled == GL_FALSE )
{
GLint infologLength;
glGetShaderiv(vertexShaderId, GL_INFO_LOG_LENGTH, &infologLength);
std::vector< char >infoLog(infologLength);
GLsizei charsWritten;
glGetShaderInfoLog(vertexShaderId, infologLength, &charsWritten, infoLog.data());
std::cout << "compile error:" << std::endl << infoLog.data() << std::endl;
// .....
}
glCompileShader(fragmentShaderId);
glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &isCompiled);
if ( isCompiled == GL_FALSE )
{
GLint infologLength;
glGetShaderiv(fragmentShaderId, GL_INFO_LOG_LENGTH, &infologLength);
std::vector< char >infoLog(infologLength);
GLsizei charsWritten;
glGetShaderInfoLog(fragmentShaderId, infologLength, &charsWritten, infoLog.data());
std::cout << "compile error:" << std::endl << infoLog.data() << std::endl;
// .....
}
Related
Simple and short question but I don't know why it is not working. When I call glViewport in the window frame buffer callback nothing changes. Error code is 1282 (0x502). I already googled and found no helpful article. Some said I should use glScissor in addition but does not work either.
Here an MCVE with an oscillating quad for visualization:
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "glm/vec3.hpp"
#include <thread>
#include <iostream>
#include <vector>
#include <chrono>
#include <Windows.h>
#include <wingdi.h>
int createShaders() {
const char* vertex = R"(
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
uniform float scale;
void main() {
gl_Position = vec4(vertexPosition_modelspace, 1.0) * vec4(vec3(scale), 1.0f);
}
)";
const char* fragment = R"(
#version 330 core
void main() {
gl_FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
)";
int vertexID, fragmentID, pid;
vertexID = glCreateShader(GL_VERTEX_SHADER);
const GLchar* source = (const GLchar*)vertex;
glShaderSource(vertexID, 1, &source, 0);
glCompileShader(vertexID);
int isCompiled = 0;
glGetShaderiv(vertexID, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
int maxLength = 0;
glGetShaderiv(vertexID, GL_INFO_LOG_LENGTH, &maxLength);
char* infoLog = new char[maxLength];
glGetShaderInfoLog(vertexID, maxLength, &maxLength, infoLog);
std::cout << infoLog << std::endl;
glDeleteShader(vertexID);
return 0;
}
fragmentID = glCreateShader(GL_FRAGMENT_SHADER);
source = (const GLchar*)fragment;
glShaderSource(fragmentID, 1, &source, 0);
glCompileShader(fragmentID);
glGetShaderiv(fragmentID, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
int maxLength = 0;
glGetShaderiv(fragmentID, GL_INFO_LOG_LENGTH, &maxLength);
char* infoLog = new char[maxLength];
glGetShaderInfoLog(fragmentID, maxLength, &maxLength, infoLog);
std::cout << infoLog << std::endl;
glDeleteShader(fragmentID);
glDeleteShader(vertexID);
return 0;
}
pid = glCreateProgram();
glAttachShader(pid, vertexID);
glAttachShader(pid, fragmentID);
glLinkProgram(pid);
int isLinked = 0;
glGetProgramiv(pid, GL_LINK_STATUS, (int*)&isLinked);
if (isLinked == GL_FALSE)
{
int maxLength = 0;
glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(pid, maxLength, &maxLength, &infoLog[0]);
glDeleteProgram(pid);
glDeleteShader(vertexID);
glDeleteShader(fragmentID);
return 0;
}
glDetachShader(pid, vertexID);
glDetachShader(pid, fragmentID);
return pid;
}
unsigned int createVertexArray() {
std::vector<glm::vec3> vertices = {
glm::vec3(0.5f, 0.5f, 0.0f),
glm::vec3(0.5f, -0.5f, 0.0f),
glm::vec3(-0.5f, -0.5f, 0.0f),
glm::vec3(-0.5f, 0.5f, 0.0f)
};
unsigned int arrayID, id;
glGenVertexArrays(1, &arrayID);
glBindVertexArray(arrayID);
glGenBuffers(1, &id);
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
return arrayID;
}
int main() {
if (!glfwInit())
return 1;
GLFWwindow* window = glfwCreateWindow(960, 520, "MCVE", NULL, NULL);
glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
});
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
return 1;
wglMakeCurrent(NULL, NULL);
std::thread mainLoopThread([window]() {
glfwMakeContextCurrent(window);
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
int shaderID = createShaders();
int vertexID = createVertexArray();
while (!glfwWindowShouldClose(window)) {
std::chrono::steady_clock::time_point current = std::chrono::steady_clock::now();
std::chrono::microseconds time = std::chrono::duration_cast<std::chrono::microseconds>(current - start);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderID);
float s = sin(time.count() / 1000000.0f * 2.0f);
glUniform1f(glGetUniformLocation(shaderID, "scale"), s);
glBindVertexArray(vertexID);
glDrawArrays(GL_QUADS, 0, 4);
glfwSwapBuffers(window);
}
});
while (!glfwWindowShouldClose(window))
glfwWaitEvents();
mainLoopThread.join();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
You try to call a OpenGL instruction without a current OpenGL Context.
The callback is executed in the main thread. However the OpenGL Context is not current in the main thread. The OpenGL context is current in the mainLoopThread thread.
Set a state in the callback function (e.g. std::atomic<bool>) and invoke glViewport in the mainLoopThread thread, once the state is set.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have been following the Modern Opengl Tutorials on YouTube by Nico Cvitak to help me transition from SDL to OpenGl/GLFW; here is a link to the lesson I can't get to work: [https://www.youtube.com/watch?v=2K_R4C1UP-c][1]
Here is my code:
myVertexShader.vs
#version 150 core
in vec2 v_pos;
void main()
{
gl_Position = vec4(v_pos, 0.0, 1.0);
}
myFragmentShader.fs
#version 150 core
out vec4 fragData;
void main()
{
fragData = vec4(1.0, 1.0, 1.0, 1.0);
}
main.cpp
#define GLFW_INCLUDE_GLCOREARB
#include <iostream>
#include <GLFW/glfw3.h>
#include <OpenGL/OpenGL.h>
#include "ShaderUtils.h"
int main(int argc, const char * argv[])
{
GLFWwindow * window;
//Initialize the library
if (!glfwInit())
return -1;
//Specify Hints
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
//Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(640, 480, "Mojicon", NULL, NULL);
if (!window)
{
glfwTerminate();
return 1;
}
//Make the window's context current
glfwMakeContextCurrent(window);
std::cout << glGetString(GL_VERSION) << std::endl;
glClearColor(0.0, 0.0, 0.0, 1.0);
GLuint vertexShader = ShaderUtils::createShaderFromFile("myVertexShader.vs", GL_VERTEX_SHADER);
GLuint fragmentShader = ShaderUtils::createShaderFromFile("myFragmentShader.fs", GL_FRAGMENT_SHADER);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "fragData");
glLinkProgram(shaderProgram);
GLint linkStatus;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE)
{
cout << "Program Link Failed!" << endl;
GLint infoLogLength;
glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar * infoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shaderProgram, infoLogLength + 1, NULL, infoLog);
cout << infoLog << endl;
delete infoLog;
return 0;
}
glUseProgram(shaderProgram);
//vertex buffer objects
GLuint myVBO;
glGenBuffers(1, &myVBO);
glBindBuffer(GL_ARRAY_BUFFER, myVBO);
GLfloat bufferData[] =
{
+0.0, +0.5,
-0.5, -0.5,
+0.5, -0.5,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
GLuint myVAO;
glGenVertexArrays(1, &myVAO);
glBindVertexArray(myVAO);
GLint positionLoc = glGetAttribLocation(shaderProgram, "v_pos");
glEnableVertexAttribArray(positionLoc);
glBindBuffer(GL_ARRAY_BUFFER, myVBO);
glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glBindVertexArray(NULL);
//Loop the window until closed
while (!glfwWindowShouldClose(window))
{
//Render here
GLint windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(myVAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(NULL);
//Poll for events
glfwPollEvents();
//Swap buffers
glfwSwapBuffers(window);
}
glDeleteBuffers(1, &myVBO);
glDeleteVertexArrays(1, &myVAO);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(shaderProgram);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
ShaderUtil.h
#define GLFW_INCLUDE_GLCOREARB
#include <iostream>
#include <fstream>
#include <streambuf>
#include <GLFW/glfw3.h>
using namespace std;
class ShaderUtils
{
public:
static GLuint createShaderFromFile(const GLchar * path, GLenum shaderType);
};
ShaderUtil.cpp
#include "ShaderUtils.h"
GLuint ShaderUtils::createShaderFromFile(const GLchar * path, GLenum shaderType)
{
GLuint shaderID = glCreateShader(shaderType);
ifstream fin;
fin.open(path);
if (!fin.is_open())
{
cout << "File Not Found '" << path << "'!" << endl;
return -1;
}
string source((istreambuf_iterator<GLchar>(fin)), istreambuf_iterator<GLchar>());
fin.close();
const GLchar * shaderSource = source.c_str();
glShaderSource(shaderID, 1, &shaderSource, NULL);
glCompileShader(shaderID);
GLint compileStatus;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus != GL_TRUE)
{
cout << "Shader Failed To Compile: '" << path << "'!" << endl;
GLint infoLogLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar * infoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shaderID, infoLogLength + 1, NULL, infoLog);
cout << infoLog << endl;
delete infoLog;
return -1;
}
return 0;
}
I tried to make this code nearly identical with the tutorials code, and I cannot for the life of me find any differences. Help me find the problem (there are no bugs) and explain it to me.
Your createShaderFromFile() method always returns 0:
GLuint ShaderUtils::createShaderFromFile(const GLchar * path, GLenum shaderType)
{
...
return 0;
}
You use this return value as a shader id:
GLuint vertexShader = ShaderUtils::createShaderFromFile(
"myVertexShader.vs", GL_VERTEX_SHADER);
GLuint fragmentShader = ShaderUtils::createShaderFromFile(
"myFragmentShader.fs", GL_FRAGMENT_SHADER);
These values will come out as 0. To make this work, you will need to return the shader id from the method:
GLuint ShaderUtils::createShaderFromFile(const GLchar * path, GLenum shaderType)
{
...
return shaderID;
}
You should be able to track down this kind of problem by stepping through the code in a debugger.
I'm trying to learn OpenGL with this tutorial I tried to do the coding in OS X Mavericks but the result is just a black window. I believe there should be a white triangle but don't know what I'm missing.
Here's the code
glut_utils.h
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
void init();
void display();
void reshape (int w, int h);
void keyboard(uchar key, int x, int y);
glut_utils.cpp
#include <string>
#include <vector>
#include "glut_utils.h"
GLuint CreateShader(GLenum eShaderType, const std::string &strShaderFile)
{
GLuint shader = glCreateShader(eShaderType);
const char *strFileData = strShaderFile.c_str();
glShaderSource(shader, 1, &strFileData, NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
GLint infoLogLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
const char *strShaderType = NULL;
switch(eShaderType)
{
case GL_VERTEX_SHADER: strShaderType = "vertex"; break;
case GL_GEOMETRY_SHADER_EXT: strShaderType = "geometry"; break;
case GL_FRAGMENT_SHADER: strShaderType = "fragment"; break;
}
fprintf(stderr, "Compile failure in %s shader:\n%s\n", strShaderType, strInfoLog);
delete[] strInfoLog;
}
return shader;
}
GLuint CreateProgram(const std::vector<GLuint> &shaderList)
{
GLuint program = glCreateProgram();
for(size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
glAttachShader(program, shaderList[iLoop]);
glLinkProgram(program);
GLint status;
glGetProgramiv (program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
GLint infoLogLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
fprintf(stderr, "Linker failure: %s\n", strInfoLog);
delete[] strInfoLog;
}
for(size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
glDetachShader(program, shaderList[iLoop]);
return program;
}
GLuint theProgram;
const std::string strVertexShader(
"#version 330\n"
"layout(location = 0) in vec4 position;\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}\n"
);
const std::string strFragmentShader(
"#version 330\n"
"out vec4 outputColor;\n"
"void main()\n"
"{\n"
" outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"
"}\n"
);
void InitializeProgram()
{
std::vector<GLuint> shaderList;
shaderList.push_back(CreateShader(GL_VERTEX_SHADER, strVertexShader));
shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, strFragmentShader));
theProgram = CreateProgram(shaderList);
std::for_each(shaderList.begin(), shaderList.end(), glDeleteShader);
}
const float vertexPositions[] = {
0.75f, 0.75f, 0.0f, 1.0f,
0.75f, -0.75f, 0.0f, 1.0f,
-0.75f, -0.75f, 0.0f, 1.0f,
};
GLuint positionBufferObject;
GLuint vao;
void InitializeVertexBuffer()
{
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
void init()
{
InitializeProgram();
InitializeVertexBuffer();
glGenVertexArraysAPPLE(1, &vao);
glBindVertexArrayAPPLE(vao);
}
void display()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(theProgram);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glUseProgram(0);
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(EXIT_SUCCESS);
return;
}
}
Tut01.cpp
#include "common.h"
#include "glut_utils.h"
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_3_2_CORE_PROFILE | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Hello Triangle");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
Try including the core profile header first:
#include <OpenGL/gl3.h>
#include <GLUT/glut.h>
Remove the APPLE suffix from glGenVertexArraysAPPLE and glBindVertexArrayAPPLE - they shouldn't be defined with the gl3.h header anyway.
I'm trying to create a sample program that can be used as a test harness for OpenGL. The one I have so far seems to work, but it seems that the MVP matrix passed via the uniform variable MVPMatrix is ignored. When I added code to read the uniform back and check that it was actually updating properly, I get an invalid operation error when doing so and I can't see why - what's going on?
#include "stdafx.h"
#include <iostream>
#include <memory>
#include <sdl/SDL.h>
#include <assimp/Importer.hpp>
#include <assimp/mesh.h>
#include <assimp/scene.h>
#include <sdl/SDL_image.h>
#include <glm/glm.hpp>
#include <Windows.h>
#include <GL/glew.h>
#include <GL/GL.h>
#include <gl/GLU.h>
#include <vector>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <assimp/Importer.hpp>
#include <assimp/mesh.h>
#include <assimp/postprocess.h>
#include <assimp/vector3.h>
using namespace std;
void checkGLShaderStatus(GLuint id, GLuint thingToCheck, bool shader) {
GLint ret;
if (shader) glGetShaderiv(id, thingToCheck, &ret); else glGetProgramiv(id, thingToCheck, &ret);
// If there was an error
if (ret == GL_FALSE) {
// Print it out, then halt
GLint maxLength = 0;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &maxLength);
GLchar *shaderErrorLog = (GLchar*)malloc(sizeof(GLchar)*(maxLength + 1));
glGetShaderInfoLog(id, maxLength, &maxLength, shaderErrorLog);
shaderErrorLog[maxLength] = '\0';
cout << shaderErrorLog;
free(shaderErrorLog);
int junk;
cin >> junk;
exit(EXIT_FAILURE);
}
}
GLuint buildShader(const GLchar **source, GLuint length, GLenum type) {
// Create the shader
GLuint shaderId = glCreateShader(type);
// Upload source code
glShaderSource(shaderId, length, source, NULL);
// Compile the shader
glCompileShader(shaderId);
// See how the compilation went
checkGLShaderStatus(shaderId, GL_COMPILE_STATUS, true);
return shaderId;
}
void checkGL(string stage) {
GLuint error = glGetError();
if (error != GL_NO_ERROR) {
cout << "OpenGL broke..";
switch (error) {
case GL_INVALID_ENUM:
cout << "Invalid Enum";
break;
case GL_INVALID_VALUE:
cout << "Value out of range";
break;
case GL_INVALID_OPERATION:
cout << "Invalid operation";
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
cout << "Incomplete framebuffer";
break;
case GL_OUT_OF_MEMORY:
cout << "Out of memory";
break;
default:
cout << "Oh boy, did it break..";
}
cout << " (" << stage << ")" << endl;
int junk;
cin >> junk;
exit(EXIT_FAILURE);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1) exit(EXIT_FAILURE);
if (IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG) == -1) exit(EXIT_FAILURE);
Assimp::Importer importer;
const aiScene *importedScene = importer.ReadFile("Table.3ds",aiProcess_Triangulate);
if (importedScene == nullptr) exit(EXIT_FAILURE);
aiMesh *theMesh = importedScene->mMeshes[0];
if (theMesh == nullptr) exit(EXIT_FAILURE);
cout << "I imported a mesh with " << theMesh->mNumVertices << " vertices and " << theMesh->mNumFaces << " faces! " << endl;
SDL_Window *win = nullptr;
win = SDL_CreateWindow("My even more awesome SDL/OGL program", 100, 100, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (win == nullptr) exit(EXIT_FAILURE);
SDL_Renderer *ren = nullptr;
ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr) exit(EXIT_FAILURE);
SDL_GLContext context = SDL_GL_CreateContext(win);
if (context == nullptr) exit(EXIT_FAILURE);
glewInit();
int attrib_vPosition = 0;
const GLchar *vertexShaderSource = { "#version 430 core\n"
"layout (location=0) in vec4 vPosition;"
"uniform mat4 MVPMatrix;"
"void main() {"
" gl_Position = MVPMatrix * vPosition;"
"}"};
GLuint vertexShader = buildShader(&vertexShaderSource, 1, GL_VERTEX_SHADER);
checkGL("compiling vertex shader");
const GLchar *fragShaderSource = { "#version 430 core\n"
"out vec4 fColor;"
"void main() {"
" fColor = vec4(0.0, 0.0, 1.0, 1.0);"
"}"
};
GLuint fragmentShader = buildShader(&fragShaderSource, 1, GL_FRAGMENT_SHADER);
checkGL("compiling fragment shader");
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
checkGLShaderStatus(shaderProgram, GL_LINK_STATUS, false);
checkGL("Linking shader");
glUseProgram(shaderProgram);
//glDeleteShader(fragmentShader);
//glDeleteShader(vertexShader);
checkGL("Running shader");
GLint MVPlocation = glGetUniformLocation(shaderProgram, "MVPMatrix");
checkGL("Getting uniform location");
glm::mat4 mvpMatrix(0.1f);
glUniformMatrix4fv(MVPlocation, 1, GL_FALSE, glm::value_ptr(mvpMatrix));
checkGL("Setting uniform");
GLint testLocation = glGetUniformLocation(shaderProgram, "MVPMatrix[0][0]");
checkGL("Getting uninform test cell location");
GLfloat testfloat;
glGetUniformfv(shaderProgram, testLocation, &testfloat);
checkGL("Reading uniform");
if (testfloat != mvpMatrix[0][0]) {
cout << "Uniform setting did not sink in..";
}
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
checkGL("Creating VAO");
GLfloat vertices[3][3] = { { -0.9f, -0.9f, 0.f }, { 0.85f, -0.9f, 0.f }, { -0.9f, 0.85f, 0.f } };
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
int vertexDataSize = 9;
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, ((void *)(0)));
glEnableVertexAttribArray(0);
checkGL("creating VBO");
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, vertexDataSize);
glFlush();
SDL_GL_SwapWindow(win);
SDL_Event event;
bool quit = false;
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
}
}
glDeleteProgram(shaderProgram);
glDeleteBuffers(1, &buffer);
glDeleteVertexArrays(1, &VAO);
SDL_GL_DeleteContext(context);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
IMG_Quit();
SDL_Quit();
return 0;
}
You shouldn't use glGetUniformfv(... glGetUniformLocation(... "MVPMatrix[0][0]")). The documentation says
glGetUniformLocation returns an integer that represents the location of a specific uniform variable within a program object. name must be a null terminated string that contains no white space. name must be an active uniform variable name in program that is not a structure, an array of structures, or a subcomponent of a vector or a matrix.
And
glGetUniform returns in params the value(s) of the specified uniform variable. The type of the uniform variable specified by location determines the number of values returned. If the uniform variable is defined in the shader as a boolean, int, or float, a single value will be returned. If it is defined as a vec2, ivec2, or bvec2, two values will be returned. If it is defined as a vec3, ivec3, or bvec3, three values will be returned, and so on. To query values stored in uniform variables declared as arrays, call glGetUniform for each element of the array. To query values stored in uniform variables declared as structures, call glGetUniform for each field in the structure. The values for uniform variables declared as a matrix will be returned in column major order.
Your uniform variable uniform mat4 MVPMatrix; is declared as a matrix type, not an array and you will retrieve the entire 4x4 matrix at once (just like you set it in a single operation). Try
GLfloat testfloat[16];
glGetUniformfv(shaderProgram, MVPLocation, testfloat);
Another problem is here:
GLfloat vertices[3][3] = { { -0.9f, -0.9f, 0.f }, { 0.85f, -0.9f, 0.f }, { -0.9f, 0.85f, 0.f } };
int vertexDataSize = 9;
glDrawArrays(GL_TRIANGLES, 0, vertexDataSize);
You don't have 9 vertices, only 3.
I am trying to have OpenGL automatically assign an ID to a glsl-attribute, but it is failing.
My main program:
#include <iostream>
#include <GL/glew.h>
#include <GL/glfw3.h>
#include "test.h"
#include "shader_utils.h"
static void error_callback(int error, const char* description) {
std::cout << description << std::endl;
}
static void key_callback(GLFWwindow* window, int a, int b) {
if (a == GLFW_KEY_ESCAPE && b == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
void test()
{
std::cout << "Starting up" << std::endl;
init();
run();
}
GLFWwindow *window;
GLuint shaders;
GLuint vertexBuffer;
int init() {
glfwSetErrorCallback(error_callback);
if(!glfwInit()) {
return -1;
}
window = glfwCreateWindow(640, 480, "GLFW test", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glewExperimental = true;
glewInit();
shaders = LoadShaders("vertex.glsl", "fragment.glsl");
GLuint vao_id;
glGenVertexArrays(1, &vao_id);
glBindVertexArray(vao_id);
static const GLfloat vertex_data[] = {
// Bottom
-.5f, -.5f, -.5f, 1.f, 0.f, 0.f,
-.5f, -.5f, .5f, 1.f, 0.f, 0.f,
.5f, -.5f, .5f, 1.f, 0.f, 0.f,
};
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
}
void checkE() {
std::cout << "Checking for errors: ";
int err;
int a = 0;
while((err = glGetError()) != GL_NO_ERROR) {
std::cout << "Error: " << err << std::endl;
a = 1;
}
if(a == 0) {
std::cout << "no errors" << std::endl;
}
std::cout.flush();
}
int run() {
GLfloat angle = 0;
while(!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaders);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
GLuint attrLocation = glGetAttribLocation(shaders, "location");
GLuint attrColor = glGetAttribLocation(shaders, "color");
std::cout << "AttribLocation('location'): ";
std::cout << glGetAttribLocation(shaders, "location") << std::endl;
std::cout << "AttribLocation('color'): ";
std::cout << glGetAttribLocation(shaders, "color") << std::endl;
checkE();
std::cout << std::endl;
std::cout << "glEnableVertexAttribArray()" << std::endl;
glEnableVertexAttribArray(attrLocation);
glEnableVertexAttribArray(attrColor);
checkE();
std::cout << std::endl;
std::cout << "glVertexAttribPointer();" << std::endl;
glVertexAttribPointer(
glGetAttribLocation(shaders, "location"), // Attribute
3, // Size
GL_FLOAT, // Size
GL_FALSE, // Normalized
24, // Stride
(GLvoid*) 0 // Offset
);
checkE();
std::cout << std::endl;
std::cout << "glVertexAttribPointer();" << std::endl;
glVertexAttribPointer(
glGetAttribLocation(shaders, "color"),
3,
GL_FLOAT,
GL_FALSE,
24,
(GLvoid*) (3*sizeof(GLfloat))
);
checkE();
std::cout << std::endl;
glDrawArrays(GL_TRIANGLES, 0, 3);
checkE();
std::cout << std::endl;
glDisableVertexAttribArray(attrLocation);
glDisableVertexAttribArray(attrColor);
checkE();
std::cout << std::endl;
glfwSwapBuffers(window);
glfwPollEvents();
glfwSetWindowShouldClose(window, GL_TRUE);
}
glfwDestroyWindow(window);
glfwTerminate();
}
Output from program:
Starting up
Compiling shader : vertex.glsl
Compiling shader : fragment.glsl
Linking program
AttribLocation('location'): -1
AttribLocation('color'): -1
Checking for errors: no errors
glEnableVertexAttribArray()
Checking for errors: Error: 1281
glVertexAttribPointer();
Checking for errors: Error: 1281
glVertexAttribPointer();
Checking for errors: Error: 1281
Checking for errors: no errors
Checking for errors: Error: 1281
Shader loader:
#include "shader_utils.h"
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include "GL/glew.h"
#include "GL/glfw3.h"
GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if(VertexShaderStream.is_open())
{
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
} else {
std::cout << "could not open\n";
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if(FragmentShaderStream.is_open()){
std::string Line = "";
while(getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
// Link the program
fprintf(stdout, "Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
std::cout.flush();
return ProgramID;
}
Vertex shader:
#version 130
in vec4 position;
in vec3 color;
out vec3 f_color;
void main() {
f_color = color;
gl_Position = position * gl_ModelViewProjectionMatrix;
}
Fragment shader:
#version 130
in vec3 color;
void main() {
gl_FragColor = vec4(color, 1);
}
For some reason I get just -1 as the location for both the attributes. Obviously the rest of the errors are caused by invalid location indices?
From OpenGL docs:
If the named attribute variable is not an active attribute in the specified program object or if name starts with the reserved prefix "gl_", a value of -1 is returned.
The names do not begin with gl_ and they are in use in the shaders, so I shouldn't get a value of -1. What am I missing?
You are failing to get an attribute location for color because it is not active. While it is true that color is used to calculate f_color in this example, the fragment shader does not use f_color so the linker determines that the vertex attribute named: color is inactive.
The solution is quite simple, really:
Fragment Shader:
#version 130
in vec3 f_color; // RENAMED from color, so that this matches the output from the VS.
void main() {
gl_FragColor = vec4(f_color, 1);
}
It is not an error to re-use the name color for different purposes in the Vertex Shader (input vertex attribute) and Fragment Shader (input varying) stages so the compiler/linker will not complain. It would be an error if you tried to do something like inout color though, so this is why you have to pass vertex attributes to geometry/tessellation/fragment shaders using a differently named varying. If the input/output names between stages do not match then chances are quite good that the original vertex attribute will be considered inactive.
Also, unless you are transposing your ModelViewProjection matrix, you have the matrix multiplication in your vertex shader backwards. Column-major matrix multiplication, as OpenGL uses, should read right-to-left. That is, you start with an object space position (right-most) and transform to clip space (left-most).
In other words, this is the proper way to transform your vertices...
gl_Position = gl_ModelViewProjectionMatrix * position;
~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
clip space object space to clip space obj space