SceneRefract: Final (hopefully) tweaks for computing the distance through the
object (the set up of the depth texture, the rendering of the back-side pass,
and sampling the depth map), and handling the projection of the transmitted
vector through the object to the exit point. Also added some comments in the
shader to explain the steps.
diff --git a/data/shaders/light-refract.frag b/data/shaders/light-refract.frag
index f71a283..bcc5096 100644
--- a/data/shaders/light-refract.frag
+++ b/data/shaders/light-refract.frag
@@ -13,23 +13,29 @@
const float matShininess = 100.0;
const vec2 point_five = vec2(0.5);
// Need the normalized eye direction and surface normal vectors to
- // compute the refraction vector through the "front" surface of the object.
+ // compute the transmitted vector through the "front" surface of the object.
vec3 eye_direction = normalize(-vertex_position.xyz);
vec3 normalized_normal = normalize(vertex_normal);
- vec3 front_refraction = refract(eye_direction, normalized_normal, 1.5);
- // Offset the base map coordinate by the refaction vector, and re-normalize
- // to texture coordinate space [0, 1].
- vec4 mc_perspective = MapCoord / MapCoord.w;
- vec4 distance_value = texture2D(DistanceMap, mc_perspective.st);
- float frontToBack = distance_value.z - mc_perspective.z;
- vec3 back_position = (front_refraction - vertex_position) + frontToBack;
- vec2 normcoord = (mc_perspective.st + front_refraction.st + point_five) * point_five;
+ vec3 front_refraction = refract(eye_direction, normalized_normal, 1.45);
+ // Find our best distance approximation through the object so we can
+ // project the transmitted vector to the back of the object to find
+ // the exit point.
+ vec3 mc_perspective = (MapCoord.xyz / MapCoord.w) + front_refraction;
+ vec2 dcoord = mc_perspective.st * point_five + point_five;
+ vec4 distance_value = texture2D(DistanceMap, dcoord);
+ vec3 back_position = vertex_position.xyz + front_refraction * distance_value.z;
+ // Use the exit point to index the map of back-side normals, and use the
+ // back-side position and normal to find the transmitted vector out of the
+ // object.
+ vec2 normcoord = back_position.st * point_five + point_five;
vec3 back_normal = texture2D(NormalMap, normcoord).xyz;
- // Now refract again, using the normal from the lookup.
- vec3 back_refraction = refract(back_position, back_normal.xyz, 1.0);
- vec2 imagecoord = (normcoord + back_refraction.st + point_five) * point_five;
+ vec3 back_refraction = refract(back_position, back_normal, 1.0);
+ // Use the transmitted vector from the exit point to determine where
+ // the vector would intersect the environment (in this case a background
+ // image.
+ vec2 imagecoord = back_refraction.st * point_five + point_five;
vec4 texel = texture2D(ImageMap, imagecoord);
- // Add in a specular component
+ // Add in specular reflection, and we have our fragment value.
vec3 light_direction = normalize(vertex_position.xyz/vertex_position.w -
LightSourcePosition.xyz/LightSourcePosition.w);
vec3 reflection = reflect(light_direction, normalized_normal);
diff --git a/src/scene-refract.cpp b/src/scene-refract.cpp
index e7fa659..f4188e0 100644
--- a/src/scene-refract.cpp
+++ b/src/scene-refract.cpp
@@ -203,11 +203,12 @@
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
glBindTexture(GL_TEXTURE_2D, tex_[COLOR]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0,
GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(1, &fbo_);
@@ -254,7 +255,6 @@
glViewport(0, 0, width_, height_);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glCullFace(GL_FRONT);
- glDepthFunc(GL_GREATER);
}
void DistanceRenderTarget::disable()
@@ -262,7 +262,6 @@
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, canvas_width_, canvas_height_);
glCullFace(GL_BACK);
- glDepthFunc(GL_LEQUAL);
}
bool
@@ -271,7 +270,6 @@
// Program object setup
static const string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-refract.vert");
static const string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-refract.frag");
- static const vec4 materialDiffuse(1.0f, 1.0f, 1.0f, 0.0f);
static const vec4 lightColor(0.4, 0.4, 0.4, 1.0);
ShaderSource vtx_source(vtx_shader_filename);
@@ -279,7 +277,6 @@
frg_source.add_const("LightColor", lightColor);
frg_source.add_const("LightSourcePosition", lightPosition);
- frg_source.add_const("MaterialDiffuse", materialDiffuse);
if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), frg_source.str())) {
return false;