Fixing differing highlights between left and right eyes in stereo modes

This commit is contained in:
Brad Davis 2015-09-14 11:24:28 -07:00
parent d189fb932f
commit 1bb15e28d6
5 changed files with 106 additions and 72 deletions

View file

@ -44,6 +44,10 @@ void Context::enableStereo(bool enable) {
_backend->enableStereo(enable);
}
bool Context::isStereo() {
return _backend->isStereo();
}
void Context::setStereoProjections(const mat4 eyeProjections[2]) {
_backend->setStereoProjections(eyeProjections);
}

View file

@ -45,6 +45,10 @@ public:
_stereo._enable = enable;
}
virtual bool isStereo() {
return _stereo._enable;
}
void setStereoProjections(const mat4 eyeProjections[2]) {
for (int i = 0; i < 2; ++i) {
_stereo._eyeProjections[i] = eyeProjections[i];
@ -169,6 +173,7 @@ public:
void render(Batch& batch);
void enableStereo(bool enable = true);
bool isStereo();
void setStereoProjections(const mat4 eyeProjections[2]);
void setStereoViews(const mat4 eyeViews[2]);
void syncCache();

View file

@ -11,6 +11,8 @@
<@if not DEFERRED_BUFFER_SLH@>
<@def DEFERRED_BUFFER_SLH@>
uniform bool stereoMode = false;
// the diffuse texture
uniform sampler2D diffuseMap;
@ -55,6 +57,12 @@ DeferredFragment unpackDeferredFragment(vec2 texcoord) {
frag.diffuseVal = texture(diffuseMap, texcoord);
frag.specularVal = texture(specularMap, texcoord);
if (stereoMode) {
if (texcoord.x > 0.5) {
texcoord.x -= 0.5;
}
texcoord.x *= 2.0;
}
// compute the view space position using the depth
float z = near / (frag.depthVal * depthScale - 1.0);
frag.position = vec4((depthTexCoordOffset + texcoord * depthTexCoordScale) * z, z, 1.0);

View file

@ -50,6 +50,26 @@
static const std::string glowIntensityShaderHandle = "glowIntensity";
struct LightLocations {
int shadowDistances;
int shadowScale;
int nearLocation;
int depthScale;
int depthTexCoordOffset;
int depthTexCoordScale;
int radius;
int ambientSphere;
int lightBufferUnit;
int atmosphereBufferUnit;
int invViewMat;
int texcoordMat;
int coneParam;
int stereo;
};
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);
gpu::PipelinePointer DeferredLightingEffect::getPipeline(SimpleProgramKey config) {
auto it = _simplePrograms.find(config);
if (it != _simplePrograms.end()) {
@ -91,6 +111,18 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
gpu::Shader::makeProgram(*_emissiveShader, slotBindings);
_viewState = viewState;
_directionalLightLocations = std::make_shared<LightLocations>();
_directionalLightShadowMapLocations = std::make_shared<LightLocations>();
_directionalLightCascadedShadowMapLocations = std::make_shared<LightLocations>();
_directionalAmbientSphereLightLocations = std::make_shared<LightLocations>();
_directionalAmbientSphereLightShadowMapLocations = std::make_shared<LightLocations>();
_directionalAmbientSphereLightCascadedShadowMapLocations = std::make_shared<LightLocations>();
_directionalSkyboxLightLocations = std::make_shared<LightLocations>();
_directionalSkyboxLightShadowMapLocations = std::make_shared<LightLocations>();
_directionalSkyboxLightCascadedShadowMapLocations = std::make_shared<LightLocations>();
_pointLightLocations = std::make_shared<LightLocations>();
_spotLightLocations = std::make_shared<LightLocations>();
loadLightProgram(deferred_light_vert, directional_light_frag, false, _directionalLight, _directionalLightLocations);
loadLightProgram(deferred_light_vert, directional_light_shadow_map_frag, false, _directionalLightShadowMap,
_directionalLightShadowMapLocations);
@ -282,7 +314,7 @@ void DeferredLightingEffect::render(RenderArgs* args) {
invViewMat = args->_viewFrustum->getView();
auto& program = _directionalLight;
const LightLocations* locations = &_directionalLightLocations;
LightLocationsPtr locations = _directionalLightLocations;
// FIXME: Note: we've removed the menu items to enable shadows, so this will always be false for now.
// When we add back shadow support, this old approach may likely be removed and completely replaced
@ -294,16 +326,16 @@ void DeferredLightingEffect::render(RenderArgs* args) {
batch.setResourceTexture(4, framebufferCache->getShadowFramebuffer()->getDepthStencilBuffer());
program = _directionalLightShadowMap;
locations = &_directionalLightShadowMapLocations;
locations = _directionalLightShadowMapLocations;
if (cascadeShadowsEnabled) {
program = _directionalLightCascadedShadowMap;
locations = &_directionalLightCascadedShadowMapLocations;
locations = _directionalLightCascadedShadowMapLocations;
if (useSkyboxCubemap) {
program = _directionalSkyboxLightCascadedShadowMap;
locations = &_directionalSkyboxLightCascadedShadowMapLocations;
locations = _directionalSkyboxLightCascadedShadowMapLocations;
} else if (_ambientLightMode > -1) {
program = _directionalAmbientSphereLightCascadedShadowMap;
locations = &_directionalAmbientSphereLightCascadedShadowMapLocations;
locations = _directionalAmbientSphereLightCascadedShadowMapLocations;
}
batch.setPipeline(program);
batch._glUniform3fv(locations->shadowDistances, 1, (const float*) &_viewState->getShadowDistances());
@ -311,10 +343,10 @@ void DeferredLightingEffect::render(RenderArgs* args) {
} else {
if (useSkyboxCubemap) {
program = _directionalSkyboxLightShadowMap;
locations = &_directionalSkyboxLightShadowMapLocations;
locations = _directionalSkyboxLightShadowMapLocations;
} else if (_ambientLightMode > -1) {
program = _directionalAmbientSphereLightShadowMap;
locations = &_directionalAmbientSphereLightShadowMapLocations;
locations = _directionalAmbientSphereLightShadowMapLocations;
}
batch.setPipeline(program);
}
@ -323,10 +355,10 @@ void DeferredLightingEffect::render(RenderArgs* args) {
} else {
if (useSkyboxCubemap) {
program = _directionalSkyboxLight;
locations = &_directionalSkyboxLightLocations;
locations = _directionalSkyboxLightLocations;
} else if (_ambientLightMode > -1) {
program = _directionalAmbientSphereLight;
locations = &_directionalAmbientSphereLightLocations;
locations = _directionalAmbientSphereLightLocations;
}
batch.setPipeline(program);
}
@ -374,7 +406,9 @@ void DeferredLightingEffect::render(RenderArgs* args) {
float depthTexCoordOffsetT = bottom * nearScale - tMin * depthTexCoordScaleT;
batch._glUniform2f(locations->depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
batch._glUniform2f(locations->depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
bool stereo = args->_context->isStereo();
batch._glUniform1f(locations->stereo, stereo ? 1 : 0);
{
Transform model;
model.setTranslation(glm::vec3(sMin, tMin, 0.0));
@ -427,20 +461,20 @@ void DeferredLightingEffect::render(RenderArgs* args) {
if (!_pointLights.empty()) {
batch.setPipeline(_pointLight);
batch._glUniform1f(_pointLightLocations.nearLocation, nearVal);
batch._glUniform1f(_pointLightLocations.depthScale, depthScale);
batch._glUniform2f(_pointLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
batch._glUniform2f(_pointLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
batch._glUniform1f(_pointLightLocations->nearLocation, nearVal);
batch._glUniform1f(_pointLightLocations->depthScale, depthScale);
batch._glUniform2f(_pointLightLocations->depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
batch._glUniform2f(_pointLightLocations->depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
batch._glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat));
batch._glUniformMatrix4fv(_pointLightLocations->invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat));
batch._glUniformMatrix4fv(_pointLightLocations.texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat));
batch._glUniformMatrix4fv(_pointLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat));
for (auto lightID : _pointLights) {
auto& light = _allocatedLights[lightID];
// IN DEBUG: light->setShowContour(true);
if (_pointLightLocations.lightBufferUnit >= 0) {
batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer());
if (_pointLightLocations->lightBufferUnit >= 0) {
batch.setUniformBuffer(_pointLightLocations->lightBufferUnit, light->getSchemaBuffer());
}
float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
@ -475,20 +509,20 @@ void DeferredLightingEffect::render(RenderArgs* args) {
if (!_spotLights.empty()) {
batch.setPipeline(_spotLight);
batch._glUniform1f(_spotLightLocations.nearLocation, nearVal);
batch._glUniform1f(_spotLightLocations.depthScale, depthScale);
batch._glUniform2f(_spotLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
batch._glUniform2f(_spotLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
batch._glUniform1f(_spotLightLocations->nearLocation, nearVal);
batch._glUniform1f(_spotLightLocations->depthScale, depthScale);
batch._glUniform2f(_spotLightLocations->depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
batch._glUniform2f(_spotLightLocations->depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
batch._glUniformMatrix4fv(_spotLightLocations.invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat));
batch._glUniformMatrix4fv(_spotLightLocations->invViewMat, 1, false, reinterpret_cast< const float* >(&invViewMat));
batch._glUniformMatrix4fv(_spotLightLocations.texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat));
batch._glUniformMatrix4fv(_spotLightLocations->texcoordMat, 1, false, reinterpret_cast< const float* >(&texcoordMat));
for (auto lightID : _spotLights) {
auto light = _allocatedLights[lightID];
// IN DEBUG: light->setShowContour(true);
batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer());
batch.setUniformBuffer(_spotLightLocations->lightBufferUnit, light->getSchemaBuffer());
auto eyeLightPos = eyePoint - light->getPosition();
auto eyeHalfPlaneDistance = glm::dot(eyeLightPos, light->getDirection());
@ -502,7 +536,7 @@ void DeferredLightingEffect::render(RenderArgs* args) {
if ((eyeHalfPlaneDistance > -nearRadius) &&
(glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius)) {
coneParam.w = 0.0f;
batch._glUniform4fv(_spotLightLocations.coneParam, 1, reinterpret_cast< const float* >(&coneParam));
batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
Transform model;
model.setTranslation(glm::vec3(0.0f, 0.0f, -1.0f));
@ -522,7 +556,7 @@ void DeferredLightingEffect::render(RenderArgs* args) {
batch.setViewTransform(viewMat);
} else {
coneParam.w = 1.0f;
batch._glUniform4fv(_spotLightLocations.coneParam, 1, reinterpret_cast< const float* >(&coneParam));
batch._glUniform4fv(_spotLightLocations->coneParam, 1, reinterpret_cast< const float* >(&coneParam));
Transform model;
model.setTranslation(light->getPosition());
@ -596,7 +630,7 @@ void DeferredLightingEffect::setupTransparent(RenderArgs* args, int lightBufferU
args->_batch->setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer());
}
void DeferredLightingEffect::loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocations& locations) {
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {
auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(vertSource)));
auto PS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fragSource)));
@ -616,20 +650,21 @@ void DeferredLightingEffect::loadLightProgram(const char* vertSource, const char
gpu::Shader::makeProgram(*program, slotBindings);
locations.shadowDistances = program->getUniforms().findLocation("shadowDistances");
locations.shadowScale = program->getUniforms().findLocation("shadowScale");
locations.nearLocation = program->getUniforms().findLocation("near");
locations.depthScale = program->getUniforms().findLocation("depthScale");
locations.depthTexCoordOffset = program->getUniforms().findLocation("depthTexCoordOffset");
locations.depthTexCoordScale = program->getUniforms().findLocation("depthTexCoordScale");
locations.radius = program->getUniforms().findLocation("radius");
locations.ambientSphere = program->getUniforms().findLocation("ambientSphere.L00");
locations.invViewMat = program->getUniforms().findLocation("invViewMat");
locations.texcoordMat = program->getUniforms().findLocation("texcoordMat");
locations.coneParam = program->getUniforms().findLocation("coneParam");
locations->stereo = program->getUniforms().findLocation("stereoMode");
locations->shadowDistances = program->getUniforms().findLocation("shadowDistances");
locations->shadowScale = program->getUniforms().findLocation("shadowScale");
locations->nearLocation = program->getUniforms().findLocation("near");
locations->depthScale = program->getUniforms().findLocation("depthScale");
locations->depthTexCoordOffset = program->getUniforms().findLocation("depthTexCoordOffset");
locations->depthTexCoordScale = program->getUniforms().findLocation("depthTexCoordScale");
locations->radius = program->getUniforms().findLocation("radius");
locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00");
locations->invViewMat = program->getUniforms().findLocation("invViewMat");
locations->texcoordMat = program->getUniforms().findLocation("texcoordMat");
locations->coneParam = program->getUniforms().findLocation("coneParam");
locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer");
locations.atmosphereBufferUnit = program->getBuffers().findLocation("atmosphereBufferUnit");
locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer");
locations->atmosphereBufferUnit = program->getBuffers().findLocation("atmosphereBufferUnit");
auto state = std::make_shared<gpu::State>();
if (lightVolume) {

View file

@ -24,7 +24,8 @@
class AbstractViewStateInterface;
class RenderArgs;
class SimpleProgramKey;
struct LightLocations;
using LightLocationsPtr = std::shared_ptr<LightLocations>;
/// Handles deferred lighting for the bits that require it (voxels...)
class DeferredLightingEffect : public Dependency {
SINGLETON_DEPENDENCY
@ -82,28 +83,9 @@ private:
DeferredLightingEffect() {}
virtual ~DeferredLightingEffect() { }
class LightLocations {
public:
int shadowDistances;
int shadowScale;
int nearLocation;
int depthScale;
int depthTexCoordOffset;
int depthTexCoordScale;
int radius;
int ambientSphere;
int lightBufferUnit;
int atmosphereBufferUnit;
int invViewMat;
int texcoordMat;
int coneParam;
};
model::MeshPointer _spotLightMesh;
model::MeshPointer getSpotLightMesh();
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocations& locations);
gpu::PipelinePointer getPipeline(SimpleProgramKey config);
gpu::ShaderPointer _simpleShader;
@ -113,30 +95,30 @@ private:
gpu::PipelinePointer _blitLightBuffer;
gpu::PipelinePointer _directionalSkyboxLight;
LightLocations _directionalSkyboxLightLocations;
LightLocationsPtr _directionalSkyboxLightLocations;
gpu::PipelinePointer _directionalSkyboxLightShadowMap;
LightLocations _directionalSkyboxLightShadowMapLocations;
LightLocationsPtr _directionalSkyboxLightShadowMapLocations;
gpu::PipelinePointer _directionalSkyboxLightCascadedShadowMap;
LightLocations _directionalSkyboxLightCascadedShadowMapLocations;
LightLocationsPtr _directionalSkyboxLightCascadedShadowMapLocations;
gpu::PipelinePointer _directionalAmbientSphereLight;
LightLocations _directionalAmbientSphereLightLocations;
LightLocationsPtr _directionalAmbientSphereLightLocations;
gpu::PipelinePointer _directionalAmbientSphereLightShadowMap;
LightLocations _directionalAmbientSphereLightShadowMapLocations;
LightLocationsPtr _directionalAmbientSphereLightShadowMapLocations;
gpu::PipelinePointer _directionalAmbientSphereLightCascadedShadowMap;
LightLocations _directionalAmbientSphereLightCascadedShadowMapLocations;
LightLocationsPtr _directionalAmbientSphereLightCascadedShadowMapLocations;
gpu::PipelinePointer _directionalLight;
LightLocations _directionalLightLocations;
LightLocationsPtr _directionalLightLocations;
gpu::PipelinePointer _directionalLightShadowMap;
LightLocations _directionalLightShadowMapLocations;
LightLocationsPtr _directionalLightShadowMapLocations;
gpu::PipelinePointer _directionalLightCascadedShadowMap;
LightLocations _directionalLightCascadedShadowMapLocations;
LightLocationsPtr _directionalLightCascadedShadowMapLocations;
gpu::PipelinePointer _pointLight;
LightLocations _pointLightLocations;
LightLocationsPtr _pointLightLocations;
gpu::PipelinePointer _spotLight;
LightLocations _spotLightLocations;
LightLocationsPtr _spotLightLocations;
class PointLight {
public: