How to draw two or more triangles in OpenGL? - c++

Can someone show show me how I can modify my code so I can draw more than one triangle?
I'm hoping to accomplish something like the picture shown here:
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
#include <common/shader.hpp>
int main(void)
{
// Initialise GLFW
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
getchar();
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);
// Open a window and create its OpenGL context
window = glfwCreateWindow(1024, 768, "Tutorial 04 - Colored Cube", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders("TransformVertexShader.vertexshader", "ColorFragmentShader.fragmentshader");
// Get a handle for our "MVP" uniform
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
int verticeCount = 3;
static const GLfloat g_vertex_buffer_data[] = {
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
};
static const GLfloat g_color_buffer_data[] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
do {
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(programID);
glm::mat4 MVP = glm::mat4(1.0);
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute. 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
);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, verticeCount * 3);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
// Cleanup VBO and shader
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &colorbuffer);
glDeleteProgram(programID);
glDeleteVertexArrays(1, &VertexArrayID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}

It's actually right in front of your nose.
Triangles are defined by 3 vertices.
static const GLfloat g_vertex_buffer_data[] = {
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
};
Here, you initialized your vertex data array with 3, 3-dimensional vertices. That's 1 triangle.
Adding more triangles, i.e. 3 sets of 3 vertices, to this array is all you need to do, along with extending the g_color_buffer_data array and changing verticeCount accordingly.
So this:
static const GLfloat g_vertex_buffer_data[] = {
-0.50f, +0.50f, +0.00f,
+0.50f, +0.50f, +0.00f,
+0.50f, -0.50f, +0.00f,
-0.50f, -0.25f, +0.00f,
-0.50f, -0.50f, +0.00f,
-0.25f, -0.50f, +0.00f,
};
static const GLfloat g_color_buffer_data[] = {
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
};
would give you 2 triangles: 1 red, 1 blue.
You could also define verticeCount as:
int verticeCount = sizeof(g_vertex_buffer_data) / (sizeof(g_vertex_buffer_data[0]) * 3);
(Thread on finding the size of a C-style array in C++)
This way you won't manually have to change it.

You can always create a new vertex buffer, but it is usually a good idea to implement vertex and fragment shaders instead. If you choose to use shaders, you can draw the buffer, transform the vertex shader, then draw the buffer again. Fragment shaders also provide a better way of specifying color dynamically. You can read more and see some examples at https://learnopengl.com/Getting-started/Shaders

Related

Trouble Rendering 2 Object separately in OpenGL

I have taken code for two projects. One being the code for creating a cube and another is the code for creating a pyramid. I am now trying to render both of the objects in OpenGL which I have done the problem is the objects are attached to one another. I have added some code heading towards rendering them separately, however I am now stuck where my cube is only showing 3 of the triangles used to create it and the whole pyramid shows. Yet the objects are still attached to one another. Any help or guidance?
#include <iostream> // cout, cerr
#include <cstdlib> // EXIT_FAILURE
#include <GL/glew.h> // GLEW library
#include <GLFW/glfw3.h> // GLFW library
// GLM Math Header inclusions
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std; // Standard namespace
using glm::vec3;
using glm::mat4;
/*Shader program Macro*/
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version " core \n" #Source
#endif
// Unnamed namespace
namespace
{
const char* const WINDOW_TITLE = "3D Scene Troubleshooting"; // Macro for window title
// Variables for window width and height
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
// Stores the GL data relative to a given mesh
struct GLMesh
{
GLuint vao; // Handle for the vertex array object 1
GLuint vao2; // Handle for the vertex array object 2
GLuint vbos[2]; // Handles for the vertex buffer objects 1
GLuint vbos2[2]; // Handles for the vertex buffer objects 2
GLuint cubeIndices; // Number of cube indices of the mesh
GLuint pyramidIndices; // Number of pyramid indices of the mesh
};
// Main GLFW window
GLFWwindow* gWindow = nullptr;
// Triangle mesh data
GLMesh gMesh;
// Shader program
GLuint gProgramId;
}
/* User-defined Function prototypes to:
* initialize the program, set the window size,
* redraw graphics on the window when resized,
* and render graphics on the screen
*/
bool UInitialize(int, char* [], GLFWwindow** window);
void UResizeWindow(GLFWwindow* window, int width, int height);
void UProcessInput(GLFWwindow* window);
void UCreateMesh(GLMesh& mesh);
void UDestroyMesh(GLMesh& mesh);
void URender();
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId);
void UDestroyShaderProgram(GLuint programId);
/* Vertex Shader Source Code*/
const GLchar* vertexShaderSource = GLSL(440,
layout(location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout(location = 1) in vec4 color; // Color data from Vertex Attrib Pointer 1
out vec4 vertexColor; // variable to transfer color data to the fragment shader
//Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f); // transforms vertices to clip coordinates
vertexColor = color; // references incoming color data
}
);
/* Fragment Shader Source Code*/
const GLchar* fragmentShaderSource = GLSL(440,
in vec4 vertexColor; // Variable to hold incoming color data from vertex shader
out vec4 fragmentColor;
void main()
{
fragmentColor = vec4(vertexColor);
}
);
int main(int argc, char* argv[])
{
if (!UInitialize(argc, argv, &gWindow))
return EXIT_FAILURE;
// Create the mesh
UCreateMesh(gMesh); // Calls the function to create the Vertex Buffer Object
// Create the shader program
if (!UCreateShaderProgram(vertexShaderSource, fragmentShaderSource, gProgramId))
return EXIT_FAILURE;
// Sets the background color of the window to black (it will be implicitely used by glClear)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// render loop
// -----------
while (!glfwWindowShouldClose(gWindow))
{
// input
// -----
UProcessInput(gWindow);
// Render this frame
URender();
glfwPollEvents();
}
// Release mesh data
UDestroyMesh(gMesh);
// Release shader program
UDestroyShaderProgram(gProgramId);
exit(EXIT_SUCCESS); // Terminates the program successfully
}
// Initialize GLFW, GLEW, and create a window
bool UInitialize(int argc, char* argv[], GLFWwindow** window)
{
// GLFW: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// GLFW: window creation
// ---------------------
* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "3D Scene TroubleShooting", NULL, NULL);
if (*window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return false;
}
glfwMakeContextCurrent(*window);
glfwSetFramebufferSizeCallback(*window, UResizeWindow);
// GLEW: initialize
// ----------------
// Note: if using GLEW version 1.13 or earlier
glewExperimental = GL_TRUE;
GLenum GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult)
{
std::cerr << glewGetErrorString(GlewInitResult) << std::endl;
return false;
}
// Displays GPU OpenGL version
cout << "INFO: OpenGL Version: " << glGetString(GL_VERSION) << endl;
return true;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
void UProcessInput(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 UResizeWindow(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
// Functioned called to render a frame
void URender()
{
// Enable z-depth
glEnable(GL_DEPTH_TEST);
// Clear the frame and z buffers
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1. Scales the object by 2
glm::mat4 scale = glm::scale(glm::vec3(2.0f, 2.0f, 2.0f));
// 2. Rotates shape by 15 degrees in the x axis
glm::mat4 rotation = glm::rotate(45.0f, glm::vec3(1.0, 1.0f, 1.0f));
// 3. Place object at the origin
glm::mat4 translation = glm::translate(glm::vec3(0.5f, -0.3f, -0.1f));
// Model matrix: transformations are applied right-to-left order
glm::mat4 model = translation * rotation * scale;
// Transforms the camera: move the camera back (z axis)
glm::mat4 view = glm::translate(glm::vec3(-2.6f, 2.9f, -5.0f));
// Creates a orthographic projection
glm::mat4 projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f);
// Set the shader to be used
glUseProgram(gProgramId);
// Retrieves and passes transform matrices to the Shader program
GLint modelLoc = glGetUniformLocation(gProgramId, "model");
GLint viewLoc = glGetUniformLocation(gProgramId, "view");
GLint projLoc = glGetUniformLocation(gProgramId, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
// Activate the VBOs contained within the mesh's VAO
glBindVertexArray(gMesh.vao);
glBindVertexArray(gMesh.vao2);
// Draws the CUBE
glDrawElements(GL_TRIANGLES, gMesh.cubeIndices, GL_UNSIGNED_SHORT, NULL); // Draws the triangle
glDrawArrays(GL_TRIANGLES, 0, 24);
// Draws the PYRAMID
glDrawElements(GL_TRIANGLES, gMesh.pyramidIndices, GL_UNSIGNED_SHORT, NULL); // Draws the triangle
glDrawArrays(GL_TRIANGLES, 0, 54);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
glfwSwapBuffers(gWindow); // Flips the the back buffer with the front buffer every frame.
}
void UCylinder(GLUquadric* qobj, GLdouble baseRadius, GLdouble topRadius, GLdouble height, GLint slices, GLint stacks)
{
GLUquadricObj* quadratic;
quadratic = gluNewQuadric();
gluCylinder(quadratic, 0.3f, 0.3f, 3.0f, 32, 32);
glDrawElements(GL_TRIANGLES, gMesh.cubeIndices, GL_UNSIGNED_SHORT, NULL);
}
// Implements the UCreateMesh function
void UCreateMesh(GLMesh& mesh)
{
// Position and Color data
GLfloat verts[] = {
// Vertex Positions // Colors (r,g,b,a)
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Right Vertex 0 (effects top right and bottom right top sides of cube)
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Bottom Right corner Vertex 1
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Bottom center of cube Vertex 2 (effects bottom left and bottomr right sides of cube)
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Center of cube Vertex 3 (effects top, bottom left and bottom right sides of cube)
0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // Bottomside left of cube Vertex 4 (doesn't effect cube color at all with current orientation)
0.5f, 0.5f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top center of cube Vertex 5
-0.5f, 0.5f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top left corner cube Vertex 6 (effects both top and bottom left sides of cube)
-0.5f, -0.5f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Bottom left of cube Vertex 7
// Vertex Positions // Colors (r,g,b,a)
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, // Vertex 8
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, // Vertex 9
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Vertex 10
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, // Vertex 11
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, // Vertex 12
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Vertex 13
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, // Vertex 14
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, // Vertex 15
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Vertex 16
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, // Vertex 17
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f, // Vertex 18
0.0f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, // Vertex 19
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, // Vertex 20
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, // Vertex 21
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Vertex 22
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, // Vertex 23
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, // Vertex 24
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Vertex 25
};
// Index data to share position data
GLushort cubeIndices[] = {
0, 1, 3, // Triangle 1
1, 2, 3, // Triangle 2
0, 1, 4, // Triangle 3
0, 4, 5, // Triangle 4
0, 5, 6, // Triangle 5
0, 3, 6, // Triangle 6
4, 5, 6, // Triangle 7
4, 6, 7, // Triangle 8
2, 3, 6, // Triangle 9
2, 6, 7, // Triangle 10
1, 4, 7, // Triangle 11
1, 2, 7, // Triangle 12
};
GLushort pyramidIndices[] = {
8, 9, 10, // Triangle 1
11, 12, 13, // Triangle 2
14, 15, 16, // Triangle 3
17, 18, 19, // Triangle 4
20, 21, 22, // Triangle 5
23, 24, 25 // Triangle 6
};
const GLuint floatsPerVertex = 3;
const GLuint floatsPerColor = 4;
// For CUBE
glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);
// For PYRAMID
glGenVertexArrays(1, &mesh.vao2);
glBindVertexArray(mesh.vao2);
// Create 2 buffers: first one for the vertex data; second one for the indices for the CUBE
glGenBuffers(2, mesh.vbos);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbos[0]); // Activates the buffer for CUBE
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU for CUBE
// Create 2 buffers: first one for the vertex data; second one for the indices for the PYRAMID
glGenBuffers(2, mesh.vbos2);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbos2[0]); // Activates the buffer for PYRAMID
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU for PYRAMID
// For CUBE
mesh.cubeIndices = sizeof(cubeIndices) / sizeof(cubeIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbos[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices, GL_STATIC_DRAW);
// For PYRAMID
mesh.pyramidIndices = sizeof(pyramidIndices) / sizeof(pyramidIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbos2[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pyramidIndices), pyramidIndices, GL_STATIC_DRAW);
// Strides between vertex coordinates is 6 (x, y, z, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);// The number of floats before each
// Create Vertex Attribute Pointers
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
}
void UDestroyMesh(GLMesh& mesh)
{
// For CUBE
glDeleteVertexArrays(1, &mesh.vao);
glDeleteBuffers(2, mesh.vbos);
// For PYRAMID
glDeleteVertexArrays(1, &mesh.vao2);
glDeleteBuffers(2, mesh.vbos2);
}
// Implements the UCreateShaders function
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId)
{
// Compilation and linkage error reporting
int success = 0;
char infoLog[512];
// Create a Shader program object.
programId = glCreateProgram();
// Create the vertex and fragment shader objects
GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
// Retrive the shader source
glShaderSource(vertexShaderId, 1, &vtxShaderSource, NULL);
glShaderSource(fragmentShaderId, 1, &fragShaderSource, NULL);
// Compile the vertex shader, and print compilation errors (if any)
glCompileShader(vertexShaderId); // compile the vertex shader
// check for shader compile errors
glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShaderId, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
return false;
}
glCompileShader(fragmentShaderId); // compile the fragment shader
// check for shader compile errors
glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShaderId, sizeof(infoLog), NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
return false;
}
// Attached compiled shaders to the shader program
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
glLinkProgram(programId); // links the shader program
// check for linking errors
glGetProgramiv(programId, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(programId, sizeof(infoLog), NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
return false;
}
glUseProgram(programId); // Uses the shader program
return true;
}
void UDestroyShaderProgram(GLuint programId)
{
glDeleteProgram(programId);
}
See Vertex Specification. You cannot specify 2 vertex array objects at the same time. You have to do this in a row.
The Vertex Array Binding is a global state. Only one VAO can be bound at a time.
When calling OpenGL instructions like glVertexAttribPointer, glEnableVertexAttribArray and glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...)`, the state of the currently bound Vertex Array Object is changed. Note that different VAOs can use the same data buffers.
void UCreateMesh(GLMesh& mesh)
{
// [...]
glGenBuffers(1, mesh.vbos);
glGenBuffers(2, mesh.vbos2);
// 1 Vertex Buffer for both objects
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbos[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
// Strides between vertex coordinates is 6 (x, y, z, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);// The number of floats before each
// CUBE
glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);
// Create Vertex Attribute Pointers
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
mesh.cubeIndices = sizeof(cubeIndices) / sizeof(cubeIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbos[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices, GL_STATIC_DRAW);
// PYRAMID
glGenVertexArrays(1, &mesh.vao2);
glBindVertexArray(mesh.vao2);
// Create Vertex Attribute Pointers
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
mesh.pyramidIndices = sizeof(pyramidIndices) / sizeof(pyramidIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vbos2[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pyramidIndices), pyramidIndices, GL_STATIC_DRAW);
}
Finally you can draw the meshes one after the other. The draw call uses the data from the currently bound Vertex Array Object. As already mentioned, only one VAO can be bound at a time:
glBindVertexArray(gMesh.vao);
glDrawElements(GL_TRIANGLES, gMesh.cubeIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(gMesh.vao2);
glDrawElements(GL_TRIANGLES, gMesh.pyramidIndices, GL_UNSIGNED_SHORT, NULL);

How to translate and rotate a Triangle in OpenGL over time?

I am trying to rotate and translate my single triangle over time. I have already written the main.cpp and I have written separate files for my Vertex and Fragment shader source code.
Here is the code in my main.cpp file:
void framebuffer_size_callback(GFLWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
// Shaders
const char *vertexShaderSource =
"#version 410\n"
"in vec3 vp;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos, 1.0);\n"
"}\0";
const char *fragmentShaderSource =
"#version 410\n"
"out vec4 FragColor;\n"
"in vec3 myColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(myColor, 1.0f);\n"
"}\n\0";
int main ()
{
// start GL context and O/S window using the GLFW helper library
if (!glfwInit ())
{
fprintf (stderr, "ERROR: could not start GLFW3\n");
return 1;
}
// uncomment these lines if on Apple 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);
GLFWwindow* window = glfwCreateWindow(640, 480, "LearnOpenGL", NULL, NULL);
if (!window)
{
fprintf(stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return 1;
}
glfwMakeContextCurrent(window);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER);
const GLubyte* version = glGetString(GL_VERSION);
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
glEnable(GL_DEPTH_TEST); // enable depth-testing
glDepthFunc(GL_LESS);
// Draw a single triangle
float points[] = {
// positions // colors
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f 0.0f, 1.0f
};
GLuint VBO = 0;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
// Generate a VAO.
GLuint VAO = 0;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
// Compile a Vertex Shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Compile a fragment shader.
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Compile shaders into a executable shader program.
int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, fragmentShader);
glAttachShader(shaderProgram, vertexShader);
glLinkProgram(shaderProgram);
// Create another float array to make my triangle fan.
float points_5_triangles[] = {
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.5f, 0.0f, 1.0f, 2.0f, 0.5f,
// Another triangle made from point 1, 3, and 4
-0.5f,
}
// Generate another VBO for my Triangle Fan
GLuint VBO_5_triangles = 0;
glGenBuffers(1, &VBO_5_triangles);
glBindBuffer(GL_ARRAY_BUFFER, VBO_5_triangles);
glBufferData(GL_ARRAY_BUFFER, sizeof(points_5_triangles), points_5_triangles, GL_STATIC_DRAW);
// Generate another VAO for my Triangle Fan
GLuint VAO_5_triangles = 0;
glGenVertexArrays(1, &VAO_5_triangles);
glBindVertexArray(VAO_5_triangles);
glBindBuffer(GL_ARRAY_BUFFER, VBO_5_triangles);
glBufferData(GL_ARRAY_BUFFER, sizeof(points_5_triangles), points_5_triangles, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
// Drawing the triangles aka render loop
while (!glfwWindowShouldClose(window))
{
processInput(window);
// wipe the drawing surface clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw Triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
// Draw Triangle Fan
glBindVertexArray(VAO_5_triangles);
glDrawArrays(GL_TRIANGLE_FAN, 0, 7);
// swap buffers and poll IO events
glfwPollEvents();
glfwSwapBuffers(window);
}
// close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
The tutorial I am following does go over transformations but in the example it uses, the triangles have textures as well as shaders. For my purposes, I want to do this without textures added to my code.
Can someone walk me through how to add 2 transformations: translate and rotation to my "single triangle" as shown in this code?
Your triangle having a texture or not has nothing to do with transformation.
You rotate your triangle simply by calculating a transformation matrix, passing it to your vertex shader and multiply it with your coordinates.
Your Vertex Shader should look look something like this:
const char *vertexShaderSource =
"#version 410\n"
"layout (location = 0) in vec3 vp;\n"
"uniform mat4 transform;"
"void main()\n"
"{\n"
" gl_Position = transform * vec4(vp, 1.0);\n"
"}\0";
I recommend you to use the glm library for that. You calculate your matrix and pass it to your shader like this:
auto transformMatrix = glm::rotate( /* your rotation calculation */ );
auto transLoc = glGetUniformLocation(shaderProgram, "transform");
glUniformMatrix4fv(transLoc , 1, GL_FALSE, glm::value_ptr(transformMatrix));

Can't create a texture with a simple box

I'm trying to render a simple blue box to a texture, so that I can pass the texture to ImGui to render it as an image. For some reason though, I only ever get a simply white texture, and I can't figure out why. I've stripped my class down to as simple a case that I can, but I still only ever get a solid white texture, instead of a blue box that takes up most of the screen.
main.cpp
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
GLFWwindow * window;
GLuint solid_texture;
GLuint loadShaders(const char * vertex_file_source, const char * fragment_file_source)
{
// Create the shaders
GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
GLuint framgent_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
GLint Result = GL_FALSE;
int InfoLogLength;
glShaderSource(vertex_shader_id, 1, &vertex_file_source, NULL);
glCompileShader(vertex_shader_id);
// Check Vertex Shader
glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &Result);
glGetShaderiv(vertex_shader_id, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(vertex_shader_id, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
std::cerr << VertexShaderErrorMessage[0] << std::endl;
}
glShaderSource(framgent_shader_id, 1, &fragment_file_source, NULL);
glCompileShader(framgent_shader_id);
// Check Fragment Shader
glGetShaderiv(framgent_shader_id, GL_COMPILE_STATUS, &Result);
glGetShaderiv(framgent_shader_id, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(framgent_shader_id, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
std::cerr << FragmentShaderErrorMessage[0] << std::endl;
}
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, vertex_shader_id);
glAttachShader(ProgramID, framgent_shader_id);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
std::cerr << ProgramErrorMessage[0] << std::endl;
}
glDetachShader(ProgramID, vertex_shader_id);
glDetachShader(ProgramID, framgent_shader_id);
glDeleteShader(vertex_shader_id);
glDeleteShader(framgent_shader_id);
return ProgramID;
}
void generate_solid_texture()
{
glGenTextures(1, &solid_texture);
// Solid texture
unsigned char solidTexturePixels[4];
solidTexturePixels[0] = ~0;
solidTexturePixels[1] = ~0;
solidTexturePixels[2] = ~0;
solidTexturePixels[3] = ~0;
glBindTexture(GL_TEXTURE_2D, solid_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, solidTexturePixels);
glBindTexture(GL_TEXTURE_2D, 0);
}
int main(void)
{
// Initialise GLFW
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
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);
// Open a window and create its OpenGL context
window = glfwCreateWindow(1024, 768, "Tutorial 14 - Render To Texture", NULL, NULL);
if (window == NULL) {
fprintf(stderr,
"Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 "
"version of the tutorials.\n");
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// We would expect width and height to be 1024 and 768
int windowWidth = 1024;
int windowHeight = 768;
// But on MacOS X with a retina screen it'll be 1024*2 and 768*2, so we get the actual framebuffer size:
glfwGetFramebufferSize(window, &windowWidth, &windowHeight);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Hide the mouse and enable unlimited mouvement
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set the mouse at the center of the screen
glfwPollEvents();
glfwSetCursorPos(window, 1024 / 2, 768 / 2);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Setup OpenGL shaders
std::string vertex_shader_source =
R""(
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 uv;
layout (location = 2) in vec3 color;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
out vec2 frag_uv;
out vec4 frag_color;
void main()
{
frag_uv = uv;
frag_color = vec4(color, 1.0f);
gl_Position = proj_matrix * mv_matrix * vec4(position.xyz, 1);
}
)"";
std::string fragment_shader_source =
R""(
#version 330 core
uniform sampler2D Texture;
in vec2 frag_uv;
in vec4 frag_color;
layout (location = 0) out vec4 color;
void main()
{
// color = frag_color * texture(Texture, frag_uv.st);
// color = vec4((frag_color * texture(Texture, frag_uv)).xyz, 1);
color = frag_color * texture(Texture, frag_uv.st);
}
)"";
GLuint program_id = loadShaders(vertex_shader_source.c_str(), fragment_shader_source.c_str());
generate_solid_texture();
// Heatmap objects
GLuint m_vao, m_vbo, m_uvbo, m_cbo;
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glGenBuffers(1, &m_vbo);
glGenBuffers(1, &m_uvbo);
glGenBuffers(1, &m_cbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
glBindBuffer(GL_ARRAY_BUFFER, m_uvbo);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
glBindBuffer(GL_ARRAY_BUFFER, m_cbo);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
// Create the FBO for later
GLuint fbo, map_texture;
glGenFramebuffers(1, &fbo);
glGenTextures(1, &map_texture);
glBindVertexArray(0);
GLsizei heat_map_width = 600;
GLsizei heat_map_height = 600;
std::vector<float> map_vertices, map_vertex_uvs, map_vertex_colors;
std::vector<float> solid_uv = {0.0f, 0.0f};
std::vector<float> bl = {0, 0}, br = {1.0f, 0}, tl = {0, 1.0f}, tr = {1.0f, 1.0f};
map_vertices = {bl[0], bl[1], 1.0f, tr[0], tr[1], 1.0f, tl[0], tl[1], 1.0f,
bl[0], bl[1], 1.0f, br[0], br[1], 1.0f, tr[0], tr[1], 1.0f};
map_vertex_uvs = {solid_uv[0], solid_uv[1], solid_uv[0], solid_uv[1], solid_uv[0], solid_uv[1],
solid_uv[0], solid_uv[1], solid_uv[0], solid_uv[1], solid_uv[0], solid_uv[1]};
map_vertex_colors = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f};
glUseProgram(program_id);
glBindTexture(GL_TEXTURE_2D, map_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, heat_map_width, heat_map_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, map_texture, 0);
// glViewport(0, 0, heat_map_width, heat_map_height);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
glClearColor(0.0f, 0.0f, 0.0f, 1.00f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(m_vao);
// Vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, map_vertices.size() * sizeof(map_vertices[0]), map_vertices.data(), GL_STATIC_DRAW);
// UV buffer
glBindBuffer(GL_ARRAY_BUFFER, m_uvbo);
glBufferData(GL_ARRAY_BUFFER, map_vertex_uvs.size() * sizeof(map_vertex_uvs[0]), map_vertex_uvs.data(),
GL_STATIC_DRAW);
// Color buffer
glBindBuffer(GL_ARRAY_BUFFER, m_cbo);
glBufferData(GL_ARRAY_BUFFER, map_vertex_colors.size() * sizeof(map_vertex_colors[0]), map_vertex_colors.data(),
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
static const GLfloat identity_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
GLuint move_matrix_location = glGetUniformLocation(program_id, "mv_matrix");
GLuint projection_matrix_location = glGetUniformLocation(program_id, "proj_matrix");
GLuint texture_location = glGetUniformLocation(program_id, "Texture");
glUniformMatrix4fv(move_matrix_location, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, identity_matrix);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, solid_texture);
glUniform1i(texture_location, 0);
glDrawArrays(GL_TRIANGLES, 0, map_vertices.size() / 3);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
// Framebuffer to texture
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Always check that our framebuffer is ok
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return false;
// The fullscreen quad's FBO
static const GLfloat g_quad_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
};
static const GLfloat g_quad_vertex_uv_data[] = {
-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
};
static const GLfloat g_quad_vertex_color_data[] = {
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
};
GLuint quad_vao;
glGenVertexArrays(1, &quad_vao);
glBindVertexArray(quad_vao);
GLuint quad_vertexbuffer;
glGenBuffers(1, &quad_vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);
GLuint quad_uvbuffer;
glGenBuffers(1, &quad_uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quad_uvbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_uv_data), g_quad_vertex_uv_data, GL_STATIC_DRAW);
GLuint quad_colorbuffer;
glGenBuffers(1, &quad_colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quad_colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_color_data), g_quad_vertex_color_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
glBindBuffer(GL_ARRAY_BUFFER, quad_uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
glBindBuffer(GL_ARRAY_BUFFER, quad_colorbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
glBindVertexArray(0);
do {
// Render to our framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(
0, 0, windowWidth,
windowHeight); // Render on the whole framebuffer, complete from the lower left corner to the upper right
// Clear the screen
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(program_id);
// Render to the screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Render on the whole framebuffer, complete from the lower left corner to the upper right
glViewport(0, 0, windowWidth, windowHeight);
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our shader
glUseProgram(program_id);
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, map_texture);
// Set our "renderedTexture" sampler to use Texture Unit 0
glUniform1i(texture_location, 0);
glBindVertexArray(quad_vao);
// Draw the triangles !
glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles
glBindVertexArray(0);
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}
I am fairly certain the issue is not with the vertex or fragment shaders, because I use them in another renderer class and that one works fine. Please let me know if I can provide anything else that would be of use.
Major Edit: I've created a minimal reproducible example of my issue.
Edit2: I believe I have updated it for the better, but now showing a black screen instead of a white one. I ran the generate_solid_texture function, enabled the verex atttrib arrays for the quad_vao, and set the framebuffer to default in the main loop.

I have converted The Red Book 9ed ex. 3.7 from old functions to 4.5 functions, but it's not displaying anything

For practice purpose, I have converted OpenGL Red Book 9ed ex. 3.7 from "old" functions to 4.5 functions. I have done it before, and it has worked on my system, but this time, it's not displaying anything, just the glClearBufferfv() color. I tried to follow the example to a tee, and I didn't omit anything. I just converted glBufferData() to glNamedBufferStorage(). And a a few other things. Here's the original code as it appears in the book. But let me copy-paste my own code and shaders:
Main.cpp
#include <iostream>
#include <glad/glad.h>
#include <KHR/khrplatform.h>
#include <GLFW/glfw3.h>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <SOIL2/SOIL2.h>
#include <Shader.h>
#include <Camera.h>
enum VAO_IDs { Triangles, NumVAOs, ID3 };
enum Buffer_IDs { ArrayBuffer1, ArrayBuffer2, EBOBuffer, NumBuffers
};
enum Attrib_IDs { vPosition = 0, cPosition = 1 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;
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;
void init()
{
GLfloat cube_positions[] = {
-1.0f, -1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 1.0f,
1.0f, -1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
GLfloat cube_colors[] = {
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f
};
GLushort cube_indices[] = {
0, 1, 2, 3, 6, 7, 4, 5,
0xFFFF,
2, 6, 0, 4, 1, 5, 3, 7
};
glCreateVertexArrays(NumVAOs, VAOs);
glCreateBuffers(NumBuffers, Buffers);
glNamedBufferStorage(Buffers[ArrayBuffer1], sizeof(cube_positions), cube_positions, GL_ARRAY_BUFFER);
glNamedBufferStorage(Buffers[ArrayBuffer2], sizeof(cube_colors), cube_colors, GL_ARRAY_BUFFER);
glNamedBufferStorage(Buffers[EBOBuffer], sizeof(cube_indices), cube_indices, GL_ELEMENT_ARRAY_BUFFER);
Shader myShader("TirangleVert.glsl", "TriangleFrag.glsl");
myShader.Use();
glBindVertexArray(VAOs[Triangles]);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer1]);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer2]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Buffers[EBOBuffer]);
glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(cPosition, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) sizeof(cube_positions));
glEnableVertexAttribArray(vPosition);
glEnableVertexAttribArray(cPosition);
}
void display()
{
GLfloat black[] = { 0.2f, 0.5f, 0.6f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray(VAOs[Triangles]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Buffers[EBOBuffer]);
glLineWidth(20);
glPointSize(20);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(0xFFFF);
glDrawElements(GL_TRIANGLE_STRIP, 17, GL_UNSIGNED_SHORT, NULL);
//glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_SHORT, NULL);
//glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_SHORT,
// (const GLvoid *)(9 * sizeof(GLushort)));
}
void dealloc()
{
glDeleteVertexArrays(NumVAOs, VAOs);
glDeleteBuffers(NumBuffers, Buffers);
}
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// 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;
}
init();
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
display();
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
dealloc();
// 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);
}
TirangleVert.glsl:
#version 450 core
layout (location = 0) in vec4 cube_pos;
layout (location = 1) in vec4 colors;
out vec4 myColor;
void main()
{
gl_Position = cube_pos;
myColor = colors;
}
TriangleFrag.glsl:
#version 450 core
layout (location = 0) in vec4 myColor;
out vec4 color;
void main()
{
color = myColor;
}
PS: I realize that there's a typo in the name of the vertex shader, but it's all accounted for. Also, there's no problem with Shader.h, as I have used it before with no issues.
Many thanks.
The last parameter of the glNamedBufferStorage is the bitfield, which specifies the intended usage of the buffer's data store, rather than GL_ARRAY_BUFFERor GL_ELEMENT_ARRAY_BUFFER. This will cause a GL_INVALID_VALUE error:
GLbitfield flags = GL_DYNAMIC_STORAGE_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
glNamedBufferStorage(Buffers[ArrayBuffer1], sizeof(cube_positions), cube_positions, flags);
glNamedBufferStorage(Buffers[ArrayBuffer2], sizeof(cube_colors), cube_colors, flags);
glNamedBufferStorage(Buffers[EBOBuffer], sizeof(cube_indices), cube_indices, flags);
glVertexAttribPointer specifies a vertex array which is refers to the array buffer which is currently bound.
The proper buffer has to be bound by glBindBuffer before glVertexAttribPointer is called. Note, there is only 1 buffer which can be currently bound.
If a buffer is bound, then the last parameter (pointer) is treated as a byte offset into the buffer object's data store. In your case this parameter has to be 0. Note, in a core profile context you have to use an array buffer, a directly addressed memory is not valid.
glBindVertexArray(VAOs[Triangles]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Buffers[EBOBuffer]);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer1]);
glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer2]);
glVertexAttribPointer(cPosition, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(vPosition);
glEnableVertexAttribArray(cPosition);

'argc' has abnormal big value while debug in vc++

I wrote a code in VC++ 2013, and when debugging it, the 'argc' argument of main function gets an abnormal big value. A value higher than 2,000,000,000 always!! But every time has value different from previous run. I checked the 'Command Arguments' field in project properties, it is empty.
How can i solve the problem?
If any more details is needed tell me.
Thanks.
the code:
#include <stdio.h>
#include <stdlib.h>
//for Windows, we use the static version of GLEW
#ifdef _WIN32
#define GLEW_STATIC
#endif
//GLFW and GLEW libraries
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "shader.h" // functions to load shader
//Global variables
GLFWwindow* window;
int main(int argc, char **argv)
{
//Initialize GLFW
if (!glfwInit()){
fprintf(stderr, "Failed to initialize GLFW\n");
exit(EXIT_FAILURE);
}
//enable anti-aliasing 4x with GLFW
glfwWindowHint(GLFW_SAMPLES, 4);
//specify the client API version that the created context must be compatible with.
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
//make the GLFW forward compatible
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//use the OpenGL Core (http://www.opengl.org/wiki/Core_And_Compatibility_in_Contexts)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//create a GLFW windows object
window = glfwCreateWindow(640, 480, "Chapter 4 - GLSL", NULL, NULL);
if (!window){
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
//make the context of the specified window current for the calling thread
glfwMakeContextCurrent(window);
glfwSwapInterval(100);
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Final to Initialize GLEW\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
GLuint program = LoadShaders("simple.vert", "simple.frag");
glBindFragDataLocation(program, 0, "color_out");
glUseProgram(program);
// Create Vertex Array Object
GLuint vertex_array;
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vertex_buffer;
GLuint color_buffer;
glGenBuffers(1, &vertex_buffer);
glGenBuffers(1, &color_buffer);
const GLfloat vertices[] = {
+1.0f, +0.0f, 0.0f,
+1.0f, -1.0f, 0.0f,
+0.0f, -1.0f, 0.0f,
-1.0f, -0.0f, 0.0f,
+0.0f, +1.0f, 0.0f,
-1.0f, +1.0f, 0.0f,
};
const GLfloat colors[] = {
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
// Specify the layout of the vertex data
GLint position_attrib = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(position_attrib);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer(position_attrib, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
GLint color_attrib = glGetAttribLocation(program, "color_in");
glEnableVertexAttribArray(color_attrib);
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
glVertexAttribPointer(color_attrib, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
while (!glfwWindowShouldClose(window)){
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw a rectangle from the 2 triangles using 6 vertices
glDrawArrays(GL_TRIANGLES, 0, 24); //draw the square
glfwSwapBuffers(window);
glfwPollEvents();
}
//clear up the memories
glDisableVertexAttribArray(position_attrib);
glDisableVertexAttribArray(color_attrib);
glDeleteBuffers(1, &vertex_buffer);
glDeleteBuffers(1, &color_buffer);
glDeleteVertexArrays(1, &vertex_array);
glDeleteProgram(program);
// Close OpenGL window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
Edit:
I removed pieces of code till reached the following code. Interestingly, if I remove glewExperimental = true; from code, some link error (error LNK2001) rises!
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#define GLEW_STATIC
#endif
//GLFW library
#include <GL/glew.h>
int main(int argc, char **argv)
{
glewExperimental = true; // Needed for core profile
exit(EXIT_SUCCESS);
}