OpenGL中为模型贴纹理

加载与创建纹理:引入stb_image.h库(加载纹理图片用)

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

创建纹理并绑定

	GLuint TexBufferA;
	glGenTextures(1,&TexBufferA);
	//激活纹理
	glActiveTexture(GL_TEXTURE1); 
	glBindTexture(GL_TEXTURE_2D,TexBufferA);

加载图片

	int width,height,nrChannel;
	stbi_set_flip_vertically_on_load(true);
	unsigned char* data=stbi_load("wall.jpg",&width,&height,&nrChannel,0);
	if (data)
	{
		// 生成纹理
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,data);
		//生成多级渐远纹理
		glGenerateMipmap(GL_TEXTURE_2D);
	}
	else
	{
		printf("load image fail1");
	}
	//释放图片
	stbi_image_free(data);

注意:如果导入的图没有α通道,生成要用的是GL_RGB,不然程序会崩溃
更新纹理坐标数据

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    // 左上
};

纹理坐标在0-1之间
解析纹理顶点坐标属性

	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
	glEnableVertexAttribArray(2);

layout位置属性是2,顶点属性长度是2,数据类型是float,不需要归一化,一个顶点的所有数据是8个,步长是6
顶点着色器接受纹理坐标,并将坐标输出到片元着色器

layout(location=0) in vec3 aPos;
layout(location=1) in vec3 aColor ;
layout(location=2) in vec2 aTexCoord ;
out vec4 vertexColor;
//纹理uv坐标
out vec2 TexCoord;
void main(){ 
gl_Position=vec4(aPos.x,aPos.y,aPos.z,1.0f);
vertexColor=vec4(aColor.x,aColor.y,aColor.z,1.0f);
TexCoord=aTexCoord;
}

片元着色器接受顶点数据,定义纹理采样器

#version 330 core 
in vec4 vertexColor;
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D ourTexture; 
uniform sampler2D ourFace; 
void main(){
			FragColor=texture(ourTexture,TexCoord)*texture(ourFace,TexCoord);
}

回到主函数,在绘制循环中激活绑定纹理

		//先激活再绑定
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D,TexBufferA);
		glActiveTexture(GL_TEXTURE3);
		glBindTexture(GL_TEXTURE_2D, TexBufferB);

设置采样器

		//告诉采样器属于哪个纹理单元
		glUniform1i(glGetUniformLocation(myShader->ID,"ourTexture"),1);
		glUniform1i(glGetUniformLocation(myShader->ID, "ourFace"), 3);

纹理单元数字与定义纹理缓冲时绑定的纹理单元有关
main函数全部代码:

#include<iostream>
#define GLEW_STATIC
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include "Shader.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
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    // 左上
};
unsigned int indices[] =
{
	0,1,2,
	2,3,0
};
int main()
{
	//testShader->test();
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//设置核心模式
	glfwInitHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	//创建窗口
	GLFWwindow* window = glfwCreateWindow(800, 800, "test", NULL, NULL);
	if (window == NULL)
	{
		printf("failed");
		glfwTerminate();
		return -1;
	}
	//联系上下文
	glfwMakeContextCurrent(window);
	glewExperimental = true;
	if (glewInit() != GLEW_OK)
	{
		printf("failed");
		glfwTerminate();
		return -1;
	}
	glViewport(0, 0, 800, 800);

	Shader* myShader = new Shader("vertexSource.txt", "fragmentSource.txt");

	GLuint VAO;
	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);

	GLuint VBO;
	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//写入数据
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);


	//使用索引绘制顶点
	GLuint EBO;
	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);


	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
	glEnableVertexAttribArray(2);
	//创建纹理并绑定
	GLuint TexBufferA;
	glGenTextures(1,&TexBufferA);
	glActiveTexture(GL_TEXTURE1); 
	glBindTexture(GL_TEXTURE_2D,TexBufferA);

	//加载图片
	int width,height,nrChannel;
	stbi_set_flip_vertically_on_load(true);
	unsigned char* data=stbi_load("wall.jpg",&width,&height,&nrChannel,0);
	if (data)
	{
		// 生成纹理
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,data);
		//生成多级渐远纹理
		glGenerateMipmap(GL_TEXTURE_2D);
	}
	else
	{
		printf("load image fail1");
	}
	//释放图片
	stbi_image_free(data);

	GLuint TexBufferB;
	glGenTextures(1, &TexBufferB);
	glActiveTexture(GL_TEXTURE3);
	glBindTexture(GL_TEXTURE_2D, TexBufferB);	

	unsigned char* data2 = stbi_load("awesomeface.png", &width, &height, &nrChannel, 0);
	if (data2)
	{
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
		glGenerateMipmap(GL_TEXTURE_2D);
	}
	else
	{
		printf("load image fail2");
	}
	stbi_image_free(data2);

	while (!glfwWindowShouldClose(window))
	{
		glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D,TexBufferA);
		glActiveTexture(GL_TEXTURE3);
		glBindTexture(GL_TEXTURE_2D, TexBufferB);
		glBindVertexArray(VAO);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
		myShader->use();
		//告诉采样器属于哪个纹理单元
		glUniform1i(glGetUniformLocation(myShader->ID,"ourTexture"),1);
		glUniform1i(glGetUniformLocation(myShader->ID, "ourFace"), 3);
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwDestroyWindow(window);
	glfwTerminate();
	return 0;
}

注:这处没有封装的着色器代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值