繁体   English   中英

LWJGL每脸照明

[英]LWJGL per face 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;
    }
}

如果有人对人脸照明有任何链接很棒,我找不到任何链接。 我确实认为这与我的带有indexs参数的Model类有关。

编辑现在可以渲染所有面,现在如何将怪异的平滑渐变照明固定为每面平面照明?

上载索引缓冲区似乎是错误的:

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 Core Profile只能绘制三角形。 因此,您可以将第一个循环替换为int length = indices.length * 3;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM