openGL初学笔记3:纹理

/* 引入相应的库 */
#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();
}

纹理

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值