I am trying to get a square on the screen. This code should draw a square, however it omits the last vertex and only draws a triangle.
Where have I gone wrong?
#include <glad/gl.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include "linmath.h"
#include <stdlib.h>
#include <stdio.h>
static const struct
{
float x, y;
float r, g, b;
} vertices[4] =
{
{ -0.5f, -0.5f, 1.f, 0.f, 0.f },
{ 0.5f, -0.5f, 0.f, 1.f, 0.f },
{ -0.5f, 0.5f, 0.f, 0.f, 1.f },
{ 0.5f, 0.5f, 0.f, 1.f, 1.f}
};
static const char* vertex_shader_text =
"#version 110\n"
"uniform mat4 MVP;\n"
"attribute vec3 vCol;\n"
"attribute vec2 vPos;\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
" color = vCol;\n"
"}\n";
static const char* fragment_shader_text =
"#version 110\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(color, 1.0);\n"
"}\n";
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
int main(void)
{
GLFWwindow* window;
GLuint vertex_buffer,edge_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location, vcol_location;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSwapInterval(1);
// NOTE: OpenGL error checks have been omitted for brevity
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
vcol_location = glGetAttribLocation(program, "vCol");
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) 0);
glEnableVertexAttribArray(vcol_location);
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
sizeof(vertices[0]), (void*) (sizeof(float) * 2));
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
mat4x4 m, p, mvp;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4x4_identity(m);
mat4x4_rotate_Z(m, m, (float) glfwGetTime());
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
mat4x4_mul(mvp, p, m);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDrawArrays(GL_POLYGON, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
I only have 3 of the 4 vertices rendering, thus resulting in a triangle instead of a square.
You're telling opengl to render 3 vertices instead of 4 with glDrawArrays(GL_POLYGON, 0, 3);
Change it to glDrawArrays(GL_POLYGON, 0, 4);
Related
I'm trying to display some simple text in OpenGL, but all I get is a black screen. I'm using cglm (glm for c), glad, and glfw. Here is my code:
#include <iostream>
#include <map>
#include <string>
#include <vendor/glad/glad.h>
#include <vendor/GLFW/glfw3.h>
#include <vendor/cglm/cglm.h>
#include <ft2build.h>
#include FT_FREETYPE_H
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
const char *vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>\n"
"out vec2 TexCoords;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
" gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);\n"
" TexCoords = vertex.zw;\n"
"};\n";
const char *fragmentShaderSource =
"#version 330 core\n"
"in vec2 TexCoords;\n"
"out vec4 color;\n"
"uniform sampler2D text;\n"
"uniform vec3 textColor;\n"
"void main()\n"
"{ \n"
" vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);\n"
" color = vec4(textColor, 1.0) * sampled;\n"
"};\n";
typedef struct my_vec3
{
float x;
float y;
float z;
} my_vec3;
typedef struct my_vec2
{
int x;
int y;
} my_vec2;
typedef struct Character
{
unsigned int TextureID; // ID handle of the glyph texture
my_vec2 Size; // Size of glyph
my_vec2 Bearing; // Offset from baseline to left/top of glyph
unsigned int Advance; // Horizontal offset to advance to next glyph
} Character;
void framebuffer_size_callback(GLFWwindow *window, int width, int height);
void processInput(GLFWwindow *window);
void RenderText(GLuint shader, std::string text, float x, float y, float scale, my_vec3 color);
unsigned int VAO, VBO;
std::map<GLchar, Character> Characters;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
printf("Failed to create GLFW window");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
printf("Failed to initialize GLAD");
return -1;
}
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED %s\n", infoLog);
}
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED %s\n", infoLog);
}
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED %s\n", infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
mat4 projection;
glm_mat4_identity(projection);
glm_ortho(0.0, static_cast<float>(SCR_WIDTH), 0.0f, static_cast<float>(SCR_HEIGHT), 0.01, 100.0, projection);
// glm_perspective(4.8, (float)SCR_WIDTH/(float)SCR_WIDTH, 0.01, 100.0, projection);
glUseProgram(shaderProgram);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, &projection[0][0]);
FT_Library ft;
if (FT_Init_FreeType(&ft))
{
std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
return -1;
}
std::string font_name = "/home/filip/Downloads/arial/arial.ttf";
FT_Face face;
if (FT_New_Face(ft, font_name.c_str(), 0, &face))
{
std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;
return -1;
}
else
{
FT_Set_Pixel_Sizes(face, 0, 48);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for (unsigned char c = 0; c < 128; c++)
{
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
{
std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
continue;
}
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
my_vec2 size;
size.x = face->glyph->bitmap.width;
size.y = face->glyph->bitmap.rows;
my_vec2 bearing;
bearing.x = face->glyph->bitmap_left;
bearing.y = face->glyph->bitmap_top;
Character character = {
texture,
size,
bearing,
static_cast<unsigned int>(face->glyph->advance.x)};
Characters.insert(std::pair<char, Character>(c, character));
}
glBindTexture(GL_TEXTURE_2D, 0);
}
FT_Done_Face(face);
FT_Done_FreeType(ft);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(window))
{
processInput(window);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
my_vec3 color1;
color1.x = 0.5;
color1.y = 0.8;
color1.z = 0.2;
my_vec3 color2;
color2.x = 0.3;
color2.y = 0.7;
color2.z = 0.9;
RenderText(shaderProgram, "This is sample text", 125.0f, 125.0f, 1.0f, color1);
RenderText(shaderProgram, "(C) LearnOpenGL123.com", 370.0f, 370.0f, 0.5f, color2);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
}
void RenderText(GLuint shader, std::string text, float x, float y, float scale, my_vec3 color)
{
glUseProgram(shader);
glUniform3f(glGetUniformLocation(shader, "textColor"), color.x, color.y, color.z);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
std::string::const_iterator c;
for (c = text.begin(); c != text.end(); c++)
{
Character ch = Characters[*c];
float xpos = x + ch.Bearing.x * scale;
float ypos = y - (ch.Size.y - ch.Bearing.y) * scale;
float w = ch.Size.x * scale;
float h = ch.Size.y * scale;
float vertices[6][4] = {
{xpos, ypos + h, 0.0f, 0.0f},
{xpos, ypos, 0.0f, 1.0f},
{xpos + w, ypos, 1.0f, 1.0f},
{xpos, ypos + h, 0.0f, 0.0f},
{xpos + w, ypos, 1.0f, 1.0f},
{xpos + w, ypos + h, 1.0f, 0.0f}};
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // be sure to use glBufferSubData and not glBufferData
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
x += (ch.Advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
I've been following this tutorial. The program compiles and runs without any errors, except that it does not render anything and I can not seem to figure out why.
It seems that you are placing your text on plane z=0
" gl_Position = projection * vec4(vertex.xy, **0.0**, 1.0);\n"
But your camera is looking to -Z (standard camera) from -0.01 to -100.0f.
glm_ortho(0.0, static_cast<float>(SCR_WIDTH), 0.0f, static_cast<float>(SCR_HEIGHT), **0.01, 100.0**, projection);
You can solve it just moving your text a little bit to the -Z axis. A value between the range you have specified in the Zmin, Zmax parameters of the glm_ortho function. Just to be inside the box that ortho is defining.
" gl_Position = projection * vec4(vertex.xy, **-3.0**, 1.0);\n"
It doesn't mind because it is an orthographic projection. Objects have the same size no matter how depth they are.
More details about projection can be found here http://www.songho.ca/opengl/gl_transform.html
I'm trying to use glVertexAttribFormat and glVertexAttribBinding to create two triangles, but it doesn't work. I followed the description of how to do this in the question here (Render one VAO containing two VBOs). I don't really knnow what to try. I am new to OpenGL and all descriptions of glVertexAttribFormat appear to assume you already know OpenGL.
This is my code:
#include <glad/glad.h>
#include <glfw/glfw3.h>
#include <iostream>
void adjustViewportToWindowSize(GLFWwindow* window, int width, int height);
void checkEsc(GLFWwindow* window);
int main(void)
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Tab name", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, 800, 600); //size of GL rendering window.
glfwSetFramebufferSizeCallback(window, adjustViewportToWindowSize);
const char* vertexShaderSource = "#version 430 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 430 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\0";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
//Attaching shaders to program
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//Can delete shader objects after they are linked
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float triangleVertices1[] = {
-0.50f, 0.0f, 0.0f,
-0.25f, 0.5f, 0.0f,
0.00f, 0.0f, 0.0f
};
float triangleVertices2[] = {
0.0f, 0.0f, 0.0f,
0.25f, 0.5f, 0.0f,
0.5f, 0.0f, 0.0f
};
unsigned int aVBO[2], VAO2;
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);
glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0); //format setup without a buffer
glVertexAttribBinding(0, 0);
glBindVertexArray(0);
//Bind Buffers to data next
glGenBuffers(2, aVBO);
glBindBuffer(GL_ARRAY_BUFFER, aVBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices1), triangleVertices1, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, aVBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices2), triangleVertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while (!glfwWindowShouldClose(window))
{
checkEsc(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO2);
glBindVertexBuffer(0, aVBO[0], 0, 3*sizeof(float));
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexBuffer(0, aVBO[1], 0, 3*sizeof(float));
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
//Clear up
glDeleteVertexArrays(1, &VAO2);
glDeleteBuffers(1, aVBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
void adjustViewportToWindowSize(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void checkEsc(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
Can also be accessed on github: https://github.com/Ritzerk/OpenGLSelfStudy
In addition to setting up the buffer bindings, you also have to enable the vertex attribute in the shader. To do so, you have to call glEnableVertexAttribArray during VAO setup:
glBindVertexArray(VAO2);
glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0);
glVertexAttribBinding(0, 0);
//Enable input in shader
glEnableVertexAttribArray(0);
glBindVertexArray(0);
This OpenGL code is supposed to render a triangle moving back and forth on the X-axis:
#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <string.h>
#include <cmath>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Window dimensions
const GLint WIDTH = 800, HEIGHT = 600;
GLuint VAO, VBO, shader, uniformModel;
bool direction = true;
float triOffest = 0.0f;
float triMaxOffset = 0.7f;
float triIncrement = 0.0005f;
// Vertex Shader
static const char* vShader = " \n\
#version 330 \n\
\n\
layout (location = 0) in vec3 pos; \n\
\n\
uniform mat4 model; \n\
\n\
void main() \n\
{ \n\
gl_Position = model * vec4(0.4 * pos.x, 0.4 * pos.y, pos.z, 1.0); \n\
}";
// Fragment Shader
static const char* fShader = " \n\
#version 330 \n\
\n\
out vec4 colour; \n\
\n\
void main() \n\
{ \n\
colour = vec4(1.0, 0.0, 0.0, 1.0); \n\
}";
void CreateTriangle()
{
GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
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, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void AddShader(GLuint theProgram, const char* shaderCode, GLenum shaderType)
{
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1];
theCode[0] = shaderCode;
GLint codeLength[1];
codeLength[0] = strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (!result)
{
glGetShaderInfoLog(theShader, sizeof(eLog), NULL, eLog);
printf("Error compiling %d shader: '%s'\n", shaderType, eLog);
return;
}
glAttachShader(theProgram, theShader);
}
void CompileShaders()
{
shader = glCreateProgram();
if (!shader)
{
printf("Error creating shader program!\n");
return;
}
AddShader(shader, vShader, GL_VERTEX_SHADER);
AddShader(shader, fShader, GL_FRAGMENT_SHADER);
GLint result = 0;
GLchar eLog[1024] = { 0 };
glLinkProgram(shader);
glGetProgramiv(shader, GL_LINK_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shader, sizeof(eLog), NULL, eLog);
printf("Error linking program: '%s'\n", eLog);
return;
}
glValidateProgram(shader);
glGetProgramiv(shader, GL_VALIDATE_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(shader, sizeof(eLog), NULL, eLog);
printf("Error validating program: '%s'\n", eLog);
return;
}
uniformModel = glGetUniformLocation(shader, "model");
}
int main()
{
// Initialise GLFW
if (!glfwInit())
{
printf("GLFW initialisation failed!");
glfwTerminate();
return 1;
}
// Setup GLFW window properties
// OpenGL version
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// core profile = No backwards Compatibility
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
GLFWwindow* mainWindow = glfwCreateWindow(WIDTH, HEIGHT, "Test Window", NULL, NULL);
if (!mainWindow)
{
printf("GLFW window creation failed!");
glfwTerminate();
return 1;
}
// Get buffer size information
int bufferWidth, bufferHeight;
glfwGetFramebufferSize(mainWindow, &bufferWidth, &bufferHeight);
// Set context for GLEW to use
glfwMakeContextCurrent(mainWindow);
// Allow modern extension features
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
printf("GLEW initialisation failed!");
glfwDestroyWindow(mainWindow);
glfwTerminate();
return 1;
}
// Setup viewport size
glViewport(0, 0, bufferWidth, bufferHeight);
CreateTriangle();
CompileShaders();
// Loop unitil window closed
while (!glfwWindowShouldClose(mainWindow))
{
// Get + Handle user input events
glfwPollEvents();
if (direction)
{
triOffest += triIncrement;
}
else
{
triOffest -= triIncrement;
}
if (abs(triOffest) >= triMaxOffset)
{
direction = !direction;
}
// Clear window
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
glm::mat4 model;
model = glm::translate(model, glm::vec3(triOffest, 0.0f, 0.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glUseProgram(0);
glfwSwapBuffers(mainWindow);
}
return 0;
}
However, after I run the code I just see a blank screen.(The triangle did render, before multiplying the translation transformation matrix with the vertex position in the vertex shader). The triangle seems to disappear after I apply the transformation model.
Could anyone help me figure out what's wrong?
As #Botje advised, I just had to initiallize the mat4 model as glm::mat4 model(1.0);
inside the main() and done.. problem solved.
I've looked for an answer to my problem for two days. Maybe I'm just terrible at searching but there doesn't seem to be an answer already out there.
I am trying to draw lines on the screen using OpenGL's glDrawArrays(GL_LINES, ..., ...). This is the current code for my fragment shader:
#version 330 core
in vec4 vertexColor;
out vec4 color;
void main( )
{
//color = vec3(0.5f, 1.0f, 1.0f);
color = vec4(0.5f, 1.0f, 1.0f, 0.5f);
//color = vertexColor;
}
Originally the color=vertexColor line was supposed to work, but nothing appeared on the screen. I thought maybe something was wrong with the data being sent from the vertex shader so I tried setting the output manually in the fragment shader. I accidentally made it a vec3 instead of a vec4 and I got an error in my console window telling me compilation of the shader had failed. But the lines appeared! They showed up in the right spot as white/gray lines of static. When I corrected the mistake and set the output to a vec4, like shown, the lines were invisible again and I had no compilation error.
What am I doing wrong that makes my lines invisible?
Edit:
Here is my first go at a "minimal, complete, and verifiable example". If you link a project with these files to GLEW, GLFW and GLM, this should run on your system. If I'm not supposed to upload a whole program, I apologize. This seems a bit big, but I don't know how else it could be "complete".
Instead of making two white static lines, this one is making only one solid black line when the fragment shader fails to compile. It still renders nothing when compilation is successful.
Main.cpp
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "ShaderMaker.h"
#include "TargetBox.h"
const GLint WIDTH = 800, HEIGHT = 600;
//Camera
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
GLfloat yaw = -90.0f;
GLfloat pitch = 0.0f;
// Delta time
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;
int main() {
cameraFront.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront.y = sin(glm::radians(pitch));
cameraFront.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(cameraFront);
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Debugger", nullptr, nullptr);
int screenWidth, screenHeight;
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
if (window == nullptr) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return EXIT_FAILURE;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (GLEW_OK != glewInit()) {
std::cout << "Failed to initialize GLEW" << std::endl;
return EXIT_FAILURE;
}
glViewport(0, 0, screenWidth, screenHeight);
glEnable(GL_DEPTH_TEST);
TargetBox tb;
GLuint modelLoc = tb.getUniform("model");
GLuint viewLoc = tb.getUniform("view");
GLuint projectionLoc = tb.getUniform("projection");
glm::mat4 projection;
projection = glm::perspective(glm::radians(45.0f), (float)screenWidth / screenHeight, 0.1f, 100.0f);
while (!glfwWindowShouldClose(window)) {
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
glClearColor(0.5f, 0.7f, 0.9f, 1.0f); // Unnecessary, but adds some color to an otherwise blank window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 view;
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
tb.useShader();
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(tb.getVAO());
glm::vec3 posMod = tb.getPos();
glm::mat4 model;
model = glm::translate(model, glm::vec3(posMod.x, posMod.y, posMod.z));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawArrays(GL_LINES, 0, 4);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glfwTerminate();
return EXIT_SUCCESS;
}
ShaderMaker.h
#pragma once
#ifndef SHADERMAKER_H
#define SHADERMAKER_H
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<GL/glew.h>
class ShaderMaker {
public:
// The program ID
GLuint Program;
// Constructor reads and builds the shader
ShaderMaker(const GLchar* vertexPath, const GLchar* fragmentPath) {
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// ensures ifstream objects can throw exceptions:
vShaderFile.exceptions(std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::badbit);
try {
// Open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// Read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// close file handlers
vShaderFile.close();
fShaderFile.close();
// Convert stream into GLchar array
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (std::ifstream::failure e) {
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar* fShaderCode = fragmentCode.c_str();
// 2. Compile shaders
GLuint fragment;
GLint success;
GLchar infoLog[512];
// Vertex shader
GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// Print compile errors if any
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Similar for fragment shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
// Print compile errors if any
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Shader program
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
glLinkProgram(this->Program);
// Print linking errors if any
glGetShaderiv(this->Program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// Delete the shaders as they're linked into our program now and no longer necessary
glDeleteShader(vertex);
glDeleteShader(fragment);
}
// Use the program
void Use() { glUseProgram(this->Program); }
// Get a uniform
GLint getUniform(const GLchar * name) {
return glGetUniformLocation(this->Program, name);
}
};
#endif
TargetBox.h
#pragma once
#ifndef TARGETBOX_H
#define TARGETBOX_H
#define GLEW_STATIC
#include <GL/glew.h>
#include<glm/glm.hpp>
#include <GLFW/glfw3.h>
#include "ShaderMaker.h"
class TargetBox
{
public:
TargetBox();
~TargetBox();
void useShader();
GLuint getVAO();
glm::vec3 getPos();
void setPos(glm::vec3 p);
GLuint getUniform(GLchar * u);
private:
glm::vec3 pos;
GLuint VAO, VBO;
const GLchar *vertexShaderPath = ".\\VShaderLine.txt";
const GLchar *fragmentShaderPath = ".\\FShaderLine.txt";
ShaderMaker shader = ShaderMaker(vertexShaderPath, fragmentShaderPath);
};
#endif
TargetBox.cpp
#include "TargetBox.h"
TargetBox::TargetBox()
{
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
GLfloat vertices[] = {
-2, 0, -5, 1.0f, 1.0f, 1.0f,
2, 0, 5, 1.0f, 1.0f, 1.0f,
2, 0, 5, 1.0f, 0.0f, 0.0f,
2, 10, 5, 0.0f, 1.0f, 0.0f
};
size_t data_len = sizeof(vertices);
glBufferData(GL_ARRAY_BUFFER, data_len, vertices, GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//Color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
TargetBox::~TargetBox()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
}
void TargetBox::useShader() { shader.Use(); }
GLuint TargetBox::getVAO() { return VAO; }
glm::vec3 TargetBox::getPos() { return pos; }
void TargetBox::setPos(glm::vec3 p) { pos = p; }
GLuint TargetBox::getUniform(GLchar * u) { return shader.getUniform(u); }
VShaderLine.txt
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
out vec4 vertexColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main( )
{
// The order of multiplication is important?
gl_Position = projection * view * model * vec4( position, 1.0 );
vertexColor = vec4(color.xyz, 1.0f);
}
FShaderLine.txt
#version 330 core
in vec4 vertexColor;
out vec4 color;
void main( )
{
color = vec3(0.5f, 1.0f, 1.0f);
//color = vec4(0.5f, 1.0f, 1.0f, 0.5f);
//color = vertexColor;
}
In order to understand how to use two buffers and binding it to vao i am trying to display a triangle with some color. I am getting an error like this
First-chance exception at 0x00000000 in ConsoleApplication12.exe: 0xC0000005: Access violation executing location 0x00000000.
When i try to debug, this error is caused by the line in the code
glCreateVertexArrays(1, &vao);
I did initialized vao, but i do not understand why the error occurred. Please help me..
Here is the code
#include <stdlib.h>
#include<iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include "glm/glm.hpp"
#define BUFFER_OFFSET(offset) ((GLvoid *) offset)
GLuint program;
static int timeFor =0;
GLuint vPos;
GLuint buffer[2];
GLuint vao = 0;
void init()
{
static const GLfloat positions[] = { 0.1f, 0.2f, 0.3f, 0.0f};
static const GLfloat colors[] = { 1.0f, 0.0f, 0.0f, 1.0f};
glCreateVertexArrays(1, &vao);
glCreateBuffers(2, &buffer[0]);
glNamedBufferStorage(buffer[0], sizeof(positions), positions, 0);
glVertexArrayVertexBuffer(vao, 0, buffer[0], 0, sizeof(glm::vec4));
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(vao, 0, 0);
glNamedBufferStorage(buffer[1], sizeof(colors), colors, 0);
glVertexArrayVertexBuffer(vao, 1, buffer[1], 0, sizeof(glm::vec4));
glVertexArrayAttribFormat(vao, 1, 4, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(vao, 1, 1);
const char* vSource = {
"#version 330\n"
"layout (location = 0) in vec4 offset;"
"layout (location = 1) in vec4 color;"
"out vec4 fColor;"
"void main() {"
"const vec4 vertices[3] = vec4[3](vec4( 0.25, -0.25, 0.5, 1.0), vec4( -0.25, -0.25, 0.5, 1.0), vec4( 0.25, 0.25, 0.5, 1.0));"
"gl_Position = vertices[gl_VertexID] + offset;"
"fColor = color;"
"}"
};
const char* fSource = {
"#version 330\n"
"in vec4 fColor;"
"out vec4 fragColor;"
"void main() {"
"fragColor = fColor;"
"}"
};
GLuint vShader, fShader;
vShader = glCreateShader(GL_VERTEX_SHADER);
fShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vShader, 1, &vSource, NULL);
glShaderSource(fShader, 1, &fSource, NULL);
glCompileShader(vShader);
glCompileShader(fShader);
program = glCreateProgram();
glAttachShader(program, vShader);
glAttachShader(program, fShader);
glLinkProgram(program);
glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
}
void reshape(int width, int height)
{
glViewport(0, 0, width, height);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
}
void main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow(argv[0]);
glewInit();
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
}
I checked my openGL version its 4.4, in which glCreateVertexArrays is not supported instead of that glGenVertexArrays must be used.