Opengl 使用顶点缓冲区对象渲染的四边形纹理仅为半透明
我正在将一些代码从OpenGL1.3转换为OpenGLES1.1。这是一个2D游戏,所以主要归结为在四边形上渲染纹理。OpenGL ES中没有即时模式,所以我不得不使用顶点缓冲区对象 但似乎组成每个四边形的两个三角形中只有一个处理透明度。以下是一个屏幕截图: 下面是我现在渲染纹理四边形的方式,这会导致:Opengl 使用顶点缓冲区对象渲染的四边形纹理仅为半透明,opengl,opengl-es,textures,vbo,opengl-es-1.1,Opengl,Opengl Es,Textures,Vbo,Opengl Es 1.1,我正在将一些代码从OpenGL1.3转换为OpenGLES1.1。这是一个2D游戏,所以主要归结为在四边形上渲染纹理。OpenGL ES中没有即时模式,所以我不得不使用顶点缓冲区对象 但似乎组成每个四边形的两个三角形中只有一个处理透明度。以下是一个屏幕截图: 下面是我现在渲染纹理四边形的方式,这会导致: glBindTexture2D(GL_TEXTURE_2D, id); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(G
glBindTexture2D(GL_TEXTURE_2D, id);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
const GLfloat texture_coordinates[] = {0, 0,
0, 1,
1, 1,
1, 0};
glTexCoordPointer(2, GL_FLOAT, 0, texture_coordinates);
const GLfloat vertices[] = {0, 0,
0, height,
width, height,
width, 0};
glVertexPointer(2, GL_FLOAT, 0, vertices);
const GLubyte indices[] = {0, 1, 2,
0, 2, 3};
glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, indices);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
下面是我如何使用即时模式渲染纹理四边形,效果很好:
glBindTexture2D(GL_TEXTURE_2D, id);
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex2i(0, 0);
glTexCoord2i(1, 0);
glVertex2i(width, 0);
glTexCoord2i(1, 1);
glVertex2i(width, height);
glTexCoord2i(0, 1);
glVertex2i(0, height);
glEnd();
下面是重现该问题的示例程序
您可以在Linux上编译它,如下所示:
g++ `pkg-config --cflags --libs sdl gl libpng` reproduce.cpp
clang++ -framework OpenGL `pkg-config --cflags --libs sdl libpng` reproduce.cpp
在Mac OS X上,如下所示:
g++ `pkg-config --cflags --libs sdl gl libpng` reproduce.cpp
clang++ -framework OpenGL `pkg-config --cflags --libs sdl libpng` reproduce.cpp
这是一个512x256透明PNG图像,可以另存为“transparent.PNG”:
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义使用VBO 1
结构Pixmap{
整数宽度;
内部高度;
常量无符号字符*数据;
盂型;
};
Pixmap加载\u png(常量标准::字符串和路径)
{
FILE*const FILE=fopen(path.c_str(),“rb”);
如果(!文件)
抛出std::runtime_错误(“无法打开”+路径);
png_字节头[8];
fread(头,1,8,文件);
const bool是_png=!png_sig_cmp(头,0,8);
如果(!is_png)
抛出std::runtime_错误(路径+“不是PNG”);
png_structp png=png_create_read_struct(png_LIBPNG_VER_STRING,
空,空,空);
如果(!png)
抛出std::runtime_错误(“未能创建png结构”);
png\u infop info=png\u创建\u信息结构(png);
如果(!info){
png\u destroy\u read\u struct(&png,(png\u infopp)NULL,(png\u infopp)NULL);
抛出std::runtime_错误(“未能创建png信息结构”);
}
png\u infop info\u end=png\u创建信息结构(png);
如果(!info_end){
png\u destroy\u read\u struct(&png,&info,(png\u infopp)NULL);
抛出std::runtime_错误(“未能创建png信息结构”);
}
if(setjmp(png_jmpbuf(png))){
png\u destroy\u read\u struct(&png,&info,&info\u end);
抛出std::runtime_错误(“来自libpng的错误”);
}
png_init_io(png,文件);
png_set_sig_字节(png,8);
png_read_info(png,info);
整数位深度;
int色_型;
png_uint_32图像宽度、图像高度;
png获取IHDR(png、信息、图像宽度、图像高度和位深度、,
&颜色类型,空,空,空);
png_读取_更新_信息(png,信息);
盂型;
开关(彩色){
案例PNG\U颜色\U类型\U RGBA:
格式=GL_RGBA;
打破
案例PNG\U颜色\U类型\U RGB:
格式=GL_RGB;
打破
违约:
png\u destroy\u read\u struct(&png,&info,&info\u end);
std::ostringstream消息流;
message_stream看到你在四元网格中使用带简单三角形条带的索引绘图,我不禁想知道,事实上这是你的问题。你的索引数组看起来像是要绘制两个带索引的三角形,而不是一个三角形条带。因此,你绘制了一个带6个顶点的三角形条带,从而绘制了4个三角形,这意味着需要额外的三角形包裹不知何故,在你的另外两个后面,会导致双重绘制,然后导致较暗的部分
因此,最简单的解决方案是将GL_三角形条带
更改为GL_三角形
,但可能会对顶点/索引重新排序,否则将按顺时针顺序绘制三角形,而1.3四元示例使用逆时针顺序(这可能与您的情况无关,但这首先是错误的方法,永远不要忽略您的订单)
但是你知道吗,这是两个三角形的三角形条带,只需要4个顶点。因此根本不需要任何索引数组,只需使用好的oldglDrawArrays
并按顺序绘制顶点。但要对它们重新排序(三角形条带使用之字形图案,所以从左到右,从上到下排列):