OpenGL画圆环

编程入门 行业动态 更新时间:2024-10-10 13:18:49

OpenGL画<a href=https://www.elefans.com/category/jswz/34/1760526.html style=圆环"/>

OpenGL画圆环

代码主要由Torus.hpp、Torus.cpp、Utils.hpp构成,通过加载纹理图片和着色器文件Torus_Texture_frag.glsl、Torus_Texture_vert.glsl实现画出一个甜甜圈的效果。

主要用到的图形库有glew、glfw3、soil2、glm

实现如下:

Utils.hpp包含了加载纹理和glsl着色器文件的功能性程序

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "SOIL2/SOIL2.h"
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp> // glm::value_ptr
#include <glm/gtc/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
using namespace std;class Utils
{
private:static GLuint prepareShader(int shaderTYPE, const char* shaderPath);public:Utils(){};static GLuint createShaderProgram(const char* vp, const char* fp);static GLuint loadTexture(const char *texImagePath)
};GLuint Utils::prepareShader(int shaderTYPE, const char* shaderPath)
{GLint shaderCompiled;string shaderStr = readShaderFile(shaderPath);const char* shaderSrc = shaderStr.c_str();GLuint shaderRef = glCreateShader(shaderTYPE);glShaderSource(shaderRef, 1, &shaderSrc, NULL);glCompileShader(shaderRef);checkOpenGLError();glGetShaderiv(shaderRef, GL_COMPILE_STATUS, &shaderCompiled);if (shaderCompiled != 1){if (shaderTYPE == 35633) cout << "Vertex ";if (shaderTYPE == 36488) cout << "Tess Control ";if (shaderTYPE == 36487) cout << "Tess Eval ";if (shaderTYPE == 36313) cout << "Geometry ";if (shaderTYPE == 35632) cout << "Fragment ";cout << "shader compilation error." << endl;printShaderLog(shaderRef);}return shaderRef;
}GLuint Utils::createShaderProgram(const char* vp, const char* fp) {GLuint vShader = prepareShader(GL_VERTEX_SHADER, vp);GLuint fShader = prepareShader(GL_FRAGMENT_SHADER, fp);GLuint vfprogram = glCreateProgram();glAttachShader(vfprogram, vShader);glAttachShader(vfprogram, fShader);finalizeShaderProgram(vfprogram);return vfprogram;
}GLuint Utils::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);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;
}

主程序入口draw_Torus.cpp

#define GLEW_STATIC
#include<GL/glew.h>
#include<GLFW\glfw3.h>
#include<string>
#include<iostream>
#include<fstream>
#include<cmath>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include"SOIL2/SOIL2.h"
#include "Utils.hpp"
#include"Torus.hpp"using namespace std;#define numVAOs 1
#define numVBOs 4float cameraX, cameraY, cameraZ;
float pyrLocX, pyrLocY, pyrLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];//allocate variables used in display() function, so that they won't need to be allocated during rendering
GLuint mvLoc, projLoc;
GLuint brickTexture;
int width, height;
float aspect, tf;
glm::mat4 pMat, vMat, mMat, mvMat;
Torus myTorus(1.8f, 1.0f, 48);
vector<int> ind;void setupVertices(void) {ind = myTorus.getIndices();vector<glm::vec3> vert = myTorus.getVertices();vector<glm::vec2> tex = myTorus.getTexCoords();vector<glm::vec3> norm =myTorus.getNormals();vector<float> pvalues;vector<float> tvalues;vector<float> nvalues;int numVertices = myTorus.getNumVertices();for (int i = 0; i < numVertices; i++) {pvalues.push_back((vert[i]).x);pvalues.push_back((vert[i]).y);pvalues.push_back((vert[i]).z);tvalues.push_back((tex[i]).s);tvalues.push_back((tex[i]).t);nvalues.push_back((norm[i]).x);nvalues.push_back((norm[i]).y);nvalues.push_back((norm[i]).z);}glGenVertexArrays(1, vao);glBindVertexArray(vao[0]);//put the vertices into buffer #0glGenBuffers(4, vbo);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);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[3]);glBufferData(GL_ELEMENT_ARRAY_BUFFER, ind.size() * 4, &ind[0], GL_STATIC_DRAW);
}void init(GLFWwindow* window) {renderingProgram = Utils::createShaderProgram("Torus_Texture_vert.glsl", "Torus_Texture_frag.glsl");glfwGetFramebufferSize(window, &width, &height);aspect = (float)width / (float)height;pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);//1.0472 radians=60degreescameraX = 1.5f; cameraY = -3.6f; cameraZ = 10.0f;pyrLocX = -0.6f; pyrLocY = 0.7f; pyrLocZ = -5.0f;//注意方位设置的问题,很可能因为方位设置使得某物体在窗口不可见brickTexture = Utils::loadTexture("imgs/donut.jpg");setupVertices();
}void  display(GLFWwindow* window, double currentTime)
{glClear(GL_DEPTH_BUFFER_BIT);glClearColor(0.0, 0.0, 0.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(renderingProgram);//get  the uniform variables for the MV and projection matricesmvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");//get location of uniforms in the shader programprojLoc = glGetUniformLocation(renderingProgram, "proj_matrix");//build view matrix,model matrix,and model-view matrix	vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));//draw the cube(use buffer #0)mvMat = vMat * mMat;glEnable(GL_CULL_FACE);glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);glEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);glEnableVertexAttribArray(1);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[3]);	glBufferData(GL_ELEMENT_ARRAY_BUFFER, ind.size() * 4, &ind[0], GL_STATIC_DRAW);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, brickTexture);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LEQUAL);glDrawElements(GL_TRIANGLES, myTorus.getNumIndices(), GL_UNSIGNED_INT, 0);
}int main(void)
{if (!glfwInit()) {exit(EXIT_FAILURE);}glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//use OpenGL version4.3GLFWwindow* window = glfwCreateWindow(2000, 2000, "Torus shadered by Donut Texture", NULL, NULL);//the last//two parameters allow for full screen mode and resource sharingglfwMakeContextCurrent(window);if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }glfwSwapInterval(1);init(window);while (!glfwWindowShouldClose(window)){display(window, glfwGetTime());glfwSwapBuffers(window);glfwPollEvents();//handle other window related  events(such as the user clicking the "X"//in the upper right corner,the window module)}glfwDestroyWindow(window);glfwTerminate();exit(EXIT_SUCCESS);return 0;
}

Torus.hpp:

#pragma once
#include<cmath>
#include<vector>
#include<glm\glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
class Torus
{
private:int numVertices;int numIndices;int prec;float inner;float outer;std::vector<int> indices;std::vector<glm::vec3> vertices;std::vector<glm::vec2> texCoords;std::vector<glm::vec3> normals;std::vector<glm::vec3> sTangents;std::vector<glm::vec3> tTangents;void init();float toRadians(float degrees);
public:Torus();Torus(float innerRadius, float outerRadius, int prec);int getNumVertices();int getNumIndices();std::vector<int> getIndices();std::vector<glm::vec3> getVertices();std::vector<glm::vec2> getTexCoords();std::vector<glm::vec3> getNormals();std::vector<glm::vec3> getStangents();std::vector<glm::vec3> getTtangents();
};

Torus.cpp:

#include<cmath>
#include<vector>
#include<iostream>
#include "Torus.hpp"
using namespace std;Torus::Torus() {prec = 48;inner = 5.0f;outer = 2.0f;init();
}Torus::Torus(float innerRadius, float outerRadius, int precIn) {prec = precIn;inner = innerRadius;outer = outerRadius;init();
}inline float Torus::toRadians(float degrees) { return (degrees * 2.0f * 3.14159f) / 360.0f; }void Torus::init() {numVertices = (prec + 1) * (prec + 1);numIndices = prec * prec * 6;for (int i = 0; i < numVertices; i++) {vertices.push_back(glm::vec3());texCoords.push_back(glm::vec2());normals.push_back(glm::vec3());sTangents.push_back(glm::vec3());tTangents.push_back(glm::vec3());}for (int i = 0; i < numIndices; i++) { indices.push_back(0); }for (int i = 0; i < prec + 1; i++) {float amt = toRadians(i * 360.0f / prec);//build the ring by rotating points around the origin,then moving them outwardglm::mat4 rMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 0.0f, 1.0f));glm::vec3 initPos(rMat * glm::vec4(outer, 0.0f, 0.0f, 1.0f));vertices[i] = glm::vec3(initPos+glm::vec3(inner,0.0f,0.0f));//compute texture coordinates for each vertex on the ringtexCoords[i] = glm::vec2(0.0f, ((float)i / (float)prec));//compute tangents and noramals -- first tangent is Y-axis rotated around ZrMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 0.0f, 1.0f));tTangents[i] = glm::vec3(rMat * glm::vec4(0.0f, -1.0f, 0.0f, 1.0f));sTangents[i] = glm::vec3(glm::vec3(0.0f, 0.0f, -1.0f));normals[i] = glm::cross(tTangents[i], sTangents[i]);for (int ring = 1; ring < prec + 1; ring++) {for (int vert = 0; vert < prec + 1; vert++) {//rotate the vertex position of the original ring around the Y axisfloat amt = (float)(toRadians(ring * 360.0f / prec));glm::mat4 rMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 1.0f, 0.0f));vertices[ring * (prec + 1) + i] = glm::vec3(rMat * glm::vec4(vertices[i], 1.0f));//compute the texture coordinates for the vertices in the new ringstexCoords[ring * (prec + 1) + vert] = glm::vec2((float)ring * 2.0f / (float)prec, texCoords[vert].t);if (texCoords[ring * (prec + 1) + i].s > 1.0) texCoords[ring * (prec + 1) + i].s -= 1.0f;//rotate the tangent and bitangent vectors around the Y axisrMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 1.0f, 0.0f));sTangents[ring * (prec + 1) + i] = glm::vec3(rMat * glm::vec4(sTangents[i], 1.0f));rMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 1.0f, 0.0f));tTangents[ring * (prec + 1) + i] = glm::vec3(rMat * glm::vec4(tTangents[i], 1.0f));//rotate the normal vector around the Y axisrMat = glm::rotate(glm::mat4(1.0f), amt, glm::vec3(0.0f, 1.0f, 0.0f));normals[ring * (prec + 1) + i] = glm::vec3(rMat * glm::vec4(normals[i], 1.0f));}}//calculate triangle indices corresponding to the two triangles built per vertexfor (int ring = 0; ring < prec; ring++) {for (int vert = 0; vert < prec; vert++) {indices[((ring * prec + vert) * 2) * 3 + 0] = ring * (prec + 1) + vert;indices[((ring * prec + vert) * 2) * 3 + 1] = (ring + 1) * (prec + 1) + vert;indices[((ring * prec + vert) * 2) * 3 + 2] = ring * (prec + 1) + vert + 1;indices[((ring * prec + vert) * 2 + 1) * 3 + 0] = ring * (prec + 1) + vert + 1;indices[((ring * prec + vert) * 2 + 1) * 3 + 1] = (ring + 1) * (prec + 1) + vert;indices[((ring * prec + vert) * 2 + 1) * 3 + 2] = (ring + 1) * (prec + 1) + vert + 1;}}}
}//accessors for the torus indices and vertices
int Torus::getNumVertices() { return numVertices; }
int Torus::getNumIndices() { return numIndices; }
std::vector<int> Torus::getIndices() { return indices; }
std::vector<glm::vec3> Torus::getVertices() { return vertices; }
std::vector<glm::vec2> Torus::getTexCoords() { return texCoords; }
std::vector<glm::vec3> Torus::getNormals() { return normals; }
std::vector<glm::vec3> Torus::getStangents() { return sTangents; }
std::vector<glm::vec3> Torus::getTtangents() { return tTangents; }

着色器Torus_Texture_frag.glsl

#version 430
in vec2 tc;
out vec4 color;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
layout (binding=0) uniform sampler2D samp;void main(void)
{color=texture(samp,tc);
}

着色器Torus_Texture_vert.glsl

#version 430
layout(location=0) in vec3 pos;
layout(location=1) in vec2 texCoord;
out vec2 tc;			//texture coordinate output to rasterizer for interpolation
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
layout (binding=0) uniform sampler2D samp;void main(void)
{gl_Position = proj_matrix * mv_matrix * vec4(pos,1.0);tc= texCoord;
}

纹理图片在draw_Torus.cpp所在目录下的imgs文件夹下

 

更多推荐

OpenGL画圆环

本文发布于:2024-03-10 11:38:39,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1727859.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:圆环   OpenGL

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!