Fade working on voxel objects

This commit is contained in:
Olivier Prat 2017-06-08 14:57:09 +02:00
parent 20d4fcbbc7
commit cba70e6be0
10 changed files with 155 additions and 42 deletions

View file

@ -48,13 +48,17 @@
#include "model/Geometry.h"
#include "EntityTreeRenderer.h"
#include "polyvox_vert.h"
#include "polyvox_fade_vert.h"
#include "polyvox_frag.h"
#include "polyvox_fade_frag.h"
#include "RenderablePolyVoxEntityItem.h"
#include "EntityEditPacketSender.h"
#include "PhysicalEntitySimulation.h"
gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr;
gpu::PipelinePointer RenderablePolyVoxEntityItem::_wireframePipeline = nullptr;
#include "FadeEffect.h"
gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipelines[2] = { nullptr, nullptr };
gpu::PipelinePointer RenderablePolyVoxEntityItem::_wireframePipelines[2] = { nullptr, nullptr };
const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5;
@ -727,31 +731,34 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
return;
}
if (!_pipeline) {
gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(std::string(polyvox_vert));
gpu::ShaderPointer pixelShader = gpu::Shader::createPixel(std::string(polyvox_frag));
if (!_pipelines[0]) {
gpu::ShaderPointer vertexShaders[2] = { gpu::Shader::createVertex(std::string(polyvox_vert)), gpu::Shader::createVertex(std::string(polyvox_fade_vert)) };
gpu::ShaderPointer pixelShaders[2] = { gpu::Shader::createPixel(std::string(polyvox_frag)), gpu::Shader::createPixel(std::string(polyvox_fade_frag)) };
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0));
slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1));
slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2));
gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader);
gpu::Shader::makeProgram(*program, slotBindings);
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3));
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK);
state->setDepthTest(true, true, gpu::LESS_EQUAL);
_pipeline = gpu::Pipeline::create(program, state);
auto wireframeState = std::make_shared<gpu::State>();
wireframeState->setCullMode(gpu::State::CULL_BACK);
wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL);
wireframeState->setFillMode(gpu::State::FILL_LINE);
_wireframePipeline = gpu::Pipeline::create(program, wireframeState);
// Two sets of pipelines: normal and fading
for (auto i = 0; i < 2; i++) {
gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShaders[i], pixelShaders[i]);
gpu::Shader::makeProgram(*program, slotBindings);
_pipelines[i] = gpu::Pipeline::create(program, state);
_wireframePipelines[i] = gpu::Pipeline::create(program, wireframeState);
}
}
if (!_vertexFormat) {
@ -765,7 +772,8 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
// Pick correct Pipeline
bool wireframe = (render::ShapeKey(args->_globalShapeKey).isWireframe());
auto pipeline = (wireframe ? _wireframePipeline : _pipeline);
auto pipelineVariation = isFading() & 1;
auto pipeline = (wireframe ? _wireframePipelines[pipelineVariation]: _pipelines[pipelineVariation]);
batch.setPipeline(pipeline);
Transform transform(voxelToWorldMatrix());
@ -809,6 +817,12 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
batch.setResourceTexture(2, DependencyManager::get<TextureCache>()->getWhiteTexture());
}
// Apply fade effect
auto fadeEffect = DependencyManager::get<FadeEffect>();
if (fadeEffect->bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime, isFading())) {
fadeEffect->bindPerBatch(batch, 3);
}
int voxelVolumeSizeLocation = pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize");
batch._glUniform3f(voxelVolumeSizeLocation, voxelVolumeSize.x, voxelVolumeSize.y, voxelVolumeSize.z);
@ -1611,7 +1625,7 @@ void RenderablePolyVoxEntityItem::bonkNeighbors() {
void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) {
EntityItem::locationChanged(tellPhysics);
if (!_pipeline || !render::Item::isValidID(_myItem)) {
if (!_pipelines[0] || !render::Item::isValidID(_myItem)) {
return;
}
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();

View file

@ -143,7 +143,7 @@ public:
void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); }
// Transparent polyvox didn't seem to be working so disable for now
// Transparent polyvox didn't seem to be working so disable for now.
bool isTransparent() override { return false; }
bool getMeshes(MeshProxyList& result) override;
@ -166,8 +166,9 @@ private:
const int MATERIAL_GPU_SLOT = 3;
render::ItemID _myItem{ render::Item::INVALID_ITEM_ID };
static gpu::PipelinePointer _pipeline;
static gpu::PipelinePointer _wireframePipeline;
static gpu::PipelinePointer _pipelines[2];
static gpu::PipelinePointer _wireframePipelines[2];
ShapeInfo _shapeInfo;

View file

@ -0,0 +1,60 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// polyvox_fade.frag
// fragment shader
//
// Created by Olivier Prat on 2017-06-08
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include model/Material.slh@>
<@include DeferredBufferWrite.slh@>
<@include Fade.slh@>
in vec3 _normal;
in vec4 _position;
in vec4 _worldPosition;
in vec4 _worldFadePosition;
uniform sampler2D xMap;
uniform sampler2D yMap;
uniform sampler2D zMap;
uniform vec3 voxelVolumeSize;
// Declare after all samplers to prevent sampler location mix up with voxel shading (sampler locations are hardcoded in RenderablePolyVoxEntityItem)
<$declareFadeFragment()$>
void main(void) {
applyFade(_worldFadePosition.xyz);
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
worldNormal = normalize(worldNormal);
float inPositionX = (_worldPosition.x - 0.5) / voxelVolumeSize.x;
float inPositionY = (_worldPosition.y - 0.5) / voxelVolumeSize.y;
float inPositionZ = (_worldPosition.z - 0.5) / voxelVolumeSize.z;
vec4 xyDiffuse = texture(xMap, vec2(-inPositionX, -inPositionY));
vec4 xzDiffuse = texture(yMap, vec2(-inPositionX, inPositionZ));
vec4 yzDiffuse = texture(zMap, vec2(inPositionZ, -inPositionY));
vec3 xyDiffuseScaled = xyDiffuse.rgb * abs(worldNormal.z);
vec3 xzDiffuseScaled = xzDiffuse.rgb * abs(worldNormal.y);
vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x);
vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0);
packDeferredFragment(
_normal,
1.0,
vec3(diffuse),
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,
DEFAULT_OCCLUSION,
DEFAULT_SCATTERING);
}

View file

@ -0,0 +1,35 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// polyvox_fade.vert
// vertex shader
//
// Created by Seth Alves on 2015-8-3
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include gpu/Inputs.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include Fade.slh@>
out vec4 _position;
out vec4 _worldPosition;
out vec3 _normal;
out vec4 _worldFadePosition;
void main(void) {
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToEyeDir(cam, obj, inNormal.xyz, _normal)$>
<$transformModelToWorldPos(obj, inPosition, _worldFadePosition)$>
_worldPosition = inPosition;
}

View file

@ -22,9 +22,13 @@ render::ShapeKey::Builder FadeEffect::getKeyBuilder(render::ShapeKey::Builder bu
return builder;
}
void FadeEffect::bindPerBatch(gpu::Batch& batch) const
{
batch.setResourceTexture(render::ShapePipeline::Slot::MAP::FADE_MASK, _fadeMaskMap);
void FadeEffect::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation) const {
batch.setResourceTexture(fadeMaskMapLocation, _fadeMaskMap);
}
void FadeEffect::bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const {
auto slot = pipeline->getProgram()->getTextures().findLocation("fadeMaskMap");
batch.setResourceTexture(slot, _fadeMaskMap);
}
float FadeEffect::computeFadePercent(quint64 startTime) const {
@ -37,12 +41,12 @@ float FadeEffect::computeFadePercent(quint64 startTime) const {
return fadeAlpha;
}
void FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state) const {
bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, state);
bool FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const {
return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, isFading);
}
void FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, State state) const {
if (state != Complete || _isDebugEnabled) {
bool FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const {
if (isFading || _isDebugEnabled) {
auto& program = pipeline->getProgram();
auto fadeOffsetLoc = program->getUniforms().findLocation("fadeOffset");
auto fadePercentLoc = program->getUniforms().findLocation("fadePercent");
@ -60,5 +64,7 @@ void FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, g
batch._glUniform1f(fadePercentLoc, percent);
batch._glUniform3f(fadeOffsetLoc, offset.x, offset.y, offset.z);
}
return true;
}
return false;
}

View file

@ -20,12 +20,6 @@ class FadeEffect : public Dependency {
SINGLETON_DEPENDENCY
public:
enum State : uint8_t {
WaitingToStart = 0,
InProgress = 1,
Complete = 2,
};
FadeEffect();
const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; }
@ -38,9 +32,10 @@ public:
render::ShapeKey::Builder getKeyBuilder(render::ShapeKey::Builder builder = render::ShapeKey::Builder()) const;
void bindPerBatch(gpu::Batch& batch) const;
void bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, State state = InProgress) const;
void bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, State state = InProgress) const;
void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation = render::ShapePipeline::Slot::MAP::FADE_MASK) const;
void bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const;
bool bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const;
bool bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const;
float computeFadePercent(quint64 startTime) const;

View file

@ -484,7 +484,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
if (wireframe) {
builder.withWireframe();
}
if (_fadeState != FadeEffect::Complete) {
if (_fadeState != STATE_COMPLETE) {
builder.withFade();
}
return builder.build();
@ -528,13 +528,13 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
return; // bail asap
}
if (_fadeState == FadeEffect::WaitingToStart) {
if (_fadeState == STATE_WAITING_TO_START) {
if (model->isLoaded()) {
if (EntityItem::getEntitiesShouldFadeFunction()()) {
_fadeStartTime = usecTimestampNow();
_fadeState = FadeEffect::InProgress;
_fadeState = STATE_IN_PROGRESS;
} else {
_fadeState = FadeEffect::Complete;
_fadeState = STATE_COMPLETE;
}
model->setRenderItemsNeedUpdate();
} else {
@ -567,7 +567,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
bindMaterial(batch, locations, args->_enableTexturing);
// Apply fade effect
DependencyManager::get<FadeEffect>()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState);
DependencyManager::get<FadeEffect>()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState!=STATE_COMPLETE);
args->_details._materialSwitches++;

View file

@ -118,8 +118,14 @@ public:
private:
enum State : uint8_t {
STATE_WAITING_TO_START = 0,
STATE_IN_PROGRESS = 1,
STATE_COMPLETE = 2,
};
mutable quint64 _fadeStartTime { 0 };
mutable FadeEffect::State _fadeState { FadeEffect::WaitingToStart } ;
mutable State _fadeState { STATE_WAITING_TO_START } ;
};

View file

@ -70,7 +70,6 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER));
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT));
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK));
slotBindings.insert(gpu::Shader::Binding(std::string("fadeBuffer"), Slot::BUFFER::FADE));
gpu::Shader::makeProgram(*program, slotBindings);
@ -90,7 +89,6 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer");
locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap");
locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap");
locations->fadeBufferUnit = program->getUniformBuffers().findLocation("fadeBuffer");
ShapeKey key{filter._flags};
auto gpuPipeline = gpu::Pipeline::create(program, state);

View file

@ -214,7 +214,6 @@ public:
LIGHTING_MODEL,
LIGHT,
LIGHT_AMBIENT_BUFFER,
FADE,
};
enum MAP {
@ -245,7 +244,6 @@ public:
int lightBufferUnit;
int lightAmbientBufferUnit;
int lightAmbientMapUnit;
int fadeBufferUnit;
int fadeMaskTextureUnit;
};
using LocationsPointer = std::shared_ptr<Locations>;