Merge pull request #237 from ey6es/master

Added basic environment data and atmosphere rendering.
This commit is contained in:
Philip Rosedale 2013-05-08 15:01:12 -07:00
commit 5e450827d8
20 changed files with 974 additions and 41 deletions

View file

@ -32,7 +32,7 @@ configure_file(InterfaceConfig.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceConf
# grab the implementation and header files from src dirs
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
foreach(SUBDIR ui)
foreach(SUBDIR ui renderer)
file(GLOB SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
set(INTERFACE_SRCS ${INTERFACE_SRCS} ${SUBDIR_SRCS})
endforeach(SUBDIR)

View file

@ -0,0 +1,48 @@
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
//
// 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 = gl_FragColor.b;
}

View file

@ -0,0 +1,100 @@
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
//
// 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

@ -0,0 +1,48 @@
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
//
// 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 = gl_FragColor.b;
}

View file

@ -0,0 +1,109 @@
//
// For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html:
//
// NVIDIA Statement on the Software
//
// The source code provided is freely distributable, so long as the NVIDIA header remains unaltered and user modifications are
// detailed.
//
// No Warranty
//
// THE SOFTWARE AND ANY OTHER MATERIALS PROVIDED BY NVIDIA ON THE ENCLOSED CD-ROM ARE PROVIDED "AS IS." NVIDIA DISCLAIMS ALL
// WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//
// Limitation of Liability
//
// NVIDIA SHALL NOT BE LIABLE TO ANY USER, DEVELOPER, DEVELOPER'S CUSTOMERS, OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH OR
// UNDER DEVELOPER FOR ANY LOSS OF PROFITS, INCOME, SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT
// OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE ESSENTIAL PURPOSE OF ANY
// LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S AGGREGATE LIABILITY TO DEVELOPER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH
// OR UNDER DEVELOPER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY DEVELOPER TO NVIDIA FOR THE SOFTWARE OR ANY OTHER MATERIALS.
//
//
// 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 fCameraHeight2; // fCameraHeight^2
uniform float fOuterRadius; // The outer (atmosphere) radius
uniform float fOuterRadius2; // fOuterRadius^2
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 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(v3CameraPos, 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 = v3CameraPos + v3Ray * fNear;
fFar -= fNear;
float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius;
float fStartDepth = exp(-1.0 / fScaleDepth);
float fStartOffset = fStartDepth * 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

@ -0,0 +1,114 @@
//
// Environment.cpp
// interface
//
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <QByteArray>
#include "Camera.h"
#include "Environment.h"
#include "renderer/ProgramObject.h"
#include "renderer/ShaderObject.h"
#include "world.h"
void Environment::init() {
_skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations);
_skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations);
}
void Environment::renderAtmosphere(Camera& camera) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(getAtmosphereCenter().x, getAtmosphereCenter().y, getAtmosphereCenter().z);
// use the camera distance to reset the near and far distances to keep the atmosphere in the frustum
glMatrixMode(GL_PROJECTION);
glPushMatrix();
float projection[16];
glGetFloatv(GL_PROJECTION_MATRIX, projection);
glm::vec3 relativeCameraPos = camera.getPosition() - getAtmosphereCenter();
float height = glm::length(relativeCameraPos);
float near = camera.getNearClip(), far = height + getAtmosphereOuterRadius();
projection[10] = (far + near) / (near - far);
projection[14] = (2.0f * far * near) / (near - far);
glLoadMatrixf(projection);
// use the appropriate shader depending on whether we're inside or outside
ProgramObject* program;
int* locations;
if (height < getAtmosphereOuterRadius()) {
program = _skyFromAtmosphereProgram;
locations = _skyFromAtmosphereUniformLocations;
} else {
program = _skyFromSpaceProgram;
locations = _skyFromSpaceUniformLocations;
}
// the constants here are from Sean O'Neil's GPU Gems entry
// (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp
program->bind();
program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos);
glm::vec3 lightDirection = glm::normalize(getSunLocation());
program->setUniform(locations[LIGHT_POS_LOCATION], lightDirection);
program->setUniform(locations[INV_WAVELENGTH_LOCATION],
1 / powf(getScatteringWavelengths().r, 4.0f),
1 / powf(getScatteringWavelengths().g, 4.0f),
1 / powf(getScatteringWavelengths().b, 4.0f));
program->setUniform(locations[CAMERA_HEIGHT2_LOCATION], height * height);
program->setUniform(locations[OUTER_RADIUS_LOCATION], getAtmosphereOuterRadius());
program->setUniform(locations[OUTER_RADIUS2_LOCATION], getAtmosphereOuterRadius() * getAtmosphereOuterRadius());
program->setUniform(locations[INNER_RADIUS_LOCATION], getAtmosphereInnerRadius());
program->setUniform(locations[KR_ESUN_LOCATION], getRayleighScattering() * getSunBrightness());
program->setUniform(locations[KM_ESUN_LOCATION], getMieScattering() * getSunBrightness());
program->setUniform(locations[KR_4PI_LOCATION], getRayleighScattering() * 4.0f * PIf);
program->setUniform(locations[KM_4PI_LOCATION], getMieScattering() * 4.0f * PIf);
program->setUniform(locations[SCALE_LOCATION], 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius()));
program->setUniform(locations[SCALE_DEPTH_LOCATION], 0.25f);
program->setUniform(locations[SCALE_OVER_SCALE_DEPTH_LOCATION],
(1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())) / 0.25f);
program->setUniform(locations[G_LOCATION], -0.990f);
program->setUniform(locations[G2_LOCATION], -0.990f * -0.990f);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glutSolidSphere(getAtmosphereOuterRadius(), 100, 50);
glDepthMask(GL_TRUE);
program->release();
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
ProgramObject* Environment::createSkyProgram(const char* from, int* locations) {
ProgramObject* program = new ProgramObject();
QByteArray prefix = QByteArray("resources/shaders/SkyFrom") + from;
program->attachFromSourceFile(GL_VERTEX_SHADER_ARB, prefix + ".vert");
program->attachFromSourceFile(GL_FRAGMENT_SHADER_ARB, prefix + ".frag");
program->link();
locations[CAMERA_POS_LOCATION] = program->getUniformLocation("v3CameraPos");
locations[LIGHT_POS_LOCATION] = program->getUniformLocation("v3LightPos");
locations[INV_WAVELENGTH_LOCATION] = program->getUniformLocation("v3InvWavelength");
locations[CAMERA_HEIGHT2_LOCATION] = program->getUniformLocation("fCameraHeight2");
locations[OUTER_RADIUS_LOCATION] = program->getUniformLocation("fOuterRadius");
locations[OUTER_RADIUS2_LOCATION] = program->getUniformLocation("fOuterRadius2");
locations[INNER_RADIUS_LOCATION] = program->getUniformLocation("fInnerRadius");
locations[KR_ESUN_LOCATION] = program->getUniformLocation("fKrESun");
locations[KM_ESUN_LOCATION] = program->getUniformLocation("fKmESun");
locations[KR_4PI_LOCATION] = program->getUniformLocation("fKr4PI");
locations[KM_4PI_LOCATION] = program->getUniformLocation("fKm4PI");
locations[SCALE_LOCATION] = program->getUniformLocation("fScale");
locations[SCALE_DEPTH_LOCATION] = program->getUniformLocation("fScaleDepth");
locations[SCALE_OVER_SCALE_DEPTH_LOCATION] = program->getUniformLocation("fScaleOverScaleDepth");
locations[G_LOCATION] = program->getUniformLocation("g");
locations[G2_LOCATION] = program->getUniformLocation("g2");
return program;
}

View file

@ -0,0 +1,55 @@
//
// Environment.h
// interface
//
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__Environment__
#define __interface__Environment__
#include "EnvironmentData.h"
#include "InterfaceConfig.h"
class Camera;
class ProgramObject;
class Environment : public EnvironmentData {
public:
void init();
void renderAtmosphere(Camera& camera);
private:
ProgramObject* createSkyProgram(const char* from, int* locations);
ProgramObject* _skyFromAtmosphereProgram;
ProgramObject* _skyFromSpaceProgram;
enum {
CAMERA_POS_LOCATION,
LIGHT_POS_LOCATION,
INV_WAVELENGTH_LOCATION,
CAMERA_HEIGHT2_LOCATION,
OUTER_RADIUS_LOCATION,
OUTER_RADIUS2_LOCATION,
INNER_RADIUS_LOCATION,
KR_ESUN_LOCATION,
KM_ESUN_LOCATION,
KR_4PI_LOCATION,
KM_4PI_LOCATION,
SCALE_LOCATION,
SCALE_DEPTH_LOCATION,
SCALE_OVER_SCALE_DEPTH_LOCATION,
G_LOCATION,
G2_LOCATION,
LOCATION_COUNT
};
int _skyFromAtmosphereUniformLocations[LOCATION_COUNT];
int _skyFromSpaceUniformLocations[LOCATION_COUNT];
};
#endif /* defined(__interface__Environment__) */

View file

@ -34,7 +34,7 @@ float Stars::changeLOD(float fraction, float overalloc, float realloc) {
return float(_ptrController->changeLOD(fraction, overalloc, realloc));
}
void Stars::render(float fovY, float aspect, float nearZ) {
void Stars::render(float fovY, float aspect, float nearZ, float alpha) {
// determine length of screen diagonal from quadrant height and aspect ratio
float quadrantHeight = nearZ * tan(angleConvert<Degrees,Radians>(fovY) * 0.5f);
@ -46,7 +46,7 @@ void Stars::render(float fovY, float aspect, float nearZ) {
// pull the modelview matrix off the GL stack
glm::mat4 view; glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(view));
_ptrController->render(fovDiagonal, aspect, glm::affineInverse(view));
_ptrController->render(fovDiagonal, aspect, glm::affineInverse(view), alpha);
}

View file

@ -37,7 +37,7 @@ class Stars {
// Renders the starfield from a local viewer's perspective.
// The parameters specifiy the field of view.
//
void render(float fovY, float aspect, float nearZ);
void render(float fovY, float aspect, float nearZ, float alpha);
//
// Sets the resolution for FOV culling.

View file

@ -58,12 +58,15 @@
#include "ui/MenuColumn.h"
#include "ui/Menu.h"
#include "ui/TextRenderer.h"
#include "renderer/ProgramObject.h"
#include "renderer/ShaderObject.h"
#include "Camera.h"
#include "Avatar.h"
#include <AgentList.h>
#include <AgentTypes.h>
#include "VoxelSystem.h"
#include "Environment.h"
#include "Oscilloscope.h"
#include "UDPSocket.h"
#include "SerialInterface.h"
@ -125,6 +128,8 @@ VoxelSystem voxels;
bool wantToKillLocalVoxels = false;
Environment environment;
#ifndef _WIN32
Audio audio(&audioScope, &myAvatar);
@ -140,6 +145,7 @@ bool renderWarningsOn = false; // Whether to show render pipeline warnings
bool statsOn = false; // Whether to show onscreen text overlay with stats
bool starsOn = false; // Whether to display the stars
bool atmosphereOn = true; // Whether to display the atmosphere
bool paintOn = false; // Whether to paint voxels as you fly around
VoxelDetail paintingVoxel; // The voxel we're painting if we're painting
unsigned char dominantColor = 0; // The dominant color of the voxel we're painting
@ -174,7 +180,7 @@ bool chatEntryOn = false; // Whether to show the chat entry
bool oculusOn = false; // Whether to configure the display for the Oculus Rift
GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion
GLhandleARB oculusProgramID = 0; // The GLSL program containing the distortion shader
ProgramObject* oculusProgram = 0; // The GLSL program containing the distortion shader
float oculusDistortionScale = 1.25; // Controls the Oculus field of view
//
@ -299,6 +305,8 @@ void init(void) {
voxels.setViewerAvatar(&myAvatar);
voxels.setCamera(&myCamera);
environment.init();
handControl.setScreenDimensions(WIDTH, HEIGHT);
headMouseX = WIDTH/2;
@ -678,10 +686,28 @@ void displaySide(Camera& whichCamera) {
if (::starsOn) {
// should be the first rendering pass - w/o depth buffer / lighting
// compute starfield alpha based on distance from atmosphere
float alpha = 1.0f;
if (::atmosphereOn) {
float height = glm::distance(whichCamera.getPosition(), environment.getAtmosphereCenter());
if (height < environment.getAtmosphereInnerRadius()) {
alpha = 0.0f;
} else if (height < environment.getAtmosphereOuterRadius()) {
alpha = (height - environment.getAtmosphereInnerRadius()) /
(environment.getAtmosphereOuterRadius() - environment.getAtmosphereInnerRadius());
}
}
// finally render the starfield
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip());
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip(), alpha);
}
// draw the sky dome
if (::atmosphereOn) {
environment.renderAtmosphere(whichCamera);
}
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
@ -802,18 +828,16 @@ void displayOculus(Camera& whichCamera) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GLhandleARB shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
glShaderSourceARB(shaderID, 1, &DISTORTION_FRAGMENT_SHADER, 0);
glCompileShaderARB(shaderID);
::oculusProgramID = glCreateProgramObjectARB();
glAttachObjectARB(::oculusProgramID, shaderID);
glLinkProgramARB(::oculusProgramID);
textureLocation = glGetUniformLocationARB(::oculusProgramID, "texture");
lensCenterLocation = glGetUniformLocationARB(::oculusProgramID, "lensCenter");
screenCenterLocation = glGetUniformLocationARB(::oculusProgramID, "screenCenter");
scaleLocation = glGetUniformLocationARB(::oculusProgramID, "scale");
scaleInLocation = glGetUniformLocationARB(::oculusProgramID, "scaleIn");
hmdWarpParamLocation = glGetUniformLocationARB(::oculusProgramID, "hmdWarpParam");
::oculusProgram = new ProgramObject();
::oculusProgram->attachFromSourceCode(GL_FRAGMENT_SHADER_ARB, DISTORTION_FRAGMENT_SHADER);
::oculusProgram->link();
textureLocation = ::oculusProgram->getUniformLocation("texture");
lensCenterLocation = ::oculusProgram->getUniformLocation("lensCenter");
screenCenterLocation = ::oculusProgram->getUniformLocation("screenCenter");
scaleLocation = ::oculusProgram->getUniformLocation("scale");
scaleInLocation = ::oculusProgram->getUniformLocation("scaleIn");
hmdWarpParamLocation = ::oculusProgram->getUniformLocation("hmdWarpParam");
} else {
glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
@ -833,13 +857,13 @@ void displayOculus(Camera& whichCamera) {
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glUseProgramObjectARB(::oculusProgramID);
glUniform1iARB(textureLocation, 0);
glUniform2fARB(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
glUniform2fARB(screenCenterLocation, 0.25, 0.5);
glUniform2fARB(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
glUniform2fARB(scaleInLocation, 4, 2 / aspectRatio);
glUniform4fARB(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
::oculusProgram->bind();
::oculusProgram->setUniform(textureLocation, 0);
::oculusProgram->setUniform(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
::oculusProgram->setUniform(screenCenterLocation, 0.25, 0.5);
::oculusProgram->setUniform(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
::oculusProgram->setUniform(scaleInLocation, 4, 2 / aspectRatio);
::oculusProgram->setUniform(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
glColor3f(1, 0, 1);
glBegin(GL_QUADS);
@ -853,8 +877,8 @@ void displayOculus(Camera& whichCamera) {
glVertex2f(0, HEIGHT);
glEnd();
glUniform2fARB(lensCenterLocation, 0.787994, 0.5);
glUniform2fARB(screenCenterLocation, 0.75, 0.5);
::oculusProgram->setUniform(lensCenterLocation, 0.787994, 0.5);
::oculusProgram->setUniform(screenCenterLocation, 0.75, 0.5);
glBegin(GL_QUADS);
glTexCoord2f(0.5, 0);
@ -870,7 +894,7 @@ void displayOculus(Camera& whichCamera) {
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
::oculusProgram->release();
glPopMatrix();
}
@ -1205,6 +1229,10 @@ int setStars(int state) {
return setValue(state, &::starsOn);
}
int setAtmosphere(int state) {
return setValue(state, &::atmosphereOn);
}
int setOculus(int state) {
bool wasOn = ::oculusOn;
int value = setValue(state, &::oculusOn);
@ -1350,6 +1378,7 @@ void initMenu() {
menuColumnRender = menu.addColumn("Render");
menuColumnRender->addRow("Voxels (V)", setVoxels);
menuColumnRender->addRow("Stars (*)", setStars);
menuColumnRender->addRow("Atmosphere (A)", setAtmosphere);
menuColumnRender->addRow("Oculus (o)", setOculus);
// Tools
@ -1515,6 +1544,7 @@ void key(unsigned char k, int x, int y) {
if (k == '/') ::statsOn = !::statsOn; // toggle stats
if (k == '*') ::starsOn = !::starsOn; // toggle stars
if (k == 'V' || k == 'v') ::showingVoxels = !::showingVoxels; // toggle voxels
if (k == 'A') ::atmosphereOn = !::atmosphereOn;
if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging
if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at
if (k == 'O' || k == 'G') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging
@ -1608,6 +1638,9 @@ void* networkReceive(void* args) {
case PACKET_HEADER_ERASE_VOXEL:
voxels.parseData(incomingPacket, bytesReceived);
break;
case PACKET_HEADER_ENVIRONMENT_DATA:
environment.parseData(incomingPacket, bytesReceived);
break;
case PACKET_HEADER_BULK_AVATAR_DATA:
AgentList::getInstance()->processBulkAgentData(&senderAddress,
incomingPacket,
@ -1712,6 +1745,7 @@ void reshape(int width, int height) {
glBindTexture(GL_TEXTURE_2D, 0);
}
} else {
camera.setAspectRatio(aspectRatio);
camera.setFieldOfView(fov = 60);
}

View file

@ -0,0 +1,119 @@
//
// ProgramObject.cpp
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include "ProgramObject.h"
#include "ShaderObject.h"
ProgramObject::ProgramObject() : _handle(glCreateProgramObjectARB()) {
}
ProgramObject::~ProgramObject() {
glDeleteObjectARB(_handle);
}
void ProgramObject::attach(ShaderObject* shader) {
glAttachObjectARB(_handle, shader->getHandle());
}
bool ProgramObject::attachFromSourceCode(int type, const char* source) {
ShaderObject* shader = new ShaderObject(type);
if (shader->compileSourceCode(source)) {
attach(shader);
return true;
} else {
delete shader;
return false;
}
}
bool ProgramObject::attachFromSourceFile(int type, const char* filename) {
ShaderObject* shader = new ShaderObject(type);
if (shader->compileSourceFile(filename)) {
attach(shader);
return true;
} else {
delete shader;
return false;
}
}
bool ProgramObject::link() {
glLinkProgramARB(_handle);
int status;
glGetObjectParameterivARB(_handle, GL_OBJECT_LINK_STATUS_ARB, &status);
return status;
}
QByteArray ProgramObject::getLog() const {
int length;
glGetObjectParameterivARB(_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
QByteArray log(length, 0);
glGetInfoLogARB(_handle, length, 0, log.data());
return log;
}
void ProgramObject::bind() const {
glUseProgramObjectARB(_handle);
}
void ProgramObject::release() const {
glUseProgramObjectARB(0);
}
int ProgramObject::getUniformLocation(const char* name) const {
return glGetUniformLocationARB(_handle, name);
}
void ProgramObject::setUniform(int location, int value) {
glUniform1iARB(location, value);
}
void ProgramObject::setUniform(const char* name, int value) {
setUniform(getUniformLocation(name), value);
}
void ProgramObject::setUniform(int location, float value) {
glUniform1fARB(location, value);
}
void ProgramObject::setUniform(const char* name, float value) {
setUniform(getUniformLocation(name), value);
}
void ProgramObject::setUniform(int location, float x, float y) {
glUniform2fARB(location, x, y);
}
void ProgramObject::setUniform(const char* name, float x, float y) {
setUniform(getUniformLocation(name), x, y);
}
void ProgramObject::setUniform(int location, const glm::vec3& value) {
glUniform3fARB(location, value.x, value.y, value.z);
}
void ProgramObject::setUniform(const char* name, const glm::vec3& value) {
setUniform(getUniformLocation(name), value);
}
void ProgramObject::setUniform(int location, float x, float y, float z) {
glUniform3fARB(location, x, y, z);
}
void ProgramObject::setUniform(const char* name, float x, float y, float z) {
setUniform(getUniformLocation(name), x, y, z);
}
void ProgramObject::setUniform(int location, float x, float y, float z, float w) {
glUniform4fARB(location, x, y, z, w);
}
void ProgramObject::setUniform(const char* name, float x, float y, float z, float w) {
setUniform(getUniformLocation(name), x, y, z, w);
}

View file

@ -0,0 +1,66 @@
//
// ProgramObject.h
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__ProgramObject__
#define __interface__ProgramObject__
#include <QObject>
#include <glm/glm.hpp>
#include "InterfaceConfig.h"
class ShaderObject;
class ProgramObject {
public:
ProgramObject();
~ProgramObject();
GLhandleARB getHandle() const { return _handle; }
void attach(ShaderObject* shader);
bool attachFromSourceCode(int type, const char* source);
bool attachFromSourceFile(int type, const char* filename);
bool link();
QByteArray getLog() const;
void bind() const;
void release() const;
int getUniformLocation(const char* name) const;
void setUniform(int location, int value);
void setUniform(const char* name, int value);
void setUniform(int location, float value);
void setUniform(const char* name, float value);
void setUniform(int location, float x, float y);
void setUniform(const char* name, float x, float y);
void setUniform(int location, const glm::vec3& value);
void setUniform(const char* name, const glm::vec3& value);
void setUniform(int location, float x, float y, float z);
void setUniform(const char* name, float x, float y, float z);
void setUniform(int location, float x, float y, float z, float w);
void setUniform(const char* name, float x, float y, float z, float w);
private:
Q_DISABLE_COPY(ProgramObject)
GLhandleARB _handle;
};
#endif /* defined(__interface__ProgramObject__) */

View file

@ -0,0 +1,39 @@
//
// ShaderObject.cpp
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <QFile>
#include "ShaderObject.h"
ShaderObject::ShaderObject(int type)
: _handle(glCreateShaderObjectARB(type)) {
}
ShaderObject::~ShaderObject() {
glDeleteObjectARB(_handle);
}
bool ShaderObject::compileSourceCode(const char* data) {
glShaderSource(_handle, 1, &data, 0);
glCompileShaderARB(_handle);
int status;
glGetObjectParameterivARB(_handle, GL_OBJECT_COMPILE_STATUS_ARB, &status);
return status;
}
bool ShaderObject::compileSourceFile(const char* filename) {
QFile file(filename);
return file.open(QIODevice::ReadOnly) && compileSourceCode(file.readAll().constData());
}
QByteArray ShaderObject::getLog() const {
int length;
glGetObjectParameterivARB(_handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
QByteArray log(length, 0);
glGetInfoLogARB(_handle, length, 0, log.data());
return log;
}

View file

@ -0,0 +1,36 @@
//
// ShaderObject.h
// interface
//
// Created by Andrzej Kapolka on 5/7/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__ShaderObject__
#define __interface__ShaderObject__
#include <QObject>
#include "InterfaceConfig.h"
class ShaderObject {
public:
ShaderObject(int type);
~ShaderObject();
GLhandleARB getHandle() const { return _handle; }
bool compileSourceCode(const char* data);
bool compileSourceFile(const char* filename);
QByteArray getLog() const;
private:
Q_DISABLE_COPY(ShaderObject)
GLhandleARB _handle;
};
#endif /* defined(__interface__ShaderObject__) */

View file

@ -361,7 +361,7 @@ namespace starfield {
public:
void render(float perspective, float angle, mat4 const& orientation) {
void render(float perspective, float angle, mat4 const& orientation, float alpha) {
#if STARFIELD_MULTITHREADING
// check out renderer
@ -377,7 +377,7 @@ namespace starfield {
#else
BrightnessLevel b = _valLodBrightness;
#endif
renderer->render(perspective, angle, orientation, b);
renderer->render(perspective, angle, orientation, b, alpha);
}
#if STARFIELD_MULTITHREADING

View file

@ -13,6 +13,8 @@
#error "This is an implementation file - not intended for direct inclusion."
#endif
#include "renderer/ProgramObject.h"
#include "starfield/Config.h"
#include "starfield/data/InputVertex.h"
#include "starfield/data/BrightnessLevel.h"
@ -70,7 +72,8 @@ namespace starfield {
GLint* _arrBatchOffs;
GLsizei* _arrBatchCount;
GLuint _hndVertexArray;
OGlProgram _objProgram;
ProgramObject _objProgram;
int _alphaLocation;
Tiling _objTiling;
@ -123,7 +126,8 @@ namespace starfield {
void render(float perspective,
float aspect,
mat4 const& orientation,
BrightnessLevel minBright) {
BrightnessLevel minBright,
float alpha) {
// printLog("
// Stars.cpp: rendering at minimal brightness %d\n", minBright);
@ -186,7 +190,7 @@ namespace starfield {
# define matrix matrix_debug
#endif
this->glBatch(glm::value_ptr(matrix), prepareBatch(
(unsigned*) _arrBatchOffs, _itrOutIndex) );
(unsigned*) _arrBatchOffs, _itrOutIndex), alpha);
#if STARFIELD_DEBUG_CULLING
# undef matrix
@ -463,24 +467,26 @@ namespace starfield {
GLchar const* const VERTEX_SHADER =
"#version 120\n"
"uniform float alpha;\n"
"void main(void) {\n"
" vec3 c = gl_Color.rgb * 1.0125;\n"
" float s = max(1.0, dot(c, c) * 0.7);\n"
" gl_Position = ftransform();\n"
" gl_FrontColor= gl_Color;\n"
" gl_FrontColor= gl_Color * alpha;\n"
" gl_PointSize = s;\n"
"}\n";
_objProgram.addShader(GL_VERTEX_SHADER, VERTEX_SHADER);
_objProgram.attachFromSourceCode(GL_VERTEX_SHADER, VERTEX_SHADER);
GLchar const* const FRAGMENT_SHADER =
"#version 120\n"
"void main(void) {\n"
" gl_FragColor = gl_Color;\n"
"}\n";
_objProgram.addShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
_objProgram.attachFromSourceCode(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
_objProgram.link();
_alphaLocation = _objProgram.getUniformLocation("alpha");
glGenBuffersARB(1, & _hndVertexArray);
}
@ -499,7 +505,7 @@ namespace starfield {
glBindBufferARB(GL_ARRAY_BUFFER, 0);
}
void glBatch(GLfloat const* matrix, GLsizei n_ranges) {
void glBatch(GLfloat const* matrix, GLsizei n_ranges, float alpha) {
// printLog("Stars.cpp: rendering %d-multibatch\n", n_ranges);
@ -527,7 +533,8 @@ namespace starfield {
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
// select shader and vertex array
_objProgram.activate();
_objProgram.bind();
_objProgram.setUniform(_alphaLocation, alpha);
glBindBufferARB(GL_ARRAY_BUFFER, _hndVertexArray);
glInterleavedArrays(GL_C4UB_V3F, sizeof(GpuVertex), 0l);
@ -537,7 +544,7 @@ namespace starfield {
// restore state
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
_objProgram.release();
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
glDisable(GL_POINT_SMOOTH);
glPopMatrix();

View file

@ -25,6 +25,7 @@ const PACKET_HEADER PACKET_HEADER_ERASE_VOXEL = 'E';
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA = 'V';
const PACKET_HEADER PACKET_HEADER_BULK_AVATAR_DATA = 'X';
const PACKET_HEADER PACKET_HEADER_TRANSMITTER_DATA = 't';
const PACKET_HEADER PACKET_HEADER_ENVIRONMENT_DATA = 'e';
const PACKET_HEADER PACKET_HEADER_DOMAIN_LIST_REQUEST = 'L';
const PACKET_HEADER PACKET_HEADER_DOMAIN_RFD = 'C';

View file

@ -0,0 +1,90 @@
//
// EnvironmentData.cpp
// interface
//
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <cstring>
#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 (and the radius of the earth)
EnvironmentData::EnvironmentData() :
_atmosphereCenter(0, -1000, 0),
_atmosphereInnerRadius(1000),
_atmosphereOuterRadius(1025),
_rayleighScattering(0.0025f),
_mieScattering(0.0010f),
_scatteringWavelengths(0.650f, 0.570f, 0.475f),
_sunLocation(1000, 1000, 0),
_sunBrightness(20.0f) {
}
int EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const {
unsigned char* bufferStart = destinationBuffer;
*destinationBuffer++ = PACKET_HEADER_ENVIRONMENT_DATA;
memcpy(destinationBuffer, &_atmosphereCenter, sizeof(_atmosphereCenter));
destinationBuffer += sizeof(_atmosphereCenter);
memcpy(destinationBuffer, &_atmosphereInnerRadius, sizeof(_atmosphereInnerRadius));
destinationBuffer += sizeof(_atmosphereInnerRadius);
memcpy(destinationBuffer, &_atmosphereOuterRadius, sizeof(_atmosphereOuterRadius));
destinationBuffer += sizeof(_atmosphereOuterRadius);
memcpy(destinationBuffer, &_rayleighScattering, sizeof(_rayleighScattering));
destinationBuffer += sizeof(_rayleighScattering);
memcpy(destinationBuffer, &_mieScattering, sizeof(_mieScattering));
destinationBuffer += sizeof(_mieScattering);
memcpy(destinationBuffer, &_scatteringWavelengths, sizeof(_scatteringWavelengths));
destinationBuffer += sizeof(_scatteringWavelengths);
memcpy(destinationBuffer, &_sunLocation, sizeof(_sunLocation));
destinationBuffer += sizeof(_sunLocation);
memcpy(destinationBuffer, &_sunBrightness, sizeof(_sunBrightness));
destinationBuffer += sizeof(_sunBrightness);
return destinationBuffer - bufferStart;
}
int EnvironmentData::parseData(unsigned char* sourceBuffer, int numBytes) {
// increment to push past the packet header
sourceBuffer++;
unsigned char* startPosition = sourceBuffer;
memcpy(&_atmosphereCenter, sourceBuffer, sizeof(_atmosphereCenter));
sourceBuffer += sizeof(_atmosphereCenter);
memcpy(&_atmosphereInnerRadius, sourceBuffer, sizeof(_atmosphereInnerRadius));
sourceBuffer += sizeof(_atmosphereInnerRadius);
memcpy(&_atmosphereOuterRadius, sourceBuffer, sizeof(_atmosphereOuterRadius));
sourceBuffer += sizeof(_atmosphereOuterRadius);
memcpy(&_rayleighScattering, sourceBuffer, sizeof(_rayleighScattering));
sourceBuffer += sizeof(_rayleighScattering);
memcpy(&_mieScattering, sourceBuffer, sizeof(_mieScattering));
sourceBuffer += sizeof(_mieScattering);
memcpy(&_scatteringWavelengths, sourceBuffer, sizeof(_scatteringWavelengths));
sourceBuffer += sizeof(_scatteringWavelengths);
memcpy(&_sunLocation, sourceBuffer, sizeof(_sunLocation));
sourceBuffer += sizeof(_sunLocation);
memcpy(&_sunBrightness, sourceBuffer, sizeof(_sunBrightness));
sourceBuffer += sizeof(_sunBrightness);
return sourceBuffer - startPosition;
}

View file

@ -0,0 +1,57 @@
//
// EnvironmentData.h
// interface
//
// Created by Andrzej Kapolka on 5/6/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__EnvironmentData__
#define __interface__EnvironmentData__
#include <glm/glm.hpp>
class EnvironmentData {
public:
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) { _rayleighScattering = scattering; }
void setMieScattering(float scattering) { _mieScattering = scattering; }
float getRayleighScattering() const { return _rayleighScattering; }
float getMieScattering() const { return _mieScattering; }
void setScatteringWavelengths(const glm::vec3& wavelengths) { _scatteringWavelengths = wavelengths; }
const glm::vec3& getScatteringWavelengths() const { return _scatteringWavelengths; }
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);
private:
glm::vec3 _atmosphereCenter;
float _atmosphereInnerRadius;
float _atmosphereOuterRadius;
float _rayleighScattering;
float _mieScattering;
glm::vec3 _scatteringWavelengths;
glm::vec3 _sunLocation;
float _sunBrightness;
};
#endif /* defined(__interface__EnvironmentData__) */

View file

@ -13,6 +13,7 @@
#include <OctalCode.h>
#include <AgentList.h>
#include <AgentTypes.h>
#include <EnvironmentData.h>
#include <VoxelTree.h>
#include "VoxelAgentData.h"
#include <SharedUtil.h>
@ -54,6 +55,9 @@ bool wantLocalDomain = false;
bool wantColorRandomizer = false;
bool debugVoxelSending = false;
EnvironmentData environmentData;
void randomlyFillVoxelTree(int levelsToGo, VoxelNode *currentRootNode) {
// randomly generate children for this node
// the first level of the tree (where levelsToGo = MAX_VOXEL_TREE_DEPTH_LEVELS) has all 8
@ -149,7 +153,7 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
int trueBytesSent = 0;
double start = usecTimestampNow();
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) {
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - 1) {
if (!agentData->nodeBag.isEmpty()) {
VoxelNode* subTree = agentData->nodeBag.extract();
bytesWritten = randomTree.encodeTreeBitstream(agentData->getMaxSearchLevel(), subTree,
@ -179,6 +183,12 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge
packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left
}
}
// send the environment packet
int envPacketLength = environmentData.getBroadcastData(tempOutputBuffer);
agentList->getAgentSocket().send(agent->getActiveSocket(), tempOutputBuffer, envPacketLength);
trueBytesSent += envPacketLength;
truePacketsSent++;
double end = usecTimestampNow();
double elapsedmsec = (end - start)/1000.0;
if (elapsedmsec > 100) {
@ -464,4 +474,4 @@ int main(int argc, const char * argv[])
pthread_join(sendVoxelThread, NULL);
return 0;
}
}