Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I try to move my object only on the y-axis. I created an array with 4 Vertex and put the data in my vertexBuffer and bind it. Also I created a vertexArray and an indexBuffer to bind them and draw my quad.
Now I change only the y-coordinate of my quad and want to overwrite the data in my vertexBuffer with glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(moveObject), moveObject); but nothing happens. Only when I fill the data before I bind my indexbuffer it will work. After that I can't change the VertexBuffer.
Here is my code of my main
#include <iostream>
#include "headerData/VertexBuffer.h"
#include "headerData/IndexBuffer.h"
#include "headerData/Shader.h"
#include "headerData/VertexLayout.h"
#include "headerData/VertexArray.h"
#include "headerData/Road.h"
#include "glm.hpp"
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
static struct VertexShader {
std::string defaultShader = "#version 330 core\n"
"layout (location = 0) in vec4 aPos;\n"
"uniform mat4 scale;"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f)*scale;\n"
"}\0";
std::string yMoveShader = "#version 330 core\n"
"layout (location = 0) in vec4 aPos;\n"
"uniform mat4 scale;"
"uniform vec4 transform;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y+transform.y, aPos.z, 1.0f)*scale;\n"
"}\0";
};
static struct FragmentShader {
std::string defaultShader = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.5f, 0.5f, 0.5f, 1.0);\n"
"}\n\0";
std::string greenShader = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.5f, 1.0f, 0.5f, 1.0);\n"
"}\n\0";
};
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
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);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(800, 800, "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;
}
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
VertexShader vertexShader;
FragmentShader fragmentShader;
Shader shaderCol(vertexShader.defaultShader, fragmentShader.defaultShader);
Shader shaderMove(vertexShader.yMoveShader, fragmentShader.greenShader);
shaderCol.bind();
//shaderMove.bind();
glm::mat4 scale = glm::ortho(-100.0f, 100.0f, -100.0f, 100.0f, -1.0f, 1.0f);
//glUniformMatrix4fv(glGetUniformLocation(shaderMove.getShaderID(), "scale"), 1, GL_FALSE, glm::value_ptr(scale));
glUniformMatrix4fv(glGetUniformLocation(shaderCol.getShaderID(), "scale"), 1, GL_FALSE, glm::value_ptr(scale));
glm::vec3 transform(0.0f, 0.0f, 0.0f);
float moveObject[] = {
20.0f, -50.0f, // top right
20.0f, -90.0f, // bottom right
-20.0f, -90.0f, // bottom left
-20.0f, -50.0f // top left
};
float colObject[] = {
2.0f, 2.0f, //top right
2.0f, -2.0f, //bottom right
-2.0f, 2.0f, //top left
-2.0, -2.0f //bot left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VA, VB, IB;
glGenVertexArrays(1, &VA);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
//glBindBuffer(GL_ARRAY_BUFFER, VBO);
//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//VertexBuffer vb;
//vb.bind(moveObject, 4 * 2 * sizeof(float));
//VertexBuffer
glGenBuffers(1, &VB);
glBindBuffer(GL_ARRAY_BUFFER, VB);
glBufferData(GL_ARRAY_BUFFER, 8 * 2 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
glBindVertexArray(VA);
//LAyout vom Buffer
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)(0));
glEnableVertexAttribArray(0);
//VertexLayout layout;
//layout.layoutPush(3);
//VertexArray va;
//va.addBuffer(vb, layout);
//IndexBuffer ib;
//ib.bind(indices, 6 * sizeof(unsigned int));
glGenBuffers(1, &IB);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IB);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, IB);
//Parameter
//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(0));
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));
//glEnableVertexAttribArray(0);
//glEnableVertexAttribArray(1);
// uncomment this call to draw in wireframe polygons.
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//Road road;
// render loop
// -----------
float time = 0;
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//shader.bind();
//glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * 3));
//glDrawArrays(GL_TRIANGLES, 0, 3);
//glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * 3));
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//road.render();
//That not work
moveObject[1] += abs(90 * sin(glfwGetTime()));
moveObject[3] += abs(90 * sin(glfwGetTime()));
moveObject[5] += abs(90 * sin(glfwGetTime()));
moveObject[7] += abs(90 * sin(glfwGetTime()));
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(moveObject), moveObject);
//transform.y = 90 * abs(sin(glfwGetTime()));
//glUniform4f(glGetUniformLocation(shaderMove.getShaderID(), "transform"), transform.x, transform.y, 0.0f, 1.0f);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//glDeleteBuffers(1, &IB);
//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, &test);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
std::cout << "callback" << std::endl;
glViewport(0, 0, width, height);
}
When you execute this line
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(moveObject), moveObject);
the data bound to GL_ARRAY_BUFFER on GPU is updated. But what data is it bound to? Look above
glBindBuffer(GL_ARRAY_BUFFER, IB);
You seem to bind your array of indices, while you probably meant
glBindBuffer(GL_ARRAY_BUFFER, VB);
Related
As the title says, I'm trying to draw a square from two triangles for class. I've tried everything I can think of but I cannot figure out why it just displays a black screen. Here is my code so far. I have the project and libraries set up correctly. I've looked over it a dozen times and can't seem to find the issue.
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
static unsigned int CompileShader(unsigned int type, const std::string& source) {
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
return id;
}
static unsigned int CreateShader(const std::string& vrtxShader, const std::string& fragShader) {
unsigned int program = glCreateProgram();
//compile shaders
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vrtxShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragShader);
//attach shaders to program
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
//delete shaders
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
//sets up GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Module 3", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
//Initialize GLEW
if (glewInit() != GLEW_OK)
std::cout << "Error!" << std::endl;
float vertPositions[] = {
// index 0
-0.5f, -0.5f, 0.0f,
1.0f, 0.0f, 0.0f,
// index 1
-5.0f, 0.5f, 0.0f,
0.0f, 0.0f, 1.0f,
// index 2
0.5f, -0.5f, 0.0f,
0.0f, 1.0f, 0.0f,
// index 3
0.5f, 0.5f, 0.0f,
1.0f, 0.0f, 0.0f,
};
float indices[] = { 0, 1, 2, 1, 2, 3 };
//creates vertex buffer object
unsigned int vbo;
unsigned int ebo;
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertPositions), vertPositions, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//attribute location and layout to gpu.
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
// Vertex Shader Program Source Code
std::string vertexShaderSource = "#version 440 core\n"
"layout (location = 0) in vec4 aPos;\n"
"layout (location = 1) in vec4 aColor;\n"
"out vec4 colorOut;\n"
"void main()\n"
"{\n"
" gl_Position = aPos;\n"
" colorOut = aColor;\n"
"}\n\0";
// Fragment Shader Program Source Code
std::string fragmentShaderSource = "#version 440 core\n"
"in vec4 colorOut;\n"
"out vec4 fragColor;\n"
"void main()\n"
"{\n"
"fragColor = colorOut;\n"
"}\n\0";
unsigned int shader = CreateShader(vertexShaderSource, fragmentShaderSource);
glUseProgram(shader);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
//draw the shapes
glDrawElements(GL_TRIANGLES, 6, GL_FLOAT, nullptr);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Why using a core profile OpenGL Context (GLFW_OPENGL_CORE_PROFILE) it is mandatory to create a Vertex Array Object. There is no default VAO when using a core profile.
e.g.:
unsigned int vao, vbo, ebo;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertPositions), vertPositions, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
Further more the type of the indices must be integral. e.g:
unsigned int indices[] = { 0, 1, 2, 1, 2, 3 };
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
I can't get instanced geometry to work with a compute shader (I got both things work in isolation but don't know how to combine them). Below is an example that renders instances of a colored quad with different offsets. I'd like to be able to update those offsets via a compute shader.
#define COMPUTE_UPDATE
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "Shader.h"
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
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);
#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);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
Shader shader("res/shaders/instanced.vs", "res/shaders/instanced.fs");
Shader compute("res/shaders/instanced.glsl");
float translations[200];
int index = 0;
float offset = 0.1f;
for (int y = -10; y < 10; y += 2)
{
for (int x = -10; x < 10; x += 2)
{
float translation[2];
translation[0] = (float)x / 10.0f + offset;
translation[1] = (float)y / 10.0f + offset;
translations[index++] = translation[0];
translations[index++] = translation[1];
}
}
unsigned int instanceVBO;
glGenBuffers(1, &instanceVBO);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, 2 * sizeof(float) * 100, &translations[0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
float quadVertices[] = {
// positions // colors
-0.05f, 0.05f, 1.0f, 0.0f, 0.0f,
0.05f, -0.05f, 0.0f, 1.0f, 0.0f,
-0.05f, -0.05f, 0.0f, 0.0f, 1.0f,
-0.05f, 0.05f, 1.0f, 0.0f, 0.0f,
0.05f, -0.05f, 0.0f, 1.0f, 0.0f,
0.05f, 0.05f, 0.0f, 1.0f, 1.0f
};
unsigned int quadVAO, quadVBO;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribDivisor(2, 1);
while (!glfwWindowShouldClose(window))
{
#ifdef COMPUTE_UPDATE
// update instanced buffer
compute.Use();
glBindVertexArray(quadVAO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, instanceVBO);
glDispatchCompute(1, 1, 1);
glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
#endif
// render
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw 100 instanced quads
shader.Use();
glBindVertexArray(quadVAO);
glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 100); // 100 triangles of 6 vertices each
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &quadVAO);
glDeleteBuffers(1, &quadVBO);
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
Compute shader:
#version 460 core
struct Particle {
vec2 pos;
};
layout(std430, binding = 1) buffer particleBuffer
{
Particle particles[];
};
layout(local_size_x = 100, local_size_y = 1, local_size_z = 1) in;
void main() {
uint i = gl_GlobalInvocationID.x;
particles[i].pos += vec2(0.01, 0.0);
}
Vertex shader:
#version 460 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aOffset;
out vec3 fColor;
void main()
{
fColor = aColor;
gl_Position = vec4(aPos + aOffset, 0.0, 1.0);
}
I tried to use FFmpeg to capture frames rendered by OpenGL. The result is a .mp4 file for playing back purposes. It works since I got the .mp4 I expected, however the quality is quite low compared to the one rendered by OpenGL. Can anyone tell me why? And How can I adjust my code to make the mp4 of the same quality as the original frames generated by OpenGL?
The result I've got:
images OpenGL vs FFmpeg
Here is my simple code:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
// settings
const unsigned int SCR_WIDTH = 500;
const unsigned int SCR_HEIGHT = 500;
// start ffmpeg telling it to expect raw rgba 720p-60hz frames
// -i - tells it to read frames from stdin
const char* cmd = "ffmpeg -f rawvideo -pix_fmt rgba -s 500x500 -i - "
"-threads 0 -preset fast -y -pix_fmt yuv420p -crf 21 -vf vflip output.mp4";
// open pipe to ffmpeg's stdin in binary write mode
FILE* ffmpeg = _popen(cmd, "wb");
int* buffer = new int[SCR_WIDTH*SCR_HEIGHT];
// shaders
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"layout (location = 2) in vec2 aTexCoord;\n"
"out vec3 ourColor;\n"
"out vec2 texCoord;\n"
"uniform mat4 transform;\n"
"void main()\n"
"{\n"
" gl_Position = transform*vec4(aPos, 1.0);\n"
" ourColor = aColor;\n"
" texCoord = aTexCoord;\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 ourColor;\n"
"in vec2 texCoord;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.0f, 0.0f, 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);
#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;
}
// render preparation: data collection and passing
// -----------------------------------------------
// vertex shader: create and compile
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// fragment shader: create and compile
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// shader program
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// first shape: square
float vertices[] = {
// positions // colors // texture coords
0.25f, 0.25f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.25f, -0.25f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.25f, -0.25f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.25f, 0.25f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
int indices[] = {
0, 1, 2,
2, 3, 0
};
unsigned int VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
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, 8 * sizeof(float), 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0);
glEnableVertexAttribArray(2);
// second shape: line(from the center of the screen to the center of the square
float vertices2[] = {
0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.0f
};
unsigned int VAO2, VBO2;
glGenVertexArrays(1, &VAO2);
glGenBuffers(1, &VBO2);
glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glEnableVertexAttribArray(0);
// wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
int frameCounter = 0;
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
if (frameCounter > 900) break;
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// be sure to activate the shader before any calls to glUniform
glUseProgram(shaderProgram);
/**********************draw rotating line*****************************/
glm::mat4 transform = glm::mat4(1.0f);
/// rotate( around the center of the screen )
transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
unsigned int transLoc = glGetUniformLocation(shaderProgram, "transform");
glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));
// draw
glBindVertexArray(VAO2);
glDrawArrays(GL_LINES, 0, 2);
/**********************draw rotating square*****************************/
transform = glm::mat4(1.0f);
/// rotate( around the center of the screen )
transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
//// translate
transform = glm::translate(transform, glm::vec3(0.5f, 0.5f, 0.0f));
//// rotate( self rotate)
transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
transLoc = glGetUniformLocation(shaderProgram, "transform");
glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));
// draw
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
/**********************draw center squares*****************************/
transform = glm::mat4(1.0f);
float scaler = sin((float)glfwGetTime())*4;
transform = glm::scale(transform, glm::vec3(scaler, scaler, scaler));
transLoc = glGetUniformLocation(shaderProgram, "transform");
glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));
// draw
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
/****** ffmpeg *****/
glReadPixels(0, 0, SCR_WIDTH, SCR_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
fwrite(buffer, sizeof(int)*SCR_WIDTH*SCR_HEIGHT, 1, ffmpeg);
frameCounter++;
/****** end: ffmpeg *****/
glfwPollEvents();
}
_pclose(ffmpeg);
// 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);
}
Switch to the libx264rgb encoder & crf 0 for lossless capture:
const char* cmd = "ffmpeg -framerate 60 -f rawvideo -pix_fmt rgba -s 500x500 -i - "
"-c:v libx264rgb -threads 0 -preset fast -y -crf 0 -vf vflip output.mp4";
Note that you'll want a re-encode the output before passing it off to other, less general software than ffmpeg since RGB isn't a terribly common color-space for H.264.
Be careful with your player software when checking results, MPV's --profile=gpu-hq on my Linux system introduced ringing artifacts around the lines while VLC didn't.
I was experimenting with using Vertex Array Objects and Element Buffer Objects. I managed to draw the letter "H" on my screen using a single VAO with an EBO bound since all my vertices and indices were in one array. I wanted to split each rectangle into a different object though and give them a different color, but only one of them is drawing on the screen.
Here's the code:
#include <glew.h>
#include <glfw3.h>
#include <iostream>
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(0.2f, 0.6f, 0.7f, 1.0f);\n"
"}\0";
const char* fragmentShaderSource2 = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(0.7f, 0.4f, 0.3f, 1.0f);\n"
"}\0";
const char* fragmentShaderSource3 = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(0.1f, 0.2f, 0.6f, 1.0f);\n"
"}\0";
int main(void)
{
GLFWwindow* window;
glewInit();
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
std::cout << "Error!" << std::endl;
float vertices[] = {
0.2f, 0.7f, 0.0f,
0.3f, 0.7f, 0.0f,
0.3f, 0.2f, 0.0f,
0.2f, 0.2f, 0.0f
};
float vertices2[] = {
0.6f, 0.7f, 0.0f,
0.7f, 0.7f, 0.0f,
0.7f, 0.2f, 0.0f,
0.6f, 0.2f, 0.0f
};
float vertices3[] = {
0.3f, 0.4f, 0.0f,
0.3f, 0.5f, 0.0f,
0.6f, 0.5f, 0.0f,
0.6f, 0.4f, 0.0f
};
unsigned int indices[] = {
1, 0, 2,
2, 3, 0
};
unsigned int indices2[] = {
5, 4, 6,
6, 7, 4
};
unsigned int indices3[] = {
8, 9, 11,
11, 10, 9
};
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);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
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);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
unsigned int fragmentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader2, 1, &fragmentShaderSource2, NULL);
glCompileShader(fragmentShader2);
unsigned int fragmentShader3 = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader3, 1, &fragmentShaderSource3, NULL);
glCompileShader(fragmentShader3);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
unsigned int shaderProgram2;
shaderProgram2 = glCreateProgram();
unsigned int shaderProgram3;
shaderProgram3 = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glAttachShader(shaderProgram2, fragmentShader2);
glAttachShader(shaderProgram2, vertexShader);
glLinkProgram(shaderProgram2);
glAttachShader(shaderProgram3, fragmentShader3);
glAttachShader(shaderProgram3, vertexShader);
glLinkProgram(shaderProgram3);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(fragmentShader2);
glDeleteShader(fragmentShader3);
unsigned int VBOs[3], VAOs[3], EBOs[3];
glGenVertexArrays(3, VAOs);
glGenBuffers(3, VBOs);
glGenBuffers(3, EBOs);
glBindVertexArray(VAOs[0]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[0]);
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);
glBindVertexArray(VAOs[1]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices2), indices2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(VAOs[2]);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices3), vertices3, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOs[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices3), indices3, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAOs[0]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glUseProgram(shaderProgram2);
glBindVertexArray(VAOs[1]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glUseProgram(shaderProgram3);
glBindVertexArray(VAOs[2]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glDeleteVertexArrays(3, VAOs);
glDeleteBuffers(3, VBOs);
glDeleteBuffers(3, EBOs);
glfwTerminate();
return 0;
}
You'll have here:
float vertices2[] = {
0.6f, 0.7f, 0.0f,
0.7f, 0.7f, 0.0f,
0.7f, 0.2f, 0.0f,
0.6f, 0.2f, 0.0f
};
together with:
unsigned int indices2[] = {
5, 4, 6,
6, 7, 4
};
That does not make sense. You only copy 4 vertices to your VBO[1], and you set the attrib pointer to offset 0 in that buffer, so the only valid indices are 0,1,2 and 3.
Your indices are set as if all your vertices were in a single big array as before, and actually, that would be a much better strategy: Keep one big vertex array, and one big element indices array, and one VAO, and just draw individual parts of that array by changing the indices argument in the glDrawElements() call, like this:
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // first 6 indices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)(6*sizeof(GLuint))); // second 6 indices
// ...
Also not that using 3 different shaders here is very inefficient. It woold be best if you just added the color as another attribute, and use a single draw call (implying a single shader, single VAO) for everything.
I've a simple OpenGL program running on macOS:
glUseProgram(program);
glViewport(0, 0, mWidth, mHeight);
glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
// Rendering Loop
while (glfwWindowShouldClose(mWindow) == false) {
if (glfwGetKey(mWindow, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(mWindow, true);
}
// why can't view port here?
glViewport(0, 0, mWidth, mHeight);
// Background Fill Color
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
// Flip Buffers and Draw
glfwSwapBuffers(mWindow);
glfwPollEvents();
}
If I comment out the glViewport call inside the loop, it works well, the triangle is rendered in the center of the window, but if I uncomment it, the triangle shows in the left bottom corner of the window.
Below is my shader and vertex data code:
const int mWidth = 1280;
const int mHeight = 800;
auto mWindow = glfwCreateWindow(mWidth, mHeight, "OpenGL", nullptr, nullptr);
const GLchar* vertex_shader_src =
"#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"
"}";
const GLchar* fragment_shader_src =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}";
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
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);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
Could somebody help me?
As #httpdigest commented, it is because macOS has 2x larger frame buffer size, if I query it with glfwGetFramebufferSize and use it as view port size, it works well!