简体   繁体   English

OpenGL首先使用光照和法线

[英]OpenGL first steps with light and normals

I'm playing around with some basic OpenGL stuff and I'm trying to set up a simple square with lighting enabled, but the lighting is not correct so there is something wrong with my normals i guess. 我在玩一些基本的OpenGL东西,并尝试设置一个启用了照明的简单正方形,但是照明不正确,所以我的法线有问题。

Or is my understanding of normals totally wrong? 还是我对法线的理解完全错误?

在此处输入图片说明

Here's my rendering code (btw I'm using lwjgl): public class Renderer { 这是我的渲染代码(顺便说一句,我正在使用lwjgl):public class Renderer {

DisplayMode displayMode;
int i;
int width;
int height;
private boolean drawAxes = false;
private float rotation = 40.0f;
private float zoom = -20f;

// ----------- Variables added for Lighting Test -----------//
private FloatBuffer matSpecular;
private FloatBuffer lightPosition;
private FloatBuffer whiteLight;
private FloatBuffer lModelAmbient;

public Renderer(int width, int height) {
    this.width = width;
    this.height = height;
}

public static Renderer start() throws LWJGLException {
    Renderer r = new Renderer(800, 600);
    r.initContext();
    r.run();
    return r;
}

private void initContext() throws LWJGLException {
    Display.setFullscreen(false);
    DisplayMode d[] = Display.getAvailableDisplayModes();
    for (int i = 0; i < d.length; i++) {
        if (d[i].getWidth() == width && d[i].getHeight() == height && d[i].getBitsPerPixel() == 32) {
            displayMode = d[i];
            break;
        }
    }
    Display.setDisplayMode(displayMode);
    Display.create();
}

private void run() {
    initGL();
    while (!Display.isCloseRequested()) {
        preRender();
        render();
        Display.update();
        Display.sync(60);
    }
    Display.destroy();
}

private void initGL() {

    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
    GL11.glClearDepth(1.0); // Depth Buffer Setup
    GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
    GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do

    GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
    GL11.glLoadIdentity(); // Reset The Projection Matrix

    // Calculate The Aspect Ratio Of The Window
    GLU.gluPerspective(45.0f, (float) displayMode.getWidth() / (float) displayMode.getHeight(), 0.1f, 100.0f);
    GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix

    // Really Nice Perspective Calculations
    GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);

    GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);

    initLightArrays();
    glShadeModel(GL_SMOOTH);
    glMaterial(GL_FRONT, GL_SPECULAR, matSpecular); // sets specular material color
    glMaterialf(GL_FRONT, GL_SHININESS, 100.0f); // sets shininess

    glLight(GL_LIGHT0, GL_POSITION, lightPosition); // sets light position
    glLight(GL_LIGHT0, GL_SPECULAR, whiteLight); // sets specular light to white
    glLight(GL_LIGHT0, GL_DIFFUSE, whiteLight); // sets diffuse light to white
    glLightModel(GL_LIGHT_MODEL_AMBIENT, lModelAmbient); // global ambient light

    glEnable(GL_LIGHTING); // enables lighting
    glEnable(GL_LIGHT0); // enables light0

    glEnable(GL_COLOR_MATERIAL); // enables opengl to use glColor3f to define material color
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // tell opengl glColor3f effects the ambient and diffuse properties of material

}

private void preRender() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    GL11.glTranslatef(0f, 0f, zoom);
    GL11.glRotatef(-60f, 1f, 0f, 0f);
    GL11.glRotatef(rotation, 0f, 0f, 1f);
}

private void render() {

    FloatBuffer cBuffer = BufferUtils.createFloatBuffer(6*3);
    float[] cArray = {  1f,1f,1f,
                        1f,1f,1f,
                        1f,1f,1f,
                        1f,1f,1f,
                        1f,1f,1f,
                        1f,1f,1f};
    cBuffer.put(cArray);
    cBuffer.flip();

    FloatBuffer vBuffer = BufferUtils.createFloatBuffer(6*3);
    float[] vArray = {  1f,1f,0f,
                        -1f,-1f,0,
                        1f,-1f,0,
                        1f,1f,0f,
                        -1f,1f,0,
                        -1f,-1f,0};
    vBuffer.put(vArray);
    vBuffer.flip();

    FloatBuffer nBuffer = BufferUtils.createFloatBuffer(6*3);
    float[] nArray = {  0f,0f,1f,
                        0f,0f,1f,
                        0f,0f,1f,
                        0f,0f,1f,
                        0f,0f,1f,
                        0f,0f,1f};
    nBuffer.put(nArray);
    nBuffer.flip();

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glColorPointer(3, 0, cBuffer);
    glVertexPointer(3, 0, vBuffer);
    glNormalPointer(3, nBuffer);
    glDrawArrays(GL_TRIANGLES, 0, 6);

    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);

    if (drawAxes) {
        drawAxes(6);
    }

    glTranslatef(0.0f, 0.0f, 3);
    glColor3f(0.1f, 0.4f, 0.9f);
}

public static void main(String[] args) throws LWJGLException {
    System.setProperty("org.lwjgl.opengl.Display.allowSoftwareOpenGL", "true");
    Renderer.start();
}

You are setting your normal pointer wrong: 您将普通指针设置为错误:

glColorPointer(3, 0, cBuffer);
glVertexPointer(3, 0, vBuffer);
glNormalPointer(3, nBuffer);

The fixed-function GL might always expects normals to be 3-dimensional vectors, henze the size parameter (which tells the GL how many values are there in every vector ) is not present in glNormalPointer . 固定函数GL可能总是希望法线是3维向量,但请注意glNormalPointer不存在size参数(告诉GL每个向量中有多少个值)。 The 3 you are setting here is the stride parameter, which specifies the byte offset between consecutive array elements. 您在此处设置的3stride参数,该参数指定连续数组元素之间的字节偏移量。 Now 3 does not make any sence, it will interpret the second normal as to beginning 3 bytes into the arry, which means it combines the last byte of your first normal's x component together with 3 bytes from your first normal's y component when it reads the second normal'x s component, and so on... 现在3没有任何意义,它将以第二个法线来解释将3个字节开始到arry中,这意味着它将在读取第一个法线的x分量的最后一个字节与第一个法线的y分量的3个字节时组合在一起。第二个normal'x组件,依此类推...

Since your array is tightly packed, you can use the shortcut 0 here, like you do with the other pointers. 由于数组是紧密包装的,因此可以像其他指针一样在此处使用快捷方式0

However, you must be aware that all of that is deprecated since almost a decade in OpenGL, modern core versions of OpenGL do not support the fixed function pipeline at all . 但是,您必须知道,自从在OpenGL中使用了将近十年以来,所有这些东西都已被弃用 ,OpenGL的现代核心版本完全不支持固定功能管线 If you are learning OpenGL nowadays, I strongly recommend you to learn modern, shader-based GL instead. 如果您现在正在学习OpenGL,则强烈建议您改为学习基于着色器的现代GL。

Without seeing more of your code, it's very difficult to see exactly what's going wrong. 没有看到更多的代码,很难确切地知道出了什么问题。

However, I do see one thing that could be a problem: 但是,我确实看到一件事可能是一个问题:

FloatBuffer vBuffer = BufferUtils.createFloatBuffer(6*3);
float[] vArray = {  1f,1f,0f,
                    1f,-1f,0,
                    -1f,-1f,0,
                    1f,1f,0f,
                    -1f,1f,0,
                    -1f,-1f,0};
vBuffer.put(vArray);
vBuffer.flip();

The winding order on your triangles are not the same. 三角形上的缠绕顺序不同。 The first triangle winds clockwise, whereas the second triangle winds counter-clockwise. 第一个三角形顺时针缠绕,而第二个三角形逆时针缠绕。 You'll need to reorder the vertices to make sure that they wind in the same direction. 您需要重新排列顶点,以确保它们以相同方向缠绕。 OpenGL usually prefers things to wind counter-clockwise, so if I were you, I'd flip the first triangle. OpenGL通常喜欢沿逆时针方向缠绕,因此如果我是你,我会翻转第一个三角形。

If you're still getting the problem after you've done this, then post the rest of your draw code, as what you're showing here doesn't give a lot of information. 如果执行此操作后仍然遇到问题,请张贴其余的绘制代码,因为此处显示的内容不会提供很多信息。

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

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