I have two shaders, one for instancing, one for just plotting a line. They correspond to two segments of code (segment1 for instancing and segment2 for a line) respectively. And the programing behaviour is weird:
segment1 work
just dispeared. Then I comment the code of segment2, segment1 works. Then I uncomment segment2 code and put it before segment1. Then both segments works. This is strange.a. when both segments uncommented, the instancing will move as expected, but the line just stays at where it borns.
b. then I comment the segment2 code, then the line will move as expected when keys pressed.
There must be some connections of the two problems. Here is some of the code, it's not runnable, I will provide full runnable code if necessary.
#include <stdio.h>
#include <stdlib.h>
#include <glad/glad.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/norm.hpp>
#include <thread>
#include <queue>
#include <mutex>
#include <glm/gtx/string_cast.hpp>
#include "../common/shader.hpp"
GLFWwindow *window;
using namespace glm;
using std::cout, std::endl;
int run_websocket(); // another thread run this function to get data into the queue
extern std::queue<std::tuple<unsigned long, float, float, bool>> queue1;
extern std::mutex m;
const int MaxParticles = 100000;
const int MaxLine = 1000;
int index = 0;
int width = 1024;
int height = 768;
float deltaTime = 0.0f;
float lastFrame = 0.0f;
void framebuffer_size_callback(GLFWwindow *window, int width1, int height1) {
width = width1;
height = height1;
glViewport(0, 0, width1, height1);
}
void processInput(GLFWwindow *window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
float f1 = 10000;
float f_up_down = 10;
float cameraSpeed = deltaTime;
if (glfwGetKey(window, GLFW_KEY_N) == GLFW_PRESS)
cameraPos += cameraSpeed * (cameraFront * f_up_down);
if (glfwGetKey(window, GLFW_KEY_M) == GLFW_PRESS)
cameraPos -= cameraSpeed * (cameraFront * f_up_down);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * (cameraSpeed * f1);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * (cameraSpeed * f1);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
cameraPos += glm::normalize(cameraUp) * (cameraSpeed * f_up_down);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
cameraPos -= glm::normalize(cameraUp) * (cameraSpeed * f_up_down);
}
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 10.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
unsigned long x0 = 0;
float y00 = 0.0f;
int main(void) {
// Initialise GLFW
std::thread t1(run_websocket);
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_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow(width, height, "title", 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);
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;
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glfwPollEvents();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLuint programID = LoadShaders("Particle.vertexshader",
"Particle.fragmentshader");
GLuint shader2 = LoadShaders("line.vertexshader",
"line.fragmentshader");
GLuint ViewProjMatrixID = glGetUniformLocation(programID, "VP");
GLuint ViewProjMatrixID2 = glGetUniformLocation(shader2, "VP2");
static GLfloat *g_particule_position_size_data = new GLfloat[MaxParticles * 4];
static GLfloat *g_line_data = new GLfloat[MaxLine * 4];
static const GLfloat g_vertex_buffer_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,
};
// vao of segment2
GLuint LineVertexArrayID;
glGenVertexArrays(1, &LineVertexArrayID);
glBindVertexArray(LineVertexArrayID);
GLuint line_buffer;
glGenBuffers(1, &line_buffer);
glBindBuffer(GL_ARRAY_BUFFER, line_buffer);
glBufferData(GL_ARRAY_BUFFER, MaxLine * 4 * sizeof(float), NULL, GL_STREAM_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0,
2,
GL_FLOAT,
GL_FALSE,
2 * sizeof(float),
(void *) 0
);
glBindVertexArray(0);
// vao of segment2 ends
// vao of segment1
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint billboard_vertex_buffer;
glGenBuffers(1, &billboard_vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0,
2,
GL_FLOAT,
GL_FALSE,
2 * sizeof(float),
(void *) 0
);
GLuint particles_position_buffer;
glGenBuffers(1, &particles_position_buffer);
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1,
4,
GL_FLOAT,
GL_FALSE,
4 * sizeof(float),
(void *) 0
);
glVertexAttribDivisor(1, 1);
glBindVertexArray(0);
// vao of segment1 ends
do {
glClear(GL_COLOR_BUFFER_BIT);
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
processInput(window);
glm::mat4 projection = glm::mat4(1.0f);
glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
projection = glm::perspective(glm::radians(90.0f), 1000.0f, 0.1f, 1000.0f);
glm::mat4 ViewProjectionMatrix = projection * view;
glm::mat4 ViewProjectionMatrix2 = projection * view;
glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, &ViewProjectionMatrix[0][0]);
glUniformMatrix4fv(ViewProjMatrixID2, 1, GL_FALSE, &ViewProjectionMatrix2[0][0]);
// why move segment2 behind segment1 then segment1 will not show ???
///// segment2
int lineNum = 1;
int line_index = 0;
glUseProgram(shader2);
glBindVertexArray(LineVertexArrayID);
glBindBuffer(GL_ARRAY_BUFFER, line_buffer);
g_line_data[line_index * 2 + 0] = -1.0f;
g_line_data[line_index * 2 + 1] = 0;
line_index = 1;
g_line_data[line_index * 2 + 0] = 1.0f;
g_line_data[line_index * 2 + 1] = 0;
glBufferData(GL_ARRAY_BUFFER, MaxLine * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, lineNum * sizeof(GLfloat) * 4, g_line_data);
glDrawArrays(GL_LINES, 0, 2);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
///// segment2
// printing some here to make sure the Math is correct
// vec4 p1 = ViewProjectionMatrix * vec4(-1.0f, 0, -0.1, 1.0);
// vec4 p2 = ViewProjectionMatrix * vec4(1.0f, 0, -0.1, 1.0);
// cout << "p1 y " << p1.y / p1.w << " , p2 y " << p2.y / p2.w << endl;
//// segment1
{
std::lock_guard<std::mutex> lck(m);
while (!queue1.empty()) {
auto &t = queue1.front();
unsigned long x_raw = std::get<0>(t);
float y = std::get<1>(t);
if (x0 == 0) {
x0 = x_raw;
y00 = y;
cameraPos += glm::vec3(0, 0, 0);
}
x_raw -= x0;
y -= y00;
float x = float(x_raw);
float s = std::get<2>(t);
bool is_sell_b = std::get<3>(t);
float is_buy = 1.0f - static_cast<float>(is_sell_b);
g_particule_position_size_data[index * 4 + 0] = x;
g_particule_position_size_data[index * 4 + 1] = y;
g_particule_position_size_data[index * 4 + 2] = s / 100;
g_particule_position_size_data[index * 4 + 3] = is_buy;
index++;
queue1.pop();
}
}
glUseProgram(programID);
glBindVertexArray(VertexArrayID);
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
// glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW); // Buffer orphaning, a common way to improve streaming perf. See above link for details.
glBufferSubData(GL_ARRAY_BUFFER, 0, index * sizeof(GLfloat) * 4, g_particule_position_size_data);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 6, index);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//// segment1
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);
delete[] g_particule_position_size_data;
// Cleanup VBO and shader
glDeleteBuffers(1, &particles_position_buffer);
glDeleteBuffers(1, &billboard_vertex_buffer);
glDeleteProgram(programID);
// glDeleteTextures(1, &Texture);
glDeleteVertexArrays(1, &VertexArrayID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}
glUniform*
sets a uniform variable in the default uniform block of the currently installed program.
Install the program with glUseProgram
before setting the uniform:
glUseProgram(programID);
glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, &ViewProjectionMatrix[0][0]);
glUseProgram(shader2);
glUniformMatrix4fv(ViewProjMatrixID2, 1, GL_FALSE, &ViewProjectionMatrix2[0][0]);
Or use glProgramUniformMatrix4fv
:
glProgramUniformMatrix4fv(programID, ViewProjMatrixID, 1, GL_FALSE, &ViewProjectionMatrix[0][0]);
glProgramUniformMatrix4fv(shader2, ViewProjMatrixID2, 1, GL_FALSE, &ViewProjectionMatrix2[0][0]);