diff --git a/dists/residualvm.rc b/dists/residualvm.rc index dc100c5c243..012e0de2a86 100644 --- a/dists/residualvm.rc +++ b/dists/residualvm.rc @@ -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 diff --git a/dists/residualvm.rc.in b/dists/residualvm.rc.in index b335d0b26f4..7204a6972a6 100644 --- a/dists/residualvm.rc.in +++ b/dists/residualvm.rc.in @@ -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 diff --git a/engines/stark/gfx/opengls.cpp b/engines/stark/gfx/opengls.cpp index f819e9214d7..306a542f65f 100644 --- a/engines/stark/gfx/opengls.cpp +++ b/engines/stark/gfx/opengls.cpp @@ -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()); diff --git a/engines/stark/gfx/opengls.h b/engines/stark/gfx/opengls.h index 068f10970be..a36d8a09afa 100644 --- a/engines/stark/gfx/opengls.h +++ b/engines/stark/gfx/opengls.h @@ -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; }; diff --git a/engines/stark/gfx/openglsactor.cpp b/engines/stark/gfx/openglsactor.cpp index cf4437f789a..ebdc1061285 100644 --- a/engines/stark/gfx/openglsactor.cpp +++ b/engines/stark/gfx/openglsactor.cpp @@ -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 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::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 &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 &bones = _model->getBones(); - GLint rot = _shader->getUniformLocation(uniform); + GLint rot = shader->getUniformLocation(uniform); if (rot == -1) { error("No uniform named '%s'", uniform); } diff --git a/engines/stark/gfx/openglsactor.h b/engines/stark/gfx/openglsactor.h index b6390b25072..867bbcad083 100644 --- a/engines/stark/gfx/openglsactor.h +++ b/engines/stark/gfx/openglsactor.h @@ -49,7 +49,7 @@ protected: typedef Common::HashMap 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); }; diff --git a/engines/stark/shaders/stark_shadow.fragment b/engines/stark/shaders/stark_shadow.fragment new file mode 100644 index 00000000000..962888af94d --- /dev/null +++ b/engines/stark/shaders/stark_shadow.fragment @@ -0,0 +1,5 @@ +OUTPUT + +void main() { + outColor = vec4(0.0, 0.0, 0.0, 1.0); +} diff --git a/engines/stark/shaders/stark_shadow.vertex b/engines/stark/shaders/stark_shadow.vertex new file mode 100644 index 00000000000..c1967e85023 --- /dev/null +++ b/engines/stark/shaders/stark_shadow.vertex @@ -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); +}