日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenGL(可编程管线):Bezier曲面

發布時間:2023/12/20 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenGL(可编程管线):Bezier曲面 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Bezier曲面

  • Bezier線
    • de Casteljau算法
  • Bezier曲面
    • bezier曲面編程思想
    • 實例
    • 代碼
    • 運行結果

Bezier線

貝塞爾曲線由一組參數方程定義,方程組中使用控制點指定特定的曲線的形狀,每個控制點都是2D空間中的一個點。

de Casteljau算法


其中B(t)為Bernstein多項式,另外了解,這里不做解釋(主要是沒有深入研究…)。

此圖來自《計算機圖形學編程(使用OpenGL和C++)》

Bezier曲面

Bezier曲面定義了3D空間中的曲面,從Bezier曲線拓展,需要將bezier曲線的參數方程從一個參數拓展為兩個參數。對于bezier曲線參數為t,在bezier曲面中參數為u和v。曲面的點由P(u, v)組成。

此圖來自《計算機圖形學編程(使用OpenGL和C++)》,此圖為二次bezier曲面,有9個控制點
此時的參數方程為:

bezier曲面編程思想

我們將曲面橫豎分別分成m,n份,那么曲面分成了m×n份,我們可以通過繪制m×n份近似矩形,就可以模擬出bezier曲面

實例

以三次bezier曲面為例:
假如我把bezier曲面分成了6×6塊,如下圖

在圖中我們可以清晰的看出u,v坐標每次的增量是1/6,我們只要算出(u,v)坐標所在處的坐標就可以繪制出所需要的bezier曲面。

代碼

構建bezier曲面類

#pragma once #include <vector> #include <glm/glm.hpp> using namespace std;class BezierFace {//頂點個數int numVertices;//索引個數int numIndices;//頂點vector<glm::vec3> vertices;//法線vector<glm::vec3> normals;//紋理vector<glm::vec2> texCoords;//索引vector<int> indices;//計算數據void init(int prec);//控制點float* controlPoints;vector<glm::vec3> controlPointsVector;//曲線階數int step;float toRadians(float degrees);float Bernstein(float u, int index); public:BezierFace();BezierFace(int step, float controlPoints[], int prec);int getNumVertices();int getNumIndices();vector<glm::vec3> getVertices();vector<glm::vec3> getNormals();vector<glm::vec2> getTexCoords();vector<int> getIndices();}; #include "BezierFace.h"void BezierFace::init(int prec) {numVertices = (prec + 1) * (prec + 1);numIndices = prec * prec * 6;for (int i = 0; i < numVertices; i++){vertices.push_back(glm::vec3());normals.push_back(glm::vec3());texCoords.push_back(glm::vec2());}for (int i = 0; i < numIndices; i++){indices.push_back(0);}for (int i = 0; i < (step + 1) * (step + 1) * 3; i += 3){controlPointsVector.push_back(glm::vec3(controlPoints[i], controlPoints[i + 1], controlPoints[i + 2]));}for (int i = 0; i <= prec; i++){for (int j = 0; j <= prec; j++){float x = 0.0f;float y = 0.0f;float z = 0.0f;float u = (float)i / prec;float v = (float)j / prec;for (int i = 0; i <= 3; i++){for (int j = 0; j <= 3; j++){int index = i * 4 + j;x += controlPointsVector[index].x * Bernstein(u, i) * Bernstein(v, j);y += controlPointsVector[index].y * Bernstein(u, i) * Bernstein(v, j);z += controlPointsVector[index].z * Bernstein(u, i) * Bernstein(v, j);}}vertices[i * (prec + 1) + j] = glm::vec3(x, y, z);normals[i * (prec + 1) + j] = glm::vec3(x, y, z);texCoords[i * (prec + 1) + j] = glm::vec2((float)j / prec, (float)i / prec);}}//計算索引for (int i = 0; i < prec; i++) {for (int j = 0; j < prec; j++) {indices[6 * (i * prec + j) + 0] = i * (prec + 1) + j;indices[6 * (i * prec + j) + 1] = i * (prec + 1) + j + 1;indices[6 * (i * prec + j) + 2] = (i + 1) * (prec + 1) + j;indices[6 * (i * prec + j) + 3] = i * (prec + 1) + j + 1;indices[6 * (i * prec + j) + 4] = (i + 1) * (prec + 1) + j + 1;indices[6 * (i * prec + j) + 5] = (i + 1) * (prec + 1) + j;}} } float BezierFace::toRadians(float degrees) { return (degrees * 2.0f * 3.14159f) / 360.0f; }float BezierFace::Bernstein(float t, int index) {switch (index){default:case 0:return pow(1.0 - t, 3);break;case 1:return 3 * t * pow(1.0 - t, 2);break;case 2:return 3 * pow(t, 2) * (1 - t);break;case 3:return pow(t, 3);break;}} BezierFace::BezierFace(){}BezierFace::BezierFace(int step, float controlPoints[], int prec) {this->step = step;this->controlPoints = controlPoints;init(prec); }int BezierFace::getNumVertices() {return numVertices; }int BezierFace::getNumIndices() {return numIndices; }vector<glm::vec3> BezierFace::getVertices() {return vertices; }vector<glm::vec3> BezierFace::getNormals() {return normals; }vector<glm::vec2> BezierFace::getTexCoords() {return texCoords; }vector<int> BezierFace::getIndices() {return indices; }

運行實例:

#define GLEW_STATIC #include <iostream> #include "Camera.h" #include "Circle.h" #include "Shader.h" #include <GL/glew.h> #include <glm/glm.hpp> #include <glm\gtc\type_ptr.hpp> // glm::value_ptr #include <glm\gtc\matrix_transform.hpp> #include <GLFW/glfw3.h> #include <SOIL2/SOIL2.h> #include "Ellipse.h" #include "Ellipsoid.h" #include "BezierFace.h" #include "BezierLine.h"using namespace std;float controlPoints[] = {-1.5, -1.5, 2.0, -0.5, -1.5, 2.0, 0.5, -1.5, -1.0, 1.5, -1.5, 2.0,-1.5, -0.5, 1.0, -0.5, 1.5, 2.0, 0.5, 0.5, 1.0, 1.5, -0.5, -1.0,-1.5, 0.5, 2.0, -0.5, 0.5, 1.0, 0.5, 0.5, 3.0, 1.5, -1.5, 1.5, -1.5, 1.5, -2.0, -0.5, 1.5, -2.0, 0.5, 0.5, 1.0, 1.5, 1.5, -1.0 }; BezierFace myBezier = BezierFace(3, controlPoints, 100); GLuint VAO, VBO[3]; GLuint texture; Shader myShader; Camera myCamera(glm::vec3(0.0f, 0.0f, 2.0f)); GLFWwindow* window; float deltaTime = 0.0f; // time between current frame and last frame float lastFrame = 0.0f; float lastX = 400.f; float lastY = 300.f; bool firstMouse = true;void processInput(GLFWwindow* window) {if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS){glfwSetWindowShouldClose(window, true);}if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS){myCamera.ProcessKeyboard(FORWARD, deltaTime);}else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS){myCamera.ProcessKeyboard(BACKWARD, deltaTime);}else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS){myCamera.ProcessKeyboard(LEFT, deltaTime);}else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS){myCamera.ProcessKeyboard(RIGHT, deltaTime);} }void mouse_callback(GLFWwindow* window, double xPos, double yPos) {if (firstMouse){lastX = xPos;lastY = yPos;firstMouse = false;}float deltaX, deltaY;deltaX = xPos - lastX;deltaY = lastY - yPos;lastX = xPos;lastY = yPos;myCamera.ProcessMouseMovement(deltaX, deltaY);}void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {myCamera.ProcessMouseScroll(yoffset); }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); }GLuint loadTexture(const char* texImagePath) {GLuint textureRef;textureRef = SOIL_load_OGL_texture(texImagePath, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);if (textureRef == 0) cout << "didnt find texture file " << texImagePath << endl;// ----- mipmap/anisotropic sectionglBindTexture(GL_TEXTURE_2D, textureRef);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glGenerateMipmap(GL_TEXTURE_2D);if (glewIsSupported("GL_EXT_texture_filter_anisotropic")) {GLfloat anisoset = 0.0f;glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisoset);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoset);}// ----- end of mipmap/anisotropic sectionreturn textureRef; }void setupVertices() {vector<float> pvalues; //頂點坐標vector<float> tvalues; //紋理坐標vector<float> nvalues; //法線vector<int> ind = myBezier.getIndices();vector<glm::vec3> verts = myBezier.getVertices();vector<glm::vec2> tex = myBezier.getTexCoords();vector<glm::vec3> norm = myBezier.getNormals();for (int i = 0; i < myBezier.getNumIndices(); i++){pvalues.push_back(verts[ind[i]].x);pvalues.push_back(verts[ind[i]].y);pvalues.push_back(verts[ind[i]].z);tvalues.push_back(tex[ind[i]].s);tvalues.push_back(tex[ind[i]].t);nvalues.push_back(norm[ind[i]].x);nvalues.push_back(norm[ind[i]].y);nvalues.push_back(norm[ind[i]].z);}glGenVertexArrays(1, &VAO);glGenBuffers(3, VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);glBufferData(GL_ARRAY_BUFFER, pvalues.size() * 4, &pvalues[0], GL_STATIC_DRAW);glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);glBufferData(GL_ARRAY_BUFFER, tvalues.size() * 4, &tvalues[0], GL_STATIC_DRAW);glBindBuffer(GL_ARRAY_BUFFER, VBO[2]);glBufferData(GL_ARRAY_BUFFER, nvalues.size() * 4, &nvalues[0], GL_STATIC_DRAW);}void init(GLFWwindow* window) {myShader = Shader("bezierVert.vert", "bezierFrag.frag");glfwSetCursorPosCallback(window, mouse_callback);glfwSetCursorPosCallback(window, mouse_callback);glfwSetScrollCallback(window, scroll_callback);glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);setupVertices();texture = loadTexture("flower.png"); }void display(GLFWwindow* window, double currentTime) {float currentFrame = glfwGetTime();deltaTime = currentFrame - lastFrame;lastFrame = currentFrame;glClearColor(1.0f, 1.0f, 1.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//輸入processInput(window);myShader.use();glm::mat4 projection = glm::perspective(glm::radians(myCamera.Zoom), 800.0f / 600.0f, 0.1f, 100.0f);glm::mat4 view = myCamera.GetViewMatrix();glm::mat4 model = glm::mat4(1.0f);myShader.setMat4("projection", projection);myShader.setMat4("view", view);myShader.setMat4("model", model);glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);glEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);glEnableVertexAttribArray(1);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture);glEnable(GL_CULL_FACE);glFrontFace(GL_CCW);glDrawArrays(GL_TRIANGLES, 0, myBezier.getNumIndices()); }int main() {if(!glfwInit()) {exit(EXIT_FAILURE);}glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);GLFWwindow* window = glfwCreateWindow(1600, 1200, "Ellipsoid", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }//glfwSwapInterval(1);glViewport(0, 0, 1600, 1200);glEnable(GL_DEPTH_TEST);init(window);while (!glfwWindowShouldClose(window)) {display(window, glfwGetTime());glfwSwapBuffers(window);glfwPollEvents();}glfwDestroyWindow(window);glfwTerminate();exit(EXIT_SUCCESS); }

著色器

#version 330 layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord;out vec2 TexCoord;uniform mat4 model; uniform mat4 view; uniform mat4 projection;void main() {gl_Position = projection * view * model * vec4(aPos, 1.0);TexCoord = aTexCoord; } #version 330 out vec4 FragColor; in vec2 TexCoord;uniform sampler2D s; void main() {FragColor = texture(s, TexCoord); }

運行結果

總結

以上是生活随笔為你收集整理的OpenGL(可编程管线):Bezier曲面的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。