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 {
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
30
src/zoom.cpp
30
src/zoom.cpp
|
@ -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:
|
||||
|
|
Reference in a new issue