This commit is contained in:
Philip Rosedale 2014-05-23 17:41:58 -07:00
commit f4c274dbe6
10 changed files with 391 additions and 11 deletions

View file

@ -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();
}

View file

@ -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();
}

View file

@ -0,0 +1,41 @@
#version 120
//
// model_shadow_map.frag
// fragment shader
//
// Created by Andrzej Kapolka on 5/23/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the diffuse texture
uniform sampler2D diffuseMap;
// the shadow texture
uniform sampler2DShadow shadowMap;
// the interpolated position
varying vec4 position;
// the interpolated normal
varying vec4 normal;
void main(void) {
// compute the base color based on OpenGL lighting model
vec4 normalizedNormal = normalize(normal);
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
float facingLight = step(0.0, diffuse) * shadow2D(shadowMap, gl_TexCoord[1].stp).r;
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
// compute the specular component (sans exponent)
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
normalizedNormal));
// modulate texture by base color and add specular contribution
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) +
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0);
}

View file

@ -0,0 +1,53 @@
#version 120
//
// model_shadow_normal_map.frag
// fragment shader
//
// Created by Andrzej Kapolka on 5/23/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the diffuse texture
uniform sampler2D diffuseMap;
// the normal map texture
uniform sampler2D normalMap;
// the shadow texture
uniform sampler2DShadow shadowMap;
// the interpolated position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
// the interpolated tangent
varying vec4 interpolatedTangent;
void main(void) {
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0);
// compute the base color based on OpenGL lighting model
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
float diffuse = dot(viewNormal, gl_LightSource[0].position);
float facingLight = step(0.0, diffuse) * shadow2D(shadowMap, gl_TexCoord[1].stp).r;
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
// compute the specular component (sans exponent)
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
normalize(vec4(vec3(interpolatedPosition), 0.0))), viewNormal));
// modulate texture by base color and add specular contribution
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) +
vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0);
}

View file

@ -0,0 +1,56 @@
#version 120
//
// model_shadow_normal_specular_map.frag
// fragment shader
//
// Created by Andrzej Kapolka on 5/23/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the diffuse texture
uniform sampler2D diffuseMap;
// the normal map texture
uniform sampler2D normalMap;
// the specular map texture
uniform sampler2D specularMap;
// the shadow texture
uniform sampler2DShadow shadowMap;
// the interpolated position
varying vec4 interpolatedPosition;
// the interpolated normal
varying vec4 interpolatedNormal;
// the interpolated tangent
varying vec4 interpolatedTangent;
void main(void) {
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) * 2.0 - vec3(1.0, 1.0, 1.0);
// compute the base color based on OpenGL lighting model
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
float diffuse = dot(viewNormal, gl_LightSource[0].position);
float facingLight = step(0.0, diffuse) * shadow2D(shadowMap, gl_TexCoord[1].stp).r;
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
// compute the specular component (sans exponent)
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
normalize(vec4(interpolatedPosition.xyz, 0.0))), viewNormal));
// modulate texture by base color and add specular contribution
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) *
gl_FrontLightProduct[0].specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
}

View file

@ -0,0 +1,44 @@
#version 120
//
// model_shadow_specular_map.frag
// fragment shader
//
// Created by Andrzej Kapolka on 5/23/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the diffuse texture
uniform sampler2D diffuseMap;
// the specular texture
uniform sampler2D specularMap;
// the shadow texture
uniform sampler2DShadow shadowMap;
// the interpolated position in view space
varying vec4 position;
// the interpolated normal
varying vec4 normal;
void main(void) {
// compute the base color based on OpenGL lighting model
vec4 normalizedNormal = normalize(normal);
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
float facingLight = step(0.0, diffuse) * shadow2D(shadowMap, gl_TexCoord[1].stp).r;
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
// compute the specular component (sans exponent)
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
normalizedNormal));
// modulate texture by base color and add specular contribution
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) *
gl_FrontLightProduct[0].specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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(_skinShadowNormalSpecularMapProgram, _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<NetworkMesh>& 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,46 @@ 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;
shadowTextureUnit = GL_TEXTURE2;
} else {
program = &_normalMapProgram;
skinProgram = &_skinNormalMapProgram;
skinLocations = &_skinNormalMapLocations;
}
} else if (mesh.hasSpecularTexture()) {
program = &_specularMapProgram;
skinProgram = &_skinSpecularMapProgram;
skinLocations = &_skinSpecularMapLocations;
if (receiveShadows) {
program = &_shadowSpecularMapProgram;
skinProgram = &_skinShadowSpecularMapProgram;
skinLocations = &_skinShadowSpecularMapLocations;
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 +1758,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 +1773,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 +1808,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);

View file

@ -344,15 +344,30 @@ private:
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 +381,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<Model>)