如何启用两个对象的不同 GL_POSITION

Posted

技术标签:

【中文标题】如何启用两个对象的不同 GL_POSITION【英文标题】:How to enable different GL_POSITION of two objects 【发布时间】:2019-08-10 05:36:32 【问题描述】:

我想创建两个具有不同灯光位置的对象。但是即使我设置了不同的位置参数,第二个物体(金球)的光位置总是与第一个物体(银球)相同。

我已经启用了一个又一个对象的光。但是第二个总是和第一个/上面的一样。

    // light from top right
    GLfloat light_position_top_right[] =  1.0, 1.0, 1.0, 0.0 ;
    // light from bottom left
    GLfloat light_position_bottom_left[] =  -1.0, -1.0, 1.0, 0.0 ;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLightfv(GL_LIGHT0, GL_POSITION, light_position_top_right);
    glLightfv(GL_LIGHT1, GL_POSITION, light_position_bottom_left);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHT1);
    glEnable(GL_DEPTH_TEST);

你可以在这个gist找到完整的代码。

我希望第二个对象的位置从左下角开始。但它从右上角显示为第一个对象。

【问题讨论】:

【参考方案1】:

您的灯光位置的第四个坐标必须是1.0 而不是0.0,否则由于投影变换的工作原理,灯光会表现得好像它们在指定方向上无限远。

第四个坐标为0.0

第四个坐标为1.0

至于为什么有两个高光而不是只有一个,您忘记为您的灯光设置正确的glLight* 设置。默认情况下,GL_LIGHT0 以白色漫反射和高光颜色开头,但所有其他灯光默认具有黑色漫反射和高光颜色。


编辑:

如果您希望单独的球体使用单独的灯光,则需要在 init() 期间初始化灯光。但是,不要马上glEnableing 灯,而是执行以下操作:

void display(void)

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
    glTranslatef(1.0, 0.0, -1.0);
    glEnable(GL_LIGHT0);
    drawGraySphere();
    glutSolidSphere(0.5, 50, 50);
    glDisable(GL_LIGHT0);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(-0.75, -0.8, 0.0);
    glEnable(GL_LIGHT1);
    drawGoldSphere();
    glutSolidSphere(0.5, 50, 50);
    glDisable(GL_LIGHT1);
    glPopMatrix();

    glFlush();

或者,在渲染每个球体之前,您可以选择只使用单个灯光,并在每帧使用glLight* 更改其参数。如果您打算拥有一堆对象,每个对象都有自己的光,这是更好的选择。

【讨论】:

对不起,但不是很清楚。 GLfloat light_position_top_right[] = 1.0, 1.0, 1.0, 1.0 ;GLfloat light_position_bottom_left[] = -1.0, -1.0, 1.0, 1.0 ;我已经更新了第四个坐标,但是结果却不如预期。 我刚刚通过添加我的期望更新了我的要点。 啊,你想对第一个对象使用 GL_LIGHT0,对第二个对象使用 GL_LIGHT1?在这种情况下,您需要在两个对象之间正确使用glEnable(GL_LIGHT*)glDisable(GL_LIGHT*)。不用担心,重新启用后,您无需再次设置灯光参数。 或者,您可以一直重复使用GL_LIGHT0,并始终根据需要在对象之间设置参数。 是的,我的第一个对象是 GL_LIGHT0,第二个对象是 GL_LIGHT1。但是,我尝试像这样启用和禁用灯光,但没有运气。它根本没有光。 glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glDisable(GL_LIGHT0);glEnable(GL_LIGHT1);glDisable(GL_LIGHT1);glEnable(GL_DEPTH_TEST);【参考方案2】:

这是您的代码,已修改为您希望它执行的操作:

#include<windows.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

void drawGoldSphere() 
    GLfloat mat_specular[] =  0.628281, 0.555802, 0.366065, 1.0 ;
    GLfloat mat_shininess[] =  51.2 ;
    GLfloat mat_ambient[] =  0.24725, 0.1995, 0.0745, 1.0 ;
    GLfloat mat_diffuse[] =  0.75164, 0.60648, 0.22648, 1.0 ;
    //Material Properties
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);


void drawGraySphere() 
    GLfloat mat_specular[] =  1.0, 1.0, 1.0, 1.0 ;
    GLfloat mat_shininess[] =  50.0 ;
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);


void init(void)

    // light from middle left
    //GLfloat light_position[] =  0.0, 0.0, 0.0, 1.0 ;
    // light from top right
    GLfloat light_position_top_right[] =  1.0, 1.0, 1.0, 0.0 ;
    // light from bottom left
    GLfloat light_position_bottom_left[] =  -1.0, -1.0, 1.0, 0.0 ;
    // light from bottom left
    //GLfloat light_position[] =  -0.1, -0.1, -0.1, 0.0 ;
    // light from middle top
    //GLfloat light_position[] =  0.0, 1.0, 0.0, 0.0 ;
    // light from middle right
    //GLfloat light_position[] =  1.0, 0.0, 0.0, 0.0 ;
    // light from middle middle
    //GLfloat light_position[] =  0.0, 0.0, 1.0, 0.0 ;
    // light from middle bottom
    //GLfloat light_position[] =  0.0, -1.0, 1.0, 0.0 ;


    GLfloat no_mat[] =  0.0, 0.0, 0.0, 1.0 ;
    GLfloat light_diffuse[] =  1.0, 1.0, 1.0, 1.0 ;
    GLfloat light_specular[] =  1.0, 1.0, 1.0, 1.0 ;
    GLfloat high_shininess[] =  100.0 ;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position_top_right);

    glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
    glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
    glLightfv(GL_LIGHT1, GL_POSITION, light_position_bottom_left);

    glEnable(GL_LIGHTING);
    glEnable(GL_DEPTH_TEST);


void display(void)

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
    glTranslatef(1.0, 0.0, -1.0);
    glEnable(GL_LIGHT0);
    drawGraySphere();
    glutSolidSphere(0.5, 50, 50);
    glDisable(GL_LIGHT0);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(-0.75, -0.8, 0.0);
    glEnable(GL_LIGHT1);
    drawGoldSphere();
    glutSolidSphere(0.5, 50, 50);
    glDisable(GL_LIGHT1);
    glPopMatrix();

    glFlush();

void reshape(int w, int h)

    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= h)
    glOrtho(-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
    1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
    else
    glOrtho(-1.5*(GLfloat)w/(GLfloat)h,
    1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

int main(int argc, char** argv)

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return 0;

渲染结果:

【讨论】:

以上是关于如何启用两个对象的不同 GL_POSITION的主要内容,如果未能解决你的问题,请参考以下文章

如何将两个不同的对象添加到一个对象中

如何连接来自两个不同 PDO 对象的表?

如何从两个不同的数组中找到共同的对象并打印另一个对象?

将源自不同表的两个 postgresql tsvector 字段连接到单个 postgresql 视图中,以启用联合全文搜索

如何将两个不同的对象传递给邮递员中的 POST 请求以测试 RESTful API?

如何更新可用于 Java 中两个不同对象的方法