OpenGL 加载透明纹理
一、编译LPNG,ZLIB
依然是以前的老一套,在此不作过多赘述
将编译好的
加到工程中
可以参考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;
}
效果如图