用OpenGL绘制彩色网格?
我的目标是能够创建所谓的占用网格,它类似于瓷砖/网格游戏,看起来像附加的图像。这是一个小机器人项目,我正在工作。所有这些都是在C/C++中完成的 因此,我希望能够:用OpenGL绘制彩色网格?,opengl,Opengl,我的目标是能够创建所谓的占用网格,它类似于瓷砖/网格游戏,看起来像附加的图像。这是一个小机器人项目,我正在工作。所有这些都是在C/C++中完成的 因此,我希望能够: 更改每个栅格单元的分辨率或大小。例如1x1cm或5x5cm等 根据某些条件更改每个单元格的颜色。障碍==黑色,自由==白色,等等。可能会添加用户单击单元格并更改颜色。例如,如果机器人在0x0启动,单元格为红色,则下一个实例移动到1x1。现在0x0应该是白色,1x1应该是红色 添加某种形式的滚动或跟随(可能通过MVP摄像头完成) 我应
我想出了一些你应该在项目中使用的东西。它是一个可缩放的网格,可以调整大小到您需要的任何尺寸。它应该相对较快,行被批处理,四边形被实例化。它与左键和右键单击以及滚轮单击和滚动进行基本交互,但是您应该能够根据需要调整此界面。API应该非常易于使用
createCell
,removeCell
,等等
有几件事:
- 该应用程序不会渲染不在视锥体中的单元格,因此放大时性能更好,尽管也有一些黑客可以让它在缩小时以相当快的速度工作
- 我只能测试1000x1000个正方形(~10-12fps完全缩小),我没有足够的内存来存储10000x1000个正方形(使用~3GB)
flatte
部分有点无结构。这种展平方法最初只是将2D模型向量展平为1D向量,然后发送到GPU(内部\U模型
数据)。三元操作确定该列表的2D切片(想想主栅格中的方框部分),这就是平截头体剔除的发生方式。
bottomLeft和topRight用于计算相机平截头体的边界框,该边界框与整个网格相交,以获得模型和颜色(有序)向量的索引,该向量发送到GPU,虽然有一定的技巧,但它确保与网格交互的操作(添加、删除、更改颜色等)为O(1)。
有一个小错误导致某些单元格冻结,这是由于在QuadRenderer的remove()
方法中将单元格重置为未初始化而导致的,该方法忽略了将其发送到GPU(一种节省性能的优化),并导致内存偏移错误,导致渲染取消同步。因此,有两种方法可以解决这个问题:取消检查,只向GPU发送初始化的单元格(速度较慢),或者将方块设置为白色(hackier)。所以我选择将移除的细胞设置为白色,这意味着它们仍然被渲染(即使它们是用清晰的颜色伪装的)。您可能可以进行更改,使白色单元格也不会被渲染,但考虑到您保持单元格未初始化以开始(看在上帝的份上,不要将其初始化为白色!),性能不会损失太多
可以将remove()函数更改为:
void remove(vec2 pos) {
//change color to white
colors[(int)pos.x][(int)pos.y] = vec3(1);
}
代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/string_cast.hpp>
using std::vector;
using std::cout;
using std::endl;
using glm::mat4;
using glm::vec2;
using glm::vec3;
using glm::vec4;
using glm::perspective;
using glm::radians;
using glm::normalize;
void processInput(GLFWwindow *window);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
// grid dimensions
const unsigned int GRID_WIDTH = 1000;
const unsigned int GRID_HEIGHT = 1000;
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;
bool realTimeUpdating = true;
// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;
// TO DO a simple camera class
vec3 cameraPos = vec3(0.0f, 0.0f, 0.0f);
vec3 cameraFront = vec3(0,0,-1);
vec3 cameraRight = vec3(1,0,0);
vec3 cameraUp = vec3(0,1,0);
mat4 model = mat4(1.0);
mat4 view;
mat4 projection;
float scrollSpeed = 2.0f;
float fov = 90.0f;
float nearDist = 0.1f;
float farDist = 1000.0f;
float ar = (float)SCR_WIDTH / (float)SCR_HEIGHT;
class LineRenderer {
int shaderProgram;
unsigned int VBO, VAO;
mat4 viewProjection;
vector<float> vertices;
public:
LineRenderer() {
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"uniform mat4 viewProjection;\n"
"void main()\n"
"{\n"
" gl_Position = viewProjection * 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,0,0,1);\n"
"}\n\0";
// vertex shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl;
}
// fragment shader
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl;
}
// link shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
vector<float> placeHolderVertices = {
};
vertices.insert( vertices.end(), placeHolderVertices.begin(), placeHolderVertices.end() );
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void setCamera(mat4 cameraMatrix) {
viewProjection = cameraMatrix;
}
void addLine(vec3 start, vec3 end) {
vector<float> lineVertices = {
start.x, start.y, start.z,
end.x, end.y, end.z,
};
vertices.insert( vertices.end(), lineVertices.begin(), lineVertices.end() );
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
}
int draw() {
glUseProgram(shaderProgram);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "viewProjection"), 1, GL_FALSE, &viewProjection[0][0]);
glBindVertexArray(VAO);
glDrawArrays(GL_LINES, 0, vertices.size() / 3);
return 0;
}
};
// maths functions to pick which grid (not necessary, just for demonstration purposes)
vec3 rayCast(double xpos, double ypos, mat4 projection, mat4 view) {
// converts a position from the 2d xpos, ypos to a normalized 3d direction
float x = (2.0f * xpos) / SCR_WIDTH - 1.0f;
float y = 1.0f - (2.0f * ypos) / SCR_HEIGHT;
float z = 1.0f;
vec3 ray_nds = vec3(x, y, z);
vec4 ray_clip = vec4(ray_nds.x, ray_nds.y, -1.0f, 1.0f);
// eye space to clip we would multiply by projection so
// clip space to eye space is the inverse projection
vec4 ray_eye = inverse(projection) * ray_clip;
// convert point to forwards
ray_eye = vec4(ray_eye.x, ray_eye.y, -1.0f, 0.0f);
// world space to eye space is usually multiply by view so
// eye space to world space is inverse view
vec4 inv_ray_wor = (inverse(view) * ray_eye);
vec3 ray_wor = vec3(inv_ray_wor.x, inv_ray_wor.y, inv_ray_wor.z);
ray_wor = normalize(ray_wor);
return ray_wor;
}
vec3 rayPlaneIntersection(vec3 ray_position, vec3 ray_direction, vec3 plane_normal, vec3 plane_position) {
float d = dot(plane_normal, plane_position - ray_position) / (0.001+dot(ray_direction, plane_normal));
return ray_position + ray_direction * d;
}
template<typename T>
vector<T> flatten(const vector<vector<T>> &orig, vec2 bottomLeft=vec2(0,0), vec2 topRight=vec2(GRID_WIDTH, GRID_HEIGHT))
{
vector<T> ret;
// for(const auto &v: orig)
// ret.insert(ret.end(), v.begin(), v.end());
float rx = (topRight.x >= GRID_WIDTH ? GRID_WIDTH : topRight.x+1);
float ry = (topRight.y >= GRID_HEIGHT ? GRID_HEIGHT : topRight.y+1);
float lx = (bottomLeft.x <= 0 ? 0 : bottomLeft.x);
float ly = (bottomLeft.y <= 0 ? 0 : bottomLeft.y);
for(int i = lx; i < rx; i++) {
vector<T> v = orig[i];
ret.insert(ret.end(), v.begin()+ly, v.begin() + ry);
}
return ret;
}
class QuadRenderer {
public:
unsigned int shaderProgram;
unsigned int VBO, VAO, EBO;
unsigned int matrixBuffer;
unsigned int colorBuffer;
vector<vector<vec3>> colors;
vector<vector<vec3>> frustumCulledColors;
vector<vec3> _colors;
vector<vector<mat4>> models;
vector<vector<mat4>> frustumCulledModels;
vector<mat4> _models;
mat4 viewProjection;
vec2 bottomLeft=vec2(0,0);
vec2 topRight=vec2(GRID_WIDTH, GRID_HEIGHT);
QuadRenderer() {
// create an empty grid
colors.resize(GRID_WIDTH);
for (int j = 0; j < GRID_WIDTH; j++) {
colors[j].resize(GRID_HEIGHT);
std::fill(colors[j].begin(),colors[j].end(),vec3(0));
}
models.resize(GRID_WIDTH);
for (int j = 0; j < GRID_WIDTH; j++) {
models[j].resize(GRID_HEIGHT);
std::fill(models[j].begin(),models[j].end(),mat4(0));
}
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in mat4 aInstanceMatrix;\n"
"layout (location = 5) in vec3 aCol\n;"
"uniform mat4 viewProjection;\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
" gl_Position = viewProjection * aInstanceMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
" color = aCol;\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 color;\n"
"void main()\n"
"{\n"
" FragColor = vec4(color,1);\n"
"}\n\0";
// build and compile our shader program
// ------------------------------------
// vertex shader
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl;
}
// fragment shader
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl;
}
// link shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float vertices[] = {
1.0f, 1.0f, 0.0f, // top right
1.0f, 0.0f, 0.0f, // bottom right
0.0f, 0.0f, 0.0f, // bottom left
0.0f, 1.0f, 0.0f // top left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first Triangle
1, 2, 3 // second Triangle
};
_models = flatten(models);
_colors = flatten(colors);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glGenBuffers(1, &matrixBuffer);
glGenBuffers(1, &colorBuffer);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, matrixBuffer);
glBufferData(GL_ARRAY_BUFFER, _models.size() * sizeof(mat4), &_models.front(), GL_STATIC_DRAW);
// set attribute pointers for matrix (4 times vec4)
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(2 * sizeof(vec4)));
glEnableVertexAttribArray(3);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(3 * sizeof(vec4)));
glEnableVertexAttribArray(4);
glVertexAttribDivisor(1, 1);
glVertexAttribDivisor(2, 1);
glVertexAttribDivisor(3, 1);
glVertexAttribDivisor(4, 1);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, _colors.size() * sizeof(vec3), &_colors.front(), GL_STATIC_DRAW);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(5);
glVertexAttribDivisor(5, 1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void calculateFrustum() {
vec3 rayWorld = rayCast(0, SCR_HEIGHT, projection, view);
vec3 worldPos = rayPlaneIntersection(cameraPos, rayWorld, vec3(0,0,1), vec3(0,0,0));
bottomLeft = vec2((int)worldPos.x, (int)worldPos.y);
rayWorld = rayCast(SCR_WIDTH, 0, projection, view);
worldPos = rayPlaneIntersection(cameraPos, rayWorld, vec3(0,0,1), vec3(0,0,0));
topRight = vec2((int)worldPos.x, (int)worldPos.y);
}
// send updated data to GPU
void update() {
_models = flatten(models, bottomLeft, topRight);
_colors = flatten(colors, bottomLeft, topRight);
vector<mat4> shadedCellModels = {};
vector<vec3> shadedCellColors = {};
for (int i = 0; i < _models.size(); i++) {
// only send initialized cells to the GPU
if (_models[i] != mat4(0) && _colors[i] != vec3(0)) {
shadedCellModels.push_back(_models[i]);
shadedCellColors.push_back(_colors[i]);
}
}
glBindBuffer(GL_ARRAY_BUFFER, matrixBuffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, shadedCellModels.size() * sizeof(mat4), &shadedCellModels.front());
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, shadedCellColors.size() * sizeof(vec3), &shadedCellColors.front());
}
void addQuad(vec2 pos, vec3 col) {
mat4 model = translate(mat4(1.0), vec3(pos, 0.0));
models[(int)pos.x][(int)pos.y] = model;
colors[(int)pos.x][(int)pos.y] = col;
}
void remove(vec2 pos) {
//change color to white
colors[(int)pos.x][(int)pos.y] = vec3(1);
}
void setCamera(mat4 cameraMatrix) {
viewProjection = cameraMatrix;
}
void draw() {
glUseProgram(shaderProgram);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "viewProjection"), 1, GL_FALSE, &viewProjection[0][0]);
// render quad
glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, _models.size());
glBindVertexArray(0);
}
};
vec3 selectedColor = vec3(0,1,0);
bool leftMouseButtonPressed = false;
bool rightMouseButtonPressed = false;
class Grid {
public:
LineRenderer lines;
QuadRenderer cells;
Grid() {
//glLineWidth(2);
// draw horizontal lines of grid
for (int j = 0; j <= GRID_HEIGHT; j++) {
lines.addLine(vec3(0, j, 0), vec3(GRID_WIDTH, j, 0));
}
// draw vertical lines of grid
for (int i = 0; i <= GRID_WIDTH; i++) {
lines.addLine(vec3(i, 0, 0), vec3(i,GRID_HEIGHT, 0));
};
}
void addCell(vec2 gridPos, vec3 color, bool updateImmediately=true) {
// ignore mouse clicks outside the grid
if (gridPos.x < 0 || gridPos.x > (GRID_WIDTH -1) || gridPos.y < 0 || gridPos.y > (GRID_HEIGHT -1)) {
return;
}
cells.addQuad(gridPos, color);
if (updateImmediately) {
cells.update();
}
}
void removeCell(vec2 gridPos, bool updateImmediately=true) {
// ignore mouse clicks outside the grid
if (gridPos.x < 0 || gridPos.x > (GRID_WIDTH -1) || gridPos.y < 0 || gridPos.y > (GRID_HEIGHT -1)) {
return;
}
cells.remove(gridPos);
if (updateImmediately) {
cells.update();
}
}
void draw() {
cells.draw();
lines.draw();
}
};
Grid *grid;
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
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "grid", NULL, NULL);
if (window == NULL)
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetScrollCallback(window, scroll_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
cout << "Failed to initialize GLAD" << endl;
return -1;
}
grid = new Grid();
for (int i = 0; i < GRID_WIDTH; i++) {
for (int j = 0; j < GRID_HEIGHT; j++) {
// when setting up grid have updateImmediately=false
// and batch update once at the end
grid->addCell(vec2(i,j), vec3(1,0,0), false);
}
}
// batch update
grid->cells.update();
// point camera at center of the grid, 15 units back from the grid
cameraPos = vec3(GRID_WIDTH/2, GRID_HEIGHT/2, 15.0f);
projection = perspective(radians(fov), ar, nearDist, farDist);
glClearColor(1.0, 1.0, 1.0, 1.0);
// set camera
view = lookAt(cameraPos, cameraPos + cameraFront, vec3(0,1,0));
grid->cells.setCamera(projection * view);
grid->lines.setCamera(projection * view);
while (!glfwWindowShouldClose(window))
{
// float currentFrame = glfwGetTime();
// deltaTime = currentFrame - lastFrame;
// lastFrame = currentFrame;
// std::cout << "FPS: " << 1.0/(0.00000001+deltaTime) << std::endl;
processInput(window);
glClear(GL_COLOR_BUFFER_BIT);
grid->draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
delete grid;
return 0;
}
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
// ray cast to find quad underneath mouse cursor
if (leftMouseButtonPressed) {
// cast from camera through mouse position
vec3 rayWorld = rayCast(lastX, lastY, projection, view);
// check for intersection with grid
vec3 worldPos = rayPlaneIntersection(cameraPos, rayWorld, vec3(0,0,1), vec3(0,0,0));
vec2 gridPos = vec2((int)worldPos.x, (int)worldPos.y);
grid->addCell(gridPos, selectedColor);
}
if (rightMouseButtonPressed) {
// cast from camera through mouse position
vec3 rayWorld = rayCast(lastX, lastY, projection, view);
// check for intersection with grid
vec3 worldPos = rayPlaneIntersection(cameraPos, rayWorld, vec3(0,0,1), vec3(0,0,0));
vec2 gridPos = vec2((int)worldPos.x, (int)worldPos.y);
grid->removeCell(gridPos);
}
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS)
selectedColor = vec3(1,0,0);
if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS)
selectedColor = vec3(0,1,0);
if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS)
selectedColor = vec3(0,0,1);
if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS)
selectedColor = vec3(1,1,0);
if (glfwGetKey(window, GLFW_KEY_5) == GLFW_PRESS)
selectedColor = vec3(1,0,1);
if (glfwGetKey(window, GLFW_KEY_6) == GLFW_PRESS)
selectedColor = vec3(1,1,0);
}
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos;
lastX = xpos;
lastY = ypos;
// switch to update less frequently when many squares on the screen
if (cameraPos.z > 15.0f) {
realTimeUpdating=false;
} else {
realTimeUpdating=true;
}
// scrolling moves camera closer and further from the grid
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_MIDDLE);
if (state == GLFW_PRESS)
{
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
cameraPos -= scrollSpeed * vec3(xoffset/(float)SCR_WIDTH, yoffset/(float)SCR_WIDTH, 0);
// update camera
view = lookAt(cameraPos, cameraPos + cameraFront, vec3(0,1,0));
grid->cells.setCamera(projection * view);
grid->lines.setCamera(projection * view);
grid->cells.calculateFrustum();
if (realTimeUpdating) {
grid->cells.update();
}
} else {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
firstMouse = true;
}
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
scrollSpeed = cameraPos.z * 0.1;
cameraPos += (float)yoffset * scrollSpeed * rayCast(lastX, lastY, projection, view);
// update camera
view = lookAt(cameraPos, cameraPos + cameraFront, vec3(0,1,0));
grid->cells.setCamera(projection * view);
grid->lines.setCamera(projection * view);
grid->cells.calculateFrustum();
grid->cells.update();
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) {
leftMouseButtonPressed = true;
} else {
leftMouseButtonPressed = false;
}
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) {
rightMouseButtonPressed = true;
} else {
rightMouseButtonPressed = false;
}
if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_RELEASE) {
if (!realTimeUpdating) {
grid->cells.update();
}
}
}
#包括
#包括
#包括
#包括
#包括
#定义GLM_启用_
#包括
#包括
#包括
使用std::vector;
使用std::cout;
使用std::endl;
使用glm::mat4;
使用glm::vec2;
使用glm::vec3;
使用glm::vec4;
使用glm::透视图;
使用glm::弧度;
使用glm::normalize;
无效处理输入(GLFWwindow*窗口);
无效鼠标回调(GLFWwindow*窗口,双XPO,双YPO);
无效鼠标按钮回调(GLFWwindow*窗口、int按钮、int操作、int mods);
void scroll_回调(GLFWwindow*窗口,双xoffset,双yoffset);
//背景
常量无符号整数SCR_WIDTH=800;
常数无符号整数SCR_高度=600;
//网格尺寸
常量无符号整数网格宽度=1000;
常量无符号整数网格高度=1000;
浮动lastX=SCR\U宽度/2.0f;
浮动弹性=SCR_高度/2.0f;
bool firstMouse=true;
bool realTimeUpdating=true;
//时机
浮动增量时间=0.0f;
浮动lastFrame=0.0f;
//做一个简单的相机类
vec3-cameraPos=vec3(0.0f,0.0f,0.0f);
vec3-cameraFront=vec3(0,0,-1);
vec3 cameraRight=vec3(1,0,0);
vec3-cameraUp=vec3(0,1,0);
mat4模型=mat4(1.0);
mat4视图;
mat4投影;
浮动滚动速度=2.0f;
浮动视野=90.0f;
浮动近距离=0.1f;
浮动远距=1000.0f;
浮动ar=(浮动)SCR_宽度/(浮动)SCR_高度;
类线条渲染器{
int着色器程序;
无符号整数VBO,VAO;
mat4视图投影;
向量顶点;
公众:
LineRenderer(){
const char*vertexShaderSource=“#版本330核心\n”
“vec3 aPos中的布局(位置=0);\n”
“统一mat4视图投影;\n”
“void main()\n”
“{\n