diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index f78ed5045b..da7e9640d9 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -31,6 +31,9 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = gl_MultiTexCoord0; + // and the shadow texture coordinates + gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position), 1.0); + // use standard pipeline transform gl_Position = ftransform(); } diff --git a/interface/resources/shaders/model_normal_map.vert b/interface/resources/shaders/model_normal_map.vert index b013a0a736..2a2f4156f0 100644 --- a/interface/resources/shaders/model_normal_map.vert +++ b/interface/resources/shaders/model_normal_map.vert @@ -36,6 +36,10 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = gl_MultiTexCoord0; + // and the shadow texture coordinates + gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], interpolatedPosition), dot(gl_EyePlaneT[0], interpolatedPosition), + dot(gl_EyePlaneR[0], interpolatedPosition), 1.0); + // use standard pipeline transform gl_Position = ftransform(); } diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index f743609dc3..d68347d33d 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -43,5 +43,8 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = gl_MultiTexCoord0; + // and the shadow texture coordinates + gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position), 1.0); + gl_Position = gl_ProjectionMatrix * position; } diff --git a/interface/resources/shaders/skin_model_normal_map.vert b/interface/resources/shaders/skin_model_normal_map.vert index 5dbc32626a..66cc7c0f58 100644 --- a/interface/resources/shaders/skin_model_normal_map.vert +++ b/interface/resources/shaders/skin_model_normal_map.vert @@ -52,5 +52,9 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = gl_MultiTexCoord0; + // and the shadow texture coordinates + gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], interpolatedPosition), dot(gl_EyePlaneT[0], interpolatedPosition), + dot(gl_EyePlaneR[0], interpolatedPosition), 1.0); + gl_Position = gl_ProjectionMatrix * interpolatedPosition; } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index d18abce677..d1a0a3ec7c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -59,18 +59,39 @@ ProgramObject Model::_program; ProgramObject Model::_normalMapProgram; ProgramObject Model::_specularMapProgram; ProgramObject Model::_normalSpecularMapProgram; + +ProgramObject Model::_shadowMapProgram; +ProgramObject Model::_shadowNormalMapProgram; +ProgramObject Model::_shadowSpecularMapProgram; +ProgramObject Model::_shadowNormalSpecularMapProgram; + ProgramObject Model::_shadowProgram; + ProgramObject Model::_skinProgram; ProgramObject Model::_skinNormalMapProgram; ProgramObject Model::_skinSpecularMapProgram; ProgramObject Model::_skinNormalSpecularMapProgram; + +ProgramObject Model::_skinShadowMapProgram; +ProgramObject Model::_skinShadowNormalMapProgram; +ProgramObject Model::_skinShadowSpecularMapProgram; +ProgramObject Model::_skinShadowNormalSpecularMapProgram; + ProgramObject Model::_skinShadowProgram; + int Model::_normalMapTangentLocation; int Model::_normalSpecularMapTangentLocation; +int Model::_shadowNormalMapTangentLocation; +int Model::_shadowNormalSpecularMapTangentLocation; + Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; Model::SkinLocations Model::_skinSpecularMapLocations; Model::SkinLocations Model::_skinNormalSpecularMapLocations; +Model::SkinLocations Model::_skinShadowMapLocations; +Model::SkinLocations Model::_skinShadowNormalMapLocations; +Model::SkinLocations Model::_skinShadowSpecularMapLocations; +Model::SkinLocations Model::_skinShadowNormalSpecularMapLocations; Model::SkinLocations Model::_skinShadowLocations; void Model::setScale(const glm::vec3& scale) { @@ -100,7 +121,8 @@ void Model::setOffset(const glm::vec3& offset) { } -void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations, int specularTextureUnit) { +void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations, + int specularTextureUnit, int shadowTextureUnit) { program.bind(); locations.clusterMatrices = program.uniformLocation("clusterMatrices"); locations.clusterIndices = program.attributeLocation("clusterIndices"); @@ -109,6 +131,7 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati program.setUniformValue("diffuseMap", 0); program.setUniformValue("normalMap", 1); program.setUniformValue("specularMap", specularTextureUnit); + program.setUniformValue("shadowMap", shadowTextureUnit); program.release(); } @@ -170,7 +193,7 @@ void Model::init() { _program.link(); _program.bind(); - _program.setUniformValue("texture", 0); + _program.setUniformValue("diffuseMap", 0); _program.release(); _normalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, @@ -209,11 +232,63 @@ void Model::init() { _normalSpecularMapTangentLocation = _normalMapProgram.attributeLocation("tangent"); _normalSpecularMapProgram.release(); + + _shadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model.vert"); + _shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + "shaders/model_shadow_map.frag"); + _shadowMapProgram.link(); + + _shadowMapProgram.bind(); + _shadowMapProgram.setUniformValue("diffuseMap", 0); + _shadowMapProgram.setUniformValue("shadowMap", 1); + _shadowMapProgram.release(); + + _shadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _shadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_shadow_normal_map.frag"); + _shadowNormalMapProgram.link(); + + _shadowNormalMapProgram.bind(); + _shadowNormalMapProgram.setUniformValue("diffuseMap", 0); + _shadowNormalMapProgram.setUniformValue("normalMap", 1); + _shadowNormalMapProgram.setUniformValue("shadowMap", 2); + _shadowNormalMapTangentLocation = _shadowNormalMapProgram.attributeLocation("tangent"); + _shadowNormalMapProgram.release(); + + _shadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model.vert"); + _shadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_shadow_specular_map.frag"); + _shadowSpecularMapProgram.link(); + + _shadowSpecularMapProgram.bind(); + _shadowSpecularMapProgram.setUniformValue("diffuseMap", 0); + _shadowSpecularMapProgram.setUniformValue("specularMap", 1); + _shadowSpecularMapProgram.setUniformValue("shadowMap", 2); + _shadowSpecularMapProgram.release(); + + _shadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/model_normal_map.vert"); + _shadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_shadow_normal_specular_map.frag"); + _shadowNormalSpecularMapProgram.link(); + + _shadowNormalSpecularMapProgram.bind(); + _shadowNormalSpecularMapProgram.setUniformValue("diffuseMap", 0); + _shadowNormalSpecularMapProgram.setUniformValue("normalMap", 1); + _shadowNormalSpecularMapProgram.setUniformValue("specularMap", 2); + _shadowNormalSpecularMapProgram.setUniformValue("shadowMap", 3); + _shadowNormalSpecularMapTangentLocation = _normalMapProgram.attributeLocation("tangent"); + _shadowNormalSpecularMapProgram.release(); + + _shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert"); _shadowProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_shadow.frag"); _shadowProgram.link(); + _skinProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model.vert"); _skinProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model.frag"); _skinProgram.link(); @@ -244,6 +319,40 @@ void Model::init() { initSkinProgram(_skinNormalSpecularMapProgram, _skinNormalSpecularMapLocations, 2); + + _skinShadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + + "shaders/skin_model.vert"); + _skinShadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + + "shaders/model_shadow_map.frag"); + _skinShadowMapProgram.link(); + + initSkinProgram(_skinShadowMapProgram, _skinShadowMapLocations); + + _skinShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinShadowNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_shadow_normal_map.frag"); + _skinShadowNormalMapProgram.link(); + + initSkinProgram(_skinShadowNormalMapProgram, _skinShadowNormalMapLocations, 1, 2); + + _skinShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model.vert"); + _skinShadowSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_shadow_specular_map.frag"); + _skinShadowSpecularMapProgram.link(); + + initSkinProgram(_skinShadowSpecularMapProgram, _skinShadowSpecularMapLocations, 1, 2); + + _skinShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/skin_model_normal_map.vert"); + _skinShadowNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/model_shadow_normal_specular_map.frag"); + _skinShadowNormalSpecularMapProgram.link(); + + initSkinProgram(_skinNormalSpecularMapProgram, _skinShadowNormalSpecularMapLocations, 2, 3); + + _skinShadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/skin_model_shadow.vert"); _skinShadowProgram.addShaderFromSourceFile(QGLShader::Fragment, @@ -1485,6 +1594,12 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& networkMeshes = _geometry->getMeshes(); + bool receiveShadows = Menu::getInstance()->isOptionChecked(MenuOption::Shadows); + if (receiveShadows) { + glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[0]); + glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[1]); + glTexGenfv(GL_R, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[2]); + } for (int i = 0; i < networkMeshes.size(); i++) { // exit early if the translucency doesn't match what we're drawing const NetworkMesh& networkMesh = networkMeshes.at(i); @@ -1507,6 +1622,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent) { ProgramObject* skinProgram = &_skinProgram; SkinLocations* skinLocations = &_skinLocations; GLenum specularTextureUnit = 0; + GLenum shadowTextureUnit = 0; if (mode == SHADOW_RENDER_MODE) { program = &_shadowProgram; skinProgram = &_skinShadowProgram; @@ -1514,21 +1630,45 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent) { } else if (!mesh.tangents.isEmpty()) { if (mesh.hasSpecularTexture()) { - program = &_normalSpecularMapProgram; - skinProgram = &_skinNormalSpecularMapProgram; - skinLocations = &_skinNormalSpecularMapLocations; + if (receiveShadows) { + program = &_shadowNormalSpecularMapProgram; + skinProgram = &_skinShadowNormalSpecularMapProgram; + skinLocations = &_skinShadowNormalSpecularMapLocations; + shadowTextureUnit = GL_TEXTURE3; + } else { + program = &_normalSpecularMapProgram; + skinProgram = &_skinNormalSpecularMapProgram; + skinLocations = &_skinNormalSpecularMapLocations; + } specularTextureUnit = GL_TEXTURE2; + } else if (receiveShadows) { + program = &_shadowNormalMapProgram; + skinProgram = &_skinShadowNormalMapProgram; + skinLocations = &_skinShadowNormalMapLocations; } else { program = &_normalMapProgram; skinProgram = &_skinNormalMapProgram; skinLocations = &_skinNormalMapLocations; } } else if (mesh.hasSpecularTexture()) { - program = &_specularMapProgram; - skinProgram = &_skinSpecularMapProgram; - skinLocations = &_skinSpecularMapLocations; - specularTextureUnit = GL_TEXTURE1; + if (receiveShadows) { + program = &_shadowSpecularMapProgram; + skinProgram = &_skinShadowSpecularMapProgram; + skinLocations = &_skinShadowSpecularMapLocations; + specularTextureUnit = GL_TEXTURE1; + shadowTextureUnit = GL_TEXTURE2; + } else { + program = &_specularMapProgram; + skinProgram = &_skinSpecularMapProgram; + skinLocations = &_skinSpecularMapLocations; + specularTextureUnit = GL_TEXTURE1; + } + } else if (receiveShadows) { + program = &_shadowMapProgram; + skinProgram = &_skinShadowMapProgram; + skinLocations = &_skinShadowMapLocations; + shadowTextureUnit = GL_TEXTURE1; } const MeshState& state = _meshStates.at(i); @@ -1617,8 +1757,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent) { Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); - if (!mesh.tangents.isEmpty()) { - specularTextureUnit = GL_TEXTURE2; + if (!mesh.tangents.isEmpty()) { glActiveTexture(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); glBindTexture(GL_TEXTURE_2D, !normalMap ? @@ -1633,6 +1772,12 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent) { Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); glActiveTexture(GL_TEXTURE0); } + + if (shadowTextureUnit) { + glActiveTexture(shadowTextureUnit); + glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); + glActiveTexture(GL_TEXTURE0); + } } glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset); offset += part.quadIndices.size() * sizeof(int); @@ -1662,6 +1807,12 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent) { glActiveTexture(GL_TEXTURE0); } + if (shadowTextureUnit) { + glActiveTexture(shadowTextureUnit); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + } + if (state.clusterMatrices.size() > 1) { skinProgram->disableAttributeArray(skinLocations->clusterIndices); skinProgram->disableAttributeArray(skinLocations->clusterWeights); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 1a6642dfc6..1c9145139b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -340,19 +340,36 @@ private: QList _runningAnimations; + bool _receivesShadows; + static ProgramObject _program; static ProgramObject _normalMapProgram; static ProgramObject _specularMapProgram; static ProgramObject _normalSpecularMapProgram; + + static ProgramObject _shadowMapProgram; + static ProgramObject _shadowNormalMapProgram; + static ProgramObject _shadowSpecularMapProgram; + static ProgramObject _shadowNormalSpecularMapProgram; + static ProgramObject _shadowProgram; + static ProgramObject _skinProgram; static ProgramObject _skinNormalMapProgram; static ProgramObject _skinSpecularMapProgram; static ProgramObject _skinNormalSpecularMapProgram; + + static ProgramObject _skinShadowMapProgram; + static ProgramObject _skinShadowNormalMapProgram; + static ProgramObject _skinShadowSpecularMapProgram; + static ProgramObject _skinShadowNormalSpecularMapProgram; + static ProgramObject _skinShadowProgram; static int _normalMapTangentLocation; static int _normalSpecularMapTangentLocation; + static int _shadowNormalMapTangentLocation; + static int _shadowNormalSpecularMapTangentLocation; class SkinLocations { public: @@ -366,9 +383,14 @@ private: static SkinLocations _skinNormalMapLocations; static SkinLocations _skinSpecularMapLocations; static SkinLocations _skinNormalSpecularMapLocations; + static SkinLocations _skinShadowMapLocations; + static SkinLocations _skinShadowNormalMapLocations; + static SkinLocations _skinShadowSpecularMapLocations; + static SkinLocations _skinShadowNormalSpecularMapLocations; static SkinLocations _skinShadowLocations; - static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1); + static void initSkinProgram(ProgramObject& program, SkinLocations& locations, + int specularTextureUnit = 1, int shadowTextureUnit = 1); }; Q_DECLARE_METATYPE(QPointer)