如何用OpenGL ES 2.0渲染一个透明surface
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何用OpenGL ES 2.0渲染一个透明surface相关的知识,希望对你有一定的参考价值。
如题,如何用OpenGLES2.0在surface上贴上纹理之后,整个surface具有透明效果?即:假设有两个surfaceView,v1,v2,v2挡住v1的部分透明,使之能够看到v1.求指教~~~~~~~
参考技术A 你学下opengl吧,要开blend效果,这是网上一段透明纹理的代码,没测过glGenTextures(1,&texture); //generate texture object,生成纹理对象glBindTexture(GL_TEXTURE_2D, texture); // enable ourtexture object,绑定纹理//这一陀就是设置纹理属性,我也看不懂glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);// generate thetexture imageglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,FreeImage_GetWidth(dib),FreeImage_GetHeight(dib), 0, GL_RGBA,GL_UNSIGNED_BYTE, bits); //从位图中抽取纹理到纹理对象中 参考技术B 你看这样行不,把V2的surface属性改一下,例如:1、GLSurfaceView v2= new GLSurfaceView();this.getHolder().setFormat(PixelFormat.TRANSLUCENT);2、在渲染器类OnSurfaceCreated函数中设置清屏的颜色:gl.glClearClolor(0,0,0,0);最后,在画的时候OnDrawFrame 开启混合 也就是我上面写的那几句 参考技术C 在一个Surface实现可以不?一个Surface中 贴两张贴图在OnDrawFrame()中,draw()模型前加上gl.glEnable(GL10_BLEND);//开启混合模式gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10_ONE_MINUS_SRC_ALPHA);//设置混合因子在 gouraud shading 中,啥是 T-junction 问题以及如何用 OpenGL 演示它
【中文标题】在 gouraud shading 中,啥是 T-junction 问题以及如何用 OpenGL 演示它【英文标题】:In gouraud shading, what is the T-junction issure and how to demonstrate it with OpenGL在 gouraud shading 中,什么是 T-junction 问题以及如何用 OpenGL 演示它 【发布时间】:2014-02-06 04:06:44 【问题描述】:我注意到 Gouraud 着色部分中的 here,它说“具有相邻多边形的 T-Junctions 有时会导致视觉异常。一般而言,应避免使用 T-Junctions”。
T-junction好像是下图中的三个面共享边,A点可能有不同的法向量,因为它属于不同的面。
但是当T-junction发生时会产生什么影响以及如何使用OpenGL来实现呢?我尝试为每个矩形的每个顶点设置不同的法线并在场景中放一盏灯,但是,在连接点 A 处我没有看到任何奇怪的东西。
这是我的代码:
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glNormal3f(0, 0,1);
glVertex3f(-5.0f, 5.0f, 0.0f);
glNormal3f(0, 1,1);
glVertex3f(5.0f, 5.0f, 0.0f);
glNormal3f(1, 1,1);
glVertex3f(5.0f, 0.0f, 0.0f);
glNormal3f(0, -1,1);
glVertex3f(-5.0f, 0.0f, 0.0f);
glEnd();
glColor3f(0.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glNormal3f(1, 0,1);
glVertex3f(-5.0f, 0.0f, 0.0f);
glNormal3f(1, 2,1);
glVertex3f(0.0f, 0.0f, 0.0f);
glNormal3f(0, 0,1);
glVertex3f(0.0f, -5.0f, 0.0f);
glNormal3f(0, 1, 2);
glVertex3f(-5.0f, -5.0f, 0.0f);
glEnd();
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_QUADS);
glNormal3f(1, 1, 3);
glVertex3f(0.0f, 0.0f, 0.0f);
glNormal3f(0, -2, 5);
glVertex3f(5.0f, 0.0f, 0.0f);
glNormal3f(-1, 1, 1);
glVertex3f(5.0f, -5.0f, 0.0f);
glNormal3f(1, -2, 0);
glVertex3f(0.0f, -5.0f, 0.0f);
glEnd();
点光源在 (0, 0, 10) 以及相机中。我认为下面的结果没有视觉异常。也许法线应该有点特别?
我做错了什么吗?谁能给我一些提示来实现这一点?
【问题讨论】:
【参考方案1】:T-Junction 对Gouraud shading 和一般几何形状都不利。
首先要记住,goraud shading 是一种在固定管线时代使用的光插值方法,其中光跨顶点插值,使顶点的网格细分(数量和连通性)直接影响着色。使用 t 形结会导致最终插值颜色的外观突然不连续(请记住,Gouraud 着色还有其他问题,例如采样不足)。
Gouraud 着色与 Phong 着色不同,直接使用顶点法线,请注意不要将 Phong 着色与 Phong 光照混淆,它们是不同的
请注意,您所展示的案例是一个 t 形路口,但您不会注意到任何阴影问题,因为网格不够细分,并且(似乎)您没有使用任何灯光。尝试在具有 t 形接头的球体上进行测试。
关于几何 t-junction 被认为是退化的情况。因为在那个边/多边形处,几何网格失去了一致性,你不再有两条边在它们的末端连接,并且你失去了多边形循环属性(阅读:有向边)。这通常是一个很难解决的问题,解决方案可能是对多边形进行三角剖分,以便现在正确连接 t-juction 边缘。
http://en.wikipedia.org/wiki/Gouraud_shading
【讨论】:
我不确定您所说的“镶嵌”是什么。其实我用的是灯光。画球体需要用glutSolidSphere吗? @TonyLic 镶嵌意味着有更多的多边形;你需要谷歌这个词,否则 gouraud shading 没有多大意义。另请阅读我提供的链接。 glutSolidSphere 不起作用,您需要创建一个带有 t 形接头的球体才能可视化该问题。 谢谢!我的意思是,我知道这个词,但我不知道如何在我的情况下进行更多的镶嵌。我可以在我的原始案例中添加更多矩形以使其镶嵌,因为创建 T-junk 球体有点复杂。另外,我是否需要为每个顶点使用 glNormal 来给它们不同的法线向量? @TonyLic 你说你正在使用照明,实际上如果你仔细观察你的例子,照明插值看起来不正确,我认为这是由于 t 形结问题,颜色应该是白色靠近边缘,但不一致。您可以使用 3d 程序创建一个球体并将其导入。您可以使用顶点和法线数组(也已弃用)。当前不推荐使用的方法称为顶点缓冲区对象。但对于您的简单示例可能有点过头了。【参考方案2】:您处理这种情况的次数越多,问题的核心就越清晰。举一个可靠的例子,花一些时间看它,你可能会“啊哈!”它会点击。
理论上,该问题通常被描述为这样一种情况,即 t-vert 的直接和相邻区域中的像素基于单独的,有时是不同的输入(t-vert 的法线与相邻顶点的法线)被着色)。您可以通过将 t-vert 的法线设置为与相邻顶点的法线非常不同(例如,与它们的平均值非常不同)来夸大问题作为说明。
在实践中,除了极端情况,您通常处理顶点之间法线的平滑渐变,因此问题更加微妙。因此,我以不同的方式看待问题:作为示例数据传播问题。这种情况会导致跨样本的插值不会以均匀的方式在表面上传播样本数据。在您的示例中,t-vert 光样本输入没有向上传播,仅向左/向右/向下传播。这就是 t 顶点存在问题的原因之一,它们表示网格网络中的不连续性,会导致此类问题。
您可以通过想象表面上每个法线点的光值,然后思考在给定光位置下整个面部的合成颜色是什么,您可以在脑海中形象化它。使用您的示例,但法线渐变更平滑,对于顶面,您会看到一个长的颜色线性插值。但是,对于底部的两个面,您会看到由 t 顶点法线驱动的两个颜色线性插值。根据光照角度,t 顶点法线可以拾取与相邻法线不同的光量。这将把它上面和下面的颜色插值分开,你会看到一个阴影接缝。
为了说明您的示例,我将仅使用一种颜色,调整法线以使它们形成更均匀的相对角度分布(类似于我将在下面放入的集合),然后使用不同的光线查看它位置(尤其是靠近 t 顶点的位置)。
top left normal: [-1, 1, 1]
top right normal: [1, 1, 1]
middle left normal: [-1, 0, 1]
t-vert normal: [0, 0, 1]
middle right normal: [1, 0, 1]
bottom left normal: [-1, -1, 1]
bottom middle normal: [0, -1, 1]
bottom right normal: [1, -1, 1]
因为这是一个由采样数据的不均匀传播引起的问题 - 并且传播就是插值的作用 - 顺便说一下,其他插值技术(如 Phong 着色)也会发生类似的异常情况。
【讨论】:
以上是关于如何用OpenGL ES 2.0渲染一个透明surface的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL学习随笔-- OpenGL ES 2.0渲染管线