OpenGLES 2.0:3D平铺视觉工件

时间:2011-08-29 22:59:14

标签: iphone opengl-es visual-artifacts

我正在寻找一种方法来更好地处理游戏引擎中3D图块对象之间的接缝。你只能在相机以这么远的角度向下倾斜时看到它们......我不相信它是纹理问题或纹理渲染问题(但我可能是错的)。

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

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项目。我很乐意提供任何代码片段 - 让我知道什么可能是一个好的开始。

Screenshot from engine demonstrating seams between tiles at low angles

UVs from Blender

使用VERTEX / PIXEL SHADER更新&模特兽医

目前,我正在使用PowerVR的POD格式存储从Blender导出的模型数据(通过PowerVR通过Collada然后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;
}      

2 个答案:

答案 0 :(得分:2)

我不知道你的盒子是如何绘制的 - 但我相信这是问题所在。当计算每个盒子的顶点时,我猜你会做这样的事情(伪代码)

int i,j,k;
float widht

for i,j,k in dims: 
  upper_left = (i,j,k)*width;
  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);

这会失败,因为你在添加时会失去精确度,所以应该共享相同位置的角实际上不会。这就是造成差距的原因。

相反,你应该做这样的事情

for i,j,k: 
  upper_left = (i,j,k)*width;
  upper_right = (i+1,j,k)*width;
  lower_left = (i,j+1,k)*width;
  lower_right = (i+1,j+1,k)*width;

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

修改

这仍然是一个精确的问题。根据我的理解,你每个块都在做一个drawcall,其中每个块唯一改变的是ModelviewMatrix。这意味着你期待这一行

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

将为inVertex和ModelviewMatrix的两个不同值提供相同的值,这是错误的。

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

编辑2:

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

答案 1 :(得分:1)

试试这些

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);