Make shadow volumes visible
This commit is contained in:
parent
b7cb346354
commit
6d3965b35e
7 changed files with 108 additions and 67 deletions
85
src/Game.cpp
85
src/Game.cpp
|
@ -30,27 +30,21 @@
|
||||||
|
|
||||||
namespace Zoom {
|
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) {
|
input(0), lightPos(0) {
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
|
||||||
glClearDepth(1.0);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
#ifndef _WIN32
|
glEnable(GL_MULTISAMPLE_ARB);
|
||||||
if(multisample)
|
|
||||||
glEnable(GL_MULTISAMPLE_ARB);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, vmml::vec4f(0.1, 0.1, 0.1, 1).array);
|
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_AMBIENT, vmml::vec4f::ZERO.array);
|
||||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, vmml::vec4f::ONE.array);
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, vmml::vec4f::ONE.array);
|
||||||
glLightfv(GL_LIGHT0, GL_SPECULAR, 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);
|
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.2);
|
||||||
glDisable(GL_LIGHT0);
|
|
||||||
|
|
||||||
glEnable(GL_COLOR_MATERIAL);
|
glEnable(GL_COLOR_MATERIAL);
|
||||||
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
|
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
|
||||||
|
@ -72,6 +66,20 @@ bool Game::loadLevel(const std::string &name) {
|
||||||
return level;
|
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) {
|
void Game::turn(float x, float y) {
|
||||||
playerRotY.rotate_y(-x*M_PI/180/10);
|
playerRotY.rotate_y(-x*M_PI/180/10);
|
||||||
|
|
||||||
|
@ -107,29 +115,29 @@ void Game::run(int delta) {
|
||||||
|
|
||||||
void Game::render() {
|
void Game::render() {
|
||||||
int i;
|
int i;
|
||||||
float light[] = {0, 0, 0, 1};
|
vmml::vec3f light(vmml::vec3f::ZERO);
|
||||||
|
|
||||||
if(lightPos < 12000) i = lightPos;
|
if(lightPos < 12000) i = lightPos;
|
||||||
else i = 24000 - lightPos;
|
else i = 24000 - lightPos;
|
||||||
|
|
||||||
if(i < 4000) {
|
if(i < 4000) {
|
||||||
light[0] = 0.0;
|
light.x() = 0.0;
|
||||||
light[2] = -i * 0.001;
|
light.z() = -i * 0.001;
|
||||||
}
|
}
|
||||||
else if(i < 8000) {
|
else if(i < 8000) {
|
||||||
light[0] = (i-4000) * 0.001;
|
light.x() = (i-4000) * 0.001;
|
||||||
light[2] = -4.0;
|
light.z() = -4.0;
|
||||||
}
|
}
|
||||||
else if(i < 12000) {
|
else if(i < 12000) {
|
||||||
light[0] = 4.0;
|
light.x() = 4.0;
|
||||||
light[2] = -4.0 - (i-8000) * 0.001;
|
light.z() = -4.0 - (i-8000) * 0.001;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
light[0] = 4.0;
|
light.x() = 4.0;
|
||||||
light[2] = -8.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;
|
vmml::mat4f transform(playerRotY), inverse;
|
||||||
transform.rotate_x(playerRotX);
|
transform.rotate_x(playerRotX);
|
||||||
|
@ -138,28 +146,37 @@ void Game::render() {
|
||||||
|
|
||||||
glLoadMatrixf(inverse.array);
|
glLoadMatrixf(inverse.array);
|
||||||
|
|
||||||
glLightfv(GL_LIGHT0, GL_POSITION, light);
|
renderer.render(triangles, light);
|
||||||
|
|
||||||
renderer.render(triangles);
|
|
||||||
|
|
||||||
Shader::disable();
|
Shader::disable();
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthMask(GL_FALSE);
|
||||||
glBlendFunc(GL_ONE, GL_ZERO);
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
glBegin(GL_LINES);
|
glDepthFunc(GL_GREATER);
|
||||||
|
glColor3f(0.05, 0.05, 0.05);
|
||||||
glColor3f(1, 1, 0);
|
glFrontFace(GL_CCW);
|
||||||
|
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
for(std::vector<BSPTree::TriangleRecord>::iterator t = triangles.begin(); t != triangles.end(); ++t) {
|
for(std::vector<BSPTree::TriangleRecord>::iterator t = triangles.begin(); t != triangles.end(); ++t) {
|
||||||
ShadowVolume v(t->triangle, light);
|
ShadowVolume v(t->triangle, light);
|
||||||
|
v.render();
|
||||||
for(int i = 0; i < 3; ++i) {
|
|
||||||
glVertex3fv(v.getVertex(i).array);
|
|
||||||
glVertex3fv((v.getVertex(i)+v.getDirection(i)).array);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glEnd();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,10 +38,12 @@ class Game {
|
||||||
RIGHT = (1 << 3)
|
RIGHT = (1 << 3)
|
||||||
};
|
};
|
||||||
|
|
||||||
Game(bool multisample);
|
Game();
|
||||||
|
|
||||||
bool loadLevel(const std::string &name);
|
bool loadLevel(const std::string &name);
|
||||||
|
|
||||||
|
void resize(int width, int height);
|
||||||
|
|
||||||
void setInput(unsigned input) {
|
void setInput(unsigned input) {
|
||||||
this->input = input;
|
this->input = input;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ Renderer::Renderer() : activeTexture(0), renderVisitor(this) {
|
||||||
lightShader = boost::shared_ptr<Shader>(Shader::load("light.vert", "light.frag"));
|
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;
|
vmml::mat4f transform, inverseTransform;
|
||||||
glGetFloatv(GL_MODELVIEW_MATRIX, transform.array);
|
glGetFloatv(GL_MODELVIEW_MATRIX, transform.array);
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ void Renderer::render(const BSPTree &tree) {
|
||||||
tree.visit(renderVisitor, viewPoint);
|
tree.visit(renderVisitor, viewPoint);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void Renderer::renderTriangle(const Triangle &t) {
|
void Renderer::renderTriangle(const Triangle &t) {
|
||||||
glColor4fv(t.getColor().array);
|
glColor4fv(t.getColor().array);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "gl.h"
|
#include "gl.h"
|
||||||
#include "BSPTree.h"
|
#include "BSPTree.h"
|
||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
namespace Zoom {
|
namespace Zoom {
|
||||||
|
@ -31,13 +32,17 @@ class Renderer {
|
||||||
public:
|
public:
|
||||||
Renderer();
|
Renderer();
|
||||||
|
|
||||||
void render(const BSPTree &tree);
|
//void render(const BSPTree &tree);
|
||||||
|
|
||||||
template <typename T>
|
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);
|
Shader::enable(ambientShader);
|
||||||
glBlendFunc(GL_ONE, GL_ZERO);
|
glBlendFunc(GL_ONE, GL_ZERO);
|
||||||
glDepthFunc(GL_LEQUAL);
|
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();
|
typename T::const_iterator t = triangles.begin();
|
||||||
if(t == triangles.end())
|
if(t == triangles.end())
|
||||||
|
@ -54,6 +59,8 @@ class Renderer {
|
||||||
Shader::enable(lightShader);
|
Shader::enable(lightShader);
|
||||||
glBlendFunc(GL_ONE, GL_ONE);
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
glDepthFunc(GL_EQUAL);
|
glDepthFunc(GL_EQUAL);
|
||||||
|
//glStencilFunc(GL_EQUAL, 0, std::numeric_limits<GLuint>::max());
|
||||||
|
//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
|
|
||||||
t = triangles.begin();
|
t = triangles.begin();
|
||||||
|
|
||||||
|
|
|
@ -20,19 +20,19 @@
|
||||||
#include "ShadowVolume.h"
|
#include "ShadowVolume.h"
|
||||||
#include "MathUtil.h"
|
#include "MathUtil.h"
|
||||||
|
|
||||||
|
#include "gl.h"
|
||||||
|
|
||||||
namespace Zoom {
|
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);
|
MathUtil::Plane trianglePlane(t);
|
||||||
|
|
||||||
for(int i = 0; i < 3; ++i) {
|
for(int i = 0; i < 3; ++i) {
|
||||||
rays[i].p = t.getVertex(i);
|
rays[i].p = t.getVertex(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(trianglePlane.isBehind(lightPos)) {
|
if(trianglePlane.isInFront(lightPos)) {
|
||||||
for(int i = 0; i < 3; ++i) {
|
visible = false;
|
||||||
rays[i].dir = vmml::vec3f::ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define ZOOM_SHADOWVOLUME_H_
|
#define ZOOM_SHADOWVOLUME_H_
|
||||||
|
|
||||||
#include <vmmlib/vector.hpp>
|
#include <vmmlib/vector.hpp>
|
||||||
|
#include <vmmlib/matrix.hpp>
|
||||||
|
|
||||||
namespace Zoom {
|
namespace Zoom {
|
||||||
|
|
||||||
|
@ -39,7 +40,11 @@ class ShadowVolume {
|
||||||
return rays[i].dir;
|
return rays[i].dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void render() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool visible;
|
||||||
|
|
||||||
struct Ray {
|
struct Ray {
|
||||||
vmml::vec3f p;
|
vmml::vec3f p;
|
||||||
vmml::vec3f dir;
|
vmml::vec3f dir;
|
||||||
|
|
30
src/zoom.cpp
30
src/zoom.cpp
|
@ -35,20 +35,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#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
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
@ -250,12 +236,13 @@ bool XIInit(Display *disp, int *opcode) {
|
||||||
return true;
|
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,
|
static const int msAttributeList[] = {GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||||
GLX_X_RENDERABLE, True,
|
GLX_X_RENDERABLE, True,
|
||||||
GLX_DOUBLEBUFFER, True,
|
GLX_DOUBLEBUFFER, True,
|
||||||
GLX_DEPTH_SIZE, 1,
|
GLX_DEPTH_SIZE, 1,
|
||||||
|
GLX_STENCIL_SIZE, 1,
|
||||||
GLX_SAMPLE_BUFFERS, 1,
|
GLX_SAMPLE_BUFFERS, 1,
|
||||||
GLX_SAMPLES, 4,
|
GLX_SAMPLES, 4,
|
||||||
None};
|
None};
|
||||||
|
@ -265,13 +252,13 @@ bool GLXinit(Display *disp, Atom windele, Window *wnd, GLXContext *gc, bool *mul
|
||||||
GLX_X_RENDERABLE, True,
|
GLX_X_RENDERABLE, True,
|
||||||
GLX_DOUBLEBUFFER, True,
|
GLX_DOUBLEBUFFER, True,
|
||||||
GLX_DEPTH_SIZE, 1,
|
GLX_DEPTH_SIZE, 1,
|
||||||
|
GLX_STENCIL_SIZE, 1,
|
||||||
None};
|
None};
|
||||||
|
|
||||||
if(!XIInit(disp, xi_opcode))
|
if(!XIInit(disp, xi_opcode))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
*multisample = true;
|
|
||||||
|
|
||||||
int nElements;
|
int nElements;
|
||||||
GLXFBConfig *fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), msAttributeList, &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);
|
XFree(fbConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
*multisample = false;
|
|
||||||
fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), attributeList, &nElements);
|
fbConfig = glXChooseFBConfig(disp, DefaultScreen(disp), attributeList, &nElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,17 +348,15 @@ int main() {
|
||||||
Window wnd;
|
Window wnd;
|
||||||
GLXContext gc;
|
GLXContext gc;
|
||||||
|
|
||||||
bool multisample;
|
|
||||||
int xi_opcode;
|
int xi_opcode;
|
||||||
int pointer;
|
int pointer;
|
||||||
if(!GLXinit(disp, windele, &wnd, &gc, &multisample, &xi_opcode, &pointer))
|
if(!GLXinit(disp, windele, &wnd, &gc, &xi_opcode, &pointer))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
glewInit();
|
glewInit();
|
||||||
|
|
||||||
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
Zoom::Game game;
|
||||||
|
game.resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||||
Zoom::Game game(multisample);
|
|
||||||
|
|
||||||
GLint samples;
|
GLint samples;
|
||||||
glGetIntegerv(GL_SAMPLES, &samples);
|
glGetIntegerv(GL_SAMPLES, &samples);
|
||||||
|
@ -394,7 +378,7 @@ int main() {
|
||||||
XNextEvent(disp, &event);
|
XNextEvent(disp, &event);
|
||||||
switch(event.type) {
|
switch(event.type) {
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
resize(event.xconfigure.width, event.xconfigure.height);
|
game.resize(event.xconfigure.width, event.xconfigure.height);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ClientMessage:
|
case ClientMessage:
|
||||||
|
|
Reference in a new issue