Only render with a two pass solution if the model is not opague

This commit is contained in:
Malin E
2023-02-08 14:14:59 +01:00
parent 14edda9e61
commit 7d2f781603
3 changed files with 115 additions and 107 deletions
+106 -91
View File
@@ -681,112 +681,119 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
constexpr int res = 2880;
const double maxDistance = res * boundingSphere() / tfov;
if (distanceToCamera < maxDistance) {
_program->activate();
// Don't render if model is too far away
if (distanceToCamera >= maxDistance) {
return;
}
// Model transform and view transform needs to be in double precision
const glm::dmat4 modelTransform =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
glm::dmat4(data.modelTransform.rotation) *
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)) *
glm::scale(_modelTransform.value(), glm::dvec3(_modelScale));
const glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() *
modelTransform;
_program->activate();
int nLightSources = 0;
_lightIntensitiesBuffer.resize(_lightSources.size());
_lightDirectionsViewSpaceBuffer.resize(_lightSources.size());
for (const std::unique_ptr<LightSource>& lightSource : _lightSources) {
if (!lightSource->isEnabled()) {
continue;
}
_lightIntensitiesBuffer[nLightSources] = lightSource->intensity();
_lightDirectionsViewSpaceBuffer[nLightSources] =
lightSource->directionViewSpace(data);
// Model transform and view transform needs to be in double precision
const glm::dmat4 modelTransform =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
glm::dmat4(data.modelTransform.rotation) *
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)) *
glm::scale(_modelTransform.value(), glm::dvec3(_modelScale));
const glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() *
modelTransform;
++nLightSources;
int nLightSources = 0;
_lightIntensitiesBuffer.resize(_lightSources.size());
_lightDirectionsViewSpaceBuffer.resize(_lightSources.size());
for (const std::unique_ptr<LightSource>& lightSource : _lightSources) {
if (!lightSource->isEnabled()) {
continue;
}
_lightIntensitiesBuffer[nLightSources] = lightSource->intensity();
_lightDirectionsViewSpaceBuffer[nLightSources] =
lightSource->directionViewSpace(data);
_program->setUniform(
_uniformCache.nLightSources,
nLightSources
);
_program->setUniform(
_uniformCache.lightIntensities,
_lightIntensitiesBuffer
);
_program->setUniform(
_uniformCache.lightDirectionsViewSpace,
_lightDirectionsViewSpaceBuffer
);
_program->setUniform(
_uniformCache.modelViewTransform,
glm::mat4(modelViewTransform)
);
++nLightSources;
}
glm::dmat4 normalTransform = glm::transpose(glm::inverse(modelViewTransform));
_program->setUniform(
_uniformCache.nLightSources,
nLightSources
);
_program->setUniform(
_uniformCache.lightIntensities,
_lightIntensitiesBuffer
);
_program->setUniform(
_uniformCache.lightDirectionsViewSpace,
_lightDirectionsViewSpaceBuffer
);
_program->setUniform(
_uniformCache.modelViewTransform,
glm::mat4(modelViewTransform)
);
_program->setUniform(
_uniformCache.normalTransform,
glm::mat4(normalTransform)
);
glm::dmat4 normalTransform = glm::transpose(glm::inverse(modelViewTransform));
_program->setUniform(
_uniformCache.projectionTransform,
data.camera.projectionMatrix()
);
_program->setUniform(_uniformCache.ambientIntensity, _ambientIntensity);
_program->setUniform(_uniformCache.diffuseIntensity, _diffuseIntensity);
_program->setUniform(_uniformCache.specularIntensity, _specularIntensity);
_program->setUniform(_uniformCache.performShading, _performShading);
_program->setUniform(
_uniformCache.normalTransform,
glm::mat4(normalTransform)
);
// Configure blending
glEnablei(GL_BLEND, 0);
switch (_blendingFuncOption) {
case DefaultBlending:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case AdditiveBlending:
glBlendFunc(GL_ONE, GL_ONE);
break;
case PolygonBlending:
glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
break;
case ColorAddingBlending:
glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
break;
};
_program->setUniform(
_uniformCache.projectionTransform,
data.camera.projectionMatrix()
);
_program->setUniform(_uniformCache.ambientIntensity, _ambientIntensity);
_program->setUniform(_uniformCache.diffuseIntensity, _diffuseIntensity);
_program->setUniform(_uniformCache.specularIntensity, _specularIntensity);
_program->setUniform(_uniformCache.performShading, _performShading);
if (!_enableDepthTest) {
glDisable(GL_DEPTH_TEST);
}
if (!_enableFaceCulling) {
glDisable(GL_CULL_FACE);
}
if (!_enableFaceCulling) {
glDisable(GL_CULL_FACE);
}
// Configure blending
glEnablei(GL_BLEND, 0);
switch (_blendingFuncOption) {
case DefaultBlending:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case AdditiveBlending:
glBlendFunc(GL_ONE, GL_ONE);
break;
case PolygonBlending:
glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
break;
case ColorAddingBlending:
glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
break;
};
if (!_enableDepthTest) {
glDisable(GL_DEPTH_TEST);
}
// Only render two pass if the model is in any way transparent
bool shouldRenderTwise = false;
const float o = opacity();
if ((o >= 0.f && o < 1.f) || _geometry->isTransparent()) {
setRenderBin(Renderable::RenderBin::PostDeferredTransparent);
shouldRenderTwise = true;
}
else {
setRenderBin(_originalRenderBin);
}
if (!shouldRenderTwise) {
_geometry->render(*_program);
}
else {
// Prepare framebuffer
GLint defaultFBO = ghoul::opengl::FramebufferObject::getActiveObject();
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
glDrawBuffers(3, ColorAttachmentArray);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearBufferfv(GL_COLOR, 1, glm::value_ptr(glm::vec4(0.f, 0.f, 0.f, 0.f)));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Render Pass 1
// Render all parts of the model into the new framebuffer without opacity
const float o = opacity();
if ((o >= 0.f && o < 1.f) || !_enableDepthTest || _geometry->isTransparent()) {
setRenderBin(Renderable::RenderBin::PostDeferredTransparent);
}
else {
setRenderBin(_originalRenderBin);
}
_geometry->render(*_program);
if (!_enableFaceCulling) {
glEnable(GL_CULL_FACE);
}
_program->deactivate();
// Render pass 2
@@ -818,7 +825,7 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
global::renderEngine->renderer()->additionalColorTexture2()
);
_quadProgram->setUniform(
_uniformOpacityCache.positionTexture,
_uniformOpacityCache.positionTexture,
positionTextureUnit
);
@@ -842,12 +849,20 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
glBindVertexArray(_quadVao);
glDrawArrays(GL_TRIANGLES, 0, 6);
_quadProgram->deactivate();
// Reset
global::renderEngine->openglStateCache().resetBlendState();
global::renderEngine->openglStateCache().resetDepthState();
glActiveTexture(GL_TEXTURE0);
}
// Reset
if (!_enableFaceCulling) {
glEnable(GL_CULL_FACE);
}
if (!_enableDepthTest) {
glEnable(GL_DEPTH_TEST);
}
global::renderEngine->openglStateCache().resetBlendState();
global::renderEngine->openglStateCache().resetDepthState();
glActiveTexture(GL_TEXTURE0);
}
void RenderableModel::update(const UpdateData& data) {
+8 -15
View File
@@ -49,9 +49,12 @@ uniform int nLightSources;
uniform vec3 lightDirectionsViewSpace[8];
uniform float lightIntensities[8];
Fragment getFragment() {
Fragment frag;
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vs_positionCameraSpace;
frag.gNormal = vec4(vs_normalViewSpace, 0.0);
frag.disableLDR2HDR = true;
// Render invisible mesh with flashy procedural material
if (use_forced_color) {
@@ -59,15 +62,10 @@ Fragment getFragment() {
float chessboard = adjustedPos.x + adjustedPos.y + adjustedPos.z;
chessboard = fract(chessboard * 0.5);
chessboard *= 2;
// Pink and complementary green in a chessboard pattern
frag.color.rgb = mix(vec3(1.0, 0.0, 0.8), vec3(0.0, 1.0, 0.2), chessboard);
frag.color.a = 1.0;
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vs_positionCameraSpace;
frag.gNormal = vec4(vs_normalViewSpace, 0.0);
frag.disableLDR2HDR = true;
return frag;
}
@@ -120,11 +118,11 @@ Fragment getFragment() {
const float specularPower = 100.0;
vec3 diffuseColor =
diffuseIntensity * lightColor * diffuseAlbedo.rgb * max(diffuseCosineFactor, 0);
diffuseIntensity * lightColor * diffuseAlbedo.rgb * max(diffuseCosineFactor, 0);
vec3 specularColor =
specularIntensity * lightColor * specularAlbedo *
pow(max(specularCosineFactor, 0), specularPower);
specularIntensity * lightColor * specularAlbedo *
pow(max(specularCosineFactor, 0), specularPower);
color += lightIntensities[i] * (diffuseColor + specularColor);
}
@@ -135,10 +133,5 @@ Fragment getFragment() {
}
frag.color.a = diffuseAlbedo.a;
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vs_positionCameraSpace;
frag.gNormal = vec4(vs_normalViewSpace, 0.0);
frag.disableLDR2HDR = true;
return frag;
}