GRAPHICS: Stencil for grim shadows [OpenGLS]
This commit is contained in:
parent
7cf3f2f99c
commit
f618b90d31
7 changed files with 112 additions and 12 deletions
|
@ -48,7 +48,7 @@
|
||||||
namespace Grim {
|
namespace Grim {
|
||||||
|
|
||||||
Shadow::Shadow() :
|
Shadow::Shadow() :
|
||||||
shadowMask(NULL), shadowMaskSize(0), active(false), dontNegate(false) {
|
shadowMask(NULL), shadowMaskSize(0), active(false), dontNegate(false), userData(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int animTurn(float turnAmt, const Math::Angle &dest, Math::Angle *cur) {
|
static int animTurn(float turnAmt, const Math::Angle &dest, Math::Angle *cur) {
|
||||||
|
|
|
@ -59,6 +59,7 @@ struct Shadow {
|
||||||
int shadowMaskSize;
|
int shadowMaskSize;
|
||||||
bool active;
|
bool active;
|
||||||
bool dontNegate;
|
bool dontNegate;
|
||||||
|
void *userData;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -117,6 +117,13 @@ struct ModelUserData {
|
||||||
uint32 _meshInfoVBO;
|
uint32 _meshInfoVBO;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ShadowUserData {
|
||||||
|
uint32 _verticesVBO;
|
||||||
|
uint32 _indicesVBO;
|
||||||
|
uint32 _numTriangles;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// taken from glm
|
// taken from glm
|
||||||
Math::Matrix4 makeLookMatrix(const Math::Vector3d& pos, const Math::Vector3d& interest, const Math::Vector3d& up) {
|
Math::Matrix4 makeLookMatrix(const Math::Vector3d& pos, const Math::Vector3d& interest, const Math::Vector3d& up) {
|
||||||
Math::Vector3d f = (interest - pos).getNormalized();
|
Math::Vector3d f = (interest - pos).getNormalized();
|
||||||
|
@ -283,16 +290,23 @@ void GfxOpenGLS::setupShaders() {
|
||||||
_actorProgram = Graphics::Shader::fromFiles(isEMI ? "emi_actor" : "grim_actor", actorAttributes);
|
_actorProgram = Graphics::Shader::fromFiles(isEMI ? "emi_actor" : "grim_actor", actorAttributes);
|
||||||
_spriteProgram = _actorProgram->clone();
|
_spriteProgram = _actorProgram->clone();
|
||||||
|
|
||||||
static const char* primAttributes[] = {"position", NULL};
|
if (!isEMI) {
|
||||||
_primitiveProgram = Graphics::Shader::fromFiles("grim_primitive", primAttributes);
|
static const char* primAttributes[] = {"position", NULL};
|
||||||
_irisProgram = _primitiveProgram->clone();
|
_primitiveProgram = Graphics::Shader::fromFiles("grim_primitive", primAttributes);
|
||||||
|
_irisProgram = _primitiveProgram->clone();
|
||||||
|
|
||||||
|
_shadowPlaneProgram = Graphics::Shader::fromFiles("grim_shadowplane", primAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
setupQuadEBO();
|
setupQuadEBO();
|
||||||
setupTexturedQuad();
|
setupTexturedQuad();
|
||||||
setupTexturedCenteredQuad();
|
setupTexturedCenteredQuad();
|
||||||
setupPrimitives();
|
|
||||||
|
|
||||||
_blastVBO = Graphics::Shader::createBuffer(GL_ARRAY_BUFFER, 128 * 16 * sizeof(float), NULL, GL_DYNAMIC_DRAW);
|
if (!isEMI) {
|
||||||
|
setupPrimitives();
|
||||||
|
|
||||||
|
_blastVBO = Graphics::Shader::createBuffer(GL_ARRAY_BUFFER, 128 * 16 * sizeof(float), NULL, GL_DYNAMIC_DRAW);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte *GfxOpenGLS::setupScreen(int screenW, int screenH, bool fullscreen) {
|
byte *GfxOpenGLS::setupScreen(int screenW, int screenH, bool fullscreen) {
|
||||||
|
@ -469,19 +483,83 @@ void GfxOpenGLS::finishActorDraw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfxOpenGLS::setShadow(Shadow *shadow) {
|
void GfxOpenGLS::setShadow(Shadow *shadow) {
|
||||||
|
_currentShadowArray = shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfxOpenGLS::drawShadowPlanes() {
|
void GfxOpenGLS::drawShadowPlanes() {
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glClearStencil(~0);
|
||||||
|
glClear(GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
glStencilFunc(GL_ALWAYS, 1, (GLuint)~0);
|
||||||
|
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
if (!_currentShadowArray->userData) {
|
||||||
|
uint32 numVertices = 0;
|
||||||
|
uint32 numTriangles = 0;
|
||||||
|
for (SectorListType::iterator i = _currentShadowArray->planeList.begin(); i != _currentShadowArray->planeList.end(); ++i) {
|
||||||
|
numVertices += i->sector->getNumVertices();
|
||||||
|
numTriangles += i->sector->getNumVertices() - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
float *vertBuf = new float[3 * numVertices];
|
||||||
|
uint16 *idxBuf = new uint16[3 * numTriangles];
|
||||||
|
|
||||||
|
float *vert = vertBuf;
|
||||||
|
uint16 *idx = idxBuf;
|
||||||
|
|
||||||
|
for (SectorListType::iterator i = _currentShadowArray->planeList.begin(); i != _currentShadowArray->planeList.end(); ++i) {
|
||||||
|
Sector *shadowSector = i->sector;
|
||||||
|
memcpy(vert, shadowSector->getVertices(), 3 * shadowSector->getNumVertices() * sizeof(float));
|
||||||
|
uint16 first = (vert - vertBuf) / 3;
|
||||||
|
for (uint16 j = 2; j < shadowSector->getNumVertices(); ++j) {
|
||||||
|
*idx++ = first;
|
||||||
|
*idx++ = first + j - 1;
|
||||||
|
*idx++ = first + j;
|
||||||
|
}
|
||||||
|
vert += 3 * shadowSector->getNumVertices();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShadowUserData *sud = new ShadowUserData;
|
||||||
|
_currentShadowArray->userData = sud;
|
||||||
|
sud->_numTriangles = numTriangles;
|
||||||
|
sud->_verticesVBO = Graphics::Shader::createBuffer(GL_ARRAY_BUFFER, 3 * numVertices * sizeof(float), vertBuf, GL_STATIC_DRAW);
|
||||||
|
sud->_indicesVBO = Graphics::Shader::createBuffer(GL_ELEMENT_ARRAY_BUFFER, 3 * numTriangles * sizeof(uint16), idxBuf, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
delete[] vertBuf;
|
||||||
|
delete[] idxBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShadowUserData *sud = (ShadowUserData *)_currentShadowArray->userData;
|
||||||
|
_shadowPlaneProgram->use();
|
||||||
|
_shadowPlaneProgram->setUniform("projMatrix", _projMatrix);
|
||||||
|
_shadowPlaneProgram->setUniform("viewMatrix", viewMatrix);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, sud->_verticesVBO);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sud->_indicesVBO);
|
||||||
|
const uint32 attribPos = _shadowPlaneProgram->getAttribute("position")._idx;
|
||||||
|
glEnableVertexAttribArray(attribPos);
|
||||||
|
glVertexAttribPointer(attribPos, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(float), 0);
|
||||||
|
glDrawElements(GL_TRIANGLES, 3 * sud->_numTriangles, GL_UNSIGNED_SHORT, 0);
|
||||||
|
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
|
||||||
|
glStencilFunc(GL_EQUAL, 1, (GLuint)~0);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfxOpenGLS::setShadowMode() {
|
void GfxOpenGLS::setShadowMode() {
|
||||||
|
GfxBase::setShadowMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfxOpenGLS::clearShadowMode() {
|
void GfxOpenGLS::clearShadowMode() {
|
||||||
|
GfxBase::clearShadowMode();
|
||||||
|
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GfxOpenGLS::isShadowModeActive() {
|
bool GfxOpenGLS::isShadowModeActive() {
|
||||||
|
@ -489,11 +567,15 @@ bool GfxOpenGLS::isShadowModeActive() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfxOpenGLS::setShadowColor(byte r, byte g, byte b) {
|
void GfxOpenGLS::setShadowColor(byte r, byte g, byte b) {
|
||||||
|
_shadowColorR = r;
|
||||||
|
_shadowColorG = g;
|
||||||
|
_shadowColorB = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfxOpenGLS::getShadowColor(byte *r, byte *g, byte *b) {
|
void GfxOpenGLS::getShadowColor(byte *r, byte *g, byte *b) {
|
||||||
|
*r = _shadowColorR;
|
||||||
|
*g = _shadowColorG;
|
||||||
|
*b = _shadowColorB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,7 @@ private:
|
||||||
Graphics::Shader* _textProgram;
|
Graphics::Shader* _textProgram;
|
||||||
Graphics::Shader* _primitiveProgram;
|
Graphics::Shader* _primitiveProgram;
|
||||||
Graphics::Shader* _irisProgram;
|
Graphics::Shader* _irisProgram;
|
||||||
|
Graphics::Shader* _shadowPlaneProgram;
|
||||||
|
|
||||||
int _smushWidth;
|
int _smushWidth;
|
||||||
int _smushHeight;
|
int _smushHeight;
|
||||||
|
|
|
@ -87,8 +87,8 @@ public:
|
||||||
int getNumSortplanes() { return _numSortplanes; }
|
int getNumSortplanes() { return _numSortplanes; }
|
||||||
int getSortplane(int setup) { return _sortplanes[setup]; }
|
int getSortplane(int setup) { return _sortplanes[setup]; }
|
||||||
int getNumVertices() { return _numVertices; }
|
int getNumVertices() { return _numVertices; }
|
||||||
Math::Vector3d *getVertices() { return _vertices; }
|
Math::Vector3d *getVertices() const { return _vertices; }
|
||||||
Math::Vector3d getNormal() { return _normal; }
|
Math::Vector3d getNormal() const { return _normal; }
|
||||||
|
|
||||||
Sector &operator=(const Sector &other);
|
Sector &operator=(const Sector &other);
|
||||||
bool operator==(const Sector &other) const;
|
bool operator==(const Sector &other) const;
|
||||||
|
|
6
engines/grim/shaders/grim_shadowplane.fragment
Normal file
6
engines/grim/shaders/grim_shadowplane.fragment
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
OUTPUT
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
outColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
10
engines/grim/shaders/grim_shadowplane.vertex
Normal file
10
engines/grim/shaders/grim_shadowplane.vertex
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
in vec3 position;
|
||||||
|
|
||||||
|
uniform highp mat4 projMatrix;
|
||||||
|
uniform highp mat4 viewMatrix;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 pos = vec4(position, 1.0);
|
||||||
|
gl_Position = projMatrix * viewMatrix * pos;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue