diff --git a/interface/resources/images/iris.png b/interface/resources/images/iris.png index 3c5b605e3d..0e6251474e 100644 Binary files a/interface/resources/images/iris.png and b/interface/resources/images/iris.png differ diff --git a/interface/resources/shaders/iris.frag b/interface/resources/shaders/iris.frag index 2f5b06d6c6..a5931c3cbe 100644 --- a/interface/resources/shaders/iris.frag +++ b/interface/resources/shaders/iris.frag @@ -15,7 +15,10 @@ uniform sampler2D texture; 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))); - gl_FragColor = vec4(gl_Color.rgb * texture2D(texture, gl_TexCoord[0].st).rgb + - pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 1.0); + + // 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/iris.vert b/interface/resources/shaders/iris.vert index 83602f3e99..8dbc56d66a 100644 --- a/interface/resources/shaders/iris.vert +++ b/interface/resources/shaders/iris.vert @@ -11,10 +11,23 @@ // the interpolated normal varying vec4 normal; +// the ratio of the indices of refraction +const float refractionEta = 0.75; + void main(void) { + + // transform and store the normal for interpolation normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); - gl_FrontColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient + - gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); - gl_TexCoord[0] = gl_MultiTexCoord0; + + // 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); + + // compute the texture coordinate based on where refracted vector hits z=0 in model space + vec4 incidence = normalize(gl_Vertex - gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0)); + vec4 refracted = refract(incidence, normalize(vec4(gl_Normal, 0.0)), refractionEta); + gl_TexCoord[0] = (gl_Vertex - (gl_Vertex.z / refracted.z) * refracted) + vec4(0.5, 0.5, 0.0, 0.0); + + // use standard pipeline transform gl_Position = ftransform(); } diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 63fc6d6c25..26ba8879ca 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -87,12 +87,14 @@ void Head::init() { _irisProgram->setUniformValue("texture", 0); - QImage image = QImage(IRIS_TEXTURE_FILENAME).convertToFormat(QImage::Format_RGB888); + QImage image = QImage(IRIS_TEXTURE_FILENAME).convertToFormat(QImage::Format_ARGB32); glGenTextures(1, &_irisTextureID); glBindTexture(GL_TEXTURE_2D, _irisTextureID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 1, GL_BGRA, GL_UNSIGNED_BYTE, image.constBits()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glBindTexture(GL_TEXTURE_2D, 0); } } @@ -462,73 +464,60 @@ void Head::renderEyeBrows() { void Head::renderEyeBalls() { - // setup the texture to be used on each iris - GLUquadric* irisQuadric = gluNewQuadric(); - gluQuadricTexture(irisQuadric, GL_TRUE); - - gluQuadricOrientation(irisQuadric, GLU_OUTSIDE); - // render white ball of left eyeball glPushMatrix(); glColor3fv(EYEBALL_COLOR); glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); - gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30); + glutSolidSphere(EYEBALL_RADIUS, 30, 30); glPopMatrix(); //render white ball of right eyeball glPushMatrix(); glColor3fv(EYEBALL_COLOR); - glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); - gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30); + glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); + glutSolidSphere(EYEBALL_RADIUS, 30, 30); glPopMatrix(); _irisProgram->bind(); glBindTexture(GL_TEXTURE_2D, _irisTextureID); glEnable(GL_TEXTURE_2D); - glm::vec3 front = getFrontDirection(); + glm::quat orientation = getOrientation(); + glm::vec3 front = orientation * IDENTITY_FRONT; // render left iris glPushMatrix(); { glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); //translate to eyeball position - glPushMatrix(); - //rotate the eyeball to aim towards the lookat position - glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _leftEyePosition); - glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); - float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); - glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); - glRotatef(180.0, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations - glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f); - glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris - gluSphere(irisQuadric, IRIS_RADIUS, 15, 15); - glPopMatrix(); + + //rotate the eyeball to aim towards the lookat position + glm::vec3 targetLookatVector = _lookAtPosition + _saccade - _leftEyePosition; + glm::quat rotation = rotationBetween(front, targetLookatVector) * orientation; + glm::vec3 rotationAxis = glm::axis(rotation); + glRotatef(glm::angle(rotation), rotationAxis.x, rotationAxis.y, rotationAxis.z); + glTranslatef(0.0f, 0.0f, -IRIS_PROTRUSION); + glScalef(IRIS_RADIUS * 2.0f, IRIS_RADIUS * 2.0f, IRIS_RADIUS); // flatten the iris + glutSolidSphere(0.5f, 15, 15); } glPopMatrix(); // render right iris glPushMatrix(); { glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); //translate to eyeball position - glPushMatrix(); - - //rotate the eyeball to aim towards the lookat position - glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _rightEyePosition); - glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); - float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); - glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); - glRotatef(180.0f, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations - glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f); - glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris - gluSphere(irisQuadric, IRIS_RADIUS, 15, 15); - glPopMatrix(); + + //rotate the eyeball to aim towards the lookat position + glm::vec3 targetLookatVector = _lookAtPosition + _saccade - _rightEyePosition; + glm::quat rotation = rotationBetween(front, targetLookatVector) * orientation; + glm::vec3 rotationAxis = glm::axis(rotation); + glRotatef(glm::angle(rotation), rotationAxis.x, rotationAxis.y, rotationAxis.z); + glTranslatef(0.0f, 0.0f, -IRIS_PROTRUSION); + glScalef(IRIS_RADIUS * 2.0f, IRIS_RADIUS * 2.0f, IRIS_RADIUS); // flatten the iris + glutSolidSphere(0.5f, 15, 15); } + glPopMatrix(); _irisProgram->release(); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); - - // delete the iris quadric now that we're done with it - gluDeleteQuadric(irisQuadric); - glPopMatrix(); } void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 93596e1c1d..4bfdb1f587 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -85,7 +85,7 @@ glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2) { if (isnan(angle) || angle < EPSILON) { return glm::quat(); } - glm::vec3 axis = glm::cross(v1, v2); + glm::vec3 axis; if (angle > 179.99f) { // 180 degree rotation; must use another axis axis = glm::cross(v1, glm::vec3(1.0f, 0.0f, 0.0f)); float axisLength = glm::length(axis);