Я хочу визуализировать некоторую форму, используя ряд Фурье, и я закончил класс инструментов рендеринга (стрелка и ручка).Но конечный результат выглядит неудобно.Моя идея рендеринга состоит в том, чтобы сначала установить позиции стрелок, а затем использовать их для рендеринга кругов в виде рукописных фигур.После поворота на фиксированный угол устанавливается стрелка.Эта идея дает следующий вывод:
эффект вывода:
На самом деле я хочу отрисовать строку, и я не знаю, какчтобы решить это.Я использую FBO для хранения почерка и рендеринга стрелки в FBO по умолчанию, коды следующие:
- main.cpp
// include for create a window
#include <glad/glad.h>
#include <GLFW/glfw3.h>
// include for matrix calculation
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
// include for creating arrow
#include "Arrow.h"
// include for creating pen
#include "Pen.h"
// include for drawing circle
#include <cmath>
#include <iostream>
#include <stdio.h>
using namespace std;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void renderBoard();
const int SCR_WIDTH = 800;
const int SCR_HEIGHT = 800;
int main()
{
// initialize window glfw 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); // uncomment this statement to fix compilation on OS X
#endif
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);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Create drawing board FBO
unsigned int boardFBO;
glGenFramebuffers(1, &boardFBO);
glBindFramebuffer(GL_FRAMEBUFFER, boardFBO);
unsigned int boardColorBuffer;
glGenTextures(1, &boardColorBuffer);
glBindTexture(GL_TEXTURE_2D, boardColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, boardColorBuffer, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
cout << "Board Color Buffer isn't complete\n" << endl;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Create arrow
Arrow arrow1(1.1), arrow2;
// Create Pen
Pen pen = Pen(0.0, 0.0, 0.0, 0.004);
pen.setOriginPosition(glm::vec3(0.0, 0.0, 0.0));
// Create Sahder
Shader arrowShader("arrow.vs", "arrow.fs");
Shader boardShader("board.vs", "board.fs");
boardShader.use();
boardShader.setInt("boardColorBuffer", 0);
bool isFirst = true;
// render loop
while (!glfwWindowShouldClose(window))
{
// input
processInput(window);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
arrow1.rotateArrow(0.5f);
arrow1.setPosition(glm::vec3(0.0, 0.0, 0.0));
arrow2.rotateArrow(5.0f);
arrow2.setPosition(arrow1.getHeadPosition());
// render pen draw
// glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, boardFBO);
glClearColor(0.0, 0.0, 0.0, 1.0);
if (isFirst) {
glClear(GL_COLOR_BUFFER_BIT);
isFirst = false;
}
arrowShader.use();
pen.setOriginPosition(arrow2.getHeadPosition());
pen.drawPen(arrowShader);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// glViewport(0, 0, SCR_WIDTH * 2, SCR_HEIGHT * 2);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
boardShader.use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, boardColorBuffer);
renderBoard();
arrowShader.use();
arrow1.drawArrow(arrowShader);
arrow2.drawArrow(arrowShader);
// render
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
}
unsigned int boardVAO = 0;
unsigned int boardVBO;
void renderBoard() {
if (boardVAO == 0) {
float boardVertices[] = {
-1.0, 1.0, 0.0, 0.0, 1.0, // up-left
-1.0, -1.0, 0.0, 0.0, 0.0, // down-left
1.0, 1.0, 0.0, 1.0, 1.0, // up-right
1.0, -1.0, 0.0, 1.0, 0.0 // down right
};
glGenVertexArrays(1, &boardVAO);
glBindVertexArray(boardVAO);
glGenBuffers(1, &boardVBO);
glBindBuffer(GL_ARRAY_BUFFER, boardVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(boardVertices), boardVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
}
glBindVertexArray(boardVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
}
Arrow.h
#ifndef Arrow_h
#define Arrow_h
#include <GLFW/glfw3.h>
#include <glad/glad.h>
// include for matrix operation
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Shader.h"
class Arrow {
public:
Arrow(float scale = 1.0, glm::vec3 position = glm::vec3(0.0, 0.0, 0.0)) {
scale = scale;
float arrowVertices[] = {
// rectangle
-0.001, 0.0, 0.0, // bottom-left
-0.001, 0.11, 0.0, // up-left
0.001, 0.0, 0.0, // bottom-right
0.001, 0.11, 0.0, // up-right
// triangle
0.0, 0.15, 0.0, // up
-0.01, 0.11, 0.0, // bottom-left
0.01, 0.11, 0.0 // bottom-right
};
int arrowIndices[] = {
0, 1, 2,
2, 1, 3,
4, 5, 6
};
arrowVertices[4] *= scale;
arrowVertices[10] *= scale;
arrowVertices[13] *= scale;
arrowVertices[16] *= scale;
arrowVertices[19] *= scale;
headPos = initHeadPos = glm::vec3(0.0, arrowVertices[13], 0.0);
tailPos = initTailPos = glm::vec3(0.0, 0.0, 0.0);
rotateOffsetModel = glm::mat4(1.0);
positionOffset = glm::mat4(1.0);
positionOffset = glm::translate(positionOffset, position);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(arrowVertices), arrowVertices, GL_STATIC_DRAW);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(arrowIndices), arrowIndices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
// draw arrow
void drawArrow(Shader shader) {
shader.use();
// alert arrow position
shader.setMat4("model", positionOffset * rotateOffsetModel);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 9, GL_UNSIGNED_INT, (void*)0);
glBindVertexArray(0);
}
// rotate arrow in local coordinate
void rotateArrow(float degree, glm::vec3 axis = glm::vec3(0.0, 0.0, 1.0)) {
rotateOffsetModel = glm::rotate(rotateOffsetModel, glm::radians(degree), axis); // get rotate matrix
headPos = glm::vec3(rotateOffsetModel * glm::vec4(initHeadPos, 1.0));
tailPos = glm::vec3(rotateOffsetModel * glm::vec4(initTailPos, 1.0));
}
// set arrow's position
void setPosition(glm::vec3 Position) {
positionOffset = glm::mat4(1.0);
positionOffset = glm::translate(positionOffset, Position);
headPos = glm::vec3(positionOffset * rotateOffsetModel * glm::vec4(initHeadPos, 1.0));
tailPos = glm::vec3(positionOffset * rotateOffsetModel * glm::vec4(initTailPos, 1.0));
}
// alert head and tail info
void alertHeadTailPosition(glm::mat4 alertModel) {
headPos = glm::vec3(alertModel * glm::vec4(initHeadPos, 1.0));
tailPos = glm::vec3(alertModel * glm::vec4(initTailPos, 1.0));
}
// get head ( the up coordinate of triangle ) coordinate
glm::vec3 getHeadPosition() {
return headPos;
}
// get tail ( the middle coordinate of triangle's bottom ) coordinate
glm::vec3 getTailPosition() {
return tailPos;
}
private:
unsigned int VAO, VBO, EBO;
glm::mat4 rotateOffsetModel, positionOffset;
glm::vec3 headPos, tailPos;
glm::vec3 initHeadPos, initTailPos; // I find that the offset set will add if I always use one variable
GLfloat Scale;
};
#endif /* Arrow_h */
Ручка
// This class is used to create a pen which is used to draw the graph
#include <GLFW/glfw3.h>
#include <glad/glad.h>
#include <iostream>
#include "Shader.h"
#include <vector>
#include <math.h>
using namespace std;
#ifndef Pen_h
#define Pen_h
class Pen {
public:
Pen(GLfloat xPos, GLfloat yPos, GLfloat zPos, GLfloat Radius)
: originPosition(glm::vec3(xPos, yPos, zPos)), radius(Radius), edges(360) {
configurePen();
}
Pen(glm::vec3 penPosition, GLfloat Radius)
: originPosition(penPosition), radius(Radius), edges(360) {
configurePen();
}
void configurePen() {
allPenVertices.push_back(originPosition);
GLfloat doublePi = 2.0 * M_PI;
for (int i = 1; i < edges + 2; i++) {
float x, y;
x = originPosition.x + cos((float)i / edges * doublePi) * radius;
y = originPosition.y + sin((float)i / edges * doublePi) * radius;
allPenVertices.push_back(glm::vec3(x, y, 0.0));
}
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, allPenVertices.size() * 3 * sizeof(float), &allPenVertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
void drawPen(Shader shader) {
shader.use();
glBindVertexArray(VAO);
shader.setMat4("model", offsetModel);
glDrawArrays(GL_TRIANGLE_FAN, 0, allPenVertices.size());
}
void setOriginPosition(glm::vec3 Position) {
offsetModel = glm::mat4(1.0);
offsetModel = glm::translate(offsetModel, glm::vec3(Position));
}
private:
GLfloat radius;
glm::vec3 originPosition;
GLint edges, numberOfVertices;
vector<glm::vec3> allPenVertices;
unsigned int VAO, VBO;
glm::mat4 offsetModel;
};
#endif /* Pen_h */
Должен ли я изменить свою идею рендеринга?Или я должен использовать алгоритм для решения?