Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement alphaGen portal #1022

Merged
merged 6 commits into from
Aug 2, 2024
Merged

Implement alphaGen portal #1022

merged 6 commits into from
Aug 2, 2024

Conversation

illwieckz
Copy link
Member

@illwieckz illwieckz commented Jan 8, 2024

I don't claim it is working, but we need this to make it work.

We can notice the current code computes the distance to portal in fragment shader, but ioq3 does it in vertex shader, and it's probably faster to do it once per vertex than once per pixel, but this is a good start.

I'm not sure the existing GLSL code is correct, but the GLSL code will not run without those patches anyway.

The ioq3 code also does the range compute in the generic shader and at some point we may want to do the same as there may be other needs for doing blend operations according to distance, but yet again, we can look small and do small steps after small steps.

@illwieckz illwieckz marked this pull request as draft January 8, 2024 14:51
@illwieckz
Copy link
Member Author

illwieckz commented Jan 8, 2024

When I apply #1019 I see the portal map being blended with distance, though it is upside down and it is not blended over the portal but over itself, but this is promising.

At least the “fade with distance” compute is right or not totally wrong.

@VReaperV
Copy link
Contributor

VReaperV commented Jan 8, 2024

When I apply #1019 I see the portal map being blended with distance, though it is upside down and it is not blended over the portal but over itself, but this is promising.

I think I've identified the issue there, hopefully should be fixed soon.

@VReaperV
Copy link
Contributor

I believe this is because of how we render portals now. The portal surfaces themselves are not rendered with the other surfaces, but alphagen portal uses Render_portal() which seems to be a really old function. I assume that's a relic of the fixed function pipeline where it had to be drawn in multiple passes. We can just pass the alphagen parameters and texture to the shader now and blend it there.

@illwieckz
Copy link
Member Author

Yeah, ioq3 apply alphaGen portal directly in generic_fp.glsl.

@VReaperV
Copy link
Contributor

We should too, we can use gl_FragDepth with a uniform passing in the alphagen value. Might need to get the linear depth since I assume that's what alphagen portal is supposed to use.

@VReaperV
Copy link
Contributor

VReaperV commented Feb 6, 2024

You might need to add Tess_Begin() and rb_surfaceTable() or equivalent. I think the reason we're getting incorrect rendering here might be because the portals are rendered as follows:

  1. PreparePortalCommand
  2. DrawViewCommand
  3. FinalisePortalCommand

That last one does a Tess_Begin(), rb_surfaceTable() and a Tess_End(), while Render_portal() just does Tess_DrawElements(), which would then have incorrect data (presumably Render_portal() would be called after FinalisePortalCommand).

@illwieckz illwieckz changed the title wip: some steps to implement alphaGen portal WIP: some steps to implement alphaGen portal Apr 28, 2024
@illwieckz
Copy link
Member Author

illwieckz commented Jun 23, 2024

Current state is:

  • image is displayed properly,
  • fading works, but fading to black instead of fading to portal render,
  • fading is done in reverse: image is seen when close and disappears when moving back, while the image should not be rendered when close and start appearing when moving back.

@VReaperV
Copy link
Contributor

  • fading works, but fading to black instead of fading to portal render,

Not sure what that means.

  • fading is done in reverse: image is seen when close and disappears when moving back, while the image should not be rendered when close and start appearing when moving back.

Isn't that the crrect behaviour? I'm pretty sure trem works like that too (it also just makes sense, what's the point of a portal that you can't really see?).

@illwieckz
Copy link
Member Author

illwieckz commented Jun 23, 2024

You should see the portal surface (the scene from the camera) when close, but the fallback image when far, with the fallback image fading from transparent to opaque while increasing the distance. The idea is that the portal is only rendered when close with an image rendered instead when far.

@VReaperV
Copy link
Contributor

Oh, so it's just backwards, right? I think just changing color.rgb *= 1.0 - clamp(len, 0.0, 1.0); to color.rgb *= clamp(len, 0.0, 1.0); should fix it.

@illwieckz
Copy link
Member Author

OK, now two things are missing:

  • Once out of range, the surface turns full black instead of just rendering the image.
  • there is no blending to a portal surface, but to black.

@illwieckz
Copy link
Member Author

illwieckz commented Jun 24, 2024

I also noticed that while it fades in the right direction, it doesn't really fade to black.

Example of test scene: map nova, viewpos 9459 3037 -21 59 3.

@VReaperV
Copy link
Contributor

I also noticed that while it fades in the right direction, it doesn't really fade to black.

It should be fading to an image though, rather than black?

@VReaperV
Copy link
Contributor

Incorrect might be because alpha channel is not set and/or because of the blend functions.

@illwieckz
Copy link
Member Author

It should be fading to an image though, rather than black?

It should be fading to the image from the distant camera.

I assume fading to black is expected when blending is not working yet.

@VReaperV
Copy link
Contributor

VReaperV commented Jul 6, 2024

Blending is fixed now.

I also noticed that while it fades in the right direction, it doesn't really fade to black.

Example of test scene: map nova, viewpos 9459 3037 -21 59 3.

What you're seeing on nova is because the game doesn't render the portal at all from this position.

@VReaperV
Copy link
Contributor

VReaperV commented Jul 6, 2024

This also happens on 0.54.1, so at least it's not a regression (or not a recent one).

@illwieckz
Copy link
Member Author

Blending is fixed now.

Excellent!

What you're seeing on nova is because the game doesn't render the portal at all from this position.

Yes. The expected behavior of such surface is that when the view position is out of range, the surface always renders the textures, so what should be disabled is not the whole material, but only the portal rendering, with the texture being displayed.

@illwieckz
Copy link
Member Author

illwieckz commented Jul 6, 2024

Doing this “fixes” it:

diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp
index 061baee51..f19166508 100644
--- a/src/engine/renderer/tr_main.cpp
+++ b/src/engine/renderer/tr_main.cpp
@@ -1587,7 +1587,7 @@ static bool SurfBoxIsOffscreen(const drawSurf_t *drawSurf, screenRect_t& surfRec
 
 	if (shortest > (shader->portalRange * shader->portalRange))
 	{
-		return true;
+//		return true;
 	}
 
 	return false;
@@ -1741,7 +1741,7 @@ static bool SurfIsOffscreen( const drawSurf_t *drawSurf, screenRect_t& surfRect
 
 	if ( shortest > ( tess.surfaceShader->portalRange * tess.surfaceShader->portalRange ) )
 	{
-		return true;
+//		return true;
 	}
 
 	return false;

But this is wrong, it defeats the portalRange, meaning the portals are always rendered. What we need is to never disable the surface when out of range, but to disable the portal rendering when out of range.

@illwieckz
Copy link
Member Author

I tried doing this:

--- a/src/engine/renderer/tr_main.cpp
+++ b/src/engine/renderer/tr_main.cpp
@@ -1585,10 +1585,7 @@ static bool SurfBoxIsOffscreen(const drawSurf_t *drawSurf, screenRect_t& surfRec
 		return false;
 	}
 
-	if (shortest > (shader->portalRange * shader->portalRange))
-	{
-		return true;
-	}
+	shader->isPortalOutOfRange |= shortest > (shader->portalRange * shader->portalRange);
 
 	return false;
 }
@@ -1739,10 +1736,7 @@ static bool SurfIsOffscreen( const drawSurf_t *drawSurf, screenRect_t& surfRect
 		return false;
 	}
 
-	if ( shortest > ( tess.surfaceShader->portalRange * tess.surfaceShader->portalRange ) )
-	{
-		return true;
-	}
+	shader->isPortalOutOfRange |= shortest > ( tess.surfaceShader->portalRange * tess.surfaceShader->portalRange );
 
 	return false;
 }

Now I'm looking for a place to do:

if ( shader->isPortalOutOfRange  )
{
 	return;
}

To avoid rendering the related portal surface when out of range, but without disabling the surface itself.

@VReaperV
Copy link
Contributor

VReaperV commented Jul 7, 2024

Now I'm looking for a place to do:

if ( shader->isPortalOutOfRange  )
{
 	return;
}

To avoid rendering the related portal surface when out of range, but without disabling the surface itself.

Perhaps in an else block here?

if ( R_MirrorViewBySurface( drawSurf ) )
{
// this is a debug option to see exactly what is being mirrored
if ( r_portalOnly->integer )
{
return;
}
}

@VReaperV
Copy link
Contributor

This works now:
unvanquished_2024-07-30_020034_000
unvanquished_2024-07-30_020040_000
unvanquished_2024-07-30_020049_000
unvanquished_2024-07-30_020054_000

@VReaperV VReaperV linked an issue Jul 30, 2024 that may be closed by this pull request
@illwieckz illwieckz changed the title WIP: some steps to implement alphaGen portal Implement alphaGen portal Jul 30, 2024
@illwieckz illwieckz marked this pull request as ready for review July 30, 2024 16:41
@slipher
Copy link
Member

slipher commented Aug 1, 2024

LGTM

@VReaperV VReaperV closed this Aug 2, 2024
@VReaperV VReaperV reopened this Aug 2, 2024
@VReaperV VReaperV merged commit c60b60c into master Aug 2, 2024
11 checks passed
@VReaperV VReaperV deleted the illwieckz/agen-portal branch August 2, 2024 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

alphaGen portal keyword is not implemented yet
3 participants