Opengl - Странный артефакт с битовым количеством вершин - PullRequest
0 голосов
/ 19 октября 2019

Я получаю странные артефакты, когда рисую свой сгенерированный объект множеством полигонов. enter image description here enter image description here Если я, например, использую меньше полигонов, все в порядке. enter image description here Если я использую слишком много полигонов, вы все равно можете видеть эти артефакты, но они слишком малы, чтобы обращать на них внимание. enter image description here Я не могу использовать слишком много полигонов, как на третьем изображении, и не могу найти причину такого странного поведения. Мой вершинный шейдер:

attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec2 a_texCoord0;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
varying vec3 fragPos;
varying vec3 normal;
varying vec2 texcoord0;

void main()
{
    gl_Position = projection * view * model * vec4(a_position, 1.0);
    fragPos = vec3(model * vec4(a_position, 1.0));
    normal = a_normal;
    texcoord0 = a_texCoord0;
}

Код моего фрагментного шейдера:

#ifdef GL_ES
precision mediump float;
#endif
varying vec3 normal;
varying vec2 texcoord0;
varying vec3 fragPos;

uniform vec3 lightPos;
uniform vec3 lightColor;

void main()
{

    vec3 color = vec3(1.0, 0, 0);
    // Ambient
    float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * lightColor;

    // Diffuse
    vec3 norm = normalize(normal);
    vec3 lightDir = normalize(lightPos - fragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;

    vec3 result = (ambient + diffuse) * color;
    gl_FragColor = vec4(result, 1.0);
}

Вот часть, как я вычисляю нормали:

public class MeshData {

    private final static int COMPONENTS_NUM = 8;

    public Vector2[] uv = new Vector2[0];
    private Vector3[] vertices = new Vector3[0];
    public short[] triangles = new short[0];
    public Normal[] normals;

    public void recalculateNormals(){
        for(int i = 0; i < triangles.length; i+=3){
            computeFaceNormal(triangles[i], triangles[i + 1], triangles[i + 2]);
        }
    }

    public static class Normal{
        private Vector3 normal = new Vector3();

        public Vector3 getUnitNormal() {
            return normal.cpy().nor();
        }

        public void addNormal(float x, float y, float z){
            normal.add(x, y, z);
        }
    }

    private void computeFaceNormal(int i1, int i2, int i3) {
        Vector3 vertex1 = vertices[i1];
        Vector3 vertex2 = vertices[i2];
        Vector3 vertex3 = vertices[i3];

        //normal
        float EPSILON = 0.000001f;
        // default return value (0, 0, 0)
        float normalX = 0, normalY = 0, normalZ = 0;
        // find 2 edge vectors: v1-v2, v1-v3
        float ex1 = vertex2.x - vertex1.x;
        float ey1 = vertex2.y - vertex1.y;
        float ez1 = vertex2.z - vertex1.z;
        float ex2 = vertex3.x - vertex1.x;
        float ey2 = vertex3.y - vertex1.y;
        float ez2 = vertex3.z - vertex1.z;
        // cross product: e1 x e2
        float nx, ny, nz;
        nx = ey1 * ez2 - ez1 * ey2;
        ny = ez1 * ex2 - ex1 * ez2;
        nz = ex1 * ey2 - ey1 * ex2;
        // normalize only if the length is > 0
        float length = (float) Math.sqrt(nx * nx + ny * ny + nz * nz);
        if (length > EPSILON) {
            // normalize
            float lengthInv = 1.0f / length;
            normalX = nx * lengthInv;
            normalY = ny * lengthInv;
            normalZ = nz * lengthInv;
        }
        normals[i1].addNormal(normalX, normalY, normalZ);
        normals[i2].addNormal(normalX, normalY, normalZ);
        normals[i3].addNormal(normalX, normalY, normalZ);
    }
}

Я использую класс Normal длясглаживать нормали. Таким образом, если несколько полигонов используют одну вершину, нормали этих полигонов будут суммироваться и затем нормализованы для этой вершины.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...