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

PS3-like streaks? #1

Open
TorutheRedFox opened this issue Mar 16, 2022 · 14 comments
Open

PS3-like streaks? #1

TorutheRedFox opened this issue Mar 16, 2022 · 14 comments

Comments

@TorutheRedFox
Copy link

The PS3 version (imo) has nicer looking streaks which, rather than using a texture, filter the flares and lerp the result with the previous frame's result in order to perform the streaks (like UG2 streaks but better looking)

might be a bit of a stretch, but could be worth a shot

@xan1242
Copy link
Owner

xan1242 commented Mar 21, 2022

Not impossible, especially considering this rendering technically already exists for motion blurring (previous frames), except that the flares and particles are omitted from its texture.

Ideally this would be done specifically for the flares into its own texture(s) so we could replicate the effect, but I'm not sure how feasible this is. This would very likely require more code hacks to allow for it, but if anybody has an idea how this works, I'd be willing to give it a shot.

We (technically) have some texture samplers free for this (MISCMAP textures) but I'm not very well versed in D3D coding to achieve the render to texture thing to work.

@TorutheRedFox
Copy link
Author

the way I'd implement it (could not be how it's done though) is to render the flares into two color buffers using MRTs, with the first buffer just being the main backbuffer, and second being the streak buffer which gets 'cleared' with a 30%-ish maybe opacity quad (with the second output having 0.8 subtracted from it)

EAGL already has MRT support (as evident by a number of shaders using an output struct for the pixel shader rather than directly outputting to COLOR0)

@xan1242
Copy link
Owner

xan1242 commented Mar 23, 2022

Could you provide an example? I'm not exactly sure where to start with this (except by looking at already existing code in the game).

@xan1242
Copy link
Owner

xan1242 commented Mar 23, 2022

use this visualtreatment shader and wait for it to rain https://pastebin.com/8xuDNRxR

Wrong issue, this is for NFSC_CustomVT. (btw - no need to wait for rain, toggle precipitation debugging with exopts or with my custom ReShade)

@TorutheRedFox
Copy link
Author

not sure what you mean by example

as in HLSL?

@TorutheRedFox
Copy link
Author

use this visualtreatment shader and wait for it to rain https://pastebin.com/8xuDNRxR

Wrong issue, this is for NFSC_CustomVT. (btw - no need to wait for rain, toggle precipitation debugging with exopts or with my custom ReShade)

yeah i just realised that lmfao

@xan1242
Copy link
Owner

xan1242 commented Mar 23, 2022

not sure what you mean by example

as in HLSL?

Yes, HLSL would be good. It doesn't have to be game compatible or anything, just to see how it would be done.

I'm not very familiar with shader coding or D3D coding so I'd like to know how it is implemented in code to see if it is even feasible. Right now I don't have a good idea of how to actually write a shader which will produce a trail effect at all (because I am basically a noob at this).

@TorutheRedFox
Copy link
Author

TorutheRedFox commented Mar 23, 2022

well this shader would need an extra buffer to be set up and passed to the shader, with the blend set to one on both srcblend and dstblend (and an extra 50% ish alpha pass with the opacity modulated by deltatime so it's not framerate bound), but it'd go something like this:

struct PS_OUTPUT_FLARES
{
	float4 color     : COLOR0;
	float4 streak    : COLOR1;
};

PS_OUTPUT_FLARES pixel_shader_flares(const VtoP_FLARES IN) : COLOR
{
	PS_OUTPUT_FLARES OUT;
	float4 diffuse = tex2Dbias(DIFFUSE_SAMPLER, IN.tex);

	float scaled_fuzz_width = IN.tex1.w;
	float depth = tex2D(HEIGHTMAP_SAMPLER,IN.tex1.xy).x;
	float fuzzz = saturate((scaled_fuzz_width*0.4 - (IN.tex1.z - depth)) / (scaled_fuzz_width));
	
	
	float4 result;	
	result = diffuse;
	result *= IN.color;//*cvBaseAlphaRef.y;
	// Apply a tone mapping to fake a HDR
	result.xyz = result.xyz / (1.5-result.xyz);
	//result.xyz = pow(result.xyz, 1.5)*1.5;
	//result.xyz	= result.x > 0.95 ? 1.0f : 0.0f;
	// cvBaseAlphaRef.x is set to 0 in players views so the fuzzz used and 1 to disable the fuzz
	result.w *= saturate(cvBaseAlphaRef.x + fuzzz);
	
	//result.xyz = fuzzz;//(scaled_fuzz_width - (IN.tex1.z - depth)) / FuzzWidth;
	//result.w = 1;
    //result.xyz = CompressColourSpace(result.xyz);
	
	// say it's 0.8 as an example, not sure what it'd actually be to look good without seeing it ingame first
	float kFlareStreakThreshold = 0.8; 
	
	OUT.color = result;
	OUT.streak = result-kFlareStreakThreshold;
	
	return OUT;
}

@TorutheRedFox
Copy link
Author

@TorutheRedFox
Copy link
Author

GPU needs D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING support it seems though (as technique pretty much relies on being able to do blending in MRTs)

an alternate method that wouldn't need MRTs would be having a separate technique that'd run a wrapper like this directly into a separate buffer (but still with the 50-ish % opacity black quad clear to keep contents from previous frame but at a lower brightness)

float4 pixel_shader_flares_streak(const VtoP_FLARES IN) : COLOR
{
	// say it's 0.8 as an example, not sure what it'd actually be to look good without seeing it ingame first
	float kFlareStreakThreshold = 0.8; 
	return pixel_shader_flares(IN) - kFlareStreakThreshold;
}

@TorutheRedFox
Copy link
Author

seems like a threshold of 0.2 is good (might need to divide it afterwards though too)

@TorutheRedFox
Copy link
Author

yeah definitely needs dividing
it's bright as hell lmao (currently just adding OUT.streak to OUT.color after computing it to visualize)
image

@TorutheRedFox
Copy link
Author

TorutheRedFox commented Mar 23, 2022

OUT.streak = saturate(result-kFlareStreakThreshold) / 4; seems okay

although another thing to note would be that the streaks seem to apply to all particles on PS3 (with sparks being bright enough to get above the threshold)

@TorutheRedFox
Copy link
Author

thinking about it they could be also just done in a similar manner to NOS streaks, just remembering screen space position rather than world space, and well, using a separate technique for thresholding (which applies to sparks and other bright particles too it seems)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants