OpenGL 加载透明纹理

时间:2024-03-16 08:01:20

一、编译LPNG,ZLIB

依然是以前的老一套,在此不作过多赘述
将编译好的
OpenGL 加载透明纹理
OpenGL 加载透明纹理
加到工程中

可以参考https://blog.csdn.net/liuyez123/article/details/50629906

二、读取PNG

LPNG有示例,我直接拿来用了

image

namespace image{

	class png {
	public:
		png();
		~png();

		long load(const ::std::string &path);

	public:

		int width;
		int height;
		png_byte color_type;
		png_byte bit_depth;
		std::unique_ptr<unsigned char> data;
	};
}

long image::png::load(const ::std::string &path)
{
	unsigned char header[8];    // 8 is the maximum size that can be checked
	int x, y;
	png_structp png_ptr;
	png_infop info_ptr;
	int number_of_passes;

	/* open file and test for it being a png */
	FILE *fp;
	fopen_s(&fp, path.c_str(), "rb");
	if (!fp)
		return -1;
	fread(header, 1, 8, fp);
	if (png_sig_cmp(header, 0, 8))
		return -2;

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	if (!png_ptr)
		return -3;

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
		return -4;

	if (setjmp(png_jmpbuf(png_ptr)))
		return -5;

	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, 8);

	png_read_info(png_ptr, info_ptr);

	width = png_get_image_width(png_ptr, info_ptr);
	height = png_get_image_height(png_ptr, info_ptr);
	/*获取通道数*/
	int channels = png_get_channels(png_ptr, info_ptr);
	color_type = png_get_color_type(png_ptr, info_ptr);
	bit_depth = png_get_bit_depth(png_ptr, info_ptr);

	number_of_passes = png_set_interlace_handling(png_ptr);
	png_read_update_info(png_ptr, info_ptr);

	if (setjmp(png_jmpbuf(png_ptr)))
		return -6;

	png_bytepp row_pointers;

	row_pointers = new png_bytep[ height]();
	int size = png_get_rowbytes(png_ptr, info_ptr);
	for (y = 0; y < height; y++)
		row_pointers[y] = new png_byte[size]();

	png_read_image(png_ptr, row_pointers);

	fclose(fp);

	unsigned char* p = new unsigned char[height*channels*size];

	// 拷贝到连续内存中,同时因为纹理坐标是由底到上,做一次转换
	int pos = 0;
	for (y = height -1; y >=0; --y) {
		for (x = 0; x < size; ++x) {
			p[pos++] = row_pointers[y][x];
		}
	}

	// 释放内存
	png_destroy_read_struct(&png_ptr, &info_ptr, 0);
	for (y = 0; y < height; ++y) {
		delete[] row_pointers[y];
	}
	delete[] row_pointers;

	data.reset(p);

	return 0;
}

三、添加纹理对象

要应用透明纹理,首先我们启用2D纹理
glEnable(GL_TEXTURE_2D);
然后关闭深度测试
glDepthMask(GL_FALSE);//关掉深度测试
glEnable(GL_BLEND); //开混合模式贴图
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);// 指定混合模式算法

绑定UV坐标

	// 绑定UV缓冲对象
	glGenBuffers(1, &_texcoord);
	glBindBuffer(GL_ARRAY_BUFFER, _texcoord);
	glBufferData(GL_ARRAY_BUFFER, sizeof(texcoord), texcoord, GL_STATIC_DRAW);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);

绑定纹理

	// 生成纹理对象
	glActiveTexture(GL_TEXTURE0);
	glGenTextures(1, &_tex);
	glBindTexture(GL_TEXTURE_2D, _tex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width,img.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.data.get());
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

_vertex.vert

#version 440

uniform mat4 _model_view;
uniform mat4 _projection;

uniform vec4 _light0_position;

layout (location = 0) in vec3 v;
layout (location = 1) in vec2 texcoord;
layout (location = 2) in vec4 c;
layout (location = 3) in vec3 n;

struct v2f{
	vec4 color;
	vec2 coord;
};

out v2f vert_out;

void main(){
	vert_out.color = c;
	vert_out.coord = texcoord;
	gl_Position = _projection * _model_view * vec4(v,1);
}

_fragment.frag

#version 440

uniform vec4 _light0_position;
uniform vec4 _light0_ambient;
uniform vec4 _light0_diffuse;

uniform sampler2D _sampler;

out vec4 o;

struct v2f{
	vec4 color;
	vec2 coord;
};

in v2f vert_out;

void main() {
	vec4 texcolor = texture2D(_sampler,vert_out.coord);
	o = texcolor;
}

效果如图
OpenGL 加载透明纹理