I get a black screen after trying to get a simple triangle on OpenGL with the SDL2...
I actually initialize the window with OpenGL and start GLEW with an object name as "EngineOpenGL" : http://pastebin.com/S4YDgY45
Then I start a scene which supposed to rendering the triangle :
"SceneOpenGL" : http://pastebin.com/GD4f5UDj
The main file :
#include <SDL.h>
#include <iostream>
#include <GL\glew.h>
#include "EngineOpenGl.h"
// DEBUG_MemoryLeaks
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
// _DEBUG
#include "SDLInitVideoException.h"
int main(int argc, char **argv) {
_CrtDumpMemoryLeaks();
EngineOpenGL * scene = new EngineOpenGL("OpenGL", 720, 1280);
try {
scene->init();
} catch (const SDLInitVideoException &e) {
delete scene;
std::cout << "Error while initialising SDL" << std::endl;
} catch (const SDLCreateWindowException &e) {
delete scene;
std::cout << "Error while initialising the window" << std::endl;
} catch (const SDLCreateContextGLException &e) {
delete scene;
std::cout << "Error while creating the contextGL" << std::endl;
} catch (const GLEWInitException &e) {
delete scene;
std::cout << "Error while initialising " << std::endl;
} catch (const SceneOpenGLException &e) {
delete scene;
std::cout << "Error while starting the scene" << std::endl;
}
scene->start();
delete scene;
// DEBUG_MemoryLeaks
_CrtDumpMemoryLeaks();
// _DEBUG
return 0;
}
FPS show the fps in the console and Input gets the user input.
Edit : I actually just tried to copy/past a code for rendering triangle and it keep doesn't work...
#include "SceneOpenGl.h"
// Shader temporaire :
#include "Shader.h"
SceneOpenGL::SceneOpenGL(SDL_Window* window) {
if (window == NULL) {
throw new SceneOpenGLException();
}
// Engine
this->window = window;
// Tools
this->fps = new FPSCount();
this->input = new Input();
// Scene
this->run = false;
int w, h;
SDL_GetWindowSize(window, &w, &h);
this->projection = glm::perspective(70.0, (double)(w/h), 1.0, 100.0);
this->modelview = glm::mat4(1.0);
}
SceneOpenGL::~SceneOpenGL(){
delete fps;
delete input;
}
void SceneOpenGL::start() {
run = true;
// Test en attendant ObjectGL.show() //
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // Top Right
0.5f, -0.5f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f // Top Left
};
GLuint indices[] = { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
// Build and compile our shader program
// Vertex shader
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Check for compile time errors
GLint success;
GLchar 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
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Check for compile time 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
GLuint 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);
GLuint VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// 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);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind
glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs), remember: do NOT unbind the EBO, keep it bound to this VAO
// /Test //
while (run) {
// FPS flag
if (fps->flag()) {
std::cout << "FPS : " << fps->getFps() << std::endl;
}
// Input check/actions
input->updateEvents();
if (input->isKeyPush(SDL_SCANCODE_ESCAPE)) {
run = false;
}
// Cleaning last frame
glClear(GL_COLOR_BUFFER_BIT);
// Test //
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
// FPS add frame
fps->addFrame();
// Rendering
SDL_GL_SwapWindow(window);
}
}
At no point are you loading your vertex data into video memory. You have a line which looks like an attempt to load the vertices into video memory:
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
.... But that's not what that function does.
You need to create and bind a Vertex Array and a Vertex Buffer:
GLuint vertex_array_id;
glGenVertexArrays(1, &vertex_array_id);
glBindVertexArray(vertex_array_id);
GLuint vertex_buffer_id;
glGenBuffers(1, &vertex_buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id);
Then, while this Vertex Array and Vertex Buffer is bound, you need to explicitly provide data to the buffer:
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
Then you use glVertexAttribPointer to specify how the data is laid out.
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);
glEnableVertexAttribArray(0);
All of that code, by the way, should probably be outside the loop. Then inside the draw loop, you simply have to call glDrawArrays.
Related
i try to paint simple triangle but i somehow can see the triangle
Here is my files
the window do created but no triangals in it dont know why
#include <iostream>
#include "GLFWManager.h"
#include <stdio.h>
#include <stdlib.h>
int main()
{
std::cout << "Hello World!\n";
GLFWManager gLFWManager;
gLFWManager.Init();
GLuint vbo;
GLuint vao;
GLfloat vertices[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
// second triangle
0.0f, -0.5f, 0.0f, // left
0.9f, -0.5f, 0.0f, // right
0.45f, 0.5f, 0.0f // top
};
glGenBuffers(1, &vbo);
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);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
int shaderProgram = gLFWManager.createShader();
// Set the clear color
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
while (!glfwWindowShouldClose(gLFWManager.window))
{
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(vao); // 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
glDrawArrays(GL_TRIANGLES, 0,6); // set the count to 3 since we're drawing 3 vertices
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(gLFWManager.window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
}
and this one :
#include "GLFWManager.h"
#include "stdio.h"
#include "stdlib.h"
int GLFWManager::windowHight = 300;
int GLFWManager::windowWidth = 300;
void GLFWManager::errorCallback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
void GLFWManager::windowSizeCallbackcallback(GLFWwindow* window, int width, int height)
{
if (width > 0 && height > 0) {
windowHight = height;
windowWidth = width;
}
}
static void KeyCallback(GLFWwindow* window, int key, int, int action, int mods)
{
switch (key)
{
case GLFW_KEY_ESCAPE:
{
if (action == GLFW_RELEASE)
{
glfwSetWindowShouldClose(window, GLFW_PRESS);
}
}
}
}
GLFWManager::GLFWManager()
{
window = nullptr;
}
GLFWManager::~GLFWManager()
{
}
void GLFWManager::Init()
{
glfwSetErrorCallback(GLFWManager::errorCallback);
if (!glfwInit())
{
exit(EXIT_FAILURE);
}
setWindowsHints();
createWindow();
glfwSetKeyCallback(window, KeyCallback);
glfwSetWindowSizeCallback(window, GLFWManager::windowSizeCallbackcallback);
const GLFWvidmode *vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (vidmode->width - windowWidth) /2 , (vidmode->height - windowHight) /2);
glfwGetFramebufferSize(window, &windowWidth, &windowHight);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
loadGlad();
}
void GLFWManager::setWindowsHints()
{
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable
}
void GLFWManager::createWindow()
{
window = glfwCreateWindow(windowWidth,windowHight, "Test", NULL, NULL);
if (!window)
{
exit(EXIT_FAILURE);
}
}
void GLFWManager::loadGlad()
{
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
fprintf(stderr, "Failed to initialize GLAD");
exit(EXIT_FAILURE);
}
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
}
int GLFWManager::createShader()
{
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";
// 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);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n %s\n ",infoLog);
}
// 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);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n %s \n",infoLog);
}
// 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);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n %s \n",infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderProgram;
}
glVertexAttribPointer and glEnableVertexAttribArray specify and enable an array of vertex attribute data and sets states in the state vector of the currently bound Vertex Array Object.
You have to bind the vertex array object (glBindVertexArray) before you can specify the vertex arrays:
// Create vertex buffer object
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Create Vertex array object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// specify array of generic vertex array data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
Note, before you call glVertexAttribPointer, the Vertex Array Object and the Vertex Buffer Object have to be bound, because glVertexAttribPointer associates the buffer which is currently bound to the ARRAY_BUFFER target, to the attribute with the specified index, in the state vector of the currently bound VAO.
I'm trying to experiment a bit with uniform variables and there's something bugging me. My code looks like this:
#include <glad/glad.h>
#include <GLFW/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"
"uniform float offset;"
"void main()\n"
"{\n"
"vec4 newPos = vec4(aPos, 1.0);\n"
"newPos.x += offset;\n"
"gl_Position = newPos;\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, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#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, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first Triangle
1, 2, 3 // second Triangle
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// 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);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glUniform1f(glGetUniformLocation(shaderProgram, "offset"), 1);
// 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);
// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
//glBindBuffer(GL_ELEMENT_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);
glBindVertexArray(VAO); // 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
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// 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);
glDeleteBuffers(1, &EBO);
// 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);
}
If I try to set a uniform variable in the program, and I render afterwards, the program loses the uniform's value and behaves as if it was 0, while if I put the glUniform1f call somewhere in the loop before the glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); it works properly. I don't understand, why my glUniform1f code gets lost?
When exactly is the uniform flushed? And is it supposed to behave like this?
glUniform sets a value of a uniform variable in the default uniform block of the currently installed program. You have to install the program by glUseProgram before.
GLint offset_loc = glGetUniformLocation(shaderProgram, "offset");
glUseProgram(shaderProgram);
glUniform1f(offset_loc , 1);
Since OpenGL 4.1 you can use glProgramUniform to set the value of a uniform variable for a specified program object.
glProgramUniform1f(shaderProgram, offset_loc, 1);
I have issue in that the window is displaying the clear color i.e. (Orange) I tried all answers on the web but they didn't seem to help me. I'm using GLFW 3.3 precompiled binaries. I'm using GLAD for OpenGL functions.
The code does not give any errors or warnings and also glGetError() returns 0 at all points of the code.
I've already tried changing the order and gDEBugger gives me error (that is, PRIV_INSTRUCTION) and the VAO and VBO tabs are empty.
Here's my code
#define GLFW_DLL
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
using namespace std;
static const char* vshSrc = "#version 330 core \n layout (location = 0) in vec3 tPos; void main(){gl_Position = tPos.x, tPos.y, tPos.z;} \0";
static const char* fshSrc = "#version 330 core \n layout (location = 0) out vec4 FragOut; void main(){FragOut = vec4(1.0f,0.4f,0.3f,1.0f);} \0";
/** Processes the input.
*Edit the fuction to add more features. */
void getInput( GLFWwindow *win ){
if(glfwGetKey(win,GLFW_KEY_ESCAPE) == GLFW_PRESS){
glfwSetWindowShouldClose(win,true);
}
}
int main( int argc, char **argv )
{
//Initialization
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
//Make compatible for MacOSX
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT,GL_TRUE);
#endif // __APPLE__
//Window creation
GLFWwindow* window = glfwCreateWindow(640,480,"Illuminati",NULL,NULL);
if (window == NULL)
{
cout << "Window creation failed" << endl;
return -1;
}
//GLAD
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
cout << "GLAD load error." << endl;
return -1;
}
//glViewport( 0, 0, 640, 480);
//==============================================================//
//Shader programs
//Vertex Shader
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vshSrc, NULL);
glCompileShader(vertexShader);
//Check for compile errors
int compilationSuccesful;
char InfoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compilationSuccesful);
if ( !compilationSuccesful ){
glGetShaderInfoLog(vertexShader, 512, NULL, InfoLog);
cout << "Vertex Shader compilation Failed. ERROR. \n \n" << InfoLog << endl;
}
//Fragment Shader
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fshSrc, NULL);
glCompileShader(fragmentShader);
//error checking for fragment shader
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compilationSuccesful);
if ( !compilationSuccesful ){
glGetShaderInfoLog(fragmentShader, 512, NULL, InfoLog);
cout << "Fragment Shader compilation Failed. ERROR. \n \n" << InfoLog << endl;
}
//Shader Program
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
//Shader attachments
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//Checking for link errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &compilationSuccesful);
if ( !compilationSuccesful ){
glGetProgramInfoLog(shaderProgram, 512, NULL, InfoLog);
cout << "The program refused to link. ERROR. \n \n" << InfoLog << endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//----------------------------------------------------------------------------------------------------------//
//Vertex data and elements
float rect[ ] {
/* 0 bottom left*/ -0.5f, -0.5f, 0.0f,
/* 1 top left*/ -0.5, 0.5f, 0.0f,
/* 2 bottom right*/ 0.5f, -0.5f, 0.0f,
/* 3 top right*/ 0.5f, 0.5f, 0.0f
};
unsigned int indices[] {
0,1,2, //first triangle
1,3,2 //second triangle
};
//==============================================================//
//Buffers and VAO
//VAO
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//VBO
unsigned int VBO;
glGenBuffers(1,&VBO);
//EBO
unsigned int EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(rect), rect, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//================================================================//
//Vertex Attributes
//glBindVertexArray(0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//for safety
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//A useless variable
//unsigned int ui;
//===============================================================//
//Render Loop
while ( !glfwWindowShouldClose(window) )
{
//Clear the buffer
glClearColor(0.9f,0.7f,0.2f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////DRAWING//////////////////////////////////////////
glBindVertexArray(VAO);
glUseProgram(shaderProgram);
//glDrawArrays(GL_TRIANGLES, 0, 4);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//////////////////////////////////////////////END/////////////////////////////////////////////
getInput(window);
glfwSwapBuffers(window);
glfwPollEvents();
}
//Exit and destructors
glfwTerminate();
return 0;
}
//End
/*
__
<( . )____
/_______/
~~~~~~~~~
~~~~~~~~~
*/
In your shader this expression will try to assign the value of tPos.z and only tPos.z to gl_Position
gl_Position = tPos.x, tPos.y, tPos.z;
The reason for that is the semantics of the Comma operator, where all expressions delimited by , are evaluated, but only the result of the very last one is used as the whole expression's R-value.
You probably just want to swizzle it, also you must assign .w:
gl_Position = vec4(tPos.xyz, 1);
#include <iostream>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#include <SDL2/SDL.h>
SDL_Window * window = NULL;
SDL_GLContext context = NULL;
const GLfloat vertices[3][4] = {
0.5f, 0.5f, 0.0f, // Top Right
0.5f, -0.5f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f // Top Left
};
const GLuint indices[3][2]= { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
const GLchar* vertexShaderSource = {"#version 330 core\n"
"layout (location = 0) in vec3 position;"
"void main(void)\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\n\0"};
//fragment
const GLchar* fragmentShaderSource = {"#version 330 core\n"
"out vec4 color;\n"
"void main(void)\n"
"{\n"
"color = vec4(1.0, 0.5, 0.2, 1.0);\n"
"}\n\0"};
bool init ();
bool init(){
if (SDL_Init(SDL_INIT_VIDEO)<0){
std::cout << "Can't make SDL" << std::endl;
}
//what version we are using
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
//SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
window = SDL_CreateWindow("Rectangle", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 512, 512, SDL_WINDOW_OPENGL);
if (!window){
std::cout << "No window created" << std::endl;
window = NULL;
return false;
}
context = SDL_GL_CreateContext(window);
//double buffering - 24bit z buffer (might need changing for different systems)
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//Makes buffer swap sync with VBLANK
SDL_GL_SetSwapInterval(1);
glViewport(0, 0, 512, 512);
return true;
};
int main(int argc, const char * argv[]) {
if (!init()) std::cout << "Failed to start up!" << std::endl;
//compiling the shaders
GLuint shaderProgram, fragmentShader, vertexShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
//error checking
GLchar info [512];
GLint success;
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(!success){
glGetShaderInfoLog(fragmentShader, 512, NULL, info);
std::cout << "Did not compile fragment shader\n"<< info;
}
std::cout<< "vertex shader made" << std::endl;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
//error checking
GLchar infoLog [512];
GLint success2;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success2);
if(!success){
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "Did not compile vertex shader\n" << info;
}
std::cout << "fragment shader made" << std::endl;
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//error checking
GLchar info3 [512];
GLint success3;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success3);
if(!success){
glGetProgramInfoLog(shaderProgram, 512, NULL, info3);
std::cout << "Did not link shaders\n" << info;
}
std::cout << "shaders linked" << std::endl;
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//sets all the VAOs, VBOs, etcs
GLuint VAO;
glGenVertexArrays(1, &VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
GLuint EBO;
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
bool loop = true;
while (loop) {
SDL_Event e;
while(SDL_PollEvent(&e)){
if (e.type == SDL_QUIT) loop = false;
if (e.type == SDL_KEYDOWN){
switch(e.key.keysym.sym){
case SDLK_ESCAPE:
loop = false;
break;
case SDLK_q:
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
break;
case SDLK_y:
std::cout << glGetString(GL_VERSION) << std::endl;
}
std::cout << glGetError() << std::endl;
}
}
}
}
//generates error 1282 for some reason
I used glGetError to see what the error was and it returned 1282, or GL_INVALID_OPERATION. Whenever I try to draw, it causes a glitchy image (will upload pic later).
The problem is definitely not the shaders, because they compile just fine.
I think it's probably how I set up the VBOs and VAO:
//sets all the VAOs, VBOs, etcs
GLuint VAO;
glGenVertexArrays(1, &VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
GLuint EBO;
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
I copied all of those straight from this tutorial https://learnopengl.com/#!Getting-started/Hello-Triangle
and the source code for the tutorial can be found here https://learnopengl.com/code_viewer.php?code=getting-started/hellotriangle2
I compared my code to the tutorial's several times, checking if I had all the right calls and parameters, but I couldn't find anything wrong. I'm pretty sure I set it all up correctly. Does anyone more experienced than me see what I've done wrong?
Edit: Ok, so I got the line 440 as where the error is thrown. I don't know if I'm reading it wrong, but my code doesn't have 440 lines in it. Does it mean line 4, character 40? I also moved SetSwapInterval() and SDL_GL_Doublebuffer functions to after the context was made.
Edit 2: Ok, so after some more digging, the line the error was thrown at was 439, (I had a load of commented out stuff which is why the number is so big), right after glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0). The complaint is INVALID_OPERATION. It also said INVALID_VALUE at line 405 - the line afterglGenBuffers(1, &EBO); when I started up the program, but didn't say it again.
Edit 3: After some more checking, it's definitely glDrawElements() that's causing this, not anything else.
I understand from this question that shader objects can be detached and deleted as soon as the program is linked.
Do buffer objects behave similarly with respect to the VAO? Can I delete them after the VAO been initialized (at the end of Scene::Scene() below) or should I leave my code as is, binding them every time I want to use them?
Scene.h:
class Scene
{
public:
void render();
Scene();
~Scene();
private:
GLuint vertexArray;
GLuint vertexBuffer;
GLuint indexBuffer;
GLuint program;
};
Scene.cpp:
#include <GL/glew.h>
#include <stdio.h>
#include "Scene.h"
namespace
{
void printProgramInfoLog(GLuint program);
void printShaderInfoLog(GLuint shader);
}
void Scene::render()
{
glBindVertexArray(vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glUseProgram(program);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
glUseProgram(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
Scene::Scene()
{
const float vertices[] =
{
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
};
const unsigned short indices[] =
{
0,
1,
2,
0,
2,
3,
};
const char* vertexShaderSource[] =
{
"#version 330\n",
"\n",
"in vec3 position;\n",
"\n",
"out vec2 fspos;",
"\n",
"void main()\n",
"{\n",
" gl_Position = vec4(position, 1.0);\n",
"fspos = vec2(position.x, position.y);\n",
"}\n",
};
const char* fragmentShaderSource[] =
{
"#version 330\n",
"\n",
"precision highp float;\n",
"\n",
"in vec2 fspos;",
"\n",
"out vec4 color;\n",
"\n",
"void main()\n",
"{\n",
" color = vec4(abs(fspos.x), abs(fspos.y), 0.0, 1.0);\n",
"}\n",
};
//-------------------------------
// Create and bind vertex array.
//-------------------------------
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
//--------------------------------------
// Create, bind and fill vertex buffer.
//--------------------------------------
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//-------------------------------------
// Create, bind and fill index buffer.
//-------------------------------------
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//-----------------
// Create program.
//-----------------
program = glCreateProgram();
//----------------------------------
// Create and attach vertex shader.
//----------------------------------
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, sizeof(vertexShaderSource) / sizeof(vertexShaderSource[0]), vertexShaderSource, 0);
glCompileShader(vertexShader);
printShaderInfoLog(vertexShader);
glAttachShader(program, vertexShader);
//------------------------------------
// Create and attach fragment shader.
//------------------------------------
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, sizeof(fragmentShaderSource) / sizeof(fragmentShaderSource[0]), fragmentShaderSource, 0);
glCompileShader(fragmentShader);
printShaderInfoLog(fragmentShader);
glAttachShader(program, fragmentShader);
//---------------
// Link program.
//---------------
glLinkProgram(program);
printProgramInfoLog(program);
//-----------------------
// Set up shader inputs.
//-----------------------
GLint position = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(position);
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, 0);
//------------------------------------
// Detach and delete fragment shader.
//------------------------------------
glDetachShader(program, fragmentShader);
glDeleteShader(fragmentShader);
//----------------------------------
// Detach and delete vertex shader.
//----------------------------------
glDetachShader(program, vertexShader);
glDeleteShader(vertexShader);
//----------------------
// Unbind vertex array.
//----------------------
glBindVertexArray(0);
//!!!!!!!!!!!!!!!!!!!
// Unbinding and deleting the buffers here and only binding the VAO in
// render() works just fine, but is it okay to do this or should I leave
// it as is?
//!!!!!!!!!!!!!!!!!!!
}
Scene::~Scene()
{
glDeleteProgram(program);
glDeleteBuffers(1, &indexBuffer);
glDeleteBuffers(1, &vertexBuffer);
glDeleteVertexArrays(1, &vertexArray);
}
namespace
{
void printProgramInfoLog(GLuint program)
{
int logLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
char* log = new char[logLength];
glGetProgramInfoLog(program, logLength, 0, log);
fprintf(stderr, "%s", log);
delete[] log;
}
}
void printShaderInfoLog(GLuint shader)
{
int logLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
char* log = new char[logLength];
glGetShaderInfoLog(shader, logLength, 0, log);
fprintf(stderr, "%s", log);
delete[] log;
}
}
}
VAOs do not store the data. They store the buffer object bindings and vertex formats. The buffer objects are still the holders of the data storage.
So no, don't do that.