Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

vmdsphere.frag

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 /***************************************************************************
00009  * RCS INFORMATION:
00010  *
00011  *      $RCSfile: vmdsphere.frag,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.35 $       $Date: 2011/04/20 21:14:36 $
00014  *
00015  ***************************************************************************
00016  * DESCRIPTION:
00017  *  This file contains the VMD OpenGL fragment shader implementing 
00018  *  a ray-traced sphere primitive with per-pixel lighting,
00019  *  phong highlights, etc.  The sphere is drawn within the confines of a 
00020  *  correctly transformed bounding cube or viewer-aligned billboard.
00021  *  Much of the shading code is shared with the main VMD fragment shader,
00022  *  with a few optimizations that simplify the sphere shader due to the
00023  *  way it is specifically known to be used within VMD.  (certain texturing
00024  *  modes can't actually occur in practice, so the shader can be simplified
00025  *  relative to what the main fragment shader must implement.
00026  ***************************************************************************/
00027 
00028 // requires GLSL version 1.10
00029 // XXX If/when we implement usage of ARB_sample_shading for 
00030 //     antialiasing of the sphere shader, we will have to 
00031 //     crank the GLSL fragment shader version to 130.
00032 #version 110
00033 
00034 // macro to enable one-sided spheres for improved speed
00035 #define FASTONESIDEDSPHERES     1
00036 
00037 //
00038 // Fragment shader varying and uniform variable definitions for data 
00039 // supplied by VMD and/or the vertex shader
00040 //
00041 varying vec3 oglcolor;         // interpolated color from the vertex shader
00042 varying vec3 V;                // view direction vector
00043 varying vec3 spherepos;
00044 varying vec3 rayorigin;
00045 varying float sphereradsq;
00046 
00047 uniform vec3 vmdlight0;        // VMD directional lights
00048 uniform vec3 vmdlight1;
00049 uniform vec3 vmdlight2;
00050 uniform vec3 vmdlight3;
00051 
00052 uniform vec3 vmdlight0H;       // Blinn halfway vectors for all four lights
00053 uniform vec3 vmdlight1H;
00054 uniform vec3 vmdlight2H;
00055 uniform vec3 vmdlight3H;
00056 
00057 uniform vec4 vmdlightscale;    // VMD light on/off state for all 4 VMD lights,
00058                                // represented as a scaling constant.  Could be
00059                                // done with on/off flags but ATI doesn't deal
00060                                // well with branching constructs, so this value
00061                                // is simply multiplied by the light's 
00062                                // contribution.  Hacky, but it works for now.
00063 
00064 uniform vec4 vmdmaterial;      // VMD material properties
00065                                // [0] is ambient (white ambient light only)
00066                                // [1] is diffuse
00067                                // [2] is specular
00068                                // [3] is shininess
00069 
00070 uniform int vmdprojectionmode; // perspective=1 orthographic=0
00071 uniform vec4 vmdprojparms;     // VMD projection parameters
00072                                // [0] is nearClip
00073                                // [1] is farClip
00074                                // [2] is 0.5 * (farClip + nearClip)
00075                                // [3] is 1.0 / (farClip - nearClip)
00076 
00077 uniform float vmdopacity;      // VMD global alpha value
00078 
00079 uniform float vmdoutline;      // VMD outline shading
00080 uniform float vmdoutlinewidth; // VMD outline shading width
00081 uniform int vmdtransmode;      // VMD transparency mode
00082 uniform int vmdfogmode;        // VMD depth cueing / fog mode
00083 uniform int vmdtexturemode;    // VMD texture mode 0=off 1=modulate 2=replace
00084 uniform sampler3D vmdtex0;     // active 3-D texture map
00085 
00086 
00087 //
00088 // VMD Sphere Fragment Shader (not for normal geometry)
00089 //
00090 void main(void) {
00091   vec3 raydir = normalize(V);
00092   vec3 spheredir = spherepos - rayorigin;
00093    
00094   //
00095   // Perform ray-sphere intersection tests based on the code in Tachyon
00096   //
00097   float b = dot(raydir, spheredir);
00098   float disc = b*b + sphereradsq - dot(spheredir, spheredir);
00099 
00100 #if defined(FASTONESIDEDSPHERES)
00101   // only calculate the nearest intersection, for speed
00102   if (disc <= 0.0)
00103     discard; // ray missed sphere entirely, discard fragment
00104 
00105   // calculate closest intersection
00106   float tnear = b - sqrt(disc);
00107 
00108   if (tnear < 0.0)
00109     discard;
00110 #else
00111   // calculate and sort both intersections
00112   if (disc <= 0.0)
00113     discard; // ray missed sphere entirely, discard fragment
00114 
00115   disc = sqrt(disc);
00116 
00117   // calculate farthest intersection
00118   float t2 = b + disc;
00119   if (t2 <= 0.0)
00120     discard; // farthest intersection is behind the eye, discard fragment
00121 
00122   // calculate closest intersection
00123   float t1 = b - disc;
00124 
00125   // select closest intersection in front of the eye
00126   float tnear;
00127   if (t1 > 0.0)
00128     tnear = t1;
00129   else
00130     tnear = t2;
00131 #endif
00132 
00133   // calculate hit point and resulting surface normal
00134   vec3 pnt = rayorigin + tnear * raydir;
00135   vec3 N = normalize(pnt - spherepos);
00136 
00137   // Output the ray-sphere intersection point as the fragment depth 
00138   // rather than the depth of the bounding box polygons.
00139   // The eye coordinate Z value must be transformed to normalized device 
00140   // coordinates before being assigned as the final fragment depth.
00141   if (vmdprojectionmode == 1) {
00142     // perspective projection = 0.5 + (hfpn + (f * n / pnt.z)) / diff
00143     gl_FragDepth = 0.5 + (vmdprojparms[2] + (vmdprojparms[1] * vmdprojparms[0] / pnt.z)) * vmdprojparms[3];
00144   } else {
00145     // orthographic projection = 0.5 + (-hfpn - pnt.z) / diff
00146     gl_FragDepth = 0.5 + (-vmdprojparms[2] - pnt.z) * vmdprojparms[3];
00147   }
00148 
00149   // Done with ray-sphere intersection test and normal calculation
00150   // beginning of shading calculations
00151   float ambient = vmdmaterial[0];   // ambient
00152   float diffuse = 0.0;
00153   float specular = 0.0;
00154   float shininess = vmdmaterial[3]; // shininess 
00155   vec3 objcolor = oglcolor;         // default if texturing is disabled
00156 
00157   // perform texturing operations for volumetric data
00158   // The only texturing mode that applies to the sphere shader
00159   // is the GL_MODULATE texturing mode with texture coordinate generation.
00160   // The other texturing mode is never encountered in the sphere shader.
00161   // Note: texsture fetches cannot occur earlier than this point since we
00162   // don't know the fragment depth until this poing.
00163   if (vmdtexturemode == 1) {
00164     // emulate GL_MODULATE
00165     // The 3-D texture coordinates must be updated based
00166     // on the eye coordinate of the ray-sphere intersection in this case
00167     vec3 spheretexcoord;
00168     vec4 specpos = vec4(pnt, 1.0);
00169     spheretexcoord.s = dot(specpos, gl_EyePlaneS[0]);
00170     spheretexcoord.t = dot(specpos, gl_EyePlaneT[0]);
00171     spheretexcoord.p = dot(specpos, gl_EyePlaneR[0]);
00172     objcolor = oglcolor * vec3(texture3D(vmdtex0, spheretexcoord));
00173   }
00174 
00175   // calculate diffuse lighting contribution
00176   diffuse += max(0.0, dot(N, vmdlight0)) * vmdlightscale[0];
00177   diffuse += max(0.0, dot(N, vmdlight1)) * vmdlightscale[1];
00178   diffuse += max(0.0, dot(N, vmdlight2)) * vmdlightscale[2];
00179   diffuse += max(0.0, dot(N, vmdlight3)) * vmdlightscale[3];
00180   diffuse *= vmdmaterial[1]; // diffuse scaling factor
00181 
00182   // compute edge outline if enabled
00183   if (vmdoutline > 0.0) {
00184     float edgefactor = dot(N,V);
00185     edgefactor = 1.0 - (edgefactor*edgefactor);
00186     edgefactor = 1.0 - pow(edgefactor, (1.0-vmdoutlinewidth)*32.0);
00187     diffuse = mix(diffuse, diffuse * edgefactor, vmdoutline);
00188   }
00189 
00190   // Calculate specular lighting contribution with Phong highlights, based
00191   // on Blinn's halfway vector variation of Phong highlights
00192   specular += pow(max(0.0, dot(N, vmdlight0H)), shininess) * vmdlightscale[0];
00193   specular += pow(max(0.0, dot(N, vmdlight1H)), shininess) * vmdlightscale[1];
00194   specular += pow(max(0.0, dot(N, vmdlight2H)), shininess) * vmdlightscale[2];
00195   specular += pow(max(0.0, dot(N, vmdlight3H)), shininess) * vmdlightscale[3];
00196   specular *= vmdmaterial[2]; // specular scaling factor
00197 
00198   // Fog computations
00199   const float Log2E = 1.442695; // = log2(2.718281828)
00200   float fog = 1.0;
00201   if (vmdfogmode == 1) {
00202     // linear fog
00203     fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;
00204   } else if (vmdfogmode == 2) {
00205     // exponential fog
00206     fog = exp2(-gl_Fog.density * gl_FogFragCoord * Log2E);
00207   } else if (vmdfogmode == 3) {
00208     // exponential-squared fog
00209     fog = exp2(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord * Log2E);
00210   }
00211   fog = clamp(fog, 0.0, 1.0);       // clamp the final fog parameter [0->1)
00212 
00213   vec3 color = objcolor * vec3(diffuse) + vec3(ambient + specular);
00214 
00215   float alpha = vmdopacity;
00216   
00217   // Emulate Raster3D's angle-dependent surface opacity if enabled
00218   if (vmdtransmode==1) {
00219     alpha = 1.0 + cos(3.1415926 * (1.0-alpha) * dot(N,V));
00220     alpha = alpha*alpha * 0.25;
00221   }
00222 
00223   gl_FragColor = vec4(mix(vec3(gl_Fog.color), color, fog), alpha);
00224 }
00225 
00226 

Generated on Thu May 24 01:51:38 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002