Untitled
unknown
c_cpp
2 years ago
8.8 kB
5
Indexable
#include<iostream>
#include<filesystem>
#include<vector>
#include<string>
#include<glad/glad.h>
#include<GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include<STB/stb_image.h>
#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
#include"textfile.h"
using namespace glm;
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 800;
GLuint program;
GLuint texture;
void setShaders() {
GLuint v, f, p;
char* vs = NULL;
char* fs = NULL;
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead("shader.vs.glsl");
fs = textFileRead("shader.fs.glsl");
glShaderSource(v, 1, (const GLchar**)&vs, NULL);
glShaderSource(f, 1, (const GLchar**)&fs, NULL);
free(vs);
free(fs);
GLint success;
char infoLog[1000];
// compile vertex shader
glCompileShader(v);
glGetShaderiv(v, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(v, 1000, NULL, infoLog);
std::cout << "ERROR: VERTEX SHADER COMPILATION FAILED\n" << infoLog << std::endl;
}
// compile fragment shader
glCompileShader(f);
glGetShaderiv(f, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(f, 1000, NULL, infoLog);
std::cout << "ERROR: FRAGMENT SHADER COMPILATION FAILED\n" << infoLog << std::endl;
}
// create program object
p = glCreateProgram(); // p: program的id
// attach shaders to program object
glAttachShader(p, f);
glAttachShader(p, v);
// link program
glLinkProgram(p);
// check for linking errors
glGetProgramiv(p, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(p, 1000, NULL, infoLog);
std::cout << "ERROR: SHADER PROGRAM LINKING FAILED\n" << infoLog << std::endl;
}
glDeleteShader(v);
glDeleteShader(f);
if (success)
glUseProgram(p);
else {
system("pause");
exit(123);
}
program = p;
}
void setTexture() {
// Load texture image
int imageWidth, imageHeight, imageChannels;
unsigned char* imageData = stbi_load("../textures/brick.png", &imageWidth, &imageHeight, &imageChannels, 0);
if (!imageData) {
std::cout << "Failed to load texture image." << std::endl;
exit(1);
}
// Create texture and bind it
GLuint new_texture;
glGenTextures(1, &new_texture);
glBindTexture(GL_TEXTURE_2D, new_texture);
// Set texture parameters and image data
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageWidth, imageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
glGenerateMipmap(GL_TEXTURE_2D);
// Free image data
stbi_image_free(imageData);
// Bind the texture to texture unit 0
glUniform1i(glGetUniformLocation(program, "Tex"), 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, new_texture);
texture = new_texture;
}
bool loadOBJ(const char* path,
std::vector<glm::vec3>& out_vertices,
std::vector<glm::vec2>& out_uvs,
std::vector<glm::vec3>& out_normals)
{
printf("Loading OBJ file %s...\n", path);
std::vector<unsigned int> vertexIndices, uvIndices, normalIndices;
std::vector<glm::vec3> temp_vertices;
std::vector<glm::vec2> temp_uvs;
std::vector<glm::vec3> temp_normals;
FILE* file = fopen(path, "r");
if (file == NULL) {
printf("Impossible to open the file ! Are you in the right path ? See Tutorial 1 for details\n");
getchar();
return false;
}
while (1) {
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
// else : parse lineHeader
if (strcmp(lineHeader, "v") == 0)
{
glm::vec3 vertex;
fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
temp_vertices.push_back(vertex);
}
else if (strcmp(lineHeader, "vt") == 0)
{
glm::vec2 uv;
fscanf(file, "%f %f\n", &uv.x, &uv.y);
uv.y = -uv.y; // Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders.
temp_uvs.push_back(uv);
}
else if (strcmp(lineHeader, "vn") == 0)
{
glm::vec3 normal;
fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
temp_normals.push_back(normal);
}
else if (strcmp(lineHeader, "f") == 0)
{
std::string vertex1, vertex2, vertex3;
unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2]);
if (matches != 9)
{
printf("File can't be read by our simple parser :-( Try exporting with other options\n");
fclose(file);
return false;
}
vertexIndices.push_back(vertexIndex[0]);
vertexIndices.push_back(vertexIndex[1]);
vertexIndices.push_back(vertexIndex[2]);
uvIndices.push_back(uvIndex[0]);
uvIndices.push_back(uvIndex[1]);
uvIndices.push_back(uvIndex[2]);
normalIndices.push_back(normalIndex[0]);
normalIndices.push_back(normalIndex[1]);
normalIndices.push_back(normalIndex[2]);
}
else
{
// Probably a comment, eat up the rest of the line
char stupidBuffer[1000];
fgets(stupidBuffer, 1000, file);
}
}
// For each vertex of each triangle
for (unsigned int i = 0; i < vertexIndices.size(); i++)
{
// Get the indices of its attributes
unsigned int vertexIndex = vertexIndices[i];
unsigned int uvIndex = uvIndices[i];
unsigned int normalIndex = normalIndices[i];
// Get the attributes thanks to the index
glm::vec3 vertex = temp_vertices[vertexIndex - 1];
glm::vec2 uv = temp_uvs[uvIndex - 1];
glm::vec3 normal = temp_normals[normalIndex - 1];
// Put the attributes in buffers
out_vertices.push_back(vertex);
out_uvs.push_back(uv);
out_normals.push_back(normal);
}
fclose(file);
return true;
}
int main(){
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "create 3D object", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
gladLoadGL();
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
// shader
setShaders();
// Vertices coordinates
std::vector<glm::vec3> vertices;
std::vector<glm::vec2> texuvs;
std::vector<glm::vec3> normals; // Won't be used at the moment.
bool res = loadOBJ("../models/cube.obj", vertices, texuvs, normals);
if (!res) {
std::cout << "Failed to load model\n";
}
else {
std::cout << "# of vertex = " << vertices.size() << std::endl;
std::cout << "# of texuvs = " << texuvs.size() << std::endl;
std::cout << "# of normals = " << normals.size() << std::endl;
}
GLuint vao, vbo;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
// Texture
setTexture();
glEnable(GL_DEPTH_TEST);
// Main while loop
while (!glfwWindowShouldClose(window)) {
glClearColor(0.07f, 0.13f, 0.17f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//shaderProgram.Activate();
glUseProgram(program);
// Bind texture
glBindTexture(GL_TEXTURE_2D, texture);
// Bind the VAO
glBindVertexArray(vao);
// Draw primitives, number of indices, datatype of indices, index of indices
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
glfwSwapBuffers(window);
glfwPollEvents();
}
// Delete all the objects we've created
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteProgram(program);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
// vertex shader code
#version 330
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 texCoord;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
texCoord = aTexCoord;
}
// fragment shader code
#version 330
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D Tex;
void main() {
fragColor = texture(Tex, texCoord);
}Editor is loading...