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 {
|
||||
|
||||
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) {
|
||||
|
|
|
@ -59,6 +59,7 @@ struct Shadow {
|
|||
int shadowMaskSize;
|
||||
bool active;
|
||||
bool dontNegate;
|
||||
void *userData;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -117,6 +117,13 @@ struct ModelUserData {
|
|||
uint32 _meshInfoVBO;
|
||||
};
|
||||
|
||||
struct ShadowUserData {
|
||||
uint32 _verticesVBO;
|
||||
uint32 _indicesVBO;
|
||||
uint32 _numTriangles;
|
||||
};
|
||||
|
||||
|
||||
// taken from glm
|
||||
Math::Matrix4 makeLookMatrix(const Math::Vector3d& pos, const Math::Vector3d& interest, const Math::Vector3d& up) {
|
||||
Math::Vector3d f = (interest - pos).getNormalized();
|
||||
|
@ -283,16 +290,23 @@ void GfxOpenGLS::setupShaders() {
|
|||
_actorProgram = Graphics::Shader::fromFiles(isEMI ? "emi_actor" : "grim_actor", actorAttributes);
|
||||
_spriteProgram = _actorProgram->clone();
|
||||
|
||||
static const char* primAttributes[] = {"position", NULL};
|
||||
_primitiveProgram = Graphics::Shader::fromFiles("grim_primitive", primAttributes);
|
||||
_irisProgram = _primitiveProgram->clone();
|
||||
if (!isEMI) {
|
||||
static const char* primAttributes[] = {"position", NULL};
|
||||
_primitiveProgram = Graphics::Shader::fromFiles("grim_primitive", primAttributes);
|
||||
_irisProgram = _primitiveProgram->clone();
|
||||
|
||||
_shadowPlaneProgram = Graphics::Shader::fromFiles("grim_shadowplane", primAttributes);
|
||||
}
|
||||
|
||||
setupQuadEBO();
|
||||
setupTexturedQuad();
|
||||
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) {
|
||||
|
@ -469,19 +483,83 @@ void GfxOpenGLS::finishActorDraw() {
|
|||
}
|
||||
|
||||
void GfxOpenGLS::setShadow(Shadow *shadow) {
|
||||
|
||||
_currentShadowArray = shadow;
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
GfxBase::setShadowMode();
|
||||
}
|
||||
|
||||
void GfxOpenGLS::clearShadowMode() {
|
||||
GfxBase::clearShadowMode();
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
}
|
||||
|
||||
bool GfxOpenGLS::isShadowModeActive() {
|
||||
|
@ -489,11 +567,15 @@ bool GfxOpenGLS::isShadowModeActive() {
|
|||
}
|
||||
|
||||
void GfxOpenGLS::setShadowColor(byte r, byte g, byte b) {
|
||||
|
||||
_shadowColorR = r;
|
||||
_shadowColorG = g;
|
||||
_shadowColorB = 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* _primitiveProgram;
|
||||
Graphics::Shader* _irisProgram;
|
||||
Graphics::Shader* _shadowPlaneProgram;
|
||||
|
||||
int _smushWidth;
|
||||
int _smushHeight;
|
||||
|
|
|
@ -87,8 +87,8 @@ public:
|
|||
int getNumSortplanes() { return _numSortplanes; }
|
||||
int getSortplane(int setup) { return _sortplanes[setup]; }
|
||||
int getNumVertices() { return _numVertices; }
|
||||
Math::Vector3d *getVertices() { return _vertices; }
|
||||
Math::Vector3d getNormal() { return _normal; }
|
||||
Math::Vector3d *getVertices() const { return _vertices; }
|
||||
Math::Vector3d getNormal() const { return _normal; }
|
||||
|
||||
Sector &operator=(const Sector &other);
|
||||
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