opengl绘制obj
时间: 2023-10-07 16:09:01 浏览: 145
要绘制一个OBJ文件,你需要使用OpenGL的三个核心功能:顶点缓冲对象(VBO)、顶点数组对象(VAO)和着色器程序。OBJ文件包含了模型的顶点、法向量和纹理坐标等信息,我们需要将这些信息读入内存,并将它们存储在VBO中,然后使用VAO将这些数据传递给着色器程序进行渲染。
以下是一个简单的OpenGL代码,用于加载并渲染一个OBJ文件:
```c++
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
struct Vertex {
float x, y, z;
float nx, ny, nz;
float u, v;
};
int main() {
// 初始化GLFW窗口
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
// 初始化GLEW库
glewExperimental = true;
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
// 加载OBJ文件
std::vector<Vertex> vertices;
std::ifstream file("model.obj");
std::string line;
while (std::getline(file, line)) {
std::istringstream iss(line);
std::string type;
iss >> type;
if (type == "v") {
Vertex vertex;
iss >> vertex.x >> vertex.y >> vertex.z;
vertices.push_back(vertex);
} else if (type == "vn") {
int index = vertices.size() - 1;
iss >> vertices[index].nx >> vertices[index].ny >> vertices[index].nz;
} else if (type == "vt") {
int index = vertices.size() - 1;
iss >> vertices[index].u >> vertices[index].v;
}
}
// 创建VBO和VAO
GLuint vbo, vao;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, nx));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, u));
// 创建着色器程序
const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoord;
out vec3 Normal;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = projection * view * model * vec4(aPos, 1.0);
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoord = aTexCoord;
}
)";
const char* fragmentShaderSource = R"(
#version 330 core
in vec3 Normal;
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D texture1;
void main() {
vec4 texColor = texture(texture1, TexCoord);
vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0));
float diff = max(dot(Normal, lightDir), 0.0);
vec3 diffuse = diff * vec3(1.0, 1.0, 1.0);
FragColor = texColor * vec4(diffuse, 1.0);
}
)";
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 渲染循环
while (!glfwWindowShouldClose(window)) {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram);
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLuint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLuint projectionLoc = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
glfwSwapBuffers(window);
glfwPollEvents();
}
// 释放资源
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glfwTerminate();
return 0;
}
```
这个代码使用了glm库进行矩阵计算,并使用了SOIL库加载纹理文件。如果你没有使用这些库,可以自行替换为其他库或手写相关函数。
阅读全文