From 6d3965b35edf5f03cd065d42af31867acf1f4637 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 24 Dec 2009 02:47:35 +0100 Subject: Make shadow volumes visible --- src/Game.cpp | 81 +++++++++++++++++++++++++++++++--------------------- src/Game.h | 4 ++- src/Renderer.cpp | 4 +-- src/Renderer.h | 11 +++++-- src/ShadowVolume.cpp | 36 +++++++++++++++++++---- src/ShadowVolume.h | 5 ++++ src/zoom.cpp | 30 +++++-------------- 7 files changed, 106 insertions(+), 65 deletions(-) diff --git a/src/Game.cpp b/src/Game.cpp index 205125a..1b23222 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -30,27 +30,21 @@ namespace Zoom { -Game::Game(bool multisample) : playerPos(vmml::vec3f::ZERO), playerRotY(vmml::mat4f::IDENTITY), playerRotX(0), +Game::Game() : playerPos(vmml::vec3f::ZERO), playerRotY(vmml::mat4f::IDENTITY), playerRotX(0), input(0), lightPos(0) { - glClearColor(0.0, 0.0, 0.0, 1.0); - glClearDepth(1.0); glEnable(GL_DEPTH_TEST); + glEnable(GL_STENCIL_TEST); glEnable(GL_BLEND); -#ifndef _WIN32 - if(multisample) - glEnable(GL_MULTISAMPLE_ARB); -#endif + glEnable(GL_MULTISAMPLE_ARB); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, vmml::vec4f(0.1, 0.1, 0.1, 1).array); glLightfv(GL_LIGHT0, GL_AMBIENT, vmml::vec4f::ZERO.array); glLightfv(GL_LIGHT0, GL_DIFFUSE, vmml::vec4f::ONE.array); glLightfv(GL_LIGHT0, GL_SPECULAR, vmml::vec4f::ONE.array); - glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.2); - glDisable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); @@ -72,6 +66,20 @@ bool Game::loadLevel(const std::string &name) { return level; } +void Game::resize(int width, int height) { + if(height == 0) { + height = 1; + } + + + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(MathUtil::perspective(50.0f, (float)width/(float)height, 0.1).array); + + glMatrixMode(GL_MODELVIEW); + + glViewport(0, 0, width, height); +} + void Game::turn(float x, float y) { playerRotY.rotate_y(-x*M_PI/180/10); @@ -107,29 +115,29 @@ void Game::run(int delta) { void Game::render() { int i; - float light[] = {0, 0, 0, 1}; + vmml::vec3f light(vmml::vec3f::ZERO); if(lightPos < 12000) i = lightPos; else i = 24000 - lightPos; if(i < 4000) { - light[0] = 0.0; - light[2] = -i * 0.001; + light.x() = 0.0; + light.z() = -i * 0.001; } else if(i < 8000) { - light[0] = (i-4000) * 0.001; - light[2] = -4.0; + light.x() = (i-4000) * 0.001; + light.z() = -4.0; } else if(i < 12000) { - light[0] = 4.0; - light[2] = -4.0 - (i-8000) * 0.001; + light.x() = 4.0; + light.z() = -4.0 - (i-8000) * 0.001; } else { - light[0] = 4.0; - light[2] = -8.0; + light.x() = 4.0; + light.z() = -8.0; } - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); vmml::mat4f transform(playerRotY), inverse; transform.rotate_x(playerRotX); @@ -138,28 +146,37 @@ void Game::render() { glLoadMatrixf(inverse.array); - glLightfv(GL_LIGHT0, GL_POSITION, light); - - renderer.render(triangles); + renderer.render(triangles, light); Shader::disable(); - glDepthFunc(GL_LEQUAL); - glBlendFunc(GL_ONE, GL_ZERO); + glDepthMask(GL_FALSE); + glBlendFunc(GL_ONE, GL_ONE); + glBlendEquation(GL_FUNC_ADD); + glDepthFunc(GL_GREATER); + glColor3f(0.05, 0.05, 0.05); + glFrontFace(GL_CCW); - glBegin(GL_LINES); + glBegin(GL_TRIANGLES); + for(std::vector::iterator t = triangles.begin(); t != triangles.end(); ++t) { + ShadowVolume v(t->triangle, light); + v.render(); + } + glEnd(); - glColor3f(1, 1, 0); + glFrontFace(GL_CW); + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); + glBegin(GL_TRIANGLES); for(std::vector::iterator t = triangles.begin(); t != triangles.end(); ++t) { ShadowVolume v(t->triangle, light); - - for(int i = 0; i < 3; ++i) { - glVertex3fv(v.getVertex(i).array); - glVertex3fv((v.getVertex(i)+v.getDirection(i)).array); - } + v.render(); } - glEnd(); + + glFrontFace(GL_CCW); + glDepthMask(GL_TRUE); + glDepthFunc(GL_LEQUAL); + glBlendEquation(GL_FUNC_ADD); } } diff --git a/src/Game.h b/src/Game.h index f6b775b..7f936b4 100644 --- a/src/Game.h +++ b/src/Game.h @@ -38,10 +38,12 @@ class Game { RIGHT = (1 << 3) }; - Game(bool multisample); + Game(); bool loadLevel(const std::string &name); + void resize(int width, int height); + void setInput(unsigned input) { this->input = input; } diff --git a/src/Renderer.cpp b/src/Renderer.cpp index 8b3d689..8aaf9c5 100644 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -27,7 +27,7 @@ Renderer::Renderer() : activeTexture(0), renderVisitor(this) { lightShader = boost::shared_ptr(Shader::load("light.vert", "light.frag")); } -void Renderer::render(const BSPTree &tree) { +/*void Renderer::render(const BSPTree &tree) { vmml::mat4f transform, inverseTransform; glGetFloatv(GL_MODELVIEW_MATRIX, transform.array); @@ -39,7 +39,7 @@ void Renderer::render(const BSPTree &tree) { tree.visit(renderVisitor, viewPoint); glEnd(); -} +}*/ void Renderer::renderTriangle(const Triangle &t) { glColor4fv(t.getColor().array); diff --git a/src/Renderer.h b/src/Renderer.h index ae9af4a..eed65bb 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -23,6 +23,7 @@ #include "gl.h" #include "BSPTree.h" #include "Shader.h" +#include namespace Zoom { @@ -31,13 +32,17 @@ class Renderer { public: Renderer(); - void render(const BSPTree &tree); + //void render(const BSPTree &tree); template - void render(const T &triangles) { + void render(const T &triangles, const vmml::vec3f &lightPos) { + glLightfv(GL_LIGHT0, GL_POSITION, vmml::vec4f(lightPos, 1).array); + Shader::enable(ambientShader); glBlendFunc(GL_ONE, GL_ZERO); glDepthFunc(GL_LEQUAL); + //glStencilFunc(GL_ALWAYS, 0, std::numeric_limits::max()); + //glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); typename T::const_iterator t = triangles.begin(); if(t == triangles.end()) @@ -54,6 +59,8 @@ class Renderer { Shader::enable(lightShader); glBlendFunc(GL_ONE, GL_ONE); glDepthFunc(GL_EQUAL); + //glStencilFunc(GL_EQUAL, 0, std::numeric_limits::max()); + //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); t = triangles.begin(); diff --git a/src/ShadowVolume.cpp b/src/ShadowVolume.cpp index b0c25ca..67a44db 100644 --- a/src/ShadowVolume.cpp +++ b/src/ShadowVolume.cpp @@ -20,19 +20,19 @@ #include "ShadowVolume.h" #include "MathUtil.h" +#include "gl.h" + namespace Zoom { -ShadowVolume::ShadowVolume(const Triangle &t, const vmml::vec3f &lightPos) { +ShadowVolume::ShadowVolume(const Triangle &t, const vmml::vec3f &lightPos) : visible(true) { MathUtil::Plane trianglePlane(t); for(int i = 0; i < 3; ++i) { rays[i].p = t.getVertex(i); } - if(trianglePlane.isBehind(lightPos)) { - for(int i = 0; i < 3; ++i) { - rays[i].dir = vmml::vec3f::ZERO; - } + if(trianglePlane.isInFront(lightPos)) { + visible = false; return; } @@ -42,4 +42,30 @@ ShadowVolume::ShadowVolume(const Triangle &t, const vmml::vec3f &lightPos) { } } +void ShadowVolume::render() const { + if(!visible) + return; + + glVertex3fv(rays[0].p.array); + glVertex3fv(rays[1].p.array); + glVertex3fv(rays[2].p.array); + + for(int i = 0; i < 3; ++i) { + const Ray &r1 = rays[i]; + const Ray &r2 = rays[(i+1)%3]; + + glVertex3fv(r1.p.array); + glVertex4fv(vmml::vec4f(r1.dir, 0).array); + glVertex3fv(r2.p.array); + + glVertex3fv(r2.p.array); + glVertex4fv(vmml::vec4f(r1.dir, 0).array); + glVertex4fv(vmml::vec4f(r2.dir, 0).array); + } + + glVertex4fv(vmml::vec4f(rays[2].dir, 0).array); + glVertex4fv(vmml::vec4f(rays[1].dir, 0).array); + glVertex4fv(vmml::vec4f(rays[0].dir, 0).array); +} + } diff --git a/src/ShadowVolume.h b/src/ShadowVolume.h index e33e19c..81a0a33 100644 --- a/src/ShadowVolume.h +++ b/src/ShadowVolume.h @@ -21,6 +21,7 @@ #define ZOOM_SHADOWVOLUME_H_ #include +#include namespace Zoom { @@ -39,7 +40,11 @@ class ShadowVolume { return rays[i].dir; } + void render() const; + private: + bool visible; + struct Ray { vmml::vec3f p; vmml::vec3f dir; diff --git a/src/zoom.cpp b/src/zoom.cpp index 8193d6a..8467816 100644 --- a/src/zoom.cpp +++ b/src/zoom.cpp @@ -35,20 +35,6 @@ #include #endif -void resize(int width, int height) { - if(height == 0) { - height = 1; - } - - - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(Zoom::MathUtil::perspective(50.0f, (float)width/(float)height, 0.1).array); - - glMatrixMode(GL_MODELVIEW); - - glViewport(0, 0, width, height); -} - #ifdef _WIN32 @@ -250,12 +236,13 @@ bool XIInit(Display *disp, int *opcode) { return true; } -bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, bool *multisample, int *xi_opcode, int *pointer) { +bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, int *xi_opcode, int *pointer) { static const int msAttributeList[] = {GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_X_RENDERABLE, True, GLX_DOUBLEBUFFER, True, GLX_DEPTH_SIZE, 1, + GLX_STENCIL_SIZE, 1, GLX_SAMPLE_BUFFERS, 1, GLX_SAMPLES, 4, None}; @@ -265,13 +252,13 @@ bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, bool *mul GLX_X_RENDERABLE, True, GLX_DOUBLEBUFFER, True, GLX_DEPTH_SIZE, 1, + GLX_STENCIL_SIZE, 1, None}; if(!XIInit(disp, xi_opcode)) return false; bool ok = false; - *multisample = true; int nElements; GLXFBConfig *fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), msAttributeList, &nElements); @@ -280,7 +267,6 @@ bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, bool *mul XFree(fbConfig); } - *multisample = false; fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), attributeList, &nElements); } @@ -362,17 +348,15 @@ int main() { Window wnd; GLXContext gc; - bool multisample; int xi_opcode; int pointer; - if(!GLXinit(disp, windele, &wnd, &gc, &multisample, &xi_opcode, &pointer)) + if(!GLXinit(disp, windele, &wnd, &gc, &xi_opcode, &pointer)) return 1; glewInit(); - resize(DEFAULT_WIDTH, DEFAULT_HEIGHT); - - Zoom::Game game(multisample); + Zoom::Game game; + game.resize(DEFAULT_WIDTH, DEFAULT_HEIGHT); GLint samples; glGetIntegerv(GL_SAMPLES, &samples); @@ -394,7 +378,7 @@ int main() { XNextEvent(disp, &event); switch(event.type) { case ConfigureNotify: - resize(event.xconfigure.width, event.xconfigure.height); + game.resize(event.xconfigure.width, event.xconfigure.height); break; case ClientMessage: -- cgit v1.2.3