OpenGLES 2.0: визуальные артефакты трехмерных плиток - PullRequest
3 голосов
/ 30 августа 2011

Мне ужасно трудно придумать, как лучше справляться со швами между трехмерными объектами плитки в моем игровом движке.Вы видите их, только когда камера наклонена под достаточно большим углом, как этот ... Я не верю, что это проблема текстуры или проблема рендеринга текстуры (но я могу ошибаться).

Ниже приведены два снимка экрана: первый демонстрирует проблему, а второй - УФ-обертывание, которое я использую для плиток в Blender.Я предоставляю место в UV для перекрытия, так что, если текстуру нужно перерисовать во время меньших мип-карт, я все равно буду в порядке.Я загружаю текстуры со следующими параметрами:

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-плиток немного прорисованы, и вы особенно заметили артефакт из-за угла освещения (направленного), которыйприменяется под этим углом.

Есть ли уловки или вещи, которые я могу проверить, чтобы устранить этот эффект?Я выполняю рендеринг в «слоях», но внутри этих слоев на основе расстояния до камеры (дальше всего).Все эти объекты находятся в одном слое.Любые идеи будут с благодарностью!

Если это полезно, это проект для iPhone / iPad с использованием OpenGLES2.0.Я рад предоставить любые фрагменты кода - просто дайте мне знать, с чего можно начать.

Screenshot from engine demonstrating seams between tiles at low angles

UVs from Blender

ОБНОВЛЕНИЕ С VERTEX / PIXEL SHADER & VERTICES МОДЕЛИ

В настоящее время я использую формат POD PowerVR для хранения данных модели, экспортированных из Blender (через Collada, а затем конвертер Collada2Pod от PowerVR).Вот координаты вершины 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 6432
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 ]

2 голосов
/ 30 августа 2011

Я не знаю, как нарисованы ваши коробки - но я считаю, что это проблема.При вычислении вершин для каждого блока я предполагаю, что вы делаете что-то вроде этого (псевдокод)

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;

Это гарантирует, что углы будут использовать те же координаты.

РЕДАКТИРОВАТЬ

Это все еще проблема точности.Из того, что я понимаю, вы выполняете вызов на каждый блок, где единственное, что меняется на блок, это ModelviewMatrix.Это означает, что вы ожидаете, что эта строка

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

даст одно и то же значение для двух разных значений inVertex и ModelviewMatrix, чтоневерно.

Чтобы решить эту проблему, вы можете сделать «фальшивое» создание экземпляров (поскольку ES не поддерживает создание экземпляров), сохраняя значения для каждого экземпляра в униформе и вычисляя значения для каждого атрибута из индекса, указанного в атрибуте..

Редактировать 2:

Хорошо, пожалуйста, пока не думайте о «поддельных» экземплярах.Теперь, пожалуйста, убедитесь, что координаты совпадают.Поэтому вместо предоставления координат только для одного блока укажите их для всех блоков и используйте только один ModelViewMatrix.Это, вероятно, будет быстрее.

1 голос
/ 31 августа 2011

попробуйте эти

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