More work on atmosphere rendering; rendering now working.

This commit is contained in:
Andrzej Kapolka 2013-05-07 12:40:15 -07:00
parent a44cb3fcb6
commit 7faa9e4318
7 changed files with 246 additions and 12 deletions

View file

@ -0,0 +1,24 @@
//
// Atmospheric scattering fragment shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//
#version 120
uniform vec3 v3LightPos;
uniform float g;
uniform float g2;
varying vec3 v3Direction;
void main (void)
{
float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);
float fMiePhase = 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos*fCos) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
gl_FragColor = gl_Color + fMiePhase * gl_SecondaryColor;
gl_FragColor.a = 1.0; // gl_FragColor.b;
}

View file

@ -0,0 +1,76 @@
//
// Atmospheric scattering vertex shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//
#version 120
uniform vec3 v3CameraPos; // The camera's current position
uniform vec3 v3LightPos; // The direction vector to the light source
uniform vec3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
uniform float fInnerRadius; // The inner (planetary) radius
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 = 2;
const float fSamples = 2.0;
varying vec3 v3Direction;
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 v3Pos = gl_Vertex.xyz;
vec3 v3Ray = v3Pos - v3CameraPos;
float fFar = length(v3Ray);
v3Ray /= fFar;
// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = v3CameraPos;
float fHeight = length(v3Start);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fStartAngle = dot(v3Ray, v3Start) / fHeight;
float fStartOffset = fDepth*scale(fStartAngle);
// Initialize the scattering loop variables
//gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0);
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);
for(int i=0; i<nSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fLightAngle = dot(v3LightPos, 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_FrontSecondaryColor.rgb = v3FrontColor * fKmESun;
gl_FrontColor.rgb = v3FrontColor * (v3InvWavelength * fKrESun);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
v3Direction = v3CameraPos - v3Pos;
}

View file

@ -5,8 +5,98 @@
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include "Environment.h"
#include <QFile>
#include <QtDebug>
void Environment::render() {
#include "Camera.h"
#include "Environment.h"
#include "world.h"
// checks for an error, printing the info log if one is deteced
static void errorCheck(GLhandleARB obj) {
if (glGetError() != GL_NO_ERROR) {
QByteArray log(1024, 0);
glGetInfoLogARB(obj, log.size(), 0, log.data());
qDebug() << log;
}
}
static GLhandleARB compileShader(int type, const QString& filename) {
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Couldn't find file." << filename;
return 0;
}
GLhandleARB shaderID = glCreateShaderObjectARB(type);
QByteArray source = file.readAll();
const char* sdata = source.constData();
glShaderSource(shaderID, 1, &sdata, 0);
glCompileShaderARB(shaderID);
errorCheck(shaderID);
return shaderID;
}
void Environment::init() {
_skyFromAtmosphereProgramID = glCreateProgramObjectARB();
glAttachObjectARB(_skyFromAtmosphereProgramID, compileShader(
GL_VERTEX_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.vert"));
glAttachObjectARB(_skyFromAtmosphereProgramID, compileShader(
GL_FRAGMENT_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.frag"));
glLinkProgramARB(_skyFromAtmosphereProgramID);
errorCheck(_skyFromAtmosphereProgramID);
_cameraPosLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "v3CameraPos");
_lightPosLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "v3LightPos");
_invWavelengthLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "v3InvWavelength");
_innerRadiusLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fInnerRadius");
_krESunLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fKrESun");
_kmESunLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fKmESun");
_kr4PiLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fKr4PI");
_km4PiLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fKm4PI");
_scaleLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fScale");
_scaleDepthLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fScaleDepth");
_scaleOverScaleDepthLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "fScaleOverScaleDepth");
_gLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "g");
_g2Location = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "g2");
}
void Environment::render(Camera& camera) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(getAtmosphereCenter().x, getAtmosphereCenter().y, getAtmosphereCenter().z);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPerspective(camera.getFieldOfView(), camera.getAspectRatio(), 100, 100000000);
glUseProgramObjectARB(_skyFromAtmosphereProgramID);
glm::vec3 relativeCameraPos = camera.getPosition() - getAtmosphereCenter();
glUniform3fARB(_cameraPosLocation, relativeCameraPos.x, relativeCameraPos.y, relativeCameraPos.z);
glm::vec3 lightDirection = glm::normalize(getSunLocation());
glUniform3fARB(_lightPosLocation, lightDirection.x, lightDirection.y, lightDirection.z);
glUniform3fARB(_invWavelengthLocation,
1 / powf(0.650f, 4.0f), 1 / powf(0.570f, 4.0f), 1 / powf(0.475f, 4.0f));
glUniform1fARB(_innerRadiusLocation, getAtmosphereInnerRadius());
glUniform1fARB(_krESunLocation, getRayleighScattering() * getSunBrightness());
glUniform1fARB(_kmESunLocation, getMieScattering() * getSunBrightness());
glUniform1fARB(_kr4PiLocation, getRayleighScattering() * 4.0f * PIf);
glUniform1fARB(_km4PiLocation, getMieScattering() * 4.0f * PIf);
glUniform1fARB(_scaleLocation, 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius()));
glUniform1fARB(_scaleDepthLocation, 0.25f);
glUniform1fARB(_scaleOverScaleDepthLocation,
(1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())) / 0.25f);
glUniform1fARB(_gLocation, -0.990f);
glUniform1fARB(_g2Location, -0.990f * -0.990f);
glFrontFace(GL_CW);
glutSolidSphere(getAtmosphereOuterRadius(), 100, 50);
glFrontFace(GL_CCW);
glUseProgramObjectARB(0);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}

View file

@ -10,15 +10,32 @@
#define __interface__Environment__
#include "EnvironmentData.h"
#include "InterfaceConfig.h"
class Camera;
class Environment : public EnvironmentData {
public:
void render();
void init();
void render(Camera& camera);
private:
GLhandleARB _skyFromAtmosphereProgramID;
int _cameraPosLocation;
int _lightPosLocation;
int _invWavelengthLocation;
int _innerRadiusLocation;
int _krESunLocation;
int _kmESunLocation;
int _kr4PiLocation;
int _km4PiLocation;
int _scaleLocation;
int _scaleDepthLocation;
int _scaleOverScaleDepthLocation;
int _gLocation;
int _g2Location;
};
#endif /* defined(__interface__Environment__) */

View file

@ -311,6 +311,8 @@ void init(void) {
voxels.setViewerAvatar(&myAvatar);
voxels.setCamera(&myCamera);
environment.init();
handControl.setScreenDimensions(WIDTH, HEIGHT);
headMouseX = WIDTH/2;
@ -682,6 +684,9 @@ void renderViewFrustum(ViewFrustum& viewFrustum) {
void displaySide(Camera& whichCamera) {
glPushMatrix();
// draw the sky dome
environment.render(whichCamera);
if (::starsOn) {
// should be the first rendering pass - w/o depth buffer / lighting
@ -1747,6 +1752,7 @@ void reshape(int width, int height) {
glBindTexture(GL_TEXTURE_2D, 0);
}
} else {
camera.setAspectRatio(aspectRatio);
camera.setFieldOfView(fov = 60);
}

View file

@ -10,6 +10,18 @@
#include "EnvironmentData.h"
#include "PacketHeaders.h"
// initial values from Sean O'Neil's GPU Gems entry (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html),
// GameEngine.cpp
EnvironmentData::EnvironmentData() :
_atmosphereCenter(0, -6371000, 0),
_atmosphereInnerRadius(6371000),
_atmosphereOuterRadius(6530275),
_rayleighScattering(0.0025f),
_mieScattering(0.0010f),
_sunLocation(1000, 1000, 0),
_sunBrightness(20.0f) {
}
int EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const {
unsigned char* bufferStart = destinationBuffer;

View file

@ -14,15 +14,24 @@
class EnvironmentData {
public:
void setAtmosphereCenter(const glm::vec3& center);
void setAtmosphereInnerRadius(float radius);
void setAtmosphereOuterRadius(float radius);
EnvironmentData();
void setAtmosphereCenter(const glm::vec3& center) { _atmosphereCenter = center; }
void setAtmosphereInnerRadius(float radius) { _atmosphereInnerRadius = radius; }
void setAtmosphereOuterRadius(float radius) { _atmosphereOuterRadius = radius; }
const glm::vec3& getAtmosphereCenter() const { return _atmosphereCenter; }
float getAtmosphereInnerRadius() const { return _atmosphereInnerRadius; }
float getAtmosphereOuterRadius() const { return _atmosphereOuterRadius; }
void setRayleighScattering(float scattering);
void setMieScattering(float scattering);
void setRayleighScattering(float scattering) { _rayleighScattering = scattering; }
void setMieScattering(float scattering) { _mieScattering = scattering; }
float getRayleighScattering() const { return _rayleighScattering; }
float getMieScattering() const { return _mieScattering; }
void setSunLocation(const glm::vec3 location);
void setSunBrightness(float brightness);
void setSunLocation(const glm::vec3& location) { _sunLocation = location; }
void setSunBrightness(float brightness) { _sunBrightness = brightness; }
const glm::vec3& getSunLocation() const { return _sunLocation; }
float getSunBrightness() const { return _sunBrightness; }
int getBroadcastData(unsigned char* destinationBuffer) const;
int parseData(unsigned char* sourceBuffer, int numBytes);