shadowmap.c

来自「OpeNGL超级宝典源代码. OpeNGL超级宝典源代码.」· C语言 代码 · 共 545 行 · 第 1/2 页

C
545
字号
void SetupRC()
{
    const GLubyte *version;

    fprintf(stdout, "Shadow Mapping Demo\n\n");

    // Make sure required functionality is available!
    version = glGetString(GL_VERSION);
    if (((version[0] != '1') || (version[1] != '.') || 
         (version[2] < '4') || (version[2] > '9')) &&   // 1.4+
        (!gltIsExtSupported("GL_ARB_shadow")))
    {
        fprintf(stderr, "Neither OpenGL 1.4 nor GL_ARB_shadow"
                        " extension is available!\n");
        Sleep(2000);
        exit(0);
    }

    // Check for optional extension
    if (gltIsExtSupported("GL_ARB_shadow_ambient"))
    {
        ambientShadowAvailable = GL_TRUE;
    }
    else
    {
        fprintf(stderr, "GL_ARB_shadow_ambient extension not available!\n");
        fprintf(stderr, "Extra ambient rendering pass will be required.\n\n");
        Sleep(2000);
    }

    fprintf(stdout, "Controls:\n");
    fprintf(stdout, "\tRight-click for menu\n\n");
    fprintf(stdout, "\tx/X\t\tMove +/- in x direction\n");
    fprintf(stdout, "\ty/Y\t\tMove +/- in y direction\n");
    fprintf(stdout, "\tz/Z\t\tMove +/- in z direction\n\n");
    fprintf(stdout, "\tf/F\t\tChange polygon offset factor +/-\n\n");
    fprintf(stdout, "\tq\t\tExit demo\n\n");
    
    // Black background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

    // Hidden surface removal
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glPolygonOffset(factor, 0.0f);

    // Set up some lighting state that never changes
    glShadeModel(GL_SMOOTH);
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_NORMALIZE);
    glEnable(GL_LIGHT0);

    // Set up some texture state that never changes
    glGenTextures(1, &shadowTextureID);
    glBindTexture(GL_TEXTURE_2D, shadowTextureID);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
    if (ambientShadowAvailable)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 
                        0.5f);
    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
    glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);

    RegenerateShadowMap();
}

void ProcessMenu(int value)
{
    switch(value)
    {
    case 1:
        noShadows = !noShadows;
        showShadowMap = GL_FALSE;
        if (noShadows)
        {
            glutChangeToMenuEntry(1, "Toggle shadows (currently OFF)", 1);
        }
        else
        {
            glutChangeToMenuEntry(1, "Toggle shadows (currently ON)", 1);
        }
        glutChangeToMenuEntry(2, "Toggle show shadowmap (currently OFF)", 2);
        break;

    case 2:
        showShadowMap = !showShadowMap;
        noShadows = GL_FALSE;
        if (showShadowMap)
        {
            glutChangeToMenuEntry(2, "Toggle show shadowmap (currently ON)", 2);
        }
        else
        {
            glutChangeToMenuEntry(2, "Toggle show shadowmap (currently OFF)", 2);
        }
        glutChangeToMenuEntry(1, "Toggle shadows (currently ON)", 1);
        break;

    case 3:
        controlCamera = !controlCamera;
        if (controlCamera)
        {
            glutChangeToMenuEntry(3, "Switch to LIGHT control (currently CAMERA)", 3);
        }
        else
        {
            glutChangeToMenuEntry(3, "Switch to CAMERA control (currently LIGHT)", 3);
        }
        break;

    default:
        break;
    }

    // Refresh the Window
    glutPostRedisplay();
}

void KeyPressFunc(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 'f':
        factor++;
        glPolygonOffset(factor, 0.0f);
        RegenerateShadowMap();
        break;
    case 'F':
        factor--;
        glPolygonOffset(factor, 0.0f);
        RegenerateShadowMap();
        break;
    case 'x':
        if (controlCamera)
            cameraPos[0] += 5.0f;
        else
            lightPos[0] += 5.0f;
        break;
    case 'X':
        if (controlCamera)
            cameraPos[0] -= 5.0f;
        else
            lightPos[0] -= 5.0f;
        break;
    case 'y':
        if (controlCamera)
            cameraPos[1] += 5.0f;
        else
            lightPos[1] += 5.0f;
        break;
    case 'Y':
        if (controlCamera)
            cameraPos[1] -= 5.0f;
        else
            lightPos[1] -= 5.0f;
        break;
    case 'z':
        if (controlCamera)
            cameraPos[2] += 5.0f;
        else
            lightPos[2] += 5.0f;
        break;
    case 'Z':
        if (controlCamera)
            cameraPos[2] -= 5.0f;
        else
            lightPos[2] -= 5.0f;
        break;
    case 'q':
    case 'Q':
    case 27 : /* ESC */
        exit(0);
    }

    // We don't need to regenerate the shadow map
    // if only the camera angle changes
    if (!controlCamera)
        RegenerateShadowMap();

    // Refresh the Window
    glutPostRedisplay();
}

void SpecialKeys(int key, int x, int y)
{
    switch (key)
    {
    case GLUT_KEY_LEFT:
        if (controlCamera)
            cameraPos[0] -= 5.0f;
        else
            lightPos[0] -= 5.0f;
        break;
    case GLUT_KEY_RIGHT:
        if (controlCamera)
            cameraPos[0] += 5.0f;
        else
            lightPos[0] += 5.0f;
        break;
    case GLUT_KEY_UP:
        if (controlCamera)
            cameraPos[2] -= 5.0f;
        else
            lightPos[2] -= 5.0f;
        break;
    case GLUT_KEY_DOWN:
        if (controlCamera)
            cameraPos[2] += 5.0f;
        else
            lightPos[2] += 5.0f;
        break;
    default:
        break;
    }

    // We don't need to regenerate the shadow map
    // if only the camera angle changes
    if (!controlCamera)
        RegenerateShadowMap();

    // Refresh the Window
    glutPostRedisplay();
}

void ChangeSize(int w, int h)
{
    GLint i;
    
    windowWidth = w;
    windowHeight = h;
    
    // Find the largest power of two that will fit in window
    if (w > h)
        shadowSize = h;
    else
        shadowSize = w;

    // Try each size until we get one that's too big
    i = 0;
    while ((1 << i) <= shadowSize)
        i++;
    shadowSize = (1 << (i-1));
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(windowWidth, windowHeight);
    glutCreateWindow("Shadow Mapping Demo");
    glutReshapeFunc(ChangeSize);
    glutKeyboardFunc(KeyPressFunc);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);

    // Create the Menu
    glutCreateMenu(ProcessMenu);
    glutAddMenuEntry("Toggle shadows (currently ON)", 1);
    glutAddMenuEntry("Toggle show shadowmap (currently OFF)", 2);
    glutAddMenuEntry("Switch to LIGHT control (currently CAMERA)", 3);
    glutAttachMenu(GLUT_RIGHT_BUTTON);

    SetupRC();

    glutMainLoop();
    return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?