diff --git a/filament/src/driver/Driver.h b/filament/src/driver/Driver.h index c27f13fd61..5734de5e01 100644 --- a/filament/src/driver/Driver.h +++ b/filament/src/driver/Driver.h @@ -204,9 +204,15 @@ public: }; }; + struct PolygonOffset { + float slope = 0; // factor in GL-speak + float constant = 0; // units in GL-speak + }; + struct PipelineState { ProgramHandle program; RasterState rasterState; + PolygonOffset polygonOffset; }; static SamplerFormat getSamplerFormat(TextureFormat format) noexcept; diff --git a/filament/src/driver/opengl/OpenGLDriver.cpp b/filament/src/driver/opengl/OpenGLDriver.cpp index 07bea988ed..5938cd7bdb 100644 --- a/filament/src/driver/opengl/OpenGLDriver.cpp +++ b/filament/src/driver/opengl/OpenGLDriver.cpp @@ -594,6 +594,26 @@ void OpenGLDriver::depthFunc(GLenum func) noexcept { }); } +void OpenGLDriver::polygonOffset(GLfloat factor, GLfloat units) noexcept { + // if we're in the shadow-pass, the default polygon offset is factor = unit = 1 + // TODO: this should be controlled by filament, instead of being a feature of the driver + if (factor == 0 && units == 0) { + TargetBufferFlags clearFlags = (TargetBufferFlags)mRenderPassParams.clear; + if ((clearFlags & TargetBufferFlags::SHADOW) == TargetBufferFlags::SHADOW) { + factor = units = 1.0f; + } + } + + update_state(state.polygonOffset, { factor, units }, [&]() { + if (factor != 0 || units != 0) { + glPolygonOffset(factor, units); + enable(GL_POLYGON_OFFSET_FILL); + } else { + disable(GL_POLYGON_OFFSET_FILL); + } + }); +} + void OpenGLDriver::setRasterStateSlow(Driver::RasterState rs) noexcept { mRasterState = rs; @@ -1975,12 +1995,6 @@ void OpenGLDriver::beginRenderPass(Driver::RenderTargetHandle rth, if (UTILS_UNLIKELY(state.draw_fbo != rt->gl.fbo)) { bindFramebuffer(GL_FRAMEBUFFER, rt->gl.fbo); - if ((clearFlags & TargetBufferFlags::SHADOW) == TargetBufferFlags::SHADOW) { - enable(GL_POLYGON_OFFSET_FILL); - } else { - disable(GL_POLYGON_OFFSET_FILL); - } - // glInvalidateFramebuffer appeared on GLES 3.0 and GL4.3, for simplicity we just // ignore it on GL (rather than having to do a runtime check). if (GLES31_HEADERS && !bugs.disable_invalidate_framebuffer) { @@ -2729,6 +2743,8 @@ void OpenGLDriver::draw( setRasterState(state.rasterState); + polygonOffset(state.polygonOffset.slope, state.polygonOffset.constant); + glDrawRangeElements(GLenum(rp->type), rp->minIndex, rp->maxIndex, rp->count, rp->gl.indicesType, reinterpret_cast(rp->offset)); diff --git a/filament/src/driver/opengl/OpenGLDriver.h b/filament/src/driver/opengl/OpenGLDriver.h index 93851c6abd..20eefda59e 100644 --- a/filament/src/driver/opengl/OpenGLDriver.h +++ b/filament/src/driver/opengl/OpenGLDriver.h @@ -296,6 +296,7 @@ private: setRasterStateSlow(rs); } } + void setTextureData(GLTexture* t, uint32_t level, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, @@ -350,6 +351,7 @@ private: inline void colorMask(GLboolean flag) noexcept; inline void depthMask(GLboolean flag) noexcept; inline void depthFunc(GLenum func) noexcept; + inline void polygonOffset(GLfloat factor, GLfloat units) noexcept; inline void setScissor(GLint left, GLint bottom, GLsizei width, GLsizei height) noexcept; inline void setViewport(GLint left, GLint bottom, GLsizei width, GLsizei height) noexcept; @@ -414,6 +416,14 @@ private: GLenum depthFunc = GL_LESS; } raster; + struct PolygonOffset { + GLfloat factor = 0; + GLfloat units = 0; + bool operator != (PolygonOffset const& rhs) noexcept { + return factor != rhs.factor || units != rhs.units; + } + } polygonOffset; + struct { utils::bitset32 caps; } enables;