Axiverse

Members
  • Content count

    760
  • Joined

  • Last visited

Community Reputation

366 Neutral

1 Follower

About Axiverse

  • Rank
    Advanced Member

Personal Information

  • Interests
    Business
    Programming
  1. Need Help Choosing Art Style

    I agree that the bottom one looks more polished. However I think that's because you only use black for line art in the top screen. I think if you played with the colors in the line art, it could look quite good. Look around at other examples, you'll see that usually it's a dark color, but there are cases where the line art can be a very light color against a dark background, etc. It also can be utilized to give the art more character as well. If you can get that to work, I'd say go with the top, otherwise bottom.
  2. So, I've found that PID systems solves for what I'm trying to do. This thread seems to be a pretty good starting point. I'm still trying to figure out do velocity as I'm shooting through the target at max velocity at the moment. https://forum.unity.com/threads/spaceship-control-using-pid-controllers.191755/
  3. I'm working on a spaceship simulation and am working on implementing autopilot. Setting the right torque in order to make the ship's heading in the right direction has been tricky. The parts I'm not sure about are how to properly translate the quaternion difference to torque and how to do it ignoring the roll of the ship. When I set the target to a identity quaternion, it seems to align just fine, but anything else, and it goes haywire. The simulation starts with a random quaternion normalized. The steps I'm currently taking are: Compute the target heading (forward is unit Y, I want it to point to unit X, I get {[ 0, 0, -0.7071068, 0.7071068 ]} in xyzw) Compute the delta orientation (I don't know how to tell it to ignore roll or choose the closet roll with this rotation). Covert it to euler. Subtract the current velocity from the euler velocity, The euler velocity is the target we are aiming for. Apply it as torque. Quaternion target = Quaternion.FromVectors(Vector3.UnitY, Vector3.UnitX); //Quaternion.Identity; Quaternion current = Entity.AngularPosition; Quaternion deltaOrientation = target * current.Inverse(); Vector3 euler = Quaternion.ToEuler(deltaOrientation); Vector3 difference = euler - Entity.AngularVelocity; //Quaternion deltaVelocity = deltaOrientation * Quaternion.FromEuler(Entity.AngularVelocity).Inverse(); //difference = Quaternion.ToEuler(deltaOrientation); //Entity.AngularVelocity = new Vector3(); Entity.ResetForces(); Entity.ApplyTorque(difference); // Primary thrusters var heading = Entity.AngularPosition.Transform(Vector3.UnitY); Entity.ApplyCentralForce(heading); base.Step(delta); Console.WriteLine($"\tNavigating {euler}\n\tHeading {heading}"); The integration code is based on bullet physics. I think that the angularVelocity is convertable to euler rotation, but I'm not sure. Also generally euler is clamped, which doesn't work here. But since the equations I've come across all seem to expect the clamp, I don't know if it works correctly with unclamped values. float angle = angularVelocity.Length(); Vector3 axis; if (angle < 0.001f) { // use Taylor's expansions of sync function axis = angularVelocity * (0.5f * delta - (delta * delta * delta) * 0.020833333333f) * angle * angle; } else { axis = angularVelocity * ((float)Math.Sin(0.5f * angle * delta) / angle); } Quaternion deltaOrientation = new Quaternion(axis, (float)Math.Cos(0.5f * angle * delta)); angularPosition = angularPosition * deltaOrientation; angularPosition = angularPosition.Normalize();
  4. I was trying to debug some zfighting issues in my d3d_12. I was using a depth stencil with the D32_FLOAT format, my camera was set to perspective with near being 0.0001f and far being 20.0f. The camera was 5 units away and the 3d model in question was approximately 1 unit deep. I was experiencing z-fighting issues which I found strange since the camera range was so narrow. When I used the graphics debugger, I found that the depth buffer only used values in the range of 0.9999+ - 1, which seems like a really narrow range given how the camera was set up. Changing the near to 0.01f fixed the z-fighting issues, but the z-buffer is still only utilizing 0.998-1. I thought that depth buffers were linear by default, have they change to logarithmic by default or how is it calculated?
  5. I've gotten pretty far with earth rendering as in the attached picture. I'm looking into rendering stars. I really like how the stars are rendered in elite dangerous but I have no clue how to start working towards this. Has anyone worked on something similar that can give me some pointers on where to start?
  6. I'm trying to cut polygons into smaller polygons constrained by a grid. I'm wondering if there's a fast way to do this other than normal poly-poly clipping because I'm dealing with a large amount of points on a comsumer's computer (via javascript).   The application is that I want to cut country boundries by longitude and latitude lines before tessellating them so they don't get clipped by the sphere that they will be matted on. If I don't do this then large triangles will go inside the sphere.
  7. I'm making a planet renderer, kind of like Google Earth. I want to implement tiling, so that different parts of the map can load like in Google Maps when you pan or zoom in or out. I'm having a hard time figuring out how to figure out what areas of the sphere exists in the view frustum and should be loaded or displayed.   Any suggestions?   Thanks.
  8. I'm trying to render a starfield properly. I'm doing something similar to the new google maps zoomed out where you can see the entire planet and stars. However, right now in my implementation i'm basically drawing a sphere with the stars in the scene. When you zoom in or out the stars get zoomed in or out, but i think the right implementation is that they don't move. How would I properly render that?   basically right now the sky is a sphere(5000), and the earth is a sphere(10) and the camera moves in and out looking at the earth. when i zoom in, a narrower area of the sky is shown, I don't think this is correct, is it? Would I scale the sky inversely to the camera zoom? -> the more the camera is zoomed, the smaller the sky is?
  9. What approaches would be best for space partitioning on a sphere? I'm working with a visualizing data on the surface of the earth.   Some operations that would be relevant Find the closest stored point to a given point See if a the given point is within a region Adding and removing points and regions   Currently, some of the approaches that I've thought of taking are: Start with a octahedron and do triangle tessellation, 4 triangles to each parent triangle. I'm not sure how to approach indexing nodes from latitude, longitude. The pros would be that the partitions would be basically equal area. Quadtree, with the first level separated by north/south hemisphere (positive/negative y) and then a normal quadtree based on the x, z coordinates. This might be a bit easier to index, but leaves might not be balanced well. Are there any other common approaches that you guys know of or can think of?   Thanks!
  10. Yeah, I'm working with arbitrary polygons. I think the better approach is converting between projections. I found a number of projections called equal-area projections that means that the polygon area is correct because points near the poles are closer together vertically.
  11. How to calculate polyhedra in realtime...

    The internet is slow here so I won't post any links, cause I do any searches... It's annoying being out of country. Anyways, from a technical standpoint..., you can create a sphere using n points if you look for "distributing points on a sphere" - there seems to be a formula based on minimizing electrostatic repulsion which looks pretty good. Then you can convert those points to a mesh using a triangulation purposes.   This is probably way overkill for any practical purposes - but just for you to know for intellectual purposes. =)
  12. How would you go about, or does anyone know of any articles/references on calculating the area of a polygon? (Remember that maps are distorted towards the poles, to the actual area isn't just the polygon area) Or any suggestions on how I might go about calculating this?
  13. Hey, I'm trying to triangulate a country on the surface on the earth. I want to limit the size of the triangles so that when I convert it from 2d points to 3d points they aren't too long/big so that when I overlay it on the surface of the parent sphere it doesn't get clipped under the surface. Is there any way to do this? The shapes are also concave as well.
  14. Got it working. I know I've tried this in the past and it's been a pain in the ass, so I'll post what I've done for future reference. Attached a image of what it looks like. =) I was missing a few uniform variables that I forgot to compute that needed to be sent to the shader.   scene = new THREE.Scene() camera = new THREE.PerspectiveCamera(70, window.innerWidth/window.innerHeight, 0.1, 1000) renderer = new THREE.WebGLRenderer() renderer.setSize(window.innerWidth, window.innerHeight) renderer.setClearColorHex(0x000000, 1) $('div.viewport').append(renderer.domElement) $(window).resize -> camera = new THREE.PerspectiveCamera(70, window.innerWidth/window.innerHeight, 0.1, 1000) renderer.setSize( window.innerWidth, window.innerHeight ) vertexSky = """ // // Atmospheric scattering vertex shader // // Author: Sean O'Neil // // Copyright (c) 2004 Sean O'Neil // uniform vec3 v3LightPosition; // The direction vector to the light source uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels uniform float fCameraHeight; // The camera's current height uniform float fCameraHeight2; // fCameraHeight^2 uniform float fOuterRadius; // The outer (atmosphere) radius uniform float fOuterRadius2; // fOuterRadius^2 uniform float fInnerRadius; // The inner (planetary) radius uniform float fInnerRadius2; // fInnerRadius^2 uniform float fKrESun; // Kr * ESun uniform float fKmESun; // Km * ESun uniform float fKr4PI; // Kr * 4 * PI uniform float fKm4PI; // Km * 4 * PI uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) uniform float fScaleOverScaleDepth; // fScale / fScaleDepth const int nSamples = 3; const float fSamples = 3.0; varying vec3 v3Direction; varying vec3 c0; varying vec3 c1; float scale(float fCos) { float x = 1.0 - fCos; return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); } void main(void) { // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere) vec3 v3Ray = position - cameraPosition; float fFar = length(v3Ray); v3Ray /= fFar; // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere) float B = 2.0 * dot(cameraPosition, v3Ray); float C = fCameraHeight2 - fOuterRadius2; float fDet = max(0.0, B*B - 4.0 * C); float fNear = 0.5 * (-B - sqrt(fDet)); // Calculate the ray's starting position, then calculate its scattering offset vec3 v3Start = cameraPosition + v3Ray * fNear; fFar -= fNear; float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius; float fStartDepth = exp(-1.0 / fScaleDepth); float fStartOffset = fStartDepth * scale(fStartAngle); //c0 = vec3(1.0, 0, 0) * fStartAngle; // Initialize the scattering loop variables float fSampleLength = fFar / fSamples; float fScaledLength = fSampleLength * fScale; vec3 v3SampleRay = v3Ray * fSampleLength; vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); // Now loop through the sample rays vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); for(int i=0; i<nSamples; i++) { float fHeight = length(v3SamplePoint); float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); float fLightAngle = dot(v3LightPosition, v3SamplePoint) / fHeight; float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight; float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle))); vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI)); v3FrontColor += v3Attenuate * (fDepth * fScaledLength); v3SamplePoint += v3SampleRay; } // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); c0 = v3FrontColor * (v3InvWavelength * fKrESun); c1 = v3FrontColor * fKmESun; v3Direction = cameraPosition - position; } """ fragmentSky = """ // // Atmospheric scattering fragment shader // // Author: Sean O'Neil // // Copyright (c) 2004 Sean O'Neil // uniform vec3 v3LightPos; uniform float g; uniform float g2; varying vec3 v3Direction; varying vec3 c0; varying vec3 c1; // Calculates the Mie phase function float getMiePhase(float fCos, float fCos2, float g, float g2) { return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(1.0 + g2 - 2.0 * g * fCos, 1.5); } // Calculates the Rayleigh phase function float getRayleighPhase(float fCos2) { return 0.75 + 0.75 * fCos2; } void main (void) { float fCos = dot(v3LightPos, v3Direction) / length(v3Direction); float fCos2 = fCos * fCos; vec3 color = getRayleighPhase(fCos2) * c0 + getMiePhase(fCos, fCos2, g, g2) * c1; gl_FragColor = vec4(color, 1.0); gl_FragColor.a = gl_FragColor.b; } """ vertexGround = """ // // Atmospheric scattering vertex shader // // Author: Sean O'Neil // // Copyright (c) 2004 Sean O'Neil // // Ported for use with three.js/WebGL by James Baicoianu uniform vec3 v3LightPosition; // The direction vector to the light source uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels uniform float fCameraHeight; // The camera's current height uniform float fCameraHeight2; // fCameraHeight^2 uniform float fOuterRadius; // The outer (atmosphere) radius uniform float fOuterRadius2; // fOuterRadius^2 uniform float fInnerRadius; // The inner (planetary) radius uniform float fInnerRadius2; // fInnerRadius^2 uniform float fKrESun; // Kr * ESun uniform float fKmESun; // Km * ESun uniform float fKr4PI; // Kr * 4 * PI uniform float fKm4PI; // Km * 4 * PI uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) uniform float fScaleOverScaleDepth; // fScale / fScaleDepth uniform sampler2D tDiffuse; varying vec3 v3Direction; varying vec3 c0; varying vec3 c1; varying vec3 vNormal; varying vec2 vUv; const int nSamples = 3; const float fSamples = 3.0; float scale(float fCos) { float x = 1.0 - fCos; return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); } void main(void) { // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere) vec3 v3Ray = position - cameraPosition; float fFar = length(v3Ray); v3Ray /= fFar; // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere) float B = 2.0 * dot(cameraPosition, v3Ray); float C = fCameraHeight2 - fOuterRadius2; float fDet = max(0.0, B*B - 4.0 * C); float fNear = 0.5 * (-B - sqrt(fDet)); // Calculate the ray's starting position, then calculate its scattering offset vec3 v3Start = cameraPosition + v3Ray * fNear; fFar -= fNear; float fDepth = exp((fInnerRadius - fOuterRadius) / fScaleDepth); float fCameraAngle = dot(-v3Ray, position) / length(position); float fLightAngle = dot(v3LightPosition, position) / length(position); float fCameraScale = scale(fCameraAngle); float fLightScale = scale(fLightAngle); float fCameraOffset = fDepth*fCameraScale; float fTemp = (fLightScale + fCameraScale); // Initialize the scattering loop variables float fSampleLength = fFar / fSamples; float fScaledLength = fSampleLength * fScale; vec3 v3SampleRay = v3Ray * fSampleLength; vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; // Now loop through the sample rays vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); vec3 v3Attenuate; for(int i=0; i<nSamples; i++) { float fHeight = length(v3SamplePoint); float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); float fScatter = fDepth*fTemp - fCameraOffset; v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI)); v3FrontColor += v3Attenuate * (fDepth * fScaledLength); v3SamplePoint += v3SampleRay; } // Calculate the attenuation factor for the ground c0 = v3Attenuate; c1 = v3FrontColor * (v3InvWavelength * fKrESun + fKmESun); gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); //gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; //gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1; vUv = uv; vNormal = normal; } """ fragmentGround = """ // // Atmospheric scattering fragment shader // // Author: Sean O'Neil // // Copyright (c) 2004 Sean O'Neil // // Ported for use with three.js/WebGL by James Baicoianu //uniform sampler2D s2Tex1; //uniform sampler2D s2Tex2; uniform float fNightScale; uniform vec3 v3LightPosition; uniform sampler2D tDiffuse; uniform sampler2D tDiffuseNight; varying vec3 c0; varying vec3 c1; varying vec3 vNormal; varying vec2 vUv; void main (void) { //gl_FragColor = vec4(c0, 1.0); //gl_FragColor = vec4(0.25 * c0, 1.0); //gl_FragColor = gl_Color + texture2D(s2Tex1, gl_TexCoord[0].st) * texture2D(s2Tex2, gl_TexCoord[1].st) * gl_SecondaryColor; vec3 diffuseTex = texture2D( tDiffuse, vUv ).xyz; vec3 diffuseNightTex = texture2D( tDiffuseNight, vUv ).xyz; vec3 day = diffuseTex * c0; vec3 night = fNightScale * diffuseNightTex * diffuseNightTex * diffuseNightTex * (1.0 - c0); gl_FragColor = vec4(c1, 1.0) + vec4(day + night, 1.0); } """ radius = 100.0 ### atmosphere = Kr : 0.0025 Km : 0.0010 ESun : 15.0 g : -0.990 innerRadius : radius outerRadius : radius * 1.05 wavelength : [0.650, 0.570, 0.475] scaleDepth : 0.25 mieScaleDepth : 0.1 ### atmosphere = Kr : 0.0025 Km : 0.0010 ESun : 20.0 g : -0.950 innerRadius : 100 outerRadius : 102.5 wavelength : [0.650, 0.570, 0.475] scaleDepth : 0.25 mieScaleDepth : 0.1 diffuse = THREE.ImageUtils.loadTexture('/map-small.jpg') diffuseNight = THREE.ImageUtils.loadTexture('/map-lights.jpg') maxAnisotropy = renderer.getMaxAnisotropy(); diffuse.anisotropy = maxAnisotropy; diffuseNight.anisotropy = maxAnisotropy; uniforms = v3LightPosition: type: "v3" value: new THREE.Vector3(1e8, 0, 1e8).normalize() v3InvWavelength: type: "v3" value: new THREE.Vector3(1 / Math.pow(atmosphere.wavelength[0], 4), 1 / Math.pow(atmosphere.wavelength[1], 4), 1 / Math.pow(atmosphere.wavelength[2], 4)) fCameraHeight: type: "f" value: 0 fCameraHeight2: type: "f" value: 0 fInnerRadius: type: "f" value: atmosphere.innerRadius fInnerRadius2: type: "f" value: atmosphere.innerRadius * atmosphere.innerRadius fOuterRadius: type: "f" value: atmosphere.outerRadius fOuterRadius2: type: "f" value: atmosphere.outerRadius * atmosphere.outerRadius fKrESun: type: "f" value: atmosphere.Kr * atmosphere.ESun fKmESun: type: "f" value: atmosphere.Km * atmosphere.ESun fKr4PI: type: "f" value: atmosphere.Kr * 4.0 * Math.PI fKm4PI: type: "f" value: atmosphere.Km * 4.0 * Math.PI fScale: type: "f" value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius) fScaleDepth: type: "f" value: atmosphere.scaleDepth fScaleOverScaleDepth: type: "f" value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius) / atmosphere.scaleDepth g: type: "f" value: atmosphere.g g2: type: "f" value: atmosphere.g * atmosphere.g nSamples: type: "i" value: 3 fSamples: type: "f" value: 3.0 tDiffuse: type: "t" value: diffuse tDiffuseNight: type: "t" value: diffuseNight tDisplacement: type: "t" value: 0 tSkyboxDiffuse: type: "t" value: 0 fNightScale: type: "f" value: 1; ground = geometry: new THREE.SphereGeometry(atmosphere.innerRadius, 50, 50) material: new THREE.ShaderMaterial uniforms: uniforms vertexShader: vertexGround fragmentShader: fragmentGround ground.mesh = new THREE.Mesh(ground.geometry, ground.material) scene.add(ground.mesh) sky = geometry: new THREE.SphereGeometry(atmosphere.outerRadius, 500, 500) material: new THREE.ShaderMaterial uniforms: uniforms vertexShader: vertexSky fragmentShader: fragmentSky sky.mesh = new THREE.Mesh(sky.geometry, sky.material) sky.material.side = THREE.BackSide sky.material.transparent = true; scene.add(sky.mesh) c = null f = 0 g = 0 render = -> requestAnimationFrame(render) # material.uniforms.v3LightPos.value.y += 0.01 f += 0.0002 g += 0.008 vector = new THREE.Vector3(radius * 1.9, 0, 0) euler = new THREE.Vector3(g / 60 + 12, -f * 10 + 20, 0) matrix = new THREE.Matrix4().setRotationFromEuler(euler) eye = matrix.multiplyVector3(vector) camera.position = eye; # camera.position = new THREE.Vector3(radius * 1.9, radius * 1.9 * Math.sin(g), radius * 1.9 * Math.cos(g)) camera.lookAt(new THREE.Vector3(0, 0, 0)) # ground.mesh.rotation.z += 0.005; # ground.mesh.rotation.x += 0.001; # sky.mesh.rotation.z += 0.005; # sky.mesh.rotation.x += 0.001; vector = new THREE.Vector3(1, 0, 0) euler = new THREE.Vector3(f, g, 0) matrix = new THREE.Matrix4().setRotationFromEuler(euler) light = matrix.multiplyVector3(vector) cameraHeight = camera.position.length() sky.material.uniforms.v3LightPosition.value = light sky.material.uniforms.fCameraHeight.value = cameraHeight sky.material.uniforms.fCameraHeight2.value = cameraHeight * cameraHeight ground.material.uniforms.v3LightPosition.value = light ground.material.uniforms.fCameraHeight.value = cameraHeight ground.material.uniforms.fCameraHeight2.value = cameraHeight * cameraHeight renderer.render(scene, camera) render()    
  15. I'm trying to implement O'neil's atmospheric scattering shader in WebGL but I'm a little stuck. I've consulted various sources and am trying to get a working implementation running, but unfortunately all I'm getting is a white circle. Is anyone here familiar with it and could possibly see where I'm going wrong? The shaders below are an implementation of the SkyFromSpace shaders.   scene = new THREE.Scene() camera = new THREE.PerspectiveCamera(70, window.innerWidth/window.innerHeight, 0.1, 1000) renderer = new THREE.WebGLRenderer() renderer.setSize(window.innerWidth, window.innerHeight) renderer.setClearColorHex(0x111111, 1) $('div.viewport').append(renderer.domElement) $(window).resize -> camera = new THREE.PerspectiveCamera(70, window.innerWidth/window.innerHeight, 0.1, 1000) renderer.setSize( window.innerWidth, window.innerHeight ) vertexSky = """ // // Atmospheric scattering vertex shader // // Author: Sean O'Neil // // Copyright (c) 2004 Sean O'Neil // uniform vec3 v3LightPosition; // The direction vector to the light source uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels uniform float fCameraHeight; // The camera's current height uniform float fCameraHeight2; // fCameraHeight^2 uniform float fOuterRadius; // The outer (atmosphere) radius uniform float fOuterRadius2; // fOuterRadius^2 uniform float fInnerRadius; // The inner (planetary) radius uniform float fInnerRadius2; // fInnerRadius^2 uniform float fKrESun; // Kr * ESun uniform float fKmESun; // Km * ESun uniform float fKr4PI; // Kr * 4 * PI uniform float fKm4PI; // Km * 4 * PI uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) uniform float fScaleOverScaleDepth; // fScale / fScaleDepth const int nSamples = 3; const float fSamples = 3.0; varying vec3 v3Direction; varying vec3 c0; varying vec3 c1; float scale(float fCos) { float x = 1.0 - fCos; return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); } void main(void) { // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere) vec3 v3Ray = position - cameraPosition; float fFar = length(v3Ray); v3Ray /= fFar; // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere) float B = 2.0 * dot(cameraPosition, v3Ray); float C = fCameraHeight2 - fOuterRadius2; float fDet = max(0.0, B*B - 4.0 * C); float fNear = 0.5 * (-B - sqrt(fDet)); // Calculate the ray's starting position, then calculate its scattering offset vec3 v3Start = cameraPosition + v3Ray * fNear; fFar -= fNear; float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius; float fStartDepth = exp(-1.0 / fScaleDepth); float fStartOffset = fStartDepth * scale(fStartAngle); //c0 = vec3(1.0, 0, 0) * fStartAngle; // Initialize the scattering loop variables float fSampleLength = fFar / fSamples; float fScaledLength = fSampleLength * fScale; vec3 v3SampleRay = v3Ray * fSampleLength; vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5; //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); // Now loop through the sample rays vec3 v3FrontColor = vec3(0.0, 0.0, 0.0); for(int i=0; i<nSamples; i++) { float fHeight = length(v3SamplePoint); float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); float fLightAngle = dot(v3LightPosition, v3SamplePoint) / fHeight; float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight; float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle))); vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI)); v3FrontColor += v3Attenuate * (fDepth * fScaledLength); v3SamplePoint += v3SampleRay; } // Finally, scale the Mie and Rayleigh colors and set up the varying variables for the pixel shader gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); c0 = v3FrontColor * (v3InvWavelength * fKrESun); c1 = v3FrontColor * fKmESun; v3Direction = cameraPosition - position; } """ fragmentSky = """ // // Atmospheric scattering fragment shader // // Author: Sean O'Neil // // Copyright (c) 2004 Sean O'Neil // uniform vec3 v3LightPos; uniform float g; uniform float g2; varying vec3 v3Direction; varying vec3 c0; varying vec3 c1; // Calculates the Mie phase function float getMiePhase(float fCos, float fCos2, float g, float g2) { return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(1.0 + g2 - 2.0 * g * fCos, 1.5); } // Calculates the Rayleigh phase function float getRayleighPhase(float fCos2) { return 0.75 + 0.75 * fCos2; } void main (void) { float fCos = dot(v3LightPos, v3Direction) / length(v3Direction); float fCos2 = fCos * fCos; vec3 color = getRayleighPhase(fCos2) * c0 + getMiePhase(fCos, fCos2, g, g2) * c1; gl_FragColor = vec4(color, 1.0); gl_FragColor.a = gl_FragColor.b; } """ radius = 1000.0 atmosphere = Kr : 0.0025 Km : 0.0010 ESun : 15.0 g : -0.990 innerRadius : radius outerRadius : radius * 1.05 wavelength : [0.650, 0.570, 0.475] scaleDepth : 0.25 mieScaleDepth : 0.1 uniforms = v3LightPosition: type: "v3" value: new THREE.Vector3(1e8, 0, 1e8).normalize() v3InvWavelength: type: "f" value: new THREE.Vector3(1 / Math.pow(atmosphere.wavelength[0], 4), 1 / Math.pow(atmosphere.wavelength[1], 4), 1 / Math.pow(atmosphere.wavelength[2], 4)) fCameraHeight: type: "f" value: 0 fCameraHeight2: type: "f" value: 0 fInnerRadius: type: "f" value: atmosphere.innerRadius fOuterRadius: type: "f" value: atmosphere.outerRadius fKrESun: type: "f" value: atmosphere.Kr * atmosphere.ESun fKmESun: type: "f" value: atmosphere.Km * atmosphere.ESun fKr4PI: type: "f" value: atmosphere.Kr * 4.0 * Math.PI fKm4PI: type: "f" value: atmosphere.Km * 4.0 * Math.PI fScale: type: "f" value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius) fScaleDepth: type: "f" value: atmosphere.scaleDepth fScaleOverScaleDepth: type: "f" value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius) / atmosphere.scaleDepth g: type: "f" value: atmosphere.g g2: type: "f" value: atmosphere.g * atmosphere.g nSamples: type: "i" value: 3 fSamples: type: "f" value: 3.0 tDiffuse: type: "t" value: 0 texture: null tDiffuseNight: type: "t" value: 0 texture: null tDisplacement: type: "t" value: 0 texture: null tSkyboxDiffuse: type: "t" value: 0 texture: null geometry = new THREE.SphereGeometry(atmosphere.outerRadius, 50, 50) material = new THREE.ShaderMaterial uniforms: uniforms vertexShader: vertexSky fragmentShader: fragmentSky sphere = new THREE.Mesh(geometry, material) scene.add(sphere) c = null f = 0 g = 0 render = -> requestAnimationFrame(render) # material.uniforms.v3LightPos.value.y += 0.01 f += 0.01 g += 0.02 camera.position.z = radius * 1.9 sphere.rotation.z += 0.005; sphere.rotation.x += 0.001; cameraHeight = camera.position.length() material.uniforms.v3LightPosition.value = new THREE.Vector3(0, Math.sin(f), Math.cos(f)) material.uniforms.fCameraHeight.value = cameraHeight material.uniforms.fCameraHeight2.value = cameraHeight * cameraHeight renderer.render(scene, camera) render()   What it should look like: http://www.youtube.com/watch?v=aVLuKN_341Q   Sources: http://forum.unity3d.com/threads/12296-Atmospheric-Scattering-help/page3 http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html http://www.nicholaswoodfield.com/showcase/planetshader.html https://github.com/gwaldron/osgearth/blob/52973323c9cac722daee04561458580cc322c6da/src/osgEarthUtil/SkyNode.cpp