Created
November 26, 2010 22:22
-
-
Save alteredq/717285 to your computer and use it in GitHub Desktop.
Chromatic dispersion refraction hack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function generateFragmentShader( maxDirLights, maxPointLights ) { | |
| var chunks = [ | |
| "#ifdef GL_ES", | |
| "precision highp float;", | |
| "#endif", | |
| maxDirLights ? "#define MAX_DIR_LIGHTS " + maxDirLights : "", | |
| maxPointLights ? "#define MAX_POINT_LIGHTS " + maxPointLights : "", | |
| "uniform int material;", // 0 - Basic, 1 - Lambert, 2 - Phong, 3 - Depth, 4 - Normal, 5 - Cube | |
| "uniform bool enableMap;", | |
| "uniform bool enableCubeMap;", | |
| "uniform bool mixEnvMap;", | |
| "uniform samplerCube tCube;", | |
| "uniform float mReflectivity;", | |
| "uniform sampler2D tMap;", | |
| "uniform vec4 mColor;", | |
| "uniform float mOpacity;", | |
| "uniform vec4 mAmbient;", | |
| "uniform vec4 mSpecular;", | |
| "uniform float mShininess;", | |
| "uniform float m2Near;", | |
| "uniform float mFarPlusNear;", | |
| "uniform float mFarMinusNear;", | |
| "uniform int pointLightNumber;", | |
| "uniform int directionalLightNumber;", | |
| maxDirLights ? "uniform mat4 viewMatrix;" : "", | |
| maxDirLights ? "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];" : "", | |
| "varying vec3 vNormal;", | |
| "varying vec2 vUv;", | |
| "varying vec3 vLightWeighting;", | |
| maxPointLights ? "varying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];" : "", | |
| "varying vec3 vViewPosition;", | |
| "varying vec3 vReflect[3];", | |
| "uniform vec3 cameraPosition;", | |
| "void main() {", | |
| "vec4 mapColor = vec4( 1.0, 1.0, 1.0, 1.0 );", | |
| "vec4 cubeColor = vec4( 1.0, 1.0, 1.0, 1.0 );", | |
| // diffuse map | |
| "if ( enableMap ) {", | |
| "mapColor = texture2D( tMap, vUv );", | |
| "}", | |
| // cube map | |
| "if ( enableCubeMap ) {", | |
| // "cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );", | |
| "cubeColor.r = textureCube( tCube, vec3( -vReflect[0].x, vReflect[0].yz ) ).r;", | |
| "cubeColor.g = textureCube( tCube, vec3( -vReflect[1].x, vReflect[1].yz ) ).g;", | |
| "cubeColor.b = textureCube( tCube, vec3( -vReflect[2].x, vReflect[2].yz ) ).b;", | |
| "}", | |
| // Cube | |
| "if ( material == 5 ) { ", | |
| "vec3 wPos = cameraPosition - vViewPosition;", | |
| "gl_FragColor = textureCube( tCube, vec3( -wPos.x, wPos.yz ) );", | |
| // Normals | |
| "} else if ( material == 4 ) { ", | |
| "gl_FragColor = vec4( 0.5*normalize( vNormal ) + vec3(0.5, 0.5, 0.5), mOpacity );", | |
| // Depth | |
| "} else if ( material == 3 ) { ", | |
| // this breaks shader validation in Chrome 9.0.576.0 dev | |
| // and also latest continuous build Chromium 9.0.583.0 (66089) | |
| // (curiously it works in Chrome 9.0.576.0 canary build and Firefox 4b7) | |
| //"float w = 1.0 - ( m2Near / ( mFarPlusNear - gl_FragCoord.z * mFarMinusNear ) );", | |
| "float w = 0.5;", | |
| "gl_FragColor = vec4( w, w, w, mOpacity );", | |
| // Blinn-Phong | |
| // based on o3d example | |
| "} else if ( material == 2 ) { ", | |
| "vec3 normal = normalize( vNormal );", | |
| "vec3 viewPosition = normalize( vViewPosition );", | |
| // point lights | |
| maxPointLights ? "vec4 pointDiffuse = vec4( 0.0, 0.0, 0.0, 0.0 );" : "", | |
| maxPointLights ? "vec4 pointSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );" : "", | |
| maxPointLights ? "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {" : "", | |
| maxPointLights ? "vec3 pointVector = normalize( vPointLightVector[ i ] );" : "", | |
| maxPointLights ? "vec3 pointHalfVector = normalize( vPointLightVector[ i ] + vViewPosition );" : "", | |
| maxPointLights ? "float pointDotNormalHalf = dot( normal, pointHalfVector );" : "", | |
| maxPointLights ? "float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );" : "", | |
| // Ternary conditional is from the original o3d shader. Here it produces abrupt dark cutoff artefacts. | |
| // Using just pow works ok in Chrome, but makes different artefact in Firefox 4. | |
| // Zeroing on negative pointDotNormalHalf seems to work in both. | |
| //"float specularCompPoint = dot( normal, pointVector ) < 0.0 || pointDotNormalHalf < 0.0 ? 0.0 : pow( pointDotNormalHalf, mShininess );", | |
| //"float specularCompPoint = pow( pointDotNormalHalf, mShininess );", | |
| //"float pointSpecularWeight = pointDotNormalHalf < 0.0 ? 0.0 : pow( pointDotNormalHalf, mShininess );", | |
| // Ternary conditional inside for loop breaks Chrome shader linking. | |
| // Must do it with if. | |
| maxPointLights ? "float pointSpecularWeight = 0.0;" : "", | |
| maxPointLights ? "if ( pointDotNormalHalf >= 0.0 )" : "", | |
| maxPointLights ? "pointSpecularWeight = pow( pointDotNormalHalf, mShininess );" : "", | |
| maxPointLights ? "pointDiffuse += mColor * pointDiffuseWeight;" : "", | |
| maxPointLights ? "pointSpecular += mSpecular * pointSpecularWeight;" : "", | |
| maxPointLights ? "}" : "", | |
| // directional lights | |
| maxDirLights ? "vec4 dirDiffuse = vec4( 0.0, 0.0, 0.0, 0.0 );" : "", | |
| maxDirLights ? "vec4 dirSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );" : "", | |
| maxDirLights ? "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {" : "", | |
| maxDirLights ? "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );" : "", | |
| maxDirLights ? "vec3 dirVector = normalize( lDirection.xyz );" : "", | |
| maxDirLights ? "vec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );" : "", | |
| maxDirLights ? "float dirDotNormalHalf = dot( normal, dirHalfVector );" : "", | |
| maxDirLights ? "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );" : "", | |
| maxDirLights ? "float dirSpecularWeight = 0.0;" : "", | |
| maxDirLights ? "if ( dirDotNormalHalf >= 0.0 )" : "", | |
| maxDirLights ? "dirSpecularWeight = pow( dirDotNormalHalf, mShininess );" : "", | |
| maxDirLights ? "dirDiffuse += mColor * dirDiffuseWeight;" : "", | |
| maxDirLights ? "dirSpecular += mSpecular * dirSpecularWeight;" : "", | |
| maxDirLights ? "}" : "", | |
| // all lights contribution summation | |
| "vec4 totalLight = mAmbient;", | |
| maxDirLights ? "totalLight += dirDiffuse + dirSpecular;" : "", | |
| maxPointLights ? "totalLight += pointDiffuse + pointSpecular;" : "", | |
| // looks nicer with weighting | |
| "if ( mixEnvMap ) {", | |
| "gl_FragColor = vec4( mix( mapColor.rgb * totalLight.xyz * vLightWeighting, cubeColor.rgb, mReflectivity ), mapColor.a );", | |
| "} else {", | |
| "gl_FragColor = vec4( mapColor.rgb * cubeColor.rgb * totalLight.xyz * vLightWeighting, mapColor.a );", | |
| "}", | |
| // Lambert: diffuse lighting | |
| "} else if ( material == 1 ) {", | |
| "if ( mixEnvMap ) {", | |
| "gl_FragColor = vec4( mix( mColor.rgb * mapColor.rgb * vLightWeighting, cubeColor.rgb, mReflectivity ), mColor.a * mapColor.a );", | |
| "} else {", | |
| "gl_FragColor = vec4( mColor.rgb * mapColor.rgb * cubeColor.rgb * vLightWeighting, mColor.a * mapColor.a );", | |
| "}", | |
| // Basic: unlit color / texture | |
| "} else {", | |
| "if ( mixEnvMap ) {", | |
| "gl_FragColor = mix( mColor * mapColor, cubeColor, mReflectivity );", | |
| "} else {", | |
| "gl_FragColor = mColor * mapColor * cubeColor;", | |
| "}", | |
| "}", | |
| "}" ]; | |
| return chunks.join("\n"); | |
| }; | |
| function generateVertexShader( maxDirLights, maxPointLights ) { | |
| var chunks = [ | |
| maxDirLights ? "#define MAX_DIR_LIGHTS " + maxDirLights : "", | |
| maxPointLights ? "#define MAX_POINT_LIGHTS " + maxPointLights : "", | |
| "attribute vec3 position;", | |
| "attribute vec3 normal;", | |
| "attribute vec2 uv;", | |
| "uniform vec3 cameraPosition;", | |
| "uniform bool enableLighting;", | |
| "uniform bool useRefract;", | |
| "uniform int pointLightNumber;", | |
| "uniform int directionalLightNumber;", | |
| "uniform vec3 ambientLightColor;", | |
| maxDirLights ? "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];" : "", | |
| maxDirLights ? "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];" : "", | |
| maxPointLights ? "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];" : "", | |
| maxPointLights ? "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];" : "", | |
| "uniform mat4 objMatrix;", | |
| "uniform mat4 viewMatrix;", | |
| "uniform mat4 modelViewMatrix;", | |
| "uniform mat4 projectionMatrix;", | |
| "uniform mat3 normalMatrix;", | |
| "varying vec3 vNormal;", | |
| "varying vec2 vUv;", | |
| "varying vec3 vLightWeighting;", | |
| maxPointLights ? "varying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];" : "", | |
| "varying vec3 vViewPosition;", | |
| "varying vec3 vReflect[3];", | |
| "uniform float mRefractionRatio;", | |
| "void main(void) {", | |
| // world space | |
| "vec4 mPosition = objMatrix * vec4( position, 1.0 );", | |
| "vViewPosition = cameraPosition - mPosition.xyz;", | |
| // this doesn't work on Mac | |
| //"vec3 nWorld = mat3(objMatrix) * normal;", | |
| "vec3 nWorld = mat3( objMatrix[0].xyz, objMatrix[1].xyz, objMatrix[2].xyz ) * normal;", | |
| // eye space | |
| "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", | |
| "vec3 transformedNormal = normalize( normalMatrix * normal );", | |
| "if ( !enableLighting ) {", | |
| "vLightWeighting = vec3( 1.0, 1.0, 1.0 );", | |
| "} else {", | |
| "vLightWeighting = ambientLightColor;", | |
| // directional lights | |
| maxDirLights ? "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {" : "", | |
| maxDirLights ? "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );" : "", | |
| maxDirLights ? "float directionalLightWeighting = max( dot( transformedNormal, normalize(lDirection.xyz ) ), 0.0 );" : "", | |
| maxDirLights ? "vLightWeighting += directionalLightColor[ i ] * directionalLightWeighting;" : "", | |
| maxDirLights ? "}" : "", | |
| // point lights | |
| maxPointLights ? "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {" : "", | |
| maxPointLights ? "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );" : "", | |
| maxPointLights ? "vPointLightVector[ i ] = normalize( lPosition.xyz - mvPosition.xyz );" : "", | |
| maxPointLights ? "float pointLightWeighting = max( dot( transformedNormal, vPointLightVector[ i ] ), 0.0 );" : "", | |
| maxPointLights ? "vLightWeighting += pointLightColor[ i ] * pointLightWeighting;" : "", | |
| maxPointLights ? "}" : "", | |
| "}", | |
| "vNormal = transformedNormal;", | |
| "vUv = uv;", | |
| "if ( useRefract ) {", | |
| "vReflect[0] = refract( normalize(mPosition.xyz - cameraPosition), normalize(nWorld.xyz), mRefractionRatio );", | |
| "vReflect[1] = refract( normalize(mPosition.xyz - cameraPosition), normalize(nWorld.xyz), mRefractionRatio*0.9 );", | |
| "vReflect[2] = refract( normalize(mPosition.xyz - cameraPosition), normalize(nWorld.xyz), mRefractionRatio*0.8 );", | |
| "} else {", | |
| "vReflect[0] = reflect( normalize(mPosition.xyz - cameraPosition), normalize(nWorld.xyz) );", | |
| "vReflect[1] = reflect( normalize(mPosition.xyz - cameraPosition), normalize(nWorld.xyz) );", | |
| "vReflect[2] = reflect( normalize(mPosition.xyz - cameraPosition), normalize(nWorld.xyz) );", | |
| "}", | |
| "gl_Position = projectionMatrix * mvPosition;", | |
| "}" ]; | |
| return chunks.join("\n"); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment