Add depth bias option to simple programs

Simple programs are now lazily generated and stored in a hash
This commit is contained in:
Atlante45 2015-07-04 18:33:03 -07:00
parent d243190caf
commit 0093403bba
2 changed files with 93 additions and 44 deletions

View file

@ -50,37 +50,44 @@
static const std::string glowIntensityShaderHandle = "glowIntensity";
gpu::PipelinePointer DeferredLightingEffect::getPipeline(SimpleProgramKey config) {
auto it = _simplePrograms.find(config);
if (it != _simplePrograms.end()) {
return it.value();
}
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
if (config.isCulled()) {
state->setCullMode(gpu::State::CULL_BACK);
} else {
state->setCullMode(gpu::State::CULL_NONE);
}
state->setDepthTest(true, true, gpu::LESS_EQUAL);
if (config.hasDepthBias()) {
state->setDepthBias(1.0f);
state->setDepthBiasSlopeScale(1.0f);
}
state->setBlendFunction(false,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
gpu::PipelinePointer pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
_simplePrograms.insert(config, pipeline);
return pipeline;
}
void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
auto VS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(simple_vert)));
auto PS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(simple_textured_frag)));
auto PSEmissive = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(simple_textured_emisive_frag)));
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS));
gpu::ShaderPointer programEmissive = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PSEmissive));
_simpleShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PS));
_emissiveShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PSEmissive));
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
gpu::Shader::makeProgram(*programEmissive, slotBindings);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setCullMode(gpu::State::CULL_BACK);
state->setDepthTest(true, true, gpu::LESS_EQUAL);
state->setBlendFunction(false,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
gpu::StatePointer stateCullNone = gpu::StatePointer(new gpu::State());
stateCullNone->setCullMode(gpu::State::CULL_NONE);
stateCullNone->setDepthTest(true, true, gpu::LESS_EQUAL);
stateCullNone->setBlendFunction(false,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
_simpleProgram = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
_simpleProgramCullNone = gpu::PipelinePointer(gpu::Pipeline::create(program, stateCullNone));
_simpleProgramEmissive = gpu::PipelinePointer(gpu::Pipeline::create(programEmissive, state));
_simpleProgramEmissiveCullNone = gpu::PipelinePointer(gpu::Pipeline::create(programEmissive, stateCullNone));
gpu::Shader::makeProgram(*_simpleShader, slotBindings);
gpu::Shader::makeProgram(*_emissiveShader, slotBindings);
_viewState = viewState;
loadLightProgram(directional_light_frag, false, _directionalLight, _directionalLightLocations);
@ -117,21 +124,12 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset(_ambientLightMode % gpu::SphericalHarmonics::NUM_PRESET));
}
void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool emmisive) {
if (emmisive) {
if (culled) {
batch.setPipeline(_simpleProgramEmissive);
} else {
batch.setPipeline(_simpleProgramEmissiveCullNone);
}
} else {
if (culled) {
batch.setPipeline(_simpleProgram);
} else {
batch.setPipeline(_simpleProgramCullNone);
}
}
if (!textured) {
void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,
bool emmisive, bool depthBias) {
SimpleProgramKey config{textured, culled, emmisive, depthBias};
batch.setPipeline(getPipeline(config));
if (!config.isTextured()) {
// If it is not textured, bind white texture and keep using textured pipeline
batch.setUniformTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
}

View file

@ -24,6 +24,7 @@
class AbstractViewStateInterface;
class RenderArgs;
class SimpleProgramKey;
/// Handles deferred lighting for the bits that require it (voxels...)
class DeferredLightingEffect : public Dependency {
@ -34,7 +35,8 @@ public:
void init(AbstractViewStateInterface* viewState);
/// Sets up the state necessary to render static untextured geometry with the simple program.
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true, bool emmisive = false);
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
bool emmisive = false, bool depthBias = false);
//// Renders a solid sphere with the simple program.
void renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color);
@ -95,11 +97,11 @@ private:
};
static void loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations);
gpu::PipelinePointer getPipeline(SimpleProgramKey config);
gpu::PipelinePointer _simpleProgram;
gpu::PipelinePointer _simpleProgramCullNone;
gpu::PipelinePointer _simpleProgramEmissive;
gpu::PipelinePointer _simpleProgramEmissiveCullNone;
gpu::ShaderPointer _simpleShader;
gpu::ShaderPointer _emissiveShader;
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
ProgramObject _directionalSkyboxLight;
LightLocations _directionalSkyboxLightLocations;
@ -160,4 +162,53 @@ private:
model::SkyboxPointer _skybox;
};
class SimpleProgramKey {
public:
enum FlagBit {
IS_TEXTURED_FLAG = 0,
IS_CULLED_FLAG,
IS_EMISSIVE_FLAG,
HAS_DEPTH_BIAS_FLAG,
NUM_FLAGS,
};
enum Flag {
IS_TEXTURED = (1 << IS_TEXTURED_FLAG),
IS_CULLED = (1 << IS_CULLED_FLAG),
IS_EMISSIVE = (1 << IS_EMISSIVE_FLAG),
HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG),
};
typedef unsigned short Flags;
bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); }
bool isTextured() const { return isFlag(IS_TEXTURED); }
bool isCulled() const { return isFlag(IS_CULLED); }
bool isEmissive() const { return isFlag(IS_EMISSIVE); }
bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); }
Flags _flags = 0;
short _spare = 0;
int getRaw() const { return *reinterpret_cast<const int*>(this); }
SimpleProgramKey(bool textured = false, bool culled = true,
bool emissive = false, bool depthBias = false) {
_flags = (textured ? IS_TEXTURED : 0) | (culled ? IS_CULLED : 0) |
(emissive ? IS_EMISSIVE : 0) | (depthBias ? HAS_DEPTH_BIAS : 0);
}
SimpleProgramKey(int bitmask) : _flags(bitmask) {}
};
inline uint qHash(const SimpleProgramKey& key, uint seed) {
return qHash(key.getRaw(), seed);
}
inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) {
return a.getRaw() == b.getRaw();
}
#endif // hifi_DeferredLightingEffect_h