23.OpenGL--阴影

来源:互联网 发布:行情软件下载 编辑:程序博客网 时间:2024/06/04 21:04
  • 理论基础 
    阴影:就是我们所说的影子,其实现原理其实就是把场景渲染了两次,第一次是把相机放到光源位置渲染场景 ,然后存储渲染的深度信息到一张纹理上,即阴影图(只关心深度信息,所以此时可以关闭光照和纹理贴图提高效率)。第二次再从观察者的角度来渲染场景,在这次渲染时才渲染阴影,这次的渲染过程本质就是纹理贴图,只不过这个纹理是阴影图,贴图的方式根据我们设置的深度纹理过滤方式处理。生成阴影的过程是这样的:对于每个片元的深度信息和第一次从灯光角度渲染的深度信息比较,如果当前深度值大于第一次渲染的深度值,则肯定有物体在当前片元和灯光之间,那么当前片元在阴影区。

  • 代码示例
#include "GLTools.h"#ifdef __APPLE__#include <glut/glut.h>#else#define FREEGLUT_STATIC#include <GL/glut.h>#endif#ifdef GL_ARB_shadow#define GL_TEXTURE_COMPARE_MODE      GL_TEXTURE_COMPARE_MODE_ARB#define GL_TEXTURE_COMPARE_FUNC      GL_TEXTURE_COMPARE_FUNC_ARB#define GL_DEPTH_TEXTURE_MODE        GL_DEPTH_TEXTURE_MODE_ARB#define GL_COMPARE_R_TO_TEXTURE      GL_COMPARE_R_TO_TEXTURE_ARB#endif#define PI       3.14159265359GLdouble    fovy      = 60.0;GLdouble    nearPlane = 10.0;GLdouble    farPlane  = 100.0;GLfloat     angle = 0.0;GLfloat     torusAngle = 0.0;GLfloat     lightPos[] = { 25.0, 25.0, 25.0, 1.0 };GLfloat     lookat[] = { 0.0, 0.0, 0.0 };GLfloat     up[] = { 0.0, 0.0, 1.0 };GLboolean showShadow = GL_FALSE;/*初始化光源与阴影图*/void init( void ){    GLfloat  white[] = { 1.0, 1.0, 1.0, 1.0 };    //生成深度纹理(阴影图,只关心深度,对图像颜色信息并不关心,所以最后数据参数可以是NULL)    glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,                 256, 256, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );//GL_DEPTH_COMPONENT:深度纹理格式,用于将深度值记录到这张图中    glLightfv( GL_LIGHT0, GL_POSITION, lightPos );    glLightfv( GL_LIGHT0, GL_SPECULAR, white );    glLightfv( GL_LIGHT0, GL_DIFFUSE, white );    //设置阴影图相关过滤方式    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );    /*深度纹理特有*/    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );//比较规则    glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE );//阴影图亮度    /*分为普通对比模式(GL_NONE)和引用到贴图对比模式(GL_COMPARE_REF_TO_TEXTURE),后者使用的深度纹理贴图是线性过滤的,而前者是直接填充。*/    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,GL_COMPARE_R_TO_TEXTURE );    //自动生成纹理坐标    glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );    glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );    glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );    glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );    glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );    glCullFace( GL_BACK );//剔除背面    glEnable( GL_DEPTH_TEST );    glEnable( GL_LIGHT0 );    glEnable( GL_LIGHTING );    glEnable( GL_TEXTURE_2D );    glEnable( GL_TEXTURE_GEN_S );    glEnable( GL_TEXTURE_GEN_T );    glEnable( GL_TEXTURE_GEN_R );    glEnable( GL_TEXTURE_GEN_Q );    glEnable( GL_COLOR_MATERIAL );//激活颜色材料模式    glEnable( GL_CULL_FACE );//激活表面剔除}void reshape( int width, int height ){    glViewport( 0, 0, width, height );    glMatrixMode( GL_PROJECTION );    glLoadIdentity();    gluPerspective( fovy, (GLdouble) width/height, nearPlane, farPlane );    glMatrixMode( GL_MODELVIEW );}void idle( void ){    angle += PI / 10000;    torusAngle += .1;    glutPostRedisplay();}void keyboard( unsigned char key, int x, int y ){    switch( key ) {        case 27:  /* Escape */            exit( 0 );            break;          //开启与关闭纹理贴图        case 't': {            static GLboolean textureOn = GL_TRUE;            textureOn = !textureOn;            if ( textureOn )                glEnable( GL_TEXTURE_2D );            else                glDisable( GL_TEXTURE_2D );        }            break;        //深度纹理贴图的两种模式对比        case 'm': {            static GLboolean compareMode = GL_TRUE;            compareMode = !compareMode;            printf( "Compare mode %s\n", compareMode ? "On" : "Off" );            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,                            compareMode ? GL_COMPARE_R_TO_TEXTURE : GL_NONE );        }            break;         //比较规则切换        case 'f': {            static GLboolean funcMode = GL_TRUE;            funcMode = !funcMode;            printf( "Operator %s\n", funcMode ? "GL_LEQUAL" : "GL_GEQUAL" );            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC,funcMode ? GL_LEQUAL : GL_GEQUAL );//当前片段z与阴影图z比较规则(<=, >=)        }            break;        //是否显示阴影图        case 's':            showShadow = !showShadow;            break;         //运动与停止        case 'p': {            static GLboolean  animate = GL_TRUE;            animate = !animate;            glutIdleFunc( animate ? idle : NULL );        }            break;    }    glutPostRedisplay();}void transposeMatrix( GLfloat m[16] ){    GLfloat  tmp;#define Swap( a, b )    tmp = a; a = b; b = tmp    Swap( m[1],  m[4]  );    Swap( m[2],  m[8]  );    Swap( m[3],  m[12] );    Swap( m[6],  m[9]  );    Swap( m[7],  m[13] );    Swap( m[11], m[14] );#undef Swap}/*绘制场景上对象*/void drawObjects( GLboolean shadowRender ){    GLboolean textureOn = glIsEnabled( GL_TEXTURE_2D );    if ( shadowRender )        glDisable( GL_TEXTURE_2D );    //绘制矩形    if ( !shadowRender ) {        glNormal3f( 0, 0, 1 );        glColor3f( 1, 1, 1 );        glRectf( -20.0, -20.0, 20.0, 20.0 );    }    //红色圆环    glPushMatrix();    glTranslatef( 11, 11, 11 );    glRotatef( 54.73, -5, 5, 0 );    glRotatef( torusAngle, 1, 0, 0 );    glColor3f( 1, 0, 0 );    glutSolidTorus( 1, 4, 8, 36 );    glPopMatrix();    //蓝色立方体    glPushMatrix();    glTranslatef( 2, 2, 2 );    glColor3f( 0, 0, 1 );    glutSolidCube( 4 );    glPopMatrix();    //线框圆表光源    glPushMatrix();    glTranslatef( lightPos[0], lightPos[1], lightPos[2] );    glColor3f( 1, 1, 1 );    glutWireSphere( 0.5, 6, 6 );    glPopMatrix();    if ( shadowRender && textureOn )        glEnable( GL_TEXTURE_2D );}/*生成阴影图*/void generateShadowMap( void ){    GLint    viewport[4];    GLfloat  lightPos[4];    glGetLightfv( GL_LIGHT0, GL_POSITION, lightPos );//获得光源的位置    glGetIntegerv( GL_VIEWPORT, viewport );//获得视口信息    glViewport( 0, 0, 256, 256 );//设置视口与阴影图大小匹配    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );    glMatrixMode( GL_PROJECTION );    glPushMatrix();    glLoadIdentity();    gluPerspective( 80.0, 1.0, 10.0, 1000.0 );    glMatrixMode( GL_MODELVIEW );    glPushMatrix();    glLoadIdentity();    gluLookAt( lightPos[0], lightPos[1], lightPos[2],              lookat[0], lookat[1], lookat[2],              up[0], up[1], up[2] );//把摄像机放到光源处    drawObjects( GL_TRUE );//绘制场景    glPopMatrix();    glMatrixMode( GL_PROJECTION );    glPopMatrix();    glMatrixMode( GL_MODELVIEW );    glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 256, 256, 0 );//摄像机移到光源处渲染的阴影图    glViewport( viewport[0], viewport[1], viewport[2], viewport[3] );//恢复当前视口    //绘制阴影图    if ( showShadow ) {        GLfloat depthImage[256][256];        glReadPixels( 0, 0, 256, 256,GL_DEPTH_COMPONENT, GL_FLOAT, depthImage );        glWindowPos2f( viewport[2]/2, 0 );//设置阴影图绘制位置        glDrawPixels( 256, 256, GL_LUMINANCE,                     GL_FLOAT, depthImage );        glutSwapBuffers();    }}//自动生成阴影图的纹理坐标void generateTextureMatrix( void ){    GLfloat  tmpMatrix[16];    glPushMatrix();    glLoadIdentity();    glTranslatef( 0.5, 0.5, 0.0 );    glScalef( 0.5, 0.5, 1.0 );    gluPerspective( 60.0, 1.0, 1.0, 1000.0 );    gluLookAt( lightPos[0], lightPos[1], lightPos[2],              lookat[0], lookat[1], lookat[2],              up[0], up[1], up[2] );    glGetFloatv( GL_MODELVIEW_MATRIX, tmpMatrix );    glPopMatrix();    transposeMatrix( tmpMatrix );    glTexGenfv( GL_S, GL_OBJECT_PLANE, &tmpMatrix[0] );    glTexGenfv( GL_T, GL_OBJECT_PLANE, &tmpMatrix[4] );    glTexGenfv( GL_R, GL_OBJECT_PLANE, &tmpMatrix[8] );    glTexGenfv( GL_Q, GL_OBJECT_PLANE, &tmpMatrix[12] );}//渲染void display( void ){    GLfloat  radius = 30;    generateShadowMap();    generateTextureMatrix();    if ( showShadow )        return;    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );    glPushMatrix();    gluLookAt( radius*cos(angle), radius*sin(angle), 30,              lookat[0], lookat[1], lookat[2],              up[0], up[1], up[2] );    drawObjects( GL_FALSE );    glPopMatrix();    glutSwapBuffers();}int main( int argc, char** argv ){     glWindowPos2f   = (PFNGLWINDOWPOS2FARBPROC)glutGetProcAddress("glWindowPos2f");    glutInit( &argc, argv );    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );    glutInitWindowSize( 512, 512 );    glutInitWindowPosition( 100, 100 );    glutCreateWindow( argv[0] );    init();    glutDisplayFunc( display );    glutReshapeFunc( reshape );    glutKeyboardFunc( keyboard );    glutIdleFunc( idle );    glutMainLoop();    return 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312

这里写图片描述

0 0