shader error fallback

This commit is contained in:
HifiExperiments 2024-06-29 21:50:33 -07:00
parent 647dbf9cea
commit 206d1c0157
5 changed files with 62 additions and 1 deletions

View file

@ -0,0 +1,30 @@
vec3 getErrorColor() {
vec3 positionWS = iWorldOrientation * (_positionMS.xyz * iWorldScale) + iWorldPosition;
float checkSize = 0.1;
vec3 edges = round(mod(positionWS, vec3(checkSize)) / checkSize);
float checkerboard = mod(edges.x + edges.y + edges.z, 2.0);
return mix(vec3(1, 0, 1), vec3(0.0), checkerboard);
}
// version 1
vec3 getProceduralColor() {
return getErrorColor();
}
// version 2
float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) {
diffuse = getErrorColor();
return 1.0;
}
// version 3
float getProceduralFragment(inout ProceduralFragment data) {
data.emissive = getErrorColor();
return 1.0;
}
// version 4
float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition data) {
data.emissive = getErrorColor();
return 1.0;
}

View file

@ -0,0 +1,7 @@
vec3 getSkyboxColor() {
vec3 normal = normalize(_normal);
float checkSize = 0.1;
vec3 edges = round(mod(normal, vec3(checkSize)) / checkSize);
float checkerboard = mod(edges.x + edges.y + edges.z, 2.0);
return mix(vec3(1, 0, 1), vec3(0.0), checkerboard);
}

View file

@ -377,6 +377,16 @@ void Procedural::prepare(gpu::Batch& batch,
_proceduralPipelines[key] = gpu::Pipeline::create(program, key.isTransparent() ? _transparentState : _opaqueState);
if (_errorFallbackFragmentSource.isEmpty()) {
QFile file(_errorFallbackFragmentPath);
file.open(QIODevice::ReadOnly);
_errorFallbackFragmentSource = QTextStream(&file).readAll();
}
fragmentSource.replacements[PROCEDURAL_BLOCK] = _errorFallbackFragmentSource.toStdString();
gpu::ShaderPointer errorFragmentShader = gpu::Shader::createPixel(fragmentSource);
gpu::ShaderPointer errorProgram = gpu::Shader::createProgram(vertexShader, errorFragmentShader);
_errorPipelines[key] = gpu::Pipeline::create(errorProgram, _opaqueState);
_lastCompile = usecTimestampNow();
if (_firstCompile == 0) {
_firstCompile = _lastCompile;
@ -385,8 +395,13 @@ void Procedural::prepare(gpu::Batch& batch,
recompiledShader = true;
}
gpu::PipelinePointer finalPipeline = recompiledShader ? _proceduralPipelines[key] : pipeline->second;
if (!finalPipeline || finalPipeline->getProgram()->compilationHasFailed()) {
finalPipeline = _errorPipelines[key];
}
// FIXME: need to handle forward rendering
batch.setPipeline(recompiledShader ? _proceduralPipelines[key] : pipeline->second);
batch.setPipeline(finalPipeline);
bool recreateUniforms = _shaderDirty || _uniformsDirty || recompiledShader || _prevKey != key;
if (recreateUniforms) {
@ -533,4 +548,6 @@ void graphics::ProceduralMaterial::initializeProcedural() {
// FIXME: Setup proper uniform slots and use correct pipelines for forward rendering
_procedural._opaqueFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural);
_procedural._transparentFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural_translucent);
_procedural._errorFallbackFragmentPath = ":" + QUrl("qrc:///shaders/errorShader.frag").path();
}

View file

@ -124,6 +124,8 @@ public:
gpu::Shader::Source _opaqueFragmentSource;
gpu::Shader::Source _transparentFragmentSource;
QString _errorFallbackFragmentSource;
gpu::StatePointer _opaqueState { std::make_shared<gpu::State>() };
gpu::StatePointer _transparentState { std::make_shared<gpu::State>() };
@ -176,11 +178,14 @@ protected:
bool _shaderDirty { true };
bool _uniformsDirty { true };
QString _errorFallbackFragmentPath;
// Rendering objects
UniformLambdas _uniforms;
NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS];
std::unordered_map<ProceduralProgramKey, gpu::PipelinePointer> _proceduralPipelines;
std::unordered_map<ProceduralProgramKey, gpu::PipelinePointer> _errorPipelines;
StandardInputs _standardInputs;
gpu::BufferPointer _standardInputsBuffer;

View file

@ -22,6 +22,8 @@ ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _crea
_procedural._vertexSource = shader::Source::get(shader::graphics::vertex::skybox);
_procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox);
_procedural._errorFallbackFragmentPath = ":" + QUrl("qrc:///shaders/errorSkyboxShader.frag").path();
_procedural.setDoesFade(false);
// Adjust the pipeline state for background using the stencil test