环境
- 系统:ubuntu20.04
- opengl版本:4.6
- glfw版本:3.3
- glad版本:4.6
- cmake版本:3.16.3
- gcc版本:10.3.0
直接上代码
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)project(textureTest)
find_package(glfw3 REQUIRED)
file(GLOB project_file main.cpp glad.c stb_image.h stbimage.h)message("PROJECT_NAME:${PROJECT_NAME}")
add_executable(${PROJECT_NAME} ${project_file})target_link_libraries(${PROJECT_NAME}-lglfw-lGL-lm-lXrandr-lX11-lpthread-ldl
)
main.cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h>#include "stbimage.h"#include <iostream>const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;const char *vertexShaderSource = "#version 330 core\n""layout(location = 0) in vec3 aPos;\n""layout(location = 1) in vec3 aColor;\n""layout(location = 2) in vec2 aTexCoord;\n""out vec3 ourColor;\n""out vec2 TexCoord;\n""void main()\n""{\n"" gl_Position = vec4(aPos, 1.0);\n"" ourColor = aColor;\n"" TexCoord = aTexCoord;\n""}\0";const char *fragmentShaderSource = "#version 330 core\n""out vec4 FragColor;\n""in vec3 ourColor;\n""in vec2 TexCoord;\n""uniform sampler2D ourTexture;\n""void main()\n""{\n"" FragColor = texture(ourTexture, TexCoord);\n""}\0";int main()
{glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);std::cout << "start..." << std::endl;//创建一个窗口GLFWwindow *window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "hello Triangle", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return -1;}//顶点着色器代码unsigned int vertexShader;vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);// check for shader compile errorsint success;char infoLog[512];glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);if (!success){glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"<< infoLog << std::endl;}//片段着色器unsigned int fragmentShader;fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);// check for shader compile errorsglGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);if (!success){glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"<< infoLog << std::endl;}//着色器程序unsigned int shaderProgram;shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);// check for linking errorsglGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (!success){glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n"<< infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);//加载纹理图片int width, height, nrChannels;//生成纹理unsigned int texture;glGenTextures(1, &texture);glBindTexture(GL_TEXTURE_2D, texture);//设置纹理环绕方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);//设置边缘的颜色值float borderColor[] = {1.0f, 1.0f, 0.0f, 1.0f};glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);// //纹理过滤设置
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//多级渐远纹理设置,这里第二句设置是什么意思呢?glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);unsigned char *data = stbi_load("wall.jpg", &width, &height, &nrChannels, 0);if (data) {//绑定和纹理图片数据结合glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);} else {std::cout << "读取图片数据错误" << std::endl;}//释放图像内存stbi_image_free(data);//设置三角形纹理坐标float vertices[] = {// ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f // 左下
// -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left};unsigned int indices[] = {0, 1, 3, // first triangle1, 2, 3 // second triangle};//绑定VAO等unsigned int VAO,VBO,EBO;glGenVertexArrays(1,&VAO);glGenBuffers(1,&VBO);glGenBuffers(1,&EBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER,VBO);glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//定位各个点的关系// position attributeglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0);glEnableVertexAttribArray(0);// color attributeglVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float)));glEnableVertexAttribArray(1);// texture coord attributeglVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 * sizeof(float)));glEnableVertexAttribArray(2);// render loop// -----------while (!glfwWindowShouldClose(window)){// render// ------glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);// bind TextureglBindTexture(GL_TEXTURE_2D, texture);// render container// ourShader.use();glUseProgram(shaderProgram);glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (const GLvoid *)0);// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)// -------------------------------------------------------------------------------glfwSwapBuffers(window);glfwPollEvents();}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteBuffers(1, &EBO);glDeleteProgram(shaderProgram);glfwTerminate();return 0;
}
stbimage.h
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
总结
- 在这个例程中,使用了索引缓存对象EBO,使用了这个对象,就需要使用
glDrawElements
函数来绘制图像,如果不使用EBO,而用glDrawElements
进行绘制,则会报段错误 - 如果不使用EBO,则绘制图像则需要使用
glDrawArrays
函数来绘制图像 - 使用了EBO,则需要做如下操作来支持
//定义绘制顶点的顺序unsigned int indices[] = {0, 1, 3, // first triangle1, 2, 3 // second triangle};//内存拷贝 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//定位各个点偏移位置的关系// position attributeglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0);glEnableVertexAttribArray(0);// color attributeglVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float)));glEnableVertexAttribArray(1);// texture coord attributeglVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 * sizeof(float)));glEnableVertexAttribArray(2);//根据索引对象进行绘制
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (const GLvoid *)0);
- 如果在你的绘制区域出现全黑的框,可能是纹理图片没有正确的加载,在这里正确的顺序是:纹理的定义–读取纹理图片
- 如果出现显示的箱体是个三角形,并且另外一部分是边缘拉伸状,则可以看一下1.点定位关系是否正确
参考