赞
踩
/* 引入相应的库 */ #include <iostream> using namespace std; #define GLEW_STATIC #include"Shader.h" #include <GLFW/glfw3.h> #include <GL/glew.h> #include <SOIL2/stb_image.h> #include <SOIL2/SOIL2.h> int width, height; //* (样例一:木板) 编写各顶点位置 + 读取纹理 */ GLfloat vertices_1[] = { //position // color // texture coords(纹理坐标) 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 2.0f, // 右上顶点 编号0 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, // 右下顶点 编号1 -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // 左下顶点 编号2 -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f // 左上顶点 编号3 }; unsigned char* image = SOIL_load_image("T_image3.png", &width, &height, 0, SOIL_LOAD_RGBA); // 获取图片 /* 四个顶点的连接信息给出来 */ GLuint indices_1[] = { 0, 1, 3, // 序号为 0、1、3 的顶点组合成一个三角形 1, 2, 3 // 序号为 1、2、3 的顶点组合成一个三角形 }; const GLint WIDTH = 600, HEIGHT = 600; int main() { glfwInit(); GLFWwindow* window_1 = glfwCreateWindow(WIDTH, HEIGHT, "Learn OpenGL Texture test", nullptr, nullptr); int screenWidth_1, screenHeight_1; glfwGetFramebufferSize(window_1, &screenWidth_1, &screenHeight_1); cout << "screenWidth_1 = " << screenWidth_1 << ", screenHeight = " << screenHeight_1 << endl; glfwMakeContextCurrent(window_1); glewInit(); /* 将我们自己设置的着色器文本传进来 */ Shader ourShader = Shader("shader_v.txt", "shader_f.txt"); // 相对路径 /* 设置顶点缓冲对象(VBO) + 设置顶点数组对象(VAO) + 索引缓冲对象(EBO) */ GLuint VAO, VBO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_1), vertices_1, GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_1), indices_1, GL_STATIC_DRAW); /* 设置链接顶点属性 */ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // 通道 0 打开 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); // 通道 1 打开 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); glEnableVertexAttribArray(2); // 通道 2 打开 /* 生成纹理 */ GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); // 读取图片信息 glGenerateMipmap(GL_TEXTURE_2D); // 多层渐进纹理 SOIL_free_image_data(image); /* 纹理环绕方式 */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); // S 坐标 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); // T 坐标 /* 纹理过滤 */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* 纹理单元:下一节重点使用 */ ourShader.Use(); // don't forget to activate/use the shader before setting uniforms! int textureLocation = glGetUniformLocation(ourShader.Program, "ourTexture"); // 找到着色器中 uniform 属性的名为"ourTexture"的纹理的索引 glUniform1i(textureLocation, 0); // 告诉 OpenGL 的着色器采样器属于哪个纹理单元 /* draw loop 画图循环 */ while (!glfwWindowShouldClose(window_1)) { /* 视口 + 时间 */ glViewport(0, 0, screenWidth_1, screenHeight_1); glfwPollEvents(); /* 渲染 + 清除颜色缓冲 */ glClearColor(0.5f, 0.8f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); /* 生成纹理 */ glActiveTexture(GL_TEXTURE0); // 激活 0 号纹理单元。最多 16 个通道 glBindTexture(GL_TEXTURE_2D, texture); // 绑定这个纹理到当前激活的纹理目标 /* 绘制图形 */ ourShader.Use(); glBindVertexArray(VAO); // 绑定 VAO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // 绑定 EBO glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // 画两个三角形 从第0个顶点开始 一共画6次 glBindVertexArray(0); // 解绑定 VAO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // 解绑定 EBO glBindTexture(GL_TEXTURE_2D, 0); // 解绑定 纹理 /* 交换缓冲 */ glfwSwapBuffers(window_1); } /* 释放资源 */ glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glfwTerminate(); // 结束 return 0; }
片段着色器代码
#version 330 core // 3.30版本
in vec3 ourColor;
in vec2 ourTextureCoords; // 将纹理坐标引入(从顶点着色器过来的)
out vec4 FragColor; // 输出是四个浮点数构成的一个向量 RGB+aerfa
uniform sampler2D ourTexture; // 纹理对象引入(从主函数过来的)
void main()
{
// FragColor = vec4(ourColor, 1.0f);
FragColor = texture(ourTexture, ourTextureCoords); // 采样获得纹理坐标
}
顶点着色器代码
#version 330 core // 3.30版本
layout(location = 0) in vec3 position; // 位置变量的顶点属性位置值为 0
layout(location = 1) in vec3 color; // 颜色变量的顶点属性位置值为 1
layout(location = 2) in vec2 textureCoords; // 纹理坐标只有两个浮点数 (s,t), 属性位置值为 2
out vec3 ourColor;
out vec2 ourTextureCoords; // 将纹理坐标传到片元着色器
void main()
{
gl_Position = vec4(position, 1.0f); // 核心函数(位置信息赋值)
// ourColor = color;
ourTextureCoords = vec2(textureCoords.x, 1-textureCoords.y);
}
着色器类
#pragma once // 为了避免同一个头文件被包含(include)多次 #include<string> #include<fstream> #include<sstream> #include<iostream> using namespace std; #include <GL\glew.h> #include <GLFW\glfw3.h> // 我们自己的着色器 class Shader { private: unsigned int vertex, fragment; // 顶点着色器 和 片元着色器 public: unsigned int Program; // 着色器程序的ID // Constructor(着色器构造函数) Shader(const char* vertexPath, const char* fragmentPath) { // 文件读取系列的变量定义 string vertexCode; string fragmentCode; ifstream vShaderFile; ifstream fShaderFile; // 异常机制处理:保证ifstream对象可以抛出异常: vShaderFile.exceptions(ifstream::badbit); fShaderFile.exceptions(ifstream::badbit); try { // 打开文件 vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); stringstream vShaderStream, fShaderStream; // 读取文件的缓冲内容到数据流中 vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); // 关闭文件处理器 vShaderFile.close(); fShaderFile.close(); // 转换数据流到string vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch (ifstream::failure e) { // 发生异常时输出 cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << endl; } /* 将 string 类型的字符串转化为 char数组 类型 */ const char* vShaderCode = vertexCode.c_str(); const char* fShaderCode = fragmentCode.c_str(); /* 顶点着色器 */ vertex = glCreateShader(GL_VERTEX_SHADER); // 创建顶点着色器对象 glShaderSource(vertex, 1, &vShaderCode, NULL); // 将顶点着色器的内容传进来 glCompileShader(vertex); // 编译顶点着色器 int flag; // 用于判断编译是否成功 char infoLog[512]; glGetShaderiv(vertex, GL_COMPILE_STATUS, &flag); // 获取编译状态 if (!flag) { glGetShaderInfoLog(vertex, 512, NULL, infoLog); cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl; } /* 片元着色器 */ fragment = glCreateShader(GL_FRAGMENT_SHADER); // 创建片元着色器对象 glShaderSource(fragment, 1, &fShaderCode, NULL); // 将片元着色器的内容传进来 glCompileShader(fragment); // 编译顶点着色器 glGetShaderiv(fragment, GL_COMPILE_STATUS, &flag); // 获取编译状态 if (!flag) { glGetShaderInfoLog(fragment, 512, NULL, infoLog); cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl; } /* 着色器程序 */ this->Program = glCreateProgram(); glAttachShader(this->Program, vertex); glAttachShader(this->Program, fragment); glLinkProgram(this->Program); if (!flag) { glGetProgramInfoLog(this->Program, 512, NULL, infoLog); cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl; } // 删除着色器,它们已经链接到我们的程序中了,已经不再需要了 glDeleteShader(vertex); glDeleteShader(fragment); } // Deconstructor(析构函数) ~Shader() { glDetachShader(this->Program, vertex); glDetachShader(this->Program, fragment); glDeleteShader(vertex); glDeleteShader(fragment); glDeleteProgram(this->Program); } void Use() { glUseProgram(this->Program); } };
纹理坐标是作为0.0到1.0范围内的浮点值指定的。纹理坐标命名为s,t,r,q,支持从一维到三位的纹理坐标,并且可以选择一种对坐标进行缩放的方法。
纹理参数通过glTexParameter函数的变量来进行设置。该函数第一个参数指定这些参数将要应用在哪个纹理模式上,第二个参数指定了需要设置哪个纹理参数,最后一个参数用于设置特定的纹理参数的值。
纹理过滤是根据一个拉伸或收缩的纹理贴图计算颜色片段的过程。
不使用Shader.h时的代码
#include <iostream> #include <GL/glew.h> #include <GLFW/glfw3.h> #include <SOIL2/SOIL2.h> #include <SOIL2/stb_image.h> #include <sstream> #include <string> #include <fstream> //顶点数组 GLfloat vertex[] = { 0.5f,0.5f,0.0f, 0.0f,0.0f,0.0f, 2.0f,2.0f, 0.5f,-0.5f,0.0f, 0.0f,0.0f,0.0f, 2.0f,0.0f, -0.5f,-0.5f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f, -0.5f,0.5f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.2f }; int height, width; //获取图片 unsigned char* image = SOIL_load_image("T_image3.png", &width, &height, 0, SOIL_LOAD_RGBA); //索引数组 unsigned int index[] = { 0,1,3, 1,2,3 }; //创建着色器 unsigned int createshader(std::string vertexshaderPath,std::string flagshaderPath) { //着色器代码 std::string vertexcode; std::string flagcode; //着色器代码流 std::stringstream vertexstream; std::stringstream flagstream; //着色器文件 std::ifstream vertexfile; std::ifstream flagfile; //打开着色器文件 vertexfile.open(vertexshaderPath); flagfile.open(flagshaderPath); //读取文件中流 vertexstream << vertexfile.rdbuf(); flagstream << flagfile.rdbuf(); //获取着色器代码 vertexcode = vertexstream.str(); flagcode = flagstream.str(); //转化为数组型 const char* vertexch = vertexcode.c_str(); const char* flagch = flagcode.c_str(); //编译着色器 unsigned int vertex, flag; vertex = glCreateShader(GL_VERTEX_SHADER); flag = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(vertex,1,&vertexch,NULL); glShaderSource(flag,1,&flagch,NULL); glCompileShader(vertex); glCompileShader(flag); unsigned int program; program=glCreateProgram(); glAttachShader(program,vertex); glAttachShader(program,flag); glLinkProgram(program); return program; } int main() { glfwInit(); GLFWwindow* window = glfwCreateWindow(600,600,"OPENGL2",NULL,NULL); int screenWidth, screenHeight; glfwGetFramebufferSize(window, &screenWidth, &screenHeight); if (!window) { glfwTerminate(); } glfwMakeContextCurrent(window); //glfwSwapInterval(1); glewInit(); //缓冲区 unsigned int VAO, VBO, EBO; glGenBuffers(1,&VAO); glGenBuffers(1,&VBO); glGenBuffers(1,&EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER,VBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO); glBufferData(GL_ARRAY_BUFFER,sizeof(vertex),vertex,GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(index),index,GL_STATIC_DRAW); //连接顶点 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat))); glEnableVertexAttribArray(2); unsigned int shader; shader = createshader("shader_v.txt", "shader_f.txt"); //纹理 GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); glGenerateMipmap(GL_TEXTURE_2D); SOIL_free_image_data(image); //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //环绕方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //过滤 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glUseProgram(shader); int textureLocation = glGetUniformLocation(shader, "ourTexture"); glUniform1i(textureLocation, 0); while (!glfwWindowShouldClose(window)) { glClearColor(0.5f, 0.8f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); //生成纹理 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //生成图形 glUseProgram(shader); glBindVertexArray(VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glfwDestroyWindow(window); glfwTerminate(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。