c++ - OpenGL 评估器仅部分点亮

标签 c++ opengl

我尝试使用求值器在 OpenGL 中使用 C++ 制作小型波发生器。

enter image description here

但是,由于我的评估器仅部分点亮,因此我运气不佳。

为什么会这样?

为了完整起见,下面我包含了完整的源代码,您可能只需要查看 init()display() 和顶部的常量的文件。

#include <gl/glui.h>
#include <math.h>

const int DIMX = 500;
const int DIMY = 500;
const int INITIALPOS_X = 200;
const int INITIALPOS_Y = 200;


// Aspect ratio (calculated on the fly)
float xy_aspect;

// UI aux. matrices
float view_rotate[16] = { 1,0,0,0,
                          0,1,0,0,
                          0,0,1,0,
                          0,0,0,1 };

float obj_pos[] = { 0.0, 0.0, 0.0 };
float obj_pan[] = { 0.0, 0.0, 0.0 };

// Referential axis
double axis_radius_begin =  0.2;
double axis_radius_end   =  0.0;
double axis_lenght       = 16.0;
int axis_nslices = 8;
int axis_nstacks = 1;

// Light 0 properties
float light0_position[]  = {5.0, 5.0, 5.0, 0.0};
float light0_ambient[] =   {0.0, 0.0, 0.0, 1.0};
float light0_diffuse[] =   {0.6, 0.6, 0.6, 1.0};
float light0_specular[] =  {1.0, 1.0, 1.0, 1.0};
float light0_kc = 0.0;
float light0_kl = 1.0;
float light0_kq = 0.0;
double light0x = 5.0;
double light0y = 5.0;
double light0z = 5.0;
double symb_light0_radius = 0.2;
int symb_light0_slices = 8;
int symb_light0_stacks =8;

// Ambient light source properties
float light_ambient[] = {0.5, 0.5, 0.5, 1.0}; /* Set the background ambient lighting. */

// Windowing related variables
int main_window;
GLUquadric* glQ;
GLUI  *glui;

const unsigned int gridSize = 40;

float grid[gridSize][gridSize][3];

const int uSize = gridSize;
const int vSize = gridSize;

GLfloat ambient[] = {0.2, 0.2, 0.2, 1.0};
GLfloat position[] = {0.0, 0.0, 2.0, 1.0};
GLfloat mat_diffuse[] = {0.6, 0.6, 0.6, 1.0};
GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};
float mat_shininess[] = {50.0};


void display(void) {
    static float value = 0;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glFrustum( -xy_aspect*.04, xy_aspect*.04, -.04, .04, .1, 50.0 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glTranslatef( obj_pos[0], obj_pos[1], -obj_pos[2]-25 );
    glTranslatef( obj_pan[0], obj_pan[1], obj_pan[2] );

    glRotated( 20.0, 1.0,0.0,0.0 );
    glRotated(-45.0, 0.0,1.0,0.0 );

    glMultMatrixf( view_rotate );

    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
    glEnable(GL_COLOR_MATERIAL);


    glColor3f(1.0,0.0,0.0);
    glPushMatrix();
    glRotated(90.0, 0.0,1.0,0.0 );
    gluCylinder(glQ, axis_radius_begin, axis_radius_end,
                     axis_lenght, axis_nslices, axis_nstacks);   
    glPopMatrix();


    glColor3f(0.0,1.0,0.0);
    glPushMatrix();
    glRotated(-90.0, 1.0,0.0,0.0 );
    gluCylinder(glQ, axis_radius_begin, axis_radius_end,
                     axis_lenght, axis_nslices, axis_nstacks);   
    glPopMatrix();


    glColor3f(0.0,0.0,1.0);
    glPushMatrix();

    gluCylinder(glQ, axis_radius_begin, axis_radius_end,
                     axis_lenght, axis_nslices, axis_nstacks);
    glPopMatrix();


    light0_position[0] = light0x;
    light0_position[1] = light0y;
    light0_position[2] = light0z;

    glLightfv(GL_LIGHT0, GL_POSITION, light0_position);

    glColor3f(1.0,1.0,0.0);
    gluQuadricOrientation( glQ, GLU_INSIDE);
    glPushMatrix();
        glTranslated(light0x,light0y,light0z);
        gluSphere(glQ, symb_light0_radius, symb_light0_slices, symb_light0_stacks);
    glPopMatrix();

    gluQuadricOrientation( glQ, GLU_OUTSIDE);

    gluQuadricDrawStyle(glQ, GLU_FILL);
    gluQuadricNormals(glQ, GLU_SMOOTH);
    gluQuadricOrientation(glQ, GLU_OUTSIDE);
    gluQuadricTexture(glQ, GL_FALSE);

    for (unsigned int y = 0; y < vSize; ++y) {
        for (unsigned int x = 0; x < uSize; ++x) {
            float xVal = 5*3.14/gridSize*x;
            float yVal = 5*3.14/gridSize*y;
            grid[y][x][0] = (float) x/gridSize*10.0;
            grid[y][x][1] = sin(xVal + value) + sin(yVal + value);
            grid[y][x][2] = (float) y/gridSize*10.0;
        }
    }

    glMap2f(GL_MAP2_VERTEX_3, 0, 1 , 3, uSize, 0, 1, uSize * 3, vSize, &grid[0][0][0]);
    glEvalMesh2(GL_FILL, 0, gridSize, 0, gridSize);

    value += 3.14/25;

    if (value > 3.14*2)
        value = 0;
    // swapping the buffers causes the rendering above to be shown
    glutSwapBuffers();
    glFlush();
}


/* Mouse handling */
void processMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {    
    }
    if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
    {   
    }

    glutPostRedisplay();

}

void processMouseMoved(int x, int y)
{

    // pedido de refrescamento da janela
    glutPostRedisplay();                

}

void processPassiveMouseMoved(int x, int y)
{

    // pedido de refrescamento da janela
    glutPostRedisplay();                
}

void reshape(int w, int h)
{
    int tx, ty, tw, th;

    GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th );
    glViewport( tx, ty, tw, th );
    xy_aspect = (float)tw / (float)th;

    glutPostRedisplay();

}


void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:      // tecla de escape termina o programa
         exit(0);
         break;
   }
}


void glut_idle( void )
{
  if ( glutGetWindow() != main_window ) 
    glutSetWindow(main_window);  

  glutPostRedisplay();

}

void init()
{
    glQ = gluNewQuadric();

    glFrontFace(GL_CCW);        // Front faces defined using a counterclockwise rotation
    glDepthFunc(GL_LEQUAL);     // Por defeito e GL_LESS
    glEnable(GL_DEPTH_TEST);    // Use a depth (z) buffer to draw only visible objects

    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

    // Face Culling para aumentar a velocidade
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);        // GL_FRONT, GL_BACK, GL_FRONT_AND_BACK


    // Define que modelo de iluminacao utilizar; consultar o manual de referencia
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_ambient);  // define luz ambiente
    glLightModelf (GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
    glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, 1);

    // por defeito a cor de fundo e o preto
    // glClearColor(1.0,1.0,1.0,1.0);    // cor de fundo a branco


    // declaracoes para a fonte luz GL_LIGHT0
    glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION,  light0_kc);
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION,    light0_kl);
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, light0_kq);

    // NOTA: a direccao e a posicao de GL_LIGHT0 estao na rotina display(), pelo
    //       que as isntrucoes seguntes nao sao necessarias
    //glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 90.0);
    //glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);
    //glLightfv(GL_LIGHT0, GL_POSITION, light0_position);


    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glEnable(GL_NORMALIZE); 

    glEnable(GL_MAP2_VERTEX_3);
    glMapGrid2f(gridSize, 0.0, 1.0, gridSize, 0.0, 1.0);


    glShadeModel(GL_SMOOTH);
    glPolygonMode(GL_FRONT, GL_FILL);
    //glPolygonMode(GL_FRONT, GL_LINE);
}

void do_nothing(int key, int x, int y) {}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize (DIMX, DIMY);
    glutInitWindowPosition (INITIALPOS_X, INITIALPOS_Y);
    main_window = glutCreateWindow (argv[0]);

    glutDisplayFunc(display);
    GLUI_Master.set_glutReshapeFunc(reshape);
    GLUI_Master.set_glutKeyboardFunc (keyboard);
    GLUI_Master.set_glutMouseFunc(processMouse);      
    glutMotionFunc(processMouseMoved);
    glutPassiveMotionFunc(processPassiveMouseMoved);
    GLUI_Master.set_glutSpecialFunc( do_nothing );


    /*** Create the bottom subwindow ***/
    glui = GLUI_Master.create_glui_subwindow( main_window, GLUI_SUBWINDOW_BOTTOM );
    glui->set_main_gfx_window( main_window );

    GLUI_Rotation *view_rot = glui->add_rotation( "Rotation", view_rotate );
    view_rot->set_spin( 1.0 );

    glui->add_column( false );
    GLUI_Translation *trans_z = glui->add_translation( "Zoom", GLUI_TRANSLATION_Z, &obj_pos[2] );
    trans_z->set_speed( .1 );

    glui->add_column(false);
    GLUI_Translation *trans_pan = glui->add_translation("Pan", GLUI_TRANSLATION_XY, &obj_pan[0]);
    trans_pan->set_speed(.1);

    GLUI_Master.set_glutIdleFunc( glut_idle );

    init();

    glutMainLoop();

    return 0;
}

最佳答案

您说 OpenGL 求值器不需要设置法线。这只是部分正确。如果您通过调用为评估器启用自动生成的法线,则不需要设置法线:

glEnable(GL_AUTO_NORMAL);

仅仅启用 GL_NORMALIZE 是不行的。

但是您当然也可以通过为 GL_MAP2_NORMAL 提供控制点来指定您自己的法线,就像为 GL_MAP2_VERTEX_3 一样。

如果不提及 OpenGL 求值器已被高度弃用并且很可能由驱动程序在软件中实现,则答案是不完整的。因此,滚动您自己的 Bezier 评估代码(这不是很难)并生成绘制为 GL_TRIANGLES 的简单网格肯定是一个更好的主意。

关于c++ - OpenGL 评估器仅部分点亮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8175620/

相关文章:

opengl - gluLookAt解释吗?

c++ - 自定义 ostream 仅打印 `<<` 链的最后一个字符串

c++ - 如何将 glm::vec4<float> 转换为 GLfloat*?

c++ - 我将如何着手将天空盒应用于世界,openGL C++

c++ - Visual Studio 2010 - 数据段和堆栈内存相同

opengl - GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 试图创建多采样帧缓冲区

opengl - 发光深度缓冲区未清除

c++ - 获取临时地址 - 需要解决方法

c++ - GoogleTest 和内存泄漏

c++ - 比较两个字符串时,如何在不使用类或库的情况下找到不在字符串数组中的第一个字符?