2017-01-06 6 views
0

Я попытался сделать что-то, что работает с нормалями от лиц, я не знаю, работает ли оно, и я получаю плавное затенение на моей модели.LWJGL на лицевое освещение

Кажется, что он отлично работает как квадроцикл, но когда я попробовал куб, он отображал только 1 квад сверху, который становится случайным, гладким, а все остальное черным. Если я выключу освещение, он отображает только 1 квад, который находится наверху.

Класс Модель:

public class Model { 
private int vbo, ibo, vao, tbo, nbo; 
private int count = 0; 

private float[] normal; 

private Matrix4f modelMatrix; 
private Vector3f position, rotation; 

private Texture texture; 
private boolean hasTexture = false; 

private String matrixName; 

public Model(float[] vertices, String matrixName, int[] ... indices) { 
    if (!initialized) { 
     log.err("JORL not initialized", "Run 'init()' at the start of your program"); 
     System.exit(1); 
    } 

    this.matrixName = matrixName; 

    vao = glGenVertexArrays(); 
    vbo = glGenBuffers(); 
    ibo = glGenBuffers(); 
    nbo = glGenBuffers(); 

    for (int[] face : indices) 
     count += face.length; 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 
    for (int[] face : indices) 
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, put(face), GL_STATIC_DRAW); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 

    glBindVertexArray(vao); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, put(vertices), GL_STATIC_DRAW); 
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 

    normal = new float[count]; 
    int current = 0; 
    for (int[] face : indices) { 
     Vector3f p1 = new Vector3f(vertices[face[0] * 3], vertices[face[0] * 3 + 1], vertices[face[0] * 3 + 2]); 
     Vector3f p2 = new Vector3f(vertices[face[1] * 3], vertices[face[1] * 3 + 1], vertices[face[1] * 3 + 2]); 
     Vector3f p3 = new Vector3f(vertices[face[2] * 3], vertices[face[2] * 3 + 1], vertices[face[2] * 3 + 2]); 

     log.info(p1.toString()); 
     log.info(p2.toString()); 
     log.info(p3.toString()); 

     Vector3f U = p2; 
     Vector3f V = p3; 
     U.sub(p1); 
     V.sub(p1); 

     normal[current * 3] = (U.y * V.z) - (U.z * V.y); 
     normal[current * 3 + 1] = (U.z * V.x) - (U.x * V.z); 
     normal[current * 3 + 2] = (U.x * V.y) - (U.y * V.x); 

     System.out.println(normal[current * 3]); 
     System.out.println(normal[current * 3 + 1]); 
     System.out.println(normal[current * 3 + 2]); 


     current++; 
    } 

    glBindVertexArray(vao); 
    glBindBuffer(GL_ARRAY_BUFFER, nbo); 
    glBufferData(GL_ARRAY_BUFFER, put(normal), GL_STATIC_DRAW); 
    glVertexAttribPointer(2, 3, GL_FLOAT, false, 0, 0); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 

    modelMatrix = new Matrix4f(); 
    position = new Vector3f(0, 0, 0); 
    rotation = new Vector3f(0, 0, 0); 
} 

public void setTexture(ShaderProgram shader, Texture texture, float[] coords) { 
    this.texture = texture; 
    hasTexture = true; 
    shader.bind(); 
    shader.editUniform(1, "has_texture"); 
    shader.editUniform(texture.getSampler(), "tex"); 
    shader.bind(); 

    tbo = glGenBuffers(); 
    glBindVertexArray(vao); 
    glBindBuffer(GL_ARRAY_BUFFER, tbo); 
    glBufferData(GL_ARRAY_BUFFER, put(coords), GL_STATIC_DRAW); 
    glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 
} 

private FloatBuffer put(float[] data) { 
    FloatBuffer pData = BufferUtils.createFloatBuffer(data.length); 
    pData.put(data).flip(); 
    return pData; 
} 

private IntBuffer put(int[] data) { 
    IntBuffer pData = BufferUtils.createIntBuffer(data.length); 
    pData.put(data).flip(); 
    return pData; 
} 

public void increaseX(float increase) { position.x += increase; } 
public void increaseY(float increase) { position.y += increase; } 
public void increaseZ(float increase) { position.z += increase; } 

public void increaseRotX(float increase) { rotation.x += increase; } 
public void increaseRotY(float increase) { rotation.y += increase; } 
public void increaseRotZ(float increase) { rotation.z += increase; } 

public void render(ShaderProgram shader) { 
    modelMatrix.identity(); 

    modelMatrix.translate(position); 
    modelMatrix.rotateX((float) Math.toRadians(rotation.x)); 
    modelMatrix.rotateY((float) Math.toRadians(rotation.y)); 
    modelMatrix.rotateZ((float) Math.toRadians(rotation.z)); 

    shader.editUniform(modelMatrix, matrixName); 

    glBindVertexArray(vao); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 
    glEnableVertexAttribArray(0); 
    glEnableVertexAttribArray(2); 
    if (hasTexture) { 
     glEnableVertexAttribArray(1); 
     texture.bind(); 
    } 

    glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0); 

    glDisableVertexAttribArray(2); 
    glDisableVertexAttribArray(0); 
    if (hasTexture) { 
     glDisableVertexAttribArray(1); 
     texture.unbind(); 
    } 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 
} 

public void delete() { 
    glDeleteBuffers(vbo); 
    glDeleteBuffers(ibo); 
    glDeleteBuffers(nbo); 
    if (hasTexture) { 
     glDeleteBuffers(tbo); 
     texture.delete(); 
    } 
    glDeleteVertexArrays(vao); 
} 

}

У меня есть легкий класс, который просто выводит цвет и положение вектора к шейдера. Камера работает нормально, и все остальное прекрасно работает, если я не использую освещение. (кроме более одного лица).

геометрия шейдеров:

#version 400 

layout(triangles) in; 
layout(triangle_strip, max_vertices = 3) out; 

in vec4 colour[]; 
in vec2 pass_tex_coords[]; 

in vec3 pass_normal[]; 
out vec3 t_normal; 
out vec3 t_light; 

out vec2 pass_tex_coords_; 
out vec4 pass_colour; 

uniform mat4 projection; 
uniform mat4 view; 
uniform mat4 model; 

uniform vec3 light_position; 

void main(void) { 
    for (int i = 0; i < gl_in.length(); i++) { 
     vec4 world_pos = projection * view * model * gl_in[i].gl_Position; 
     gl_Position = world_pos; 

     pass_tex_coords_ = pass_tex_coords[i]; 
     pass_colour = colour[i]; 

     t_normal = (view * model * vec4(pass_normal[i], 0)).xyz; 
     t_light = (view * vec4(light_position, 1)).xyz; 

     EmitVertex(); 
    } 

    EndPrimitive(); 
} 

пиксельный шейдер:

#version 400 

in vec4 pass_colour; 
in vec2 pass_tex_coords_; 

in vec3 t_normal; 
in vec3 t_light; 

out vec4 out_colour; 

uniform int has_texture; 
uniform sampler2D tex; 

uniform vec4 light_colour; 

void main(void) { 
    vec3 n_normal = normalize(t_normal); 
    vec3 n_light = normalize(t_light); 
    float cosTheta = dot(n_normal, n_light); 

    if (has_texture != 1) { 
     out_colour = texture(tex, pass_tex_coords_) * pass_colour * cosTheta; 
    } else { 
     out_colour = pass_colour; 
    } 
} 

Если кто имеет какие-либо ссылки на на лицо освещение, которое было бы здорово, я не смог найти. Я действительно думаю, что это имеет какое-то отношение к моему грязному классу модели с параметром индексов.

EDIT Все лица визуализируют сейчас, теперь как я могу исправить странное плавное освещение градиента, чтобы быть плоским освещением на лице?

ответ

0

Выгрузка буфера индексов кажется неправильным:

for (int[] face : indices) 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, put(face), GL_STATIC_DRAW); 

Этого код наложения в каждой итерации связанного буфера элемента массива, но это, кажется, как если бы вы хотите добавить индексы один за другим к буфер. То, что вы на самом деле хотите, должно быть что-то вроде этого:

//Calculate total length of indices 
int lenght = 0; 
for (int[] face : indices) 
    length += face.length; 

//Pack data together 
IntBuffer pData = BufferUtils.createIntBuffer(length); 

int start_idx = 0; 
for (int[] face : indices) 
{ 
    pData.put(face, start_idx, face.length); 
    start_idx += face.length; 
} 

pData.flip(); 

//Upload to OpenGL 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, pData, GL_STATIC_DRAW); 

Обратите внимание, что каждая запись в индексы (int[] face) должен иметь ровно три элемента, так как OpenGL ядра профиля можно рисовать только треугольники. Таким образом, вы можете заменить первый цикл на int length = indices.length * 3;

+0

Хорошо спасибо, теперь он отображает весь куб. Но как насчет освещения? Он проявляет себя как плавный градиент, но его просто массивный беспорядок. Кажется, только 2 лица подвержены влиянию света, а лица, затронутые, просто делают какую-то сумасшедшую вещь –

Смежные вопросы