Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

shadowtex.c 29KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. /*
  2. * Shadow demo using the GL_ARB_depth_texture, GL_ARB_shadow and
  3. * GL_ARB_shadow_ambient extensions.
  4. *
  5. * Brian Paul
  6. * 19 Feb 2001
  7. *
  8. * Added GL_EXT_shadow_funcs support on 23 March 2002
  9. * Added GL_EXT_packed_depth_stencil support on 15 March 2006.
  10. * Added GL_EXT_framebuffer_object support on 27 March 2006.
  11. * Removed old SGIX extension support on 5 April 2006.
  12. * Added vertex / fragment program support on 7 June 2007 (Ian Romanick).
  13. *
  14. * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
  15. *
  16. * Permission is hereby granted, free of charge, to any person obtaining a
  17. * copy of this software and associated documentation files (the "Software"),
  18. * to deal in the Software without restriction, including without limitation
  19. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  20. * and/or sell copies of the Software, and to permit persons to whom the
  21. * Software is furnished to do so, subject to the following conditions:
  22. *
  23. * The above copyright notice and this permission notice shall be included
  24. * in all copies or substantial portions of the Software.
  25. *
  26. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  27. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  28. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  29. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  30. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  31. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  32. */
  33. #include <assert.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <math.h>
  38. #include <GL/glew.h>
  39. #include <GL/glut.h>
  40. #include "showbuffer.h"
  41. #define DEG_TO_RAD (3.14159 / 180.0)
  42. static GLint WindowWidth = 450, WindowHeight = 300;
  43. static GLfloat Xrot = 15, Yrot = 0, Zrot = 0;
  44. static GLfloat Red[4] = {1, 0, 0, 1};
  45. static GLfloat Green[4] = {0, 1, 0, 1};
  46. static GLfloat Blue[4] = {0, 0, 1, 1};
  47. static GLfloat Yellow[4] = {1, 1, 0, 1};
  48. static GLfloat LightDist = 10;
  49. static GLfloat LightLatitude = 45.0;
  50. static GLfloat LightLongitude = 45.0;
  51. static GLfloat LightPos[4];
  52. static GLfloat SpotDir[3];
  53. static GLfloat SpotAngle = 40.0 * DEG_TO_RAD;
  54. static GLfloat ShadowNear = 4.0, ShadowFar = 24.0;
  55. static GLint ShadowTexWidth = 256, ShadowTexHeight = 256;
  56. static GLboolean LinearFilter = GL_FALSE;
  57. static GLfloat Bias = -0.06;
  58. static GLboolean Anim = GL_TRUE;
  59. static GLboolean NeedNewShadowMap = GL_FALSE;
  60. static GLuint ShadowTexture, GrayTexture;
  61. static GLuint ShadowFBO;
  62. static GLfloat lightModelview[16];
  63. static GLfloat lightProjection[16];
  64. static GLuint vert_prog;
  65. static GLuint frag_progs[3];
  66. static GLuint curr_frag = 0;
  67. static GLuint max_frag = 1;
  68. #define NUM_FRAG_MODES 3
  69. static const char *FragProgNames[] = {
  70. "fixed-function",
  71. "program without \"OPTION ARB_fragment_program_shadow\"",
  72. "program with \"OPTION ARB_fragment_program_shadow\"",
  73. };
  74. static GLboolean HaveShadow = GL_FALSE;
  75. static GLboolean HaveFBO = GL_FALSE;
  76. static GLboolean UseFBO = GL_FALSE;
  77. static GLboolean HaveVP = GL_FALSE;
  78. static GLboolean HaveFP = GL_FALSE;
  79. static GLboolean HaveFP_Shadow = GL_FALSE;
  80. static GLboolean UseVP = GL_FALSE;
  81. static GLboolean HavePackedDepthStencil = GL_FALSE;
  82. static GLboolean UsePackedDepthStencil = GL_FALSE;
  83. static GLboolean HaveEXTshadowFuncs = GL_FALSE;
  84. static GLboolean HaveShadowAmbient = GL_FALSE;
  85. static GLint Operator = 0;
  86. static const GLenum OperatorFunc[8] = {
  87. GL_LEQUAL, GL_LESS, GL_GEQUAL, GL_GREATER,
  88. GL_EQUAL, GL_NOTEQUAL, GL_ALWAYS, GL_NEVER };
  89. static const char *OperatorName[8] = {
  90. "GL_LEQUAL", "GL_LESS", "GL_GEQUAL", "GL_GREATER",
  91. "GL_EQUAL", "GL_NOTEQUAL", "GL_ALWAYS", "GL_NEVER" };
  92. static GLuint DisplayMode;
  93. #define SHOW_SHADOWS 0
  94. #define SHOW_DEPTH_IMAGE 1
  95. #define SHOW_DEPTH_MAPPING 2
  96. #define SHOW_DISTANCE 3
  97. #define MAT4_MUL(dest_vec, src_mat, src_vec) \
  98. "DP4 " dest_vec ".x, " src_mat "[0], " src_vec ";\n" \
  99. "DP4 " dest_vec ".y, " src_mat "[1], " src_vec ";\n" \
  100. "DP4 " dest_vec ".z, " src_mat "[2], " src_vec ";\n" \
  101. "DP4 " dest_vec ".w, " src_mat "[3], " src_vec ";\n"
  102. #define MAT3_MUL(dest_vec, src_mat, src_vec) \
  103. "DP3 " dest_vec ".x, " src_mat "[0], " src_vec ";\n" \
  104. "DP3 " dest_vec ".y, " src_mat "[1], " src_vec ";\n" \
  105. "DP3 " dest_vec ".z, " src_mat "[2], " src_vec ";\n"
  106. #define NORMALIZE(dest, src) \
  107. "DP3 " dest ".w, " src ", " src ";\n" \
  108. "RSQ " dest ".w, " dest ".w;\n" \
  109. "MUL " dest ", " src ", " dest ".w;\n"
  110. /**
  111. * Vertex program for shadow mapping.
  112. */
  113. static const char vert_code[] =
  114. "!!ARBvp1.0\n"
  115. "ATTRIB iPos = vertex.position;\n"
  116. "ATTRIB iNorm = vertex.normal;\n"
  117. "PARAM mvinv[4] = { state.matrix.modelview.invtrans };\n"
  118. "PARAM mvp[4] = { state.matrix.mvp };\n"
  119. "PARAM mv[4] = { state.matrix.modelview };\n"
  120. "PARAM texmat[4] = { state.matrix.texture[0] };\n"
  121. "PARAM lightPos = state.light[0].position;\n"
  122. "PARAM ambientCol = state.lightprod[0].ambient;\n"
  123. "PARAM diffuseCol = state.lightprod[0].diffuse;\n"
  124. "TEMP n, lightVec;\n"
  125. "ALIAS V = lightVec;\n"
  126. "ALIAS NdotL = n;\n"
  127. "OUTPUT oPos = result.position;\n"
  128. "OUTPUT oColor = result.color;\n"
  129. "OUTPUT oTex = result.texcoord[0];\n"
  130. /* Transform the vertex to clip coordinates. */
  131. MAT4_MUL("oPos", "mvp", "iPos")
  132. /* Transform the vertex to eye coordinates. */
  133. MAT4_MUL("V", "mv", "iPos")
  134. /* Transform the vertex to projected light coordinates. */
  135. MAT4_MUL("oTex", "texmat", "iPos")
  136. /* Transform the normal to eye coordinates. */
  137. MAT3_MUL("n", "mvinv", "iNorm")
  138. /* Calculate the vector from the vertex to the light in eye
  139. * coordinates.
  140. */
  141. "SUB lightVec, lightPos, V;\n"
  142. NORMALIZE("lightVec", "lightVec")
  143. /* Compute diffuse lighting coefficient.
  144. */
  145. "DP3 NdotL.x, n, lightVec;\n"
  146. "MAX NdotL.x, NdotL.x, {0.0};\n"
  147. "MIN NdotL.x, NdotL.x, {1.0};\n"
  148. /* Accumulate color contributions.
  149. */
  150. "MOV oColor, diffuseCol;\n"
  151. "MAD oColor.xyz, NdotL.x, diffuseCol, ambientCol;\n"
  152. "END\n"
  153. ;
  154. static const char frag_code[] =
  155. "!!ARBfp1.0\n"
  156. "TEMP shadow, temp;\n"
  157. "TXP shadow, fragment.texcoord[0], texture[0], 2D;\n"
  158. "RCP temp.x, fragment.texcoord[0].w;\n"
  159. "MUL temp.x, temp.x, fragment.texcoord[0].z;\n"
  160. "SGE shadow, shadow.x, temp.x;\n"
  161. "MUL result.color.rgb, fragment.color, shadow.x;\n"
  162. "MOV result.color.a, fragment.color;\n"
  163. "END\n"
  164. ;
  165. static const char frag_shadow_code[] =
  166. "!!ARBfp1.0\n"
  167. "OPTION ARB_fragment_program_shadow;\n"
  168. "TEMP shadow;\n"
  169. "TXP shadow, fragment.texcoord[0], texture[0], SHADOW2D;\n"
  170. "MUL result.color.rgb, fragment.color, shadow.x;\n"
  171. "MOV result.color.a, fragment.color.a;\n"
  172. "END\n"
  173. ;
  174. static void
  175. DrawScene(void)
  176. {
  177. GLfloat k = 6;
  178. /* sphere */
  179. glPushMatrix();
  180. glTranslatef(1.6, 2.2, 2.7);
  181. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Green);
  182. glColor4fv(Green);
  183. glutSolidSphere(1.5, 15, 15);
  184. glPopMatrix();
  185. /* dodecahedron */
  186. glPushMatrix();
  187. glTranslatef(-2.0, 1.2, 2.1);
  188. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red);
  189. glColor4fv(Red);
  190. glutSolidDodecahedron();
  191. glPopMatrix();
  192. /* icosahedron */
  193. glPushMatrix();
  194. glTranslatef(-0.6, 1.3, -0.5);
  195. glScalef(1.5, 1.5, 1.5);
  196. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Yellow);
  197. glColor4fv(Red);
  198. glutSolidIcosahedron();
  199. glPopMatrix();
  200. /* a plane */
  201. glPushMatrix();
  202. glTranslatef(0, -1.1, 0);
  203. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue);
  204. glColor4fv(Blue);
  205. glNormal3f(0, 1, 0);
  206. glBegin(GL_POLYGON);
  207. glVertex3f(-k, 0, -k);
  208. glVertex3f( k, 0, -k);
  209. glVertex3f( k, 0, k);
  210. glVertex3f(-k, 0, k);
  211. glEnd();
  212. glPopMatrix();
  213. }
  214. /**
  215. * Calculate modelview and project matrices for the light
  216. *
  217. * Stores the results in \c lightProjection (projection matrix) and
  218. * \c lightModelview (modelview matrix).
  219. */
  220. static void
  221. MakeShadowMatrix(const GLfloat lightPos[4], const GLfloat spotDir[3],
  222. GLfloat spotAngle, GLfloat shadowNear, GLfloat shadowFar)
  223. {
  224. /* compute frustum to enclose spot light cone */
  225. const GLfloat d = shadowNear * tan(spotAngle);
  226. glMatrixMode(GL_PROJECTION);
  227. glPushMatrix();
  228. glLoadIdentity();
  229. glFrustum(-d, d, -d, d, shadowNear, shadowFar);
  230. glGetFloatv(GL_PROJECTION_MATRIX, lightProjection);
  231. glPopMatrix();
  232. glMatrixMode(GL_MODELVIEW);
  233. glPushMatrix();
  234. glLoadIdentity();
  235. gluLookAt(lightPos[0], lightPos[1], lightPos[2],
  236. lightPos[0] + spotDir[0],
  237. lightPos[1] + spotDir[1],
  238. lightPos[2] + spotDir[2],
  239. 0.0, 1.0, 0.0);
  240. glGetFloatv(GL_MODELVIEW_MATRIX, lightModelview);
  241. glPopMatrix();
  242. }
  243. /**
  244. * Load \c GL_TEXTURE matrix with light's MVP matrix.
  245. */
  246. static void SetShadowTextureMatrix(void)
  247. {
  248. static const GLfloat biasMatrix[16] = {
  249. 0.5, 0.0, 0.0, 0.0,
  250. 0.0, 0.5, 0.0, 0.0,
  251. 0.0, 0.0, 0.5, 0.0,
  252. 0.5, 0.5, 0.5, 1.0,
  253. };
  254. glMatrixMode(GL_TEXTURE);
  255. glLoadMatrixf(biasMatrix);
  256. glTranslatef(0.0, 0.0, Bias);
  257. glMultMatrixf(lightProjection);
  258. glMultMatrixf(lightModelview);
  259. glMatrixMode(GL_MODELVIEW);
  260. }
  261. static void
  262. EnableIdentityTexgen(void)
  263. {
  264. /* texgen so that texcoord = vertex coord */
  265. static GLfloat sPlane[4] = { 1, 0, 0, 0 };
  266. static GLfloat tPlane[4] = { 0, 1, 0, 0 };
  267. static GLfloat rPlane[4] = { 0, 0, 1, 0 };
  268. static GLfloat qPlane[4] = { 0, 0, 0, 1 };
  269. glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
  270. glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
  271. glTexGenfv(GL_R, GL_EYE_PLANE, rPlane);
  272. glTexGenfv(GL_Q, GL_EYE_PLANE, qPlane);
  273. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  274. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  275. glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  276. glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  277. glEnable(GL_TEXTURE_GEN_S);
  278. glEnable(GL_TEXTURE_GEN_T);
  279. glEnable(GL_TEXTURE_GEN_R);
  280. glEnable(GL_TEXTURE_GEN_Q);
  281. }
  282. /*
  283. * Setup 1-D texgen so that the distance from the light source, between
  284. * the near and far planes maps to s=0 and s=1. When we draw the scene,
  285. * the grayness will indicate the fragment's distance from the light
  286. * source.
  287. */
  288. static void
  289. EnableDistanceTexgen(const GLfloat lightPos[4], const GLfloat lightDir[3],
  290. GLfloat lightNear, GLfloat lightFar)
  291. {
  292. GLfloat m, d;
  293. GLfloat sPlane[4];
  294. GLfloat nearPoint[3];
  295. m = sqrt(lightDir[0] * lightDir[0] +
  296. lightDir[1] * lightDir[1] +
  297. lightDir[2] * lightDir[2]);
  298. d = lightFar - lightNear;
  299. /* nearPoint = point on light direction vector which intersects the
  300. * near plane of the light frustum.
  301. */
  302. nearPoint[0] = lightPos[0] + lightDir[0] / m * lightNear;
  303. nearPoint[1] = lightPos[1] + lightDir[1] / m * lightNear;
  304. nearPoint[2] = lightPos[2] + lightDir[2] / m * lightNear;
  305. sPlane[0] = lightDir[0] / d / m;
  306. sPlane[1] = lightDir[1] / d / m;
  307. sPlane[2] = lightDir[2] / d / m;
  308. sPlane[3] = -(sPlane[0] * nearPoint[0]
  309. + sPlane[1] * nearPoint[1]
  310. + sPlane[2] * nearPoint[2]);
  311. glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
  312. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  313. glEnable(GL_TEXTURE_GEN_S);
  314. }
  315. static void
  316. DisableTexgen(void)
  317. {
  318. glDisable(GL_TEXTURE_GEN_S);
  319. glDisable(GL_TEXTURE_GEN_T);
  320. glDisable(GL_TEXTURE_GEN_R);
  321. glDisable(GL_TEXTURE_GEN_Q);
  322. }
  323. static void
  324. ComputeLightPos(GLfloat dist, GLfloat latitude, GLfloat longitude,
  325. GLfloat pos[4], GLfloat dir[3])
  326. {
  327. pos[0] = dist * sin(longitude * DEG_TO_RAD);
  328. pos[1] = dist * sin(latitude * DEG_TO_RAD);
  329. pos[2] = dist * cos(latitude * DEG_TO_RAD) * cos(longitude * DEG_TO_RAD);
  330. pos[3] = 1;
  331. dir[0] = -pos[0];
  332. dir[1] = -pos[1];
  333. dir[2] = -pos[2];
  334. }
  335. /**
  336. * Render the shadow map / depth texture.
  337. * The result will be in the texture object named ShadowTexture.
  338. */
  339. static void
  340. RenderShadowMap(void)
  341. {
  342. GLenum depthFormat; /* GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL_EXT */
  343. GLenum depthType; /* GL_UNSIGNED_INT_24_8_EXT or GL_UNSIGNED_INT */
  344. if (WindowWidth >= 1024 && WindowHeight >= 1024) {
  345. ShadowTexWidth = ShadowTexHeight = 1024;
  346. }
  347. else if (WindowWidth >= 512 && WindowHeight >= 512) {
  348. ShadowTexWidth = ShadowTexHeight = 512;
  349. }
  350. else if (WindowWidth >= 256 && WindowHeight >= 256) {
  351. ShadowTexWidth = ShadowTexHeight = 256;
  352. }
  353. else {
  354. ShadowTexWidth = ShadowTexHeight = 128;
  355. }
  356. printf("Rendering %d x %d depth texture\n", ShadowTexWidth, ShadowTexHeight);
  357. if (UsePackedDepthStencil) {
  358. depthFormat = GL_DEPTH_STENCIL_EXT;
  359. depthType = GL_UNSIGNED_INT_24_8_EXT;
  360. }
  361. else {
  362. depthFormat = GL_DEPTH_COMPONENT;
  363. depthType = GL_UNSIGNED_INT;
  364. }
  365. glMatrixMode(GL_PROJECTION);
  366. glLoadMatrixf(lightProjection);
  367. glMatrixMode(GL_MODELVIEW);
  368. glLoadMatrixf(lightModelview);
  369. if (UseFBO) {
  370. GLenum fbo_status;
  371. glTexImage2D(GL_TEXTURE_2D, 0, depthFormat,
  372. ShadowTexWidth, ShadowTexHeight, 0,
  373. depthFormat, depthType, NULL);
  374. /* Set the filter mode so that the texture is texture-complete.
  375. * Otherwise it will cause the framebuffer to fail the framebuffer
  376. * completeness test.
  377. */
  378. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  379. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShadowFBO);
  380. glDrawBuffer(GL_NONE);
  381. glReadBuffer(GL_NONE);
  382. fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
  383. if (fbo_status != GL_FRAMEBUFFER_COMPLETE_EXT) {
  384. fprintf(stderr, "FBO not complete! status = 0x%04x\n", fbo_status);
  385. assert(fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT);
  386. }
  387. }
  388. assert(!glIsEnabled(GL_TEXTURE_1D));
  389. assert(!glIsEnabled(GL_TEXTURE_2D));
  390. glViewport(0, 0, ShadowTexWidth, ShadowTexHeight);
  391. glClear(GL_DEPTH_BUFFER_BIT);
  392. glEnable(GL_DEPTH_TEST);
  393. DrawScene();
  394. if (UseFBO) {
  395. /* all done! */
  396. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  397. }
  398. else {
  399. /*
  400. * copy depth buffer into the texture map
  401. */
  402. if (DisplayMode == SHOW_DEPTH_MAPPING) {
  403. /* load depth image as gray-scale luminance texture */
  404. GLuint *depth = (GLuint *)
  405. malloc(ShadowTexWidth * ShadowTexHeight * sizeof(GLuint));
  406. assert(depth);
  407. glReadPixels(0, 0, ShadowTexWidth, ShadowTexHeight,
  408. depthFormat, depthType, depth);
  409. glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
  410. ShadowTexWidth, ShadowTexHeight, 0,
  411. GL_LUMINANCE, GL_UNSIGNED_INT, depth);
  412. free(depth);
  413. }
  414. else {
  415. /* The normal shadow case - a real depth texture */
  416. glCopyTexImage2D(GL_TEXTURE_2D, 0, depthFormat,
  417. 0, 0, ShadowTexWidth, ShadowTexHeight, 0);
  418. if (UsePackedDepthStencil) {
  419. /* debug check */
  420. GLint intFormat;
  421. glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
  422. GL_TEXTURE_INTERNAL_FORMAT, &intFormat);
  423. assert(intFormat == GL_DEPTH_STENCIL_EXT);
  424. }
  425. }
  426. }
  427. }
  428. /**
  429. * Show the shadow map as a grayscale image.
  430. */
  431. static void
  432. ShowShadowMap(void)
  433. {
  434. glClear(GL_COLOR_BUFFER_BIT);
  435. glMatrixMode(GL_TEXTURE);
  436. glLoadIdentity();
  437. glMatrixMode(GL_PROJECTION);
  438. glLoadIdentity();
  439. glOrtho(0, WindowWidth, 0, WindowHeight, -1, 1);
  440. glMatrixMode(GL_MODELVIEW);
  441. glLoadIdentity();
  442. glDisable(GL_DEPTH_TEST);
  443. glDisable(GL_LIGHTING);
  444. glEnable(GL_TEXTURE_2D);
  445. DisableTexgen();
  446. /* interpret texture's depth values as luminance values */
  447. if (HaveShadow) {
  448. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
  449. }
  450. glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
  451. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  452. glBegin(GL_POLYGON);
  453. glTexCoord2f(0, 0); glVertex2f(0, 0);
  454. glTexCoord2f(1, 0); glVertex2f(ShadowTexWidth, 0);
  455. glTexCoord2f(1, 1); glVertex2f(ShadowTexWidth, ShadowTexHeight);
  456. glTexCoord2f(0, 1); glVertex2f(0, ShadowTexHeight);
  457. glEnd();
  458. glDisable(GL_TEXTURE_2D);
  459. glEnable(GL_DEPTH_TEST);
  460. glEnable(GL_LIGHTING);
  461. }
  462. /**
  463. * Redraw window image
  464. */
  465. static void
  466. Display(void)
  467. {
  468. GLenum error;
  469. ComputeLightPos(LightDist, LightLatitude, LightLongitude,
  470. LightPos, SpotDir);
  471. if (NeedNewShadowMap) {
  472. MakeShadowMatrix(LightPos, SpotDir, SpotAngle, ShadowNear, ShadowFar);
  473. RenderShadowMap();
  474. NeedNewShadowMap = GL_FALSE;
  475. }
  476. glViewport(0, 0, WindowWidth, WindowHeight);
  477. if (DisplayMode == SHOW_DEPTH_IMAGE) {
  478. ShowShadowMap();
  479. }
  480. else {
  481. /* prepare to draw scene from camera's view */
  482. const GLfloat ar = (GLfloat) WindowWidth / (GLfloat) WindowHeight;
  483. glMatrixMode(GL_PROJECTION);
  484. glLoadIdentity();
  485. glFrustum(-ar, ar, -1.0, 1.0, 4.0, 50.0);
  486. glMatrixMode(GL_MODELVIEW);
  487. glLoadIdentity();
  488. glTranslatef(0.0, 0.0, -22.0);
  489. glRotatef(Xrot, 1, 0, 0);
  490. glRotatef(Yrot, 0, 1, 0);
  491. glRotatef(Zrot, 0, 0, 1);
  492. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  493. glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
  494. if (LinearFilter) {
  495. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  496. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  497. }
  498. else {
  499. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  500. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  501. }
  502. if (DisplayMode == SHOW_DEPTH_MAPPING) {
  503. if (HaveShadow) {
  504. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
  505. }
  506. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  507. glEnable(GL_TEXTURE_2D);
  508. SetShadowTextureMatrix();
  509. EnableIdentityTexgen();
  510. }
  511. else if (DisplayMode == SHOW_DISTANCE) {
  512. glMatrixMode(GL_TEXTURE);
  513. glLoadIdentity();
  514. glMatrixMode(GL_MODELVIEW);
  515. EnableDistanceTexgen(LightPos, SpotDir, ShadowNear+Bias, ShadowFar);
  516. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  517. glEnable(GL_TEXTURE_1D);
  518. assert(!glIsEnabled(GL_TEXTURE_2D));
  519. }
  520. else {
  521. assert(DisplayMode == SHOW_SHADOWS);
  522. if (HaveShadow) {
  523. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
  524. GL_COMPARE_R_TO_TEXTURE_ARB);
  525. }
  526. if (curr_frag > 0) {
  527. glEnable(GL_FRAGMENT_PROGRAM_ARB);
  528. }
  529. else {
  530. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  531. }
  532. glEnable(GL_TEXTURE_2D);
  533. SetShadowTextureMatrix();
  534. if (UseVP) {
  535. glEnable(GL_VERTEX_PROGRAM_ARB);
  536. }
  537. else {
  538. glEnable(GL_LIGHTING);
  539. EnableIdentityTexgen();
  540. }
  541. }
  542. DrawScene();
  543. if (UseVP) {
  544. glDisable(GL_VERTEX_PROGRAM_ARB);
  545. }
  546. else {
  547. DisableTexgen();
  548. glDisable(GL_LIGHTING);
  549. }
  550. if (curr_frag > 0) {
  551. glDisable(GL_FRAGMENT_PROGRAM_ARB);
  552. }
  553. glDisable(GL_TEXTURE_1D);
  554. glDisable(GL_TEXTURE_2D);
  555. }
  556. glutSwapBuffers();
  557. error = glGetError();
  558. if (error) {
  559. printf("GL Error: %s\n", (char *) gluErrorString(error));
  560. }
  561. }
  562. static void
  563. Reshape(int width, int height)
  564. {
  565. WindowWidth = width;
  566. WindowHeight = height;
  567. NeedNewShadowMap = GL_TRUE;
  568. }
  569. static void
  570. Idle(void)
  571. {
  572. static double t0 = -1.;
  573. double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
  574. if (t0 < 0.0)
  575. t0 = t;
  576. dt = t - t0;
  577. t0 = t;
  578. Yrot += 75.0 * dt;
  579. /*LightLongitude -= 5.0;*/
  580. glutPostRedisplay();
  581. }
  582. static void
  583. Key(unsigned char key, int x, int y)
  584. {
  585. const GLfloat step = 3.0;
  586. (void) x;
  587. (void) y;
  588. switch (key) {
  589. case 'a':
  590. Anim = !Anim;
  591. if (Anim)
  592. glutIdleFunc(Idle);
  593. else
  594. glutIdleFunc(NULL);
  595. break;
  596. case 'b':
  597. Bias -= 0.01;
  598. printf("Bias %g\n", Bias);
  599. break;
  600. case 'B':
  601. Bias += 0.01;
  602. printf("Bias %g\n", Bias);
  603. break;
  604. case 'd':
  605. DisplayMode = SHOW_DISTANCE;
  606. break;
  607. case 'f':
  608. LinearFilter = !LinearFilter;
  609. printf("%s filtering\n", LinearFilter ? "Bilinear" : "Nearest");
  610. break;
  611. case 'i':
  612. DisplayMode = SHOW_DEPTH_IMAGE;
  613. break;
  614. case 'm':
  615. DisplayMode = SHOW_DEPTH_MAPPING;
  616. break;
  617. case 'M':
  618. curr_frag = (1 + curr_frag) % max_frag;
  619. if (!HaveShadow && (curr_frag == 0)) {
  620. curr_frag = 1;
  621. }
  622. printf("Using fragment %s\n", FragProgNames[curr_frag]);
  623. if (HaveFP) {
  624. glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, frag_progs[curr_frag]);
  625. }
  626. break;
  627. case 'n':
  628. case 's':
  629. case ' ':
  630. DisplayMode = SHOW_SHADOWS;
  631. break;
  632. case 'o':
  633. if (HaveEXTshadowFuncs) {
  634. Operator++;
  635. if (Operator >= 8)
  636. Operator = 0;
  637. printf("Operator: %s\n", OperatorName[Operator]);
  638. if (HaveShadow) {
  639. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB,
  640. OperatorFunc[Operator]);
  641. }
  642. }
  643. break;
  644. case 'p':
  645. UsePackedDepthStencil = !UsePackedDepthStencil;
  646. if (UsePackedDepthStencil && !HavePackedDepthStencil) {
  647. printf("Sorry, GL_EXT_packed_depth_stencil not supported\n");
  648. UsePackedDepthStencil = GL_FALSE;
  649. }
  650. else {
  651. printf("Use GL_DEPTH_STENCIL_EXT: %d\n", UsePackedDepthStencil);
  652. /* Don't really need to regenerate shadow map texture, but do so
  653. * to exercise more code more often.
  654. */
  655. NeedNewShadowMap = GL_TRUE;
  656. }
  657. break;
  658. case 'v':
  659. UseVP = !UseVP && HaveVP;
  660. printf("Using vertex %s mode.\n",
  661. UseVP ? "program" : "fixed-function");
  662. break;
  663. case 'z':
  664. Zrot -= step;
  665. break;
  666. case 'Z':
  667. Zrot += step;
  668. break;
  669. case 27:
  670. exit(0);
  671. break;
  672. }
  673. fflush(stdout);
  674. glutPostRedisplay();
  675. }
  676. static void
  677. SpecialKey(int key, int x, int y)
  678. {
  679. const GLfloat step = 3.0;
  680. const int mod = glutGetModifiers();
  681. (void) x;
  682. (void) y;
  683. switch (key) {
  684. case GLUT_KEY_UP:
  685. if (mod)
  686. LightLatitude += step;
  687. else
  688. Xrot += step;
  689. break;
  690. case GLUT_KEY_DOWN:
  691. if (mod)
  692. LightLatitude -= step;
  693. else
  694. Xrot -= step;
  695. break;
  696. case GLUT_KEY_LEFT:
  697. if (mod)
  698. LightLongitude += step;
  699. else
  700. Yrot += step;
  701. break;
  702. case GLUT_KEY_RIGHT:
  703. if (mod)
  704. LightLongitude -= step;
  705. else
  706. Yrot -= step;
  707. break;
  708. }
  709. if (mod)
  710. NeedNewShadowMap = GL_TRUE;
  711. glutPostRedisplay();
  712. }
  713. /* A helper for finding errors in program strings */
  714. static int FindLine( const char *program, int position )
  715. {
  716. int i, line = 1;
  717. for (i = 0; i < position; i++) {
  718. if (program[i] == '\n')
  719. line++;
  720. }
  721. return line;
  722. }
  723. static GLuint
  724. compile_program(GLenum target, const char *code)
  725. {
  726. GLuint p;
  727. GLint errorPos;
  728. glGenProgramsARB(1, & p);
  729. glBindProgramARB(target, p);
  730. glProgramStringARB(target, GL_PROGRAM_FORMAT_ASCII_ARB,
  731. strlen(code), code);
  732. glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
  733. if (glGetError() != GL_NO_ERROR || errorPos != -1) {
  734. int l = FindLine(code, errorPos);
  735. printf("Fragment Program Error (pos=%d line=%d): %s\n", errorPos, l,
  736. (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
  737. exit(0);
  738. }
  739. glBindProgramARB(target, 0);
  740. return p;
  741. }
  742. static void
  743. Init(void)
  744. {
  745. static const GLfloat borderColor[4] = {1.0, 0.0, 0.0, 0.0};
  746. if (!glutExtensionSupported("GL_ARB_depth_texture")) {
  747. printf("Sorry, this demo requires the GL_ARB_depth_texture extension\n");
  748. exit(1);
  749. }
  750. HaveShadow = glutExtensionSupported("GL_ARB_shadow");
  751. HaveVP = glutExtensionSupported("GL_ARB_vertex_program");
  752. HaveFP = glutExtensionSupported("GL_ARB_fragment_program");
  753. HaveFP_Shadow = glutExtensionSupported("GL_ARB_fragment_program_shadow");
  754. if (!HaveShadow && !HaveFP) {
  755. printf("Sorry, this demo requires either the GL_ARB_shadow extension "
  756. "or the GL_ARB_fragment_program extension\n");
  757. exit(1);
  758. }
  759. printf("Using GL_ARB_depth_texture\n");
  760. if (HaveShadow) {
  761. printf("and GL_ARB_shadow\n");
  762. }
  763. if (HaveFP) {
  764. printf("and GL_ARB_fragment_program\n");
  765. }
  766. HaveShadowAmbient = glutExtensionSupported("GL_ARB_shadow_ambient");
  767. if (HaveShadowAmbient) {
  768. printf("and GL_ARB_shadow_ambient\n");
  769. }
  770. HaveEXTshadowFuncs = glutExtensionSupported("GL_EXT_shadow_funcs");
  771. HavePackedDepthStencil = glutExtensionSupported("GL_EXT_packed_depth_stencil");
  772. UsePackedDepthStencil = HavePackedDepthStencil;
  773. #if defined(GL_EXT_framebuffer_object)
  774. HaveFBO = glutExtensionSupported("GL_EXT_framebuffer_object");
  775. UseFBO = HaveFBO;
  776. if (UseFBO) {
  777. printf("Using GL_EXT_framebuffer_object\n");
  778. }
  779. #endif
  780. /*
  781. * Set up the 2D shadow map texture
  782. */
  783. glGenTextures(1, &ShadowTexture);
  784. glBindTexture(GL_TEXTURE_2D, ShadowTexture);
  785. glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
  786. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  787. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  788. if (HaveShadow) {
  789. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
  790. GL_COMPARE_R_TO_TEXTURE_ARB);
  791. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
  792. }
  793. if (HaveShadowAmbient) {
  794. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.3);
  795. }
  796. #if defined(GL_EXT_framebuffer_object)
  797. if (UseFBO) {
  798. glGenFramebuffersEXT(1, &ShadowFBO);
  799. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ShadowFBO);
  800. glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
  801. GL_COLOR_ATTACHMENT0_EXT,
  802. GL_RENDERBUFFER_EXT, 0);
  803. glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
  804. GL_TEXTURE_2D, ShadowTexture, 0);
  805. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  806. }
  807. #endif
  808. /*
  809. * Setup 1-D grayscale texture image for SHOW_DISTANCE mode
  810. */
  811. glGenTextures(1, &GrayTexture);
  812. glBindTexture(GL_TEXTURE_1D, GrayTexture);
  813. glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  814. glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  815. glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  816. {
  817. GLuint i;
  818. GLubyte image[256];
  819. for (i = 0; i < 256; i++)
  820. image[i] = i;
  821. glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE,
  822. 256, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, image);
  823. }
  824. if (HaveVP) {
  825. vert_prog = compile_program(GL_VERTEX_PROGRAM_ARB, vert_code);
  826. glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vert_prog);
  827. }
  828. max_frag = 1;
  829. frag_progs[0] = 0;
  830. if (HaveFP) {
  831. frag_progs[1] = compile_program(GL_FRAGMENT_PROGRAM_ARB, frag_code);
  832. max_frag = 2;
  833. }
  834. if (HaveFP && HaveFP_Shadow) {
  835. frag_progs[2] = compile_program(GL_FRAGMENT_PROGRAM_ARB,
  836. frag_shadow_code);
  837. max_frag = 3;
  838. }
  839. if (!HaveShadow) {
  840. curr_frag = 1;
  841. glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, frag_progs[curr_frag]);
  842. }
  843. glEnable(GL_DEPTH_TEST);
  844. glEnable(GL_LIGHTING);
  845. glEnable(GL_LIGHT0);
  846. }
  847. static void
  848. PrintHelp(void)
  849. {
  850. printf("Keys:\n");
  851. printf(" a = toggle animation\n");
  852. printf(" i = show depth texture image\n");
  853. printf(" m = show depth texture mapping\n");
  854. printf(" d = show fragment distance from light source\n");
  855. printf(" n = show normal, shadowed image\n");
  856. printf(" f = toggle nearest/bilinear texture filtering\n");
  857. printf(" b/B = decrease/increase shadow map Z bias\n");
  858. printf(" p = toggle use of packed depth/stencil\n");
  859. printf(" M = cycle through fragment program modes\n");
  860. printf(" v = toggle vertex program modes\n");
  861. printf(" cursor keys = rotate scene\n");
  862. printf(" <shift> + cursor keys = rotate light source\n");
  863. if (HaveEXTshadowFuncs)
  864. printf(" o = cycle through comparison modes\n");
  865. fflush(stdout);
  866. }
  867. int
  868. main(int argc, char *argv[])
  869. {
  870. glutInitWindowSize(WindowWidth, WindowHeight);
  871. glutInit(&argc, argv);
  872. glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
  873. glutCreateWindow(argv[0]);
  874. glewInit();
  875. glutReshapeFunc(Reshape);
  876. glutKeyboardFunc(Key);
  877. glutSpecialFunc(SpecialKey);
  878. glutDisplayFunc(Display);
  879. if (Anim)
  880. glutIdleFunc(Idle);
  881. Init();
  882. PrintHelp();
  883. glutMainLoop();
  884. return 0;
  885. }