【问题标题】:OpenGLES 2.0: 3D Tile Visual ArtifactsOpenGLES 2.0:3D 平铺视觉工件
【发布时间】:2011-11-06 09:50:06
【问题描述】:

我很难找到一种方法来更好地处理我的游戏引擎中 3D 平铺对象之间的接缝。只有当相机像这样以足够远的角度向下倾斜时,您才能看到它们……我不认为这是纹理问题或纹理渲染问题(但我可能是错的)。

下面是两张截图 - 第一张展示了问题,而第二张是我在 Blender 中用于瓷砖的 UV 包裹。我在 UV 中为重叠提供了空间,这样如果纹理需要在较小的 mip-map 期间过度绘制,我应该仍然很好。我正在使用以下纹理参数加载纹理:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

在我看来,3D 瓷砖的侧面略微被绘制,您特别注意到由于从该角度应用的照明角度(定向)而产生的伪影。

我可以检查任何技巧或东西来消除这种影响吗?我在“图层”中渲染,但在这些图层中基于相机距离(最远的第一)。所有这些对象都在同一层中。任何想法将不胜感激!

如果有用,这是一个使用 OpenGLES2.0 的 iPhone/iPad 项目。我很乐意提供任何代码 sn-ps - 请让我知道可能是一个好的起点。

使用顶点/像素着色器和模型顶点更新

目前,我正在使用 PowerVR 的 POD 格式来存储从 Blender 导出的模型数据(通过 Collada,然后是 PowerVR 的 Collada2Pod 转换器)。这是 GL_SHORT 顶点坐标(模型空间):

64 -64 32
64 64 32
-64 64 32
-64 -64 32
64 -64 -32
-64 -64 -32
-64 64 -32
64 64 -32
64 -64 32
64 -64 -32
64 64 -32
64 64 32
64 64 32
64 64 -32
-64 64 -32
-64 64 32
-64 64 32
-64 64 -32
-64 -64 -32
-64 -64 32
64 -64 -32
64 -64 32
-64 -64 32
-64 -64 -32

所以一切都应该是完美的,我希望。这是着色器:

attribute highp vec3  inVertex; 
attribute highp vec3  inNormal;
attribute highp vec2  inTexCoord;

uniform highp mat4  ProjectionMatrix;
uniform highp mat4  ModelviewMatrix;
uniform highp mat3  ModelviewITMatrix;
uniform highp vec3  LightColor;
uniform highp vec3  LightPosition1;
uniform highp float LightStrength1;
uniform highp float LightStrength2;
uniform highp vec3  LightPosition2;
uniform highp float Shininess;

varying mediump vec2  TexCoord;
varying lowp    vec3  DiffuseLight;
varying lowp    vec3  SpecularLight;

void main()
{
    // transform normal to eye space
    highp vec3 normal = normalize(ModelviewITMatrix * inNormal);

    // transform vertex position to eye space
    highp vec3 ecPosition = vec3(ModelviewMatrix * vec4(inVertex, 1.0));

    // initalize light intensity varyings
    DiffuseLight = vec3(0.0);
    SpecularLight = vec3(0.0);

    // Run the directional light
    PointLight(true, normal, LightPosition1, ecPosition, LightStrength1);
    PointLight(true, normal, LightPosition2, ecPosition, LightStrength2);

    // Transform position
    gl_Position = ProjectionMatrix * ModelviewMatrix * vec4(inVertex, 1.0);

    // Pass through texcoords and filter
    TexCoord = inTexCoord;
}      

【问题讨论】:

  • 可能是顶点着色器中顶点的精度问题?
  • 可能...我会检查并回复您。我想我正在使用 highp 指示符...我将实际顶点数据存储在 GL_SHORT 中以获取打包属性。这会导致问题吗?我想我在从 GL_FLOAT 切换到 GL_SHORT 之前遇到了这个问题。
  • 约翰,你能看看顶点着色器吗?我正在为我的 inVertex 使用高 vec3,并查看我从这个 3D 对象的模型文件中输入的 GL_SHORT,我看不出任何精度错误可能会发挥作用。我是否遗漏了一些明显的东西?
  • 它看起来是正确的,检查下面的答案,我也认为这是因为变量的有限精度导致计算结果被截断

标签: iphone opengl-es visual-artifacts


【解决方案1】:

我不知道你的盒子是怎么画的——但我相信这就是问题所在。在计算每个盒子的顶点时,我猜你会做这样的事情(伪代码)

整数 i,j,k; 浮动宽度 对于 i,j,k 以暗淡为单位: 上左=(i,j,k)*宽度; upper_right = (upper_left.x+width,upper_left.y,upper_left.z); lower_left = (upper_left.x, upper_left.y+width,upper_left.z); lower_right = (upper_left.x+width,upper_left.y+width,upper_left.z);

这将失败,因为您在添加时会丢失精度,因此应该共享相同位置的角实际上不会。这就是造成差距的原因。

相反,您应该这样做

对于 i,j,k: 上左=(i,j,k)*宽度; upper_right = (i+1,j,k)*宽度; lower_left = (i,j+1,k)*宽度; lower_right = (i+1,j+1,k)*宽度;

这将确保角落使用相同的坐标。

编辑

这仍然是一个精度问题。据我了解,您正在为每个块执行一次绘制调用,其中每个块唯一更改的是ModelviewMatrix。这意味着您期望这条线

position = ProjectionMatrix * ModelviewMatrix * vec4(inVertex, 1.0);

对于inVertex和ModelviewMatrix这两个不同的值会给出相同的值,这是错误的。

要解决这个问题,你可以做“假”实例化(因为 ES 不支持实例化),方法是将每个实例的值保存在制服中,并根据属性中给定的索引计算每个属性的值。

编辑 2:

好的,请暂时不要考虑“假”实例。现在,请确保坐标相同。因此,不要只为一个块提供坐标,而是为所有块提供坐标,并且只使用一个 ModelViewMatrix。那可能也会更快。

【讨论】:

  • Arne,感谢您的快速回复!目前,我正在使用 GL_SHORTS 以 PowerVR 的 .POD 文件格式存储模型顶点。我已经更新了原始帖子以显示模型中使用的顶点 - 正如您所看到的,至少在这种情况下,我不认为这是一个精度问题。我还将发布我正在使用的着色器,以防可能导致问题...
  • 我想我理解你的建议...... ModelviewMatrix 是相对于每个模型相对于相机的位置......所以如果你有两个彼此相邻的对象共享左上角和右上角的顶点(obj1 的左侧,obj2 的右侧),该顶点位于相同的世界坐标中,但其模型视图矩阵在创建此工件时略有不同。那正确吗?我想我明白什么是实例化(用独特的属性多次渲染一个对象?),但不知道如何才能做到这一点。你能提供更多细节吗?我想我差不多了!
  • 嗯 - OpenGL ES 不支持实例化,所以简单的解决方案是在设备上创建所有坐标。我提到的是绕过 GLES 不支持实例化这一事实的技巧。是一个非常特殊的东西,你保存所有的每个实例的数据(模型在世界中的位置),以及每个顶点的数据(相对位置)在制服中,并在每个上使用一个标识符vertex 来指示要使用的顶点和实例变量。目前可能不值得在您的情况下查看,因为它可能只会使您的代码复杂化。
  • Arne,现在这更有意义了......我可能昨晚因为一整天的编码而感到迷茫!我有一个忙碌的一天,但我会在今晚晚些时候玩它,然后和你一起回来。非常感谢您抽出宝贵时间提供如此有用的见解!
  • 只是一个更新,我认为这是解决方案 - 但我仍在使用它。在更新到新的 Xcode 测试版时遇到了一些其他问题 - 去看看吧!我会尽快结束并与您联系...再次感谢!
【解决方案2】:

试试这些

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

【讨论】:

  • 恐怕这些滤镜设置没有帮助 - 在较低的角度仍然有相同的视觉伪影。不过谢谢,好主意!
猜你喜欢
  • 1970-01-01
  • 2011-10-09
  • 2012-08-29
  • 2016-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多