10
\$\begingroup\$

I have an infinite hexagonal floor, generated by tessellating a point grid in a tessellation shader pair:

enter image description here

Note that this is a flat wireframe - the "shadows" are a lighting trick:

enter image description here

Now, I'd like to make this appear to be thick, refractive glass, but am unsure how to proceed.

The first thing that came to mind is to

  1. set a uniform containing the requested "thickness" of the blocks
  2. When calculating lighting, use Snell's law to calculate the optical path length a ray would take through the hex block, if it were actually as thick as the "thickness" uniform says, and sum the alpha over that length. That would give the transparency, but doesn't handle things like internal reflection / TIR, etc.

enter image description here

I haven't tried that yet, so I'm not sure what the visual result would be.

Ultimately, for this particular level, I'm trying to get that glass, hexagonal floor look used in Tron: Legacy during the disc battle. (See this image for an example.)

Suggestions?

\$\endgroup\$
  • 1
    \$\begingroup\$ Can you explain more what look you're trying to achieve? The Tron shot shows mostly reflection, AFAICT, not refraction - you can't really see through the floor plates in most shots. Assuming you don't just want a shiny surface, what do you want to see through the floor? Is there a subfloor texture you want to show? Is there a whole scene under the floor (like in Tron)? Or do you want it to be more like frosted glass where you can't see a distinct image, but have a subsurface scattering effect? \$\endgroup\$ – Nathan Reed Mar 5 '14 at 21:19
  • \$\begingroup\$ Subsurface scattering, though I didn't know that's what it is called. Makes Googling easier. :) \$\endgroup\$ – 3Dave Mar 5 '14 at 23:09
4
\$\begingroup\$

This article in GPU Gems goes into depth about refraction, which can give pretty nice results

(a)Complete transparency (b)Refractive glass

In the most basic sense

The first step of the basic refraction technique is to render the scene geometry into a texture, skipping all refractive meshes. This texture can be used to determine which objects are visible behind the refractive objects that will be rendered in a subsequent pass. We denote this texture as S.

The second step is to render the refractive meshes, looking up values from the texture S with a perturbation applied to simulate the refractive look. The perturbation can be achieved using a normal map N, where the normal-map red and green (XY) components are used and scaled by some small value to add a displacement into the projected texture coordinates. This approach is straightforward to implement in a shader:

  1. fetch the texture N
  2. use the XY components scaled by a small value (such as 0.05)
  3. add this displacement value into the projected texture coordinates for S

The following listing shows a shader that demonstrates this approach

half4 main(float2 bumpUV : TEXCOORD0,
  float4 screenPos : TEXCOORD1,
  uniform sampler2D tex0,
  uniform sampler2D tex1,
  uniform float4 vScale) : COLOR
{
  // fetch bump texture, unpack from [0..1] to [-1..1]
  half4 bumpTex=2.0 * tex2D(tex0, bumpUV.xy) - 1.0;

  // displace texture coordinates    
  half2 newUV = (screenPos.xy/screenPos.w) + bumpTex.xy * vScale.xy;

  // fetch refraction map
  return tex2D(tex1, newUV);
}

The next images illustrates these three steps

The three steps listed in the shader above

There are more advanced techniques in the same article which can achieve a much more appealing look


For a similar effect in Unity, You might want to have a look at The Refraction Shader wiki page

\$\endgroup\$
3
\$\begingroup\$

I will take the image you showed as a reference for how I imagine the effect. The algorithm I can think of is simple:

  1. Render the environment into a cube map texture inorder to simulate the environment reflection.
  2. Apply the cube map texture into a plane that represents the layer below the refractive floor. Don't render the plane yet.
  3. Render the plane into a texture, a normal 2D texture.
  4. Pass the texture to the refractive shader used to render the refractive floor.
  5. Now render the refractive meshes/floor with a refraction shader.

Regarding the refraction shader, inorder to simulate the glass you can do

  • Use fresnel term to simulate the reflection and refraction.
  • Use the normals/normal map to do a texture fetch.

I just thought of the idea, so I didn't test it. I am sure it needs more work, Maybe I will do once I return from work.

\$\endgroup\$
  • \$\begingroup\$ Interesting approach - I'll have to stew on that one for a bit. Thanks for the input. \$\endgroup\$ – 3Dave Mar 6 '14 at 22:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.