From 167e7d13777693ce748ffdc3e145cd7244c8e4c0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 16 Jun 2015 14:05:14 -0700 Subject: [PATCH] first cut at atmospheres in batch (doesn't work) --- interface/src/Application.cpp | 10 +- interface/src/Environment.cpp | 150 +++++++++++++++--- interface/src/Environment.h | 17 +- libraries/gpu/src/gpu/Batch.h | 2 + libraries/gpu/src/gpu/GLBackend.cpp | 28 ++++ .../model/src/model/SkyFromAtmosphere.slf | 6 +- .../model/src/model/SkyFromAtmosphere.slv | 21 +-- libraries/model/src/model/SkyFromSpace.slf | 4 +- libraries/model/src/model/SkyFromSpace.slv | 25 ++- 9 files changed, 217 insertions(+), 46 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 22cbad6775..4c84e39b64 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3255,6 +3255,9 @@ namespace render { template <> const Item::Bound payloadGetBound(const BackgroundRenderData::Pointer& stuff) { return Item::Bound(); } template <> void payloadRender(const BackgroundRenderData::Pointer& background, RenderArgs* args) { + Q_ASSERT(args->_batch); + gpu::Batch& batch = *args->_batch; + // Background rendering decision auto skyStage = DependencyManager::get()->getSkyStage(); auto skybox = model::SkyboxPointer(); @@ -3322,7 +3325,11 @@ namespace render { PerformanceTimer perfTimer("atmosphere"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... atmosphere..."); - background->_environment->renderAtmospheres(*(args->_viewFrustum)); + //gpu::Batch batch; + background->_environment->renderAtmospheres(batch, *(args->_viewFrustum)); + //gpu::GLBackend::renderBatch(batch, true); + //glUseProgram(0); + } } @@ -3333,7 +3340,6 @@ namespace render { if (skybox) { gpu::Batch batch; model::Skybox::render(batch, *(Application::getInstance()->getDisplayViewFrustum()), *skybox); - gpu::GLBackend::renderBatch(batch, true); glUseProgram(0); } diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 9f197920d9..1e9c571a57 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -28,6 +28,11 @@ #include "Environment.h" +#include "../../build/libraries/model/SkyFromSpace_vert.h" +#include "../../build/libraries/model/SkyFromSpace_frag.h" +#include "../../build/libraries/model/SkyFromAtmosphere_vert.h" +#include "../../build/libraries/model/SkyFromAtmosphere_frag.h" + uint qHash(const HifiSockAddr& sockAddr) { if (sockAddr.getAddress().isNull()) { return 0; // shouldn't happen, but if it does, zero is a perfectly valid hash @@ -56,6 +61,15 @@ void Environment::init() { _skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations); _skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations); + + + + qDebug() << "line:" << __LINE__; + setupAtmosphereProgram(SkyFromSpace_vert, SkyFromSpace_frag, _newSkyFromSpaceProgram, _newSkyFromSpaceUniformLocations); + qDebug() << "line:" << __LINE__; + setupAtmosphereProgram(SkyFromAtmosphere_vert, SkyFromAtmosphere_frag, _newSkyFromAtmosphereProgram, _newSkyFromAtmosphereUniformLocations); + qDebug() << "line:" << __LINE__; + // start off with a default-constructed environment data _data[HifiSockAddr()][0]; @@ -63,22 +77,84 @@ void Environment::init() { _initialized = true; } +void Environment::setupAtmosphereProgram(const char* vertSource, const char* fragSource, gpu::PipelinePointer& pipelineProgram, int* locations) { + + auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(vertSource))); + auto PS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fragSource))); + + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setCullMode(gpu::State::CULL_NONE); + state->setDepthTest(false); + state->setBlendFunction(true,gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + pipelineProgram = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); + + locations[CAMERA_POS_LOCATION] = program->getUniforms().findLocation("v3CameraPos"); + locations[LIGHT_POS_LOCATION] = program->getUniforms().findLocation("v3LightPos"); + locations[INV_WAVELENGTH_LOCATION] = program->getUniforms().findLocation("v3InvWavelength"); + locations[CAMERA_HEIGHT2_LOCATION] = program->getUniforms().findLocation("fCameraHeight2"); + locations[OUTER_RADIUS_LOCATION] = program->getUniforms().findLocation("fOuterRadius"); + locations[OUTER_RADIUS2_LOCATION] = program->getUniforms().findLocation("fOuterRadius2"); + locations[INNER_RADIUS_LOCATION] = program->getUniforms().findLocation("fInnerRadius"); + locations[KR_ESUN_LOCATION] = program->getUniforms().findLocation("fKrESun"); + locations[KM_ESUN_LOCATION] = program->getUniforms().findLocation("fKmESun"); + locations[KR_4PI_LOCATION] = program->getUniforms().findLocation("fKr4PI"); + locations[KM_4PI_LOCATION] = program->getUniforms().findLocation("fKm4PI"); + locations[SCALE_LOCATION] = program->getUniforms().findLocation("fScale"); + locations[SCALE_DEPTH_LOCATION] = program->getUniforms().findLocation("fScaleDepth"); + locations[SCALE_OVER_SCALE_DEPTH_LOCATION] = program->getUniforms().findLocation("fScaleOverScaleDepth"); + locations[G_LOCATION] = program->getUniforms().findLocation("g"); + locations[G2_LOCATION] = program->getUniforms().findLocation("g2"); + + /* + + program.addShaderFromSourceCode(QGLShader::Vertex, vertSource); + program.addShaderFromSourceCode(QGLShader::Fragment, fragSource); + program.link(); + + program.bind(); + + locations[CAMERA_POS_LOCATION] = program.uniformLocation("v3CameraPos"); + locations[LIGHT_POS_LOCATION] = program.uniformLocation("v3LightPos"); + locations[INV_WAVELENGTH_LOCATION] = program.uniformLocation("v3InvWavelength"); + locations[CAMERA_HEIGHT2_LOCATION] = program.uniformLocation("fCameraHeight2"); + locations[OUTER_RADIUS_LOCATION] = program.uniformLocation("fOuterRadius"); + locations[OUTER_RADIUS2_LOCATION] = program.uniformLocation("fOuterRadius2"); + locations[INNER_RADIUS_LOCATION] = program.uniformLocation("fInnerRadius"); + locations[KR_ESUN_LOCATION] = program.uniformLocation("fKrESun"); + locations[KM_ESUN_LOCATION] = program.uniformLocation("fKmESun"); + locations[KR_4PI_LOCATION] = program.uniformLocation("fKr4PI"); + locations[KM_4PI_LOCATION] = program.uniformLocation("fKm4PI"); + locations[SCALE_LOCATION] = program.uniformLocation("fScale"); + locations[SCALE_DEPTH_LOCATION] = program.uniformLocation("fScaleDepth"); + locations[SCALE_OVER_SCALE_DEPTH_LOCATION] = program.uniformLocation("fScaleOverScaleDepth"); + locations[G_LOCATION] = program.uniformLocation("g"); + locations[G2_LOCATION] = program.uniformLocation("g2"); + + program.release(); + */ +} + void Environment::resetToDefault() { _data.clear(); _data[HifiSockAddr()][0]; } -void Environment::renderAtmospheres(ViewFrustum& camera) { +void Environment::renderAtmospheres(gpu::Batch& batch, ViewFrustum& camera) { // get the lock for the duration of the call QMutexLocker locker(&_mutex); if (_environmentIsOverridden) { - renderAtmosphere(camera, _overrideData); + renderAtmosphere(batch, camera, _overrideData); } else { foreach (const ServerData& serverData, _data) { // TODO: do something about EnvironmentData foreach (const EnvironmentData& environmentData, serverData) { - renderAtmosphere(camera, environmentData); + renderAtmosphere(batch, camera, environmentData); } } } @@ -228,30 +304,39 @@ ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { return program; } -void Environment::renderAtmosphere(ViewFrustum& camera, const EnvironmentData& data) { +void Environment::renderAtmosphere(gpu::Batch& batch, ViewFrustum& camera, const EnvironmentData& data) { glm::vec3 center = data.getAtmosphereCenter(); - glPushMatrix(); - glTranslatef(center.x, center.y, center.z); + //glPushMatrix(); + //glTranslatef(center.x, center.y, center.z); + + Transform transform; + transform.setTranslation(center); + transform.setScale(1.0f); + batch.setModelTransform(transform); glm::vec3 relativeCameraPos = camera.getPosition() - center; float height = glm::length(relativeCameraPos); // use the appropriate shader depending on whether we're inside or outside - ProgramObject* program; + //ProgramObject* program; int* locations; if (height < data.getAtmosphereOuterRadius()) { - program = _skyFromAtmosphereProgram; - locations = _skyFromAtmosphereUniformLocations; + //program = &_newSkyFromAtmosphereProgram; + batch.setPipeline(_newSkyFromAtmosphereProgram); + locations = _newSkyFromAtmosphereUniformLocations; } else { - program = _skyFromSpaceProgram; - locations = _skyFromSpaceUniformLocations; + //program = &_newSkyFromSpaceProgram; + batch.setPipeline(_newSkyFromSpaceProgram); + locations = _newSkyFromSpaceUniformLocations; } // 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->bind(); + /* program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos); glm::vec3 lightDirection = glm::normalize(data.getSunLocation()); program->setUniform(locations[LIGHT_POS_LOCATION], lightDirection); @@ -273,15 +358,40 @@ void Environment::renderAtmosphere(ViewFrustum& camera, const EnvironmentData& d (1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f); program->setUniformValue(locations[G_LOCATION], -0.990f); program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); + */ - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glEnable(GL_BLEND); - DependencyManager::get()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere - glDepthMask(GL_TRUE); + + batch._glUniform3fv(locations[CAMERA_POS_LOCATION], relativeCameraPos); + glm::vec3 lightDirection = glm::normalize(data.getSunLocation()); + batch._glUniform3fv(locations[LIGHT_POS_LOCATION], lightDirection); + batch._glUniform3f(locations[INV_WAVELENGTH_LOCATION], + 1 / powf(data.getScatteringWavelengths().r, 4.0f), + 1 / powf(data.getScatteringWavelengths().g, 4.0f), + 1 / powf(data.getScatteringWavelengths().b, 4.0f)); + batch._glUniform1f(locations[CAMERA_HEIGHT2_LOCATION], height * height); + batch._glUniform1f(locations[OUTER_RADIUS_LOCATION], data.getAtmosphereOuterRadius()); + batch._glUniform1f(locations[OUTER_RADIUS2_LOCATION], data.getAtmosphereOuterRadius() * data.getAtmosphereOuterRadius()); + batch._glUniform1f(locations[INNER_RADIUS_LOCATION], data.getAtmosphereInnerRadius()); + batch._glUniform1f(locations[KR_ESUN_LOCATION], data.getRayleighScattering() * data.getSunBrightness()); + batch._glUniform1f(locations[KM_ESUN_LOCATION], data.getMieScattering() * data.getSunBrightness()); + batch._glUniform1f(locations[KR_4PI_LOCATION], data.getRayleighScattering() * 4.0f * PI); + batch._glUniform1f(locations[KM_4PI_LOCATION], data.getMieScattering() * 4.0f * PI); + batch._glUniform1f(locations[SCALE_LOCATION], 1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())); + batch._glUniform1f(locations[SCALE_DEPTH_LOCATION], 0.25f); + batch._glUniform1f(locations[SCALE_OVER_SCALE_DEPTH_LOCATION], + (1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f); + batch._glUniform1f(locations[G_LOCATION], -0.990f); + batch._glUniform1f(locations[G2_LOCATION], -0.990f * -0.990f); + + + //glDepthMask(GL_FALSE); + //glDisable(GL_DEPTH_TEST); + //glDisable(GL_CULL_FACE); + //glEnable(GL_BLEND); + DependencyManager::get()->renderSphere(batch,1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere + //glDepthMask(GL_TRUE); - program->release(); + //program->release(); - glPopMatrix(); + //glPopMatrix(); } diff --git a/interface/src/Environment.h b/interface/src/Environment.h index c1b4171947..9048678230 100644 --- a/interface/src/Environment.h +++ b/interface/src/Environment.h @@ -16,6 +16,9 @@ #include #include +#include + +#include #include "EnvironmentData.h" @@ -29,7 +32,7 @@ public: void init(); void resetToDefault(); - void renderAtmospheres(ViewFrustum& camera); + void renderAtmospheres(gpu::Batch& batch, ViewFrustum& camera); void override(const EnvironmentData& overrideData) { _overrideData = overrideData; _environmentIsOverridden = true; } void endOverride() { _environmentIsOverridden = false; } @@ -46,12 +49,12 @@ private: ProgramObject* createSkyProgram(const char* from, int* locations); - void renderAtmosphere(ViewFrustum& camera, const EnvironmentData& data); + void renderAtmosphere(gpu::Batch& batch, ViewFrustum& camera, const EnvironmentData& data); bool _initialized; ProgramObject* _skyFromAtmosphereProgram; ProgramObject* _skyFromSpaceProgram; - + enum { CAMERA_POS_LOCATION, LIGHT_POS_LOCATION, @@ -74,6 +77,14 @@ private: int _skyFromAtmosphereUniformLocations[LOCATION_COUNT]; int _skyFromSpaceUniformLocations[LOCATION_COUNT]; + + void setupAtmosphereProgram(const char* vertSource, const char* fragSource, gpu::PipelinePointer& pipelineProgram, int* locations); + + + gpu::PipelinePointer _newSkyFromAtmosphereProgram; + gpu::PipelinePointer _newSkyFromSpaceProgram; + int _newSkyFromAtmosphereUniformLocations[LOCATION_COUNT]; + int _newSkyFromSpaceUniformLocations[LOCATION_COUNT]; typedef QHash ServerData; diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 405ea9459d..77c9308af5 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -150,6 +150,7 @@ public: void _glUseProgram(GLuint program); void _glUniform1f(GLint location, GLfloat v0); void _glUniform2f(GLint location, GLfloat v0, GLfloat v1); + void _glUniform3f(GLint location, GLfloat v0, GLfloat v1); void _glUniform4fv(GLint location, GLsizei count, const GLfloat* value); void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); @@ -210,6 +211,7 @@ public: COMMAND_glUseProgram, COMMAND_glUniform1f, COMMAND_glUniform2f, + COMMAND_glUniform3f, COMMAND_glUniform4fv, COMMAND_glUniformMatrix4fv, diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index da6979fb27..7ba344dfbd 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -61,6 +61,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUseProgram), (&::gpu::GLBackend::do_glUniform1f), (&::gpu::GLBackend::do_glUniform2f), + (&::gpu::GLBackend::do_glUniform3f), (&::gpu::GLBackend::do_glUniform4fv), (&::gpu::GLBackend::do_glUniformMatrix4fv), @@ -462,6 +463,7 @@ void Batch::_glUniform2f(GLint location, GLfloat v0, GLfloat v1) { DO_IT_NOW(_glUniform2f, 1); } + void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) { if (_pipeline._program == 0) { // We should call updatePipeline() to bind the program but we are not doing that @@ -475,6 +477,32 @@ void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } +void Batch::_glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) { + ADD_COMMAND_GL(glUniform3f); + + _params.push_back(v2); + _params.push_back(v1); + _params.push_back(v0); + _params.push_back(location); + + DO_IT_NOW(_glUniform3f, 1); +} + +void GLBackend::do_glUniform3f(Batch& batch, uint32 paramOffset) { + if (_pipeline._program == 0) { + // We should call updatePipeline() to bind the program but we are not doing that + // because these uniform setters are deprecated and we don;t want to create side effect + return; + } + glUniform3f( + batch._params[paramOffset + 3]._int, + batch._params[paramOffset + 2]._float, + batch._params[paramOffset + 1]._float, + batch._params[paramOffset + 0]._float); + (void) CHECK_GL_ERROR(); +} + + void Batch::_glUniform4fv(GLint location, GLsizei count, const GLfloat* value) { ADD_COMMAND_GL(glUniform4fv); diff --git a/libraries/model/src/model/SkyFromAtmosphere.slf b/libraries/model/src/model/SkyFromAtmosphere.slf index 02036d0d7c..b82cddc282 100755 --- a/libraries/model/src/model/SkyFromAtmosphere.slf +++ b/libraries/model/src/model/SkyFromAtmosphere.slf @@ -51,7 +51,8 @@ uniform vec3 v3LightPos; uniform float g; uniform float g2; -varying vec3 position; +varying vec3 myPosition; + float scale(float fCos) { @@ -59,10 +60,11 @@ float scale(float 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 = position; + vec3 v3Pos = myPosition; vec3 v3Ray = v3Pos - v3CameraPos; float fFar = length(v3Ray); v3Ray /= fFar; diff --git a/libraries/model/src/model/SkyFromAtmosphere.slv b/libraries/model/src/model/SkyFromAtmosphere.slv index 785f89bb48..c19cb34c6a 100755 --- a/libraries/model/src/model/SkyFromAtmosphere.slv +++ b/libraries/model/src/model/SkyFromAtmosphere.slv @@ -33,6 +33,9 @@ // Copyright (c) 2004 Sean O'Neil // +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + 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 @@ -50,19 +53,19 @@ uniform float fScaleOverScaleDepth; // fScale / fScaleDepth const int nSamples = 2; const float fSamples = 2.0; -varying vec3 position; +varying vec3 myPosition; -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) - position = gl_Vertex.xyz * fOuterRadius; + myPosition = gl_Vertex.xyz * fOuterRadius; - gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0); + //gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0); + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + vec4 v4pos = vec4(myPosition, 1.0); + <$transformModelToClipPos(cam, obj, v4pos, gl_Position)$> } diff --git a/libraries/model/src/model/SkyFromSpace.slf b/libraries/model/src/model/SkyFromSpace.slf index 5f6ce80efa..4e13438ccb 100755 --- a/libraries/model/src/model/SkyFromSpace.slf +++ b/libraries/model/src/model/SkyFromSpace.slf @@ -53,7 +53,7 @@ uniform float g2; const int nSamples = 2; const float fSamples = 2.0; -varying vec3 position; +varying vec3 myPosition; float scale(float fCos) { @@ -65,7 +65,7 @@ float scale(float fCos) 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 = position; + vec3 v3Pos = myPosition; vec3 v3Ray = v3Pos - v3CameraPos; float fFar = length(v3Ray); v3Ray /= fFar; diff --git a/libraries/model/src/model/SkyFromSpace.slv b/libraries/model/src/model/SkyFromSpace.slv index 6740d1909e..9090d76da2 100755 --- a/libraries/model/src/model/SkyFromSpace.slv +++ b/libraries/model/src/model/SkyFromSpace.slv @@ -1,5 +1,6 @@ -#version 120 - +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> // // For licensing information, see http://http.developer.nvidia.com/GPUGems/gpugems_app01.html: // @@ -32,12 +33,20 @@ // Copyright (c) 2004 Sean O'Neil // +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> + uniform float fOuterRadius; // The outer (atmosphere) radius -varying vec3 position; +varying vec3 myPosition; -void main(void) -{ - position = gl_Vertex.xyz * fOuterRadius; - gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0); -} + +void main(void) { + myPosition = gl_Vertex.xyz * fOuterRadius; + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + vec4 v4pos = vec4(myPosition, 1.0); + <$transformModelToClipPos(cam, obj, v4pos, gl_Position)$> +} \ No newline at end of file