LWJGL每面照明

时间:2017-01-06 23:32:16

标签: java opengl lighting

我尝试制作一些可以解决面部法线问题的东西,我不知道它是否有效,我的模型上有光滑的阴影。

它似乎可以很好地作为一个四边形,但是当我尝试一个立方体时,它只在顶部呈现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);
}

}

我有一个光类,它只向着色器输出颜色和位置矢量。 如果我不使用照明,相机工作正常,其他一切正常。 (除了超过1张脸)。

几何着色器:

    #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;
    }
}

如果任何人有任何链接到每个面部照明将是伟大的,我找不到任何。 我认为这与我的带有indices参数的凌乱的Model类有关。

EDIT 所有面孔现在渲染,现在我如何修复奇怪的平滑渐变照明作为每面平面照明?

1 个答案:

答案 0 :(得分: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;

替换第一个循环