STARK: Project a black shadow from above

This commit is contained in:
Douglas Liu 2018-07-22 12:24:36 +08:00
parent 8e9c5580ac
commit 891375d509
8 changed files with 79 additions and 9 deletions

View File

@ -63,6 +63,8 @@ shaders/stark_surface.fragment FILE "engines/stark/shaders/stark_surface.fr
shaders/stark_surface.vertex FILE "engines/stark/shaders/stark_surface.vertex"
shaders/stark_fade.fragment FILE "engines/stark/shaders/stark_fade.fragment"
shaders/stark_fade.vertex FILE "engines/stark/shaders/stark_fade.vertex"
shaders/stark_shadow.fragment FILE "engines/stark/shaders/stark_shadow.fragment"
shaders/stark_shadow.vertex FILE "engines/stark/shaders/stark_shadow.vertex"
#endif
#endif

View File

@ -63,6 +63,8 @@ shaders/stark_surface.fragment FILE "engines/stark/shaders/stark_surface.fr
shaders/stark_surface.vertex FILE "engines/stark/shaders/stark_surface.vertex"
shaders/stark_fade.fragment FILE "engines/stark/shaders/stark_fade.fragment"
shaders/stark_fade.vertex FILE "engines/stark/shaders/stark_fade.vertex"
shaders/stark_shadow.fragment FILE "engines/stark/shaders/stark_shadow.fragment"
shaders/stark_shadow.vertex FILE "engines/stark/shaders/stark_shadow.vertex"
#endif
#endif

View File

@ -61,6 +61,7 @@ OpenGLSDriver::OpenGLSDriver() :
_surfaceShader(nullptr),
_actorShader(nullptr),
_fadeShader(nullptr),
_shadowShader(nullptr),
_surfaceVBO(0),
_fadeVBO(0) {
}
@ -71,6 +72,7 @@ OpenGLSDriver::~OpenGLSDriver() {
delete _surfaceShader;
delete _actorShader;
delete _fadeShader;
delete _shadowShader;
}
void OpenGLSDriver::init() {
@ -85,6 +87,9 @@ void OpenGLSDriver::init() {
static const char* actorAttributes[] = { "position1", "position2", "bone1", "bone2", "boneWeight", "normal", "texcoord", nullptr };
_actorShader = OpenGL::Shader::fromFiles("stark_actor", actorAttributes);
static const char* shadowAttributes[] = { "position1", "position2", "bone1", "bone2", "boneWeight", nullptr };
_shadowShader = OpenGL::Shader::fromFiles("stark_shadow", shadowAttributes);
static const char* fadeAttributes[] = { "position", nullptr };
_fadeShader = OpenGL::Shader::fromFiles("stark_fade", fadeAttributes);
_fadeVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(fadeVertices), fadeVertices);
@ -201,6 +206,10 @@ OpenGL::Shader *OpenGLSDriver::createFadeShaderInstance() {
return _fadeShader->clone();
}
OpenGL::Shader *OpenGLSDriver::createShadowShaderInstance() {
return _shadowShader->clone();
}
Graphics::Surface *OpenGLSDriver::getViewportScreenshot() const {
Graphics::Surface *s = new Graphics::Surface();
s->create(_viewport.width(), _viewport.height(), getRGBAPixelFormat());

View File

@ -25,6 +25,8 @@
#include "common/system.h"
//#define USE_GLES2
#if defined(USE_GLES2) || defined(USE_OPENGL_SHADERS)
#include "engines/stark/gfx/driver.h"
@ -58,6 +60,7 @@ public:
OpenGL::Shader *createActorShaderInstance();
OpenGL::Shader *createSurfaceShaderInstance();
OpenGL::Shader *createFadeShaderInstance();
OpenGL::Shader *createShadowShaderInstance();
void start2DMode();
void end2DMode();
@ -75,6 +78,7 @@ private:
OpenGL::Shader *_surfaceShader;
OpenGL::Shader *_actorShader;
OpenGL::Shader *_fadeShader;
OpenGL::Shader *_shadowShader;
uint32 _surfaceVBO;
uint32 _fadeVBO;
};

View File

@ -39,12 +39,14 @@ OpenGLSActorRenderer::OpenGLSActorRenderer(OpenGLSDriver *gfx) :
_gfx(gfx),
_faceVBO(0) {
_shader = _gfx->createActorShaderInstance();
_shadowShader = _gfx->createShadowShaderInstance();
}
OpenGLSActorRenderer::~OpenGLSActorRenderer() {
clearVertices();
delete _shader;
delete _shadowShader;
}
void OpenGLSActorRenderer::render(const Math::Vector3d &position, float direction, const LightEntryArray &lights) {
@ -86,8 +88,8 @@ void OpenGLSActorRenderer::render(const Math::Vector3d &position, float directio
_shader->setUniform("modelViewMatrix", modelViewMatrix);
_shader->setUniform("projectionMatrix", projectionMatrix);
_shader->setUniform("normalMatrix", normalMatrix.getRotation());
setBoneRotationArrayUniform("boneRotation");
setBonePositionArrayUniform("bonePosition");
setBoneRotationArrayUniform(_shader, "boneRotation");
setBonePositionArrayUniform(_shader, "bonePosition");
setLightArrayUniform("lights", lights);
Common::Array<Face *> faces = _model->getFaces();
@ -112,6 +114,28 @@ void OpenGLSActorRenderer::render(const Math::Vector3d &position, float directio
}
_shader->unbind();
// Shadow
_shadowShader->enableVertexAttribute("position1", _faceVBO, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), 0);
_shadowShader->enableVertexAttribute("position2", _faceVBO, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(float), 12);
_shadowShader->enableVertexAttribute("bone1", _faceVBO, 1, GL_FLOAT, GL_FALSE, 14 * sizeof(float), 24);
_shadowShader->enableVertexAttribute("bone2", _faceVBO, 1, GL_FLOAT, GL_FALSE, 14 * sizeof(float), 28);
_shadowShader->enableVertexAttribute("boneWeight", _faceVBO, 1, GL_FLOAT, GL_FALSE, 14 * sizeof(float), 32);
_shadowShader->use(true);
_shadowShader->setUniform("modelViewMatrix", modelViewMatrix);
_shadowShader->setUniform("projectionMatrix", projectionMatrix);
setBoneRotationArrayUniform(_shadowShader, "boneRotation");
setBonePositionArrayUniform(_shadowShader, "bonePosition");
for (Common::Array<Face *>::const_iterator face = faces.begin(); face != faces.end(); ++face) {
GLuint ebo = _faceEBO[*face];
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glDrawElements(GL_TRIANGLES, (*face)->vertexIndices.size(), GL_UNSIGNED_INT, 0);
}
_shadowShader->unbind();
}
void OpenGLSActorRenderer::clearVertices() {
@ -173,10 +197,10 @@ uint32 OpenGLSActorRenderer::createFaceEBO(const Face *face) {
return OpenGL::Shader::createBuffer(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32) * face->vertexIndices.size(), &face->vertexIndices[0]);
}
void OpenGLSActorRenderer::setBonePositionArrayUniform(const char *uniform) {
void OpenGLSActorRenderer::setBonePositionArrayUniform(OpenGL::Shader *shader, const char *uniform) {
const Common::Array<BoneNode *> &bones = _model->getBones();
GLint pos = _shader->getUniformLocation(uniform);
GLint pos = shader->getUniformLocation(uniform);
if (pos == -1) {
error("No uniform named '%s'", uniform);
}
@ -194,10 +218,10 @@ void OpenGLSActorRenderer::setBonePositionArrayUniform(const char *uniform) {
delete[] positions;
}
void OpenGLSActorRenderer::setBoneRotationArrayUniform(const char *uniform) {
void OpenGLSActorRenderer::setBoneRotationArrayUniform(OpenGL::Shader *shader, const char *uniform) {
const Common::Array<BoneNode *> &bones = _model->getBones();
GLint rot = _shader->getUniformLocation(uniform);
GLint rot = shader->getUniformLocation(uniform);
if (rot == -1) {
error("No uniform named '%s'", uniform);
}

View File

@ -49,7 +49,7 @@ protected:
typedef Common::HashMap<Face *, uint32> FaceBufferMap;
OpenGLSDriver *_gfx;
OpenGL::Shader *_shader;
OpenGL::Shader *_shader, *_shadowShader;
uint32 _faceVBO;
FaceBufferMap _faceEBO;
@ -58,8 +58,8 @@ protected:
void uploadVertices();
uint32 createModelVBO(const Model *model);
uint32 createFaceEBO(const Face *face);
void setBonePositionArrayUniform(const char *uniform);
void setBoneRotationArrayUniform(const char *uniform);
void setBonePositionArrayUniform(OpenGL::Shader *shader, const char *uniform);
void setBoneRotationArrayUniform(OpenGL::Shader *shader, const char *uniform);
void setLightArrayUniform(const char *uniform, const LightEntryArray &lights);
};

View File

@ -0,0 +1,5 @@
OUTPUT
void main() {
outColor = vec4(0.0, 0.0, 0.0, 1.0);
}

View File

@ -0,0 +1,24 @@
in vec3 position1;
in vec3 position2;
in float bone1;
in float bone2;
in float boneWeight;
const int maxBones = 70;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform vec4 boneRotation[maxBones];
uniform vec3 bonePosition[maxBones];
vec3 qrot(vec4 q, vec3 v) {
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);
}
void main() {
vec3 b1 = qrot(boneRotation[int(bone1)], position1) + bonePosition[int(bone1)];
vec3 b2 = qrot(boneRotation[int(bone2)], position2) + bonePosition[int(bone2)];
vec3 modelPosition = mix(b2, b1, boneWeight);
gl_Position = projectionMatrix * modelViewMatrix * vec4(modelPosition.x, 0.0, modelPosition.z, 1.0);
}