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.36 $ $Date: 2020年02月24日 21:25:51 $ 00014 * 00015 ***************************************************************************/ 00030 00035 #version 110 00036 00038 #define FASTONESIDEDSPHERES 1 00039 00040 // 00041 // Fragment shader varying and uniform variable definitions for data 00042 // supplied by VMD and/or the vertex shader 00043 // 00044 varying vec3 oglcolor; 00045 varying vec3 V; 00046 varying vec3 spherepos; 00047 varying vec3 rayorigin; 00048 varying float sphereradsq; 00049 00050 uniform vec3 vmdlight0; 00051 uniform vec3 vmdlight1; 00052 uniform vec3 vmdlight2; 00053 uniform vec3 vmdlight3; 00054 00055 uniform vec3 vmdlight0H; 00056 uniform vec3 vmdlight1H; 00057 uniform vec3 vmdlight2H; 00058 uniform vec3 vmdlight3H; 00059 00060 uniform vec4 vmdlightscale; 00061 00062 00063 00064 00065 00066 00067 uniform vec4 vmdmaterial; 00068 00069 00070 00071 00072 00073 uniform int vmdprojectionmode; 00074 uniform vec4 vmdprojparms; 00075 00076 00077 00078 00079 00080 uniform float vmdopacity; 00081 00082 uniform float vmdoutline; 00083 uniform float vmdoutlinewidth; 00084 uniform int vmdtransmode; 00085 uniform int vmdfogmode; 00086 uniform int vmdtexturemode; 00087 uniform sampler3D vmdtex0; 00088 00089 00093 void main(void) { 00094 vec3 raydir = normalize(V); 00095 vec3 spheredir = spherepos - rayorigin; 00096 00097 // 00098 // Perform ray-sphere intersection tests based on the code in Tachyon 00099 // 00100 float b = dot(raydir, spheredir); 00101 float disc = b*b + sphereradsq - dot(spheredir, spheredir); 00102 00103 #if defined(FASTONESIDEDSPHERES) 00104 // only calculate the nearest intersection, for speed 00105 if (disc <= 0.0) 00106 discard; // ray missed sphere entirely, discard fragment 00107 00108 // calculate closest intersection 00109 float tnear = b - sqrt(disc); 00110 00111 if (tnear < 0.0) 00112 discard; 00113 #else 00114 // calculate and sort both intersections 00115 if (disc <= 0.0) 00116 discard; // ray missed sphere entirely, discard fragment 00117 00118 disc = sqrt(disc); 00119 00120 // calculate farthest intersection 00121 float t2 = b + disc; 00122 if (t2 <= 0.0) 00123 discard; // farthest intersection is behind the eye, discard fragment 00124 00125 // calculate closest intersection 00126 float t1 = b - disc; 00127 00128 // select closest intersection in front of the eye 00129 float tnear; 00130 if (t1 > 0.0) 00131 tnear = t1; 00132 else 00133 tnear = t2; 00134 #endif 00135 00136 // calculate hit point and resulting surface normal 00137 vec3 pnt = rayorigin + tnear * raydir; 00138 vec3 N = normalize(pnt - spherepos); 00139 00140 // Output the ray-sphere intersection point as the fragment depth 00141 // rather than the depth of the bounding box polygons. 00142 // The eye coordinate Z value must be transformed to normalized device 00143 // coordinates before being assigned as the final fragment depth. 00144 if (vmdprojectionmode == 1) { 00145 // perspective projection = 0.5 + (hfpn + (f * n / pnt.z)) / diff 00146 gl_FragDepth = 0.5 + (vmdprojparms[2] + (vmdprojparms[1] * vmdprojparms[0] / pnt.z)) * vmdprojparms[3]; 00147 } else { 00148 // orthographic projection = 0.5 + (-hfpn - pnt.z) / diff 00149 gl_FragDepth = 0.5 + (-vmdprojparms[2] - pnt.z) * vmdprojparms[3]; 00150 } 00151 00152 // Done with ray-sphere intersection test and normal calculation 00153 // beginning of shading calculations 00154 float ambient = vmdmaterial[0]; // ambient 00155 float diffuse = 0.0; 00156 float specular = 0.0; 00157 float shininess = vmdmaterial[3]; // shininess 00158 vec3 objcolor = oglcolor; // default if texturing is disabled 00159 00160 // perform texturing operations for volumetric data 00161 // The only texturing mode that applies to the sphere shader 00162 // is the GL_MODULATE texturing mode with texture coordinate generation. 00163 // The other texturing mode is never encountered in the sphere shader. 00164 // Note: texsture fetches cannot occur earlier than this point since we 00165 // don't know the fragment depth until this poing. 00166 if (vmdtexturemode == 1) { 00167 // emulate GL_MODULATE 00168 // The 3-D texture coordinates must be updated based 00169 // on the eye coordinate of the ray-sphere intersection in this case 00170 vec3 spheretexcoord; 00171 vec4 specpos = vec4(pnt, 1.0); 00172 spheretexcoord.s = dot(specpos, gl_EyePlaneS[0]); 00173 spheretexcoord.t = dot(specpos, gl_EyePlaneT[0]); 00174 spheretexcoord.p = dot(specpos, gl_EyePlaneR[0]); 00175 objcolor = oglcolor * vec3(texture3D(vmdtex0, spheretexcoord)); 00176 } 00177 00178 // calculate diffuse lighting contribution 00179 diffuse += max(0.0, dot(N, vmdlight0)) * vmdlightscale[0]; 00180 diffuse += max(0.0, dot(N, vmdlight1)) * vmdlightscale[1]; 00181 diffuse += max(0.0, dot(N, vmdlight2)) * vmdlightscale[2]; 00182 diffuse += max(0.0, dot(N, vmdlight3)) * vmdlightscale[3]; 00183 diffuse *= vmdmaterial[1]; // diffuse scaling factor 00184 00185 // compute edge outline if enabled 00186 if (vmdoutline > 0.0) { 00187 float edgefactor = dot(N,V); 00188 edgefactor = 1.0 - (edgefactor*edgefactor); 00189 edgefactor = 1.0 - pow(edgefactor, (1.0-vmdoutlinewidth)*32.0); 00190 diffuse = mix(diffuse, diffuse * edgefactor, vmdoutline); 00191 } 00192 00193 // Calculate specular lighting contribution with Phong highlights, based 00194 // on Blinn's halfway vector variation of Phong highlights 00195 specular += pow(max(0.0, dot(N, vmdlight0H)), shininess) * vmdlightscale[0]; 00196 specular += pow(max(0.0, dot(N, vmdlight1H)), shininess) * vmdlightscale[1]; 00197 specular += pow(max(0.0, dot(N, vmdlight2H)), shininess) * vmdlightscale[2]; 00198 specular += pow(max(0.0, dot(N, vmdlight3H)), shininess) * vmdlightscale[3]; 00199 specular *= vmdmaterial[2]; // specular scaling factor 00200 00201 // Fog computations 00202 const float Log2E = 1.442695; // = log2(2.718281828) 00203 float fog = 1.0; 00204 if (vmdfogmode == 1) { 00205 // linear fog 00206 fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale; 00207 } else if (vmdfogmode == 2) { 00208 // exponential fog 00209 fog = exp2(-gl_Fog.density * gl_FogFragCoord * Log2E); 00210 } else if (vmdfogmode == 3) { 00211 // exponential-squared fog 00212 fog = exp2(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord * Log2E); 00213 } 00214 fog = clamp(fog, 0.0, 1.0); // clamp the final fog parameter [0->1) 00215 00216 vec3 color = objcolor * vec3(diffuse) + vec3(ambient + specular); 00217 00218 float alpha = vmdopacity; 00219 00220 // Emulate Raster3D's angle-dependent surface opacity if enabled 00221 if (vmdtransmode==1) { 00222 alpha = 1.0 + cos(3.1415926 * (1.0-alpha) * dot(N,V)); 00223 alpha = alpha*alpha * 0.25; 00224 } 00225 00226 gl_FragColor = vec4(mix(vec3(gl_Fog.color), color, fog), alpha); 00227 } 00228 00229