I'm trying to get a super simple GLFW and VBO example running, but I'm stuck. I've used glBegin and glEnd for other projects, but I'm trying to update my code to work with OpenGL ES 2, but for now I just want to be as forward compatible as possible.
From some examples online, I've come up with the following code:
#include <stdlib.h>
#include <GL/glfw3.h>
#include <stdio.h>
#define bool int
#define true 1
#define false 0
const int width = 800;
const int height = 600;
bool opened = true;
GLuint glTriangle;
GLfloat triangle[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
void init() {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glGenBuffers(1, &glTriangle);
glBindBuffer(GL_ARRAY_BUFFER, glTriangle);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW);
}
void display() {
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, glTriangle);
glVertexAttribPointer(0L, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
}
int windowClose(GLFWwindow window) {
opened = false;
return GL_TRUE;
}
void main() {
if (!glfwInit()) {
printf("glfwInit didn't work\n");
return;
}
GLFWwindow window = glfwCreateWindow(width, height, GLFW_WINDOWED, "Test", 0);
glfwMakeContextCurrent(window);
init();
glfwSetWindowCloseCallback(window, windowClose);
glfwSwapInterval(1);
while(opened) {
display();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
}
This code runs, but all I get is a black screen when I expected to see a white triangle. I've tried to avoid anything fancy like shaders/textures until I at least get something painted to the screen.
If it matters, I'm compiling with: gcc -o test -lGL -lglfw -lm test.c on Linux with OpenGL version 2.1 through the Mesa driver.
What am I doing wrong? If I need to specify color information, what is a simple way to do that?
You shouldn't be using glEnableVertexAttribArray / glVertexAttribPointer with the fixed pipeline. It might work (I'm not positive, I think attrib 0 might alias to the vertex attrib array, but not sure). It's not really correct to do so.
If you don't have a shader you should be using glEnableClientState and glVertexPointer for vertex data.
The default color is (1,1,1,1), so I think you should be ok on colors for now.
Related
I'm adding transformations to my C OpenGL program. I'm using CGLM as my maths library. The program has no warnings or errors. Still however, when I compile and run the program, I simply get a window coloured my clear colour. The following is my program's main loop
// Initialize variables for framerate counting
double lastTime = glfwGetTime();
int frameCount = 0;
// Program loop
while (!glfwWindowShouldClose(window)) {
// Calculate framerate
double thisTime = glfwGetTime();
frameCount++;
// If a second has passed.
if (thisTime - lastTime >= 1.0) {
printf("%i FPS\n", frameCount);
frameCount = 0;
lastTime = thisTime;
}
processInput(window);
// Clear the window
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Bind textures on texture units
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
// Create transformations
mat4 transform = {{1.0f}};
glm_translate(transform, (vec3){0.5f, -0.5f, 0.0f});
glm_rotate(transform, (float)glfwGetTime(), (vec3){0.0f, 0.0f, 1.0f});
printf("%i\n", transform);
// Get matrix's uniform location and set matrix
shaderUse(myShaderPtr);
GLint transformLoc = glGetUniformLocation(myShaderPtr->shaderID, "transform");
printf("%i\n", transformLoc);
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, *transform);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window); // Swap the front and back buffers
glfwPollEvents(); // Check for events (mouse movement, mouse click, keyboard press, keyboard release etc.)
}
The Program is up on github here if you'd like to check out the full code.
The output of this program is
However, the intended output is a spinning box with my profile picture on it.
mat4 transform = {{1.0f}}; does not do what you expect. C doesn't have a constructor like C++. The C++ version's constructor initialized the matrix with the Identity matrix. You have to use glm_mat4_identity to initialize with the identity matrix:
mat4 transform;
glm_mat4_identity(transform);
glm_rotate(transform, (float)glfwGetTime(), (vec3){0.0f, 0.0f, 1.0f});
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, (float*)transform);
Additionally, you need to specify and add an orthographic projection matrix that compensates for the aspect ratio of the viewport:
float aspect = (float)width / (float)height;
mat4 projection;
glm_ortho(-aspect, aspect, -1.0f, 1.0f, -1.0f, 1.0f, projection)
mat4 transform;
glm_rotate(transform, (float)glfwGetTime(), (vec3){0.0f, 0.0f, 1.0f});
glm_mat4_identity(transform);
mat4 mvp;
glm_mat4_mul(projection, transform, mvp);
GLint transformLoc = glGetUniformLocation(myShaderPtr->shaderID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, (float*)mvp);
I recently downloaded GLFW3 since it's better than GLUT from what I heard. I managed to get a window to display and change the clear colors but I cannot figure out why I'm not rendering anything in my draw calls. In this case, it's a triangle. I'm running this on XCode 9.2 and this is the code I have right now:
#define GLFW_INCLUDE_GLCOREARB
#include <stdio.h>
#include <stdlib.h>
#include <GLFW/glfw3.h>
static const GLfloat vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
int main(int argc, const char * argv[]) {
GLuint VertexBufferID;
GLFWwindow* window;
/* Initialize the library */
if ( !glfwInit() )
{
return -1;
}
#ifdef __APPLE__
/* We need to explicitly ask for a 3.2 context on OS X */
glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow( 400 , 400, "Hello World", NULL, NULL );
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glGenBuffers(1, &VertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STATIC_DRAW);
//Edit in
**program = initShaders(VSHADER_SOURCE, FSHADER_SOURCE);**
while (!glfwWindowShouldClose(window))
{
/* Render here */
//set clear color
glClearColor(0.0, 0.0, 0.0, 1.0);
//clear window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the buffers
//Draw
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferID);
//got error 0x502 on line below
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
//Edit in
**glUseProgram(program);**
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
It's probably a minor mistake but I can't see it.
Edit: Okay shaders are required here from what I'm told. I don't know how I got away with it in GLUT. I guess it was an older version. So here are the shader programs I'm using.
"#version 330 core\n"
"layout(location = 0) in vec3 vertexPosition_modelspace;\n"
"void main()\n"
"{\n"
" gl_Position.xyz = vertexPosition_modelspace;\n"
" gl_Position.w = 1.0;\n"
"}\n";
"#version 330 core\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
" color = vec3(1, 0, 0);\n"
"}\n";
I should also mention that I've been following this tutorial for help as well. http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
As for errors, I found an error in glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); as code 502, where it apparently means GL_INVALID_OPERATION, which I don't know what that means in this case.
The 2nd parameter of glBufferData is the target type of the buffer and not the named buffer object itself. glBufferData uses the named buffer object which is bound to the specified target:
glBufferData(
GL_ARRAY_BUFFER, // GL_ARRAY_BUFFER instead of VertexBufferID
sizeof(vertex_buffer_data),
vertex_buffer_data,
GL_STATIC_DRAW);
If you want to use a OpenGL Core profile context, then you have to use a shader program, this is not optional.
Further you have to create a named Vertex Array Object, because the default vertex array object (0) is not present in core profile context.
The modern way of rendering in OpenGL, would be to use a Shader program.
If you don't want to use use a shader program, than you have to use a compatibility context and you have to define the array of vertex data using the deprected way by glVertexPointer and you have to enable the client-side capability for vertex coordinates by glEnableClientState( GL_VERTEX_ARRAY ).
glfwWindowHint (GLFW_OPENGL_PROFILE,
GLFW_OPENGL_COMPAT_PROFILE); // instead of GLFW_OPENGL_CORE_PROFILE
.....
glGenBuffers(1, &VertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferID);
glBufferData(GL_ARRAY_BUFFER,
sizeof(vertex_buffer_data), vertex_buffer_data, GL_STATIC_DRAW);
.....
glEnableClientState( GL_VERTEX_ARRAY );
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferID);
glVertexPointer(3, GL_FLOAT, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState( GL_VERTEX_ARRAY );
Been a while since I've needed to ask a question,
I'm trying out SDL2 and OpenGL (3.3 which is the compatibility limit with mesa) because the GLSL really interests me, however on my work machine I learned very quickly that it isn't easy to get things to work. Every tutorial I've used and even the Mesa demos themselves use headers that don't come with Ubuntu's base GL library, I've already resigned and installed GLEW but it doesn't feel right continously adding libraries to make things work, the GL headers I have are:
glcorearb.h, glew.h, glext.h, gl.h, gl_mangle.h, glu.h, glu_mangle.h,
glxew.h, glxext.h, glx.h, glxint.h, glx_mangle.h, glxmd.h, glxproto.h,
glxtokens.h, wglew.h
I tried following LazyFoo's tutorials but did not have the same result of getting a white quad to appear. I followed opengl-tutorial's tutorials and did not get the same result of a white triangle to appear (it mentions to not worry if you don't see it at first, but doesn't explain what to do in the case that it doesn't (I tried to follow the rest of the tutorial, but I'm writing this in C and not C++ so I'm worried about straying too far from the tutorials' and confusing the issue further. I've installed SDL2 and made sure I had everything. This is the code I have in my current SDL2/GL program, it does not at all reveal a white triangle, it's a combination of tutorials, but I've read all the SDL API material I could to make sure nothing on the SDL side affects what GL tries to do.
#define SDL_ASSERT_LEVEL 3
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_error.h>
#include <SDL2/SDL_assert.h>
#include <SDL2/SDL_version.h>
#include <SDL2/SDL_events.h>
#include <GL/gl.h>
int main(){
SDL_version compiledWith, linkedWith;
SDL_VERSION(&compiledWith);
SDL_GetVersion(&linkedWith);
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0){
fprintf(stderr, "\nUnable to initialize SDL: %s\n", SDL_GetError());
exit(1);
}
SDL_Log("\nCompiled with: %d.%d.%d\n", compiledWith.major,
compiledWith.minor, compiledWith.patch);
SDL_Log("\nLinked with: %d.%d.%d\n", linkedWith.major,
linkedWith.minor, linkedWith.patch);
SDL_Window* window = SDL_CreateWindow("SDL2/OpenGL Demo", 0, 0, 640, 480,
SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
//Can now make GL calls after the below line
SDL_GLContext glContext = SDL_GL_CreateContext(window);
GLuint vertexArrayID;
glGenVertexArrays(1, &vertexArrayID);
glBindVertexArray(vertexArrayID);
static const GLfloat gVertexBufferData[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gVertexBufferData),
gVertexBufferData, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
SDL_Event theEvent;
bool running = true;
while(running){
while(SDL_PollEvent(&theEvent)){
switch(theEvent.type){
case SDL_QUIT:
SDL_Log("\nQuit request acknowledged\n");
//Finish up GL usage
SDL_GL_DeleteContext(glContext);
//Finish up SDL usage
SDL_Quit();
running = false;
break;
default:
break;
}
}
}
return 0;
}
I use gcc main.c -lSDL2 -lGL -o test for linking, I suspect I might be missing linkage libraries but I'm not sure where I can check if I am or not, the compiler doesn't warn me about anything it can't find unless I follow a tutorial that uses something I don't have.
To conclude since this is a longer post than anticipated, the question is:
Am I missing any important library to actually get this to work on my system (Ubuntu 15.04 Intel Haswell Mobile x86/MMX/SSE2)?
Did I miss something in my code that is necessary to see the white triangle?
This question already has answers here:
How do I create an OpenGL 3.3 context in GLFW 3
(1 answer)
Simple triangle using OpenGL and GLFW [duplicate]
(1 answer)
Closed 8 years ago.
I'm following the http://opengl-tutorials.org tutorial series, and came up with a very basic code for drawing a white triangle on screen, but I can't seem to get it to work.
I've compiled glfw without any additional options using appleshell's answer here: OpenGL 3.3/4.1 on Mac OSX 10.9 using GLFW library
I created a simple source code based on the site instructions:
#include <stdio.h>
#include <stdlib.h>
#include <glfw3.h>
// Need gl3.h for glGenVertexArrays() and glBindVertexArray()
#include <OpenGL/gl3.h>
// An array of 3 vectors which represents 3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
#define printGlErr(func) err = glGetError(); if (err) fprintf(stderr, func " error: %u at line %d\n", err, __LINE__);
GLuint err;
int main(int argc, const char * argv[]) {
if (!glfwInit()) {
fprintf( stderr, "Failed to initialize GLFW\n" );
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
// Open a window and create its OpenGL context
GLFWwindow* window;
window = glfwCreateWindow(1024, 768, "Triangle", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window.\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Init stuff
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// This will identify our vertex buffer
GLuint vertexbuffer;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
printGlErr("glGenBuffers()");
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
printGlErr("glBindBuffer()");
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
printGlErr("glBufferData()");
do {
// Draw stuff
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
printGlErr("glVertexAttribPointer()");
glDrawArrays(GL_TRIANGLES, 0, 3);
printGlErr("glDrawArrays()");
glDisableVertexAttribArray(0);
printGlErr("glDisableVertexAttribArray()");
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0); // Check if the ESC key was pressed or the window was closed
printf("Goodbye!\n");
return(0);
}
I can't seem to get the code to work. I'm getting a GL_INVALID_OPERATION on the glDrawArrays() function call.
The code renders a black window on Mavericks and on Yosemite. This is my hardware specs: http://support.apple.com/kb/SP653
It does not crash, it exits on ESC, but nothing else happens (other than spamming the error code on the console). The results are the same using any of the 2 available video boards.
Also, I'm compiling the source code using the following line on terminal:
gcc main.c -o triangle -framework OpenGl -framework Cocoa -framework IOKit -framework CoreVideo -I../glfw/include/GLFW -L../glfw/src -lglfw3
I've begun doing a bit of OpenGL, and I've just discovered alternatives to the fixed function pipeline, so I went searching tutorials. Sadly, most good tutorials use C++, and I would like to stick to C if possible. So I wasn't able to just copy-paste stuff and try it.
Copy-pasting and merging code gave errors though, and I'm not sure how I should deal with them. The error in question was "Segmentation fault", and here is the code:
#include <GL/glfw.h>
#include <GL/glu.h>
#include <stdlib.h>
#define SCREEN_WIDTH 1600
#define SCREEN_HEIGHT 1000
void main(int argc, char **argv)
{
float mouse_x, mouse_y;
GLuint positionBufferObject;
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,
};
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
int running = GL_TRUE;
// Initialize GLFW
if( !glfwInit() )
{
exit( EXIT_FAILURE );
}
// Open an OpenGL window
if( !glfwOpenWindow(SCREEN_WIDTH,SCREEN_HEIGHT, 8,8,8,8,8,8, GLFW_WINDOW ) )
{
glfwTerminate();
exit( EXIT_FAILURE );
}
while (running)
{
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
}
Of course, a lot of code is missing here, because it (apparently) didn't influence the error.
Commenting out "glDrawArrays" fixes the error, and OpenGL runs normally (without drawing anything, logically).
Any help?
You should initialise gl before you start binding buffers and so on. The initialisation process fetches and assigns the pointers to these functions. Otherwise they're null.