From b4dd6b57aaf9dda78b2cf1949f1c513181824c12 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 6 May 2013 13:30:07 -0700 Subject: [PATCH 01/13] Starting on environment bits. --- interface/src/Environment.cpp | 12 +++++ interface/src/Environment.h | 24 +++++++++ interface/src/main.cpp | 6 +++ libraries/shared/src/PacketHeaders.h | 1 + libraries/voxels/src/EnvironmentData.cpp | 69 ++++++++++++++++++++++++ libraries/voxels/src/EnvironmentData.h | 43 +++++++++++++++ 6 files changed, 155 insertions(+) create mode 100644 interface/src/Environment.cpp create mode 100644 interface/src/Environment.h create mode 100644 libraries/voxels/src/EnvironmentData.cpp create mode 100644 libraries/voxels/src/EnvironmentData.h diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp new file mode 100644 index 0000000000..3bff8961df --- /dev/null +++ b/interface/src/Environment.cpp @@ -0,0 +1,12 @@ +// +// Environment.cpp +// interface +// +// Created by Andrzej Kapolka on 5/6/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. + +#include "Environment.h" + +void Environment::render() { + +} diff --git a/interface/src/Environment.h b/interface/src/Environment.h new file mode 100644 index 0000000000..e028d86e32 --- /dev/null +++ b/interface/src/Environment.h @@ -0,0 +1,24 @@ +// +// Environment.h +// interface +// +// Created by Andrzej Kapolka on 5/16/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__Environment__ +#define __interface__Environment__ + +#include "EnvironmentData.h" + +class Environment : public EnvironmentData { +public: + + void render(); + +private: + + +}; + +#endif /* defined(__interface__Environment__) */ diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 424e4113bc..3a2e3a9acd 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -74,6 +74,7 @@ #include #include #include "VoxelSystem.h" +#include "Environment.h" #include "Oscilloscope.h" #include "UDPSocket.h" #include "SerialInterface.h" @@ -136,6 +137,8 @@ VoxelSystem voxels; bool wantToKillLocalVoxels = false; +Environment environment; + #ifndef _WIN32 Audio audio(&audioScope, &myAvatar); @@ -1645,6 +1648,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, diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index ed2e5d5638..4fd6aa105d 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -23,5 +23,6 @@ const char PACKET_HEADER_ERASE_VOXEL = 'E'; const char PACKET_HEADER_VOXEL_DATA = 'V'; const char PACKET_HEADER_BULK_AVATAR_DATA = 'X'; const char PACKET_HEADER_TRANSMITTER_DATA = 't'; +const char PACKET_HEADER_ENVIRONMENT_DATA = 'e'; #endif diff --git a/libraries/voxels/src/EnvironmentData.cpp b/libraries/voxels/src/EnvironmentData.cpp new file mode 100644 index 0000000000..9fff790810 --- /dev/null +++ b/libraries/voxels/src/EnvironmentData.cpp @@ -0,0 +1,69 @@ +// +// EnvironmentData.cpp +// interface +// +// Created by Andrzej Kapolka on 5/6/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. + +#include + +#include "EnvironmentData.h" +#include "PacketHeaders.h" + +int EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const { + unsigned char* bufferStart = destinationBuffer; + + 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, &_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(&_sunLocation, sourceBuffer, sizeof(_sunLocation)); + sourceBuffer += sizeof(_sunLocation); + + memcpy(&_sunBrightness, sourceBuffer, sizeof(_sunBrightness)); + sourceBuffer += sizeof(_sunBrightness); + + return sourceBuffer - startPosition; +} + diff --git a/libraries/voxels/src/EnvironmentData.h b/libraries/voxels/src/EnvironmentData.h new file mode 100644 index 0000000000..12ebcd4a94 --- /dev/null +++ b/libraries/voxels/src/EnvironmentData.h @@ -0,0 +1,43 @@ +// +// EnvironmentData.h +// interface +// +// Created by Andrzej Kapolka on 5/16/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__EnvironmentData__ +#define __interface__EnvironmentData__ + +#include + +class EnvironmentData { +public: + + void setAtmosphereCenter(const glm::vec3& center); + void setAtmosphereInnerRadius(float radius); + void setAtmosphereOuterRadius(float radius); + + void setRayleighScattering(float scattering); + void setMieScattering(float scattering); + + void setSunLocation(const glm::vec3 location); + void setSunBrightness(float brightness); + + 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 _sunLocation; + float _sunBrightness; +}; + +#endif /* defined(__interface__EnvironmentData__) */ From 7faa9e4318e00b3c94799e289b09cd08355e75e3 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 7 May 2013 12:40:15 -0700 Subject: [PATCH 02/13] More work on atmosphere rendering; rendering now working. --- .../resources/shaders/SkyFromAtmosphere.frag | 24 +++++ .../resources/shaders/SkyFromAtmosphere.vert | 76 +++++++++++++++ interface/src/Environment.cpp | 96 ++++++++++++++++++- interface/src/Environment.h | 21 +++- interface/src/main.cpp | 6 ++ libraries/voxels/src/EnvironmentData.cpp | 12 +++ libraries/voxels/src/EnvironmentData.h | 23 +++-- 7 files changed, 246 insertions(+), 12 deletions(-) create mode 100644 interface/resources/shaders/SkyFromAtmosphere.frag create mode 100644 interface/resources/shaders/SkyFromAtmosphere.vert diff --git a/interface/resources/shaders/SkyFromAtmosphere.frag b/interface/resources/shaders/SkyFromAtmosphere.frag new file mode 100644 index 0000000000..3b9ccee8a5 --- /dev/null +++ b/interface/resources/shaders/SkyFromAtmosphere.frag @@ -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; +} diff --git a/interface/resources/shaders/SkyFromAtmosphere.vert b/interface/resources/shaders/SkyFromAtmosphere.vert new file mode 100644 index 0000000000..19261ca046 --- /dev/null +++ b/interface/resources/shaders/SkyFromAtmosphere.vert @@ -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 +#include -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(); } diff --git a/interface/src/Environment.h b/interface/src/Environment.h index e028d86e32..f2517cb018 100644 --- a/interface/src/Environment.h +++ b/interface/src/Environment.h @@ -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__) */ diff --git a/interface/src/main.cpp b/interface/src/main.cpp index dd63a74c1a..171c530286 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -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); } diff --git a/libraries/voxels/src/EnvironmentData.cpp b/libraries/voxels/src/EnvironmentData.cpp index 9fff790810..4882a00e2e 100644 --- a/libraries/voxels/src/EnvironmentData.cpp +++ b/libraries/voxels/src/EnvironmentData.cpp @@ -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; diff --git a/libraries/voxels/src/EnvironmentData.h b/libraries/voxels/src/EnvironmentData.h index 12ebcd4a94..2bac3ba920 100644 --- a/libraries/voxels/src/EnvironmentData.h +++ b/libraries/voxels/src/EnvironmentData.h @@ -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); From 47f35669298dd0b544868a889478ffdd8264a53b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 7 May 2013 14:40:30 -0700 Subject: [PATCH 03/13] Wavelengths, switch for environment rendering, far plane adjustment. --- interface/src/Environment.cpp | 34 +++++++++++++----------- interface/src/main.cpp | 13 +++++++-- libraries/voxels/src/EnvironmentData.cpp | 9 ++++++- libraries/voxels/src/EnvironmentData.h | 5 ++++ 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 5b074eafc8..73f7db4943 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -12,15 +12,6 @@ #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)) { @@ -32,7 +23,6 @@ static GLhandleARB compileShader(int type, const QString& filename) { const char* sdata = source.constData(); glShaderSource(shaderID, 1, &sdata, 0); glCompileShaderARB(shaderID); - errorCheck(shaderID); return shaderID; } @@ -43,7 +33,6 @@ void Environment::init() { glAttachObjectARB(_skyFromAtmosphereProgramID, compileShader( GL_FRAGMENT_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.frag")); glLinkProgramARB(_skyFromAtmosphereProgramID); - errorCheck(_skyFromAtmosphereProgramID); _cameraPosLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "v3CameraPos"); _lightPosLocation = glGetUniformLocationARB(_skyFromAtmosphereProgramID, "v3LightPos"); @@ -65,18 +54,28 @@ void Environment::render(Camera& camera) { 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(); - glLoadIdentity(); - gluPerspective(camera.getFieldOfView(), camera.getAspectRatio(), 100, 100000000); - glUseProgramObjectARB(_skyFromAtmosphereProgramID); + float projection[16]; + glGetFloatv(GL_PROJECTION_MATRIX, projection); glm::vec3 relativeCameraPos = camera.getPosition() - getAtmosphereCenter(); + float near = camera.getNearClip(), far = glm::length(relativeCameraPos) + getAtmosphereOuterRadius(); + projection[10] = (far + near) / (near - far); + projection[14] = (2.0f * far * near) / (near - far); + glLoadMatrixf(projection); + + // the constants here are from Sean O'Neil's GPU Gems entry + // (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp + glUseProgramObjectARB(_skyFromAtmosphereProgramID); 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)); + 1 / powf(getScatteringWavelengths().r, 4.0f), + 1 / powf(getScatteringWavelengths().g, 4.0f), + 1 / powf(getScatteringWavelengths().b, 4.0f)); glUniform1fARB(_innerRadiusLocation, getAtmosphereInnerRadius()); glUniform1fARB(_krESunLocation, getRayleighScattering() * getSunBrightness()); glUniform1fARB(_kmESunLocation, getMieScattering() * getSunBrightness()); @@ -90,7 +89,10 @@ void Environment::render(Camera& camera) { glUniform1fARB(_g2Location, -0.990f * -0.990f); glFrontFace(GL_CW); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); glutSolidSphere(getAtmosphereOuterRadius(), 100, 50); + glDepthMask(GL_TRUE); glFrontFace(GL_CCW); glUseProgramObjectARB(0); @@ -98,5 +100,5 @@ void Environment::render(Camera& camera) { glPopMatrix(); glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + glPopMatrix(); } diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 171c530286..7686976d43 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -152,6 +152,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 environmentOn = true; // Whether to display the environment 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 @@ -685,8 +686,10 @@ void displaySide(Camera& whichCamera) { glPushMatrix(); // draw the sky dome - environment.render(whichCamera); - + if (::environmentOn) { + environment.render(whichCamera); + } + if (::starsOn) { // should be the first rendering pass - w/o depth buffer / lighting @@ -1218,6 +1221,10 @@ int setStars(int state) { return setValue(state, &::starsOn); } +int setEnvironment(int state) { + return setValue(state, &::environmentOn); +} + int setOculus(int state) { bool wasOn = ::oculusOn; int value = setValue(state, &::oculusOn); @@ -1363,6 +1370,7 @@ void initMenu() { menuColumnRender = menu.addColumn("Render"); menuColumnRender->addRow("Voxels (V)", setVoxels); menuColumnRender->addRow("Stars (*)", setStars); + menuColumnRender->addRow("Environment (E)", setEnvironment); menuColumnRender->addRow("Oculus (o)", setOculus); // Tools @@ -1550,6 +1558,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 == 'E') ::environmentOn = !::environmentOn; 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 diff --git a/libraries/voxels/src/EnvironmentData.cpp b/libraries/voxels/src/EnvironmentData.cpp index 4882a00e2e..a616715aa8 100644 --- a/libraries/voxels/src/EnvironmentData.cpp +++ b/libraries/voxels/src/EnvironmentData.cpp @@ -11,13 +11,14 @@ #include "PacketHeaders.h" // initial values from Sean O'Neil's GPU Gems entry (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), -// GameEngine.cpp +// GameEngine.cpp (and the radius of the earth) EnvironmentData::EnvironmentData() : _atmosphereCenter(0, -6371000, 0), _atmosphereInnerRadius(6371000), _atmosphereOuterRadius(6530275), _rayleighScattering(0.0025f), _mieScattering(0.0010f), + _scatteringWavelengths(0.650f, 0.570f, 0.475f), _sunLocation(1000, 1000, 0), _sunBrightness(20.0f) { } @@ -40,6 +41,9 @@ int EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const { memcpy(destinationBuffer, &_mieScattering, sizeof(_mieScattering)); destinationBuffer += sizeof(_mieScattering); + memcpy(destinationBuffer, &_scatteringWavelengths, sizeof(_scatteringWavelengths)); + destinationBuffer += sizeof(_scatteringWavelengths); + memcpy(destinationBuffer, &_sunLocation, sizeof(_sunLocation)); destinationBuffer += sizeof(_sunLocation); @@ -70,6 +74,9 @@ int EnvironmentData::parseData(unsigned char* sourceBuffer, int numBytes) { memcpy(&_mieScattering, sourceBuffer, sizeof(_mieScattering)); sourceBuffer += sizeof(_mieScattering); + memcpy(&_scatteringWavelengths, sourceBuffer, sizeof(_scatteringWavelengths)); + sourceBuffer += sizeof(_scatteringWavelengths); + memcpy(&_sunLocation, sourceBuffer, sizeof(_sunLocation)); sourceBuffer += sizeof(_sunLocation); diff --git a/libraries/voxels/src/EnvironmentData.h b/libraries/voxels/src/EnvironmentData.h index 2bac3ba920..69d2f46aec 100644 --- a/libraries/voxels/src/EnvironmentData.h +++ b/libraries/voxels/src/EnvironmentData.h @@ -28,6 +28,9 @@ public: 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; } @@ -45,6 +48,8 @@ private: float _rayleighScattering; float _mieScattering; + glm::vec3 _scatteringWavelengths; + glm::vec3 _sunLocation; float _sunBrightness; }; From 7c9b0d8f58eea1ddc8ae96db5b432c69f41874a0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 7 May 2013 15:10:02 -0700 Subject: [PATCH 04/13] Have the voxel server push out an environment packet with its regular updates. --- libraries/voxels/src/EnvironmentData.cpp | 2 ++ voxel-server/src/main.cpp | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libraries/voxels/src/EnvironmentData.cpp b/libraries/voxels/src/EnvironmentData.cpp index a616715aa8..e951c55c06 100644 --- a/libraries/voxels/src/EnvironmentData.cpp +++ b/libraries/voxels/src/EnvironmentData.cpp @@ -26,6 +26,8 @@ EnvironmentData::EnvironmentData() : int EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const { unsigned char* bufferStart = destinationBuffer; + *destinationBuffer++ = PACKET_HEADER_ENVIRONMENT_DATA; + memcpy(destinationBuffer, &_atmosphereCenter, sizeof(_atmosphereCenter)); destinationBuffer += sizeof(_atmosphereCenter); diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 380f2cc794..dca2dc49ae 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "VoxelAgentData.h" #include @@ -48,6 +49,8 @@ bool wantVoxelPersist = true; bool wantColorRandomizer = false; bool debugVoxelSending = false; +EnvironmentData environmentData; + void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) { float r = random ? randFloatInRange(0.05,0.1) : 0.25; float xc = random ? randFloatInRange(r,(1-r)) : 0.5; @@ -237,7 +240,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, @@ -267,6 +270,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) { @@ -559,4 +568,4 @@ int main(int argc, const char * argv[]) pthread_join(sendVoxelThread, NULL); return 0; -} \ No newline at end of file +} From 7c8a06ed4de1a7a4d51d90ee9391fdd6f25cd727 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 7 May 2013 17:40:55 -0700 Subject: [PATCH 05/13] Added wrapper classes for shaders/shader programs to ease the process of compiling, linking, assigning uniforms, etc. They're modeled after the ones included in QtOpenGL, which we can't use at the moment because they require a Qt OpenGL context. --- interface/CMakeLists.txt | 2 +- interface/src/Environment.cpp | 87 +++++++---------- interface/src/Environment.h | 5 +- interface/src/main.cpp | 46 ++++----- interface/src/renderer/ProgramObject.cpp | 119 +++++++++++++++++++++++ interface/src/renderer/ProgramObject.h | 66 +++++++++++++ interface/src/renderer/ShaderObject.cpp | 39 ++++++++ interface/src/renderer/ShaderObject.h | 36 +++++++ libraries/voxels/src/EnvironmentData.h | 2 +- 9 files changed, 323 insertions(+), 79 deletions(-) create mode 100644 interface/src/renderer/ProgramObject.cpp create mode 100644 interface/src/renderer/ProgramObject.h create mode 100644 interface/src/renderer/ShaderObject.cpp create mode 100644 interface/src/renderer/ShaderObject.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index dbcb79edc7..dcef05bdf6 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -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) diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 73f7db4943..56eb0ab7d1 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -5,48 +5,31 @@ // Created by Andrzej Kapolka on 5/6/13. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. -#include -#include - #include "Camera.h" #include "Environment.h" +#include "renderer/ProgramObject.h" +#include "renderer/ShaderObject.h" #include "world.h" -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); - 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); - - _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"); + _skyFromAtmosphereProgram = new ProgramObject(); + _skyFromAtmosphereProgram->attachFromSourceFile(GL_VERTEX_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.vert"); + _skyFromAtmosphereProgram->attachFromSourceFile(GL_FRAGMENT_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.frag"); + _skyFromAtmosphereProgram->link(); + + _cameraPosLocation = _skyFromAtmosphereProgram->getUniformLocation("v3CameraPos"); + _lightPosLocation = _skyFromAtmosphereProgram->getUniformLocation("v3LightPos"); + _invWavelengthLocation = _skyFromAtmosphereProgram->getUniformLocation("v3InvWavelength"); + _innerRadiusLocation = _skyFromAtmosphereProgram->getUniformLocation("fInnerRadius"); + _krESunLocation = _skyFromAtmosphereProgram->getUniformLocation("fKrESun"); + _kmESunLocation = _skyFromAtmosphereProgram->getUniformLocation("fKmESun"); + _kr4PiLocation = _skyFromAtmosphereProgram->getUniformLocation("fKr4PI"); + _km4PiLocation = _skyFromAtmosphereProgram->getUniformLocation("fKm4PI"); + _scaleLocation = _skyFromAtmosphereProgram->getUniformLocation("fScale"); + _scaleDepthLocation = _skyFromAtmosphereProgram->getUniformLocation("fScaleDepth"); + _scaleOverScaleDepthLocation = _skyFromAtmosphereProgram->getUniformLocation("fScaleOverScaleDepth"); + _gLocation = _skyFromAtmosphereProgram->getUniformLocation("g"); + _g2Location = _skyFromAtmosphereProgram->getUniformLocation("g2"); } void Environment::render(Camera& camera) { @@ -68,25 +51,25 @@ void Environment::render(Camera& camera) { // the constants here are from Sean O'Neil's GPU Gems entry // (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp - glUseProgramObjectARB(_skyFromAtmosphereProgramID); - glUniform3fARB(_cameraPosLocation, relativeCameraPos.x, relativeCameraPos.y, relativeCameraPos.z); + _skyFromAtmosphereProgram->bind(); + _skyFromAtmosphereProgram->setUniform(_cameraPosLocation, relativeCameraPos); glm::vec3 lightDirection = glm::normalize(getSunLocation()); - glUniform3fARB(_lightPosLocation, lightDirection.x, lightDirection.y, lightDirection.z); - glUniform3fARB(_invWavelengthLocation, + _skyFromAtmosphereProgram->setUniform(_lightPosLocation, lightDirection); + _skyFromAtmosphereProgram->setUniform(_invWavelengthLocation, 1 / powf(getScatteringWavelengths().r, 4.0f), 1 / powf(getScatteringWavelengths().g, 4.0f), 1 / powf(getScatteringWavelengths().b, 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, + _skyFromAtmosphereProgram->setUniform(_innerRadiusLocation, getAtmosphereInnerRadius()); + _skyFromAtmosphereProgram->setUniform(_krESunLocation, getRayleighScattering() * getSunBrightness()); + _skyFromAtmosphereProgram->setUniform(_kmESunLocation, getMieScattering() * getSunBrightness()); + _skyFromAtmosphereProgram->setUniform(_kr4PiLocation, getRayleighScattering() * 4.0f * PIf); + _skyFromAtmosphereProgram->setUniform(_km4PiLocation, getMieScattering() * 4.0f * PIf); + _skyFromAtmosphereProgram->setUniform(_scaleLocation, 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())); + _skyFromAtmosphereProgram->setUniform(_scaleDepthLocation, 0.25f); + _skyFromAtmosphereProgram->setUniform(_scaleOverScaleDepthLocation, (1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())) / 0.25f); - glUniform1fARB(_gLocation, -0.990f); - glUniform1fARB(_g2Location, -0.990f * -0.990f); + _skyFromAtmosphereProgram->setUniform(_gLocation, -0.990f); + _skyFromAtmosphereProgram->setUniform(_g2Location, -0.990f * -0.990f); glFrontFace(GL_CW); glDepthMask(GL_FALSE); @@ -95,7 +78,7 @@ void Environment::render(Camera& camera) { glDepthMask(GL_TRUE); glFrontFace(GL_CCW); - glUseProgramObjectARB(0); + _skyFromAtmosphereProgram->release(); glPopMatrix(); diff --git a/interface/src/Environment.h b/interface/src/Environment.h index f2517cb018..e9be491d9c 100644 --- a/interface/src/Environment.h +++ b/interface/src/Environment.h @@ -2,7 +2,7 @@ // Environment.h // interface // -// Created by Andrzej Kapolka on 5/16/13. +// Created by Andrzej Kapolka on 5/6/13. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // @@ -13,6 +13,7 @@ #include "InterfaceConfig.h" class Camera; +class ProgramObject; class Environment : public EnvironmentData { public: @@ -22,7 +23,7 @@ public: private: - GLhandleARB _skyFromAtmosphereProgramID; + ProgramObject* _skyFromAtmosphereProgram; int _cameraPosLocation; int _lightPosLocation; int _invWavelengthLocation; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 9b879adc74..f215dc4c52 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -58,6 +58,8 @@ #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" @@ -178,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 // @@ -813,18 +815,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); @@ -844,13 +844,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); @@ -864,8 +864,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); @@ -881,7 +881,7 @@ void displayOculus(Camera& whichCamera) { glEnable(GL_BLEND); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); - glUseProgramObjectARB(0); + ::oculusProgram->release(); glPopMatrix(); } diff --git a/interface/src/renderer/ProgramObject.cpp b/interface/src/renderer/ProgramObject.cpp new file mode 100644 index 0000000000..d2346bf3b3 --- /dev/null +++ b/interface/src/renderer/ProgramObject.cpp @@ -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); +} diff --git a/interface/src/renderer/ProgramObject.h b/interface/src/renderer/ProgramObject.h new file mode 100644 index 0000000000..e46d40c13f --- /dev/null +++ b/interface/src/renderer/ProgramObject.h @@ -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 + +#include + +#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__) */ diff --git a/interface/src/renderer/ShaderObject.cpp b/interface/src/renderer/ShaderObject.cpp new file mode 100644 index 0000000000..617f960204 --- /dev/null +++ b/interface/src/renderer/ShaderObject.cpp @@ -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 + +#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; +} diff --git a/interface/src/renderer/ShaderObject.h b/interface/src/renderer/ShaderObject.h new file mode 100644 index 0000000000..297650a40f --- /dev/null +++ b/interface/src/renderer/ShaderObject.h @@ -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 + +#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__) */ diff --git a/libraries/voxels/src/EnvironmentData.h b/libraries/voxels/src/EnvironmentData.h index 69d2f46aec..b4de3498c6 100644 --- a/libraries/voxels/src/EnvironmentData.h +++ b/libraries/voxels/src/EnvironmentData.h @@ -2,7 +2,7 @@ // EnvironmentData.h // interface // -// Created by Andrzej Kapolka on 5/16/13. +// Created by Andrzej Kapolka on 5/6/13. // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // From 4567c31a2639b88ddec8405ffdce765530e79d84 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 8 May 2013 09:55:46 -0700 Subject: [PATCH 06/13] Added licensing information from the GPU Gems site, fixed spacing. --- .../resources/shaders/SkyFromAtmosphere.frag | 24 ++++++++++++++++ .../resources/shaders/SkyFromAtmosphere.vert | 28 +++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/interface/resources/shaders/SkyFromAtmosphere.frag b/interface/resources/shaders/SkyFromAtmosphere.frag index 3b9ccee8a5..fb41786544 100644 --- a/interface/resources/shaders/SkyFromAtmosphere.frag +++ b/interface/resources/shaders/SkyFromAtmosphere.frag @@ -1,3 +1,27 @@ +// +// 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 // diff --git a/interface/resources/shaders/SkyFromAtmosphere.vert b/interface/resources/shaders/SkyFromAtmosphere.vert index 19261ca046..2587d262a2 100644 --- a/interface/resources/shaders/SkyFromAtmosphere.vert +++ b/interface/resources/shaders/SkyFromAtmosphere.vert @@ -1,3 +1,27 @@ +// +// 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 // @@ -45,7 +69,7 @@ void main(void) float fHeight = length(v3Start); float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight)); float fStartAngle = dot(v3Ray, v3Start) / fHeight; - float fStartOffset = fDepth*scale(fStartAngle); + float fStartOffset = fDepth * scale(fStartAngle); // Initialize the scattering loop variables //gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0); @@ -62,7 +86,7 @@ void main(void) 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))); + float fScatter = (fStartOffset + fDepth * (scale(fLightAngle) - scale(fCameraAngle))); vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI)); v3FrontColor += v3Attenuate * (fDepth * fScaledLength); v3SamplePoint += v3SampleRay; From 8d4a74cf03522e96c781eb11aeb0312aff9048fa Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 8 May 2013 10:00:31 -0700 Subject: [PATCH 07/13] Render environment -> render atmosphere. --- interface/src/Environment.cpp | 2 +- interface/src/Environment.h | 2 +- interface/src/main.cpp | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 56eb0ab7d1..224055ae27 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -32,7 +32,7 @@ void Environment::init() { _g2Location = _skyFromAtmosphereProgram->getUniformLocation("g2"); } -void Environment::render(Camera& camera) { +void Environment::renderAtmosphere(Camera& camera) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(getAtmosphereCenter().x, getAtmosphereCenter().y, getAtmosphereCenter().z); diff --git a/interface/src/Environment.h b/interface/src/Environment.h index e9be491d9c..51d7b92e1e 100644 --- a/interface/src/Environment.h +++ b/interface/src/Environment.h @@ -19,7 +19,7 @@ class Environment : public EnvironmentData { public: void init(); - void render(Camera& camera); + void renderAtmosphere(Camera& camera); private: diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c030a9314b..20de0099c0 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -145,7 +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 environmentOn = true; // Whether to display the environment +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 @@ -684,8 +684,8 @@ void displaySide(Camera& whichCamera) { glPushMatrix(); // draw the sky dome - if (::environmentOn) { - environment.render(whichCamera); + if (::atmosphereOn) { + environment.renderAtmosphere(whichCamera); } if (::starsOn) { @@ -1216,8 +1216,8 @@ int setStars(int state) { return setValue(state, &::starsOn); } -int setEnvironment(int state) { - return setValue(state, &::environmentOn); +int setAtmosphere(int state) { + return setValue(state, &::atmosphereOn); } int setOculus(int state) { @@ -1365,7 +1365,7 @@ void initMenu() { menuColumnRender = menu.addColumn("Render"); menuColumnRender->addRow("Voxels (V)", setVoxels); menuColumnRender->addRow("Stars (*)", setStars); - menuColumnRender->addRow("Environment (E)", setEnvironment); + menuColumnRender->addRow("Atmosphere (A)", setAtmosphere); menuColumnRender->addRow("Oculus (o)", setOculus); // Tools @@ -1548,7 +1548,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 == 'E') ::environmentOn = !::environmentOn; + 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 From 310c0288c70cdf95a217df064a2ef9790e5be029 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 8 May 2013 10:31:13 -0700 Subject: [PATCH 08/13] Changed atmosphere radius to 1000 meters. --- libraries/voxels/src/EnvironmentData.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/voxels/src/EnvironmentData.cpp b/libraries/voxels/src/EnvironmentData.cpp index e951c55c06..e7af40c8d3 100644 --- a/libraries/voxels/src/EnvironmentData.cpp +++ b/libraries/voxels/src/EnvironmentData.cpp @@ -13,13 +13,13 @@ // 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, -6371000, 0), - _atmosphereInnerRadius(6371000), - _atmosphereOuterRadius(6530275), + _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), + _sunLocation(1000, 500, 0), _sunBrightness(20.0f) { } From 82f16e7f34b77d409107f2f19bbaf2acad0fecdb Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 8 May 2013 11:42:31 -0700 Subject: [PATCH 09/13] Include the "sky from space" shaders, too, and use them when the camera is outside the atmosphere's outer radius. --- interface/resources/shaders/SkyFromSpace.frag | 48 ++++++++ interface/resources/shaders/SkyFromSpace.vert | 109 ++++++++++++++++++ interface/src/Environment.cpp | 97 ++++++++++------ interface/src/Environment.h | 39 ++++--- 4 files changed, 246 insertions(+), 47 deletions(-) create mode 100644 interface/resources/shaders/SkyFromSpace.frag create mode 100644 interface/resources/shaders/SkyFromSpace.vert diff --git a/interface/resources/shaders/SkyFromSpace.frag b/interface/resources/shaders/SkyFromSpace.frag new file mode 100644 index 0000000000..1056320e07 --- /dev/null +++ b/interface/resources/shaders/SkyFromSpace.frag @@ -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 = 1.0; // gl_FragColor.b; +} diff --git a/interface/resources/shaders/SkyFromSpace.vert b/interface/resources/shaders/SkyFromSpace.vert new file mode 100644 index 0000000000..d230ee8518 --- /dev/null +++ b/interface/resources/shaders/SkyFromSpace.vert @@ -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 + #include "Camera.h" #include "Environment.h" #include "renderer/ProgramObject.h" @@ -12,24 +14,8 @@ #include "world.h" void Environment::init() { - _skyFromAtmosphereProgram = new ProgramObject(); - _skyFromAtmosphereProgram->attachFromSourceFile(GL_VERTEX_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.vert"); - _skyFromAtmosphereProgram->attachFromSourceFile(GL_FRAGMENT_SHADER_ARB, "resources/shaders/SkyFromAtmosphere.frag"); - _skyFromAtmosphereProgram->link(); - - _cameraPosLocation = _skyFromAtmosphereProgram->getUniformLocation("v3CameraPos"); - _lightPosLocation = _skyFromAtmosphereProgram->getUniformLocation("v3LightPos"); - _invWavelengthLocation = _skyFromAtmosphereProgram->getUniformLocation("v3InvWavelength"); - _innerRadiusLocation = _skyFromAtmosphereProgram->getUniformLocation("fInnerRadius"); - _krESunLocation = _skyFromAtmosphereProgram->getUniformLocation("fKrESun"); - _kmESunLocation = _skyFromAtmosphereProgram->getUniformLocation("fKmESun"); - _kr4PiLocation = _skyFromAtmosphereProgram->getUniformLocation("fKr4PI"); - _km4PiLocation = _skyFromAtmosphereProgram->getUniformLocation("fKm4PI"); - _scaleLocation = _skyFromAtmosphereProgram->getUniformLocation("fScale"); - _scaleDepthLocation = _skyFromAtmosphereProgram->getUniformLocation("fScaleDepth"); - _scaleOverScaleDepthLocation = _skyFromAtmosphereProgram->getUniformLocation("fScaleOverScaleDepth"); - _gLocation = _skyFromAtmosphereProgram->getUniformLocation("g"); - _g2Location = _skyFromAtmosphereProgram->getUniformLocation("g2"); + _skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations); + _skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations); } void Environment::renderAtmosphere(Camera& camera) { @@ -44,32 +30,48 @@ void Environment::renderAtmosphere(Camera& camera) { float projection[16]; glGetFloatv(GL_PROJECTION_MATRIX, projection); glm::vec3 relativeCameraPos = camera.getPosition() - getAtmosphereCenter(); - float near = camera.getNearClip(), far = glm::length(relativeCameraPos) + getAtmosphereOuterRadius(); + 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 - _skyFromAtmosphereProgram->bind(); - _skyFromAtmosphereProgram->setUniform(_cameraPosLocation, relativeCameraPos); + program->bind(); + program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos); glm::vec3 lightDirection = glm::normalize(getSunLocation()); - _skyFromAtmosphereProgram->setUniform(_lightPosLocation, lightDirection); - _skyFromAtmosphereProgram->setUniform(_invWavelengthLocation, + 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)); - _skyFromAtmosphereProgram->setUniform(_innerRadiusLocation, getAtmosphereInnerRadius()); - _skyFromAtmosphereProgram->setUniform(_krESunLocation, getRayleighScattering() * getSunBrightness()); - _skyFromAtmosphereProgram->setUniform(_kmESunLocation, getMieScattering() * getSunBrightness()); - _skyFromAtmosphereProgram->setUniform(_kr4PiLocation, getRayleighScattering() * 4.0f * PIf); - _skyFromAtmosphereProgram->setUniform(_km4PiLocation, getMieScattering() * 4.0f * PIf); - _skyFromAtmosphereProgram->setUniform(_scaleLocation, 1.0f / (getAtmosphereOuterRadius() - getAtmosphereInnerRadius())); - _skyFromAtmosphereProgram->setUniform(_scaleDepthLocation, 0.25f); - _skyFromAtmosphereProgram->setUniform(_scaleOverScaleDepthLocation, + 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); - _skyFromAtmosphereProgram->setUniform(_gLocation, -0.990f); - _skyFromAtmosphereProgram->setUniform(_g2Location, -0.990f * -0.990f); + program->setUniform(locations[G_LOCATION], -0.990f); + program->setUniform(locations[G2_LOCATION], -0.990f * -0.990f); glFrontFace(GL_CW); glDepthMask(GL_FALSE); @@ -78,10 +80,37 @@ void Environment::renderAtmosphere(Camera& camera) { glDepthMask(GL_TRUE); glFrontFace(GL_CCW); - _skyFromAtmosphereProgram->release(); + 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; +} diff --git a/interface/src/Environment.h b/interface/src/Environment.h index 51d7b92e1e..9c68b5c3e5 100644 --- a/interface/src/Environment.h +++ b/interface/src/Environment.h @@ -23,20 +23,33 @@ public: private: + ProgramObject* createSkyProgram(const char* from, int* locations); + ProgramObject* _skyFromAtmosphereProgram; - 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; + 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__) */ From 5138f62aef31699e9f3bf514ac3cb14d4620778c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 8 May 2013 11:50:59 -0700 Subject: [PATCH 10/13] Use the "proper" alpha value (i.e., the one from the original shader). This makes the sky somewhat darker, but that probably just means we need more scattering or a brighter sun. --- interface/resources/shaders/SkyFromAtmosphere.frag | 2 +- interface/resources/shaders/SkyFromSpace.frag | 2 +- interface/src/Environment.cpp | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/resources/shaders/SkyFromAtmosphere.frag b/interface/resources/shaders/SkyFromAtmosphere.frag index fb41786544..9f6cc39f1b 100644 --- a/interface/resources/shaders/SkyFromAtmosphere.frag +++ b/interface/resources/shaders/SkyFromAtmosphere.frag @@ -44,5 +44,5 @@ 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; + gl_FragColor.a = gl_FragColor.b; } diff --git a/interface/resources/shaders/SkyFromSpace.frag b/interface/resources/shaders/SkyFromSpace.frag index 1056320e07..be872c5dbd 100644 --- a/interface/resources/shaders/SkyFromSpace.frag +++ b/interface/resources/shaders/SkyFromSpace.frag @@ -44,5 +44,5 @@ 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; + gl_FragColor.a = gl_FragColor.b; } diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index e0d52fca38..c198e7b8bb 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -73,12 +73,10 @@ void Environment::renderAtmosphere(Camera& camera) { program->setUniform(locations[G_LOCATION], -0.990f); program->setUniform(locations[G2_LOCATION], -0.990f * -0.990f); - glFrontFace(GL_CW); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glutSolidSphere(getAtmosphereOuterRadius(), 100, 50); glDepthMask(GL_TRUE); - glFrontFace(GL_CCW); program->release(); From 4ed7176ff6234353496fde9c98ee2a8fc79369ef Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 8 May 2013 12:07:21 -0700 Subject: [PATCH 11/13] Move the sun back up again to match the lighting. --- libraries/voxels/src/EnvironmentData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/voxels/src/EnvironmentData.cpp b/libraries/voxels/src/EnvironmentData.cpp index e7af40c8d3..c08489bf67 100644 --- a/libraries/voxels/src/EnvironmentData.cpp +++ b/libraries/voxels/src/EnvironmentData.cpp @@ -19,7 +19,7 @@ EnvironmentData::EnvironmentData() : _rayleighScattering(0.0025f), _mieScattering(0.0010f), _scatteringWavelengths(0.650f, 0.570f, 0.475f), - _sunLocation(1000, 500, 0), + _sunLocation(1000, 1000, 0), _sunBrightness(20.0f) { } From 8a21823469ecd777fe4cac1fc38a424bb3faf7fb Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 8 May 2013 12:11:48 -0700 Subject: [PATCH 12/13] Render the stars, when enabled, before the atmosphere. --- interface/src/main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index bc33c996e1..dfd557f93c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -683,11 +683,6 @@ void renderViewFrustum(ViewFrustum& viewFrustum) { void displaySide(Camera& whichCamera) { glPushMatrix(); - // draw the sky dome - if (::atmosphereOn) { - environment.renderAtmosphere(whichCamera); - } - if (::starsOn) { // should be the first rendering pass - w/o depth buffer / lighting @@ -695,6 +690,11 @@ void displaySide(Camera& whichCamera) { stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip()); } + // draw the sky dome + if (::atmosphereOn) { + environment.renderAtmosphere(whichCamera); + } + glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); From caeccf59ecea5735e62985828bb628c66f4a0c42 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 8 May 2013 13:13:56 -0700 Subject: [PATCH 13/13] When the stars and the atmosphere are both on, adjust the stars' alpha value based on the distance from the atmosphere. --- interface/src/Stars.cpp | 4 ++-- interface/src/Stars.h | 2 +- interface/src/main.cpp | 15 ++++++++++++- interface/src/starfield/Controller.h | 4 ++-- interface/src/starfield/renderer/Renderer.h | 25 +++++++++++++-------- 5 files changed, 35 insertions(+), 15 deletions(-) diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index a049269305..e8e0222420 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -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(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); } diff --git a/interface/src/Stars.h b/interface/src/Stars.h index caca215444..7088bee36e 100644 --- a/interface/src/Stars.h +++ b/interface/src/Stars.h @@ -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. diff --git a/interface/src/main.cpp b/interface/src/main.cpp index dfd557f93c..abbb67cdbc 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -686,8 +686,21 @@ 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 diff --git a/interface/src/starfield/Controller.h b/interface/src/starfield/Controller.h index a9dc52e747..93dc134392 100644 --- a/interface/src/starfield/Controller.h +++ b/interface/src/starfield/Controller.h @@ -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 diff --git a/interface/src/starfield/renderer/Renderer.h b/interface/src/starfield/renderer/Renderer.h index 8e9c45bc78..8a7e4bd6de 100644 --- a/interface/src/starfield/renderer/Renderer.h +++ b/interface/src/starfield/renderer/Renderer.h @@ -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();