Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Some more example programs.

Demonstrating the use of the stencil buffer and shadow mapping.
  • Loading branch information...
commit fc93db984107af67d5fa6988cdd1961dd882570d 1 parent b0a5f7e
Vilya Harvey authored
2  CMakeLists.txt
@@ -91,6 +91,8 @@ example(basic)
91 91 example(example)
92 92 example(imageview)
93 93 example(raymarch)
  94 +example(shadowmap)
  95 +example(stencil)
94 96 example(styled)
95 97
96 98 #example(picking)
10 TODO.txt
@@ -7,6 +7,7 @@ TODO
7 7 - Make the loadOBJ and loadPLY functions public.
8 8 - Make it possible to register additional geometry loaders without changing the VGL code.
9 9 - Add support for LWO files.
  10 +- Add support for .3ds files, using lib3ds: http://lib3ds.sf.net/
10 11
11 12 - Comment the code properly, in a structured format that Doxygen or something can use.
12 13 - Add a build target to generate the docs.
@@ -18,3 +19,12 @@ TODO
18 19 - Get the ArcballCamera working *better* than the hacked-together camera in the
19 20 OBJViewer.
20 21
  22 +- Scene graph classes
  23 +- Scene graph renderer
  24 + - Walk the scene graph to build up a vector of render commands. Note that
  25 + unloading a buffer / texture / shader should be a command too.
  26 + - build up an adjacency matrix for dependencies between render commands.
  27 + - Do a topological sort of the render commands.
  28 + - Fuse commands where possible.
  29 + - Sort the render commands to minimise the number of state changes & maximise
  30 + reuse of buffers/textures.
340 example/shadowmap.cpp
... ... @@ -0,0 +1,340 @@
  1 +#include "vgl.h"
  2 +
  3 +//
  4 +// Classes
  5 +//
  6 +
  7 +class DirectionalLight
  8 +{
  9 +public:
  10 + DirectionalLight(const vgl::Vec3f& pos, const vgl::Vec3f& target,
  11 + const vgl::Vec3f& up);
  12 +
  13 + void setupProjectionMatrix(int shadowMapWidth, int shadowMapHeight);
  14 + void setupModelViewMatrix();
  15 + void setupLight(float brightness);
  16 +
  17 + vgl::Matrix4f getShadowMatrix(int shadowMapWidth, int shadowMapHeight);
  18 +
  19 + const vgl::Vec3f& getPos() const;
  20 + const vgl::Vec3f& getTarget() const;
  21 + const vgl::Vec3f& getUp() const;
  22 +
  23 +private:
  24 + vgl::Vec3f _pos, _target, _up;
  25 + vgl::Matrix4f _projMatrix, _modelViewMatrix;
  26 +};
  27 +
  28 +
  29 +class ShadowMapRenderer : public vgl::Renderer
  30 +{
  31 +public:
  32 + ShadowMapRenderer(DirectionalLight* light, vgl::Camera* camera);
  33 +
  34 + virtual void setup();
  35 + virtual void render();
  36 +
  37 +protected:
  38 + void saveShadowTexture();
  39 + void setupShadowMap();
  40 + void drawSceneFromLight();
  41 + void drawSceneFromCamera(float brightness, int viewport[]);
  42 + void drawScene();
  43 +
  44 +private:
  45 + int _shadowMapWidth;
  46 + int _shadowMapHeight;
  47 + GLuint _shadowTex;
  48 +
  49 + DirectionalLight* _light;
  50 + vgl::Camera* _camera;
  51 +};
  52 +
  53 +
  54 +class ShadowMapViewer : public vgl::Viewer
  55 +{
  56 +public:
  57 + ShadowMapViewer(ShadowMapRenderer* shadowMapRenderer);
  58 +
  59 + virtual void render();
  60 +};
  61 +
  62 +
  63 +//
  64 +// DirectionalLight methods
  65 +//
  66 +
  67 +DirectionalLight::DirectionalLight(const vgl::Vec3f& pos,
  68 + const vgl::Vec3f& target,
  69 + const vgl::Vec3f& up) :
  70 + _pos(pos),
  71 + _target(target),
  72 + _up(up)
  73 +{
  74 +}
  75 +
  76 +
  77 +void DirectionalLight::setupProjectionMatrix(int shadowMapWidth,
  78 + int shadowMapHeight)
  79 +{
  80 + float distance = length(_target - _pos);
  81 + gluPerspective(30, float(shadowMapWidth) / float(shadowMapHeight),
  82 + distance * 0.1, distance * 2.0);
  83 +}
  84 +
  85 +
  86 +void DirectionalLight::setupModelViewMatrix()
  87 +{
  88 + gluLookAt(_pos.x, _pos.y, _pos.z, _target.x, _target.y, _target.z,
  89 + _up.x, _up.y, _up.z);
  90 +}
  91 +
  92 +
  93 +void DirectionalLight::setupLight(float brightness)
  94 +{
  95 + const vgl::Vec3f kColor(brightness, brightness, brightness);
  96 + const vgl::Vec3f kBlack(0, 0, 0);
  97 +
  98 + glLightfv(GL_LIGHT1, GL_POSITION, _pos.data);
  99 + glLightfv(GL_LIGHT1, GL_AMBIENT, kColor.data);
  100 + glLightfv(GL_LIGHT1, GL_DIFFUSE, kColor.data);
  101 + glLightfv(GL_LIGHT1, GL_SPECULAR, kBlack.data);
  102 + glEnable(GL_LIGHT1);
  103 + glEnable(GL_LIGHTING);
  104 +}
  105 +
  106 +
  107 +vgl::Matrix4f DirectionalLight::getShadowMatrix(int shadowMapWidth,
  108 + int shadowMapHeight)
  109 +{
  110 + const float kBias[] = {
  111 + 0.5, 0.0, 0.0, 0.0,
  112 + 0.0, 0.5, 0.0, 0.0,
  113 + 0.0, 0.0, 0.5, 0.0,
  114 + 0.5, 0.5, 0.5, 1.0
  115 + };
  116 +
  117 + glMatrixMode(GL_MODELVIEW);
  118 + glPushMatrix();
  119 + glLoadMatrixf(kBias);
  120 + setupProjectionMatrix(shadowMapWidth, shadowMapHeight);
  121 + setupModelViewMatrix();
  122 +
  123 + vgl::Matrix4f shadowMatrix;
  124 + glGetFloatv(GL_MODELVIEW_MATRIX, shadowMatrix.data);
  125 + glPopMatrix();
  126 +
  127 + return shadowMatrix;
  128 +}
  129 +
  130 +
  131 +//
  132 +// ShadowMapRenderer functions
  133 +//
  134 +
  135 +ShadowMapRenderer::ShadowMapRenderer(DirectionalLight* light, vgl::Camera* camera) :
  136 + vgl::Renderer(),
  137 + _shadowMapWidth(512),
  138 + _shadowMapHeight(512),
  139 + _shadowTex(0),
  140 + _light(light),
  141 + _camera(camera)
  142 +{
  143 +}
  144 +
  145 +
  146 +void ShadowMapRenderer::setup()
  147 +{
  148 + glEnable(GL_CULL_FACE);
  149 + glEnable(GL_DEPTH_TEST);
  150 + glEnable(GL_NORMALIZE);
  151 + glEnable(GL_COLOR_MATERIAL);
  152 +
  153 + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  154 +
  155 + glCullFace(GL_BACK);
  156 + glShadeModel(GL_SMOOTH);
  157 + glDepthFunc(GL_LEQUAL);
  158 +
  159 + const vgl::Vec3f kWhite(1, 1, 1);
  160 +
  161 + glClearColor(0, 0, 0, 0);
  162 + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  163 + glMaterialfv(GL_FRONT, GL_SPECULAR, kWhite.data);
  164 + glMaterialf(GL_FRONT, GL_SHININESS, 16.0);
  165 +
  166 + // Create the shadowmap texture.
  167 + glGenTextures(1, &_shadowTex);
  168 + glBindTexture(GL_TEXTURE_2D, _shadowTex);
  169 + glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  170 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  171 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  172 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  173 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  174 + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
  175 + _shadowMapWidth, _shadowMapHeight, 0, GL_LUMINANCE, GL_FLOAT, NULL);
  176 +}
  177 +
  178 +
  179 +void ShadowMapRenderer::render()
  180 +{
  181 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  182 +
  183 + // Store the current viewport settings.
  184 + int viewport[4];
  185 + glGetIntegerv(GL_VIEWPORT, viewport);
  186 + int width = viewport[2];
  187 + int height = viewport[3];
  188 +
  189 + // Draw the scene from the light's point of view.
  190 + drawSceneFromLight();
  191 +
  192 + // Save the rendered scene in the shadow map.
  193 + saveShadowTexture();
  194 +
  195 + // Draw the scene from the cameras point of view with a dim light for the shadowed areas.
  196 + drawSceneFromCamera(0.2f, viewport);
  197 +
  198 + // Setup the shadow map.
  199 + setupShadowMap();
  200 +
  201 + // Draw the scene from the cameras point of view with a bright light for the unshadowed areas.
  202 + //drawSceneFromCamera(1.0f, viewport);
  203 +
  204 + // Cleanup
  205 + glDisable(GL_TEXTURE_2D);
  206 + glDisable(GL_TEXTURE_GEN_S);
  207 + glDisable(GL_TEXTURE_GEN_T);
  208 + glDisable(GL_TEXTURE_GEN_R);
  209 + glDisable(GL_TEXTURE_GEN_Q);
  210 + glDisable(GL_LIGHTING);
  211 + glDisable(GL_ALPHA_TEST);
  212 +}
  213 +
  214 +
  215 +void ShadowMapRenderer::saveShadowTexture()
  216 +{
  217 + glBindTexture(GL_TEXTURE_2D, _shadowTex);
  218 + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, _shadowMapWidth, _shadowMapHeight, 0);
  219 + glClear(GL_DEPTH_BUFFER_BIT);
  220 +}
  221 +
  222 +
  223 +void ShadowMapRenderer::setupShadowMap()
  224 +{
  225 + vgl::Matrix4f shadowMatrix = _light->getShadowMatrix(_shadowMapWidth, _shadowMapHeight);
  226 + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  227 + glTexGenfv(GL_S, GL_EYE_PLANE, shadowMatrix.rows[0]);
  228 + glEnable(GL_TEXTURE_GEN_S);
  229 + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  230 + glTexGenfv(GL_T, GL_EYE_PLANE, shadowMatrix.rows[1]);
  231 + glEnable(GL_TEXTURE_GEN_T);
  232 + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  233 + glTexGenfv(GL_R, GL_EYE_PLANE, shadowMatrix.rows[2]);
  234 + glEnable(GL_TEXTURE_GEN_R);
  235 + glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  236 + glTexGenfv(GL_Q, GL_EYE_PLANE, shadowMatrix.rows[3]);
  237 + glEnable(GL_TEXTURE_GEN_Q);
  238 + glBindTexture(GL_TEXTURE_2D, _shadowTex);
  239 + glEnable(GL_TEXTURE_2D);
  240 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
  241 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
  242 + glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
  243 + glAlphaFunc(GL_GEQUAL, 0.99f);
  244 + glEnable(GL_ALPHA_TEST);
  245 +}
  246 +
  247 +
  248 +void ShadowMapRenderer::drawSceneFromLight()
  249 +{
  250 + glMatrixMode(GL_PROJECTION);
  251 + glLoadIdentity();
  252 + _light->setupProjectionMatrix(_shadowMapWidth, _shadowMapHeight);
  253 + glMatrixMode(GL_MODELVIEW);
  254 + glLoadIdentity();
  255 + _light->setupModelViewMatrix();
  256 + glViewport(0, 0, _shadowMapWidth, _shadowMapHeight);
  257 + glCullFace(GL_FRONT);
  258 + glShadeModel(GL_FLAT);
  259 + glColorMask(0, 0, 0, 0);
  260 + drawScene();
  261 +}
  262 +
  263 +
  264 +void ShadowMapRenderer::drawSceneFromCamera(float brightness, int viewport[])
  265 +{
  266 + glMatrixMode(GL_PROJECTION);
  267 + glLoadIdentity();
  268 + _camera->setupProjectionMatrix();
  269 + glMatrixMode(GL_MODELVIEW);
  270 + glLoadIdentity();
  271 + _camera->setupModelViewMatrix();
  272 + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
  273 + glCullFace(GL_BACK);
  274 + glShadeModel(GL_SMOOTH);
  275 + glColorMask(1, 1, 1, 1);
  276 + _light->setupLight(brightness);
  277 + drawScene();
  278 +}
  279 +
  280 +
  281 +void ShadowMapRenderer::drawScene()
  282 +{
  283 + glFrontFace(GL_CW); // The triangle winding order on the teapot seems to be clockwise...
  284 + glColor3f(1, 0, 0);
  285 + glPushMatrix();
  286 + glTranslatef(0, 0.5, 0);
  287 + glutSolidTeapot(0.5);
  288 + glPopMatrix();
  289 +
  290 + glFrontFace(GL_CCW);
  291 + glColor3f(0, 0, 1);
  292 + glPushMatrix();
  293 + glScalef(1, 0.1, 1);
  294 + glTranslatef(0, -0.5, 0);
  295 + glutSolidCube(1.0);
  296 + glPopMatrix();
  297 +}
  298 +
  299 +
  300 +//
  301 +// ShadowMapViewer functions
  302 +//
  303 +
  304 +ShadowMapViewer::ShadowMapViewer(ShadowMapRenderer* renderer) :
  305 + vgl::Viewer("Shadow map test", 1024, 768, renderer)
  306 +{
  307 +}
  308 +
  309 +
  310 +void ShadowMapViewer::render()
  311 +{
  312 + _renderer->render();
  313 + glutSwapBuffers();
  314 +}
  315 +
  316 +
  317 +//
  318 +// Functions
  319 +//
  320 +
  321 +int main(int argc, char**argv)
  322 +{
  323 + const int kWidth = 1024;
  324 + const int kHeight = 768;
  325 +
  326 + vgl::ArcballCamera camera(vgl::Vec3f(0, 0, 5),
  327 + vgl::Vec3f(0, 0, 0),
  328 + vgl::Vec3f(0, 1, 0),
  329 + -1, 1, -1, 1,
  330 + 30, kWidth, kHeight);
  331 +
  332 + DirectionalLight light(vgl::Vec3f(0, 5, 0),
  333 + vgl::Vec3f(0, 0, 0),
  334 + vgl::Vec3f(1, 0, 0));
  335 +
  336 + ShadowMapRenderer renderer(&light, &camera);
  337 + vgl::Viewer viewer("Stencil buffer test", kWidth, kHeight, &renderer, &camera);
  338 + viewer.run();
  339 + return 0;
  340 +}
118 example/stencil.cpp
... ... @@ -0,0 +1,118 @@
  1 +#include "vgl.h"
  2 +
  3 +
  4 +//
  5 +// Classes
  6 +//
  7 +
  8 +class StencilRenderer : public vgl::Renderer
  9 +{
  10 +public:
  11 + virtual void setup();
  12 + virtual void render();
  13 +};
  14 +
  15 +
  16 +//
  17 +// StencilRenderer methods
  18 +//
  19 +
  20 +void StencilRenderer::setup()
  21 +{
  22 + int viewport[4];
  23 + glGetIntegerv(GL_VIEWPORT, viewport);
  24 + int width = viewport[0];
  25 + int height = viewport[1];
  26 +
  27 + const unsigned char pixels[64] = {
  28 + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  29 + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  30 + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  31 + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  32 + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  33 + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  34 + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  35 + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  36 + };
  37 +
  38 + width = 1024;
  39 + height = 768;
  40 + gluOrtho2D(0, width, 0, height);
  41 +
  42 + // Fill the stencil buffer.
  43 + glClearStencil(0);
  44 + glClear(GL_STENCIL_BUFFER_BIT);
  45 + glColorMask(0, 0, 0, 0);
  46 + glEnable(GL_STENCIL_TEST);
  47 + glDisable(GL_DEPTH_TEST);
  48 + glStencilFunc(GL_EQUAL, 1, 1);
  49 + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  50 + for (int y = 0; y < height; y += 8) {
  51 + for (int x = 0; x < width; x += 8) {
  52 + glRasterPos2i(x, y);
  53 + glDrawPixels(8, 8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, pixels);
  54 + }
  55 + }
  56 + vgl::checkGLError("fucked up the stencil buffer initialisation");
  57 +
  58 + glColorMask(1, 1, 1, 1);
  59 + glEnable(GL_DEPTH_TEST);
  60 + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  61 +}
  62 +
  63 +
  64 +void StencilRenderer::render()
  65 +{
  66 + // Draw the left eye image.
  67 + glStencilFunc(GL_EQUAL, 1, 1);
  68 + glColor3f(0, 0, 1);
  69 + glutSolidTeapot(1.0);
  70 +
  71 + // Draw the right eye image.
  72 + glStencilFunc(GL_NOTEQUAL, 1, 1);
  73 + glColor3f(0, 1, 1);
  74 + glutSolidTeapot(1.0);
  75 +
  76 +// glDisable(GL_STENCIL_TEST);
  77 +
  78 +// int viewport[4];
  79 +// glGetIntegerv(GL_VIEWPORT, viewport);
  80 +// int width = 1024;//viewport[0];
  81 +// int height = 768;//viewport[1];
  82 +
  83 +// const unsigned char pixels[64] = {
  84 +// 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  85 +// 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  86 +// 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  87 +// 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  88 +// 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  89 +// 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  90 +// 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  91 +// 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
  92 +// };
  93 +// gluOrtho2D(0, width, 0, height);
  94 +//// glRasterPos2i(0, 0);
  95 +//// glDrawPixels(8, 8, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels);
  96 +//// glRasterPos2f(0.5, 0.5);
  97 +//// glDrawPixels(8, 8, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels);
  98 +// for (int y = 0; y < height; y += 8) {
  99 +// for (int x = 0; x < width; x += 8) {
  100 +// glRasterPos2f(x, y);
  101 +// glDrawPixels(8, 8, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels);
  102 +// }
  103 +// }
  104 +// vgl::checkGLError("fucked up the stencil buffer initialisation");
  105 +}
  106 +
  107 +
  108 +//
  109 +// Functions
  110 +//
  111 +
  112 +int main(int argc, char** argv)
  113 +{
  114 + StencilRenderer renderer;
  115 + vgl::Viewer viewer("Stencil buffer test", 1024, 768, &renderer);
  116 + viewer.run();
  117 + return 0;
  118 +}
2  src/vgl_viewer.cpp
@@ -100,7 +100,7 @@ Viewer::Viewer(
100 100
101 101 // Setup GLUT
102 102 glutInit(&argc, argv);
103   - glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
  103 + glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_STENCIL);
104 104 glutInitWindowPosition(100, 100);
105 105 glutInitWindowSize(width, height);
106 106 glutCreateWindow((title != NULL) ? title : "Unnamed");

0 comments on commit fc93db9

Please sign in to comment.
Something went wrong with that request. Please try again.