Make shadow volumes visible

This commit is contained in:
Matthias Schiffer 2009-12-24 02:47:35 +01:00
parent b7cb346354
commit 6d3965b35e
7 changed files with 108 additions and 67 deletions

View file

@ -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
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);
glBegin(GL_LINES);
glColor3f(1, 1, 0);
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_TRIANGLES);
for(std::vector<BSPTree::TriangleRecord>::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_CW);
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBegin(GL_TRIANGLES);
for(std::vector<BSPTree::TriangleRecord>::iterator t = triangles.begin(); t != triangles.end(); ++t) {
ShadowVolume v(t->triangle, light);
v.render();
}
glEnd();
glFrontFace(GL_CCW);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glBlendEquation(GL_FUNC_ADD);
}
}

View file

@ -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;
}

View file

@ -27,7 +27,7 @@ Renderer::Renderer() : activeTexture(0), renderVisitor(this) {
lightShader = boost::shared_ptr<Shader>(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);

View file

@ -23,6 +23,7 @@
#include "gl.h"
#include "BSPTree.h"
#include "Shader.h"
#include <limits>
namespace Zoom {
@ -31,13 +32,17 @@ class Renderer {
public:
Renderer();
void render(const BSPTree &tree);
//void render(const BSPTree &tree);
template <typename T>
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<GLuint>::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<GLuint>::max());
//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
t = triangles.begin();

View file

@ -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);
}
}

View file

@ -21,6 +21,7 @@
#define ZOOM_SHADOWVOLUME_H_
#include <vmmlib/vector.hpp>
#include <vmmlib/matrix.hpp>
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;

View file

@ -35,20 +35,6 @@
#include <unistd.h>
#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: