PDA

View Full Version : The goal of refraction or ray tracing



LolPatrol
06-17-2011, 11:06 AM
Hello,
I'm wondering what the best way to achieve this particular goal would be. I create a 3D object (just a few lists of triangles that I've created) which represents a lens (as found in a pair of glasses). This lens can be freely rotated by the user. It rests in front of a stationary background (a quad with a texture).

Ideally, I would like the lens to properly refract the background. That is, to represent that light has passed through the back surface (from one index of refraction to another), some distance through the lens, then back out the front.

I started to think that I might end up drawing the background into a texture, draw one surface's effect on that texture into another, then draw the other surface's effect on that texture into a third, but that all seems quite a bit much, nor does it account for when the object is rotated 180.

Any suggestions? Thank you very much!

Ilian Dinev
06-17-2011, 11:34 AM
Instead of redrawing scene, glCopyTexSubImage2D .
On cpu, take the two refractive objects' centers, calculate their z after transformation to cameraspace, sort by that z - to know which should be rendered first.

LolPatrol
06-17-2011, 12:11 PM
Are there any good examples around of using glCopyTexSubImage2D in the manner you suggest?

Thank you.

Ilian Dinev
06-17-2011, 12:15 PM
The doc is fairly straightforward - it simply copies whatever's in the backbuffer, to a texture. Then you use that texture are the "background" you mentioned.

LolPatrol
06-17-2011, 12:36 PM
Unfortunately, I'm a little lost as to where that would come in. Would it be a process like the following?

Draw background.
Enable refaction shader
Draw back of object.
Disable refraction shader
Copy buffer to texture.
Clear buffer.
Draw background from texture.
Enable refaction shader
Draw side of object.
Disable refraction shader
Copy buffer to texture.
Clear buffer.
Draw background from texture
Enable refaction shader
Draw front of object.
Disable refraction shader
Flush to screen

LolPatrol
06-19-2011, 12:29 PM
So with the following vertex and fragment shaders...

vertexSource :=
'varying vec3 normal, view;' +
'void main(void){' +
'gl_Position = ftransform();' +
'normal = normalize(gl_NormalMatrix * gl_Normal);' +
'view = normalize(gl_ModelViewMatrix * gl_Vertex).xyz;' +
'}';

fragmentSource :=
'varying vec3 normal, view;' +
'uniform samplerCube Environment;' +
'void main(void){' +
'vec3 refrTexCoord = refract(-view, normal, 1.5);' +
'vec4 refrCol = textureCube(Environment, refrTexCoord);' +
'gl_FragColor = refrCol;' +
'}';

I notice two things. One is that the whole triangle is colored with the texture at the vertex, rather than texturing the pixels. The other is that when a certain angle is reached for a given triangle, it stops being textured with the cube map and switches to that beige. There's a third issue that it doesn't seem to be refracting what I would expect when I rotate it, but it's hard to tell when it's rendering a single color per triangle, so I'd like to attack that problem first. I've attached two pictures (hopefully) which show these two issues.

Thank you for any help you're able to offer!

dorbie
06-21-2011, 01:00 PM
Render the refracted scene to a texture. Texture the refracting surface with this texture. In the shader distort the texture using adjusted texture coordinate information using view vector and surface normal information.

Once this works you can then consider more accurate and sophisticated methods that for example account for refracted scene depth.

Basically a refraction demo is going to probably need reflection too and there are different apporaches depending on your scene, for example a well bounded 3D object can be rendered like this using a cubemap, but a water surface is best drawn as a reflected and refracted projection and then used in the shader.

There are examples of these methods available online and in SDKs.

dorbie
06-21-2011, 01:05 PM
OK I just caught up with your latest post, are you flatshading the surface normals?

It seems that the issue is either your vertex data is not sharing surface normals at the vertices of the object facets leading to a discontinuity or your surface normal or varying interpolation of the normal is being defeated by flatshading.

Either one would lead to a visual appearance similar to your results.

LolPatrol
06-21-2011, 02:04 PM
Thank you for your reply.

For what you mention in your first post: "Render the refracted scene to a texture. Texture the refracting surface with this texture. In the shader distort the texture using adjusted texture coordinate information using view vector and surface normal information." To rephrase this to check my understanding, those steps would be
1) Draw the background
2) Draw the triangles for face the lens that's furthest away, and use a shader to refract through that face to the background.
3) Copy the framebuffer to a texture.
4) Draw the triangles for the closet face of the lens, and use a shader to texture it with the new texture....

...actually I'm not sure about that "using adjusted texture coordinate information using view vector and surface normal information" part. Would that just be refracting through the back of the lens as a lookup to the modified texture? My apologies for my lack of understanding.

I did find that removing the negation of the view matrix in the texture coordinate lookup line fixed most of that triangle hubbub, and lowering the ratio in indices of refraction stopped the loss-of-texturing (as shown in the attached picture (I also added a slight tinge of blue to make the lens easier to see). I switched over to using a grid as the background and for all sides of the cube map.

One thing I'm surely going to run in to is to have the distance to the background represent the same distance to the cube map. Currently, the object is pulling its only color detail from the cube map (via the textureCube(Environment, refrTexCoord);). I'm not too sure how to have the background properly proportioned when using it in conjunction with the cube map. I suppose the texture I replace in step 3 up above could be one of the sides of the cube map so that I don't have to worry about the background.

On an unrelated note, why would a call to glCallList cause all the triangle windings to reverse? I have to reverse the vertex order in how I draw triangles and create normals because the first time I display text with glCallList, the culling flip-flops.