OpenGL开发环境配置-Windows/MinGW/Clion/CMake
因为某些原因,不想用过于臃肿的VS了,转而使用常用的jetbrains的CLion,Clion沿袭了jetbrans的优良传统,基本代码提示功能还是比较好的,不过就是对于windows不熟悉cmake(像我这样)的朋友可能不是太友好,经过了2个小时的查资料,终于正常运行了一个简单示例。
下面谈谈如何在Windows下配置这个开发环境。
起始,我是参考了我的前一篇OpenGL+VS开发环境的搭建,实际上除了freeglut重新下载的是MinGW版本之外,其他的文件并无区别,当然为了方便引用,我把所有相关文件都保存到了一个文件目录下,按照dll(bin),头文件(include),lib(lib)存放。
下面是我的文件目录结构
C:. │ re.txt │ ├─bin │ │ freeglut.dll │ │ glu32.dll │ │ opengl32.dll │ │ │ ├─Release │ │ ├─Win32 │ │ │ glew32.dll │ │ │ glewinfo.exe │ │ │ visualinfo.exe │ │ │ │ │ └─x64 │ │ glew32.dll │ │ glewinfo.exe │ │ visualinfo.exe │ │ │ ├─ReleaseMX │ │ ├─Win32 │ │ │ glew32mx.dll │ │ │ │ │ └─x64 │ │ glew32mx.dll │ │ │ └─x64 │ freeglut.dll │ ├─include │ │ GL.h │ │ GLU.h │ │ │ └─GL │ freeglut.h │ freeglut_ext.h │ freeglut_std.h │ glew.h │ glut.h │ glxew.h │ wglew.h │ └─lib │ GlU32.Lib │ libfreeglut.a │ libfreeglut_static.a │ OpenGL32.Lib │ ├─Release │ ├─Win32 │ │ glew32.lib │ │ glew32s.lib │ │ │ └─x64 │ glew32.lib │ glew32s.lib │ ├─ReleaseMX │ ├─Win32 │ │ glew32mx.lib │ │ glew32mxs.lib │ │ │ └─x64 │ glew32mx.lib │ glew32mxs.lib │ └─x64 libfreeglut.a libfreeglut_static.a
文件怎么放其实很随意,就是http://www.cnblogs.com/lhyz/p/4178004.html中第一步的文件按照类型放到上述三个文件夹下,下载freeglut的mingw版本后解压缩,同样将相应文件夹下的东西转移到上述文件夹下,同样也适用于glew(经过测试暂时用不到它)。
然后是最重要的,将dll的那个bin目录加入到系统的PATH环境变量下,否则程序会因为运行时检测不到依赖而退出(诡异的是build会成功,所以---呵呵)
接下来的问题就是怎么编写CMakeList.txt了
在Clion下新建项目之后会自动帮你建立CMakeList.txt和一个源文件,
我编写CMakeList.txt暂时如下:
cmake_minimum_required(VERSION 3.2) project(opengl) include_directories(C:\\\\opengl\\\\include) add_executable(opengl dinoshader.c) set(TARGET_LIB "C:\\\\opengl\\\\lib\\\\GlU32.Lib" "C:\\\\opengl\\\\lib\\\\OpenGL32.Lib" "C:\\\\opengl\\\\lib\\\\libfreeglut.a" "C:\\\\opengl\\\\lib\\\\libfreeglut_static.a" ) target_link_libraries(opengl ${TARGET_LIB})
TARGET_LIB设置的就是所有需要引用的lib和a库文件的绝对地址了,如果还有缺少的只需要再添加就好了。
下面测试文件dinoshader.c
1 /* Copyright (c) Mark J. Kilgard, 1994, 1997. */ 2 3 /* This program is freely distributable without licensing fees 4 and is provided without guarantee or warrantee expressed or 5 implied. This program is -not- in the public domain. */ 6 7 /* Example for PC game developers to show how to *combine* texturing, 8 reflections, and projected shadows all in real-time with OpenGL. 9 Robust reflections use stenciling. Robust projected shadows 10 use both stenciling and polygon offset. PC game programmers 11 should realize that neither stenciling nor polygon offset are 12 supported by Direct3D, so these real-time rendering algorithms 13 are only really viable with OpenGL. 14 15 The program has modes for disabling the stenciling and polygon 16 offset uses. It is worth running this example with these features 17 toggled off so you can see the sort of artifacts that result. 18 19 Notice that the floor texturing, reflections, and shadowing 20 all co-exist properly. */ 21 22 /* When you run this program: Left mouse button controls the 23 view. Middle mouse button controls light position (left & 24 right rotates light around dino; up & down moves light 25 position up and down). Right mouse button pops up menu. */ 26 27 /* Check out the comments in the "redraw" routine to see how the 28 reflection blending and surface stenciling is done. You can 29 also see in "redraw" how the projected shadows are rendered, 30 31 including the use of stenciling and polygon offset. */ 32 33 /* This program is derived from glutdino.c */ 34 35 /* Compile: cc -o dinoshade dinoshade.c -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */ 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <math.h> /* for cos(), sin(), and sqrt() */ 41 #include <GL/freeglut.h> /* OpenGL Utility Toolkit header */ 42 43 /* Some <math.h> files do not define M_PI... */ 44 #ifndef M_PI 45 #define M_PI 3.14159265 46 #endif 47 48 /* Variable controlling various rendering modes. */ 49 static int stencilReflection = 1, stencilShadow = 1, offsetShadow = 1; 50 static int renderShadow = 1, renderDinosaur = 1, renderReflection = 1; 51 static int linearFiltering = 0, useMipmaps = 0, useTexture = 1; 52 static int reportSpeed = 0; 53 static int animation = 1; 54 static GLboolean lightSwitch = GL_TRUE; 55 static int directionalLight = 1; 56 static int forceExtension = 0; 57 58 /* Time varying or user-controled variables. */ 59 static float jump = 0.0; 60 static float lightAngle = 0.0, lightHeight = 20; 61 GLfloat angle = -150; 62 /* in degrees */ 63 GLfloat angle2 = 30; 64 /* in degrees */ 65 66 int moving, startx, starty; 67 int lightMoving = 0, lightStartX, lightStartY; 68 69 enum { 70 MISSING, EXTENSION, ONE_DOT_ONE 71 }; 72 int polygonOffsetVersion; 73 74 static GLdouble bodyWidth = 3.0; 75 /* *INDENT-OFF* */ 76 static GLfloat body[][2] = {{0, 3}, 77 {1, 1}, 78 {5, 1}, 79 {8, 4}, 80 {10, 4}, 81 {11, 5}, 82 {11, 11.5}, 83 {13, 12}, 84 {13, 13}, 85 {10, 13.5}, 86 {13, 14}, 87 {13, 15}, 88 {11, 16}, 89 {8, 16}, 90 {7, 15}, 91 {7, 13}, 92 {8, 12}, 93 {7, 11}, 94 {6, 6}, 95 {4, 3}, 96 {3, 2}, 97 {1, 2}}; 98 static GLfloat arm[][2] = {{8, 10}, 99 {9, 9}, 100 {10, 9}, 101 {13, 8}, 102 {14, 9}, 103 {16, 9}, 104 {15, 9.5}, 105 {16, 10}, 106 {15, 10}, 107 {15.5, 11}, 108 {14.5, 10}, 109 {14, 11}, 110 {14, 10}, 111 {13, 9}, 112 {11, 11}, 113 {9, 11}}; 114 static GLfloat leg[][2] = {{8, 6}, 115 {8, 4}, 116 {9, 3}, 117 {9, 2}, 118 {8, 1}, 119 {8, 0.5}, 120 {9, 0}, 121 {12, 0}, 122 {10, 1}, 123 {10, 2}, 124 {12, 4}, 125 {11, 6}, 126 {10, 7}, 127 {9, 7}}; 128 static GLfloat eye[][2] = {{8.75, 15}, 129 {9, 14.7}, 130 {9.6, 14.7}, 131 {10.1, 15}, 132 {9.6, 15.25}, 133 {9, 15.25}}; 134 static GLfloat lightPosition[4]; 135 static GLfloat lightColor[] = {0.8, 1.0, 0.8, 1.0}; 136 /* green-tinted */ 137 static GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0}; 138 /* *INDENT-ON* */ 139 140 /* Nice floor texture tiling pattern. */ 141 static char *circles[] = { 142 "....xxxx........", 143 "..xxxxxxxx......", 144 ".xxxxxxxxxx.....", 145 ".xxx....xxx.....", 146 "xxx......xxx....", 147 "xxx......xxx....", 148 "xxx......xxx....", 149 "xxx......xxx....", 150 ".xxx....xxx.....", 151 ".xxxxxxxxxx.....", 152 "..xxxxxxxx......", 153 "....xxxx........", 154 "................", 155 "................", 156 "................", 157 "................", 158 }; 159 160 static void 161 makeFloorTexture(void) { 162 GLubyte floorTexture[16][16][3]; 163 GLubyte *loc; 164 int s, t; 165 166 /* Setup RGB image for the texture. */ 167 loc = (GLubyte *) floorTexture; 168 for (t = 0; t < 16; t++) { 169 for (s = 0; s < 16; s++) { 170 if (circles[t][s] == 'x') { 171 /* Nice green. */ 172 loc[0] = 0x1f; 173 loc[1] = 0x8f; 174 loc[2] = 0x1f; 175 } else { 176 /* Light gray. */ 177 loc[0] = 0xaa; 178 loc[1] = 0xaa; 179 loc[2] = 0xaa; 180 } 181 loc += 3; 182 } 183 } 184 185 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 186 187 if (useMipmaps) { 188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 189 GL_LINEAR_MIPMAP_LINEAR); 190 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 16, 16, 191 GL_RGB, GL_UNSIGNED_BYTE, floorTexture); 192 } else { 193 if (linearFiltering) { 194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 195 } else { 196 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 197 } 198 glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0, 199 GL_RGB, GL_UNSIGNED_BYTE, floorTexture); 200 } 201 } 202 203 enum { 204 X, Y, Z, W 205 }; 206 enum { 207 A, B, C, D 208 }; 209 210 /* Create a matrix that will project the desired shadow. */ 211 void 212 shadowMatrix(GLfloat shadowMat[4][4], 213 GLfloat groundplane[4], 214 GLfloat lightpos[4]) { 215 GLfloat dot; 216 217 /* Find dot product between light position vector and ground plane normal. */ 218 dot = groundplane[X] * lightpos[X] + 219 groundplane[Y] * lightpos[Y] + 220 groundplane[Z] * lightpos[Z] + 221 groundplane[W] * lightpos[W]; 222 223 shadowMat[0][0] = dot - lightpos[X] * groundplane[X]; 224 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y]; 225 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z]; 226 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W]; 227 228 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X]; 229 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y]; 230 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z]; 231 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W]; 232 233 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X]; 234 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y]; 235 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z]; 236 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W]; 237 238 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X]; 239 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y]; 240 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z]; 241 shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; 242 243 } 244 245 /* Find the plane equation given 3 points. */ 246 void 247 findPlane(GLfloat plane[4], 248 GLfloat v0[3], GLfloat v1[3], GLfloat v2[3]) { 249 GLfloat vec0[3], vec1[3]; 250 251 /* Need 2 vectors to find cross product. */ 252 vec0[X] = v1[X] - v0[X]; 253 vec0[Y] = v1[Y] - v0[Y]; 254 vec0[Z] = v1[Z] - v0[Z]; 255 256 vec1[X] = v2[X] - v0[X]; 257 vec1[Y] = v2[Y] - v0[Y]; 258 vec1[Z] = v2[Z] - v0[Z]; 259 260 /* find cross product to get A, B, and C of plane equation */ 261 plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y]; 262 plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]); 263 plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X]; 264 265 plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]); 266 } 267 268 void 269 extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize, 270 GLdouble thickness, GLuint side, GLuint edge, GLuint whole) { 271 static GLUtriangulatorObj *tobj = NULL; 272 GLdouble vertex[3], dx, dy, len; 273 int i; 274 int count = (int) (dataSize / (2 * sizeof(GLfloat))); 275 276 if (tobj == NULL) { 277 tobj = gluNewTess(); /* create and initialize a GLU 278 polygon tesselation object */ 279 gluTessCallback(tobj, GLU_BEGIN, glBegin); 280 gluTessCallback(tobj, GLU_VERTEX, glVertex2fv); /* semi-tricky */ 281 gluTessCallback(tobj, GLU_END, glEnd); 282 } 283 glNewList(side, GL_COMPILE); 284 glShadeModel(GL_SMOOTH); /* smooth minimizes seeing 285 tessellation */ 286 gluBeginPolygon(tobj); 287 for (i = 0; i < count; i++) { 288 vertex[0] = data[i][0]; 289 vertex[1] = data[i][1]; 290 vertex[2] = 0; 291 gluTessVertex(tobj, vertex, data[i]); 292 } 293 gluEndPolygon(tobj); 294 glEndList(); 295 glNewList(edge, GL_COMPILE); 296 glShadeModel(GL_FLAT); /* flat shade keeps angular hands 297 from being "smoothed" */ 298 glBegin(GL_QUAD_STRIP); 299 for (i = 0; i <= count; i++) { 300 /* mod function handles closing the edge */ 301 glVertex3f(data[i % count][0], data[i % count][1], 0.0); 302 glVertex3f(data[i % count][0], data[i % count][1], thickness); 303 /* Calculate a unit normal by dividing by Euclidean 304 distance. We * could be lazy and use 305 glEnable(GL_NORMALIZE) so we could pass in * arbitrary 306 normals for a very slight performance hit. */ 307 dx = data[(i + 1) % count][1] - data[i % count][1]; 308 dy = data[i % count][0] - data[(i + 1) % count][0]; 309 len = sqrt(dx * dx + dy * dy); 310 glNormal3f(dx / len, dy / len, 0.0); 311 } 312 glEnd(); 313 glEndList(); 314 glNewList(whole, GL_COMPILE); 315 glFrontFace(GL_CW); 316 glCallList(edge); 317 glNormal3f(0.0, 0.0, -1.0); /* constant normal for side */ 318 glCallList(side); 319 glPushMatrix(); 320 glTranslatef(0.0, 0.0, thickness); 321 glFrontFace(GL_CCW); 322 glNormal3f(0.0, 0.0, 1.0); /* opposite normal for other side */ 323 glCallList(side); 324 glPopMatrix(); 325 glEndList(); 326 } 327 328 /* Enumerants for refering to display lists. */ 329 typedef enum { 330 RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE, 331 LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE 332 } displayLists; 333 334 static void 335 makeDinosaur(void) { 336 extrudeSolidFromPolygon(body, sizeof(body), bodyWidth, 337 BODY_SIDE, BODY_EDGE, BODY_WHOLE); 338 extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4, 339 ARM_SIDE, ARM_EDGE, ARM_WHOLE); 340 extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2, 341 LEG_SIDE, LEG_EDGE, LEG_WHOLE); 342 extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2, 343 EYE_SIDE, EYE_EDGE, EYE_WHOLE); 344 } 345 346 static void 347 drawDinosaur(void) { 348 glPushMatrix(); 349 /* Translate the dinosaur to be at (0,8,0). */ 350 glTranslatef(-8, 0, -bodyWidth / 2); 351 glTranslatef(0.0, jump, 0.0); 352 glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor); 353 glCallList(BODY_WHOLE); 354 glTranslatef(0.0, 0.0, bodyWidth); 355 glCallList(ARM_WHOLE); 356 glCallList(LEG_WHOLE); 357 glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4); 358 glCallList(ARM_WHOLE); 359 glTranslatef(0.0, 0.0, -bodyWidth / 4); 360 glCallList(LEG_WHOLE); 361 glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1); 362 glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor); 363 glCallList(EYE_WHOLE); 364 glPopMatrix(); 365 } 366 367 static GLfloat floorVertices[4][3] = { 368 {-20.0, 0.0, 20.0}, 369 {20.0, 0.0, 20.0}, 370 {20.0, 0.0, -20.0}, 371 {-20.0, 0.0, -20.0}, 372 }; 373 374 /* Draw a floor (possibly textured). */ 375 static void 376 drawFloor(void) { 377 glDisable(GL_LIGHTING); 378 379 if (useTexture) { 380 glEnable(GL_TEXTURE_2D); 381 } 382 383 glBegin(GL_QUADS); 384 glTexCoord2f(0.0, 0.0); 385 glVertex3fv(floorVertices[0]); 386 glTexCoord2f(0.0, 16.0); 387 glVertex3fv(floorVertices[1]); 388 glTexCoord2f(16.0, 16.0); 389 glVertex3fv(floorVertices[2]); 390 glTexCoord2f(16.0, 0.0); 391 glVertex3fv(floorVertices[3]); 392 glEnd(); 393 394 if (useTexture) { 395 glDisable(GL_TEXTURE_2D); 396 } 397 398 glEnable(GL_LIGHTING); 399 } 400 401 static GLfloat floorPlane[4]; 402 static GLfloat floorShadow[4][4]; 403 404 static void 405 redraw(void) { 406 int start, end; 407 408 if (reportSpeed) { 409 start = glutGet(GLUT_ELAPSED_TIME); 410 } 411 412 /* Clear; default stencil clears to zero. */ 413 if ((stencilReflection && renderReflection) || (stencilShadow && renderShadow)) { 414 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 415 } else { 416 /* Avoid clearing stencil when not using it. */ 417 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 418 } 419 420 /* Reposition the light source. */ 421 lightPosition[0] = 12 * cos(lightAngle); 422 lightPosition[1] = lightHeight; 423 lightPosition[2] = 12 * sin(lightAngle); 424 if (directionalLight) { 425 lightPosition[3] = 0.0; 426 } else { 427 lightPosition[3] = 1.0; 428 } 429 430 shadowMatrix(floorShadow, floorPlane, lightPosition); 431 432 glPushMatrix(); 433 /* Perform scene rotations based on user mouse input. */ 434 glRotatef(angle2, 1.0, 0.0, 0.0); 435 glRotatef(angle, 0.0, 1.0, 0.0); 436 437 /* Tell GL new light source position. */ 438 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); 439 440 if (renderReflection) { 441 if (stencilReflection) { 442 /* We can eliminate the visual "artifact" of seeing the "flipped" 443 dinosaur underneath the floor by using stencil. The idea is 444 draw the floor without color or depth update but so that 445 a stencil value of one is where the floor will be. Later when 446 rendering the dinosaur reflection, we will only update pixels 447 with a stencil value of 1 to make sure the reflection only 448 lives on the floor, not below the floor. */ 449 450 /* Don't update color or depth. */ 451 glDisable(GL_DEPTH_TEST); 452 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 453 454 /* Draw 1 into the stencil buffer. */ 455 glEnable(GL_STENCIL_TEST); 456 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 457 glStencilFunc(GL_ALWAYS, 1, 0xffffffff); 458 459 /* Now render floor; floor pixels just get their stencil set to 1. */ 460 drawFloor(); 461 462 /* Re-enable update of color and depth. */ 463 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 464 glEnable(GL_DEPTH_TEST); 465 466 /* Now, only render where stencil is set to 1. */ 467 glStencilFunc(GL_EQUAL, 1, 0xffffffff); /* draw if ==1 */ 468 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 469 } 470 471 glPushMatrix(); 472 473 /* The critical reflection step: Reflect dinosaur through the floor 474 (the Y=0 plane) to make a relection. */ 475 glScalef(1.0, -1.0, 1.0); 476 477 /* Reflect the light position. */ 478 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); 479 480 /* To avoid our normals getting reversed and hence botched lighting 481 on the reflection, turn on normalize. */ 482 glEnable(GL_NORMALIZE); 483 glCullFace(GL_FRONT); 484 485 /* Draw the reflected dinosaur. */ 486 drawDinosaur(); 487 488 /* Disable noramlize again and re-enable back face culling. */ 489 glDisable(GL_NORMALIZE); 490 glCullFace(GL_BACK); 491 492 glPopMatrix(); 493 494 /* Switch back to the unreflected light position. */ 495 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); 496 497 if (stencilReflection) { 498 glDisable(GL_STENCIL_TEST); 499 } 500 } 501 502 /* Back face culling will get used to only draw either the top or the 503 bottom floor. This let's us get a floor with two distinct 504 appearances. The top floor surface is reflective and kind of red. 505 The bottom floor surface is not reflective and blue. */ 506 507 /* Draw "bottom" of floor in blue. */ 508 glFrontFace(GL_CW); /* Switch face orientation. */ 509 glColor4f(0.1, 0.1, 0.7, 1.0); 510 drawFloor(); 511 glFrontFace(GL_CCW); 512 513 if (renderShadow) { 514 if (stencilShadow) { 515 /* Draw the floor with stencil value 3. This helps us only 516 draw the shadow once per floor pixel (and only on the 517 floor pixels). */ 518 glEnable(GL_STENCIL_TEST); 519 glStencilFunc(GL_ALWAYS, 3, 0xffffffff); 520 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 521 } 522 } 523 524 /* Draw "top" of floor. Use blending to blend in reflection. */ 525 glEnable(GL_BLEND); 526 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 527 glColor4f(0.7, 0.0, 0.0, 0.3); 528 glColor4f(1.0, 1.0, 1.0, 0.3); 529 drawFloor(); 530 glDisable(GL_BLEND); 531 532 if (renderDinosaur) { 533 /* Draw "actual" dinosaur, not its reflection. */ 534 drawDinosaur(); 535 } 536 537 if (renderShadow) { 538 539 /* Render the projected shadow. */ 540 541 if (stencilShadow) { 542 543 /* Now, only render where stencil is set above 2 (ie, 3 where 544 the top floor is). Update stencil with 2 where the shadow 545 gets drawn so we don't redraw (and accidently reblend) the 546 shadow). */ 547 glStencilFunc(GL_LESS, 2, 0xffffffff); /* draw if ==1 */ 548 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 549 } 550 551 /* To eliminate depth buffer artifacts, we use polygon offset 552 to raise the depth of the projected shadow slightly so 553 that it does not depth buffer alias with the floor. */ 554 if (offsetShadow) { 555 switch (polygonOffsetVersion) { 556 case EXTENSION: 557 #ifdef GL_EXT_polygon_offset 558 glEnable(GL_POLYGON_OFFSET_EXT); 559 break; 560 #endif 561 #ifdef GL_VERSION_1_1 562 case ONE_DOT_ONE: 563 glEnable(GL_POLYGON_OFFSET_FILL); 564 break; 565 #endif 566 case MISSING: 567 /* Oh well. */ 568 break; 569 } 570 } 571 572 /* Render 50% black shadow color on top of whatever the 573 floor appareance is. */ 574 glEnable(GL_BLEND); 575 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 576 glDisable(GL_LIGHTING); /* Force the 50% black. */ 577 glColor4f(0.0, 0.0, 0.0, 0.5); 578 579 glPushMatrix(); 580 /* Project the shadow. */ 581 glMultMatrixf((GLfloat *) floorShadow); 582 drawDinosaur(); 583 glPopMatrix(); 584 585 glDisable(GL_BLEND); 586 glEnable(GL_LIGHTING); 587 588 if (offsetShadow) { 589 switch (polygonOffsetVersion) { 590 #ifdef GL_EXT_polygon_offset 591 case EXTENSION: 592 glDisable(GL_POLYGON_OFFSET_EXT); 593 break; 594 #endif 595 #ifdef GL_VERSION_1_1 596 case ONE_DOT_ONE: 597 glDisable(GL_POLYGON_OFFSET_FILL); 598 break; 599 #endif 600 case MISSING: 601 /* Oh well. */ 602 break; 603 } 604 } 605 if (stencilShadow) { 606 glDisable(GL_STENCIL_TEST); 607 } 608 } 609 610 glPushMatrix(); 611 glDisable(GL_LIGHTING); 612 glColor3f(1.0, 1.0, 0.0); 613 if (directionalLight) { 614 /* Draw an arrowhead. */ 615 glDisable(GL_CULL_FACE); 616 glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]); 617 glRotatef(lightAngle * -180.0 / M_PI, 0, 1, 0); 618 glRotatef(atan(lightHeight / 12) * 180.0 / M_PI, 0, 0, 1); 619 glBegin(GL_TRIANGLE_FAN); 620 glVertex3f(0, 0, 0); 621 glVertex3f(2, 1, 1); 622 glVertex3f(2, -1, 1); 623 glVertex3f(2, -1, -1); 624 glVertex3f(2, 1, -1); 625 glVertex3f(2, 1, 1); 626 glEnd(); 627 /* Draw a white line from light direction. */ 628 glColor3f(1.0, 1.0, 1.0); 629 glBegin(GL_LINES); 630 glVertex3f(0, 0, 0); 631 glVertex3f(5, 0, 0); 632 glEnd(); 633 glEnable(GL_CULL_FACE); 634 } else { 635 /* Draw a yellow ball at the light source. */ 636 glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]); 637 glutSolidSphere(1.0, 5, 5); 638 } 639 glEnable(GL_LIGHTING); 640 glPopMatrix(); 641 642 glPopMatrix(); 643 644 if (reportSpeed) { 645 glFinish(); 646 end = glutGet(GLUT_ELAPSED_TIME); 647 printf("Speed %.3g frames/sec (%d ms)\n", 1000.0 / (end - start), end - start); 648 } 649 650 glutSwapBuffers(); 651 } 652 653 /* ARGSUSED2 */ 654 static void 655 mouse(int button, int state, int x, int y) { 656 if (button == GLUT_LEFT_BUTTON) { 657 if (state == GLUT_DOWN) { 658 moving = 1; 659 startx = x; 660 starty = y; 661 } 662 if (state == GLUT_UP) { 663 moving = 0; 664 } 665 } 666 if (button == GLUT_MIDDLE_BUTTON) { 667 if (state == GLUT_DOWN) { 668 lightMoving = 1; 669 lightStartX = x; 670 lightStartY = y; 671 } 672 if (state == GLUT_UP) { 673 lightMoving = 0; 674 } 675 } 676 } 677 678 /* ARGSUSED1 */ 679 static void 680 motion(int x, int y) { 681 if (moving) { 682 angle = angle + (x - startx); 683 angle2 = angle2 + (y - starty); 684 startx = x; 685 starty = y; 686 glutPostRedisplay(); 687 } 688 if (lightMoving) { 689 lightAngle += (x - lightStartX) / 40.0; 690 lightHeight += (lightStartY - y) / 20.0; 691 lightStartX = x; 692 lightStartY = y; 693 glutPostRedisplay(); 694 } 695 } 696 697 /* Advance time varying state when idle callback registered. */ 698 static void 699 idle(void) { 700 static float time = 0.0; 701 702 time = glutGet(GLUT_ELAPSED_TIME) / 500.0; 703 704 jump = 4.0 * fabs(sin(time) * 0.5); 705 if (!lightMoving) { 706 lightAngle += 0.03; 707 } 708 glutPostRedisplay(); 709 } 710 711 enum { 712 M_NONE, M_MOTION, M_LIGHT, M_TEXTURE, M_SHADOWS, M_REFLECTION, M_DINOSAUR, 713 M_STENCIL_REFLECTION, M_STENCIL_SHADOW, M_OFFSET_SHADOW, 714 M_POSITIONAL, M_DIRECTIONAL, M_PERFORMANCE 715 }; 716 717 static void 718 controlLights(int value) { 719 switch (value) { 720 case M_NONE: 721 return; 722 case M_MOTION: 723 animation = 1 - animation; 724 if (animation) { 725 glutIdleFunc(idle); 726 } else { 727 glutIdleFunc(NULL); 728 } 729 break; 730 case M_LIGHT: 731 lightSwitch = !lightSwitch; 732 if (lightSwitch) { 733 glEnable(GL_LIGHT0); 734 } else { 735 glDisable(GL_LIGHT0); 736 } 737 break; 738 case M_TEXTURE: 739 useTexture = !useTexture; 740 break; 741 case M_SHADOWS: 742 renderShadow = 1 - renderShadow; 743 break; 744 case M_REFLECTION: 745 renderReflection = 1 - renderReflection; 746 break; 747 case M_DINOSAUR: 748 renderDinosaur = 1 - renderDinosaur; 749 break; 750 case M_STENCIL_REFLECTION: 751 stencilReflection = 1 - stencilReflection; 752 break; 753 case M_STENCIL_SHADOW: 754 stencilShadow = 1 - stencilShadow; 755 break; 756 case M_OFFSET_SHADOW: 757 offsetShadow = 1 - offsetShadow; 758 break; 759 case M_POSITIONAL: 760 directionalLight = 0; 761 break; 762 case M_DIRECTIONAL: 763 directionalLight = 1; 764 break; 765 case M_PERFORMANCE: 766 reportSpeed = 1 - reportSpeed; 767 break; 768 } 769 glutPostRedisplay(); 770 } 771 772 /* When not visible, stop animating. Restart when visible again. */ 773 static void 774 visible(int vis) { 775 if (vis == GLUT_VISIBLE) { 776 if (animation) 777 glutIdleFunc(idle); 778 } else { 779 if (!animation) 780 glutIdleFunc(NULL); 781 } 782 } 783 784 /* Press any key to redraw; good when motion stopped and 785 performance reporting on. */ 786 /* ARGSUSED */ 787 static void 788 key(unsigned char c, int x, int y) { 789 if (c == 27) { 790 exit(0); /* IRIS GLism, Escape quits. */ 791 } 792 glutPostRedisplay(); 793 } 794 795 /* Press any key to redraw; good when motion stopped and 796 performance reporting on. */ 797 /* ARGSUSED */ 798 static void 799 special(int k, int x, int y) { 800 glutPostRedisplay(); 801 } 802 803 static int 804 supportsOneDotOne(void) { 805 const char *version; 806 int major, minor; 807 808 version = (char *) glGetString(GL_VERSION); 809 if (sscanf(version, "%d.%d", &major, &minor) == 2) 810 return major >= 1 && minor >= 1; 811 return 0; /* OpenGL version string malformed! */ 812 } 813 814 int 815 main(int argc, char **argv) { 816 int i; 817 818 glutInit(&argc, argv); 819 820 for (i = 1; i < argc; i++) { 821 if (!strcmp("-linear", argv[i])) { 822 linearFiltering = 1; 823 } else if (!strcmp("-mipmap", argv[i])) { 824 useMipmaps = 1; 825 } else if (!strcmp("-ext", argv[i])) { 826 forceExtension = 1; 827 } 828 } 829 830 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL | GLUT_MULTISAMPLE); 831 832 #if 1 833 /* In GLUT 4.0, you'll be able to do this an be sure to 834 get 2 bits of stencil if the machine has it for you. */ 835 glutInitDisplayString("samples stencil>=2 rgb double depth"); 836 #endif 837 838 glutCreateWindow("Shadowy Leapin' Lizards"); 839 840 if (glutGet(GLUT_WINDOW_STENCIL_SIZE) <= 1) { 841 printf("dinoshade: Sorry, I need at least 2 bits of stencil.\n"); 842 exit(1); 843 } 844 845 /* Register GLUT callbacks. */ 846 glutDisplayFunc(redraw); 847 glutMouseFunc(mouse); 848 glutMotionFunc(motion); 849 glutVisibilityFunc(visible); 850 glutKeyboardFunc(key); 851 glutSpecialFunc(special); 852 853 glutCreateMenu(controlLights); 854 855 glutAddMenuEntry("Toggle motion", M_MOTION); 856 glutAddMenuEntry("-----------------------", M_NONE); 857 glutAddMenuEntry("Toggle light", M_LIGHT); 858 glutAddMenuEntry("Toggle texture", M_TEXTURE); 859 glutAddMenuEntry("Toggle shadows", M_SHADOWS); 860 glutAddMenuEntry("Toggle reflection", M_REFLECTION); 861 glutAddMenuEntry("Toggle dinosaur", M_DINOSAUR); 862 glutAddMenuEntry("-----------------------", M_NONE); 863 glutAddMenuEntry("Toggle reflection stenciling", M_STENCIL_REFLECTION); 864 glutAddMenuEntry("Toggle shadow stenciling", M_STENCIL_SHADOW); 865 glutAddMenuEntry("Toggle shadow offset", M_OFFSET_SHADOW); 866 glutAddMenuEntry("----------------------", M_NONE); 867 glutAddMenuEntry("Positional light", M_POSITIONAL); 868 glutAddMenuEntry("Directional light", M_DIRECTIONAL); 869 glutAddMenuEntry("-----------------------", M_NONE); 870 glutAddMenuEntry("Toggle performance", M_PERFORMANCE); 871 glutAttachMenu(GLUT_RIGHT_BUTTON); 872 makeDinosaur(); 873 874 #ifdef GL_VERSION_1_1 875 if (supportsOneDotOne() && !forceExtension) { 876 polygonOffsetVersion = ONE_DOT_ONE; 877 glPolygonOffset(-2.0, -1.0); 878 } else 879 #endif 880 { 881 #ifdef GL_EXT_polygon_offset 882 /* check for the polygon offset extension */ 883 if (glutExtensionSupported("GL_EXT_polygon_offset")) { 884 polygonOffsetVersion = EXTENSION; 885 glPolygonOffsetEXT(-0.1, -0.002); 886 } else 887 #endif 888 { 889 polygonOffsetVersion = MISSING; 890 printf("\ndinoshine: Missing polygon offset.\n"); 891 printf(" Expect shadow depth aliasing artifacts.\n\n"); 892 } 893 } 894 895 glEnable(GL_CULL_FACE); 896 glEnable(GL_DEPTH_TEST); 897 glEnable(GL_TEXTURE_2D); 898 glLineWidth(3.0); 899 900 glMatrixMode(GL_PROJECTION); 901 gluPerspective( /* field of view in degree */ 40.0, 902 /* aspect ratio */ 1.0, 903 /* Z near */ 20.0, /* Z far */ 100.0); 904 glMatrixMode(GL_MODELVIEW); 905 gluLookAt(0.0, 8.0, 60.0, /* eye is at (0,8,60) */ 906 0.0, 8.0, 0.0, /* center is at (0,8,0) */ 907 0.0, 1.0, 0.); /* up is in postivie Y direction */ 908 909 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); 910 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); 911 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1); 912 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05); 913 glEnable(GL_LIGHT0); 914 glEnable(GL_LIGHTING); 915 916 makeFloorTexture(); 917 918 /* Setup floor plane for projected shadow calculations. */ 919 findPlane(floorPlane, floorVertices[1], floorVertices[2], floorVertices[3]); 920 921 glutMainLoop(); 922 return 0; /* ANSI C requires main to return int. */ 923 }
不得不说我找的sample还是太老了,凑合看吧,至少能够测试就好了,因为暂时没有继续学习opengl的打算,所以只能配置到这里了,想要我的opengl目录下文件的可以用QQ找我,我可以把压缩包传给你。
好了,看看结果就知道是否完成了。
OK,暂时就是这样。稍后几天有空的话我会试着重新建立opencv的环境。