diff --git a/interface/resources/shaders/blendface.frag b/interface/resources/shaders/blendface.frag new file mode 100644 index 0000000000..ad37e514b9 --- /dev/null +++ b/interface/resources/shaders/blendface.frag @@ -0,0 +1,24 @@ +#version 120 + +// +// blendface.frag +// fragment shader +// +// Created by Andrzej Kapolka on 10/14/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the diffuse texture +uniform sampler2D texture; + +// the interpolated normal +varying vec4 normal; + +void main(void) { + // compute the specular component (sans exponent) based on the normal OpenGL lighting model + float specular = max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), normalize(normal))); + + // modulate texture by diffuse color and add specular contribution + gl_FragColor = gl_Color * texture2D(texture, gl_TexCoord[0].st) + + pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular; +} diff --git a/interface/resources/shaders/blendface.vert b/interface/resources/shaders/blendface.vert new file mode 100644 index 0000000000..5556000b0e --- /dev/null +++ b/interface/resources/shaders/blendface.vert @@ -0,0 +1,28 @@ +#version 120 + +// +// blendface.vert +// vertex shader +// +// Created by Andrzej Kapolka on 10/14/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the interpolated normal +varying vec4 normal; + +void main(void) { + + // transform and store the normal for interpolation + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + + // compute standard diffuse lighting per-vertex + gl_FrontColor = vec4(gl_Color.rgb * (gl_LightModel.ambient.rgb + gl_LightSource[0].ambient.rgb + + gl_LightSource[0].diffuse.rgb * max(0.0, dot(normal, gl_LightSource[0].position))), gl_Color.a); + + // pass along the texture coordinate + gl_TexCoord[0] = gl_MultiTexCoord0; + + // use standard pipeline transform + gl_Position = ftransform(); +} diff --git a/interface/resources/shaders/skin_blendface.vert b/interface/resources/shaders/skin_blendface.vert index d3d833d6fe..2bd1e35525 100644 --- a/interface/resources/shaders/skin_blendface.vert +++ b/interface/resources/shaders/skin_blendface.vert @@ -16,9 +16,12 @@ uniform mat4 clusterMatrices[MAX_CLUSTERS]; attribute vec4 clusterIndices; attribute vec4 clusterWeights; +// the interpolated normal +varying vec4 normal; + void main(void) { vec4 position = vec4(0.0, 0.0, 0.0, 0.0); - vec4 normal = vec4(0.0, 0.0, 0.0, 0.0); + normal = vec4(0.0, 0.0, 0.0, 0.0); for (int i = 0; i < INDICES_PER_VERTEX; i++) { mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])]; float clusterWeight = clusterWeights[i]; diff --git a/interface/src/avatar/BlendFace.cpp b/interface/src/avatar/BlendFace.cpp index b438769f5e..b0992488d5 100644 --- a/interface/src/avatar/BlendFace.cpp +++ b/interface/src/avatar/BlendFace.cpp @@ -28,30 +28,32 @@ BlendFace::~BlendFace() { deleteGeometry(); } -ProgramObject BlendFace::_eyeProgram; +ProgramObject BlendFace::_program; ProgramObject BlendFace::_skinProgram; int BlendFace::_clusterMatricesLocation; int BlendFace::_clusterIndicesLocation; int BlendFace::_clusterWeightsLocation; void BlendFace::init() { - if (!_eyeProgram.isLinked()) { + if (!_program.isLinked()) { switchToResourcesParentIfRequired(); - _eyeProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/eye.vert"); - _eyeProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/iris.frag"); - _eyeProgram.link(); + _program.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/blendface.vert"); + _program.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/blendface.frag"); + _program.link(); - _eyeProgram.bind(); - _eyeProgram.setUniformValue("texture", 0); - _eyeProgram.release(); + _program.bind(); + _program.setUniformValue("texture", 0); + _program.release(); _skinProgram.addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/skin_blendface.vert"); + _skinProgram.addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/blendface.frag"); _skinProgram.link(); _skinProgram.bind(); _clusterMatricesLocation = _skinProgram.uniformLocation("clusterMatrices"); _clusterIndicesLocation = _skinProgram.attributeLocation("clusterIndices"); _clusterWeightsLocation = _skinProgram.attributeLocation("clusterWeights"); + _skinProgram.setUniformValue("texture", 0); _skinProgram.release(); } } @@ -288,7 +290,10 @@ bool BlendFace::render(float alpha) { } else { glPushMatrix(); glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]); + _program.bind(); } + } else { + _program.bind(); } glBindTexture(GL_TEXTURE_2D, texture == NULL ? 0 : texture->getID()); @@ -349,7 +354,10 @@ bool BlendFace::render(float alpha) { } else { glPopMatrix(); + _program.release(); } + } else { + _program.release(); } } diff --git a/interface/src/avatar/BlendFace.h b/interface/src/avatar/BlendFace.h index 9a6d87f275..6add54d6b8 100644 --- a/interface/src/avatar/BlendFace.h +++ b/interface/src/avatar/BlendFace.h @@ -82,7 +82,7 @@ private: QVector _blendedVertices; QVector _blendedNormals; - static ProgramObject _eyeProgram; + static ProgramObject _program; static ProgramObject _skinProgram; static int _clusterMatricesLocation; static int _clusterIndicesLocation;