Opengl 渲染透明纹理

Opengl 渲染透明纹理,opengl,textures,alphablending,Opengl,Textures,Alphablending,我有一个纹理,它有一些部分是透明的,我想应用在一个对象上,它的面是一些不透明的材料(或者颜色,如果它更简单的话),但是最终的对象是透明的。我希望最终的对象是完全不透明的 这是我的密码: 首先,我设置了材质: glDisable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT); glColor4f(0.00, 0.00, 0.00, 1.00); glColorMaterial(GL_FR

我有一个纹理,它有一些部分是透明的,我想应用在一个对象上,它的面是一些不透明的材料(或者颜色,如果它更简单的话),但是最终的对象是透明的。我希望最终的对象是完全不透明的

这是我的密码:

首先,我设置了材质:

   glDisable(GL_COLOR_MATERIAL);
   glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
   glColor4f(0.00, 0.00, 0.00, 1.00);
   glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
   glColor4f(0.80, 0.80, 0.80, 1.00);
   glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
   glColor4f(0.01, 0.01, 0.01, 1.00);
   glEnable(GL_COLOR_MATERIAL);
然后我设置VBOs

   glBindTexture(GL_TEXTURE_2D, object->texture);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

   glBindBuffer(GL_ARRAY_BUFFER, object->object);
   glVertexPointer(3, GL_FLOAT, sizeof(Vertex), ver_offset);
   glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), tex_offset);
   glNormalPointer(GL_FLOAT, sizeof(Vertex), nor_offset);
最后我画了这个物体

   glEnable(GL_BLEND);
   glDisable(GL_DEPTH_TEST);

   glDisable(GL_TEXTURE_2D);
   glBlendFunc(GL_ONE, GL_ZERO);
   glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

   glEnable(GL_TEXTURE_2D);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

   glDisableClientState(GL_VERTEX_ARRAY);
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);

   glDisable(GL_BLEND); 
   glEnable(GL_DEPTH_TEST);
我尝试将不同的参数传递给glBlendFunc(),但没有成功。我已经在这里上传了源代码:

更新 我得到了,但是我想要(或者没有纹理)


第二张和第三张图片是用。我研究了源代码,但由于我对OpenGL的知识有限,我不太了解。

使用像素着色器会简单得多。否则,我认为您需要多次渲染或多个纹理。
您可以在此处找到全面的详细信息:

如果您试图将两个纹理应用于对象,您确实希望设置两个纹理并使用多纹理来实现此外观。您的方法是绘制两次几何体,这是对性能的巨大浪费


多重纹理将仅从两个纹理单元采样,同时仅绘制一次几何体。您可以使用着色器来实现这一点(实际上应该这样做),或者仍然可以使用固定函数管道(请参见:)

AFAIK混合函数采用片段颜色(与纹理颜色相反)。因此,如果再次使用混合绘制对象,三角形将变为透明


您想要完成的事情可以使用多文本处理来完成这只是一个猜测,因为您没有提供任何实际问题的屏幕截图,但为什么要禁用深度测试?当然,您希望在第一次通过时使用标准的GL_LESS启用深度测试,然后在第二次通过时使用GL_EQUAL启用深度测试

编辑:


尝试禁用混合并绘制单遍,将纹理功能设置为
GL\u贴花
,而不是
GL\u调制
。这将基于纹理的alpha通道在顶点颜色和纹理颜色之间混合,但将alpha通道设置为顶点颜色


请注意,这将忽略应用于纹理不透明的任何顶点颜色的任何照明,但根据您的描述,这听起来像是预期效果。

您试图实现什么?一个有一些实心像素的透明对象?或者是一个带有一些透明纹理的实体对象显示下面的纯色?后者:一个带有一些透明纹理的实体对象显示下面的纯色?感谢更新。。。并按照我的建议整理好你的Z缓冲区。更新了我的答案,加入了Z缓冲修复。像素着色器比多重纹理更简单?当然!这取决于你的目标平台和引擎,但如果你想实现像玻璃或切割这样的下降透明度效果,使用简单的像素着色器比使用固定功能管线容易得多。我不同意所有事情都应该使用着色器来完成。但是你以19秒的优势击败了我;-)OpenGL3.X已经完全淘汰了FFP的一部分,着色器是未来的发展方向。我不想改变纹理。我想要一种材质和一种纹理(比如灰色金属(材质)上的绘画(纹理))。我同意绘制两次几何体是浪费时间,并且可能存在问题,因此我正在寻找替代方法。您可能仍然希望在此处使用两种纹理-将第一种纹理设置为非常小的纹理,该纹理的颜色适合灰色材质,并将第二种纹理设置为细节纹理。这可能看起来很尴尬,但在现代硬件上读取两个纹理的速度非常快,而渲染几何体和切换渲染状态的速度要慢得多。如果您需要动态着色,则使用颜色填充2x2纹理非常快,并将为您提供相同的净效果。
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);  // ie do not disable
glDepthFunc( GL_LESS );   // only pass polys have a z value less than ones already in the z-buffer (ie are in front of any previous pixels)

glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE, GL_ZERO);
glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

// for the second pass we only want to blend pixels where they occupy the same position 
// as in the previous pass.  Therefore set to equal and only pixels that match the
// previous pass will be blended together.
glDepthFunc( GL_EQUAL );

glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDrawArrays(GL_TRIANGLES, 0, object->num_faces);

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glDisable(GL_BLEND);