1 // This file is part of libigl, a simple c++ geometry processing library.
2 //
3 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public License
6 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
7 // obtain one at http://mozilla.org/MPL/2.0/.
8 #include "lens_flare.h"
9 
10 #include "../C_STR.h"
11 #include "unproject.h"
12 #include "project.h"
13 #include "shine_textures.h"
14 #include "flare_textures.h"
15 
16 #include <iostream>
17 #include <stdint.h>
18 
19 // http://www.opengl.org/archives/resources/features/KilgardTechniques/LensFlare/glflare.c
20 
lens_flare_load_textures(std::vector<GLuint> & shine_id,std::vector<GLuint> & flare_id)21 IGL_INLINE void igl::opengl2::lens_flare_load_textures(
22   std::vector<GLuint> & shine_id,
23   std::vector<GLuint> & flare_id)
24 {
25 
26   const auto setup_texture =[](
27     const uint8_t * texture,
28     const int width,
29     const int height,
30     GLuint texobj,
31     GLenum minFilter, GLenum maxFilter)
32   {
33     glBindTexture(GL_TEXTURE_2D, texobj);
34     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
35     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
36     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, maxFilter);
37     glTexImage2D(GL_TEXTURE_2D, 0, 1, width, height, 0,
38       GL_LUMINANCE, GL_UNSIGNED_BYTE, texture);
39   };
40 
41   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
42   shine_id.resize(10);
43   glGenTextures(10,&shine_id[0]);
44   for (int i = 0; i < (int)shine_id.size(); i++) {
45     setup_texture(
46       SHINE_TEXTURES[i],
47       SHINE_TEXTURE_WIDTHS[i],
48       SHINE_TEXTURE_HEIGHTS[i],
49       shine_id[i], GL_LINEAR, GL_LINEAR);
50   }
51   flare_id.resize(6);
52   glGenTextures(6,&flare_id[0]);
53   for (int i = 0; i < (int)flare_id.size(); i++) {
54     setup_texture(
55       FLARE_TEXTURES[i],
56       FLARE_TEXTURE_WIDTHS[i],
57       FLARE_TEXTURE_HEIGHTS[i],
58       flare_id[i], GL_LINEAR, GL_LINEAR);
59   }
60 }
61 
lens_flare_create(const float * A,const float * B,const float * C,std::vector<igl::opengl2::Flare> & flares)62 IGL_INLINE void igl::opengl2::lens_flare_create(
63   const float * A,
64   const float * B,
65   const float * C,
66   std::vector<igl::opengl2::Flare> & flares)
67 {
68   using namespace std;
69   flares.resize(12);
70   /* Shines */
71   flares[0] = Flare(-1, 1.0f, 0.1f, C, 1.0);
72   flares[1] = Flare(-1, 1.0f, 0.15f, B, 1.0);
73   flares[2] = Flare(-1, 1.0f, 0.35f, A, 1.0);
74 
75   /* Flares */
76   flares[3] =  Flare(2, 1.3f, 0.04f, A, 0.6);
77   flares[4] =  Flare(3, 1.0f, 0.1f, A, 0.4);
78   flares[5] =  Flare(1, 0.5f, 0.2f, A, 0.3);
79   flares[6] =  Flare(3, 0.2f, 0.05f, A, 0.3);
80   flares[7] =  Flare(0, 0.0f, 0.04f, A, 0.3);
81   flares[8] =  Flare(5, -0.25f, 0.07f, A, 0.5);
82   flares[9] =  Flare(5, -0.4f, 0.02f, A, 0.6);
83   flares[10] = Flare(5, -0.6f, 0.04f, A, 0.4);
84   flares[11] = Flare(5, -1.0f, 0.03f, A, 0.2);
85 }
86 
lens_flare_draw(const std::vector<igl::opengl2::Flare> & flares,const std::vector<GLuint> & shine_ids,const std::vector<GLuint> & flare_ids,const Eigen::Vector3f & light,const float near_clip,int & shine_tic)87 IGL_INLINE void igl::opengl2::lens_flare_draw(
88   const std::vector<igl::opengl2::Flare> & flares,
89   const std::vector<GLuint> & shine_ids,
90   const std::vector<GLuint> & flare_ids,
91   const Eigen::Vector3f & light,
92   const float near_clip,
93   int & shine_tic)
94 {
95   bool ot2 = glIsEnabled(GL_TEXTURE_2D);
96   bool ob = glIsEnabled(GL_BLEND);
97   bool odt = glIsEnabled(GL_DEPTH_TEST);
98   bool ocm = glIsEnabled(GL_COLOR_MATERIAL);
99   bool ol = glIsEnabled(GL_LIGHTING);
100   int obsa,obda,odf,odwm;
101   glGetIntegerv(GL_BLEND_SRC_ALPHA,&obsa);
102   glGetIntegerv(GL_BLEND_DST_ALPHA,&obda);
103   glGetIntegerv(GL_DEPTH_FUNC,&odf);
104   glGetIntegerv(GL_DEPTH_WRITEMASK,&odwm);
105 
106   glDisable(GL_COLOR_MATERIAL);
107   glEnable(GL_DEPTH_TEST);
108   //glDepthFunc(GL_LEQUAL);
109   glDepthMask(GL_FALSE);
110   glEnable(GL_TEXTURE_2D);
111   glDisable(GL_LIGHTING);
112   glEnable(GL_BLEND);
113   glBlendFunc(GL_ONE, GL_ONE);
114 
115   using namespace Eigen;
116   using namespace std;
117 
118   //// view_dir  direction from eye to position it is looking at
119   //const Vector3f view_dir =  (at - from).normalized();
120 
121   //// near_clip  distance from eye to near clipping plane along view_dir
122   //// center   position on near clipping plane along viewdir from eye
123   //const Vector3f center =  from + near_clip*view_dir;
124 
125   Vector3f plight = project(light);
126   // Orthogonal vectors to view direction at light
127   Vector3f psx = plight;
128   psx(0) += 1;
129   Vector3f psy = plight;
130   psy(1) += 1;
131 
132   // axis toward center
133   int vp[4];
134   glGetIntegerv(GL_VIEWPORT,vp);
135   Vector3f center = unproject(Vector3f(0.5*vp[2],0.5*vp[3],plight[2]-1e-3));
136   //Vector3f center(0,0,1);
137   Vector3f axis = light-center;
138   //glLineWidth(4.);
139   //glColor3f(1,0,0);
140   //glBegin(GL_LINES);
141   //glVertex3fv(center.data());
142   //glVertex3fv(light.data());
143   //glEnd();
144 
145   const Vector3f SX = unproject(psx).normalized();
146   const Vector3f SY = unproject(psy).normalized();
147 
148   for(int i = 0; i < (int)flares.size(); i++)
149   {
150     const Vector3f sx = flares[i].scale * SX;
151     const Vector3f sy = flares[i].scale * SY;
152     glColor3fv(flares[i].color);
153     if (flares[i].type < 0) {
154       glBindTexture(GL_TEXTURE_2D, shine_ids[shine_tic]);
155       shine_tic = (shine_tic + 1) % shine_ids.size();
156     } else
157     {
158       glBindTexture(GL_TEXTURE_2D, flare_ids[flares[i].type]);
159     }
160 
161     /* position = center + flare[i].loc * axis */
162     const Vector3f position = center + flares[i].loc * axis;
163     Vector3f tmp;
164 
165     glBegin(GL_QUADS);
166     glTexCoord2f(0.0, 0.0);
167     tmp =  position +  sx;
168     tmp =  tmp +  sy;
169     glVertex3fv(tmp.data());
170 
171     glTexCoord2f(1.0, 0.0);
172     tmp =  position -  sx;
173     tmp =  tmp +  sy;
174     glVertex3fv(tmp.data());
175 
176     glTexCoord2f(1.0, 1.0);
177     tmp =  position -  sx;
178     tmp =  tmp -  sy;
179     glVertex3fv(tmp.data());
180 
181     glTexCoord2f(0.0, 1.0);
182     tmp =  position +  sx;
183     tmp =  tmp -  sy;
184     glVertex3fv(tmp.data());
185     glEnd();
186   }
187   ot2?glEnable(GL_TEXTURE_2D):glDisable(GL_TEXTURE_2D);
188   ob?glEnable(GL_BLEND):glDisable(GL_BLEND);
189   odt?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST);
190   ocm?glEnable(GL_COLOR_MATERIAL):glDisable(GL_COLOR_MATERIAL);
191   ol?glEnable(GL_LIGHTING):glDisable(GL_LIGHTING);
192   glBlendFunc(obsa,obda);
193   glDepthFunc(odf);
194   glDepthMask(odwm);
195 }
196