opengl-第六章:加入纹理Texture和纹理数据TextureData

新版本的QKEngine特性介绍

在新版本的引擎里面,我们进行了架构上的优化,目前引擎需要绘制的数据包括纹理数 
据,Shader程序,还有Buffer,我们统一继承自Element,然后统一在Window的循环调
用里面进行for call.

测试代码:

#include <BaseWindow.h>
#include <Shader.h>
#include <SimpleData.h>
#include <TextureData.h>
#include <Texture.h>
int main(int argc, char *argv[])
{
          
   
	BaseWindow window;

	Shader shader("vertex","fragment");
	SimpleData sd("test");
	SimpleData sd2("test2");
	TextureData sd3("test");
	Texture tt("pp.jpg",500,500);

	window.addElement(make_shared<Texture>(tt));
	window.addElement(make_shared<TextureData>(sd3));
	window.addElement(make_shared<Shader>(shader));
	
	window.run();
	return 0;
}

系统架构图

测试结果

新的数据文件.dtexture

现在,我们产生了新的数据文件.dtexture,该文件主要服务于EBO对象,并支持
注释#,你可以直接通过#将该行或者该行之后的数据注释掉,在引擎处理里面
将会忽视掉这些数据

纹理的绘制机制

如果要绘制纹理,需要做几个方面的准备

新的数据结构

绑定EBO数据

注意,当我们用EBO进行绘制时需要制定VAO,VBO,然后才能绑定EBO
glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);

	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, vLen * 4, this->data, GL_STATIC_DRAW);
	
	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, iLen * 4, 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);

绘制数据

glBindVertexArray(VAO);
	glDrawElements(GL_TRIANGLES, iLen, GL_UNSIGNED_INT, 0);

纹理的绑定

绑定到ID

这一步相当于将纹理数据绑定给ID
string bufName = getResourcesFolder() + "Texture\" + vName;
	glGenTextures(1, &ID);
	glBindTexture(GL_TEXTURE_2D, ID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	int w,h,nrChannels;
	unsigned char *data = stbi_load(bufName.c_str(), &w, &h, &nrChannels, 0);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	if (data)
	{
          
   
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
		glGenerateMipmap(GL_TEXTURE_2D);
	}
	else
	{
          
   
		std::cout << "Failed to load texture" << std::endl;
	}
	stbi_image_free(data);

使用

opengl是一个大型状态机,这个时候我们直接在画这个图之前,将当前的纹理状态设置为
该ID就可以了
glBindTexture(GL_TEXTURE_2D, ID);

Shader的设置

在顶点着色器获取CPU压进去的纹理坐标

将纹理坐标从顶点着色器传给片元着色器

在片元着色器接收这个纹理坐标

在片元着色器捕捉当前opengl状态机上的纹理状态

完成纹理状态->纹理坐标的映射

经验分享 程序员 微信小程序 职场和发展