-
运行环境我是直接跟着learn opengl里面的教程搞了,cmake编译一下,用VS2019(2017之类的同理)。在绘制三角形教程的基础上,主要注意修改一下顶点渲染器和片段渲染器里面的变量。
-
shader.cpp等不用动,这一部分是用来编译渲染器代码的。
-
给出需要修改的代码,在代码中给出注释进行对应学习也不错哈哈
1.主程序
main.cpp
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
using namespace glm;
#include <common/shader.hpp>
// 需要下载这个图像加载库!
#define STB_IMAGE_IMPLEMENTATION
#include "common/stb_image.h"
int main( void )
{
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow( 1024, 768, "Tutorial 02 - Red triangle", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );
// 应用纹理
GLfloat 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 // 左上
};
// 索引 这里要学习一下EBO方面的内容
unsigned int indices[] = {
0, 1, 3, // 第一个三角形
1, 2, 3 // 第二个三角形
};
unsigned int VBO, VAO, 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);
// 属性
// 顶点
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(0 * sizeof(GLfloat)));
glEnableVertexAttribArray(0);
// 颜色
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
// 纹理坐标
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0); // Unbind VAO
// 生成纹理
// 输入生成纹理的数量,然后把它们储存在第二个参数的GLuint数组中
//(我们的例子中只是一个单独的GLuint)
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);// 绑定它,让之后任何的纹理指令都可以配置当前绑定的纹理
// 纹理环绕方式 有默认的行为
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
// 纹理过滤
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);
// 加载图片
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);
// 一定要注意路径!否则绘制出来是黑色,但运行不会给出报错
unsigned char *data = stbi_load("C:/Users/Administrator/Desktop/container.jpg", &width, &height, &nrChannels, 0);
// 手动进行加载检测,如果没什么东西就打印提示
if (data) {
std::cout << "load pic success..." << std::endl;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "load error, check your pic_path..." << std::endl;
}
stbi_image_free(data);
glBindTexture(GL_TEXTURE_2D, 0);
do{
// Clear the screen
glClear( GL_COLOR_BUFFER_BIT );
// 绑定纹理坐标和纹理单元
// 它会自动把纹理赋值给片段着色器的采样器
glBindTexture(GL_TEXTURE_2D, texture);
// Use our shader
glUseProgram(programID);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
// Draw the triangle !
//glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle
//glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
// Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
// Cleanup VBO
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteVertexArrays(1, &VAO);
glDeleteProgram(programID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}
2.顶点渲染器
#version 330 core
// 这里的location对应的属性里面的第一个数,对应好即可将变量关联过来
// Input vertex data, different for all executions of this shader.
layout (location = 0) in vec3 vertexPosition_modelspace;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main(){
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
ourColor = color;
TexCoord = texCoord;
}
3.片段渲染器
#version 330 core
in vec3 ourColor;
in vec2 TexCoord;
// Ouput data
out vec4 color;
//out vec4 FragColor;
// 把纹理对象传给片段着色器
uniform sampler2D ourTexture;
void main()
{
// Output color = red
color = texture(ourTexture, TexCoord);
//FragColor = texture(ourTexture, TexCoord);
}
-
效果
-
避坑:
- 加载图片要把路径写全,不然是黑色的,后来我加上检查才发现过来的是空指针,耽误了半晚上。
- 待办
- 立体物体的贴图
- 探索位姿估计中训练数据的采样方式,设置虚拟相机进行数据渲染
参考
1.Docs » 入门 » 纹理
2.OpenGL之纹理贴图(Texture)
2020.10.05
每天看世界都还是美丽的,那晚上为什么还是会觉得寒冷饥饿呢…