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
1.2.14 written by Dimitri van Heesch,
© 1997-2002